diff --git a/sdk/example/game/lib/action.dart b/sdk/example/game/lib/action.dart new file mode 100644 index 0000000000000000000000000000000000000000..400bcd8b13dda63e1b84b1b01a66a540b89a1e7a --- /dev/null +++ b/sdk/example/game/lib/action.dart @@ -0,0 +1,156 @@ +part of sprites; + +typedef void PointSetter(Point point); + +abstract class Action { + bool _finished = false; + + void step(double dt); + void update(double t) { + } +} + +abstract class ActionInterval extends Action { + double _duration; + + bool _firstTick = true; + double _elapsed = 0.0; + + double get duration => _duration; + + ActionInterval([this._duration = 0.0]); + + void step(double dt) { + if (_firstTick) { + _firstTick = false; + } else { + _elapsed += dt; + } + + double t; + if (this._duration == 0.0) { + t = 1.0; + } else { + t = (_elapsed / _duration).clamp(0.0, 1.0); + } + + update(t); + + if (t >= 1.0) _finished = true; + } +} + +class ActionRepeat extends ActionInterval { + final int numRepeats; + final ActionInterval action; + + ActionRepeat(this.action, this.numRepeats) { + _duration = action.duration * numRepeats; + } + + void update(double t) { + action.update((t * numRepeats.toDouble()) % numRepeats.toDouble()); + } +} + +// TODO: Implement +class ActionSequence extends ActionInterval { + final List actions; + + ActionSequence(this.actions) { + for (Action action in actions) { + _duration += action._duration; + } + } +} + +class ActionRepeatForever extends Action { + final ActionInterval action; + double _elapsedInAction = 0.0; + + ActionRepeatForever(this.action); + + step(double dt) { + _elapsedInAction += dt; + while (_elapsedInAction > action.duration) { + _elapsedInAction -= action.duration; + } + _elapsedInAction = Math.max(_elapsedInAction, 0.0); + + double t; + if (action._duration == 0.0) { + t = 1.0; + } else { + t = (_elapsedInAction / action._duration).clamp(0.0, 1.0); + } + + action.update(t); + } +} + +class ActionTween extends ActionInterval { + final Function setter; + final startVal; + final endVal; + + var _delta; + + ActionTween(this.setter, this.startVal, this.endVal, double duration) : super(duration) { + _computeDelta(); + } + + void _computeDelta() { + if (startVal is Point) { + double xStart = startVal.x; + double yStart = startVal.y; + double xEnd = endVal.x; + double yEnd = endVal.y; + _delta = new Point(xEnd - xStart, yEnd - yStart); + } else if (startVal is double) { + _delta = endVal - startVal; + } else { + assert(false); + } + } + + void update(double t) { + var newVal; + + if (startVal is Point) { + double xStart = startVal.x; + double yStart = startVal.y; + double xDelta = _delta.x; + double yDelta = _delta.y; + + newVal = new Point(xStart + xDelta * t, yStart + yDelta * t); + } else if (startVal is double) { + newVal = startVal + _delta * t; + } else { + assert(false); + } + + setter(newVal); + } +} + +class ActionController { + + List _actions = []; + + ActionController(); + + void run(Action action) { + _actions.add(action); + } + + void step(double dt) { + for (int i = _actions.length - 1; i >= 0; i--) { + Action action = _actions[i]; + action.step(dt); + + if (action._finished) { + _actions.removeAt(i); + } + } + } +} \ No newline at end of file diff --git a/sdk/example/game/lib/color_secuence.dart b/sdk/example/game/lib/color_secuence.dart index 72e9a4000a185a342885ddef16d457e891e146e5..37fd5bb6b99c433bbd539dfc9516d7be7ca8f66d 100644 --- a/sdk/example/game/lib/color_secuence.dart +++ b/sdk/example/game/lib/color_secuence.dart @@ -32,21 +32,15 @@ class ColorSequence { int gDelta = ((rand.nextDouble() * 2.0 - 1.0) * greenVar).toInt(); int bDelta = ((rand.nextDouble() * 2.0 - 1.0) * blueVar).toInt(); - int aNew = _clamp(color.alpha + aDelta, 0, 255); - int rNew = _clamp(color.red + rDelta, 0, 255); - int gNew = _clamp(color.green + gDelta, 0, 255); - int bNew = _clamp(color.blue + bDelta, 0, 255); + int aNew = (color.alpha + aDelta).clamp(0, 255); + int rNew = (color.red + rDelta).clamp(0, 255); + int gNew = (color.green + gDelta).clamp(0, 255); + int bNew = (color.blue + bDelta).clamp(0, 255); colors.add(new Color.fromARGB(aNew, rNew, gNew, bNew)); } } - int _clamp(int val, int min, int max) { - if (val < min) return min; - if (val > max) return max; - return val; - } - Color colorAtPosition(double pos) { assert(pos >= 0.0 && pos <= 1.0); diff --git a/sdk/example/game/lib/game_demo_world.dart b/sdk/example/game/lib/game_demo_world.dart index a65ed98d979f5d4efdaad38b2c4990ea61d9d99a..eff5fe2f90b337579ab1bf08be449bbaa5837dde 100644 --- a/sdk/example/game/lib/game_demo_world.dart +++ b/sdk/example/game/lib/game_demo_world.dart @@ -303,6 +303,12 @@ class Asteroid extends Sprite { _rand.nextDouble() * _maxAsteroidSpeed * 2 - _maxAsteroidSpeed); userInteractionEnabled = true; + + // Rotate forever + double direction = (_rand.nextBool()) ? 360.0 : -360.0; + ActionTween rot = new ActionTween( (a) => rotation = a, 0.0, direction, 2.0 * _rand.nextDouble() + 2.0); + ActionRepeatForever repeat = new ActionRepeatForever(rot); + actions.run(repeat); } bool handleEvent(SpriteBoxEvent event) { diff --git a/sdk/example/game/lib/node.dart b/sdk/example/game/lib/node.dart index 51bb6239e01149bf56628caeb073dec73d3487fa..a1680b5fab28d1840d965ab5ef26333d2426af13 100644 --- a/sdk/example/game/lib/node.dart +++ b/sdk/example/game/lib/node.dart @@ -59,6 +59,15 @@ class Node { List_children = []; + ActionController _actions; + + ActionController get actions { + if (_actions == null) { + _actions = new ActionController(); + } + return _actions; + } + // Constructors /// Creates a new [Node] without any transformation. diff --git a/sdk/example/game/lib/sprite_box.dart b/sdk/example/game/lib/sprite_box.dart index 25598c381ef3b8542730b6992b996bfc660f93cb..aa5d064e2ac05f2274e9d90c3ec8f91df36c9742 100644 --- a/sdk/example/game/lib/sprite_box.dart +++ b/sdk/example/game/lib/sprite_box.dart @@ -287,10 +287,21 @@ class SpriteBox extends RenderBox { // Print frame rate if (_numFrames % 60 == 0) print("delta: $delta fps: $_frameRate"); + _runActions(_rootNode, delta); _callUpdate(_rootNode, delta); _scheduleTick(); } + void _runActions(Node node, double dt) { + if (node._actions != null) { + node._actions.step(dt); + } + for (int i = node.children.length - 1; i >= 0; i--) { + Node child = node.children[i]; + _runActions(child, dt); + } + } + void _callUpdate(Node node, double dt) { node.update(dt); for (int i = node.children.length - 1; i >= 0; i--) { diff --git a/sdk/example/game/lib/sprites.dart b/sdk/example/game/lib/sprites.dart index 96e25ebd9c977de112631f1a5607d65ab27135fb..f926906282eae524b96ab2ff70f203a7ac468428 100644 --- a/sdk/example/game/lib/sprites.dart +++ b/sdk/example/game/lib/sprites.dart @@ -21,3 +21,5 @@ part 'texture.dart'; part 'spritesheet.dart'; part 'particle_system.dart'; part 'color_secuence.dart'; +part 'action.dart'; +part 'util.dart'; diff --git a/sdk/example/game/lib/util.dart b/sdk/example/game/lib/util.dart new file mode 100644 index 0000000000000000000000000000000000000000..66568a5cb87fe62740fc746187d2be50b2c5cd9f --- /dev/null +++ b/sdk/example/game/lib/util.dart @@ -0,0 +1,2 @@ +part of sprites; +