diff --git a/compiled/radium.js b/compiled/radium.js index f99bd85..689015a 100644 --- a/compiled/radium.js +++ b/compiled/radium.js @@ -21,6 +21,9 @@ this.createScene = __bind(this.createScene, this); this.setPreloadScene = __bind(this.setPreloadScene, this); this.setInitialScene = __bind(this.setInitialScene, this); + this.skipTimers = __bind(this.skipTimers, this); + this.updateTimers = __bind(this.updateTimers, this); + this.updateEasings = __bind(this.updateEasings, this); this.iteration = __bind(this.iteration, this); this.loop = __bind(this.loop, this); this.start = __bind(this.start, this); @@ -33,11 +36,15 @@ this.last_frameskip_collection = Math.floor(Date.now()); this.frameskip = 0; this.current_frameskip = 0; + this.current_frame = 0; this.scenes = {}; this.objects = {}; this.sounds = {}; this.sprites = {}; this.tilesets = {}; + this.easings = []; + this.named_timers = {}; + this.unnamed_timers = []; } Engine.prototype.addCanvas = function(canvas, label) { @@ -79,15 +86,18 @@ }; Engine.prototype.iteration = function() { - var belated_timeout, current_frame, frame_interval, name, next_frame, overtime, scene, _ref; + var belated_timeout, current_frame, frame_interval, name, next_frame, overtime, scene, skipped_frames, _ref; frame_interval = 1000 / this.fps; current_frame = Date.now(); next_frame = current_frame + frame_interval; + this.current_frame += 1; if (Math.floor(current_frame) > this.last_frameskip_collection) { this.frameskip = this.current_frameskip; this.current_frameskip = 0; this.last_frameskip_collection = Math.floor(current_frame); } + this.updateEasings(); + this.updateTimers(); _ref = this.scenes; for (name in _ref) { scene = _ref[name]; @@ -99,12 +109,89 @@ return setTimeout(this.iteration, next_frame - Date.now()); } else { overtime = Date.now() - next_frame; - this.current_frameskip += Math.floor(overtime / frame_interval); + skipped_frames = Math.floor(overtime / frame_interval); + this.current_frameskip += skipped_frames; + this.current_frame += skipped_frames; + this.skipTimers(skipped_frames); belated_timeout = overtime % frame_interval; return setTimeout(this.iteration, belated_timeout); } }; + Engine.prototype.updateEasings = function() { + var easing, _i, _len, _ref; + _ref = this.easings; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + easing = _ref[_i]; + if (this.current_frame >= (easing.start_frame + easing.duration)) { + if (easing.infinite) { + easing.start_frame = this.current_frame; + easing.updateValue(this.current_frame); + } else { + easing.finished = true; + easing.value = easing.end; + } + } else { + easing.updateValue(this.current_frame); + } + } + return this.easings = this.easings.filter(function(obj) { + return !obj.finished; + }); + }; + + Engine.prototype.updateTimers = function() { + var key, timer, timer_name, val, _i, _len, _ref, _ref1, _results; + _ref = this.unnamed_timers.concat((function() { + var _ref, _results; + _ref = this.named_timers; + _results = []; + for (key in _ref) { + val = _ref[key]; + _results.push(val); + } + return _results; + }).call(this)); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + timer = _ref[_i]; + timer.step(); + } + this.unnamed_timers = this.unnamed_timers.filter(function(obj) { + return !obj.finished; + }); + _ref1 = this.named_timers; + _results = []; + for (timer_name in _ref1) { + timer = _ref1[timer_name]; + if (timer.finished) { + _results.push(delete this.named_timers[timer_name]); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Engine.prototype.skipTimers = function(frames) { + var key, timer, val, _i, _len, _ref, _results; + _ref = this.unnamed_timers.concat((function() { + var _ref, _results1; + _ref = this.named_timers; + _results1 = []; + for (key in _ref) { + val = _ref[key]; + _results1.push(val); + } + return _results1; + }).call(this)); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + timer = _ref[_i]; + _results.push(timer.skip(frames)); + } + return _results; + }; + Engine.prototype.setInitialScene = function(scene) { return this.initial_scene = scene; }; @@ -196,19 +283,19 @@ })(this), _finishPath: (function(_this) { return function(surface, options) { - var _ref, _ref1, _ref10, _ref11, _ref12, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; + var _ref, _ref1, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref17, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; if ((_ref = options.stroke) != null ? _ref : true) { - surface.lineWidth = (_ref1 = (_ref2 = options.lineWidth) != null ? _ref2 : (_ref3 = options.pen) != null ? _ref3.lineWidth : void 0) != null ? _ref1 : 1; - surface.strokeStyle = (_ref4 = (_ref5 = options.lineColor) != null ? _ref5 : (_ref6 = options.pen) != null ? _ref6.lineColor : void 0) != null ? _ref4 : "black"; - if ((_ref7 = options._is_text) != null ? _ref7 : false) { + surface.lineWidth = (_ref1 = (_ref2 = (_ref3 = (_ref4 = (_ref5 = options.lineWidth) != null ? _ref5.value : void 0) != null ? _ref4 : options.lineWidth) != null ? _ref3 : (_ref6 = options.pen) != null ? (_ref7 = _ref6.lineWidth) != null ? _ref7.value : void 0 : void 0) != null ? _ref2 : (_ref8 = options.pen) != null ? _ref8.lineWidth : void 0) != null ? _ref1 : 1; + surface.strokeStyle = (_ref9 = (_ref10 = options.lineColor) != null ? _ref10 : (_ref11 = options.pen) != null ? _ref11.lineColor : void 0) != null ? _ref9 : "black"; + if ((_ref12 = options._is_text) != null ? _ref12 : false) { surface.strokeText(options.text, options.x, options.y); } else { surface.stroke(); } } - if ((_ref8 = options.fill) != null ? _ref8 : false) { - surface.fillStyle = (_ref9 = (_ref10 = options.fillColor) != null ? _ref10 : (_ref11 = options.pen) != null ? _ref11.fillColor : void 0) != null ? _ref9 : "white"; - if ((_ref12 = options._is_text) != null ? _ref12 : false) { + if ((_ref13 = options.fill) != null ? _ref13 : false) { + surface.fillStyle = (_ref14 = (_ref15 = options.fillColor) != null ? _ref15 : (_ref16 = options.pen) != null ? _ref16.fillColor : void 0) != null ? _ref14 : "white"; + if ((_ref17 = options._is_text) != null ? _ref17 : false) { return surface.fillText(options.text, options.x, options.y); } else { return surface.fill(); @@ -227,26 +314,31 @@ })(this), _applyTextContext: (function(_this) { return function(surface, options) { - var font_family, font_size, font_style, font_weight, scale, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; + var font_family, font_size, font_style, font_weight, scale, _ref, _ref1, _ref10, _ref11, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; font_family = (_ref = options.font) != null ? _ref : "sans-serif"; - font_size = (_ref1 = options.size) != null ? _ref1 : 16; - font_weight = (_ref2 = options.weight) != null ? _ref2 : "normal"; - font_style = (_ref3 = options.style) != null ? _ref3 : "normal"; - scale = (_ref4 = options.scale) != null ? _ref4 : 1; + font_size = (_ref1 = (_ref2 = (_ref3 = options.size) != null ? _ref3.value : void 0) != null ? _ref2 : options.size) != null ? _ref1 : 16; + font_weight = (_ref4 = options.weight) != null ? _ref4 : "normal"; + font_style = (_ref5 = options.style) != null ? _ref5 : "normal"; + scale = (_ref6 = (_ref7 = (_ref8 = options.scale) != null ? _ref8.value : void 0) != null ? _ref7 : options.scale) != null ? _ref6 : 1; surface.save(); surface.font = "" + font_weight + " " + font_style + " " + font_size + "px '" + font_family + "'"; - surface.globalAlpha = (_ref5 = options.alpha) != null ? _ref5 : 1; + surface.globalAlpha = (_ref9 = (_ref10 = (_ref11 = options.alpha) != null ? _ref11.value : void 0) != null ? _ref10 : options.alpha) != null ? _ref9 : 1; return surface.scale(scale, scale); }; })(this), line: (function(_this) { return function(x1, y1, x2, y2, options, surface) { + var _ref, _ref1, _ref2, _ref3; if (options == null) { options = {}; } if (surface == null) { surface = ""; } + x1 = (_ref = x1.value) != null ? _ref : x1; + y1 = (_ref1 = y1.value) != null ? _ref1 : y1; + x2 = (_ref2 = x2.value) != null ? _ref2 : x2; + y2 = (_ref3 = y2.value) != null ? _ref3 : y2; surface = _this._startPath(surface, options); surface.moveTo(x1, y1); surface.lineTo(x2, y2); @@ -255,12 +347,17 @@ })(this), rectangle: (function(_this) { return function(x1, y1, x2, y2, options, surface) { + var _ref, _ref1, _ref2, _ref3; if (options == null) { options = {}; } if (surface == null) { surface = ""; } + x1 = (_ref = x1.value) != null ? _ref : x1; + y1 = (_ref1 = y1.value) != null ? _ref1 : y1; + x2 = (_ref2 = x2.value) != null ? _ref2 : x2; + y2 = (_ref3 = y2.value) != null ? _ref3 : y2; surface = _this._startPath(surface, options); surface.rect(x1, y1, x2 - x1, y2 - y1); return _this._finishPath(surface, options); @@ -268,13 +365,17 @@ })(this), boxEllipse: (function(_this) { return function(x1, y1, x2, y2, options, surface) { - var rx, ry, x, y; + var rx, ry, x, y, _ref, _ref1, _ref2, _ref3; if (options == null) { options = {}; } if (surface == null) { surface = ""; } + x1 = (_ref = x1.value) != null ? _ref : x1; + y1 = (_ref1 = y1.value) != null ? _ref1 : y1; + x2 = (_ref2 = x2.value) != null ? _ref2 : x2; + y2 = (_ref3 = y2.value) != null ? _ref3 : y2; x = (x1 + x2) / 2; y = (y1 + y2) / 2; rx = (x2 - x1) / 2; @@ -284,20 +385,24 @@ })(this), radiusEllipse: (function(_this) { return function(x, y, rx, ry, options, surface) { - var i, step, _i, _ref, _ref1; + var i, step, _i, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; if (options == null) { options = {}; } if (surface == null) { surface = ""; } + x = (_ref = x.value) != null ? _ref : x; + y = (_ref1 = y.value) != null ? _ref1 : y; + rx = (_ref2 = rx.value) != null ? _ref2 : rx; + ry = (_ref3 = ry.value) != null ? _ref3 : ry; surface = _this._startPath(surface, options); - step = (_ref = options.step) != null ? _ref : 0.1; + step = (_ref4 = (_ref5 = (_ref6 = options.step) != null ? _ref6.value : void 0) != null ? _ref5 : options.step) != null ? _ref4 : 0.1; if (rx === ry) { surface.arc(x, y, rx, 0, 2 * Math.PI, false); } else { surface.moveTo(x + rx, y); - for (i = _i = 0, _ref1 = Math.PI * 2 + step; 0 <= _ref1 ? _i <= _ref1 : _i >= _ref1; i = 0 <= _ref1 ? ++_i : --_i) { + for (i = _i = 0, _ref7 = Math.PI * 2 + step; 0 <= _ref7 ? _i <= _ref7 : _i >= _ref7; i = 0 <= _ref7 ? ++_i : --_i) { surface.lineTo(x + (Math.cos(i) * rx), y + (Math.sin(i) * ry)); } } @@ -328,19 +433,19 @@ })(this), text: (function(_this) { return function(x, y, text, options, surface) { - var text_width; + var text_width, _ref, _ref1, _ref2, _ref3, _ref4; if (options == null) { options = {}; } if (surface == null) { surface = ""; } + x = (_ref = x.value) != null ? _ref : x; + y = (_ref1 = y.value) != null ? _ref1 : y; if (options.alignment == null) { options.alignment = "left"; } - if (options.scale == null) { - options.scale = 1; - } + options.scale = (_ref2 = (_ref3 = (_ref4 = options.scale) != null ? _ref4.value : void 0) != null ? _ref3 : options.scale) != null ? _ref2 : 1; options._is_text = true; options.text = text; options.y = y; diff --git a/easing.html b/easing.html new file mode 100644 index 0000000..d61a772 --- /dev/null +++ b/easing.html @@ -0,0 +1,14 @@ + + + + Easing Demo + + + + + + + +
+ + \ No newline at end of file diff --git a/radium/engine.coffee b/radium/engine.coffee index 025717a..89e4fea 100644 --- a/radium/engine.coffee +++ b/radium/engine.coffee @@ -7,12 +7,16 @@ class Engine @last_frameskip_collection = Math.floor(Date.now()) @frameskip = 0 @current_frameskip = 0 + @current_frame = 0 @scenes = {} @objects = {} @sounds = {} @sprites = {} @tilesets = {} + @easings = [] + @named_timers = {} + @unnamed_timers = [] addCanvas: (canvas, label = "") => @canvases[label] = util.unpackElement(canvas) @@ -48,12 +52,19 @@ class Engine current_frame = Date.now() next_frame = current_frame + frame_interval + @current_frame += 1 + if Math.floor(current_frame) > @last_frameskip_collection @frameskip = @current_frameskip @current_frameskip = 0 @last_frameskip_collection = Math.floor(current_frame) - # Actual iteration code + # Actual iteration code... + # First update the registered easings. + @updateEasings() + # Then process registered timers. + @updateTimers() + # Now we run the scene-specific code. scene.iteration() for name, scene of @scenes when scene.active # Frameskip check and triggering next iteration @@ -62,10 +73,43 @@ class Engine else # Frameskip! overtime = Date.now() - next_frame - @current_frameskip += Math.floor(overtime / frame_interval) + skipped_frames = Math.floor(overtime / frame_interval) + @current_frameskip += skipped_frames + @current_frame += skipped_frames + @skipTimers(skipped_frames) belated_timeout = overtime % frame_interval setTimeout(@iteration, belated_timeout) + updateEasings: => + for easing in @easings + if @current_frame >= (easing.start_frame + easing.duration) + if easing.infinite + easing.start_frame = @current_frame + easing.updateValue(@current_frame) + else + easing.finished = true + easing.value = easing.end + else + easing.updateValue(@current_frame) + + # Clean up finished easings + @easings = @easings.filter (obj) -> not obj.finished + + updateTimers: => + for timer in @unnamed_timers.concat (val for key, val of @named_timers) + timer.step() + + # Clean up finished timers + @unnamed_timers = @unnamed_timers.filter (obj) -> not obj.finished + + for timer_name, timer of @named_timers + if timer.finished + delete @named_timers[timer_name] + + skipTimers: (frames) => + for timer in @unnamed_timers.concat (val for key, val of @named_timers) + timer.skip(frames) + setInitialScene: (scene) => @initial_scene = scene diff --git a/radium/engine.draw.coffee b/radium/engine.draw.coffee index 0f2a400..2114cf7 100644 --- a/radium/engine.draw.coffee +++ b/radium/engine.draw.coffee @@ -9,7 +9,7 @@ Engine::draw = _finishPath: (surface, options) => if options.stroke ? true - surface.lineWidth = options.lineWidth ? options.pen?.lineWidth ? 1 + surface.lineWidth = options.lineWidth?.value ? options.lineWidth ? options.pen?.lineWidth?.value ? options.pen?.lineWidth ? 1 surface.strokeStyle = options.lineColor ? options.pen?.lineColor ? "black" if options._is_text ? false @@ -33,28 +33,46 @@ Engine::draw = _applyTextContext: (surface, options) => font_family = options.font ? "sans-serif" - font_size = options.size ? 16 + font_size = options.size?.value ? options.size ? 16 font_weight = options.weight ? "normal" font_style = options.style ? "normal" - scale = options.scale ? 1 + scale = options.scale?.value ? options.scale ? 1 surface.save() surface.font = "#{font_weight} #{font_style} #{font_size}px '#{font_family}'" - surface.globalAlpha = options.alpha ? 1 + surface.globalAlpha = options.alpha?.value ? options.alpha ? 1 surface.scale(scale, scale) line: (x1, y1, x2, y2, options = {}, surface = "") => + # Ease-able properties + x1 = x1.value ? x1 + y1 = y1.value ? y1 + x2 = x2.value ? x2 + y2 = y2.value ? y2 + surface = @_startPath(surface, options) surface.moveTo(x1, y1) surface.lineTo(x2, y2) @_finishPath(surface, options) rectangle: (x1, y1, x2, y2, options = {}, surface = "") => + # Ease-able properties + x1 = x1.value ? x1 + y1 = y1.value ? y1 + x2 = x2.value ? x2 + y2 = y2.value ? y2 + surface = @_startPath(surface, options) surface.rect(x1, y1, x2 - x1, y2 - y1) @_finishPath(surface, options) boxEllipse: (x1, y1, x2, y2, options = {}, surface = "") => + # Ease-able properties + x1 = x1.value ? x1 + y1 = y1.value ? y1 + x2 = x2.value ? x2 + y2 = y2.value ? y2 + x = (x1 + x2) / 2; y = (y1 + y2) / 2; rx = (x2 - x1) / 2; @@ -62,9 +80,15 @@ Engine::draw = @radiusEllipse(x, y, rx, ry, options, surface) radiusEllipse: (x, y, rx, ry, options = {}, surface = "") => + # Ease-able properties + x = x.value ? x + y = y.value ? y + rx = rx.value ? rx + ry = ry.value ? ry + surface = @_startPath(surface, options) - step = options.step ? 0.1 + step = options.step?.value ? options.step ? 0.1 if rx == ry surface.arc(x, y, rx, 0, 2 * Math.PI, false) @@ -83,9 +107,13 @@ Engine::draw = pass # TODO text: (x, y, text, options = {}, surface = "") => + # Ease-able properties + x = x.value ? x + y = y.value ? y + # Defaults options.alignment ?= "left" - options.scale ?= 1 + options.scale = options.scale?.value ? options.scale ? 1 options._is_text = true options.text = text options.y = y diff --git a/radium/engine.ease.coffee b/radium/engine.ease.coffee new file mode 100644 index 0000000..77f30e5 --- /dev/null +++ b/radium/engine.ease.coffee @@ -0,0 +1,165 @@ +Engine::ease = + _calculateElasticValues: (amplitude, period, change, inout = false) => + if !period? + if inout + period = duration * (0.3 * 1.5) + else + period = duration * 0.3 + + if !amplitude? or amplitude < Math.abs(change) + amplitude = change + overshoot = period / 4 + else + overshoot = period / (2 * Math.PI) * Math.asin(change / amplitude) + + return [amplitude, period, change] + + backIn: (start, end, duration, infinite = false, overshoot = 1.70158) => + return new Ease("backIn", infinite, start, end, @current_frame, duration, overshoot) + backOut: (start, end, duration, infinite = false, overshoot = 1.70158) => + return new Ease("backOut", infinite, start, end, @current_frame, duration, overshoot) + backInOut: (start, end, duration, infinite = false, overshoot = 1.70158) => + return new Ease("backInOut", infinite, start, end, @current_frame, duration, overshoot) + bounceOut: (start, end, duration, infinite = false) => + return new Ease("bounceOut", infinite, start, end, @current_frame, duration) + bounceIn: (start, end, duration, infinite = false) => + return new Ease("bounceIn", infinite, start, end, @current_frame, duration) + bounceInOut: (start, end, duration, infinite = false) => + return new Ease("bounceInOut", infinite, start, end, @current_frame, duration) + circOut: (start, end, duration, infinite = false) => + return new Ease("circOut", infinite, start, end, @current_frame, duration) + circIn: (start, end, duration, infinite = false) => + return new Ease("circIn", infinite, start, end, @current_frame, duration) + circInOut: (start, end, duration, infinite = false) => + return new Ease("circInOut", infinite, start, end, @current_frame, duration) + cubicOut: (start, end, duration, infinite = false) => + return new Ease("cubicOut", infinite, start, end, @current_frame, duration) + cubicIn: (start, end, duration, infinite = false) => + return new Ease("cubicIn", infinite, start, end, @current_frame, duration) + cubicInOut: (start, end, duration, infinite = false) => + return new Ease("cubicInOut", infinite, start, end, @current_frame, duration) + elasticOut: (start, end, duration, infinite = false, amplitude = null, period = null) => + [amplitude, period, change] = @_calculateElasticValues(amplitude, period, end - start) + end = start + change + return new Ease("elasticOut", infinite, start, end, @current_frame, duration) + elasticIn: (start, end, duration, infinite = false, amplitude = null, period = null) => + [amplitude, period, change] = @_calculateElasticValues(amplitude, period, end - start) + end = start + change + return new Ease("elasticIn", infinite, start, end, @current_frame, duration) + elasticInOut: (start, end, duration, infinite = false, amplitude = null, period = null) => + [amplitude, period, change] = @_calculateElasticValues(amplitude, period, end - start, true) + end = start + change + return new Ease("elasticInOut", infinite, start, end, @current_frame, duration) + expoOut: (start, end, duration, infinite = false) => + return new Ease("expoOut", infinite, start, end, @current_frame, duration) + expoIn: (start, end, duration, infinite = false) => + return new Ease("expoIn", infinite, start, end, @current_frame, duration) + expoInOut: (start, end, duration, infinite = false) => + return new Ease("expoInOut", infinite, start, end, @current_frame, duration) + linearNone: (start, end, duration, infinite = false) => + return new Ease("linearNone", infinite, start, end, @current_frame, duration) + linearOut: (start, end, duration, infinite = false) => + return new Ease("linearNone", infinite, start, end, @current_frame, duration) + linearIn: (start, end, duration, infinite = false) => + return new Ease("linearNone", infinite, start, end, @current_frame, duration) + linearInOut: (start, end, duration, infinite = false) => + return new Ease("linearNone", infinite, start, end, @current_frame, duration) + quadOut: (start, end, duration, infinite = false) => + return new Ease("quadOut", infinite, start, end, @current_frame, duration) + quadIn: (start, end, duration, infinite = false) => + return new Ease("quadIn", infinite, start, end, @current_frame, duration) + quadInOut: (start, end, duration, infinite = false) => + return new Ease("quadInOut", infinite, start, end, @current_frame, duration) + quartOut: (start, end, duration, infinite = false) => + return new Ease("quartOut", infinite, start, end, @current_frame, duration) + quartIn: (start, end, duration, infinite = false) => + return new Ease("quartIn", infinite, start, end, @current_frame, duration) + quartInOut: (start, end, duration, infinite = false) => + return new Ease("quartInOut", infinite, start, end, @current_frame, duration) + sineOut: (start, end, duration, infinite = false) => + return new Ease("sineOut", infinite, start, end, @current_frame, duration) + sineIn: (start, end, duration, infinite = false) => + return new Ease("sineIn", infinite, start, end, @current_frame, duration) + sineInOut: (start, end, duration, infinite = false) => + return new Ease("sineInOut", infinite, start, end, @current_frame, duration) + + +class Ease + # Port based on https://github.com/jimjeffers/Easie. I don't think this qualifies as a "bad thing" :) + constructor: (type, @infinite, @start, end, @start_frame, @duration, @params...) -> + @func = this[type] + @change = end - @start + @value = @start + @finished = false + # TODO: Investigate whether JS engines cache deterministic outcomes by themselves. If not, + # the below could provide some performance gain. + #@bounce_constant_1 = 1 / 2.75 + #@bounce_constant_2 = 2 / 2.75 + #@bounce_constant_3 = 2.5 / 2.75 + + updateValue: (current_frame) => + @value = @func(current_frame - @start_frame) + + backIn: (time) => + time = time / @duration + overshoot = @params[0] + return @change * time * time * ((overshoot + 1) * time - overshoot) + @start + + backOut: (time) => + time = time / @duration - 1 + overshoot = @params[0] + return @change * (time * time * ((overshoot + 1) * time + overshoot) + 1) + @start + + backInOut: (time) => + time = time / (@duration / 2) + overshoot = @params[0] * 1.525 + + if time < 1 + return @change / 2 * (time * time * ((overshoot + 1) * time - overshoot)) + @start + else + time -= 2 + return @change / 2 * (time * time * ((overshoot + 1) * time + overshoot) + 2) + @start + + bounceOut: (time, start = null) => + time = time / @duration + start = start ? @start + + if time < 1 / 2.75 + return @change * (7.5625 * time * time) + start + else if time < 2 / 2.75 + time = time - (1.5 / 2.75) + return @change * (7.5625 * time * time + 0.75) + start + else if time < 2.5 / 2.75 + time = time - (2.25 / 2.75) + return @change * (7.5625 * time * time + 0.9375) + start + else + time = time - (2.625 / 2.75) + return @change * (7.5625 * time * time + 0.984375) + start + + bounceIn: (time, start = null) => + start = start ? @start + return @change - @bounceOut(@duration - time, 0) + start + + bounceInOut: (time) => + if time < @duration / 2 + return @bounceIn(time * 2, 0) + @start + else + return @bounceOut(time * 2 - @duration, 0) + @start + + circIn: (time) => + time = time / @duration + return -@change * (Math.sqrt(1 - time * time) - 1) + @start + + circOut: (time) => + time = time / @duration - 1 + return @change * Math.sqrt(1 - time * time) + @start + + circInOut: (time) => + time = time / (@duration / 2) + + if time < 1 + return -@change / 2 * (Math.sqrt(1 - time * time) - 1) + @start + else + time = time - 2 + return @change / 2 * (Math.sqrt(1 - time * time) + 1) + @begin + \ No newline at end of file diff --git a/radium/engine.timing.coffee b/radium/engine.timing.coffee new file mode 100644 index 0000000..cd129a7 --- /dev/null +++ b/radium/engine.timing.coffee @@ -0,0 +1,30 @@ +Engine::timing = + startTimer: (frames, callback, name = null, repeat = false) => + timer = new Timer(frames, callback, repeat) + if name? + @named_timers[name] = timer + else + @unnamed_timers.push(timer) + + stopTimer: (name) + @timers[name].stop() + +class Timer + constructor: (@frames, @callback, @repeat) => + @current_frame = 0 + @finished = false + + step: => + if @current_frame >= @frames + @callback() + + if repeat + @current_frame = 0 + else + @finished = true + + skip: (frames) => + @current_frame += frames + + stop: => + @finished = true \ No newline at end of file