pxt-common-packages 10.3.2 → 10.3.4
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 +2 -2
- 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 +7736 -7608
- package/libs/controller---none/built/debug/binary.js +7715 -7587
- package/libs/datalogger/built/debug/binary.js +63 -63
- package/libs/edge-connector/built/debug/binary.js +9 -9
- package/libs/esp32/built/debug/binary.js +462 -462
- package/libs/game/built/debug/binary.js +7628 -7500
- package/libs/game/camera.ts +18 -13
- package/libs/game/physics.ts +2 -1
- package/libs/game/scenes.ts +3 -0
- 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/multiplayer/README.md +4 -0
- package/libs/multiplayer/docs/.gitkeep +0 -0
- package/libs/multiplayer/fieldEditors.ts +23 -0
- package/libs/multiplayer/images.ts +303 -0
- package/libs/multiplayer/mp.ts +625 -0
- package/libs/multiplayer/pxt.json +19 -0
- package/libs/multiplayer/stateKind.ts +14 -0
- package/libs/multiplayer/targetoverrides.ts +1 -0
- package/libs/multiplayer/test.ts +0 -0
- package/libs/net/built/debug/binary.js +176 -176
- package/libs/net-game/built/debug/binary.js +9540 -9412
- package/libs/palette/built/debug/binary.js +7627 -7499
- 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 +7627 -7499
- package/libs/storyboard/built/debug/binary.js +7627 -7499
- package/package.json +1 -1
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
namespace sprites.multiplayer {
|
|
2
|
+
//% blockId=mp_setPlayerSprite
|
|
3
|
+
//% block="set $player sprite to $sprite=variables_get(mySprite)"
|
|
4
|
+
//% player.shadow=mp_playernumber
|
|
5
|
+
//% weight=75
|
|
6
|
+
//% blockGap=8
|
|
7
|
+
//% group="Multiplayer"
|
|
8
|
+
//% parts="multiplayer"
|
|
9
|
+
export function setPlayerSprite(player: number, sprite: Sprite) {
|
|
10
|
+
mp._state().setPlayerSprite(player, sprite);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//% blockId=mp_getPlayerSprite
|
|
14
|
+
//% block="$player sprite"
|
|
15
|
+
//% player.shadow=mp_playernumber
|
|
16
|
+
//% weight=70
|
|
17
|
+
//% blockGap=8
|
|
18
|
+
//% group="Multiplayer"
|
|
19
|
+
//% parts="multiplayer"
|
|
20
|
+
export function getPlayerSprite(player: number): Sprite {
|
|
21
|
+
return mp._state().getPlayerSprite(player);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//% blockId=mp_isPlayerSprite
|
|
25
|
+
//% block="is $sprite $player sprite"
|
|
26
|
+
//% sprite.shadow=variables_get
|
|
27
|
+
//% sprite.defl=mySprite
|
|
28
|
+
//% player.shadow=mp_playernumber
|
|
29
|
+
//% weight=60
|
|
30
|
+
//% group="Multiplayer"
|
|
31
|
+
//% parts="multiplayer"
|
|
32
|
+
export function isPlayerSprite(sprite: Sprite, player: number): boolean {
|
|
33
|
+
return getPlayerSprite(player) === sprite;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
namespace controller.multiplayer {
|
|
38
|
+
//% blockId=mp_moveWithButtons
|
|
39
|
+
//% block="$player move $sprite with buttons||vx $vx vy $vy"
|
|
40
|
+
//% player.shadow=mp_playernumber
|
|
41
|
+
//% sprite.shadow=variables_get
|
|
42
|
+
//% sprite.defl=mySprite
|
|
43
|
+
//% vx.defl=100
|
|
44
|
+
//% vy.defl=100
|
|
45
|
+
//% vx.shadow="spriteSpeedPicker"
|
|
46
|
+
//% vy.shadow="spriteSpeedPicker"
|
|
47
|
+
//% expandableArgumentMode="toggle"
|
|
48
|
+
//% inlineInputMode=inline
|
|
49
|
+
//% group="Multiplayer"
|
|
50
|
+
//% parts="multiplayer"
|
|
51
|
+
//% weight=100
|
|
52
|
+
export function moveWithButtons(
|
|
53
|
+
player: number,
|
|
54
|
+
sprite: Sprite,
|
|
55
|
+
vx?: number,
|
|
56
|
+
vy?: number
|
|
57
|
+
) {
|
|
58
|
+
mp.getController(player).moveSprite(sprite, vx, vy);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//% blockId=mp_onButtonEvent
|
|
62
|
+
//% block="on $button button $event for $player"
|
|
63
|
+
//% draggableParameters=reporter
|
|
64
|
+
//% group="Multiplayer"
|
|
65
|
+
//% parts="multiplayer"
|
|
66
|
+
//% weight=90
|
|
67
|
+
export function onButtonEvent(
|
|
68
|
+
button: mp.MultiplayerButton,
|
|
69
|
+
event: ControllerButtonEvent,
|
|
70
|
+
handler: (player: number) => void
|
|
71
|
+
) {
|
|
72
|
+
mp._state().onButtonEvent(button, event, handler);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//% blockId=mp_isButtonPressed
|
|
76
|
+
//% block="is $player $button button pressed"
|
|
77
|
+
//% player.shadow=mp_playernumber
|
|
78
|
+
//% group="Multiplayer"
|
|
79
|
+
//% parts="multiplayer"
|
|
80
|
+
//% weight=80
|
|
81
|
+
//% blockGap=8
|
|
82
|
+
export function isButtonPressed(
|
|
83
|
+
player: number,
|
|
84
|
+
button: mp.MultiplayerButton
|
|
85
|
+
): boolean {
|
|
86
|
+
return mp.getButton(mp.getController(player), button).isPressed();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
namespace info.multiplayer {
|
|
91
|
+
//% blockId=mp_getPlayerState
|
|
92
|
+
//% block="$player $state"
|
|
93
|
+
//% player.shadow=mp_playernumber
|
|
94
|
+
//% state.shadow=mp_multiplayerstate
|
|
95
|
+
//% group="Multiplayer"
|
|
96
|
+
//% parts="multiplayer"
|
|
97
|
+
//% weight=100
|
|
98
|
+
//% blockGap=8
|
|
99
|
+
export function getPlayerState(player: number, state: number): number {
|
|
100
|
+
if (state === MultiplayerState.Score) {
|
|
101
|
+
return mp.getInfo(player).score();
|
|
102
|
+
} else if (state === MultiplayerState.Lives) {
|
|
103
|
+
return mp.getInfo(player).life();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return mp._state().getPlayerState(player, state);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
//% blockId=mp_setPlayerState
|
|
110
|
+
//% block="set $player $state to $value"
|
|
111
|
+
//% player.shadow=mp_playernumber
|
|
112
|
+
//% state.shadow=mp_multiplayerstate
|
|
113
|
+
//% group="Multiplayer"
|
|
114
|
+
//% parts="multiplayer"
|
|
115
|
+
//% weight=90
|
|
116
|
+
//% blockGap=8
|
|
117
|
+
export function setPlayerState(
|
|
118
|
+
player: number,
|
|
119
|
+
state: number,
|
|
120
|
+
value: number
|
|
121
|
+
) {
|
|
122
|
+
if (state === MultiplayerState.Score) {
|
|
123
|
+
return mp.getInfo(player).setScore(value);
|
|
124
|
+
} else if (state === MultiplayerState.Lives) {
|
|
125
|
+
return mp.getInfo(player).setLife(value);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
mp._state().setPlayerState(player, state, value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//% blockId=mp_changePlayerStateBy
|
|
132
|
+
//% block="change $player $state by $deltaValue"
|
|
133
|
+
//% player.shadow=mp_playernumber
|
|
134
|
+
//% state.shadow=mp_multiplayerstate
|
|
135
|
+
//% deltaValue.defl=1
|
|
136
|
+
//% group="Multiplayer"
|
|
137
|
+
//% parts="multiplayer"
|
|
138
|
+
//% weight=80
|
|
139
|
+
export function changePlayerStateBy(
|
|
140
|
+
player: number,
|
|
141
|
+
state: number,
|
|
142
|
+
deltaValue: number
|
|
143
|
+
) {
|
|
144
|
+
setPlayerState(
|
|
145
|
+
player,
|
|
146
|
+
state,
|
|
147
|
+
getPlayerState(player, state) + deltaValue
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//% blockId=mp_onScore
|
|
152
|
+
//% block="on score $score for $player"
|
|
153
|
+
//% score.defl=100
|
|
154
|
+
//% draggableParameters=reporter
|
|
155
|
+
//% group="Multiplayer"
|
|
156
|
+
//% parts="multiplayer"
|
|
157
|
+
//% weight=70
|
|
158
|
+
//% blockGap=8
|
|
159
|
+
export function onScore(score: number, handler: (player: number) => void) {
|
|
160
|
+
mp._state().onReachedScore(score, handler);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//% blockId=mp_onLifeZero
|
|
164
|
+
//% block="on life zero for $player"
|
|
165
|
+
//% draggableParameters=reporter
|
|
166
|
+
//% group="Multiplayer"
|
|
167
|
+
//% parts="multiplayer"
|
|
168
|
+
//% weight=60
|
|
169
|
+
export function onLifeZero(handler: (player: number) => void) {
|
|
170
|
+
mp._state().onLifeZero(handler);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//% icon="\uf0c0"
|
|
175
|
+
//% block="Multiplayer"
|
|
176
|
+
//% color="#207a77"
|
|
177
|
+
namespace mp {
|
|
178
|
+
export enum PlayerNumber {
|
|
179
|
+
//% block="1"
|
|
180
|
+
One = 1,
|
|
181
|
+
//% block="2"
|
|
182
|
+
Two = 2,
|
|
183
|
+
//% block="3"
|
|
184
|
+
Three = 3,
|
|
185
|
+
//% block="4"
|
|
186
|
+
Four = 4,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export enum MultiplayerButton {
|
|
190
|
+
//% block="A"
|
|
191
|
+
A,
|
|
192
|
+
//% block="B"
|
|
193
|
+
B,
|
|
194
|
+
//% block="up"
|
|
195
|
+
Up,
|
|
196
|
+
//% block="right"
|
|
197
|
+
Right,
|
|
198
|
+
//% block="down"
|
|
199
|
+
Down,
|
|
200
|
+
//% block="left"
|
|
201
|
+
Left,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
//% blockId=mp_setPlayerIndicatorsVisible
|
|
205
|
+
//% block="set player indicators $visible"
|
|
206
|
+
//% visible.shadow=toggleOnOff
|
|
207
|
+
//% visible.defl=true
|
|
208
|
+
//% group="Utility"
|
|
209
|
+
//% parts="multiplayer"
|
|
210
|
+
//% weight=100
|
|
211
|
+
export function setPlayerIndicatorsVisible(visible: boolean) {
|
|
212
|
+
mp._state().setPlayerIndicatorsVisible(visible);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
//% blockId=mp_isPlayer
|
|
216
|
+
//% block="$toCheck is $player"
|
|
217
|
+
//% toCheck.shadow=variables_get
|
|
218
|
+
//% toCheck.defl=player
|
|
219
|
+
//% player.shadow=mp_playernumber
|
|
220
|
+
//% group="Utility"
|
|
221
|
+
//% parts="multiplayer"
|
|
222
|
+
//% weight=90
|
|
223
|
+
export function isPlayer(toCheck: number, player: number): boolean {
|
|
224
|
+
return toCheck === player;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
//% blockId=mp_allPlayers
|
|
228
|
+
//% block="array of all players"
|
|
229
|
+
//% group="Utility"
|
|
230
|
+
//% parts="multiplayer"
|
|
231
|
+
//% weight=80
|
|
232
|
+
export function allPlayers(): number[] {
|
|
233
|
+
return [1, 2, 3, 4];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//% blockId=mp_indexToPlayer
|
|
237
|
+
//% block="$index to player number"
|
|
238
|
+
//% index.shadow=variables_get
|
|
239
|
+
//% index.defl=index
|
|
240
|
+
//% group="Utility"
|
|
241
|
+
//% parts="multiplayer"
|
|
242
|
+
//% weight=70
|
|
243
|
+
//% blockGap=8
|
|
244
|
+
export function indexToPlayer(index: number) {
|
|
245
|
+
if (index < 0 || index > 3) return -1;
|
|
246
|
+
return (index | 0) + 1;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
//% blockId=mp_playerToIndex
|
|
250
|
+
//% block="$player to index"
|
|
251
|
+
//% player.shadow=mp_playernumber
|
|
252
|
+
//% group="Utility"
|
|
253
|
+
//% parts="multiplayer"
|
|
254
|
+
//% weight=60
|
|
255
|
+
export function playerToIndex(player: number) {
|
|
256
|
+
if (player < 1 || player > 4) return -1;
|
|
257
|
+
return (player | 0) - 1;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function getController(player: number): controller.Controller {
|
|
261
|
+
switch (player) {
|
|
262
|
+
case 1:
|
|
263
|
+
return controller.player1 as any;
|
|
264
|
+
case 2:
|
|
265
|
+
return controller.player2;
|
|
266
|
+
case 3:
|
|
267
|
+
return controller.player3;
|
|
268
|
+
case 4:
|
|
269
|
+
return controller.player4;
|
|
270
|
+
}
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export function getInfo(player: number) {
|
|
275
|
+
switch (player) {
|
|
276
|
+
case 1:
|
|
277
|
+
return info.player1;
|
|
278
|
+
case 2:
|
|
279
|
+
return info.player2;
|
|
280
|
+
case 3:
|
|
281
|
+
return info.player3;
|
|
282
|
+
case 4:
|
|
283
|
+
return info.player4;
|
|
284
|
+
}
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function getButton(
|
|
289
|
+
ctrl: controller.Controller,
|
|
290
|
+
button: MultiplayerButton
|
|
291
|
+
) {
|
|
292
|
+
switch (button) {
|
|
293
|
+
case MultiplayerButton.A:
|
|
294
|
+
return ctrl.A;
|
|
295
|
+
case MultiplayerButton.B:
|
|
296
|
+
return ctrl.B;
|
|
297
|
+
case MultiplayerButton.Up:
|
|
298
|
+
return ctrl.up;
|
|
299
|
+
case MultiplayerButton.Right:
|
|
300
|
+
return ctrl.right;
|
|
301
|
+
case MultiplayerButton.Down:
|
|
302
|
+
return ctrl.down;
|
|
303
|
+
case MultiplayerButton.Left:
|
|
304
|
+
return ctrl.left;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let stateStack: MPState[];
|
|
309
|
+
|
|
310
|
+
class ButtonHandler {
|
|
311
|
+
constructor(
|
|
312
|
+
public button: mp.MultiplayerButton,
|
|
313
|
+
public event: ControllerButtonEvent,
|
|
314
|
+
public handler: (player: number) => void
|
|
315
|
+
) {}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
class ScoreHandler {
|
|
319
|
+
constructor(
|
|
320
|
+
public target: number,
|
|
321
|
+
public handler: (player: number) => void
|
|
322
|
+
) {}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
class PlayerStateEntry {
|
|
326
|
+
public player1: number;
|
|
327
|
+
public player2: number;
|
|
328
|
+
public player3: number;
|
|
329
|
+
public player4: number;
|
|
330
|
+
|
|
331
|
+
constructor() {
|
|
332
|
+
this.player1 = 0;
|
|
333
|
+
this.player2 = 0;
|
|
334
|
+
this.player3 = 0;
|
|
335
|
+
this.player4 = 0;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
getForPlayer(player: number) {
|
|
339
|
+
switch (player) {
|
|
340
|
+
case 1:
|
|
341
|
+
return this.player1;
|
|
342
|
+
case 2:
|
|
343
|
+
return this.player2;
|
|
344
|
+
case 3:
|
|
345
|
+
return this.player3;
|
|
346
|
+
case 4:
|
|
347
|
+
return this.player4;
|
|
348
|
+
}
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
setForPlayer(player: number, value: number) {
|
|
353
|
+
switch (player) {
|
|
354
|
+
case 1:
|
|
355
|
+
this.player1 = value;
|
|
356
|
+
break;
|
|
357
|
+
case 2:
|
|
358
|
+
this.player2 = value;
|
|
359
|
+
break;
|
|
360
|
+
case 3:
|
|
361
|
+
this.player3 = value;
|
|
362
|
+
break;
|
|
363
|
+
case 4:
|
|
364
|
+
this.player4 = value;
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
class MPState {
|
|
371
|
+
playerSprites: Sprite[];
|
|
372
|
+
buttonHandlers: ButtonHandler[];
|
|
373
|
+
scoreHandlers: ScoreHandler[];
|
|
374
|
+
playerState: PlayerStateEntry[];
|
|
375
|
+
lifeZeroHandler: (player: number) => void;
|
|
376
|
+
indicatorsVisible: boolean;
|
|
377
|
+
indicatorRenderable: scene.Renderable;
|
|
378
|
+
|
|
379
|
+
constructor() {
|
|
380
|
+
this.playerSprites = [];
|
|
381
|
+
this.buttonHandlers = [];
|
|
382
|
+
this.playerState = [];
|
|
383
|
+
this.scoreHandlers = [];
|
|
384
|
+
this.indicatorsVisible = false;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
onButtonEvent(
|
|
388
|
+
button: mp.MultiplayerButton,
|
|
389
|
+
event: ControllerButtonEvent,
|
|
390
|
+
handler: (playerNumber: number) => void
|
|
391
|
+
) {
|
|
392
|
+
const existing = this.getButtonHandler(button, event);
|
|
393
|
+
|
|
394
|
+
if (existing) {
|
|
395
|
+
existing.handler = handler;
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
this.buttonHandlers.push(new ButtonHandler(button, event, handler));
|
|
400
|
+
|
|
401
|
+
const registerHandler = (p: number) => {
|
|
402
|
+
mp.getButton(mp.getController(p), button).onEvent(event, () => {
|
|
403
|
+
this.getButtonHandler(button, event).handler(p);
|
|
404
|
+
});
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
for (let player = 1; player < 5; player++) {
|
|
408
|
+
registerHandler(player);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
onReachedScore(score: number, handler: (playerNumber: number) => void) {
|
|
413
|
+
const existing = this.getScoreHandler(score);
|
|
414
|
+
|
|
415
|
+
if (existing) {
|
|
416
|
+
existing.handler = handler;
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
this.scoreHandlers.push(new ScoreHandler(score, handler));
|
|
421
|
+
|
|
422
|
+
const registerHandler = (p: number) => {
|
|
423
|
+
mp.getInfo(p).onScore(score, () => {
|
|
424
|
+
this.getScoreHandler(score).handler(p);
|
|
425
|
+
});
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
for (let player = 1; player < 5; player++) {
|
|
429
|
+
registerHandler(player);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
onLifeZero(handler: (playerNumber: number) => void) {
|
|
434
|
+
if (!this.lifeZeroHandler) {
|
|
435
|
+
const registerHandler = (p: number) => {
|
|
436
|
+
mp.getInfo(p).onLifeZero(() => {
|
|
437
|
+
this.lifeZeroHandler(p);
|
|
438
|
+
});
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
for (let player = 1; player < 5; player++) {
|
|
442
|
+
registerHandler(player);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
this.lifeZeroHandler = handler;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
setPlayerSprite(player: number, sprite: Sprite) {
|
|
450
|
+
player |= 0;
|
|
451
|
+
if (player < 1 || player > 4) return;
|
|
452
|
+
|
|
453
|
+
while (this.playerSprites.length < player + 1) {
|
|
454
|
+
this.playerSprites.push(undefined);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
this.playerSprites[player] = sprite;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
getPlayerSprite(player: number) {
|
|
461
|
+
return this.playerSprites[player];
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
setPlayerState(player: number, state: number, value: number) {
|
|
465
|
+
this.getOrCreatePlayerStateEntry(state).setForPlayer(player, value);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
getPlayerState(player: number, state: number) {
|
|
469
|
+
return this.getOrCreatePlayerStateEntry(state).getForPlayer(player);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
setPlayerIndicatorsVisible(visible: boolean) {
|
|
473
|
+
this.indicatorsVisible = visible;
|
|
474
|
+
|
|
475
|
+
if (visible && !this.indicatorRenderable) {
|
|
476
|
+
this.indicatorRenderable = scene.createRenderable(
|
|
477
|
+
99,
|
|
478
|
+
(target, camera) => {
|
|
479
|
+
if (this.indicatorsVisible)
|
|
480
|
+
this.drawIndicators(target, camera);
|
|
481
|
+
}
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
protected getOrCreatePlayerStateEntry(state: number) {
|
|
487
|
+
if (!this.playerState[state]) {
|
|
488
|
+
while (this.playerState.length < state + 1) {
|
|
489
|
+
this.playerState.push(undefined);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
this.playerState[state] = new PlayerStateEntry();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return this.playerState[state];
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
protected getButtonHandler(
|
|
499
|
+
button: mp.MultiplayerButton,
|
|
500
|
+
event: ControllerButtonEvent
|
|
501
|
+
) {
|
|
502
|
+
for (const bHandler of this.buttonHandlers) {
|
|
503
|
+
if (bHandler.button === button && bHandler.event === event)
|
|
504
|
+
return bHandler;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return undefined;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
protected getScoreHandler(score: number) {
|
|
511
|
+
for (const sHandler of this.scoreHandlers) {
|
|
512
|
+
if (sHandler.target === score) return sHandler;
|
|
513
|
+
}
|
|
514
|
+
return undefined;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
protected drawIndicators(target: Image, camera: scene.Camera) {
|
|
518
|
+
for (let player = 1; player < 5; player++) {
|
|
519
|
+
const sprite = this.getPlayerSprite(player);
|
|
520
|
+
|
|
521
|
+
if (
|
|
522
|
+
!sprite ||
|
|
523
|
+
sprite.flags &
|
|
524
|
+
(sprites.Flag.Destroyed | sprites.Flag.Invisible)
|
|
525
|
+
) {
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
let top = Fx.toInt(sprite._hitbox.top);
|
|
530
|
+
let bottom = Fx.toInt(sprite._hitbox.bottom);
|
|
531
|
+
let left = Fx.toInt(sprite._hitbox.left);
|
|
532
|
+
let right = Fx.toInt(sprite._hitbox.right);
|
|
533
|
+
|
|
534
|
+
if (!(sprite.flags & sprites.Flag.RelativeToCamera)) {
|
|
535
|
+
top -= camera.drawOffsetY;
|
|
536
|
+
bottom -= camera.drawOffsetY;
|
|
537
|
+
left -= camera.drawOffsetX;
|
|
538
|
+
right -= camera.drawOffsetX;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (left < 0) {
|
|
542
|
+
const indicator = multiplayer._indicatorForPlayer(
|
|
543
|
+
player,
|
|
544
|
+
CollisionDirection.Right
|
|
545
|
+
);
|
|
546
|
+
target.drawTransparentImage(
|
|
547
|
+
indicator,
|
|
548
|
+
Math.max(right + 2, 0),
|
|
549
|
+
Math.min(
|
|
550
|
+
Math.max(
|
|
551
|
+
top +
|
|
552
|
+
((bottom - top) >> 1) -
|
|
553
|
+
(indicator.height >> 1),
|
|
554
|
+
0
|
|
555
|
+
),
|
|
556
|
+
screen.height - indicator.height
|
|
557
|
+
)
|
|
558
|
+
);
|
|
559
|
+
} else if (right > 160) {
|
|
560
|
+
const indicator = multiplayer._indicatorForPlayer(
|
|
561
|
+
player,
|
|
562
|
+
CollisionDirection.Left
|
|
563
|
+
);
|
|
564
|
+
target.drawTransparentImage(
|
|
565
|
+
indicator,
|
|
566
|
+
Math.min(
|
|
567
|
+
left - indicator.width - 2,
|
|
568
|
+
screen.width - indicator.width
|
|
569
|
+
),
|
|
570
|
+
Math.min(
|
|
571
|
+
Math.max(
|
|
572
|
+
top +
|
|
573
|
+
((bottom - top) >> 1) -
|
|
574
|
+
(indicator.height >> 1),
|
|
575
|
+
0
|
|
576
|
+
),
|
|
577
|
+
screen.height - indicator.height
|
|
578
|
+
)
|
|
579
|
+
);
|
|
580
|
+
} else if (top < 18) {
|
|
581
|
+
const indicator = multiplayer._indicatorForPlayer(
|
|
582
|
+
player,
|
|
583
|
+
CollisionDirection.Bottom
|
|
584
|
+
);
|
|
585
|
+
target.drawTransparentImage(
|
|
586
|
+
indicator,
|
|
587
|
+
left + ((right - left) >> 1) - (indicator.width >> 1),
|
|
588
|
+
Math.max(bottom + 2, 0)
|
|
589
|
+
);
|
|
590
|
+
} else {
|
|
591
|
+
const indicator = multiplayer._indicatorForPlayer(
|
|
592
|
+
player,
|
|
593
|
+
CollisionDirection.Top
|
|
594
|
+
);
|
|
595
|
+
target.drawTransparentImage(
|
|
596
|
+
indicator,
|
|
597
|
+
left + ((right - left) >> 1) - (indicator.width >> 1),
|
|
598
|
+
Math.min(
|
|
599
|
+
top - indicator.height - 2,
|
|
600
|
+
screen.height - indicator.height
|
|
601
|
+
)
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function init() {
|
|
609
|
+
if (stateStack) return;
|
|
610
|
+
stateStack = [new MPState()];
|
|
611
|
+
game.addScenePushHandler(() => {
|
|
612
|
+
stateStack.push(new MPState());
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
game.addScenePopHandler(() => {
|
|
616
|
+
stateStack.pop();
|
|
617
|
+
if (stateStack.length === 0) stateStack.push(new MPState());
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export function _state() {
|
|
622
|
+
init();
|
|
623
|
+
return stateStack[stateStack.length - 1];
|
|
624
|
+
}
|
|
625
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "multiplayer",
|
|
3
|
+
"description": "Additional blocks for building multiplayer games",
|
|
4
|
+
"files": [
|
|
5
|
+
"README.md",
|
|
6
|
+
"fieldEditors.ts",
|
|
7
|
+
"images.ts",
|
|
8
|
+
"mp.ts",
|
|
9
|
+
"stateKind.ts",
|
|
10
|
+
"targetoverrides.ts"
|
|
11
|
+
],
|
|
12
|
+
"testFiles": [
|
|
13
|
+
"test.ts"
|
|
14
|
+
],
|
|
15
|
+
"public": true,
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"game": "file:../game"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
namespace MultiplayerState {
|
|
2
|
+
let nextKind: number;
|
|
3
|
+
|
|
4
|
+
export function create() {
|
|
5
|
+
if (nextKind === undefined) nextKind = 0;
|
|
6
|
+
return nextKind++;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//% isKind
|
|
10
|
+
export const Score = create();
|
|
11
|
+
|
|
12
|
+
//% isKind
|
|
13
|
+
export const Lives = create();
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// TODO any platform specific overrides
|
|
File without changes
|