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
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
//% color="#207a77"
|
|
2
|
+
//% icon="\uf0c0"
|
|
3
|
+
//% block="Multiplayer"
|
|
4
|
+
namespace mp {
|
|
5
|
+
const MAX_PLAYERS = 4;
|
|
6
|
+
|
|
7
|
+
export enum PlayerNumber {
|
|
8
|
+
//% block="1"
|
|
9
|
+
One = 1,
|
|
10
|
+
//% block="2"
|
|
11
|
+
Two = 2,
|
|
12
|
+
//% block="3"
|
|
13
|
+
Three = 3,
|
|
14
|
+
//% block="4"
|
|
15
|
+
Four = 4
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export enum PlayerProperty {
|
|
19
|
+
//% block="index"
|
|
20
|
+
Index = 1,
|
|
21
|
+
//% block="number"
|
|
22
|
+
Number = 2
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export enum MultiplayerButton {
|
|
26
|
+
//% block="A"
|
|
27
|
+
A,
|
|
28
|
+
//% block="B"
|
|
29
|
+
B,
|
|
30
|
+
//% block="up"
|
|
31
|
+
Up,
|
|
32
|
+
//% block="right"
|
|
33
|
+
Right,
|
|
34
|
+
//% block="down"
|
|
35
|
+
Down,
|
|
36
|
+
//% block="left"
|
|
37
|
+
Left
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class ButtonHandler {
|
|
41
|
+
constructor(public button: MultiplayerButton, public event: ControllerButtonEvent, public handler: (player: Player) => void) {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class ControllerEventHandler {
|
|
46
|
+
constructor(public event: ControllerEvent, public handler: (player: Player) => void) {
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
class ScoreHandler {
|
|
51
|
+
constructor(public target: number, public handler: (player: Player) => void) {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A player in the game
|
|
57
|
+
*/
|
|
58
|
+
export class Player {
|
|
59
|
+
_sprite: Sprite;
|
|
60
|
+
_state: number[];
|
|
61
|
+
_index: number;
|
|
62
|
+
_data: any;
|
|
63
|
+
|
|
64
|
+
constructor(index: number) {
|
|
65
|
+
this._index = index;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get index(): number {
|
|
69
|
+
return this._index;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get number(): number {
|
|
73
|
+
return this._index + 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get data(): any {
|
|
77
|
+
if (!this._data) this._data = {};
|
|
78
|
+
return this._data;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
set data(value: any) {
|
|
82
|
+
this._data = value;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
getProperty(prop: PlayerProperty): number {
|
|
86
|
+
switch (prop) {
|
|
87
|
+
case PlayerProperty.Index: return this.index;
|
|
88
|
+
case PlayerProperty.Number: return this.number;
|
|
89
|
+
default: return 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getSprite(): Sprite {
|
|
94
|
+
return this._sprite;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
setSprite(sprite: Sprite) {
|
|
98
|
+
if (sprite && sprite.image) {
|
|
99
|
+
// Passing 'implicit' flag so we don't override icons that
|
|
100
|
+
// user has explicitly defined.
|
|
101
|
+
multiplayer.postPresenceIcon(
|
|
102
|
+
this.number,
|
|
103
|
+
sprite.image,
|
|
104
|
+
/** implicit **/ true
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
// Passing 'implicit' flag so we don't override icons that
|
|
108
|
+
// user has explicitly defined.
|
|
109
|
+
multiplayer.postPresenceIcon(
|
|
110
|
+
this.number,
|
|
111
|
+
undefined,
|
|
112
|
+
/** implicit **/ true
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
this._sprite = sprite;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
moveWithButtons(vx?: number, vy?: number) {
|
|
120
|
+
this._getController().moveSprite(this.getSprite(), vx, vy);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getState(key: number): number {
|
|
124
|
+
if (key === MultiplayerState.score) {
|
|
125
|
+
return this._getInfo().score();
|
|
126
|
+
}
|
|
127
|
+
if (key === MultiplayerState.life) {
|
|
128
|
+
return this._getInfo().life();
|
|
129
|
+
}
|
|
130
|
+
return this._getState(key);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
setState(key: number, val: number) {
|
|
134
|
+
if (key === MultiplayerState.score) {
|
|
135
|
+
this._getInfo().setScore(val);
|
|
136
|
+
}
|
|
137
|
+
if (key === MultiplayerState.life) {
|
|
138
|
+
this._getInfo().setLife(val);
|
|
139
|
+
}
|
|
140
|
+
this._setState(key, val);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
_setState(key: number, val: number) {
|
|
144
|
+
this._ensureState(key);
|
|
145
|
+
if (this._state.length > key)
|
|
146
|
+
this._state[key] = val;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
_getState(key: number): number {
|
|
150
|
+
this._ensureState(key);
|
|
151
|
+
return (this._state.length > key) ? this._state[key] : 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_ensureState(key: number) {
|
|
155
|
+
if (!this._state) this._state = [];
|
|
156
|
+
if (key < 0 || key > 255) return;
|
|
157
|
+
while (this._state.length < key) this._state.push(0);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_getInfo(): info.PlayerInfo {
|
|
161
|
+
switch (this._index) {
|
|
162
|
+
case 0: return info.player1;
|
|
163
|
+
case 1: return info.player2;
|
|
164
|
+
case 2: return info.player3;
|
|
165
|
+
case 3: return info.player4;
|
|
166
|
+
default: return undefined;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
_getController(): controller.Controller {
|
|
171
|
+
switch (this._index) {
|
|
172
|
+
case 0: return controller.player1 as any;
|
|
173
|
+
case 1: return controller.player2;
|
|
174
|
+
case 2: return controller.player3;
|
|
175
|
+
case 3: return controller.player4;
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
class MPState {
|
|
182
|
+
players: Player[];
|
|
183
|
+
buttonHandlers: ButtonHandler[];
|
|
184
|
+
controllerEventHandlers: ControllerEventHandler[];
|
|
185
|
+
scoreHandlers: ScoreHandler[];
|
|
186
|
+
lifeZeroHandler: (player: Player) => void;
|
|
187
|
+
indicatorsVisible: boolean;
|
|
188
|
+
indicatorRenderable: scene.Renderable;
|
|
189
|
+
|
|
190
|
+
constructor() {
|
|
191
|
+
this.players = [];
|
|
192
|
+
for (let i = 0; i < MAX_PLAYERS; ++i)
|
|
193
|
+
this.players.push(new Player(i));
|
|
194
|
+
this.buttonHandlers = [];
|
|
195
|
+
this.controllerEventHandlers = [];
|
|
196
|
+
this.scoreHandlers = [];
|
|
197
|
+
this.indicatorsVisible = false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
onButtonEvent(button: MultiplayerButton, event: ControllerButtonEvent, handler: (player: Player) => void) {
|
|
201
|
+
const existing = this.getButtonHandler(button, event);
|
|
202
|
+
|
|
203
|
+
if (existing) {
|
|
204
|
+
existing.handler = handler;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
this.buttonHandlers.push(new ButtonHandler(button, event, handler));
|
|
209
|
+
|
|
210
|
+
for (const player of this.players) {
|
|
211
|
+
getButton(player._getController(), button).onEvent(event, () => {
|
|
212
|
+
this.getButtonHandler(button, event).handler(player);
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
onControllerEvent(event: ControllerEvent, handler: (player: Player) => void) {
|
|
218
|
+
const existing = this.getControllerEventHandler(event);
|
|
219
|
+
|
|
220
|
+
if (existing) {
|
|
221
|
+
existing.handler = handler;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
this.controllerEventHandlers.push(new ControllerEventHandler(event, handler));
|
|
226
|
+
|
|
227
|
+
for (const player of this.players) {
|
|
228
|
+
player._getController().onEvent(event, () => {
|
|
229
|
+
this.getControllerEventHandler(event).handler(player);
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
onReachedScore(score: number, handler: (player: Player) => void) {
|
|
235
|
+
const existing = this.getScoreHandler(score);
|
|
236
|
+
|
|
237
|
+
if (existing) {
|
|
238
|
+
existing.handler = handler;
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this.scoreHandlers.push(new ScoreHandler(score, handler));
|
|
243
|
+
|
|
244
|
+
for (const player of this.players) {
|
|
245
|
+
player._getInfo().onScore(score, () => {
|
|
246
|
+
this.getScoreHandler(score).handler(player);
|
|
247
|
+
})
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
onLifeZero(handler: (player: Player) => void) {
|
|
252
|
+
if (!this.lifeZeroHandler) {
|
|
253
|
+
for (const player of this.players) {
|
|
254
|
+
player._getInfo().onLifeZero(() => {
|
|
255
|
+
this.lifeZeroHandler(player);
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
this.lifeZeroHandler = handler;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
setPlayerIndicatorsVisible(visible: boolean) {
|
|
263
|
+
this.indicatorsVisible = visible;
|
|
264
|
+
|
|
265
|
+
if (visible && !this.indicatorRenderable) {
|
|
266
|
+
this.indicatorRenderable = scene.createRenderable(99, (target, camera) => {
|
|
267
|
+
if (this.indicatorsVisible) this.drawIndicators(target, camera);
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
getButtonHandler(button: MultiplayerButton, event: ControllerButtonEvent) {
|
|
273
|
+
for (const handler of this.buttonHandlers) {
|
|
274
|
+
if (handler.button === button && handler.event === event) return handler;
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
getControllerEventHandler(event: ControllerEvent) {
|
|
280
|
+
for (const handler of this.controllerEventHandlers) {
|
|
281
|
+
if (handler.event === event) return handler;
|
|
282
|
+
}
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
getScoreHandler(score: number) {
|
|
288
|
+
for (const handler of this.scoreHandlers) {
|
|
289
|
+
if (handler.target === score) return handler;
|
|
290
|
+
}
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
drawIndicators(target: Image, camera: scene.Camera) {
|
|
295
|
+
for (const player of this.players) {
|
|
296
|
+
const sprite = player.getSprite();
|
|
297
|
+
|
|
298
|
+
if (!sprite || sprite.flags & (sprites.Flag.Destroyed | sprites.Flag.Invisible)) {
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
let top = Fx.toInt(sprite._hitbox.top)
|
|
303
|
+
let bottom = Fx.toInt(sprite._hitbox.bottom)
|
|
304
|
+
let left = Fx.toInt(sprite._hitbox.left)
|
|
305
|
+
let right = Fx.toInt(sprite._hitbox.right)
|
|
306
|
+
|
|
307
|
+
if (!(sprite.flags & sprites.Flag.RelativeToCamera)) {
|
|
308
|
+
top -= camera.drawOffsetY;
|
|
309
|
+
bottom -= camera.drawOffsetY;
|
|
310
|
+
left -= camera.drawOffsetX;
|
|
311
|
+
right -= camera.drawOffsetX;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (left < 0) {
|
|
315
|
+
const indicator = _indicatorForPlayer(player.number, CollisionDirection.Right);
|
|
316
|
+
target.drawTransparentImage(
|
|
317
|
+
indicator,
|
|
318
|
+
Math.max(right + 2, 0),
|
|
319
|
+
Math.min(
|
|
320
|
+
Math.max(
|
|
321
|
+
(top + ((bottom - top) >> 1) - (indicator.height >> 1)),
|
|
322
|
+
0
|
|
323
|
+
),
|
|
324
|
+
screen.height - indicator.height
|
|
325
|
+
)
|
|
326
|
+
)
|
|
327
|
+
}
|
|
328
|
+
else if (right > 160) {
|
|
329
|
+
const indicator = _indicatorForPlayer(player.number, CollisionDirection.Left);
|
|
330
|
+
target.drawTransparentImage(
|
|
331
|
+
indicator,
|
|
332
|
+
Math.min(left - indicator.width - 2, screen.width - indicator.width),
|
|
333
|
+
Math.min(
|
|
334
|
+
Math.max(
|
|
335
|
+
(top + ((bottom - top) >> 1) - (indicator.height >> 1)),
|
|
336
|
+
0
|
|
337
|
+
),
|
|
338
|
+
screen.height - indicator.height
|
|
339
|
+
)
|
|
340
|
+
)
|
|
341
|
+
}
|
|
342
|
+
else if (top < 18) {
|
|
343
|
+
const indicator = _indicatorForPlayer(player.number, CollisionDirection.Bottom);
|
|
344
|
+
target.drawTransparentImage(
|
|
345
|
+
indicator,
|
|
346
|
+
(left + ((right - left) >> 1) - (indicator.width >> 1)),
|
|
347
|
+
Math.max(bottom + 2, 0)
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
const indicator = _indicatorForPlayer(player.number, CollisionDirection.Top);
|
|
352
|
+
target.drawTransparentImage(
|
|
353
|
+
indicator,
|
|
354
|
+
(left + ((right - left) >> 1) - (indicator.width >> 1)),
|
|
355
|
+
Math.min(top - indicator.height - 2, screen.height - indicator.height)
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
let stateStack: MPState[];
|
|
363
|
+
|
|
364
|
+
function init() {
|
|
365
|
+
if (stateStack) return;
|
|
366
|
+
stateStack = [new MPState()];
|
|
367
|
+
game.addScenePushHandler(() => {
|
|
368
|
+
stateStack.push(new MPState());
|
|
369
|
+
});
|
|
370
|
+
game.addScenePopHandler(() => {
|
|
371
|
+
stateStack.pop();
|
|
372
|
+
if (stateStack.length === 0) stateStack.push(new MPState());
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export function _mpstate() {
|
|
377
|
+
init();
|
|
378
|
+
return stateStack[stateStack.length - 1];
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function getButton(ctrl: controller.Controller, button: MultiplayerButton) {
|
|
382
|
+
switch (button) {
|
|
383
|
+
case MultiplayerButton.A: return ctrl.A;
|
|
384
|
+
case MultiplayerButton.B: return ctrl.B;
|
|
385
|
+
case MultiplayerButton.Up: return ctrl.up;
|
|
386
|
+
case MultiplayerButton.Right: return ctrl.right;
|
|
387
|
+
case MultiplayerButton.Down: return ctrl.down;
|
|
388
|
+
case MultiplayerButton.Left: return ctrl.left;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Gets the sprite of the player
|
|
394
|
+
* @param player The player to get the sprite of
|
|
395
|
+
* @returns The sprite of the player, or undefined if the player has no assigned sprite
|
|
396
|
+
*/
|
|
397
|
+
//% blockId=mp_getPlayerSprite
|
|
398
|
+
//% block="$player sprite"
|
|
399
|
+
//% player.shadow=mp_playerSelector
|
|
400
|
+
//% group=Sprites
|
|
401
|
+
//% weight=100
|
|
402
|
+
//% blockGap=8
|
|
403
|
+
//% help=multiplayer/get-player-sprite
|
|
404
|
+
//% parts="multiplayer"
|
|
405
|
+
export function getPlayerSprite(player: Player): Sprite {
|
|
406
|
+
return player.getSprite();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Sets the sprite of the player
|
|
411
|
+
* @param player The player to set the sprite for
|
|
412
|
+
* @param sprite The sprite to set
|
|
413
|
+
*/
|
|
414
|
+
//% blockId=mp_setPlayerSprite
|
|
415
|
+
//% block="set $player sprite to $sprite"
|
|
416
|
+
//% player.shadow=mp_playerSelector
|
|
417
|
+
//% sprite.shadow=spritescreate
|
|
418
|
+
//% group=Sprites
|
|
419
|
+
//% weight=100
|
|
420
|
+
//% blockGap=8
|
|
421
|
+
//% help=multiplayer/set-player-sprite
|
|
422
|
+
//% parts="multiplayer"
|
|
423
|
+
export function setPlayerSprite(player: Player, sprite: Sprite) {
|
|
424
|
+
player.setSprite(sprite);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Control a player's sprite with directional buttons
|
|
429
|
+
* @param player The player to control
|
|
430
|
+
* @param vx The horizontal velocity of the sprite (optional)
|
|
431
|
+
* @param vy The vertical velocity of the sprite (optional)
|
|
432
|
+
*/
|
|
433
|
+
//% blockId=mp_moveWithButtons
|
|
434
|
+
//% block="move $player with buttons||vx $vx vy $vy"
|
|
435
|
+
//% player.shadow=mp_playerSelector
|
|
436
|
+
//% vx.defl=100
|
|
437
|
+
//% vy.defl=100
|
|
438
|
+
//% vx.shadow="spriteSpeedPicker"
|
|
439
|
+
//% vy.shadow="spriteSpeedPicker"
|
|
440
|
+
//% expandableArgumentMode="toggle"
|
|
441
|
+
//% inlineInputMode=inline
|
|
442
|
+
//% group=Controller
|
|
443
|
+
//% weight=100
|
|
444
|
+
//% blockGap=8
|
|
445
|
+
//% help=controller/move-sprite
|
|
446
|
+
//% parts="multiplayer"
|
|
447
|
+
export function moveWithButtons(player: Player, vx?: number, vy?: number) {
|
|
448
|
+
player.moveWithButtons(vx, vy);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Runs code when a button on any controller is pressed, released, or held
|
|
453
|
+
* @param button The button to listen for
|
|
454
|
+
* @param event The event to listen for (pressed, released, or held)
|
|
455
|
+
* @param handler The code to run when the button is pressed, released, or held
|
|
456
|
+
*/
|
|
457
|
+
//% blockId=mp_onButtonEvent
|
|
458
|
+
//% block="on $button button $event for $player"
|
|
459
|
+
//% draggableParameters=reporter
|
|
460
|
+
//% group=Controller
|
|
461
|
+
//% weight=90
|
|
462
|
+
//% blockGap=8
|
|
463
|
+
//% help=controller/on-button-event
|
|
464
|
+
//% parts="multiplayer"
|
|
465
|
+
export function onButtonEvent(button: MultiplayerButton, event: ControllerButtonEvent, handler: (player: Player) => void) {
|
|
466
|
+
_mpstate().onButtonEvent(button, event, handler);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Queries the state of a button on a controller
|
|
471
|
+
* @param player The player to query
|
|
472
|
+
* @param button The button to query
|
|
473
|
+
* @returns true if the button is pressed
|
|
474
|
+
*/
|
|
475
|
+
//% blockId=mp_isButtonPressed
|
|
476
|
+
//% block="is $player $button button pressed"
|
|
477
|
+
//% player.shadow=mp_playerSelector
|
|
478
|
+
//% group=Controller
|
|
479
|
+
//% weight=80
|
|
480
|
+
//% blockGap=8
|
|
481
|
+
//% help=controller/button/is-pressed
|
|
482
|
+
//% parts="multiplayer"
|
|
483
|
+
export function isButtonPressed(player: Player, button: MultiplayerButton): boolean {
|
|
484
|
+
return getButton(player._getController(), button).isPressed();
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Runs code when a controller is connected or disconnected
|
|
489
|
+
* @param event The event to listen for (controller connected or disconnected)
|
|
490
|
+
* @param handler Code to run when the event is raised
|
|
491
|
+
*/
|
|
492
|
+
//% blockId=mp_onControllerEvent
|
|
493
|
+
//% block="on $player $event"
|
|
494
|
+
//% draggableParameters=reporter
|
|
495
|
+
//% group=Controller
|
|
496
|
+
//% weight=70
|
|
497
|
+
//% blockGap=8
|
|
498
|
+
//% help=controller/on-event
|
|
499
|
+
//% parts="multiplayer"
|
|
500
|
+
export function onControllerEvent(event: ControllerEvent, handler: (player: Player) => void) {
|
|
501
|
+
_mpstate().onControllerEvent(event, handler);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Gets the value of the specified player state
|
|
506
|
+
* @param player The player to get the state for
|
|
507
|
+
* @param state The state to get
|
|
508
|
+
* @returns The value of the state
|
|
509
|
+
*/
|
|
510
|
+
//% blockId=mp_getPlayerState
|
|
511
|
+
//% block="$player $state"
|
|
512
|
+
//% player.shadow=mp_playerSelector
|
|
513
|
+
//% state.shadow=mp_multiplayerstate
|
|
514
|
+
//% group=Info
|
|
515
|
+
//% weight=100
|
|
516
|
+
//% blockGap=8
|
|
517
|
+
//% help=multiplayer/get-player-state
|
|
518
|
+
//% parts="multiplayer"
|
|
519
|
+
export function getPlayerState(player: Player, state: number): number {
|
|
520
|
+
return player.getState(state);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Sets the value of the specified player state
|
|
525
|
+
* @param player The player to set the state for
|
|
526
|
+
* @param state The state to set
|
|
527
|
+
* @param value The value to set the state to
|
|
528
|
+
*/
|
|
529
|
+
//% blockId=mp_setPlayerState
|
|
530
|
+
//% block="set $player $state to $value"
|
|
531
|
+
//% player.shadow=mp_playerSelector
|
|
532
|
+
//% state.shadow=mp_multiplayerstate
|
|
533
|
+
//% group=Info
|
|
534
|
+
//% weight=90
|
|
535
|
+
//% blockGap=8
|
|
536
|
+
//% help=multiplayer/set-player-state
|
|
537
|
+
//% parts="multiplayer"
|
|
538
|
+
export function setPlayerState(player: Player, state: number, value: number) {
|
|
539
|
+
player.setState(state, value);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Changes the value of the specified player state
|
|
544
|
+
* @param player The player to change the state for
|
|
545
|
+
* @param state The state to change
|
|
546
|
+
* @param delta The amount to change the state by
|
|
547
|
+
*/
|
|
548
|
+
//% blockId=mp_changePlayerStateBy
|
|
549
|
+
//% block="change $player $state by $delta"
|
|
550
|
+
//% player.shadow=mp_playerSelector
|
|
551
|
+
//% state.shadow=mp_multiplayerstate
|
|
552
|
+
//% delta.defl=1
|
|
553
|
+
//% group=Info
|
|
554
|
+
//% weight=80
|
|
555
|
+
//% blockGap=8
|
|
556
|
+
//% help=multiplayer/change-player-state-by
|
|
557
|
+
//% parts="multiplayer"
|
|
558
|
+
export function changePlayerStateBy(player: Player, state: number, delta: number) {
|
|
559
|
+
player.setState(state, player.getState(state) + delta);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Gets a property of the player
|
|
564
|
+
* @param player The player to get the property of
|
|
565
|
+
* @param prop The property to get
|
|
566
|
+
* @returns The value of the property
|
|
567
|
+
*/
|
|
568
|
+
//% blockId=mp_getPlayerProperty
|
|
569
|
+
//% block="$player $prop"
|
|
570
|
+
//% player.shadow=mp_playerSelector
|
|
571
|
+
//% group=Info
|
|
572
|
+
//% weight=100
|
|
573
|
+
//% blockGap=8
|
|
574
|
+
//% help=multiplayer/get-player-property
|
|
575
|
+
//% parts="multiplayer"
|
|
576
|
+
export function getPlayerProperty(player: Player, prop: PlayerProperty): number {
|
|
577
|
+
return player.getProperty(prop);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Runs code once each time a player's score reaches a given value.
|
|
582
|
+
* @param score The score to check for, eg: 100
|
|
583
|
+
* @param handler The code to run when the score is reached
|
|
584
|
+
*/
|
|
585
|
+
//% blockId=mp_onScore
|
|
586
|
+
//% block="on score $score for $player"
|
|
587
|
+
//% score.defl=100
|
|
588
|
+
//% draggableParameters=reporter
|
|
589
|
+
//% group=Info
|
|
590
|
+
//% weight=70
|
|
591
|
+
//% blockGap=8
|
|
592
|
+
//% help=info/on-score
|
|
593
|
+
//% parts="multiplayer"
|
|
594
|
+
export function onScore(score: number, handler: (player: Player) => void) {
|
|
595
|
+
_mpstate().onReachedScore(score, handler);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Runs code when a player's number of lives reaches zero
|
|
600
|
+
* @param handler The code to run when the lives reach zero
|
|
601
|
+
*/
|
|
602
|
+
//% blockId=mp_onLifeZero
|
|
603
|
+
//% block="on life zero for $player"
|
|
604
|
+
//% draggableParameters=reporter
|
|
605
|
+
//% group=Info
|
|
606
|
+
//% weight=60
|
|
607
|
+
//% blockGap=8
|
|
608
|
+
//% help=info/on-life-zero
|
|
609
|
+
//% parts="multiplayer"
|
|
610
|
+
export function onLifeZero(handler: (player: Player) => void) {
|
|
611
|
+
_mpstate().onLifeZero(handler);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Gets the player by number
|
|
616
|
+
* @param number The one-based number of the player
|
|
617
|
+
* @returns Player, or undefined if not found
|
|
618
|
+
*/
|
|
619
|
+
//% blockId=mp_getPlayerByNumber
|
|
620
|
+
//% block="player $number"
|
|
621
|
+
//% number.shadow=variables_get
|
|
622
|
+
//% number.defl=number
|
|
623
|
+
//% group=Utility
|
|
624
|
+
//% weight=80
|
|
625
|
+
//% blockGap=8
|
|
626
|
+
//% help=multiplayer/get-player-by-number
|
|
627
|
+
//% parts="multiplayer"
|
|
628
|
+
export function getPlayerByNumber(number: number): Player {
|
|
629
|
+
const index = number - 1;
|
|
630
|
+
return getPlayerByIndex(index);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Gets the player by index
|
|
635
|
+
* @param index The zero-based index of the player
|
|
636
|
+
* @returns Player, or undefined if not found
|
|
637
|
+
*/
|
|
638
|
+
//% blockId=mp_getPlayerByIndex
|
|
639
|
+
//% block="player at $index"
|
|
640
|
+
//% index.shadow=variables_get
|
|
641
|
+
//% index.defl=index
|
|
642
|
+
//% group=Utility
|
|
643
|
+
//% weight=80
|
|
644
|
+
//% blockGap=8
|
|
645
|
+
//% help=multiplayer/get-player-by-index
|
|
646
|
+
//% parts="multiplayer"
|
|
647
|
+
export function getPlayerByIndex(index: number): Player {
|
|
648
|
+
if (index < 0 || index >= MAX_PLAYERS) return undefined;
|
|
649
|
+
return _mpstate().players[index];
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Selects one of the players by number
|
|
654
|
+
* @param number The player number
|
|
655
|
+
* @returns The player
|
|
656
|
+
*/
|
|
657
|
+
//% blockId=mp_playerSelector
|
|
658
|
+
//% block="player $number"
|
|
659
|
+
//% group=Utility
|
|
660
|
+
//% weight=80
|
|
661
|
+
//% blockGap=8
|
|
662
|
+
//% help=multiplayer/player-selector
|
|
663
|
+
//% parts="multiplayer"
|
|
664
|
+
export function playerSelector(number: PlayerNumber): Player {
|
|
665
|
+
const index = number - 1;
|
|
666
|
+
return getPlayerByIndex(index);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Gets the player the sprite is assigned to
|
|
671
|
+
* @param sprite the sprite
|
|
672
|
+
* @returns Player, or undefined if not found
|
|
673
|
+
*/
|
|
674
|
+
//% blockId=mp_getPlayerBySprite
|
|
675
|
+
//% block="$sprite player"
|
|
676
|
+
//% sprite.shadow=variables_get
|
|
677
|
+
//% sprite.defl=mySprite
|
|
678
|
+
//% group=Sprites
|
|
679
|
+
//% weight=90
|
|
680
|
+
//% blockGap=8
|
|
681
|
+
//% help=multiplayer/get-player-by-sprite
|
|
682
|
+
//% parts="multiplayer"
|
|
683
|
+
export function getPlayerBySprite(sprite: Sprite): Player {
|
|
684
|
+
for (const player of _mpstate().players) {
|
|
685
|
+
if (player.getSprite() === sprite) return player;
|
|
686
|
+
}
|
|
687
|
+
return undefined;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Turns player indicators on or off
|
|
692
|
+
* @param visible indicator visibility
|
|
693
|
+
*/
|
|
694
|
+
//% blockId=mp_setPlayerIndicatorsVisible
|
|
695
|
+
//% block="set player indicators $visible"
|
|
696
|
+
//% visible.shadow=toggleOnOff
|
|
697
|
+
//% visible.defl=true
|
|
698
|
+
//% group=Utility
|
|
699
|
+
//% weight=100
|
|
700
|
+
//% blockGap=8
|
|
701
|
+
//% help=multiplayer/set-player-indicators-visible
|
|
702
|
+
//% parts="multiplayer"
|
|
703
|
+
export function setPlayerIndicatorsVisible(visible: boolean) {
|
|
704
|
+
_mpstate().setPlayerIndicatorsVisible(visible);
|
|
705
|
+
}
|
|
706
|
+
}
|