pxt-arcade 1.12.2 → 1.12.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/built/target.js +158 -146
- package/built/target.json +158 -146
- package/built/targetlight.json +5 -5
- package/built/theme.json +5 -0
- package/docs/SUMMARY.md +1 -0
- package/docs/hardware/adding.md +46 -52
- package/docs/hero-banner.md +8 -8
- package/docs/hour-of-code-2022-es.html +0 -1
- package/docs/hour-of-code-2022-pt.html +0 -1
- package/docs/hour-of-code-2022.html +12 -13
- package/docs/index-ref.json +1 -1
- package/docs/kiosk.html +1 -1
- package/docs/multiplayer.md +135 -0
- package/docs/projects/SUMMARY.md +3 -1
- package/docs/skillmap/balloon/balloon1.md +26 -312
- package/docs/skillmap/balloon/balloon2.md +18 -315
- package/docs/skillmap/balloon/balloon3.md +18 -317
- package/docs/skillmap/balloon/balloon4.md +105 -583
- package/docs/skillmap/balloon.md +14 -13
- package/docs/skillmap/mole/mole1.md +51 -326
- package/docs/skillmap/mole/mole2.md +43 -332
- package/docs/skillmap/mole/mole3.md +47 -316
- package/docs/{test/skillmap → skillmap}/mole/mole4.md +0 -0
- package/docs/skillmap/mole.md +14 -4
- package/docs/skillmap/turkey/turkey1.md +194 -127
- package/docs/skillmap/turkey/turkey2.md +144 -96
- package/docs/skillmap/turkey/turkey3.md +135 -84
- package/docs/skillmap/turkey.md +12 -10
- package/docs/skillmaps.md +24 -8
- package/docs/static/hero-gallery/holiday.png +0 -0
- package/docs/static/kiosk/asset-manifest.json +6 -6
- package/docs/static/kiosk/static/css/main.b60591be.css +2 -0
- package/docs/static/kiosk/static/css/main.b60591be.css.map +1 -0
- package/docs/static/kiosk/static/js/main.7c9f0b91.js +3 -0
- package/docs/static/kiosk/static/js/{main.01c7792a.js.LICENSE.txt → main.7c9f0b91.js.LICENSE.txt} +12 -32
- package/docs/static/kiosk/static/js/main.7c9f0b91.js.map +1 -0
- package/docs/static/multiplayer/help/emojis.png +0 -0
- package/docs/static/multiplayer/help/host-multiplayer.png +0 -0
- package/docs/static/multiplayer/help/hosted-game.png +0 -0
- package/docs/static/multiplayer/help/join-game.png +0 -0
- package/docs/static/multiplayer/help/joined-game.png +0 -0
- package/docs/static/multiplayer/help/share-button.png +0 -0
- package/docs/static/multiplayer/help/start-game.png +0 -0
- package/docs/static/skillmap/assets/dkc-logo-small.png +0 -0
- package/docs/static/tutorials/aliens/reload.png +0 -0
- package/docs/static/tutorials/arrows/2pbg.png +0 -0
- package/docs/static/tutorials/arrows/key.png +0 -0
- package/docs/static/tutorials/arrows/p1.png +0 -0
- package/docs/static/tutorials/arrows/p2.png +0 -0
- package/docs/static/tutorials/holiday/bgd.png +0 -0
- package/docs/static/tutorials/holiday/p1.png +0 -0
- package/docs/static/tutorials/holiday/p2.png +0 -0
- package/docs/static/tutorials/horse/finish.png +0 -0
- package/docs/static/tutorials/horse/frame.png +0 -0
- package/docs/static/tutorials/horse/p1.png +0 -0
- package/docs/static/tutorials/horse/p2.png +0 -0
- package/docs/test/courses/carnival.md +57 -0
- package/docs/test/courses/class-arcade.md +57 -0
- package/docs/test/skillmap/balloon.md +1 -1
- package/docs/test/skillmap/dino/{collectort1.md → dino1.md} +135 -79
- package/docs/test/skillmap/dino/{collectort2.md → dino2.md} +0 -0
- package/docs/test/skillmap/dino/{collectort3.md → dino3.md} +0 -0
- package/docs/test/skillmap/dino/{collectort4.md → dino4.md} +0 -0
- package/docs/test/skillmap/dino/{collectort5.md → dino5.md} +0 -0
- package/docs/test/skillmap/dino.md +82 -0
- package/docs/test/skillmap/mole.md +1 -1
- package/docs/test/skillmap/story/story1.md +8 -21
- package/docs/test/skillmap/story/story2.md +17 -28
- package/docs/test/skillmap/story/story3.md +51 -469
- package/docs/test/skillmap/story/story4.md +1 -2
- package/docs/test/skillmap/turkey.md +1 -0
- package/docs/test/tutorials/arrow.md +677 -0
- package/docs/test/tutorials/debug.md +180 -0
- package/docs/test/tutorials/holiday.md +609 -0
- package/docs/test/tutorials/horse.md +456 -0
- package/docs/test/tutorials/hundred.md +400 -0
- package/docs/test/tutorials/target.md +6 -2
- package/docs/test/tutorials/wakanda-forever.md +206 -147
- package/docs/tutorials/arrow.md +677 -0
- package/docs/tutorials/holiday.md +609 -0
- package/docs/tutorials/horse.md +456 -0
- package/docs/{test/tutorials/target/target_copy.md → tutorials/target.md} +11 -1085
- package/docs/tutorials/wakanda-forever.md +206 -147
- package/package.json +3 -3
- package/docs/skillmap/turkey/turkey0.md +0 -197
- package/docs/skillmap/turkey/turkey1a.md +0 -308
- package/docs/skillmap/turkey/turkey2a.md +0 -277
- package/docs/skillmap/turkey/turkey3a.md +0 -219
- package/docs/static/kiosk/static/css/main.927f4dad.css +0 -2
- package/docs/static/kiosk/static/css/main.927f4dad.css.map +0 -1
- package/docs/static/kiosk/static/js/main.01c7792a.js +0 -3
- package/docs/static/kiosk/static/js/main.01c7792a.js.map +0 -1
- package/docs/test/skillmap/balloon/balloon1.md +0 -247
- package/docs/test/skillmap/balloon/balloon2.md +0 -377
- package/docs/test/skillmap/balloon/balloon3.md +0 -389
- package/docs/test/skillmap/balloon/balloon4.md +0 -385
- package/docs/test/skillmap/mole/mole1.md +0 -382
- package/docs/test/skillmap/mole/mole2.md +0 -422
- package/docs/test/skillmap/mole/mole3.md +0 -384
- package/docs/test/skillmap/turkey/turkey1.md +0 -338
- package/docs/test/skillmap/turkey/turkey2.md +0 -318
- package/docs/test/skillmap/turkey/turkey3.md +0 -265
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
Special thanks to *Lucas_M* for creating the original Target Practice game!
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
## {2. Read Instructions}
|
|
@@ -15,86 +17,33 @@
|
|
|
15
17
|
|
|
16
18
|
This video will show you what to do.
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Feel free to pause or restart the video as often as you need!
|
|
21
|
+
|
|
22
|
+
Click "Pop out video" to resize the video window or move it around the screen.
|
|
19
23
|
|
|
20
|
-

|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
|
|
24
28
|
```package
|
|
25
29
|
simple-blocks=github:microsoft/arcade-tutorial-extensions/simple-blocks/
|
|
26
|
-
|
|
27
|
-
pxt-sprite-scaling=github:microsoft/pxt-common-packages/libs/sprite-scaling/
|
|
30
|
+
carnival=github:microsoft/arcade-carnival
|
|
28
31
|
```
|
|
29
32
|
|
|
30
33
|
|
|
31
|
-
```template
|
|
32
|
-
|
|
33
|
-
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
|
|
34
|
-
carnival.startTimer()
|
|
35
|
-
})
|
|
36
|
-
// game.onGameOverExpanded(winTypes.Multi)
|
|
37
|
-
controller.B.onEvent(ControllerButtonEvent.Pressed, function () {
|
|
38
|
-
info.player2.setScore(0)
|
|
39
|
-
info.player1.setScore(10)
|
|
40
|
-
// game.onGameOverExpanded(winTypes.Timed)
|
|
41
|
-
carnival.customGameOverExpanded("Spooky!", effects.confetti, music.magicWand, scoreTypes.HTime, 0)
|
|
42
|
-
})
|
|
43
|
-
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
|
|
44
|
-
throwBall = carnival.createProjectileBallFromSprite(assets.image`ball-blue`, myBall)
|
|
45
|
-
})
|
|
46
|
-
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Booth, function (sprite, otherSprite) {
|
|
47
|
-
info.changeScoreBy(-1)
|
|
48
|
-
sprite.destroy()
|
|
49
|
-
})
|
|
50
|
-
sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {
|
|
51
|
-
otherSprite.destroy()
|
|
52
|
-
sprite.destroy()
|
|
53
|
-
info.changeScoreBy(1)
|
|
54
|
-
music.baDing.play()
|
|
55
|
-
})
|
|
56
|
-
let theTarget: Sprite = null
|
|
57
|
-
let throwBall: Ball = null
|
|
58
|
-
let myBall: Ball = null
|
|
59
|
-
scene.setBackgroundImage(assets.image`wildWest`)
|
|
60
|
-
myBall = carnival.create(assets.image`ball-yellow`, SpriteKind.Player)
|
|
61
|
-
myBall.setPosition(80, 90)
|
|
62
|
-
let statusbar = statusbars.create(120, 6, StatusBarKind.Health)
|
|
63
|
-
statusbar.setColor(5, 10)
|
|
64
|
-
statusbar.setBarBorder(1, 1)
|
|
65
|
-
statusbar.setPosition(80, 113)
|
|
66
|
-
let myBooth = sprites.create(assets.image`booth`, SpriteKind.Booth)
|
|
67
|
-
carnival.startTimer()
|
|
68
|
-
myBall.controlBallWithArrowKeys(true)
|
|
69
|
-
myBall.setIter(10)
|
|
70
|
-
myBall.setTraceMulti(tracers.Cross)
|
|
71
|
-
myBall.variablePower(
|
|
72
|
-
statusbar,
|
|
73
|
-
30,
|
|
74
|
-
50,
|
|
75
|
-
100
|
|
76
|
-
)
|
|
77
|
-
forever(function () {
|
|
78
|
-
theTarget = sprites.createProjectileFromSide(assets.image`target`, 50, 0)
|
|
79
|
-
theTarget.bottom = 56
|
|
80
|
-
theTarget.setKind(SpriteKind.Enemy)
|
|
81
|
-
pause(randint(500, 2000))
|
|
82
|
-
})
|
|
83
|
-
|
|
84
34
|
|
|
85
|
-
```
|
|
86
35
|
|
|
87
36
|
```ghost
|
|
88
37
|
|
|
89
38
|
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
|
|
90
39
|
carnival.startTimer()
|
|
91
40
|
})
|
|
92
|
-
// game.onGameOverExpanded(
|
|
41
|
+
// game.onGameOverExpanded(carnival.WinTypes.Multi)
|
|
93
42
|
controller.B.onEvent(ControllerButtonEvent.Pressed, function () {
|
|
94
43
|
info.player2.setScore(0)
|
|
95
44
|
info.player1.setScore(10)
|
|
96
|
-
// game.onGameOverExpanded(
|
|
97
|
-
carnival.customGameOverExpanded("Spooky!", effects.confetti, music.magicWand,
|
|
45
|
+
// game.onGameOverExpanded(carnival.WinTypes.Timed)
|
|
46
|
+
carnival.customGameOverExpanded("Spooky!", effects.confetti, music.magicWand, carnival.ScoreTypes.HTime, 0)
|
|
98
47
|
})
|
|
99
48
|
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
|
|
100
49
|
throwBall = carnival.createProjectileBallFromSprite(assets.image`ball-blue`, myBall)
|
|
@@ -123,7 +72,7 @@ let myBooth = sprites.create(assets.image`booth`, SpriteKind.Booth)
|
|
|
123
72
|
carnival.startTimer()
|
|
124
73
|
myBall.controlBallWithArrowKeys(true)
|
|
125
74
|
myBall.setIter(10)
|
|
126
|
-
myBall.setTraceMulti(
|
|
75
|
+
myBall.setTraceMulti(carnival.Tracers.Cross)
|
|
127
76
|
myBall.variablePower(
|
|
128
77
|
statusbar,
|
|
129
78
|
30,
|
|
@@ -137,1029 +86,6 @@ forever(function () {
|
|
|
137
86
|
pause(randint(500, 2000))
|
|
138
87
|
})
|
|
139
88
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
```customts
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
namespace SpriteKind {
|
|
150
|
-
//% isKind
|
|
151
|
-
export const Ball = SpriteKind.create()
|
|
152
|
-
//% isKind
|
|
153
|
-
export const Booth = SpriteKind.create()
|
|
154
|
-
//% isKind
|
|
155
|
-
export const Mouse = SpriteKind.create()
|
|
156
|
-
//% isKind
|
|
157
|
-
export const Crosshair = SpriteKind.create()
|
|
158
|
-
//% isKind
|
|
159
|
-
export const Moon = SpriteKind.create()
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
enum winTypes {
|
|
163
|
-
//% block="win game"
|
|
164
|
-
Win,
|
|
165
|
-
//% block="lose game"
|
|
166
|
-
Lose,
|
|
167
|
-
//% block="best score"
|
|
168
|
-
Score,
|
|
169
|
-
//% block="best time"
|
|
170
|
-
Timed,
|
|
171
|
-
//% block="multiplayer"
|
|
172
|
-
Multi,
|
|
173
|
-
//% block="custom" blockHidden
|
|
174
|
-
Custom
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
enum scoreTypes {
|
|
178
|
-
//% block="high score"
|
|
179
|
-
HScore,
|
|
180
|
-
//% block="low score"
|
|
181
|
-
LScore,
|
|
182
|
-
//% block="high time"
|
|
183
|
-
HTime,
|
|
184
|
-
//% block="low time"
|
|
185
|
-
LTime,
|
|
186
|
-
//% block="none"
|
|
187
|
-
None
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
enum speeds {
|
|
191
|
-
//% block="fast"
|
|
192
|
-
Fast,
|
|
193
|
-
//% block="medium"
|
|
194
|
-
Med,
|
|
195
|
-
//% block="slow"
|
|
196
|
-
Slow
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
enum areas {
|
|
200
|
-
//% block="top"
|
|
201
|
-
Top,
|
|
202
|
-
//% block="middle"
|
|
203
|
-
Mid,
|
|
204
|
-
//% block="bottom"
|
|
205
|
-
Bottom
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
enum tracers {
|
|
209
|
-
//% block="full"
|
|
210
|
-
Full,
|
|
211
|
-
//% block="partial"
|
|
212
|
-
Part,
|
|
213
|
-
//% block="pointer"
|
|
214
|
-
Pointer,
|
|
215
|
-
//% block="crosshair"
|
|
216
|
-
Cross,
|
|
217
|
-
//% block="off"
|
|
218
|
-
Off
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
let textSprite: TextSprite = null
|
|
222
|
-
//let fanfare: effects.BackgroundEffect = undefined;
|
|
223
|
-
//let winStyle="winTypes.Score"
|
|
224
|
-
|
|
225
|
-
// Get array of player info
|
|
226
|
-
let players: info.PlayerInfo[];
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* An extension full of carnival goodness
|
|
232
|
-
*/
|
|
233
|
-
//% weight=100 color=#b70082 icon="\uf54e"
|
|
234
|
-
//% groups='["Ball", "Timer", "Countdown", "Game", "Scene"]'
|
|
235
|
-
namespace carnival {
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Adds text to the top, middle, or bottom
|
|
239
|
-
* of screen as defined by games
|
|
240
|
-
*/
|
|
241
|
-
//% group="Scene"
|
|
242
|
-
//% blockId=add_label_to
|
|
243
|
-
//% block="add label $myLabel to $myPosition of window || $myColor"
|
|
244
|
-
//% myLabel.defl="Whack-the-Mole"
|
|
245
|
-
//% myColor.shadow="colorindexpicker"
|
|
246
|
-
//% myColor.defl=4
|
|
247
|
-
//% myPosition.defl=areas.Bottom
|
|
248
|
-
//% inlineInputMode=inline
|
|
249
|
-
export function add_label_to(myLabel: string, myPosition: areas, myColor?: number) {
|
|
250
|
-
if (myColor == undefined)
|
|
251
|
-
myColor = 4;
|
|
252
|
-
|
|
253
|
-
textSprite = textsprite.create(myLabel, 0, myColor)
|
|
254
|
-
if (myPosition == areas.Bottom) textSprite.setPosition(80, 110);
|
|
255
|
-
if (myPosition == areas.Mid) textSprite.setPosition(80, 50);
|
|
256
|
-
if (myPosition == areas.Top) textSprite.setPosition(80, 20);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// Formerly of the Info Category -----
|
|
262
|
-
|
|
263
|
-
let countdownInitialized = false;
|
|
264
|
-
let countUpInitialized = false;
|
|
265
|
-
|
|
266
|
-
class TimerState {
|
|
267
|
-
public playerStates: info.PlayerState[];
|
|
268
|
-
public visibilityFlag: number;
|
|
269
|
-
|
|
270
|
-
//public timerElapsed: number;
|
|
271
|
-
public bgColor: number;
|
|
272
|
-
public borderColor: number;
|
|
273
|
-
public fontColor: number;
|
|
274
|
-
|
|
275
|
-
constructor() {
|
|
276
|
-
this.visibilityFlag = info.Visibility.Hud;
|
|
277
|
-
this.bgColor = screen.isMono ? 0 : 1;
|
|
278
|
-
this.borderColor = screen.isMono ? 1 : 3;
|
|
279
|
-
this.fontColor = screen.isMono ? 1 : 3;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
let timerState: TimerState = undefined;
|
|
284
|
-
|
|
285
|
-
let timerStateStack: {
|
|
286
|
-
state: TimerState,
|
|
287
|
-
scene: scene.Scene
|
|
288
|
-
}[];
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Adds timer to game
|
|
293
|
-
*/
|
|
294
|
-
//% color="#b70082"
|
|
295
|
-
//% group="Timer"
|
|
296
|
-
//% blockId=start_count_up_game
|
|
297
|
-
//% block="start timer"
|
|
298
|
-
//% inlineInputMode=inline
|
|
299
|
-
export function startTimer() {
|
|
300
|
-
control.timer1.reset();
|
|
301
|
-
updateFlag(info.Visibility.Countdown, true);
|
|
302
|
-
timerHUD();
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Set whether timer should be displayed
|
|
308
|
-
* @param on if true, countdown is shown; otherwise, countdown is hidden
|
|
309
|
-
*/
|
|
310
|
-
//% color="#b70082"
|
|
311
|
-
//% group="Timer"
|
|
312
|
-
//% blockId=show_timer
|
|
313
|
-
//% block="show timer $on=toggleOnOff"
|
|
314
|
-
//% inlineInputMode=inline
|
|
315
|
-
export function showTimer(on: boolean) {
|
|
316
|
-
updateFlag(info.Visibility.Countdown, on);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Return the current value of the count-up timer
|
|
321
|
-
*/
|
|
322
|
-
//% color="#b70082"
|
|
323
|
-
//% group="Timer"
|
|
324
|
-
//% blockId=get_timer
|
|
325
|
-
//% block="timer value"
|
|
326
|
-
//% inlineInputMode=inline
|
|
327
|
-
export function getTimerValue():number {
|
|
328
|
-
return control.timer1.millis();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
function updateFlag(flag: info.Visibility, on: boolean) {
|
|
333
|
-
timerHUD();
|
|
334
|
-
if (on) timerState.visibilityFlag |= flag;
|
|
335
|
-
else timerState.visibilityFlag = ~(~timerState.visibilityFlag | flag);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function drawTimer(millis: number) {
|
|
339
|
-
if (millis < 0) millis = 0;
|
|
340
|
-
millis |= 0;
|
|
341
|
-
|
|
342
|
-
const font = image.font8;
|
|
343
|
-
const smallFont = image.font5;
|
|
344
|
-
const seconds = Math.idiv(millis, 1000);
|
|
345
|
-
const width = font.charWidth * 5 - 2;
|
|
346
|
-
let left = (screen.width >> 1) - (width >> 1) + 1;
|
|
347
|
-
let color1 = timerState.fontColor;
|
|
348
|
-
let color2 = timerState.bgColor;
|
|
349
|
-
|
|
350
|
-
screen.fillRect(left - 3, 0, width + 6, font.charHeight + 3, timerState.borderColor)
|
|
351
|
-
screen.fillRect(left - 2, 0, width + 4, font.charHeight + 2, color2)
|
|
352
|
-
|
|
353
|
-
if (seconds < 60) {
|
|
354
|
-
const top = 1;
|
|
355
|
-
const remainder = Math.idiv(millis % 1000, 10);
|
|
356
|
-
|
|
357
|
-
screen.print(formatDecimal(seconds) + ".", left, top, color1, font)
|
|
358
|
-
const decimalLeft = left + 3 * font.charWidth;
|
|
359
|
-
screen.print(formatDecimal(remainder), decimalLeft, top + 2, color1, smallFont)
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
const minutes = Math.idiv(seconds, 60);
|
|
363
|
-
const remainder = seconds % 60;
|
|
364
|
-
screen.print(formatDecimal(minutes) + ":" + formatDecimal(remainder), left, 1, color1, font);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
function formatDecimal(val: number) {
|
|
369
|
-
val |= 0;
|
|
370
|
-
if (val < 10) {
|
|
371
|
-
return "0" + val;
|
|
372
|
-
}
|
|
373
|
-
return val.toString();
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function timerHUD() {
|
|
377
|
-
if (timerState) return;
|
|
378
|
-
|
|
379
|
-
timerState = new TimerState();
|
|
380
|
-
|
|
381
|
-
scene.createRenderable(
|
|
382
|
-
scene.HUD_Z,
|
|
383
|
-
() => {
|
|
384
|
-
|
|
385
|
-
// show timer
|
|
386
|
-
if (timerState.visibilityFlag & info.Visibility.Countdown) {
|
|
387
|
-
const scene = game.currentScene();
|
|
388
|
-
//const elapsed = scene.millis();
|
|
389
|
-
const elapsed = control.timer1.millis();
|
|
390
|
-
drawTimer(elapsed);
|
|
391
|
-
let t = elapsed / 1000;
|
|
392
|
-
if (t <= 0) {
|
|
393
|
-
t = 0;
|
|
394
|
-
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* Adds game end style to countdown
|
|
405
|
-
*/
|
|
406
|
-
//% color="#b70082"
|
|
407
|
-
//% group="Countdown"
|
|
408
|
-
//% blockId=start_countdown_game
|
|
409
|
-
//% block="start countdown $myTime (s) and game over $winType || effect $winEffect"
|
|
410
|
-
//% myTime.defl=15
|
|
411
|
-
//% winType.defl=winTypes.Score
|
|
412
|
-
//% winEffect.defl=effects.confetti
|
|
413
|
-
//% inlineInputMode=inline
|
|
414
|
-
export function startCountdownGame(myTime: number, winType: winTypes, winEffect?: effects.BackgroundEffect) {
|
|
415
|
-
if (!winType)
|
|
416
|
-
winType = winTypes.Win;
|
|
417
|
-
if (!winEffect && winType != winTypes.Lose) {
|
|
418
|
-
winEffect = effects.confetti;
|
|
419
|
-
}
|
|
420
|
-
else { winEffect = effects.melt; }
|
|
421
|
-
|
|
422
|
-
init(winType, winEffect);
|
|
423
|
-
info.startCountdown(myTime);
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function saveLowScore(newLow: number) {
|
|
428
|
-
const curr = settings.readNumber("low-score")
|
|
429
|
-
if (curr == undefined || newLow < curr){
|
|
430
|
-
settings.writeNumber("low-score", newLow);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Get the last recorded low score
|
|
435
|
-
function lowScore(): number {
|
|
436
|
-
return settings.readNumber("low-score");
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
function newGameOver(winStyle: winTypes, fanfare: effects.BackgroundEffect, winSound?:music.Melody, scoreType?: scoreTypes, message?: string, customScore?: number) {
|
|
441
|
-
|
|
442
|
-
// Prep default variables for different win types
|
|
443
|
-
let winnerNumber = [1]; // Which players have the high scores?
|
|
444
|
-
let thisBest = info.score(); // Who has the best score this round?
|
|
445
|
-
let newBest = false; // Is thisBest the newBest for all games?
|
|
446
|
-
let bestScore = info.highScore(); // What is the bestScore of all time?
|
|
447
|
-
|
|
448
|
-
// Save number of seconds passed during game
|
|
449
|
-
const thisScene = game.currentScene();
|
|
450
|
-
//let timeElapsed = roundOff(thisScene.millis() / 1000, 2); //Can't get points to match timer perfectly
|
|
451
|
-
let timeElapsed = Math.floor(thisScene.millis() / 1000);
|
|
452
|
-
|
|
453
|
-
if (control.timer1.millis() >=0) {
|
|
454
|
-
timeElapsed = Math.floor(control.timer1.millis() / 1000);
|
|
455
|
-
// timeElapsed = roundOff(control.timer1.millis() / 1000, 2); //Can't get points to match timer perfectly
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/*
|
|
460
|
-
// Save all scores as relevant to the game.
|
|
461
|
-
info.saveAllScores(); // This is throwing an error for some reason
|
|
462
|
-
*/
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
// Initialize thisBest if customScore wasn't included
|
|
466
|
-
if (customScore === undefined) {
|
|
467
|
-
thisBest = info.player1.getState().score;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// Initialize the messaging / fanfare based on winStyle
|
|
471
|
-
if (winStyle == winTypes.Custom) {
|
|
472
|
-
if (!scoreType) { scoreType = scoreTypes.HScore;}
|
|
473
|
-
if (!message) { message = "Game Over!"; }
|
|
474
|
-
if (!fanfare) { fanfare = effects.confetti; }
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
} else if (winStyle == winTypes.Win) {
|
|
478
|
-
scoreType = scoreTypes.HScore;
|
|
479
|
-
message = "You Win!";
|
|
480
|
-
if (!fanfare) { fanfare = effects.confetti; }
|
|
481
|
-
|
|
482
|
-
} else if (winStyle == winTypes.Score) {
|
|
483
|
-
scoreType = scoreTypes.HScore;
|
|
484
|
-
message = "Great Score!" ;
|
|
485
|
-
if (!fanfare) { fanfare = effects.confetti; }
|
|
486
|
-
|
|
487
|
-
} else if (winStyle == winTypes.Timed) {
|
|
488
|
-
scoreType = scoreTypes.LTime;
|
|
489
|
-
message = "Great Time!" ;
|
|
490
|
-
if (!fanfare) { fanfare = effects.confetti; }
|
|
491
|
-
|
|
492
|
-
} else if (winStyle == winTypes.Multi) {
|
|
493
|
-
scoreType = scoreTypes.HScore;
|
|
494
|
-
if (!fanfare) { fanfare = effects.confetti; }
|
|
495
|
-
|
|
496
|
-
// Find winner of multiplayer
|
|
497
|
-
const scoreInfo1 = info.player1.getState();
|
|
498
|
-
const scoreInfo2 = info.player2.getState();
|
|
499
|
-
const scoreInfo3 = info.player3.getState();
|
|
500
|
-
const scoreInfo4 = info.player4.getState();
|
|
501
|
-
const allScores = [scoreInfo1.score, scoreInfo2.score, scoreInfo3.score, scoreInfo4.score];
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
// Find player with highest score in Multi
|
|
505
|
-
thisBest = -Infinity; // Make sure there's no false tie
|
|
506
|
-
for (let i = 0; i < 4; i++) {
|
|
507
|
-
if (allScores[i] != undefined && allScores[i] > thisBest) {
|
|
508
|
-
thisBest = allScores[i];
|
|
509
|
-
winnerNumber = [i+1];
|
|
510
|
-
} else if (allScores[i] != undefined && allScores[i] == thisBest) {
|
|
511
|
-
winnerNumber.push(i + 1);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
// Construct string for one winner
|
|
516
|
-
if (!message && winnerNumber.length <= 1) {
|
|
517
|
-
message = "Player " + winnerNumber[0] + " Wins!" ;
|
|
518
|
-
} else {
|
|
519
|
-
//Construct string for ties
|
|
520
|
-
message = "Players ";
|
|
521
|
-
|
|
522
|
-
for (let i = 0; i < ((winnerNumber.length)-1); i++) {
|
|
523
|
-
message += winnerNumber[i] + " & ";
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// remove the last ampersand and the trailing space
|
|
527
|
-
message += winnerNumber[(winnerNumber.length) - 1] + " Tied!";
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
} else {
|
|
531
|
-
if (!scoreType) { scoreType = scoreTypes.None;}
|
|
532
|
-
if (!message) { message = "Game Over!"; }
|
|
533
|
-
if (!fanfare) { fanfare = effects.melt; }
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Overwrite current game score if something was passed in
|
|
537
|
-
if (customScore != undefined) {
|
|
538
|
-
thisBest = customScore;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
// Set bestScore and newBest based on score and scoreType
|
|
542
|
-
if (scoreType == scoreTypes.HScore){
|
|
543
|
-
if (thisBest > bestScore) {
|
|
544
|
-
newBest = true;
|
|
545
|
-
bestScore = thisBest;
|
|
546
|
-
info.setScore(thisBest);
|
|
547
|
-
info.saveHighScore();
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
} else if (scoreType == scoreTypes.LScore) {
|
|
551
|
-
bestScore = settings.readNumber("low-score");
|
|
552
|
-
if(bestScore == undefined){bestScore = Infinity;}
|
|
553
|
-
if (thisBest < bestScore) {
|
|
554
|
-
newBest = true;
|
|
555
|
-
bestScore = thisBest;
|
|
556
|
-
info.setScore(thisBest);
|
|
557
|
-
saveLowScore(thisBest);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
} else if (scoreType == scoreTypes.HTime) {
|
|
561
|
-
|
|
562
|
-
// Set thisBest to timeElapsed if no customScore
|
|
563
|
-
if (!customScore) {
|
|
564
|
-
thisBest = timeElapsed;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (thisBest > bestScore) {
|
|
568
|
-
newBest = true;
|
|
569
|
-
bestScore = thisBest;
|
|
570
|
-
info.setScore(thisBest);
|
|
571
|
-
info.saveHighScore();
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
} else if (scoreType == scoreTypes.LTime) {
|
|
575
|
-
bestScore = settings.readNumber("low-score");
|
|
576
|
-
if (bestScore == undefined) { bestScore = Infinity; }
|
|
577
|
-
|
|
578
|
-
// Set thisBest to timeElapsed if no customScore
|
|
579
|
-
if (!customScore) {
|
|
580
|
-
thisBest = timeElapsed;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
if (thisBest < bestScore) {
|
|
584
|
-
newBest = true;
|
|
585
|
-
bestScore = thisBest;
|
|
586
|
-
info.setScore(thisBest);
|
|
587
|
-
saveLowScore(thisBest);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
} else {
|
|
591
|
-
|
|
592
|
-
// Score judging type must be "None"
|
|
593
|
-
thisBest = undefined;
|
|
594
|
-
bestScore = undefined;
|
|
595
|
-
newBest = false;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Make sure there's a sound to playe
|
|
599
|
-
if (! winSound){winSound = music.powerUp;}
|
|
600
|
-
|
|
601
|
-
// releasing memory and clear fibers. Do not add anything that releases the fiber until background is set below,
|
|
602
|
-
// or screen will be cleared on the new frame and will not appear as background in the game over screen.
|
|
603
|
-
game.popScene();
|
|
604
|
-
game.pushScene();
|
|
605
|
-
scene.setBackgroundImage(screen.clone());
|
|
606
|
-
|
|
607
|
-
winSound.play();
|
|
608
|
-
|
|
609
|
-
fanfare.startScreenEffect();
|
|
610
|
-
|
|
611
|
-
pause(400);
|
|
612
|
-
|
|
613
|
-
const overDialog = new GameOverDialog(true, message, thisBest, bestScore, newBest);
|
|
614
|
-
scene.createRenderable(scene.HUD_Z, target => {
|
|
615
|
-
overDialog.update();
|
|
616
|
-
target.drawTransparentImage(
|
|
617
|
-
overDialog.image,
|
|
618
|
-
0,
|
|
619
|
-
(screen.height - overDialog.image.height) >> 1
|
|
620
|
-
);
|
|
621
|
-
});
|
|
622
|
-
pause(500); // wait for users to stop pressing keys
|
|
623
|
-
overDialog.displayCursor();
|
|
624
|
-
game.waitAnyButton();
|
|
625
|
-
control.reset();
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
function roundOff(thisNum:number, toPlace:number): number {
|
|
630
|
-
const x = Math.pow(10, toPlace);
|
|
631
|
-
return Math.round(thisNum * x) / x;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
function init(winStyle: winTypes, fanfare: effects.BackgroundEffect) {
|
|
635
|
-
if (countdownInitialized) return;
|
|
636
|
-
countdownInitialized = true;
|
|
637
|
-
|
|
638
|
-
info.onCountdownEnd(function () {
|
|
639
|
-
|
|
640
|
-
//Handling manually to include number of seconds passed
|
|
641
|
-
/*
|
|
642
|
-
if (winStyle == winTypes.Win) {
|
|
643
|
-
game.over(true, fanfare)
|
|
644
|
-
} else */ if (winStyle == winTypes.Lose) {
|
|
645
|
-
game.over(false, fanfare)
|
|
646
|
-
} else {
|
|
647
|
-
newGameOver(winStyle, fanfare);
|
|
648
|
-
}
|
|
649
|
-
})
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
export class GameOverDialog extends game.BaseDialog {
|
|
653
|
-
protected cursorOn: boolean;
|
|
654
|
-
protected isNewbestScore: boolean;
|
|
655
|
-
|
|
656
|
-
constructor(
|
|
657
|
-
protected win: boolean,
|
|
658
|
-
protected messageText: string,
|
|
659
|
-
protected score?: number,
|
|
660
|
-
protected best?: number,
|
|
661
|
-
protected newBest?: boolean
|
|
662
|
-
) {
|
|
663
|
-
super(screen.width, 46, img`
|
|
664
|
-
1 1 1
|
|
665
|
-
f f f
|
|
666
|
-
1 1 1
|
|
667
|
-
`);
|
|
668
|
-
this.cursorOn = false;
|
|
669
|
-
|
|
670
|
-
/* Since best time is lower, need to do this elsewhere
|
|
671
|
-
this.isNewbestScore = this.score > this.bestScore;
|
|
672
|
-
*/
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
displayCursor() {
|
|
676
|
-
this.cursorOn = true;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
update() {
|
|
680
|
-
this.clearInterior();
|
|
681
|
-
this.drawTextCore();
|
|
682
|
-
|
|
683
|
-
if (this.cursorOn) {
|
|
684
|
-
this.drawCursorRow();
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
drawTextCore() {
|
|
689
|
-
const titleHeight = 8;
|
|
690
|
-
|
|
691
|
-
this.image.printCenter(
|
|
692
|
-
this.messageText,
|
|
693
|
-
titleHeight,
|
|
694
|
-
screen.isMono ? 1 : 5,
|
|
695
|
-
image.font8
|
|
696
|
-
);
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (this.score != undefined) {
|
|
700
|
-
const scoreHeight = 23;
|
|
701
|
-
const bestScoreHeight = 34;
|
|
702
|
-
const scoreColor = screen.isMono ? 1 : 2;
|
|
703
|
-
|
|
704
|
-
this.image.printCenter(
|
|
705
|
-
"Score:" + this.score,
|
|
706
|
-
scoreHeight,
|
|
707
|
-
scoreColor,
|
|
708
|
-
image.font8
|
|
709
|
-
);
|
|
710
|
-
|
|
711
|
-
if (this.newBest == true) {
|
|
712
|
-
this.image.printCenter(
|
|
713
|
-
"New Best Score!",
|
|
714
|
-
bestScoreHeight,
|
|
715
|
-
scoreColor,
|
|
716
|
-
image.font5
|
|
717
|
-
);
|
|
718
|
-
} else {
|
|
719
|
-
this.image.printCenter(
|
|
720
|
-
"Best:" + this.best,
|
|
721
|
-
bestScoreHeight,
|
|
722
|
-
scoreColor,
|
|
723
|
-
image.font8
|
|
724
|
-
);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// End Info
|
|
731
|
-
|
|
732
|
-
// Formerly namespace Game
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
/**
|
|
736
|
-
* Adds additional end game styles
|
|
737
|
-
*/
|
|
738
|
-
//% color="#b70082"
|
|
739
|
-
//% group="Game"
|
|
740
|
-
//% blockId=on_game_over_expanded
|
|
741
|
-
//% block="game over $winStyle || add effect $winEffect"
|
|
742
|
-
//% winType.defl=winTypes.Win
|
|
743
|
-
//% winEffect.defl=effects.confetti
|
|
744
|
-
//% inlineInputMode=inline
|
|
745
|
-
export function onGameOverExpanded(winStyle: winTypes, winEffect?: effects.BackgroundEffect) {
|
|
746
|
-
|
|
747
|
-
if (winEffect == undefined) {
|
|
748
|
-
if (winStyle == winTypes.Lose) { winEffect = effects.melt; }
|
|
749
|
-
else { winEffect = effects.confetti; }
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
if (winStyle == winTypes.Lose) {
|
|
753
|
-
game.over(false, winEffect)
|
|
754
|
-
} else {
|
|
755
|
-
newGameOver(winStyle, winEffect);
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
/**
|
|
760
|
-
* Adds custom end game styles
|
|
761
|
-
*/
|
|
762
|
-
//% color="#b70082"
|
|
763
|
-
//% group="Game"
|
|
764
|
-
//% blockId=on_game_over_custom_expanded
|
|
765
|
-
//% block="game over $message || with $winEffect and $gameSound send score $score judge $scoring"
|
|
766
|
-
//% message.defl="Great Job!"
|
|
767
|
-
//% scoring.defl=scoreTypes.None
|
|
768
|
-
//% winEffect.defl=effects.confetti
|
|
769
|
-
//% gameSound.defl=music.powerUp
|
|
770
|
-
//% inlineInputMode=inline
|
|
771
|
-
export function customGameOverExpanded(message: string, winEffect?: effects.BackgroundEffect, gameSound?: music.Melody, scoring?: scoreTypes, score?: number) {
|
|
772
|
-
if (!winEffect) { winEffect = effects.confetti; }
|
|
773
|
-
if (!scoring) { scoring = scoreTypes.HScore; }
|
|
774
|
-
if (score == undefined) { info.score();}
|
|
775
|
-
if (!gameSound) { gameSound = music.powerUp;}
|
|
776
|
-
game.setGameOverSound(true, gameSound);
|
|
777
|
-
newGameOver(winTypes.Custom, winEffect, gameSound, scoring, message, score);
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
// Formerly namespace Ball
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
/**
|
|
786
|
-
* Creates a new throwable from an image and kind
|
|
787
|
-
* @param img the image for the sprite
|
|
788
|
-
* @param kind the kind to make the throwable
|
|
789
|
-
* @param x optional initial x position, eg: 10
|
|
790
|
-
* @param y optional initial y position, eg: 110
|
|
791
|
-
*/
|
|
792
|
-
//% blockId=throwCreate block="ball $img=screen_image_picker of kind $kind=spritekind || at x $x y $y"
|
|
793
|
-
//% color="#b70082"
|
|
794
|
-
//% group="Ball"
|
|
795
|
-
//% expandableArgumentMode=toggle
|
|
796
|
-
//% inlineInputMode=inline
|
|
797
|
-
//% blockSetVariable=myBall
|
|
798
|
-
//% weight=100
|
|
799
|
-
export function create(img: Image,
|
|
800
|
-
kind: number,
|
|
801
|
-
x: number = 10,
|
|
802
|
-
y: number = 110): Ball {
|
|
803
|
-
return new Ball(img, kind, x, y);
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* Create a new ball with a given speed that starts from the location of another sprite.
|
|
810
|
-
* The sprite auto-destroys when it leaves the screen. You can modify position after it's created.
|
|
811
|
-
*/
|
|
812
|
-
//% group="Ball"
|
|
813
|
-
//% color="#b70082"
|
|
814
|
-
//% blockId=spritescreateprojectileballfromparent block="ball projectile $img=screen_image_picker based on $parentBall=variables_get(myBall) || of kind $kind=spritekind"
|
|
815
|
-
//& kind.defl=1
|
|
816
|
-
//% blockSetVariable=myBall
|
|
817
|
-
//% inlineInputMode=inline
|
|
818
|
-
export function createProjectileBallFromSprite(img: Image, parentBall: Ball, kind?: number): Ball {
|
|
819
|
-
let vx = xComponent(parentBall.angle, parentBall.pow);
|
|
820
|
-
let vy = carnival.yComponent(parentBall.angle, parentBall.pow);
|
|
821
|
-
let ay = parentBall.gravity;
|
|
822
|
-
let ax = parentBall.wind;
|
|
823
|
-
let p = parentBall.pow;
|
|
824
|
-
if (!kind) { kind = SpriteKind.Projectile;}
|
|
825
|
-
return createProjectileBall(img, vx, vy, ax, ay, p, kind, parentBall);
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
/**
|
|
829
|
-
* Create a new sprite with given speed, and place it at the edge of the screen so it moves towards the middle.
|
|
830
|
-
* The sprite auto-destroys when it leaves the screen. You can modify position after it's created.
|
|
831
|
-
*/
|
|
832
|
-
//% group="Ball"
|
|
833
|
-
//% color="#b70082"
|
|
834
|
-
//% blockId=spritescreateprojectileball block="ball $img=screen_image_picker vx $vx vy $vy of kind $kind=spritekind||based on $parentBall=variables_get(myBall)"
|
|
835
|
-
//% weight=99
|
|
836
|
-
//% blockSetVariable=myBall
|
|
837
|
-
//% inlineInputMode=inline
|
|
838
|
-
//% expandableArgumentMode=toggle
|
|
839
|
-
function createProjectileBall(img: Image, vx: number, vy: number, ax: number, ay: number, power: number, kind?: number, parentBall?: Ball) {
|
|
840
|
-
const s = carnival.create(img, kind || SpriteKind.Projectile);
|
|
841
|
-
const sc = game.currentScene();
|
|
842
|
-
|
|
843
|
-
if (parentBall) {
|
|
844
|
-
s.setPosition(parentBall.x, parentBall.y);
|
|
845
|
-
s.vx = xComponent(parentBall.angle, parentBall.pow);
|
|
846
|
-
s.vy = carnival.yComponent(parentBall.angle, parentBall.pow);
|
|
847
|
-
s.ay = parentBall.gravity;
|
|
848
|
-
s.ax = parentBall.wind;
|
|
849
|
-
s.pow = parentBall.pow;
|
|
850
|
-
} else {
|
|
851
|
-
// put it at the edge of the screen so that it moves towards the middle
|
|
852
|
-
// If the scene has a tile map, place the sprite fully on the screen
|
|
853
|
-
const xOff = sc.tileMap ? -(s.width >> 1) : (s.width >> 1) - 1;
|
|
854
|
-
const yOff = sc.tileMap ? -(s.height >> 1) : (s.height >> 1) - 1;
|
|
855
|
-
const cam = game.currentScene().camera;
|
|
856
|
-
|
|
857
|
-
let initialX = cam.offsetX;
|
|
858
|
-
let initialY = cam.offsetY;
|
|
859
|
-
|
|
860
|
-
if (vx < 0) {
|
|
861
|
-
initialX += screen.width + xOff;
|
|
862
|
-
} else if (vx > 0) {
|
|
863
|
-
initialX += -xOff;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
if (vy < 0) {
|
|
867
|
-
initialY += screen.height + yOff;
|
|
868
|
-
} else if (vy > 0) {
|
|
869
|
-
initialY += -yOff;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
s.setPosition(initialX, initialY);
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
s.moon.destroy();
|
|
876
|
-
s.flags |= sprites.Flag.AutoDestroy | sprites.Flag.DestroyOnWall;
|
|
877
|
-
|
|
878
|
-
return s;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
/**
|
|
884
|
-
* Convert degrees to radians
|
|
885
|
-
* @param degree to convert
|
|
886
|
-
* @return converted value in radians
|
|
887
|
-
*/
|
|
888
|
-
function degreeToRadian(degree: number): number {
|
|
889
|
-
return degree * Math.PI / 180;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
/**
|
|
893
|
-
* Evaluate the x component of a given vector
|
|
894
|
-
* @param degree angle of vector
|
|
895
|
-
* @param magnitude magnitude of vector
|
|
896
|
-
* @return x component of vector
|
|
897
|
-
*/
|
|
898
|
-
//% group="Ball"
|
|
899
|
-
//% color="#b70082"
|
|
900
|
-
export function xComponent(degree: number, magnitude: number): number {
|
|
901
|
-
return magnitude * Math.cos(degreeToRadian(degree));
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
/**
|
|
905
|
-
* Evaluate the y component of a given vector
|
|
906
|
-
* @param degree angle of vector
|
|
907
|
-
* @param magnitude magnitude of vector
|
|
908
|
-
* @return y component of vector
|
|
909
|
-
*/
|
|
910
|
-
//% group="Ball"
|
|
911
|
-
//% color="#b70082"
|
|
912
|
-
export function yComponent(degree: number, magnitude: number): number {
|
|
913
|
-
return -magnitude * Math.sin(degreeToRadian(degree));
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* A throwable
|
|
919
|
-
**/
|
|
920
|
-
|
|
921
|
-
//% blockNamespace=carnival color="#b70082" blockGap=8
|
|
922
|
-
class Ball extends sprites.ExtendableSprite {
|
|
923
|
-
private renderable: scene.Renderable;
|
|
924
|
-
|
|
925
|
-
private controlKeys: boolean;
|
|
926
|
-
private trace: boolean;
|
|
927
|
-
|
|
928
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
929
|
-
//% blockCombine block="angle"
|
|
930
|
-
//% weight=8
|
|
931
|
-
public angle: number;
|
|
932
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
933
|
-
//% blockCombine block="power"
|
|
934
|
-
//% weight=8
|
|
935
|
-
public pow: number;
|
|
936
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
937
|
-
//% blockCombine block="tracing time (seconds)"
|
|
938
|
-
//% weight=8
|
|
939
|
-
public iter: number;
|
|
940
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
941
|
-
//% blockCombine block="trace color"
|
|
942
|
-
//% weight=8
|
|
943
|
-
public traceColor: number;
|
|
944
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
945
|
-
//% blockCombine block="gravity"
|
|
946
|
-
//% weight=8
|
|
947
|
-
public gravity: number;
|
|
948
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
949
|
-
//% blockCombine block="wind"
|
|
950
|
-
//% weight=8
|
|
951
|
-
public wind: number;
|
|
952
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
953
|
-
//% blockCombine block="angle adjust rate"
|
|
954
|
-
//% weight=8
|
|
955
|
-
public angleRate: number;
|
|
956
|
-
//% group="Ball" blockSetVariable="myBall"
|
|
957
|
-
//% blockCombine block="wind"
|
|
958
|
-
//% weight=8
|
|
959
|
-
public powerRate: number;
|
|
960
|
-
//% blockSetVariable="myBall"
|
|
961
|
-
//% blockCombine block="moon"
|
|
962
|
-
//% weight=8
|
|
963
|
-
public moon: Sprite;
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
public constructor(img: Image,
|
|
967
|
-
kind: number,
|
|
968
|
-
x: number,
|
|
969
|
-
y: number) {
|
|
970
|
-
super(img);
|
|
971
|
-
this.setKind(kind);
|
|
972
|
-
this.x = x;
|
|
973
|
-
this.y = y;
|
|
974
|
-
|
|
975
|
-
this.gravity = 20;
|
|
976
|
-
this.pow = 50;
|
|
977
|
-
this.angle = 10;
|
|
978
|
-
this.angleRate = 3;
|
|
979
|
-
this.powerRate = 3;
|
|
980
|
-
this.iter = .4;
|
|
981
|
-
this.wind = 0;
|
|
982
|
-
this.moon = sprites.create(assets.image`crosshair`, SpriteKind.Moon);
|
|
983
|
-
this.moon.setFlag(SpriteFlag.Invisible, true);
|
|
984
|
-
|
|
985
|
-
this.renderable = scene.createRenderable(-0.5, (target, camera) => {
|
|
986
|
-
let xComp = carnival.xComponent(this.angle, this.pow);
|
|
987
|
-
let yComp = carnival.yComponent(this.angle, this.pow);
|
|
988
|
-
let xOffset = camera.offsetX;
|
|
989
|
-
let yOffset = camera.offsetY;
|
|
990
|
-
|
|
991
|
-
for (let i: number = 0.1; i < this.iter; i += i / 5) {
|
|
992
|
-
let x = this.x + i * xComp + (i ** 2) * this.wind / 2;
|
|
993
|
-
let y = this.y + i * yComp + (i ** 2) * this.gravity / 2;
|
|
994
|
-
target.setPixel(
|
|
995
|
-
x - xOffset,
|
|
996
|
-
y - yOffset,
|
|
997
|
-
this.traceColor
|
|
998
|
-
);
|
|
999
|
-
}
|
|
1000
|
-
}, () => !this.ay && this.trace);
|
|
1001
|
-
|
|
1002
|
-
this.controlKeys = false;
|
|
1003
|
-
this.trace = false;
|
|
1004
|
-
this.traceColor = 1;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
/**
|
|
1008
|
-
* Gets the throwables's sprite
|
|
1009
|
-
*/
|
|
1010
|
-
//% blockId=throwSprite block="$this sprite"
|
|
1011
|
-
//% weight=8
|
|
1012
|
-
get sprite(): Sprite {
|
|
1013
|
-
return this;
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
/**
|
|
1017
|
-
* Set how to show the trace for the estimated path
|
|
1018
|
-
* @param on whether to turn on or off this feature, eg: true
|
|
1019
|
-
*/
|
|
1020
|
-
//% blockId=setTraceMulti block="trace $this path estimate $traceWay"
|
|
1021
|
-
//% weight=50
|
|
1022
|
-
//% color="#b70082"
|
|
1023
|
-
//% group="Ball"
|
|
1024
|
-
//% traceWay.defl="tracers.Full"
|
|
1025
|
-
//% this.defl=myBall
|
|
1026
|
-
public setTraceMulti(traceWay: tracers): void {
|
|
1027
|
-
|
|
1028
|
-
if(traceWay == tracers.Full){
|
|
1029
|
-
this.moon.setFlag(SpriteFlag.Invisible, true);
|
|
1030
|
-
this.iter = 3;
|
|
1031
|
-
this.trace = true;
|
|
1032
|
-
} else if (traceWay == tracers.Part) {
|
|
1033
|
-
this.moon.setFlag(SpriteFlag.Invisible, true);
|
|
1034
|
-
this.iter = .3;
|
|
1035
|
-
this.trace = true;
|
|
1036
|
-
} else if (traceWay == tracers.Pointer) {
|
|
1037
|
-
this.moon.setFlag(SpriteFlag.Invisible, true);
|
|
1038
|
-
this.iter = .2;
|
|
1039
|
-
this.trace = true;
|
|
1040
|
-
} else if (traceWay == tracers.Cross) {
|
|
1041
|
-
this.trace = false;
|
|
1042
|
-
this.moon.setFlag(SpriteFlag.Invisible, false);
|
|
1043
|
-
} else {
|
|
1044
|
-
this.trace = false;
|
|
1045
|
-
this.moon.setFlag(SpriteFlag.Invisible, false);
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
/**
|
|
1051
|
-
* Set the crosshairs to distance away from center of
|
|
1052
|
-
* ball in direction ball will travel
|
|
1053
|
-
*/
|
|
1054
|
-
//% color="#b70082"
|
|
1055
|
-
//% weight=50
|
|
1056
|
-
//% blockId=updatecross block="update crosshairs || using distance $dist "
|
|
1057
|
-
//% expandableArgumentMode=toggle
|
|
1058
|
-
//% dist.defl=3
|
|
1059
|
-
public update_crosshair(dist?:number) {
|
|
1060
|
-
if(dist == undefined) {dist = 3;}
|
|
1061
|
-
spriteutils.placeAngleFrom(
|
|
1062
|
-
this.moon,
|
|
1063
|
-
this.angle * Math.PI / -180,
|
|
1064
|
-
Math.max(this.width + dist, this.height + dist),
|
|
1065
|
-
this
|
|
1066
|
-
)
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
/**
|
|
1070
|
-
* Set the trace length for the estimated path in percent
|
|
1071
|
-
*/
|
|
1072
|
-
//% weight=50
|
|
1073
|
-
//% color="#b70082"
|
|
1074
|
-
//% group="Ball""
|
|
1075
|
-
//% blockId=setIter block="set $this trace length to $len \\%"
|
|
1076
|
-
//% len.defl=50
|
|
1077
|
-
//% this.defl=myBall
|
|
1078
|
-
public setIter(len: number): void {
|
|
1079
|
-
// Make 100 percent distance = 3
|
|
1080
|
-
this.iter = 3 * (len/100);
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
/**
|
|
1084
|
-
* Throw the throwable with the current settings
|
|
1085
|
-
*/
|
|
1086
|
-
//% weight=50
|
|
1087
|
-
//% color="#b70082"
|
|
1088
|
-
//% group="Ball"
|
|
1089
|
-
//% blockId=throwIt block="toss $this"
|
|
1090
|
-
//% this.defl=myBall
|
|
1091
|
-
public throwIt(): void {
|
|
1092
|
-
this.vx = carnival.xComponent(this.angle, this.pow);
|
|
1093
|
-
this.vy = carnival.yComponent(this.angle, this.pow);
|
|
1094
|
-
this.ay = this.gravity;
|
|
1095
|
-
this.ax = this.wind;
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
/**
|
|
1099
|
-
* Stop the throwable at the current location
|
|
1100
|
-
*/
|
|
1101
|
-
//% color="#b70082"
|
|
1102
|
-
//% weight=50
|
|
1103
|
-
//% group="Ball"
|
|
1104
|
-
//% blockId=stopIt block="stop $this"
|
|
1105
|
-
//% this.defl=myBall
|
|
1106
|
-
public stopIt(): void {
|
|
1107
|
-
this.ay = 0;
|
|
1108
|
-
this.ax = 0;
|
|
1109
|
-
this.vx = 0;
|
|
1110
|
-
this.vy = 0;
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
/**
|
|
1114
|
-
* Set whether to control the throwable with the arrow keys; left and right
|
|
1115
|
-
* to adjust the angle, and up and down to increase / decrease power
|
|
1116
|
-
* @param on whether to turn on or off this feature, eg: true
|
|
1117
|
-
*/
|
|
1118
|
-
//% color="#b70082"
|
|
1119
|
-
//% weight=50
|
|
1120
|
-
//% group="Ball"
|
|
1121
|
-
//% blockId=controlBallKeys block="control $this with arrow keys || $on=toggleOnOff"
|
|
1122
|
-
//% this.defl=myBall
|
|
1123
|
-
//% inlineInputMode=inline
|
|
1124
|
-
public controlBallWithArrowKeys(on: boolean = true): void {
|
|
1125
|
-
this.controlKeys = on;
|
|
1126
|
-
|
|
1127
|
-
game.onUpdate(() => {
|
|
1128
|
-
if (this.controlKeys) {
|
|
1129
|
-
this.angle -= controller.dx() * this.angleRate / 2;
|
|
1130
|
-
this.pow -= controller.dy() * this.powerRate / 2;
|
|
1131
|
-
}
|
|
1132
|
-
})
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
/**
|
|
1136
|
-
* Set whether to control the throwable with the arrow keys; left and right
|
|
1137
|
-
* to adjust the angle, and up and down to increase / decrease power
|
|
1138
|
-
* @param on whether to turn on or off this feature, eg: true
|
|
1139
|
-
*/
|
|
1140
|
-
//% blockId=variablePower block="vary $this power using $status(statusbar) from $minNum \\% to $maxNum \\% || speed $thisSpeed"
|
|
1141
|
-
//% weight=2
|
|
1142
|
-
//% color="#b70082"
|
|
1143
|
-
//% group="Ball"
|
|
1144
|
-
//% minNum.defl=50
|
|
1145
|
-
//% maxNum.defl=100
|
|
1146
|
-
//% this.defl=myBall
|
|
1147
|
-
//% inlineInputMode=inline
|
|
1148
|
-
public variablePower(status: StatusBarSprite, minNum: number, maxNum: number, thisSpeed?:number): void {
|
|
1149
|
-
if(thisSpeed == undefined){thisSpeed = 100;}
|
|
1150
|
-
if(minNum < 0){minNum = 0;}
|
|
1151
|
-
if(maxNum > 100){maxNum = 100;}
|
|
1152
|
-
game.onUpdate(() => {
|
|
1153
|
-
status.value = minNum + Math.abs(Math.sin(game.runtime() / (90000*(1/thisSpeed))) * (maxNum-minNum))
|
|
1154
|
-
this.pow = status.value;
|
|
1155
|
-
this.update_crosshair();
|
|
1156
|
-
})
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
89
|
```
|
|
1164
90
|
|
|
1165
91
|
|