Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: sky/sdk/example/game/lib/action.dart

Issue 1235653004: Improved action animations in sprites (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 part of sprites; 1 part of sprites;
2 2
3 typedef void ActionCallback(); 3 typedef void ActionCallback();
4 4
5 abstract class Action { 5 abstract class Action {
6 Object _tag; 6 Object _tag;
7 bool _finished = false; 7 bool _finished = false;
8 bool _added = false;
8 9
9 void step(double dt); 10 void step(double dt);
10 void update(double t) { 11 void update(double t) {
11 } 12 }
12 13
14 void _reset() {
15 _finished = false;
16 }
17
13 double get duration => 0.0; 18 double get duration => 0.0;
14 } 19 }
15 20
16 abstract class ActionInterval extends Action { 21 abstract class ActionInterval extends Action {
17 double _duration; 22 double _duration;
18 23
19 bool _firstTick = true; 24 bool _firstTick = true;
20 double _elapsed = 0.0; 25 double _elapsed = 0.0;
21 26
22 double get duration => _duration; 27 double get duration => _duration;
28 Curve curve;
23 29
24 ActionInterval([this._duration = 0.0]); 30 ActionInterval([this._duration = 0.0, this.curve]);
25 31
26 void step(double dt) { 32 void step(double dt) {
27 if (_firstTick) { 33 if (_firstTick) {
28 _firstTick = false; 34 _firstTick = false;
29 } else { 35 } else {
30 _elapsed += dt; 36 _elapsed += dt;
31 } 37 }
32 38
33 double t; 39 double t;
34 if (this._duration == 0.0) { 40 if (this._duration == 0.0) {
35 t = 1.0; 41 t = 1.0;
36 } else { 42 } else {
37 t = (_elapsed / _duration).clamp(0.0, 1.0); 43 t = (_elapsed / _duration).clamp(0.0, 1.0);
38 } 44 }
39 45
40 update(t); 46 if (curve == null) {
47 update(t);
48 } else {
49 update(curve.transform(t));
50 }
41 51
42 if (t >= 1.0) _finished = true; 52 if (t >= 1.0) _finished = true;
43 } 53 }
44 } 54 }
45 55
46 class ActionRepeat extends ActionInterval { 56 class ActionRepeat extends ActionInterval {
47 final int numRepeats; 57 final int numRepeats;
48 final ActionInterval action; 58 final ActionInterval action;
59 int _lastFinishedRepeat = -1;
49 60
50 ActionRepeat(this.action, this.numRepeats) { 61 ActionRepeat(this.action, this.numRepeats) {
51 _duration = action.duration * numRepeats; 62 _duration = action.duration * numRepeats;
52 } 63 }
53 64
54 void update(double t) { 65 void update(double t) {
55 action.update((t * numRepeats.toDouble()) % numRepeats.toDouble()); 66 int currentRepeat = Math.min((t * numRepeats.toDouble()).toInt(), numRepeats - 1);
67 for (int i = Math.max(_lastFinishedRepeat, 0); i < currentRepeat; i++) {
68 if (!action._finished) action.update(1.0);
69 action._reset();
70 }
71 _lastFinishedRepeat = currentRepeat;
72
73 double ta = (t * numRepeats.toDouble()) % 1.0;
74 action.update(ta);
75
76 if (t >= 1.0) {
77 action.update(1.0);
78 action._finished = true;
79 }
56 } 80 }
57 } 81 }
58 82
83 class ActionRepeatForever extends Action {
84 final ActionInterval action;
85 double _elapsedInAction = 0.0;
86
87 ActionRepeatForever(this.action);
88
89 step(double dt) {
90 _elapsedInAction += dt;
91 while (_elapsedInAction > action.duration) {
92 _elapsedInAction -= action.duration;
93 if (!action._finished) action.update(1.0);
94 action._reset();
95 }
96 _elapsedInAction = Math.max(_elapsedInAction, 0.0);
97
98 double t;
99 if (action._duration == 0.0) {
100 t = 1.0;
101 } else {
102 t = (_elapsedInAction / action._duration).clamp(0.0, 1.0);
103 }
104
105 action.update(t);
106 }
107 }
108
59 class ActionSequence extends ActionInterval { 109 class ActionSequence extends ActionInterval {
60 Action _a; 110 Action _a;
61 Action _b; 111 Action _b;
62 double _split; 112 double _split;
63 113
64 ActionSequence(List<Action> actions) { 114 ActionSequence(List<Action> actions) {
65 assert(actions.length >= 2); 115 assert(actions.length >= 2);
66 116
67 if (actions.length == 2) { 117 if (actions.length == 2) {
68 // Base case 118 // Base case
(...skipping 15 matching lines...) Expand all
84 134
85 void update(double t) { 135 void update(double t) {
86 if (t < _split) { 136 if (t < _split) {
87 // Play first action 137 // Play first action
88 double ta; 138 double ta;
89 if (_split > 0.0) { 139 if (_split > 0.0) {
90 ta = (t / _split).clamp(0.0, 1.0); 140 ta = (t / _split).clamp(0.0, 1.0);
91 } else { 141 } else {
92 ta = 1.0; 142 ta = 1.0;
93 } 143 }
94 _a.update(ta); 144 _updateWithCurve(_a, ta);
95 } else if (t >= 1.0) { 145 } else if (t >= 1.0) {
96 // Make sure everything is finished 146 // Make sure everything is finished
97 if (!_a._finished) _a.update(1.0); 147 if (!_a._finished) _finish(_a);
98 if (!_b._finished) _b.update(1.0); 148 if (!_b._finished) _finish(_b);
99 } else { 149 } else {
100 // Play second action, but first make sure the first has finished 150 // Play second action, but first make sure the first has finished
101 if (!_a._finished) _a.update(1.0); 151 if (!_a._finished) _finish(_a);
102 double tb; 152 double tb;
103 if (_split < 1.0) { 153 if (_split < 1.0) {
104 tb = (1.0 - (1.0 - t) / (1.0 - _split)).clamp(0.0, 1.0); 154 tb = (1.0 - (1.0 - t) / (1.0 - _split)).clamp(0.0, 1.0);
105 } else { 155 } else {
106 tb = 1.0; 156 tb = 1.0;
107 } 157 }
108 _b.update(tb); 158 _updateWithCurve(_b, tb);
159 }
160 }
161
162 void _updateWithCurve(Action action, double t) {
163 if (action is ActionInterval) {
164 ActionInterval actionInterval = action;
165 if (actionInterval.curve == null) {
166 action.update(t);
167 } else {
168 action.update(actionInterval.curve.transform(t));
169 }
170 } else {
171 action.update(t);
172 }
173
174 if (t >= 1.0) {
175 action._finished = true;
176 }
177 }
178
179 void _finish(Action action) {
180 action.update(1.0);
181 action._finished = true;
182 }
183
184 void _reset() {
185 super._reset();
186 _a._reset();
187 _b._reset();
188 }
189 }
190
191 class ActionGroup extends ActionInterval {
192 List<Action> _actions;
193
194 ActionGroup(this._actions) {
195 for (Action action in _actions) {
196 if (action.duration > _duration) {
197 _duration = action.duration;
198 }
199 }
200 }
201
202 void update(double t) {
203 if (t >= 1.0) {
204 // Finish all unfinished actions
205 for (Action action in _actions) {
206 if (!action._finished) {
207 action.update(1.0);
208 action._finished = true;
209 }
210 }
211 } else {
212 for (Action action in _actions) {
213 if (action.duration == 0.0) {
214 // Fire all instant actions immediately
215 if (!action._finished) {
216 action.update(1.0);
217 action._finished = true;
218 }
219 } else {
220 // Update child actions
221 double ta = (t / (action.duration / duration)).clamp(0.0, 1.0);
222 if (ta < 1.0) {
223 if (action is ActionInterval) {
224 ActionInterval actionInterval = action;
225 if (actionInterval.curve == null) {
226 action.update(ta);
227 } else {
228 action.update(actionInterval.curve.transform(ta));
229 }
230 } else {
231 action.update(ta);
232 }
233 } else if (!action._finished){
234 action.update(1.0);
235 action._finished = true;
236 }
237 }
238 }
239 }
240 }
241
242 void _reset() {
243 for (Action action in _actions) {
244 action._reset();
109 } 245 }
110 } 246 }
111 } 247 }
112 248
113 abstract class ActionInstant extends Action { 249 abstract class ActionInstant extends Action {
114 250
115 void step(double dt) { 251 void step(double dt) {
116 } 252 }
117 253
118 void update(double t) { 254 void update(double t) {
(...skipping 17 matching lines...) Expand all
136 class ActionRemoveNode extends ActionInstant { 272 class ActionRemoveNode extends ActionInstant {
137 Node _node; 273 Node _node;
138 274
139 ActionRemoveNode(this._node); 275 ActionRemoveNode(this._node);
140 276
141 void fire() { 277 void fire() {
142 _node.removeFromParent(); 278 _node.removeFromParent();
143 } 279 }
144 } 280 }
145 281
146 class ActionRepeatForever extends Action {
147 final ActionInterval action;
148 double _elapsedInAction = 0.0;
149
150 ActionRepeatForever(this.action);
151
152 step(double dt) {
153 _elapsedInAction += dt;
154 while (_elapsedInAction > action.duration) {
155 _elapsedInAction -= action.duration;
156 }
157 _elapsedInAction = Math.max(_elapsedInAction, 0.0);
158
159 double t;
160 if (action._duration == 0.0) {
161 t = 1.0;
162 } else {
163 t = (_elapsedInAction / action._duration).clamp(0.0, 1.0);
164 }
165
166 action.update(t);
167 }
168 }
169
170 class ActionTween extends ActionInterval { 282 class ActionTween extends ActionInterval {
171 final Function setter; 283 final Function setter;
172 final startVal; 284 final startVal;
173 final endVal; 285 final endVal;
174 286
175 var _delta; 287 var _delta;
176 288
177 ActionTween(this.setter, this.startVal, this.endVal, double duration) : super( duration) { 289 ActionTween(this.setter, this.startVal, this.endVal, double duration, [Curve c urve]) : super(duration, curve) {
178 _computeDelta(); 290 _computeDelta();
179 } 291 }
180 292
181 void _computeDelta() { 293 void _computeDelta() {
182 if (startVal is Point) { 294 if (startVal is Point) {
295 // Point
183 double xStart = startVal.x; 296 double xStart = startVal.x;
184 double yStart = startVal.y; 297 double yStart = startVal.y;
185 double xEnd = endVal.x; 298 double xEnd = endVal.x;
186 double yEnd = endVal.y; 299 double yEnd = endVal.y;
187 _delta = new Point(xEnd - xStart, yEnd - yStart); 300 _delta = new Point(xEnd - xStart, yEnd - yStart);
301 } else if (startVal is Size) {
302 // Size
303 double wStart = startVal.width;
304 double hStart = startVal.height;
305 double wEnd = endVal.width;
306 double hEnd = endVal.height;
307 _delta = new Size(wEnd - wStart, hEnd - hStart);
308 } else if (startVal is Rect) {
309 // Rect
310 double lStart = startVal.left;
311 double tStart = startVal.top;
312 double rStart = startVal.right;
313 double bStart = startVal.bottom;
314 double lEnd = endVal.left;
315 double tEnd = endVal.top;
316 double rEnd = endVal.right;
317 double bEnd = endVal.bottom;
318 _delta = new Rect.fromLTRB(lEnd - lStart, tEnd - tStart, rEnd - rStart, bE nd - bStart);
188 } else if (startVal is double) { 319 } else if (startVal is double) {
320 // Double
189 _delta = endVal - startVal; 321 _delta = endVal - startVal;
190 } else if (startVal is Color) { 322 } else if (startVal is Color) {
323 // Color
191 int aDelta = endVal.alpha - startVal.alpha; 324 int aDelta = endVal.alpha - startVal.alpha;
192 int rDelta = endVal.red - startVal.red; 325 int rDelta = endVal.red - startVal.red;
193 int gDelta = endVal.green - startVal.green; 326 int gDelta = endVal.green - startVal.green;
194 int bDelta = endVal.blue - startVal.blue; 327 int bDelta = endVal.blue - startVal.blue;
195 _delta = new _ColorDiff(aDelta, rDelta, gDelta, bDelta); 328 _delta = new _ColorDiff(aDelta, rDelta, gDelta, bDelta);
196 } else { 329 } else {
197 assert(false); 330 assert(false);
198 } 331 }
199 } 332 }
200 333
201 void update(double t) { 334 void update(double t) {
202 var newVal; 335 var newVal;
203 336
204 if (startVal is Point) { 337 if (startVal is Point) {
205 // Point 338 // Point
206 double xStart = startVal.x; 339 double xStart = startVal.x;
207 double yStart = startVal.y; 340 double yStart = startVal.y;
208 double xDelta = _delta.x; 341 double xDelta = _delta.x;
209 double yDelta = _delta.y; 342 double yDelta = _delta.y;
210 newVal = new Point(xStart + xDelta * t, yStart + yDelta * t); 343 newVal = new Point(xStart + xDelta * t, yStart + yDelta * t);
344 } else if (startVal is Size) {
345 // Size
346 double wStart = startVal.width;
347 double hStart = startVal.height;
348 double wDelta = _delta.width;
349 double hDelta = _delta.height;
350 newVal = new Size(wStart + wDelta * t, hStart + hDelta * t);
351 } else if (startVal is Rect) {
352 // Rect
353 double lStart = startVal.left;
354 double tStart = startVal.top;
355 double rStart = startVal.right;
356 double bStart = startVal.bottom;
357 double lDelta = _delta.left;
358 double tDelta = _delta.top;
359 double rDelta = _delta.right;
360 double bDelta = _delta.bottom;
361 newVal = new Rect.fromLTRB(lStart + lDelta * t, tStart + tDelta * t, rStar t + rDelta * t, bStart + bDelta * t);
211 } else if (startVal is double) { 362 } else if (startVal is double) {
212 // Doubles 363 // Doubles
213 newVal = startVal + _delta * t; 364 newVal = startVal + _delta * t;
214 } else if (startVal is Color) { 365 } else if (startVal is Color) {
215 // Colors 366 // Colors
216 int aNew = (startVal.alpha + (_delta.alpha * t).toInt()).clamp(0, 255); 367 int aNew = (startVal.alpha + (_delta.alpha * t).toInt()).clamp(0, 255);
217 int rNew = (startVal.red + (_delta.red * t).toInt()).clamp(0, 255); 368 int rNew = (startVal.red + (_delta.red * t).toInt()).clamp(0, 255);
218 int gNew = (startVal.green + (_delta.green * t).toInt()).clamp(0, 255); 369 int gNew = (startVal.green + (_delta.green * t).toInt()).clamp(0, 255);
219 int bNew = (startVal.blue + (_delta.blue * t).toInt()).clamp(0, 255); 370 int bNew = (startVal.blue + (_delta.blue * t).toInt()).clamp(0, 255);
220 newVal = new Color.fromARGB(aNew, rNew, gNew, bNew); 371 newVal = new Color.fromARGB(aNew, rNew, gNew, bNew);
221 } else { 372 } else {
222 // Oopses 373 // Oopses
223 assert(false); 374 assert(false);
224 } 375 }
225 376
226 setter(newVal); 377 setter(newVal);
227 } 378 }
228 } 379 }
229 380
230 class ActionController { 381 class ActionController {
231 382
232 List<Action> _actions = []; 383 List<Action> _actions = [];
233 384
234 ActionController(); 385 ActionController();
235 386
236 void run(Action action, [Object tag]) { 387 void run(Action action, [Object tag]) {
388 assert(!action._added);
389
237 action._tag = tag; 390 action._tag = tag;
391 action._added = true;
238 action.update(0.0); 392 action.update(0.0);
239 _actions.add(action); 393 _actions.add(action);
240 } 394 }
241 395
242 void stop(Action action) { 396 void stop(Action action) {
243 _actions.remove(action); 397 if (_actions.remove(action)) {
398 action._added = false;
399 action._reset();
400 }
401 }
402
403 void _stopAtIndex(int i) {
404 Action action = _actions[i];
405 action._added = false;
406 action._reset();
407 _actions.removeAt(i);
244 } 408 }
245 409
246 void stopWithTag(Object tag) { 410 void stopWithTag(Object tag) {
247 for (int i = _actions.length - 1; i >= 0; i--) { 411 for (int i = _actions.length - 1; i >= 0; i--) {
248 Action action = _actions[i]; 412 Action action = _actions[i];
249 if (action._tag == tag) { 413 if (action._tag == tag) {
250 _actions.removeAt(i); 414 _stopAtIndex(i);
251 print("removing tag: $tag");
252 } 415 }
253 } 416 }
254 } 417 }
255 418
256 void stopAll() { 419 void stopAll() {
257 _actions.clear(); 420 for (int i = _actions.length - 1; i >= 0; i--) {
421 _stopAtIndex(i);
422 }
258 } 423 }
259 424
260 void step(double dt) { 425 void step(double dt) {
261 for (int i = _actions.length - 1; i >= 0; i--) { 426 for (int i = _actions.length - 1; i >= 0; i--) {
262 Action action = _actions[i]; 427 Action action = _actions[i];
263 action.step(dt); 428 action.step(dt);
264 429
265 if (action._finished) { 430 if (action._finished) {
431 action._added = false;
266 _actions.removeAt(i); 432 _actions.removeAt(i);
267 } 433 }
268 } 434 }
269 } 435 }
270 } 436 }
271 437
272 class _ColorDiff { 438 class _ColorDiff {
273 final int alpha; 439 final int alpha;
274 final int red; 440 final int red;
275 final int green; 441 final int green;
276 final int blue; 442 final int blue;
277 443
278 _ColorDiff(this.alpha, this.red, this.green, this.blue); 444 _ColorDiff(this.alpha, this.red, this.green, this.blue);
279 } 445 }
446
447 double _bounce(double t)
448 {
449 if (t < 1.0 / 2.75) {
450 return 7.5625 * t * t;
451 } else if (t < 2 / 2.75) {
452 t -= 1.5 / 2.75;
453 return 7.5625 * t * t + 0.75;
454 } else if (t < 2.5 / 2.75) {
455 t -= 2.25 / 2.75;
456 return 7.5625 * t * t + 0.9375;
457 }
458 t -= 2.625 / 2.75;
459 return 7.5625 * t * t + 0.984375;
460 }
461
462 class BounceOutCurve implements Curve {
463 const BounceOutCurve();
464
465 double transform(double t) {
466 return _bounce(t);
467 }
468 }
469
470 const BounceOutCurve bounceOut = const BounceOutCurve();
OLDNEW
« no previous file with comments | « no previous file | sky/sdk/example/game/lib/sprite_box.dart » ('j') | sky/sdk/example/game/lib/sprites.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698