pxt-common-packages 10.3.5 → 10.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/libs/azureiot/built/debug/binary.js +461 -461
- package/libs/color/built/debug/binary.js +8 -8
- package/libs/color-sensor/built/debug/binary.js +8 -8
- package/libs/controller/built/debug/binary.js +7239 -7205
- package/libs/controller---none/built/debug/binary.js +7219 -7185
- package/libs/datalogger/built/debug/binary.js +63 -63
- package/libs/edge-connector/built/debug/binary.js +8 -8
- package/libs/esp32/built/debug/binary.js +462 -462
- package/libs/game/animation.ts +403 -323
- package/libs/game/built/debug/binary.js +7158 -7124
- package/libs/game/controller.ts +6 -0
- package/libs/game/info.ts +9 -0
- package/libs/game/physics.ts +2 -2
- package/libs/lcd/built/debug/binary.js +8 -8
- package/libs/light-spectrum-sensor/built/debug/binary.js +8 -8
- package/libs/lora/built/debug/binary.js +8 -8
- package/libs/matrix-keypad/built/debug/binary.js +8 -8
- package/libs/mixer/instrument.ts +22 -3
- package/libs/mixer/sequencer.ts +2 -2
- package/libs/mqtt/built/debug/binary.js +176 -176
- package/libs/multiplayer/fieldEditors.ts +1 -9
- package/libs/multiplayer/images.ts +1 -1
- package/libs/multiplayer/player.ts +706 -0
- package/libs/multiplayer/pxt.json +1 -1
- package/libs/multiplayer/stateKind.ts +2 -2
- package/libs/net/built/debug/binary.js +176 -176
- package/libs/net-game/built/debug/binary.js +8747 -8713
- package/libs/palette/built/debug/binary.js +7153 -7119
- package/libs/pixel/built/debug/binary.js +8 -8
- package/libs/power/built/debug/binary.js +8 -8
- package/libs/proximity/built/debug/binary.js +8 -8
- package/libs/radio/built/debug/binary.js +8 -8
- package/libs/radio-broadcast/built/debug/binary.js +8 -8
- package/libs/rotary-encoder/built/debug/binary.js +8 -8
- package/libs/screen/built/debug/binary.js +50 -50
- package/libs/servo/built/debug/binary.js +8 -8
- package/libs/sprite-scaling/built/debug/binary.js +7157 -7123
- package/libs/storyboard/built/debug/binary.js +7157 -7123
- package/package.json +1 -1
- package/libs/multiplayer/mp.ts +0 -643
package/libs/game/animation.ts
CHANGED
|
@@ -28,130 +28,87 @@ namespace animation {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export class Path {
|
|
31
|
-
|
|
32
|
-
protected lastNode: number; // The index of the last node to fire
|
|
31
|
+
length: number;
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
protected args: number[];
|
|
34
|
+
protected currentCommand: string;
|
|
35
|
+
protected lastControlX: number;
|
|
36
|
+
protected lastControlY: number;
|
|
37
|
+
|
|
38
|
+
protected startX: number;
|
|
39
|
+
protected startY: number;
|
|
40
|
+
|
|
41
|
+
protected lastX: number;
|
|
42
|
+
protected lastY: number;
|
|
43
|
+
|
|
44
|
+
protected strIndex: number;
|
|
45
|
+
protected commandIndex: number;
|
|
46
|
+
|
|
47
|
+
constructor(protected path: string) {
|
|
48
|
+
this.strIndex = 0;
|
|
49
|
+
|
|
50
|
+
// Run through the path once to get the length and check for errors
|
|
51
|
+
this.length = 0;
|
|
52
|
+
while (this.strIndex < this.path.length) {
|
|
53
|
+
this.readNextCommand();
|
|
54
|
+
if (this.currentCommand) this.length++;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.reset();
|
|
37
58
|
}
|
|
38
59
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const p1 = new Point(args[0], args[1]);
|
|
45
|
-
node = new MoveTo(p1);
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
case "m": { // m dx dy
|
|
49
|
-
const p1 = new Point(p0.x + args[0], p0.y + args[1]);
|
|
50
|
-
node = new MoveTo(p1);
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
case "L": { // L x y
|
|
54
|
-
const p1 = new Point(args[0], args[1]);
|
|
55
|
-
node = new LineTo(p0, p1);
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
case "l": { // l dx dy
|
|
59
|
-
const p1 = new Point(p0.x + args[0], p0.y + args[1]);
|
|
60
|
-
node = new LineTo(p0, p1);
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
case "H": { // H x
|
|
64
|
-
const p1 = new Point(args[0], p0.y);
|
|
65
|
-
node = new LineTo(p0, p1);
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
case "h": { // h dx
|
|
69
|
-
const p1 = new Point(p0.x + args[0], p0.y);
|
|
70
|
-
node = new LineTo(p0, p1);
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
case "V": { // V y
|
|
74
|
-
const p1 = new Point(p0.x, args[0]);
|
|
75
|
-
node = new LineTo(p0, p1);
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
case "v": { // v dy
|
|
79
|
-
const p1 = new Point(p0.x, p0.y + args[0]);
|
|
80
|
-
node = new LineTo(p0, p1);
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
case "Q": { // Q x1 y1 x2 y2
|
|
84
|
-
const p1 = new Point(args[0], args[1]);
|
|
85
|
-
const p2 = new Point(args[2], args[3]);
|
|
86
|
-
node = new QuadraticCurveTo(p0, p1, p2);
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
case "q": { // q dx1 dy1 dx2 dy2
|
|
90
|
-
const p1 = new Point(p0.x + args[0], p0.y + args[1]);
|
|
91
|
-
const p2 = new Point(p0.x + args[2], p0.y + args[3]);
|
|
92
|
-
node = new QuadraticCurveTo(p0, p1, p2);
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
case "T": { // T x2 y2
|
|
96
|
-
let lastControlPoint: Point = lastNode.getLastControlPoint();
|
|
97
|
-
if (!lastControlPoint) break;
|
|
60
|
+
protected readNextCommand() {
|
|
61
|
+
if (this.strIndex >= this.path.length) {
|
|
62
|
+
this.currentCommand = undefined;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
98
65
|
|
|
99
|
-
|
|
100
|
-
const p2 = new Point(args[0], args[1]);
|
|
101
|
-
node = new QuadraticCurveTo(p0, p1, p2);
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
case "t": { // t dx2 dy2
|
|
105
|
-
let lastControlPoint: Point = lastNode.getLastControlPoint();
|
|
106
|
-
if (!lastControlPoint) break;
|
|
66
|
+
this.currentCommand = this.readNextToken();
|
|
107
67
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const p1 = new Point(p0.x + (p0.x - lastControlPoint.x), p0.y + (p0.y - lastControlPoint.y));
|
|
142
|
-
const p2 = new Point(p0.x + args[0], p0.y + args[1]);
|
|
143
|
-
const p3 = new Point(p0.x + args[2], p0.y + args[3]);
|
|
144
|
-
node = new CubicCurveTo(p0, p1, p2, p3);
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
case "Z": // Z
|
|
148
|
-
case "z": { // z
|
|
149
|
-
node = new LineTo(p0, pathStart);
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
68
|
+
if (!this.currentCommand) return;
|
|
69
|
+
|
|
70
|
+
this.args = [];
|
|
71
|
+
|
|
72
|
+
const numArgs = Path.commandToArgCount(this.currentCommand);
|
|
73
|
+
|
|
74
|
+
if (numArgs === -1) throw "Unknown path command '" + this.currentCommand +"'";
|
|
75
|
+
|
|
76
|
+
for (let i = 0; i < numArgs; i++) {
|
|
77
|
+
this.args.push(parseFloat(this.readNextToken()))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for (const arg of this.args) {
|
|
81
|
+
if (Number.isNaN(arg)) throw "Invalid argument for path command '" + this.currentCommand + "'";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
reset() {
|
|
86
|
+
this.args = undefined;
|
|
87
|
+
this.currentCommand = undefined;
|
|
88
|
+
this.lastControlX = undefined;
|
|
89
|
+
this.lastControlY = undefined;
|
|
90
|
+
this.startX = undefined;
|
|
91
|
+
this.startY = undefined;
|
|
92
|
+
this.lastX = undefined;
|
|
93
|
+
this.lastY = undefined;
|
|
94
|
+
this.strIndex = 0;
|
|
95
|
+
this.commandIndex = 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected readNextToken() {
|
|
99
|
+
while (this.path.charCodeAt(this.strIndex) === 32 && this.strIndex < this.path.length) {
|
|
100
|
+
this.strIndex ++;
|
|
152
101
|
}
|
|
153
102
|
|
|
154
|
-
return
|
|
103
|
+
if (this.strIndex >= this.path.length) return undefined;
|
|
104
|
+
|
|
105
|
+
const tokenStart = this.strIndex;
|
|
106
|
+
|
|
107
|
+
while (this.path.charCodeAt(this.strIndex) !== 32 && this.strIndex < this.path.length) {
|
|
108
|
+
this.strIndex++;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return this.path.substr(tokenStart, this.strIndex - tokenStart);
|
|
155
112
|
}
|
|
156
113
|
|
|
157
114
|
private static commandToArgCount(command: string): number {
|
|
@@ -191,227 +148,344 @@ namespace animation {
|
|
|
191
148
|
}
|
|
192
149
|
}
|
|
193
150
|
|
|
194
|
-
public
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
// This implementation of SVG parsing does not support the A/a commands, nor does it support exponents in arguments
|
|
199
|
-
const digits = "0123456789";
|
|
200
|
-
const separators = ", \t\n\r\f\v";
|
|
201
|
-
const signs = "+-";
|
|
202
|
-
|
|
203
|
-
let currentArg: string = "";
|
|
204
|
-
let command: string = null;
|
|
205
|
-
let args: number[] = [];
|
|
206
|
-
|
|
207
|
-
for (let i = 0; i < pathString.length; i++) {
|
|
208
|
-
const char = pathString.charAt(i);
|
|
209
|
-
const lastNode = path.nodes[path.nodes.length - 1];
|
|
210
|
-
|
|
211
|
-
// This is an SVG path parser. It's kinda complicated. For each character, evaluate the following conditions:
|
|
212
|
-
// - if it's a digit, add it to the current argument
|
|
213
|
-
// - else if it's whitespace or newline, finish the current argument and prepare for the next one
|
|
214
|
-
// - else if it's a command, complete the previous argument, and prepare for the next one
|
|
215
|
-
// - if there's sufficient data to make a node during this step, create it and continue
|
|
216
|
-
// - else if it's a plus/minus sign, and if it's the start of a new argument, add it to allow for positive/negative numbers
|
|
217
|
-
// - if it's the end of the string, complete the current argument before proceeding to the next step
|
|
218
|
-
// - if there's sufficient data to make a node after all of these steps, create it
|
|
219
|
-
if (digits.indexOf(char) > -1) { // Parses number arguments
|
|
220
|
-
currentArg += char;
|
|
221
|
-
} else if (separators.indexOf(char) > -1 && currentArg) { // Terminates number arguments
|
|
222
|
-
args.push(parseInt(currentArg));
|
|
223
|
-
currentArg = "";
|
|
224
|
-
} else if (this.commandToArgCount(char) > -1) { // Parses command arguments
|
|
225
|
-
if (command && currentArg) {
|
|
226
|
-
args.push(parseInt(currentArg));
|
|
227
|
-
|
|
228
|
-
// Try to finish up this node, otherwise just toss it out
|
|
229
|
-
if (command && args.length >= this.commandToArgCount(command)) {
|
|
230
|
-
let node: PathNode = this.generateNode(p0, command, args, [
|
|
231
|
-
pathStart,
|
|
232
|
-
lastNode
|
|
233
|
-
]);
|
|
234
|
-
path.add(node);
|
|
235
|
-
p0 = node.getEndPoint(); // Set the start for the next node to the end of this node
|
|
236
|
-
if (node.setStart) pathStart = p0; // If this is a move command, then this sets the new start of the path (for the Z/z command)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Clean up before continuing
|
|
240
|
-
command = "";
|
|
241
|
-
args = [];
|
|
242
|
-
currentArg = "";
|
|
243
|
-
}
|
|
244
|
-
command = char;
|
|
245
|
-
} else if (signs.indexOf(char) > -1) { // Allows for positive/negative values
|
|
246
|
-
if (currentArg) {
|
|
247
|
-
args.push(parseInt(currentArg));
|
|
248
|
-
currentArg = "";
|
|
249
|
-
}
|
|
250
|
-
currentArg = char;
|
|
251
|
-
}
|
|
151
|
+
public run(interval: number, target: Sprite, runningTime: number): boolean {
|
|
152
|
+
const nodeIndex = Math.floor(runningTime / interval); // The current node
|
|
153
|
+
const nodeTime = runningTime % interval; // The time the current node has been animating
|
|
252
154
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
155
|
+
if (this.startX === undefined) {
|
|
156
|
+
this.startX = target.x;
|
|
157
|
+
this.startY = target.y;
|
|
158
|
+
this.lastX = target.x;
|
|
159
|
+
this.lastY = target.y;
|
|
160
|
+
this.commandIndex = 0;
|
|
161
|
+
this.readNextCommand();
|
|
162
|
+
}
|
|
259
163
|
|
|
260
|
-
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
lastNode
|
|
266
|
-
]);
|
|
267
|
-
path.add(node);
|
|
268
|
-
p0 = node.getEndPoint();
|
|
269
|
-
if (node.setStart) pathStart = p0;
|
|
270
|
-
|
|
271
|
-
// Reset and prepare for the next command
|
|
272
|
-
command = "";
|
|
273
|
-
args = [];
|
|
274
|
-
currentArg = "";
|
|
164
|
+
while (this.commandIndex < nodeIndex) {
|
|
165
|
+
if (this.currentCommand) {
|
|
166
|
+
this.runCurrentCommand(target, interval, interval);
|
|
167
|
+
this.lastX = target.x;
|
|
168
|
+
this.lastY = target.y;
|
|
275
169
|
}
|
|
170
|
+
this.commandIndex++
|
|
171
|
+
this.readNextCommand();
|
|
276
172
|
}
|
|
277
173
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
public add(node: PathNode) {
|
|
282
|
-
this.nodes.push(node);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
get length(): number {
|
|
286
|
-
return this.nodes.length;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
public run(interval: number, target: Sprite, startedAt: number): boolean {
|
|
290
|
-
const runningTime = control.millis() - startedAt; // The time since the start of the path
|
|
291
|
-
const nodeIndex = Math.floor(runningTime / interval); // The current node
|
|
292
|
-
const nodeTime = runningTime % interval; // The time the current node has been animating
|
|
293
|
-
|
|
294
|
-
if (this.lastNode > -1 && this.lastNode < nodeIndex && this.nodes.length) { // If the last node hasn't been completed yet
|
|
295
|
-
this.nodes[this.lastNode].apply(target, interval, interval); // Applies the last state of the previous node in case it was missed (this makes sure all moveTos fire)
|
|
296
|
-
|
|
297
|
-
if (nodeIndex >= this.nodes.length) return true; // Once the nodeIndex is past the last item of the array, only then end the animation
|
|
174
|
+
if (nodeIndex >= this.length) {
|
|
175
|
+
return true;
|
|
298
176
|
}
|
|
299
|
-
this.lastNode = nodeIndex;
|
|
300
177
|
|
|
301
|
-
this.
|
|
178
|
+
this.runCurrentCommand(target, nodeTime, interval);
|
|
302
179
|
return false;
|
|
303
180
|
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
export abstract class PathNode {
|
|
307
|
-
setStart: boolean;
|
|
308
|
-
constructor() {
|
|
309
|
-
this.setStart = false;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
apply(target: Sprite, nodeTime: number, interval: number) {};
|
|
313
|
-
|
|
314
|
-
getLastControlPoint(): Point {
|
|
315
|
-
return null;
|
|
316
|
-
};
|
|
317
181
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
182
|
+
protected runCurrentCommand(target: Sprite, nodeTime: number, intervalTime: number) {
|
|
183
|
+
switch (this.currentCommand) {
|
|
184
|
+
case "M": // M x y
|
|
185
|
+
this.lastControlX = undefined;
|
|
186
|
+
this.lastControlY = undefined;
|
|
187
|
+
moveTo(
|
|
188
|
+
target,
|
|
189
|
+
nodeTime,
|
|
190
|
+
intervalTime,
|
|
191
|
+
this.args[0],
|
|
192
|
+
this.args[1]
|
|
193
|
+
);
|
|
194
|
+
break;
|
|
195
|
+
case "m": // m dx dy
|
|
196
|
+
this.lastControlX = undefined;
|
|
197
|
+
this.lastControlY = undefined;
|
|
198
|
+
moveTo(
|
|
199
|
+
target,
|
|
200
|
+
nodeTime,
|
|
201
|
+
intervalTime,
|
|
202
|
+
this.args[0] + this.lastX,
|
|
203
|
+
this.args[1] + this.lastY
|
|
204
|
+
);
|
|
205
|
+
break;
|
|
206
|
+
case "L": // L x y
|
|
207
|
+
this.lastControlX = undefined;
|
|
208
|
+
this.lastControlY = undefined;
|
|
209
|
+
lineTo(
|
|
210
|
+
target,
|
|
211
|
+
nodeTime,
|
|
212
|
+
intervalTime,
|
|
213
|
+
this.lastX,
|
|
214
|
+
this.lastY,
|
|
215
|
+
this.args[0],
|
|
216
|
+
this.args[1]
|
|
217
|
+
);
|
|
218
|
+
break;
|
|
219
|
+
case "l": // l dx dy
|
|
220
|
+
this.lastControlX = undefined;
|
|
221
|
+
this.lastControlY = undefined;
|
|
222
|
+
lineTo(
|
|
223
|
+
target,
|
|
224
|
+
nodeTime,
|
|
225
|
+
intervalTime,
|
|
226
|
+
this.lastX,
|
|
227
|
+
this.lastY,
|
|
228
|
+
this.args[0] + this.lastX,
|
|
229
|
+
this.args[1] + this.lastY
|
|
230
|
+
);
|
|
231
|
+
break;
|
|
232
|
+
case "H": // H x
|
|
233
|
+
this.lastControlX = undefined;
|
|
234
|
+
this.lastControlY = undefined;
|
|
235
|
+
lineTo(
|
|
236
|
+
target,
|
|
237
|
+
nodeTime,
|
|
238
|
+
intervalTime,
|
|
239
|
+
this.lastX,
|
|
240
|
+
this.lastY,
|
|
241
|
+
this.args[0],
|
|
242
|
+
this.lastY
|
|
243
|
+
);
|
|
244
|
+
break;
|
|
245
|
+
case "h": // h dx
|
|
246
|
+
this.lastControlX = undefined;
|
|
247
|
+
this.lastControlY = undefined;
|
|
248
|
+
lineTo(
|
|
249
|
+
target,
|
|
250
|
+
nodeTime,
|
|
251
|
+
intervalTime,
|
|
252
|
+
this.lastX,
|
|
253
|
+
this.lastY,
|
|
254
|
+
this.args[0] + this.lastX,
|
|
255
|
+
this.lastY
|
|
256
|
+
);
|
|
257
|
+
break;
|
|
258
|
+
case "V": // V y
|
|
259
|
+
this.lastControlX = undefined;
|
|
260
|
+
this.lastControlY = undefined;
|
|
261
|
+
lineTo(
|
|
262
|
+
target,
|
|
263
|
+
nodeTime,
|
|
264
|
+
intervalTime,
|
|
265
|
+
this.lastX,
|
|
266
|
+
this.lastY,
|
|
267
|
+
this.lastX,
|
|
268
|
+
this.args[0]
|
|
269
|
+
);
|
|
270
|
+
break;
|
|
271
|
+
case "v": // v dy
|
|
272
|
+
this.lastControlX = undefined;
|
|
273
|
+
this.lastControlY = undefined;
|
|
274
|
+
lineTo(
|
|
275
|
+
target,
|
|
276
|
+
nodeTime,
|
|
277
|
+
intervalTime,
|
|
278
|
+
this.lastX,
|
|
279
|
+
this.lastY,
|
|
280
|
+
this.lastX,
|
|
281
|
+
this.args[0] + this.lastY
|
|
282
|
+
);
|
|
283
|
+
break;
|
|
284
|
+
case "Q": // Q x1 y1 x2 y2
|
|
285
|
+
this.lastControlX = this.args[0];
|
|
286
|
+
this.lastControlY = this.args[1];
|
|
287
|
+
quadraticCurveTo(
|
|
288
|
+
target,
|
|
289
|
+
nodeTime,
|
|
290
|
+
intervalTime,
|
|
291
|
+
this.lastX,
|
|
292
|
+
this.lastY,
|
|
293
|
+
this.args[0],
|
|
294
|
+
this.args[1],
|
|
295
|
+
this.args[2],
|
|
296
|
+
this.args[3]
|
|
297
|
+
)
|
|
298
|
+
break;
|
|
299
|
+
case "q": // q dx1 dy1 dx2 dy2
|
|
300
|
+
this.lastControlX = this.args[0] + this.lastX;
|
|
301
|
+
this.lastControlY = this.args[1] + this.lastY;
|
|
302
|
+
quadraticCurveTo(
|
|
303
|
+
target,
|
|
304
|
+
nodeTime,
|
|
305
|
+
intervalTime,
|
|
306
|
+
this.lastX,
|
|
307
|
+
this.lastY,
|
|
308
|
+
this.args[0] + this.lastX,
|
|
309
|
+
this.args[1] + this.lastY,
|
|
310
|
+
this.args[2] + this.lastX,
|
|
311
|
+
this.args[3] + this.lastY
|
|
312
|
+
);
|
|
313
|
+
break;
|
|
314
|
+
case "T": // T x2 y2
|
|
315
|
+
this.ensureControlPoint();
|
|
316
|
+
quadraticCurveTo(
|
|
317
|
+
target,
|
|
318
|
+
nodeTime,
|
|
319
|
+
intervalTime,
|
|
320
|
+
this.lastX,
|
|
321
|
+
this.lastY,
|
|
322
|
+
this.lastX + this.lastX - this.lastControlX,
|
|
323
|
+
this.lastY + this.lastY - this.lastControlY,
|
|
324
|
+
this.args[0],
|
|
325
|
+
this.args[1],
|
|
326
|
+
);
|
|
327
|
+
if (nodeTime === intervalTime) {
|
|
328
|
+
this.lastControlX = this.lastX + this.lastX - this.lastControlX;
|
|
329
|
+
this.lastControlY = this.lastY + this.lastY - this.lastControlY;
|
|
330
|
+
}
|
|
331
|
+
break;
|
|
332
|
+
case "t": // t dx2 dy2
|
|
333
|
+
this.ensureControlPoint();
|
|
334
|
+
quadraticCurveTo(
|
|
335
|
+
target,
|
|
336
|
+
nodeTime,
|
|
337
|
+
intervalTime,
|
|
338
|
+
this.lastX,
|
|
339
|
+
this.lastY,
|
|
340
|
+
this.lastX + this.lastX - this.lastControlX,
|
|
341
|
+
this.lastY + this.lastY - this.lastControlY,
|
|
342
|
+
this.args[0] + this.lastX,
|
|
343
|
+
this.args[1] + this.lastY,
|
|
344
|
+
);
|
|
345
|
+
if (nodeTime === intervalTime) {
|
|
346
|
+
this.lastControlX = this.lastX + this.lastX - this.lastControlX;
|
|
347
|
+
this.lastControlY = this.lastY + this.lastY - this.lastControlY;
|
|
348
|
+
}
|
|
349
|
+
break;
|
|
350
|
+
case "C": // C x1 y1 x2 y2 x3 y3
|
|
351
|
+
this.lastControlX = this.args[2];
|
|
352
|
+
this.lastControlY = this.args[3];
|
|
353
|
+
cubicCurveTo(
|
|
354
|
+
target,
|
|
355
|
+
nodeTime,
|
|
356
|
+
intervalTime,
|
|
357
|
+
this.lastX,
|
|
358
|
+
this.lastY,
|
|
359
|
+
this.args[0],
|
|
360
|
+
this.args[1],
|
|
361
|
+
this.args[2],
|
|
362
|
+
this.args[3],
|
|
363
|
+
this.args[4],
|
|
364
|
+
this.args[5],
|
|
365
|
+
);
|
|
366
|
+
break;
|
|
367
|
+
case "c": // c dx1 dy1 dx2 dy2 dx3 dy3
|
|
368
|
+
this.lastControlX = this.args[2] + this.lastX;
|
|
369
|
+
this.lastControlY = this.args[3] + this.lastY;
|
|
370
|
+
cubicCurveTo(
|
|
371
|
+
target,
|
|
372
|
+
nodeTime,
|
|
373
|
+
intervalTime,
|
|
374
|
+
this.lastX,
|
|
375
|
+
this.lastY,
|
|
376
|
+
this.args[0] + this.lastX,
|
|
377
|
+
this.args[1] + this.lastY,
|
|
378
|
+
this.args[2] + this.lastX,
|
|
379
|
+
this.args[3] + this.lastY,
|
|
380
|
+
this.args[4] + this.lastX,
|
|
381
|
+
this.args[5] + this.lastY,
|
|
382
|
+
);
|
|
383
|
+
break;
|
|
384
|
+
case "S": // S x2 y2 x3 y3
|
|
385
|
+
this.ensureControlPoint();
|
|
386
|
+
cubicCurveTo(
|
|
387
|
+
target,
|
|
388
|
+
nodeTime,
|
|
389
|
+
intervalTime,
|
|
390
|
+
this.lastX,
|
|
391
|
+
this.lastY,
|
|
392
|
+
this.lastX + this.lastX - this.lastControlX,
|
|
393
|
+
this.lastY + this.lastY - this.lastControlY,
|
|
394
|
+
this.args[0],
|
|
395
|
+
this.args[1],
|
|
396
|
+
this.args[2],
|
|
397
|
+
this.args[3]
|
|
398
|
+
);
|
|
399
|
+
if (nodeTime === intervalTime) {
|
|
400
|
+
this.lastControlX = this.args[0];
|
|
401
|
+
this.lastControlY = this.args[1];
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
case "s": // s dx2 dy2 dx3 dy3
|
|
405
|
+
this.ensureControlPoint();
|
|
406
|
+
cubicCurveTo(
|
|
407
|
+
target,
|
|
408
|
+
nodeTime,
|
|
409
|
+
intervalTime,
|
|
410
|
+
this.lastX,
|
|
411
|
+
this.lastY,
|
|
412
|
+
this.lastX + this.lastX - this.lastControlX,
|
|
413
|
+
this.lastY + this.lastY - this.lastControlY,
|
|
414
|
+
this.args[0] + this.lastX,
|
|
415
|
+
this.args[1] + this.lastY,
|
|
416
|
+
this.args[2] + this.lastX,
|
|
417
|
+
this.args[3] + this.lastY,
|
|
418
|
+
);
|
|
419
|
+
if (nodeTime === intervalTime) {
|
|
420
|
+
this.lastControlX = this.args[0] + this.lastX;
|
|
421
|
+
this.lastControlY = this.args[1] + this.lastY;
|
|
422
|
+
}
|
|
423
|
+
break;
|
|
424
|
+
case "Z": // Z
|
|
425
|
+
case "z": // z
|
|
426
|
+
this.lastControlX = undefined;
|
|
427
|
+
this.lastControlY = undefined;
|
|
428
|
+
lineTo(
|
|
429
|
+
target,
|
|
430
|
+
nodeTime,
|
|
431
|
+
intervalTime,
|
|
432
|
+
this.lastX,
|
|
433
|
+
this.lastY,
|
|
434
|
+
this.startX,
|
|
435
|
+
this.startY
|
|
436
|
+
);
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
332
439
|
}
|
|
333
440
|
|
|
334
|
-
|
|
335
|
-
|
|
441
|
+
protected ensureControlPoint() {
|
|
442
|
+
if (this.lastControlX === undefined) throw "Invalid path command. S/s and T/t must follow either Q/q or C/c"
|
|
336
443
|
}
|
|
337
444
|
}
|
|
338
445
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
super();
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
apply(target: Sprite, nodeTime: number, interval: number) {
|
|
345
|
-
const x = Math.round(((this.p1.x - this.p0.x) / interval) * nodeTime) + this.p0.x;
|
|
346
|
-
const y = Math.round(((this.p1.y - this.p0.y) / interval) * nodeTime) + this.p0.y;
|
|
347
|
-
|
|
348
|
-
target.setPosition(x, y);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
getEndPoint(): Point {
|
|
352
|
-
return this.p1;
|
|
353
|
-
}
|
|
446
|
+
function moveTo(target: Sprite, nodeTime: number, interval: number, x: number, y: number) {
|
|
447
|
+
if (nodeTime >= interval) target.setPosition(x, y);
|
|
354
448
|
}
|
|
355
449
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
apply(target: Sprite, nodeTime: number, interval: number) {
|
|
362
|
-
const progress = nodeTime / interval;
|
|
363
|
-
const diff = 1 - progress;
|
|
364
|
-
const a = Math.pow(diff, 2);
|
|
365
|
-
const b = 2 * diff * progress;
|
|
366
|
-
const c = Math.pow(progress, 2);
|
|
367
|
-
|
|
368
|
-
const x = Math.round(a * this.p0.x + b * this.p1.x + c * this.p2.x);
|
|
369
|
-
const y = Math.round(a * this.p0.y + b * this.p1.y + c * this.p2.y);
|
|
370
|
-
|
|
371
|
-
target.setPosition(x, y);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
getLastControlPoint(): Point {
|
|
375
|
-
return this.p1;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
getEndPoint(): Point {
|
|
379
|
-
return this.p2;
|
|
380
|
-
}
|
|
450
|
+
function lineTo(target: Sprite, nodeTime: number, interval: number, x0: number, y0: number, x1: number, y1: number) {
|
|
451
|
+
target.setPosition(
|
|
452
|
+
Math.round(((x1 - x0) / interval) * nodeTime) + x0,
|
|
453
|
+
Math.round(((y1 - y0) / interval) * nodeTime) + y0
|
|
454
|
+
);
|
|
381
455
|
}
|
|
382
456
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const x = Math.round(a * this.p0.x + b * this.p1.x + c * this.p2.x + d * this.p3.x);
|
|
397
|
-
const y = Math.round(a * this.p0.y + b * this.p1.y + c * this.p2.y + d * this.p3.y);
|
|
398
|
-
|
|
399
|
-
target.setPosition(x, y);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
getLastControlPoint(): Point {
|
|
403
|
-
return this.p2;
|
|
404
|
-
}
|
|
457
|
+
function quadraticCurveTo(target: Sprite, nodeTime: number, interval: number, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number) {
|
|
458
|
+
const progress = nodeTime / interval;
|
|
459
|
+
const diff = 1 - progress;
|
|
460
|
+
const a = diff * diff;
|
|
461
|
+
const b = 2 * diff * progress;
|
|
462
|
+
const c = progress * progress;
|
|
463
|
+
|
|
464
|
+
target.setPosition(
|
|
465
|
+
Math.round(a * x0 + b * x1 + c * x2),
|
|
466
|
+
Math.round(a * y0 + b * y1 + c * y2)
|
|
467
|
+
);
|
|
468
|
+
}
|
|
405
469
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
470
|
+
function cubicCurveTo(target: Sprite, nodeTime: number, interval: number, x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) {
|
|
471
|
+
const progress = nodeTime / interval;
|
|
472
|
+
const diff = 1 - progress;
|
|
473
|
+
const a = diff * diff * diff;
|
|
474
|
+
const b = 3 * diff * diff * progress;
|
|
475
|
+
const c = 3 * diff * progress * progress;
|
|
476
|
+
const d = progress * progress * progress;
|
|
477
|
+
|
|
478
|
+
target.setPosition(
|
|
479
|
+
Math.round(a * x0 + b * x1 + c * x2 + d * x3),
|
|
480
|
+
Math.round(a * y0 + b * y1 + c * y2 + d * y3)
|
|
481
|
+
);
|
|
409
482
|
}
|
|
410
483
|
|
|
411
484
|
export abstract class SpriteAnimation {
|
|
412
|
-
protected
|
|
485
|
+
protected elapsedTime: number;
|
|
413
486
|
|
|
414
487
|
constructor(public sprite: Sprite, protected loop: boolean) {
|
|
488
|
+
this.elapsedTime = 0;
|
|
415
489
|
}
|
|
416
490
|
|
|
417
491
|
public init() {
|
|
@@ -457,10 +531,9 @@ namespace animation {
|
|
|
457
531
|
}
|
|
458
532
|
|
|
459
533
|
public update(): boolean {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const
|
|
463
|
-
const frameIndex = Math.floor(runningTime / this.frameInterval);
|
|
534
|
+
this.elapsedTime += game.eventContext().deltaTimeMillis;
|
|
535
|
+
|
|
536
|
+
const frameIndex = Math.floor(this.elapsedTime / this.frameInterval);
|
|
464
537
|
|
|
465
538
|
if (this.lastFrame != frameIndex && this.frames.length) {
|
|
466
539
|
if (!this.loop && frameIndex >= this.frames.length) {
|
|
@@ -477,19 +550,26 @@ namespace animation {
|
|
|
477
550
|
}
|
|
478
551
|
|
|
479
552
|
export class MovementAnimation extends SpriteAnimation {
|
|
553
|
+
protected startX: number;
|
|
554
|
+
protected startY: number;
|
|
555
|
+
|
|
480
556
|
constructor(sprite: Sprite, private path: Path, private nodeInterval: number, loop?: boolean) {
|
|
481
557
|
super(sprite, loop);
|
|
482
|
-
|
|
483
|
-
this.
|
|
558
|
+
this.startX = sprite.x;
|
|
559
|
+
this.startY = sprite.y;
|
|
560
|
+
this.elapsedTime = 0;
|
|
484
561
|
}
|
|
485
562
|
|
|
486
563
|
public update(): boolean {
|
|
487
|
-
|
|
564
|
+
this.elapsedTime += game.eventContext().deltaTimeMillis;
|
|
488
565
|
|
|
489
|
-
let result = this.path.run(this.nodeInterval, this.sprite, this.
|
|
566
|
+
let result = this.path.run(this.nodeInterval, this.sprite, this.elapsedTime);
|
|
490
567
|
if (result) {
|
|
491
568
|
if (!this.loop) return true;
|
|
492
|
-
this.
|
|
569
|
+
this.elapsedTime = 0;
|
|
570
|
+
this.path.reset();
|
|
571
|
+
this.sprite.x = this.startX;
|
|
572
|
+
this.sprite.y = this.startY;
|
|
493
573
|
}
|
|
494
574
|
return false;
|
|
495
575
|
}
|
|
@@ -524,7 +604,7 @@ namespace animation {
|
|
|
524
604
|
//% group="Animate"
|
|
525
605
|
//% help=animation/run-movement-animation
|
|
526
606
|
export function runMovementAnimation(sprite: Sprite, pathString: string, duration?: number, loop?: boolean) {
|
|
527
|
-
const path =
|
|
607
|
+
const path = new Path(pathString);
|
|
528
608
|
const anim = new MovementAnimation(sprite, path, duration / path.length, !!loop);
|
|
529
609
|
anim.init();
|
|
530
610
|
}
|