pxt-common-packages 9.4.4 → 9.4.8
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/built/common-sim.d.ts +3 -2
- package/built/common-sim.js +15 -1
- package/libs/azureiot/built/debug/binary.js +461 -461
- package/libs/color/built/debug/binary.js +8 -8
- package/libs/color/colors.ts +11 -0
- package/libs/color-sensor/built/debug/binary.js +8 -8
- package/libs/controller/built/debug/binary.js +9043 -7832
- package/libs/controller---none/built/debug/binary.js +9022 -7811
- 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/_locales/game-strings.json +21 -0
- package/libs/game/built/debug/binary.js +8935 -7724
- package/libs/game/hitbox.ts +40 -22
- package/libs/game/renderText.ts +74 -11
- package/libs/game/sprite.ts +244 -16
- package/libs/game/spritesay.ts +206 -53
- 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/mqtt/built/debug/binary.js +176 -176
- package/libs/net/built/debug/binary.js +176 -176
- package/libs/net/controller.ts +4 -0
- package/libs/net-game/built/debug/binary.js +10832 -9617
- package/libs/palette/built/debug/binary.js +8934 -7723
- 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 +9 -9
- 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/screen/image.cpp +14 -4
- package/libs/screen/image.ts +5 -4
- package/libs/screen/sim/image.ts +15 -3
- package/libs/servo/built/debug/binary.js +8 -8
- package/libs/sprite-scaling/README.md +3 -0
- package/libs/sprite-scaling/_locales/sprite-scaling-jsdoc-strings.json +1 -0
- package/libs/sprite-scaling/_locales/sprite-scaling-strings.json +9 -0
- package/libs/sprite-scaling/built/debug/binary.js +40047 -0
- package/libs/sprite-scaling/pxt.json +16 -0
- package/libs/sprite-scaling/scaling.ts +111 -0
- package/libs/sprite-scaling/targetoverrides.ts +1 -0
- package/libs/sprite-scaling/test.ts +0 -0
- package/libs/storyboard/built/debug/binary.js +8934 -7723
- package/libs/wifi---esp32/buildlogin.sh +1 -0
- package/libs/wifi---esp32/controller.ts +19 -1
- package/libs/wifi---esp32/enums.d.ts +2 -0
- package/libs/wifi---esp32/httpserver.cpp +166 -0
- package/libs/wifi---esp32/login.full.html +37 -0
- package/libs/wifi---esp32/login.html +1 -0
- package/libs/wifi---esp32/pxt.json +1 -0
- package/libs/wifi---esp32/shims.d.ts +4 -0
- package/libs/wifi---esp32/sim/wifisockets.ts +3 -0
- package/libs/wifi---esp32/wifi.cpp +13 -14
- package/libs/wifi---esp32/wifi.h +13 -1
- package/package.json +1 -1
package/libs/game/hitbox.ts
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
namespace game {
|
|
2
2
|
export class Hitbox {
|
|
3
|
-
|
|
4
|
-
rev: number;
|
|
3
|
+
hash: Fx8;
|
|
5
4
|
parent: Sprite;
|
|
6
5
|
ox: Fx8;
|
|
7
6
|
oy: Fx8;
|
|
8
7
|
width: Fx8;
|
|
9
8
|
height: Fx8;
|
|
10
9
|
|
|
11
|
-
constructor(parent: Sprite, width:
|
|
12
|
-
this.
|
|
13
|
-
this.rev = parent.image.revision();
|
|
10
|
+
constructor(parent: Sprite, width: Fx8, height: Fx8, ox: Fx8, oy: Fx8) {
|
|
11
|
+
this.hash = parent.calcDimensionalHash();
|
|
14
12
|
this.parent = parent;
|
|
15
|
-
this.width =
|
|
16
|
-
this.height =
|
|
17
|
-
this.ox =
|
|
18
|
-
this.oy =
|
|
13
|
+
this.width = width;
|
|
14
|
+
this.height = height;
|
|
15
|
+
this.ox = ox;
|
|
16
|
+
this.oy = oy;
|
|
19
17
|
}
|
|
20
18
|
|
|
21
19
|
get left() {
|
|
@@ -41,7 +39,23 @@ namespace game {
|
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
isValid() {
|
|
44
|
-
return this.
|
|
42
|
+
return this.hash === this.parent.calcDimensionalHash();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
contains(x: Fx8, y: Fx8): boolean {
|
|
46
|
+
return (x >= this.left) && (x <= this.right) && (y >= this.top) && (y <= this.bottom);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
overlapsWith(other: Hitbox): boolean {
|
|
50
|
+
if (this.contains(other.left, other.top)) return true;
|
|
51
|
+
if (this.contains(other.left, other.bottom)) return true;
|
|
52
|
+
if (this.contains(other.right, other.top)) return true;
|
|
53
|
+
if (this.contains(other.right, other.bottom)) return true;
|
|
54
|
+
if (other.contains(this.left, this.top)) return true;
|
|
55
|
+
if (other.contains(this.left, this.bottom)) return true;
|
|
56
|
+
if (other.contains(this.right, this.top)) return true;
|
|
57
|
+
if (other.contains(this.right, this.bottom)) return true;
|
|
58
|
+
return false;
|
|
45
59
|
}
|
|
46
60
|
}
|
|
47
61
|
|
|
@@ -51,24 +65,28 @@ namespace game {
|
|
|
51
65
|
return s._hitbox;
|
|
52
66
|
|
|
53
67
|
const i = s.image;
|
|
54
|
-
let minX = i.width;
|
|
55
|
-
let minY = i.height;
|
|
56
|
-
let maxX =
|
|
57
|
-
let maxY =
|
|
68
|
+
let minX = Fx8(i.width);
|
|
69
|
+
let minY = Fx8(i.height);
|
|
70
|
+
let maxX = Fx.zeroFx8;
|
|
71
|
+
let maxY = Fx.zeroFx8;
|
|
58
72
|
|
|
59
|
-
for (let c = 0; c < i.width; c
|
|
60
|
-
for (let r = 0; r < i.height; r
|
|
73
|
+
for (let c = 0, fxc = Fx.zeroFx8; c < i.width; c++, fxc = Fx.add(fxc, Fx.oneFx8)) {
|
|
74
|
+
for (let r = 0, fxr = Fx.zeroFx8; r < i.height; r++, fxr = Fx.add(fxr, Fx.oneFx8)) {
|
|
61
75
|
if (i.getPixel(c, r)) {
|
|
62
|
-
minX =
|
|
63
|
-
minY =
|
|
64
|
-
maxX =
|
|
65
|
-
maxY =
|
|
76
|
+
minX = Fx.min(minX, fxc);
|
|
77
|
+
minY = Fx.min(minY, fxr);
|
|
78
|
+
maxX = Fx.max(maxX, fxc);
|
|
79
|
+
maxY = Fx.max(maxY, fxr);
|
|
66
80
|
}
|
|
67
81
|
}
|
|
68
82
|
}
|
|
69
83
|
|
|
70
|
-
|
|
71
|
-
|
|
84
|
+
minX = Fx.mul(minX, s._sx);
|
|
85
|
+
minY = Fx.mul(minY, s._sy);
|
|
86
|
+
maxX = Fx.mul(maxX, s._sx);
|
|
87
|
+
maxY = Fx.mul(maxY, s._sy);
|
|
88
|
+
const width = Fx.add(Fx.sub(maxX, minX), Fx.oneFx8);
|
|
89
|
+
const height = Fx.add(Fx.sub(maxY, minY), Fx.oneFx8);
|
|
72
90
|
|
|
73
91
|
return new Hitbox(s, width, height, minX, minY);
|
|
74
92
|
}
|
package/libs/game/renderText.ts
CHANGED
|
@@ -61,6 +61,8 @@ namespace sprites {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
calculatePartialHeight(startLine: number, lengthToDraw: number) {
|
|
64
|
+
if (this.linebreaks.length === 0) return this.font.charHeight;
|
|
65
|
+
|
|
64
66
|
let current = 0;
|
|
65
67
|
|
|
66
68
|
for (let i = startLine; i < this.linebreaks.length + 1; i++) {
|
|
@@ -93,9 +95,9 @@ namespace sprites {
|
|
|
93
95
|
return total;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
|
|
97
|
-
const prevEnd =
|
|
98
|
-
let end =
|
|
98
|
+
lineEnd(lineIndex: number) {
|
|
99
|
+
const prevEnd = lineIndex > 0 ? this.linebreaks[lineIndex - 1] : 0;
|
|
100
|
+
let end = lineIndex < this.linebreaks.length ? this.linebreaks[lineIndex] : this.text.length;
|
|
99
101
|
let didMove = false;
|
|
100
102
|
|
|
101
103
|
// Trim trailing whitespace
|
|
@@ -115,8 +117,8 @@ namespace sprites {
|
|
|
115
117
|
return didMove ? end + 1 : end;
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
|
|
119
|
-
let start =
|
|
120
|
+
lineStart(lineIndex: number) {
|
|
121
|
+
let start = lineIndex > 0 ? this.linebreaks[lineIndex - 1] : 0;
|
|
120
122
|
|
|
121
123
|
// Trim leading whitespace
|
|
122
124
|
while (start < this.text.length) {
|
|
@@ -133,6 +135,29 @@ namespace sprites {
|
|
|
133
135
|
|
|
134
136
|
return start;
|
|
135
137
|
}
|
|
138
|
+
|
|
139
|
+
widthOfLine(lineIndex: number, fullTextOffset?: number) {
|
|
140
|
+
if (fullTextOffset != undefined) {
|
|
141
|
+
return (Math.min(this.lineEnd(lineIndex), fullTextOffset + 1) - this.lineStart(lineIndex)) * this.font.charWidth;
|
|
142
|
+
}
|
|
143
|
+
return (this.lineEnd(lineIndex) - this.lineStart(lineIndex)) * this.font.charWidth;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
widthOfLines(lineStartIndex: number, lineEndIndex: number, offset?: number) {
|
|
147
|
+
if (this.linebreaks.length === 0) return this.widthOfLine(0, offset);
|
|
148
|
+
|
|
149
|
+
let width = 0;
|
|
150
|
+
let fullTextOffset: number;
|
|
151
|
+
for (let i = lineStartIndex; i < Math.min(lineEndIndex, this.linebreaks.length + 1); i++) {
|
|
152
|
+
if (offset != undefined) {
|
|
153
|
+
fullTextOffset = this.lineStart(i) + offset;
|
|
154
|
+
offset -= this.lineEnd(i) - this.lineStart(i);
|
|
155
|
+
}
|
|
156
|
+
if (fullTextOffset !== undefined && this.lineStart(i) > fullTextOffset) break;
|
|
157
|
+
width = Math.max(width, this.widthOfLine(i, fullTextOffset));
|
|
158
|
+
}
|
|
159
|
+
return width;
|
|
160
|
+
}
|
|
136
161
|
}
|
|
137
162
|
|
|
138
163
|
|
|
@@ -203,6 +228,9 @@ namespace sprites {
|
|
|
203
228
|
protected pageLine: number;
|
|
204
229
|
protected timer: number;
|
|
205
230
|
protected pauseMillis: number;
|
|
231
|
+
protected onTickCB: () => void;
|
|
232
|
+
protected onEndCB: () => void;
|
|
233
|
+
protected prevOffset: number;
|
|
206
234
|
|
|
207
235
|
constructor(public text: RenderText, public height: number) {
|
|
208
236
|
this.state = RenderTextAnimationState.Idle;
|
|
@@ -232,17 +260,21 @@ namespace sprites {
|
|
|
232
260
|
}
|
|
233
261
|
|
|
234
262
|
currentHeight() {
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
263
|
+
const minHeight = this.text.lineHeight();
|
|
264
|
+
const maxHeight = Math.max(
|
|
265
|
+
Math.min(
|
|
266
|
+
Math.idiv(this.height, this.text.lineHeight()) + 1,
|
|
267
|
+
this.text.linebreaks.length + 1 - this.pageLine
|
|
268
|
+
) * this.text.lineHeight(),
|
|
269
|
+
minHeight
|
|
270
|
+
);
|
|
239
271
|
|
|
240
272
|
|
|
241
273
|
if (this.state === RenderTextAnimationState.Printing) {
|
|
242
|
-
return Math.min(
|
|
274
|
+
return Math.max(Math.min(
|
|
243
275
|
this.text.calculatePartialHeight(this.pageLine, this.currentOffset()),
|
|
244
276
|
maxHeight
|
|
245
|
-
)
|
|
277
|
+
), minHeight)
|
|
246
278
|
}
|
|
247
279
|
else if (this.state === RenderTextAnimationState.Pausing) {
|
|
248
280
|
return maxHeight
|
|
@@ -252,10 +284,34 @@ namespace sprites {
|
|
|
252
284
|
}
|
|
253
285
|
}
|
|
254
286
|
|
|
287
|
+
currentWidth() {
|
|
288
|
+
return this.text.widthOfLines(
|
|
289
|
+
this.pageLine,
|
|
290
|
+
this.pageLine + Math.idiv(this.currentHeight(), this.text.lineHeight()) + 1,
|
|
291
|
+
this.state === RenderTextAnimationState.Printing ? this.currentOffset() : undefined
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
255
295
|
currentOffset() {
|
|
256
296
|
return Math.idiv(control.millis() - this.timer, this.tickPeriod)
|
|
257
297
|
}
|
|
258
298
|
|
|
299
|
+
isDone() {
|
|
300
|
+
return this.state === RenderTextAnimationState.Idle;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
cancel() {
|
|
304
|
+
this.state = RenderTextAnimationState.Idle;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
onCharacterPrinted(cb: () => void) {
|
|
308
|
+
this.onTickCB = cb;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
onAnimationEnd(cb: () => void) {
|
|
312
|
+
this.onEndCB = cb;
|
|
313
|
+
}
|
|
314
|
+
|
|
259
315
|
draw(canvas: Image, left: number, top: number, color: number) {
|
|
260
316
|
if (this.state === RenderTextAnimationState.Idle) return;
|
|
261
317
|
else if (this.state === RenderTextAnimationState.Printing) {
|
|
@@ -269,6 +325,10 @@ namespace sprites {
|
|
|
269
325
|
this.pageLine + Math.idiv(this.height, this.text.lineHeight()) + 1
|
|
270
326
|
);
|
|
271
327
|
|
|
328
|
+
if (this.onTickCB && this.prevOffset !== this.currentOffset()) {
|
|
329
|
+
this.onTickCB();
|
|
330
|
+
}
|
|
331
|
+
|
|
272
332
|
if (pageFinished) {
|
|
273
333
|
this.state = RenderTextAnimationState.Pausing;
|
|
274
334
|
this.timer = this.pauseMillis
|
|
@@ -290,6 +350,7 @@ namespace sprites {
|
|
|
290
350
|
this.pageLine += Math.idiv(this.height, this.text.lineHeight()) + 1;
|
|
291
351
|
if (this.pageLine > this.text.linebreaks.length) {
|
|
292
352
|
this.state = RenderTextAnimationState.Idle;
|
|
353
|
+
if (this.onEndCB) this.onEndCB();
|
|
293
354
|
}
|
|
294
355
|
else {
|
|
295
356
|
this.state = RenderTextAnimationState.Printing;
|
|
@@ -297,6 +358,8 @@ namespace sprites {
|
|
|
297
358
|
}
|
|
298
359
|
}
|
|
299
360
|
}
|
|
361
|
+
|
|
362
|
+
this.prevOffset = this.currentOffset();
|
|
300
363
|
}
|
|
301
364
|
}
|
|
302
365
|
}
|
package/libs/game/sprite.ts
CHANGED
|
@@ -58,6 +58,36 @@ enum FlipOption {
|
|
|
58
58
|
FlipXY
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
enum ScaleDirection {
|
|
62
|
+
//% block="vertically"
|
|
63
|
+
Vertically = 0x01,
|
|
64
|
+
//% block="horizontally"
|
|
65
|
+
Horizontally = 0x02,
|
|
66
|
+
//% block="uniformly"
|
|
67
|
+
Uniformly = Vertically | Horizontally,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
enum ScaleAnchor {
|
|
71
|
+
//% block="middle"
|
|
72
|
+
Middle = 0,
|
|
73
|
+
//% block="top"
|
|
74
|
+
Top = 0x01,
|
|
75
|
+
//% block="left"
|
|
76
|
+
Left = 0x02,
|
|
77
|
+
//% block="right"
|
|
78
|
+
Right = 0x04,
|
|
79
|
+
//% block="bottom"
|
|
80
|
+
Bottom = 0x08,
|
|
81
|
+
//% block="top left"
|
|
82
|
+
TopLeft = Top | Left,
|
|
83
|
+
//% block="top right"
|
|
84
|
+
TopRight = Top | Right,
|
|
85
|
+
//% block="bottom left"
|
|
86
|
+
BottomLeft = Bottom | Left,
|
|
87
|
+
//% block="bottom right"
|
|
88
|
+
BottomRight = Bottom | Right,
|
|
89
|
+
}
|
|
90
|
+
|
|
61
91
|
/**
|
|
62
92
|
* A sprite on the screen
|
|
63
93
|
**/
|
|
@@ -71,27 +101,31 @@ class Sprite extends sprites.BaseSprite {
|
|
|
71
101
|
_ay: Fx8
|
|
72
102
|
_fx: Fx8 // friction
|
|
73
103
|
_fy: Fx8 // friction
|
|
104
|
+
_sx: Fx8 // scale
|
|
105
|
+
_sy: Fx8 // scale
|
|
106
|
+
_width: Fx8 // scaled width
|
|
107
|
+
_height: Fx8 // scaled height
|
|
74
108
|
|
|
75
109
|
//% group="Physics" blockSetVariable="mySprite"
|
|
76
110
|
//% blockCombine block="x" callInDebugger
|
|
77
111
|
get x(): number {
|
|
78
|
-
return Fx.toFloat(this._x
|
|
112
|
+
return Fx.toFloat(Fx.add(this._x, Fx.div(this._width, Fx.twoFx8)));
|
|
79
113
|
}
|
|
80
114
|
//% group="Physics" blockSetVariable="mySprite"
|
|
81
115
|
//% blockCombine block="x"
|
|
82
116
|
set x(v: number) {
|
|
83
|
-
this.left = v - (this.
|
|
117
|
+
this.left = v - (this.width / 2)
|
|
84
118
|
}
|
|
85
119
|
|
|
86
120
|
//% group="Physics" blockSetVariable="mySprite"
|
|
87
121
|
//% blockCombine block="y" callInDebugger
|
|
88
122
|
get y(): number {
|
|
89
|
-
return Fx.toFloat(this._y
|
|
123
|
+
return Fx.toFloat(Fx.add(this._y, Fx.div(this._height, Fx.twoFx8)));
|
|
90
124
|
}
|
|
91
125
|
//% group="Physics" blockSetVariable="mySprite"
|
|
92
126
|
//% blockCombine block="y"
|
|
93
127
|
set y(v: number) {
|
|
94
|
-
this.top = v - (this.
|
|
128
|
+
this.top = v - (this.height / 2)
|
|
95
129
|
}
|
|
96
130
|
|
|
97
131
|
//% group="Physics" blockSetVariable="mySprite"
|
|
@@ -158,6 +192,42 @@ class Sprite extends sprites.BaseSprite {
|
|
|
158
192
|
set fy(v: number) {
|
|
159
193
|
this._fy = Fx8(Math.max(0, v))
|
|
160
194
|
}
|
|
195
|
+
//% group="Physics" blockSetVariable="mySprite"
|
|
196
|
+
//% blockCombine block="sx (scale x)" callInDebugger
|
|
197
|
+
get sx(): number {
|
|
198
|
+
return Fx.toFloat(this._sx);
|
|
199
|
+
}
|
|
200
|
+
//% group="Physics" blockSetVariable="mySprite"
|
|
201
|
+
//% blockCombine block="sx (scale x)"
|
|
202
|
+
set sx(v: number) {
|
|
203
|
+
const x = this.x;
|
|
204
|
+
this._sx = Fx8(Math.max(0, v));
|
|
205
|
+
this.recalcSize();
|
|
206
|
+
this.left = x - this.width / 2;
|
|
207
|
+
}
|
|
208
|
+
//% group="Physics" blockSetVariable="mySprite"
|
|
209
|
+
//% blockCombine block="sy (scale y)" callInDebugger
|
|
210
|
+
get sy(): number {
|
|
211
|
+
return Fx.toFloat(this._sy);
|
|
212
|
+
}
|
|
213
|
+
//% group="Physics" blockSetVariable="mySprite"
|
|
214
|
+
//% blockCombine block="sy (scale y)"
|
|
215
|
+
set sy(v: number) {
|
|
216
|
+
const y = this.y;
|
|
217
|
+
this._sy = Fx8(Math.max(0, v));
|
|
218
|
+
this.recalcSize();
|
|
219
|
+
this.top = y - this.height / 2;
|
|
220
|
+
}
|
|
221
|
+
//% group="Physics" blockSetVariable="mySprite"
|
|
222
|
+
//% blockCombine block="scale" callInDebugger
|
|
223
|
+
get scale(): number {
|
|
224
|
+
return Math.max(this.sx, this.sy);
|
|
225
|
+
}
|
|
226
|
+
//% group="Physics" blockSetVariable="mySprite"
|
|
227
|
+
//% blockCombine block="scale"
|
|
228
|
+
set scale(v: number) {
|
|
229
|
+
this.sx = this.sy = v;
|
|
230
|
+
}
|
|
161
231
|
|
|
162
232
|
private _data: any;
|
|
163
233
|
/**
|
|
@@ -219,6 +289,8 @@ class Sprite extends sprites.BaseSprite {
|
|
|
219
289
|
this.ay = 0
|
|
220
290
|
this.fx = 0
|
|
221
291
|
this.fy = 0
|
|
292
|
+
this._sx = Fx.oneFx8;
|
|
293
|
+
this._sy = Fx.oneFx8;
|
|
222
294
|
this.flags = 0
|
|
223
295
|
this.setImage(img);
|
|
224
296
|
this.setKind(-1); // not a member of any type by default
|
|
@@ -229,7 +301,7 @@ class Sprite extends sprites.BaseSprite {
|
|
|
229
301
|
}
|
|
230
302
|
|
|
231
303
|
__serialize(offset: number): Buffer {
|
|
232
|
-
const buf = control.createBuffer(offset +
|
|
304
|
+
const buf = control.createBuffer(offset + 16);
|
|
233
305
|
let k = offset;
|
|
234
306
|
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._x)); k += 2;
|
|
235
307
|
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._y)); k += 2;
|
|
@@ -237,6 +309,8 @@ class Sprite extends sprites.BaseSprite {
|
|
|
237
309
|
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._vy)); k += 2;
|
|
238
310
|
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._ax)); k += 2;
|
|
239
311
|
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._ay)); k += 2;
|
|
312
|
+
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._sx)); k += 2;
|
|
313
|
+
buf.setNumber(NumberFormat.Int16LE, k, Fx.toInt(this._sy)); k += 2;
|
|
240
314
|
return buf;
|
|
241
315
|
}
|
|
242
316
|
|
|
@@ -257,8 +331,17 @@ class Sprite extends sprites.BaseSprite {
|
|
|
257
331
|
//% blockId=spritesetimage block="set %sprite(mySprite) image to %img=screen_image_picker"
|
|
258
332
|
//% weight=7 help=sprites/sprite/set-image
|
|
259
333
|
setImage(img: Image) {
|
|
260
|
-
if (!img
|
|
334
|
+
if (!img || img === this._image) return;
|
|
261
335
|
this._image = img;
|
|
336
|
+
this.recalcSize();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
calcDimensionalHash() {
|
|
340
|
+
return Fx.mul(Fx.mul(this._width, this._height), Fx8(this._image.revision()));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
resetHitbox() {
|
|
344
|
+
this._hitbox = null;
|
|
262
345
|
this.setHitbox();
|
|
263
346
|
}
|
|
264
347
|
|
|
@@ -311,19 +394,29 @@ class Sprite extends sprites.BaseSprite {
|
|
|
311
394
|
return !(this.flags & SpriteFlag.Invisible);
|
|
312
395
|
}
|
|
313
396
|
|
|
397
|
+
private recalcSize(): void {
|
|
398
|
+
this._width = Fx8(this._image.width * this.sx);
|
|
399
|
+
this._height = Fx8(this._image.height * this.sy);
|
|
400
|
+
this.resetHitbox();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private isScaled(): boolean {
|
|
404
|
+
return this._sx !== Fx.oneFx8 || this._sy !== Fx.oneFx8;
|
|
405
|
+
}
|
|
406
|
+
|
|
314
407
|
//% group="Physics" blockSetVariable="mySprite"
|
|
315
|
-
//% blockCombine block="width"
|
|
408
|
+
//% blockCombine block="width" callInDebugger
|
|
316
409
|
get width() {
|
|
317
|
-
return this.
|
|
410
|
+
return Fx.toInt(this._width);
|
|
318
411
|
}
|
|
319
412
|
//% group="Physics" blockSetVariable="mySprite"
|
|
320
|
-
//% blockCombine block="height"
|
|
413
|
+
//% blockCombine block="height" callInDebugger
|
|
321
414
|
get height() {
|
|
322
|
-
return this.
|
|
415
|
+
return Fx.toInt(this._height);
|
|
323
416
|
}
|
|
324
417
|
|
|
325
418
|
//% group="Physics" blockSetVariable="mySprite"
|
|
326
|
-
//% blockCombine block="left"
|
|
419
|
+
//% blockCombine block="left" callInDebugger
|
|
327
420
|
get left() {
|
|
328
421
|
return Fx.toFloat(this._x)
|
|
329
422
|
}
|
|
@@ -342,7 +435,7 @@ class Sprite extends sprites.BaseSprite {
|
|
|
342
435
|
}
|
|
343
436
|
|
|
344
437
|
//% group="Physics" blockSetVariable="mySprite"
|
|
345
|
-
//% blockCombine block="right"
|
|
438
|
+
//% blockCombine block="right" callInDebugger
|
|
346
439
|
get right() {
|
|
347
440
|
return this.left + this.width
|
|
348
441
|
}
|
|
@@ -353,7 +446,7 @@ class Sprite extends sprites.BaseSprite {
|
|
|
353
446
|
}
|
|
354
447
|
|
|
355
448
|
//% group="Physics" blockSetVariable="mySprite"
|
|
356
|
-
//% blockCombine block="top"
|
|
449
|
+
//% blockCombine block="top" callInDebugger
|
|
357
450
|
get top() {
|
|
358
451
|
return Fx.toFloat(this._y);
|
|
359
452
|
}
|
|
@@ -372,7 +465,7 @@ class Sprite extends sprites.BaseSprite {
|
|
|
372
465
|
}
|
|
373
466
|
|
|
374
467
|
//% group="Physics" blockSetVariable="mySprite"
|
|
375
|
-
//% blockCombine block="bottom"
|
|
468
|
+
//% blockCombine block="bottom" callInDebugger
|
|
376
469
|
get bottom() {
|
|
377
470
|
return this.top + this.height;
|
|
378
471
|
}
|
|
@@ -576,7 +669,19 @@ class Sprite extends sprites.BaseSprite {
|
|
|
576
669
|
const l = Math.floor(this.left - ox);
|
|
577
670
|
const t = Math.floor(this.top - oy);
|
|
578
671
|
|
|
579
|
-
|
|
672
|
+
if (!this.isScaled())
|
|
673
|
+
screen.drawTransparentImage(this._image, l, t);
|
|
674
|
+
else
|
|
675
|
+
screen.blit(
|
|
676
|
+
// dst rect in screen
|
|
677
|
+
l, t,
|
|
678
|
+
this.width,
|
|
679
|
+
this.height,
|
|
680
|
+
// src rect in sprite image
|
|
681
|
+
this._image,
|
|
682
|
+
0, 0,
|
|
683
|
+
this._image.width, this._image.height,
|
|
684
|
+
true, false);
|
|
580
685
|
|
|
581
686
|
if (this.flags & SpriteFlag.ShowPhysics) {
|
|
582
687
|
const font = image.font5;
|
|
@@ -697,7 +802,46 @@ class Sprite extends sprites.BaseSprite {
|
|
|
697
802
|
return false
|
|
698
803
|
if (other.flags & SPRITE_NO_SPRITE_OVERLAPS)
|
|
699
804
|
return false
|
|
700
|
-
|
|
805
|
+
if (!other._hitbox.overlapsWith(this._hitbox))
|
|
806
|
+
return false;
|
|
807
|
+
if (!this.isScaled() && !other.isScaled()) {
|
|
808
|
+
return other._image.overlapsWith(
|
|
809
|
+
this._image,
|
|
810
|
+
this.left - other.left,
|
|
811
|
+
this.top - other.top)
|
|
812
|
+
} else {
|
|
813
|
+
if (this.sx == 0 || this.sy == 0 || other.sx == 0 || other.sy == 0) return false;
|
|
814
|
+
|
|
815
|
+
let A: Sprite;
|
|
816
|
+
let B: Sprite;
|
|
817
|
+
|
|
818
|
+
// Render larger-scaled sprite onto smaller-scaled one so that we don't
|
|
819
|
+
// skip over source pixels in the check.
|
|
820
|
+
|
|
821
|
+
// A is the smaller-scaled sprite
|
|
822
|
+
if (this.sx * this.sy < other.sx * other.sy) {
|
|
823
|
+
A = this;
|
|
824
|
+
B = other;
|
|
825
|
+
} else {
|
|
826
|
+
A = other;
|
|
827
|
+
B = this;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// Render B onto A
|
|
831
|
+
return helpers.imageBlit(
|
|
832
|
+
A.image,
|
|
833
|
+
// Dst rect in A
|
|
834
|
+
(B.left - A.left) / A.sx,
|
|
835
|
+
(B.top - A.top) / A.sy,
|
|
836
|
+
B.width / A.sx,
|
|
837
|
+
B.height / A.sy,
|
|
838
|
+
B.image,
|
|
839
|
+
// Src rect in B
|
|
840
|
+
0, 0,
|
|
841
|
+
B.image.width,
|
|
842
|
+
B.image.height,
|
|
843
|
+
true, true);
|
|
844
|
+
}
|
|
701
845
|
}
|
|
702
846
|
|
|
703
847
|
/**
|
|
@@ -939,6 +1083,90 @@ class Sprite extends sprites.BaseSprite {
|
|
|
939
1083
|
}
|
|
940
1084
|
}
|
|
941
1085
|
|
|
1086
|
+
setScaleCore(sx?: number, sy?: number, anchor?: ScaleAnchor, proportional?: boolean): void {
|
|
1087
|
+
anchor = anchor || ScaleAnchor.Middle;
|
|
1088
|
+
|
|
1089
|
+
const hasSx = sx != null;
|
|
1090
|
+
const hasSy = sy != null;
|
|
1091
|
+
|
|
1092
|
+
const oldW = this.width;
|
|
1093
|
+
const oldH = this.height;
|
|
1094
|
+
|
|
1095
|
+
if (hasSx) {
|
|
1096
|
+
const oldSx = this.sx;
|
|
1097
|
+
this.sx = sx;
|
|
1098
|
+
if (!hasSy && proportional) {
|
|
1099
|
+
const ratio = sx / oldSx;
|
|
1100
|
+
this.sy *= ratio;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
if (hasSy) {
|
|
1104
|
+
const oldSy = this.sy;
|
|
1105
|
+
this.sy = sy;
|
|
1106
|
+
if (!hasSx && proportional) {
|
|
1107
|
+
const ratio = sy / oldSy;
|
|
1108
|
+
this.sx *= ratio;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
if (anchor & (ScaleAnchor.Left | ScaleAnchor.Right)) {
|
|
1113
|
+
const newW = this.width;
|
|
1114
|
+
const diff = newW - oldW;
|
|
1115
|
+
const diffOver2 = (diff / 2) | 0;
|
|
1116
|
+
if (anchor & ScaleAnchor.Left) { this.x += diffOver2; }
|
|
1117
|
+
if (anchor & ScaleAnchor.Right) { this.x -= diffOver2; }
|
|
1118
|
+
}
|
|
1119
|
+
if (anchor & (ScaleAnchor.Top | ScaleAnchor.Bottom)) {
|
|
1120
|
+
const newH = this.height;
|
|
1121
|
+
const diff = newH - oldH;
|
|
1122
|
+
const diffOver2 = (diff / 2) | 0;
|
|
1123
|
+
if (anchor & ScaleAnchor.Top) { this.y += diffOver2; }
|
|
1124
|
+
if (anchor & ScaleAnchor.Bottom) { this.y -= diffOver2; }
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
//% blockId=sprite_set_scale
|
|
1129
|
+
//% block="set %sprite(mySprite) scale to $value anchor $anchor"
|
|
1130
|
+
//% expandableArgumentMode=enabled
|
|
1131
|
+
//% inlineInputMode=inline
|
|
1132
|
+
//% value.defl=1
|
|
1133
|
+
//% anchor.defl=ScaleAnchor.Middle
|
|
1134
|
+
//% help=sprites/sprite/set-scale
|
|
1135
|
+
//% group="Scale" weight=90
|
|
1136
|
+
setScale(value: number, anchor?: ScaleAnchor): void {
|
|
1137
|
+
const direction = ScaleDirection.Uniformly;
|
|
1138
|
+
anchor = anchor || ScaleAnchor.Middle;
|
|
1139
|
+
|
|
1140
|
+
let sx: number;
|
|
1141
|
+
let sy: number;
|
|
1142
|
+
|
|
1143
|
+
if (direction & ScaleDirection.Horizontally) sx = value;
|
|
1144
|
+
if (direction & ScaleDirection.Vertically) sy = value;
|
|
1145
|
+
|
|
1146
|
+
this.setScaleCore(sx, sy, anchor);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
//% blockId=sprite_change_scale
|
|
1150
|
+
//% block="change %sprite(mySprite) scale by $value anchor $anchor"
|
|
1151
|
+
//% expandableArgumentMode=enabled
|
|
1152
|
+
//% inlineInputMode=inline
|
|
1153
|
+
//% value.defl=1
|
|
1154
|
+
//% anchor.defl=ScaleAnchor.Middle
|
|
1155
|
+
//% help=sprites/sprite/change-scale
|
|
1156
|
+
//% group="Scale" weight=90
|
|
1157
|
+
changeScale(value: number, anchor?: ScaleAnchor): void {
|
|
1158
|
+
const direction = ScaleDirection.Uniformly;
|
|
1159
|
+
anchor = anchor || ScaleAnchor.Middle;
|
|
1160
|
+
|
|
1161
|
+
let sx: number;
|
|
1162
|
+
let sy: number;
|
|
1163
|
+
|
|
1164
|
+
if (direction & ScaleDirection.Horizontally) sx = this.sx + value;
|
|
1165
|
+
if (direction & ScaleDirection.Vertically) sy = this.sy + value;
|
|
1166
|
+
|
|
1167
|
+
this.setScaleCore(sx, sy, anchor);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
942
1170
|
toString() {
|
|
943
1171
|
return `${this.id}(${this.x},${this.y})->(${this.vx},${this.vy})`;
|
|
944
1172
|
}
|