mirror of
https://github.com/wassname/cardsforscience.git
synced 2026-06-27 16:14:52 +08:00
Refactored flame and bubbles
This commit is contained in:
+24
-17
@@ -1,19 +1,26 @@
|
||||
{
|
||||
"name": "sciencealchemy",
|
||||
"description": "Science Alchemy",
|
||||
"main": "js/app.js",
|
||||
"moduleType": [],
|
||||
"license": "MIT",
|
||||
"homepage": "",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular-dragdrop": "~1.0.13"
|
||||
}
|
||||
"name": "sciencealchemy",
|
||||
"description": "Science Alchemy",
|
||||
"main": "js/app.js",
|
||||
"moduleType": [],
|
||||
"license": "MIT",
|
||||
"homepage": "",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular": "1.4.x",
|
||||
"angular-mocks": "1.4.x",
|
||||
"jquery": "~2.1.1",
|
||||
"bootstrap": "~3.1.1",
|
||||
"angular-route": "1.4.x",
|
||||
"angular-resource": "1.4.x",
|
||||
"angular-animate": "1.4.x",
|
||||
"angular-dragdrop": "~1.0.13"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ h1 br {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#detector canvas {
|
||||
#detector .test-tube, #detector .detector-events{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="particleClicker">
|
||||
<html lang="en" ng-app="scienceAlchemy">
|
||||
<head>
|
||||
<title>Science Alchemy</title>
|
||||
<meta charset="utf-8">
|
||||
@@ -88,7 +88,7 @@
|
||||
class="{{r.key}} element element-icon {{ r.state.interesting ? 'blink' : '' }} {{'q'+r.state.color+'-12'}}"
|
||||
data-element="{{r.key}}"
|
||||
data-drag="true"
|
||||
jqyoui-draggable
|
||||
jqyoui-draggable="{containment:'offset'}"
|
||||
data-jqyoui-options="{{rc.dragOptions}}"
|
||||
>
|
||||
{{r.key}}
|
||||
@@ -116,7 +116,7 @@
|
||||
>
|
||||
Your detector. Click on it to generate events.
|
||||
</canvas>
|
||||
<canvas id="detector-flame" width="400" height="400" class="prevent-select">
|
||||
<canvas id="detector-flame" width="400" height="400" class="prevent-select" ng-click="dc.toggleFlameFuel()">
|
||||
Your bunsen burner. Click it to turn on and off.
|
||||
</canvas>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
var allObjects = game.allObjects;
|
||||
var lastSaved;
|
||||
|
||||
var app = angular.module('particleClicker', ['ngDragDrop']);
|
||||
var app = angular.module('scienceAlchemy', ['ngDragDrop']);
|
||||
|
||||
// add helpers as filters
|
||||
app.filter('niceNumber', ['$filter', function($filter) {
|
||||
@@ -56,7 +56,7 @@
|
||||
hoverClass: "ui-state-active",
|
||||
}
|
||||
this.onDrop = function(event,ui){
|
||||
detector.onDrop(event,ui,lab);
|
||||
detector.onDrop(event,ui,game);
|
||||
}
|
||||
this.click = function() {
|
||||
lab.clickDetector();
|
||||
@@ -64,6 +64,10 @@
|
||||
UI.showUpdateValue("#update-data", lab.state.detector);
|
||||
return false;
|
||||
};
|
||||
this.toggleFlameFuel = function(){
|
||||
console.log('toggleFlameFuel');
|
||||
detector.flame.toggleFuel();
|
||||
}
|
||||
});
|
||||
|
||||
app.controller('ElementController', ['$compile', function($compile) {
|
||||
|
||||
+115
-60
@@ -5,16 +5,16 @@
|
||||
This plugin available for use in all personal or commercial projects under both MIT and GPL licenses.
|
||||
*/
|
||||
|
||||
;(function ( $, window, document, undefined ) {
|
||||
(function ( $, window, document, undefined ) {
|
||||
|
||||
var pluginName = "bubblr";
|
||||
|
||||
/** default options **/
|
||||
var defaults = {
|
||||
|
||||
numberOfBubbles: 10,
|
||||
backgroundColor: "transparent",
|
||||
bubbleColor: "White",
|
||||
bubbleOpacity: .7,
|
||||
bubbleOpacity: 0.7,
|
||||
bubbleMinSize: 1,
|
||||
bubbleMaxSize: 2,
|
||||
bubbleMaxSpeed: 2,
|
||||
@@ -22,11 +22,23 @@
|
||||
animationSpeed: 10
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the bubblr
|
||||
* @param {dom element} element - dom canvas element
|
||||
* @param {object} options - options see Bubblr._defaults for options
|
||||
*/
|
||||
function Bubblr( element, options ) {
|
||||
this.element = element;
|
||||
this.options = $.extend( {}, defaults, options) ;
|
||||
this._defaults = defaults;
|
||||
this.state = {
|
||||
bubbles: [],
|
||||
started: false,
|
||||
globalTick: 0,
|
||||
genBubbles: false,
|
||||
}
|
||||
this.init();
|
||||
this.start();
|
||||
}
|
||||
|
||||
Bubblr.prototype.init = function () {
|
||||
@@ -38,95 +50,113 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.timerId) this.remove();
|
||||
|
||||
$canvas = $(this.element);
|
||||
|
||||
this.width = $canvas.width();
|
||||
this.height = $canvas.height();
|
||||
|
||||
// this.state.globalTick=0;
|
||||
// this.state.continuous=false; // new bubbles
|
||||
// this.state.started = false // if there is an animation loop
|
||||
|
||||
$canvas.css("background-color", this.options.backgroundColor)
|
||||
|
||||
this.bubbles = new Array();
|
||||
// this.state.bubbles = new Array();
|
||||
|
||||
// initial bubbles
|
||||
for(i = 0; i < this.options.numberOfBubbles; i++) {
|
||||
this.bubbles[i] = this.generateBubble();
|
||||
this.state.bubbles[i] = this.generateBubble();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.on=false;
|
||||
|
||||
for(i in this.bubbles) {
|
||||
this.drawBubble(this.bubbles[i]);
|
||||
for(i in this.state.bubbles) {
|
||||
this.drawBubble(this.state.bubbles[i]);
|
||||
}
|
||||
|
||||
this.timerId = setInterval(function() {
|
||||
self.animationLoop();
|
||||
}, this.options.animationSpeed);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Recenter on resize,
|
||||
* bind this to $(window).on('resize',bubblr.onResize.bind(bubblr);) if needed
|
||||
**/
|
||||
Bubblr.prototype.onResize= function(){
|
||||
this.clear();
|
||||
this.width = Math.max($canvas.width(),this.element.width);
|
||||
this.height = Math.max($canvas.height(),this.element.height);
|
||||
this.width = $(this.element).outerWidth();
|
||||
this.height = $(this.element).outerWidth();
|
||||
};
|
||||
|
||||
Bubblr.prototype.start = function(timespan) {
|
||||
var self = this;
|
||||
if (!this.on){
|
||||
// this.timerId = setInterval(function() {
|
||||
// self.animationLoop();
|
||||
// }, this.options.animationSpeed);
|
||||
if (timespan) this.nextOffID = setTimeout(self.stop.bind(self),timespan);
|
||||
this.on=true;
|
||||
} else {
|
||||
clearInterval(this.nextOffID);
|
||||
this.nextOffID = setTimeout(self.stop.bind(self),timespan);
|
||||
/** Start animation loop if not started **/
|
||||
Bubblr.prototype.start = function() {
|
||||
if (!this.state.started){
|
||||
this.state.started=true;
|
||||
this.animationLoop();
|
||||
}
|
||||
};
|
||||
|
||||
/** Stop animation loop **/
|
||||
Bubblr.prototype.stop = function() {
|
||||
this.on=false;
|
||||
this.nextOffID=null;
|
||||
};
|
||||
|
||||
/** remove animation loop **/
|
||||
Bubblr.prototype.remove = function (arguments) {
|
||||
clearInterval(this.timerId);
|
||||
this.timerId=null;
|
||||
detector.bubblr.clear()
|
||||
}
|
||||
|
||||
Bubblr.prototype.animationLoop = function() {
|
||||
|
||||
this.state.started=false;
|
||||
this.clear();
|
||||
|
||||
for(i in this.bubbles) {
|
||||
this.update(i, this.bubbles[i]);
|
||||
this.draw(i, this.bubbles[i]);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Animation loop run Bubblr.stop and start control this **/
|
||||
Bubblr.prototype.animationLoop = function() {
|
||||
window.requestAnimFrame(this.animationLoop.bind(this));
|
||||
this.state.globalTick++;
|
||||
if (this.state.started) this.animate();
|
||||
};
|
||||
|
||||
Bubblr.prototype.animate = function (arguments) {
|
||||
this.clear();
|
||||
for(i in this.state.bubbles) {
|
||||
this.update(i, this.state.bubbles[i]);
|
||||
this.draw(i, this.state.bubbles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Bubblr.prototype.clear = function () {
|
||||
this.ctx.globalAlpha = 1;
|
||||
this.ctx.fillStyle = this.options.backgroundColor;
|
||||
this.ctx.clearRect(0,0,this.width, this.height);
|
||||
};
|
||||
|
||||
|
||||
Bubblr.prototype.draw = function (index, bubble) {
|
||||
this.ctx.globalAlpha = this.options.bubbleOpacity;
|
||||
this.drawBubble(bubble);
|
||||
};
|
||||
|
||||
/** Update bubble position **/
|
||||
Bubblr.prototype.update = function (index, bubble) {
|
||||
bubble.y = bubble.y - bubble.speed
|
||||
|
||||
if(bubble.y < 0 && this.on)
|
||||
this.bubbles[index] = this.generateBubble(true);
|
||||
if(bubble.y < 0 && this.state.continuous)
|
||||
// reset to bottom if continuous running is on
|
||||
this.state.bubbles[index] = this.generateBubble(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a single bubble
|
||||
* @param {object} options - options for the bubble
|
||||
* @param {Number} options.x - Starting x position. Defaults to a random
|
||||
* location.
|
||||
* @param {Number} options.y - starting y level. Default to the bottom or
|
||||
* null for random position, a number sets a
|
||||
* specific level. Note the top is 0, while the
|
||||
* bottom is `-$(element).height()`
|
||||
*/
|
||||
Bubblr.prototype.bubble = function (options){
|
||||
this.state.bubbles.push(this.generateBubble(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to generate multiple bubble
|
||||
* @param {[type]} amount - amount of bubbles to create
|
||||
* @param {[type]} options - see Bubblr.bubble for description
|
||||
*/
|
||||
Bubblr.prototype.genBubbles = function (amount,options) {
|
||||
for (var i = 0; i < amount; i++) {
|
||||
this.state.bubbles.push(this.generateBubble(options));
|
||||
}
|
||||
}
|
||||
|
||||
Bubblr.prototype.drawBubble = function(bubble) {
|
||||
this.ctx.fillStyle = this.options.bubbleColor;
|
||||
@@ -136,20 +166,33 @@
|
||||
this.ctx.fill();
|
||||
};
|
||||
|
||||
Bubblr.prototype.generateBubble = function(start_y_at_zero) {
|
||||
Bubblr.prototype.generateBubble = function(options) {
|
||||
options = options || {};
|
||||
var bubble = new Object();
|
||||
bubble.x = this.randomize(1,this.width);
|
||||
|
||||
if(start_y_at_zero) {
|
||||
|
||||
if(options.x===undefined || options.x===null)
|
||||
bubble.x = this.randomize(1,this.width);
|
||||
else
|
||||
bubble.x = options.x
|
||||
|
||||
if(options.y===undefined)
|
||||
bubble.y = this.height;
|
||||
}
|
||||
else {
|
||||
else if (options.y===null)
|
||||
bubble.y = this.randomize(1,this.height);
|
||||
}
|
||||
else
|
||||
bubble.y = options.y
|
||||
|
||||
if (options.radius)
|
||||
bubble.radius = options.radius
|
||||
else
|
||||
bubble.radius = this.randomize(this.options.bubbleMinSize, this.options.bubbleMaxSize);
|
||||
|
||||
if (options.speed)
|
||||
bubble.speed = options.speed;
|
||||
else
|
||||
bubble.speed = this.randomize(this.options.bubbleMinSpeed, this.options.bubbleMaxSpeed);
|
||||
|
||||
bubble.radius = this.randomize(this.options.bubbleMinSize, this.options.bubbleMaxSize);
|
||||
bubble.speed = this.randomize(this.options.bubbleMinSpeed, this.options.bubbleMaxSpeed);
|
||||
return bubble;
|
||||
};
|
||||
|
||||
@@ -157,7 +200,7 @@
|
||||
return Math.floor((Math.random()*max)+min);
|
||||
};
|
||||
|
||||
|
||||
// $.flame will create or return the bubblr element
|
||||
$.fn[pluginName] = function ( options ) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'plugin_' + pluginName)) {
|
||||
@@ -168,3 +211,15 @@
|
||||
}
|
||||
|
||||
})( jQuery, window, document );
|
||||
|
||||
// shim for requestAnimFrame
|
||||
window.requestAnimFrame = (function(){
|
||||
return window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(/* function */ callback, /* DOMElement */ element){
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
|
||||
+49
-10
@@ -15,6 +15,12 @@ var detector =
|
||||
list: [],
|
||||
},
|
||||
|
||||
flame:
|
||||
{
|
||||
canvas: null,
|
||||
ctx: null
|
||||
},
|
||||
|
||||
visible: true,
|
||||
|
||||
width: 400,
|
||||
@@ -36,6 +42,9 @@ var detector =
|
||||
detector.events.canvas = document.getElementById('detector-events');
|
||||
detector.events.ctx = detector.events.canvas.getContext('2d');
|
||||
|
||||
detector.flame.canvas = document.getElementById('detector-flame');
|
||||
detector.flame.ctx = detector.events.canvas.getContext('2d');
|
||||
|
||||
// set size
|
||||
// TODO resize "#detector-flame" too
|
||||
var devicePixelRatio = window.devicePixelRatio || 1;
|
||||
@@ -58,6 +67,9 @@ var detector =
|
||||
detector.events.canvas.width = baseSize;
|
||||
detector.events.canvas.height = baseSize;
|
||||
|
||||
detector.flame.canvas.width = baseSize;
|
||||
detector.flame.canvas.height = baseSize;
|
||||
|
||||
if (devicePixelRatio !== backingStoreRatio) {
|
||||
var oldWidth = detector.core.canvas.width;
|
||||
var oldHeight = detector.core.canvas.height;
|
||||
@@ -81,6 +93,7 @@ var detector =
|
||||
|
||||
|
||||
detector.initBubbles();
|
||||
detector.initFlame();
|
||||
// TODO refactor flame animation and put it here
|
||||
// this.flame = $('#detector-flame').flame();
|
||||
|
||||
@@ -106,6 +119,16 @@ var detector =
|
||||
detector.bubblr = bubblrElem.data('plugin_bubblr');
|
||||
},
|
||||
|
||||
initFlame: function(){
|
||||
var flameElem = $('#detector-flame').flame();
|
||||
this.flame = flameElem.data('plugin_flame')
|
||||
},
|
||||
|
||||
onResize: function(){
|
||||
this.bubblr.onResize();
|
||||
this.flame.onResize();
|
||||
},
|
||||
|
||||
animate: function(time)
|
||||
{
|
||||
// var duration = typeof time !== 'undefined' ? time - detector.lastRender : 16;
|
||||
@@ -118,28 +141,42 @@ var detector =
|
||||
/** When a user clicks the detector **/
|
||||
addEvent: function()
|
||||
{
|
||||
detector.bubblr.start(500); // bubble for 500ms, TODO make one bubble
|
||||
detector.bubblr.bubble(); // bubble for 500ms, TODO make one bubble
|
||||
},
|
||||
|
||||
/** When a worker clicks the detector **/
|
||||
addEventExternal: function(numWorkers)
|
||||
{
|
||||
// detector.bubblr.start(500*numWorkers);
|
||||
// detector.bubblr.bubble(numWorkers);
|
||||
},
|
||||
|
||||
/** Draw current events **/
|
||||
draw: function(duration)
|
||||
{
|
||||
detector.bubblr.start(duration);
|
||||
detector.bubblr.bubble();
|
||||
},
|
||||
|
||||
onDrop: function(event, ui, lab){
|
||||
onDrop: function(event, ui, game){
|
||||
// TODO tidy this, attach new runes to something better
|
||||
// FIXME at the moment it duplicates runes, but we need a better system
|
||||
var self=this;
|
||||
console.debug('onDrop',arguments);
|
||||
var $draggable = $(ui.draggable),
|
||||
$droppable = $(event.target);
|
||||
|
||||
// if the dragger came from the elements panels, clone it to here
|
||||
var newElement = $draggable.clone();
|
||||
var $detector = $droppable.parent()
|
||||
$detector.append(newElement);
|
||||
// also set position to that of droppable
|
||||
newElement.offset($draggable.offset())
|
||||
|
||||
|
||||
var elementStore = game.elements.filter(function(e){return e.key==$draggable.data('element')});
|
||||
elementStore[0].state.amount-=1;
|
||||
|
||||
// get everything intersecting the drop
|
||||
|
||||
var draggableTop = $draggable.offset().top;
|
||||
var draggableHeight = $draggable.height();
|
||||
var draggableBottom = draggableTop + draggableHeight;
|
||||
@@ -161,17 +198,19 @@ var detector =
|
||||
&& left <= draggableRight && right >= draggableLeft;
|
||||
return isCoveredByDraggable;
|
||||
});
|
||||
// TODO also get draggable covered by droppable
|
||||
for (var i = 0; i < $droppablesCoveredByDraggable.length; i++) {
|
||||
this.experiment($draggable,$droppablesCoveredByDraggable[i]);
|
||||
|
||||
}
|
||||
// just get one thes with a data-element attribute
|
||||
var inputs = $droppablesCoveredByDraggable.filter(function(e){
|
||||
return $(e).data('element');
|
||||
})
|
||||
inputs.push($draggable);
|
||||
var reaction = game.experiment({inputs:inputs});
|
||||
console.log('droppables', $droppablesCoveredByDraggable.length);
|
||||
|
||||
// duplicate
|
||||
var newRune = this.runeElem(ui.draggable.data('id'),$draggable.parent().parent());
|
||||
newRune.position({my:'center', at:'center',of: $draggable})
|
||||
|
||||
// var newRune = ui.draggable.clone(true,true);
|
||||
// $draggable.parent().append(newRune);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+210
-99
@@ -1,109 +1,220 @@
|
||||
/* http://codepen.io/jackrugile/pen/Jbnpv */
|
||||
// TODO refactor this to be a object with inputs and outputs, and to center on
|
||||
// window resize
|
||||
var c = document.getElementById('detector-flame'),
|
||||
ctx = c.getContext('2d'),
|
||||
cw = c.width = 400,
|
||||
ch = c.height = 300,
|
||||
parts = [],
|
||||
partCount = 200,
|
||||
partsFull = false,
|
||||
hueRange = 50,
|
||||
globalTick = 0,
|
||||
rand = function(min, max){
|
||||
return Math.floor( (Math.random() * (max - min + 1) ) + min);
|
||||
|
||||
/**
|
||||
* @name Flame
|
||||
* @description jquery plugin to generate flame on a canvas element..
|
||||
* Based on http://codepen.io/jackrugile/pen/Jbnpv
|
||||
* @copyright (c) 2015 wassname
|
||||
* @license: MIT
|
||||
*/
|
||||
// TODO recenter on canvas/window resize
|
||||
;(function ( $, window, document, undefined ) {
|
||||
var pluginName = "flame";
|
||||
|
||||
var defaults = {
|
||||
hueRange: 50,
|
||||
};
|
||||
|
||||
var defaultState = {
|
||||
parts: [],
|
||||
partCount: 200,
|
||||
partsFull: false,
|
||||
on: true,
|
||||
rendering: false,
|
||||
globalTick: 0,
|
||||
width: null,
|
||||
height: null,
|
||||
}
|
||||
|
||||
var Part = function(flame){
|
||||
this.flame=flame;
|
||||
this.ctx=this.flame.ctx;
|
||||
this.reset();
|
||||
};
|
||||
|
||||
var Part = function(){
|
||||
this.reset();
|
||||
};
|
||||
|
||||
Part.prototype.reset = function(){
|
||||
this.startRadius = rand(1, 25);
|
||||
this.radius = this.startRadius;
|
||||
this.x = cw/2 + (rand(0, 6) - 3);
|
||||
this.y = 250;
|
||||
this.vx = 0;
|
||||
this.vy = 0;
|
||||
this.hue = rand(globalTick - hueRange, globalTick + hueRange);
|
||||
this.saturation = rand(50, 100);
|
||||
this.lightness = rand(20, 70);
|
||||
this.startAlpha = rand(1, 10) / 100;
|
||||
this.alpha = this.startAlpha;
|
||||
this.decayRate = .1;
|
||||
this.startLife = 7;
|
||||
this.life = this.startLife;
|
||||
this.lineWidth = rand(1, 3);
|
||||
}
|
||||
|
||||
Part.prototype.update = function(){
|
||||
this.vx += (rand(0, 200) - 100) / 1500;
|
||||
this.vy -= this.life/50;
|
||||
this.x += this.vx;
|
||||
this.y += this.vy;
|
||||
this.alpha = this.startAlpha * (this.life / this.startLife);
|
||||
this.radius = this.startRadius * (this.life / this.startLife);
|
||||
this.life -= this.decayRate;
|
||||
if(
|
||||
this.x > cw + this.radius ||
|
||||
this.x < -this.radius ||
|
||||
this.y > ch + this.radius ||
|
||||
this.y < -this.radius ||
|
||||
this.life <= this.decayRate
|
||||
){
|
||||
this.reset();
|
||||
}
|
||||
};
|
||||
|
||||
Part.prototype.render = function(){
|
||||
ctx.beginPath();
|
||||
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
|
||||
ctx.fillStyle = ctx.strokeStyle = 'hsla('+this.hue+', '+this.saturation+'%, '+this.lightness+'%, '+this.alpha+')';
|
||||
ctx.lineWidth = this.lineWidth;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
var createParts = function(){
|
||||
if(!partsFull){
|
||||
if(parts.length > partCount){
|
||||
partsFull = true;
|
||||
} else {
|
||||
parts.push(new Part());
|
||||
Part.prototype.reset = function(){
|
||||
this.startRadius = this.rand(1, 25);
|
||||
this.radius = this.startRadius;
|
||||
this.width = this.flame.state.width;
|
||||
this.height = this.flame.state.height;
|
||||
this.x = this.width/2 + (this.rand(0, 6) - 3);
|
||||
this.y = 250;
|
||||
this.vx = 0;
|
||||
this.vy = 0;
|
||||
this.hue = this.rand(this.flame.state.globalTick - this.flame.options.hueRange, this.flame.state.globalTick + this.flame.options.hueRange);
|
||||
this.saturation = this.rand(50, 100);
|
||||
this.lightness = this.rand(20, 70);
|
||||
this.startAlpha = this.rand(1, 10) / 100;
|
||||
this.alpha = this.startAlpha;
|
||||
this.decayRate = 0.1;
|
||||
this.startLife = 7;
|
||||
this.life = this.startLife;
|
||||
this.lineWidth = this.rand(1, 3);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var updateParts = function(){
|
||||
var i = parts.length;
|
||||
while(i--){
|
||||
parts[i].update();
|
||||
}
|
||||
};
|
||||
Part.prototype.update = function(){
|
||||
this.vx += (this.rand(0, 200) - 100) / 1500;
|
||||
this.vy -= this.life/50;
|
||||
this.x += this.vx;
|
||||
this.y += this.vy;
|
||||
this.alpha = this.startAlpha * (this.life / this.startLife);
|
||||
this.radius = this.startRadius * (this.life / this.startLife);
|
||||
this.life -= this.decayRate;
|
||||
if(
|
||||
this.x > this.width + this.radius ||
|
||||
this.x < -this.radius ||
|
||||
this.y > this.height + this.radius ||
|
||||
this.y < -this.radius ||
|
||||
this.life <= this.decayRate
|
||||
){
|
||||
this.reset();
|
||||
}
|
||||
};
|
||||
|
||||
var renderParts = function(){
|
||||
var i = parts.length;
|
||||
while(i--){
|
||||
parts[i].render();
|
||||
}
|
||||
};
|
||||
Part.prototype.render = function(){
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
|
||||
this.ctx.fillStyle = this.ctx.strokeStyle = 'hsla('+this.hue+', '+this.saturation+'%, '+this.lightness+'%, '+this.alpha+')';
|
||||
this.ctx.lineWidth = this.lineWidth;
|
||||
this.ctx.fill();
|
||||
this.ctx.stroke();
|
||||
};
|
||||
|
||||
var clear = function(){
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.fillStyle = 'hsla(0, 0%, 0%, .3)';
|
||||
ctx.fillRect(0, 0, cw, ch);
|
||||
ctx.globalCompositeOperation = 'lighter';
|
||||
};
|
||||
Part.prototype.rand = function(min, max){
|
||||
return Math.floor( (Math.random() * (max - min + 1) ) + min);
|
||||
};
|
||||
|
||||
var loop = function(){
|
||||
window.requestAnimFrame(loop, c);
|
||||
clear();
|
||||
createParts();
|
||||
updateParts();
|
||||
renderParts();
|
||||
globalTick++;
|
||||
};
|
||||
var Flame = function(element, options){
|
||||
this.element = element;
|
||||
this.options = $.extend( {}, defaults, options) ;
|
||||
this._defaults = defaults;
|
||||
this.init();
|
||||
};
|
||||
|
||||
window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}();
|
||||
Flame.prototype.init = function (arguments) {
|
||||
if(this.element.getContext) {
|
||||
this.ctx = this.element.getContext("2d");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (this.state) this.stop();
|
||||
this.state = $.extend( {parts: [],partsFull: false,globalTick: 0,}, defaultState, this.state);
|
||||
// this.state = {
|
||||
// parts: [],
|
||||
// partCount: 200,
|
||||
// partsFull: false,
|
||||
// on: true,
|
||||
// rendering: false,
|
||||
// globalTick: 0,
|
||||
// width: null,
|
||||
// height: null,
|
||||
// }
|
||||
this.state.width = $(this.element).outerWidth();
|
||||
this.state.height = $(this.element).outerWidth();
|
||||
this.start();
|
||||
}
|
||||
|
||||
loop();
|
||||
/** If needed: $(window).on('resize',this.onResize.bind(this) **/
|
||||
Flame.prototype.onResize = function (arguments) {
|
||||
this.init();
|
||||
}
|
||||
|
||||
Flame.prototype.createParts = function(){
|
||||
if(this.state.parts.length > this.state.partCount){
|
||||
this.state.partsFull = true;
|
||||
} else {
|
||||
this.state.parts.push(new Part(this));
|
||||
}
|
||||
};
|
||||
|
||||
Flame.prototype.updateParts = function(){
|
||||
var i = this.state.parts.length;
|
||||
while(i--){
|
||||
this.state.parts[i].update();
|
||||
}
|
||||
};
|
||||
|
||||
Flame.prototype.renderParts = function(){
|
||||
var i = this.state.parts.length;
|
||||
while(i--){
|
||||
this.state.parts[i].render();
|
||||
}
|
||||
};
|
||||
|
||||
Flame.prototype.clear = function (arguments) {
|
||||
this.ctx.globalAlpha = 1;
|
||||
this.ctx.fillStyle = 'hsla(0, 0%, 0%, .0)';
|
||||
this.ctx.clearRect(0,0,this.state.width, this.state.height);
|
||||
}
|
||||
|
||||
/** Fades the previous flames into opacity to product a blur **/
|
||||
Flame.prototype.fade = function(){
|
||||
this.ctx.globalCompositeOperation = 'destination-out';
|
||||
this.ctx.fillStyle = 'hsla(0, 0%, 0%, .3)';
|
||||
this.ctx.fillRect(0, 0, this.state.width, this.state.height);
|
||||
this.ctx.globalCompositeOperation = 'lighter';
|
||||
};
|
||||
|
||||
Flame.prototype.draw = function (arguments) {
|
||||
this.fade();
|
||||
if (this.state.on){
|
||||
this.createParts();
|
||||
} else if (this.state.parts.length>1){
|
||||
this.state.parts.pop();
|
||||
}
|
||||
this.updateParts();
|
||||
this.renderParts();
|
||||
}
|
||||
|
||||
Flame.prototype.start = function (arguments) {
|
||||
if (!this.state.rendering){
|
||||
this.state.rendering=true
|
||||
this.animate();
|
||||
return this
|
||||
} else {return;}
|
||||
}
|
||||
|
||||
Flame.prototype.stop = function (arguments) {
|
||||
this.state.rendering=false;
|
||||
this.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Toggle fuel and the flame will burn down or up again **/
|
||||
Flame.prototype.toggleFuel = function (state) {
|
||||
if (state===undefined)
|
||||
detector.flame.state.on=!detector.flame.state.on;
|
||||
else
|
||||
detector.flame.state.on=state;
|
||||
return detector.flame.state.on;
|
||||
}
|
||||
|
||||
Flame.prototype.animate = function(){
|
||||
window.requestAnimFrame(this.animate.bind(this),this.element);
|
||||
this.state.globalTick++;
|
||||
if (this.state.rendering) this.draw();
|
||||
};
|
||||
|
||||
$.fn[pluginName] = function ( options ) {
|
||||
return this.each(function () {
|
||||
if (!$.data(this, 'plugin_' + pluginName)) {
|
||||
$.data(this, 'plugin_' + pluginName,
|
||||
new Flame( this, options ));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// shim for requestAnimFrame
|
||||
window.requestAnimFrame = (function(){
|
||||
return window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(/* function */ callback, /* DOMElement */ element){
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
})( jQuery, window, document );
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* jQuery UI Touch Punch 0.2.3
|
||||
*
|
||||
* Copyright 2011–2014, Dave Furfero
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*
|
||||
* Depends:
|
||||
* jquery.ui.widget.js
|
||||
* jquery.ui.mouse.js
|
||||
*/
|
||||
!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
|
||||
+43
-1
@@ -28,7 +28,6 @@ var Game = (function(Helpers,GameObjects,ObjectStorage) {
|
||||
this.workers = Helpers.loadFile('json/workers.json');
|
||||
this.upgrades = Helpers.loadFile('json/upgrades.json');
|
||||
this.achievements = Helpers.loadFile('json/achievements.json');
|
||||
this.runes = Helpers.loadFile('json/runes.json');
|
||||
this.keywords = Helpers.loadFile('json/keywords.json');
|
||||
|
||||
// Turn JSON files into actual game objects and fill map of all objects
|
||||
@@ -98,6 +97,49 @@ var Game = (function(Helpers,GameObjects,ObjectStorage) {
|
||||
return rules;
|
||||
},
|
||||
|
||||
/** Run an experiment depending on ingredients and conditions **/
|
||||
Game.prototype.experiment = function(options) {
|
||||
var inputs = options.inputs || [];
|
||||
var inputKeys = inputs.map(function(i,e){return $(e).data('element')});
|
||||
inputKeys.sort(); // this makes reaction be independant of order
|
||||
|
||||
var result = this.rules[inputKeys]
|
||||
if (result) {
|
||||
return this.reaction(result.ingredients,result.rune)
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/** Remove ingredients and make results with animations **/
|
||||
Game.prototype.reaction= function(ingredients,results){
|
||||
|
||||
// remove ingredients
|
||||
for (var i = 0; i < ingredients.length; i++) {
|
||||
var ingredient = ingredients[i];
|
||||
|
||||
}
|
||||
|
||||
// TODO use jqueru ui transfer effect to remove or puff
|
||||
$(aElem).remove();
|
||||
$(bElem).remove();
|
||||
|
||||
// if the dragger came from the elements panels, clone it to here
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
// make sure it's discovered
|
||||
var resultKey = results[i];
|
||||
var elementStore = this.elements.filter(function(e){return e.key===resultKey;});
|
||||
elementStore.state.discovered=true;
|
||||
|
||||
// add new element to beaker
|
||||
var newElement = $('#elementContent').find('.'+resultKey).clone();
|
||||
$('#detector').append(newElement);
|
||||
newElement.offset($draggable.offset())
|
||||
}
|
||||
|
||||
// effects
|
||||
this.bubblr.start(1500);
|
||||
|
||||
},
|
||||
Game.prototype.save = function() {
|
||||
// Save every object's state to local storage
|
||||
for (var key in this.allObjects) {
|
||||
|
||||
@@ -74,29 +74,7 @@ var GameObjects = (function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
/** Run an experiment depending on ingredients and conditions **/
|
||||
Lab.prototype.experiment = function(options) {
|
||||
var elements = options.elements || [];
|
||||
var elementKeys = elements.map(function(e){return $(e).data('element')});
|
||||
elementKeys.sort(); // this makes reaction be independant of order
|
||||
|
||||
var result = this.rules[elementKeys]
|
||||
if (result) {
|
||||
this.reaction(result.ingredients,result.rune)
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/** Remove ingredients and make results with animations **/
|
||||
Lab.prototype.reaction= function(ingredients,results){
|
||||
// TODO put new rune in old position, add animations
|
||||
var rune = this.runeElem(r,$(aElem).parent().parent());
|
||||
$('#observationsContent').append('<div class="col-md-12">'+this.runes[a]+'+'+this.runes[b]+'='+this.runes[r]+'</div>')
|
||||
this.bubblr.start(1500);
|
||||
// TODO use jqueru ui transfer effect to remove or puff
|
||||
$(aElem).remove();
|
||||
$(bElem).remove();
|
||||
}
|
||||
Lab.prototype.buy = function(cost) {
|
||||
if (this.state.money >= cost) {
|
||||
this.state.money -= cost;
|
||||
|
||||
Reference in New Issue
Block a user