diff --git a/docs/courses/summer-training.md b/docs/courses/summer-training.md index 4b7d5817191..68e37a481ee 100644 --- a/docs/courses/summer-training.md +++ b/docs/courses/summer-training.md @@ -34,10 +34,10 @@ We will be hosting three **free** online trainings, leading up to a special in-p "labelClass": "orange ribbon large" },{ "name": "Micro:bit at CSTA", - "description": "Join us in Vegas on 6/16/24 for an introduction to using micro:bit in the classroom", + "description": "Join us in Vegas on 7/16/24 for an introduction to using micro:bit in the classroom", "url":"https://aka.ms/CSTA24reg", "imageUrl": "https://pxt.azureedge.net/blob/ce157b871e8d7330375d8dc8ade57d7426259ef4/static/electron-icons.icns", - "label": "In Person on 6/16/24", + "label": "In Person on 7/16/24", "labelClass": "black ribbon large" } ] diff --git a/docs/static/tutorials/bubbles/game.png b/docs/static/tutorials/bubbles/game.png new file mode 100644 index 00000000000..6218770f1d8 Binary files /dev/null and b/docs/static/tutorials/bubbles/game.png differ diff --git a/docs/static/tutorials/bubbles/io2_title.png b/docs/static/tutorials/bubbles/io2_title.png new file mode 100644 index 00000000000..c88fa1b1461 Binary files /dev/null and b/docs/static/tutorials/bubbles/io2_title.png differ diff --git a/docs/test/tutorials/bubbles.md b/docs/test/tutorials/bubbles.md index b8b0315836c..d09d8e43e14 100644 --- a/docs/test/tutorials/bubbles.md +++ b/docs/test/tutorials/bubbles.md @@ -1,170 +1,124 @@ -# Core Memories with Joy +# Bubble Stacking with Joy ### @explicitHints true ## Intro @showdialog -Are you ready to code a pizza party? +Are you ready to have an adventure with Joy and the rest of the emotions from Inside Out 2? Click **Next** to make your own game! -Follow this tutorial to create your own multiplayer experience that you can play online together with family and friends! +![Play Bubble Stacking with Joy](/static/tutorials/bubbles/io2_title.png "How many memories can you store?") -![Play Pizza Party](/static/tutorials/pizza-party/playtime.gif "You can play with up to 4 people!") - ## {2. Your First Block} -**Meet the Cast!** +**Ready to start coding?** -We've already loaded the images of each character into an array. +Let's set the scene by adding "core memories" to the game window. -This is how the program will know which image -to assign to each player. +--- -~hint What is an array?πŸ•΅πŸ½ + +- :dot circle: Open the ``||bubble: Bubble||`` category **in the toolbox** and grab
+``||bubble:create board||``
+then snap it inside the empty
+``||loops(noclick): on start||``
+block already in the workspace. --- -In computer science, an **ARRAY** is an ordered list of items. -We give this list a name, so that we can ask for items from this list later. +~hint What does that mean? 🀷🏽 + +--- -For example, the list in our program is called **characters**. -If we want to flip the first image from this list, we can add a block -like this to our program: +When giving instructions, we'll color some text to give you a better idea of what you are looking for. +For example, when we suggest the
+``||bubble:create board||``
+block, we are pointing you toward
```block -let characters: Image[] = [] -characters[0].flipX() +bubble.createBoard() ``` hint~ -```blocks -let characters: Image[] = [] - -characters = [ -pizzaassets.P1, -pizzaassets.P2, -pizzaassets.P3, -pizzaassets.P4 -] -``` - #### ~ tutorialhint ```blocks -let characters: Image[] = [] - -characters = [ -pizzaassets.P1, -pizzaassets.P2, -pizzaassets.P3, -pizzaassets.P4 -] +//@highlight +bubble.createBoard() ``` -## {3. Set the Scene} - -**Let's decide where the action happens.** - -- :tree: Open the ``||scene:Scene||`` category and drag
-``||scene:set background image to [ ]||``
-into **the end** of the
-``||loops(noclick): on start||``
-container already in the workspace. - -- :paint brush: Click the empty square in the background block and flip to the **Gallery** tab. -![Switch to the Gallery tab](/static/skillmap/assets/gallery.png " ") -then choose the first background image called **City**. - - +## {3. Check Your Screen!} -#### ~ tutorialhint +- :binoculars: Look at your project in the game window to see what your code has done. -```blocks -let characters: Image[] = [] +You should see two rows of memory bubbles lining the top of the game window. -characters = [ -pizzaassets.P1, -pizzaassets.P2, -pizzaassets.P3, -pizzaassets.P4 -] +![The game window is in the lower left corner](/static/tutorials/bubbles/game.png "Your game will automatically load in this window after every step.") -//@highlight -scene.setBackgroundImage(pizzaassets.City) -``` +## {4. Add Bubble} +**Let's add a memory bubble to aim.** -## {4. Set players} +--- -**Add Player 1** -- :suitcase: Open the ``||pizza:Pizza||`` category and drag
-``||pizza:set game for [1] player(s) with [characters]||``
-into **the end** of the
+- :dot circle: Open the ``||bubble: Bubble||`` category **in the toolbox** and grab
+``||bubble:load new bubble||``
+then snap it inside at **the end of** the
``||loops(noclick): on start||``
-container already in the workspace. +block already in the workspace. +--- -~hint Pizza category? πŸ• +~hint ⁉️ No bubbles showing? --- -Within special tutorials, you'll sometimes see custom categories that we don't offer in our normal interface. These categories are **Extensions**. +This game relies on setting the scene before you add your main bubble. If you don't see anything loaded in your game window, you may have instructions in the wrong order. -When creating custom projects or tutorials, people can craft their own blocks that others can add into their toolbox as an extension. Since we can't get to the **Extensions** gallery from a tutorial, the categories you need have been provided in the toolbox by default. +Check to see that your code looks like this: -If you want to use the ``||pizza:Pizza||`` category in another tutorial someday, make sure to grab the share link for this finished project and you'll be able to import the blocks from this tutorial into another project! +```blocks +bubble.createBoard() +//@highlight +bubble.load_bubble() +``` hint~ - - - #### ~ tutorialhint ```blocks -let characters: Image[] = [] - -characters = [ -pizzaassets.P1, -pizzaassets.P2, -pizzaassets.P3, -pizzaassets.P4 -] -scene.setBackgroundImage(pizzaassets.City) +bubble.createBoard() //@highlight -pizza.setPlayersWith (characters, 1) +bubble.load_bubble() ``` -## {5. Check Your Game!} - - -- :binoculars: Look at your project in the game window to see what your code has done. - -You should see a single sprite in the game window that looks like the first image in your array. +## {5. Gaming with Joy} -**Click on the game window and try moving your _sprite_ using the arrow keys or joypad.** +**Add your emotion!** +To do this, we'll need to add a **sprite** to the bottom of the screen. ~hint What's a sprite? πŸ’‘ @@ -174,599 +128,272 @@ In Arcade, each character or image that does something is called a **SPRITE**. Sprites have properties that you can use and change -- things like scale, position, and lifespan are all properties of sprites. -Our players will be sprites, too. +Our characters will be sprites, too. hint~ +- :paper plane: Open the ``||sprites:Sprites||`` category and drag
+``||variables(sprites):set [mySprite] to sprite [ ] of kind [Player]||``
+into the **end of** the
+``||loops(noclick): on start||``
+container already in the workspace. - - -## {6. Add more} - -**Add more players.** - -- :game: From the ``||mp:Multiplayer||`` category, drag the
-``||mp:on [thisPlayer][connected]||``
-bundle into **an empty** area of the workspace.
- -Now, when other players join, more sprites will appear in the game window. - -**Test it out by clicking the player icons to the left of the game window.** - -![Test with the player buttons to the left of the game window](/static/tutorials/pizza-party/players1.png "An image highlighting the player icons") - -πŸ“ _Note: In actual game play, each player will join in order. To simulate this, make sure to test with **Player 1** first, then **Player 2**, then **Player 3**, etc._ - - - -#### ~ tutorialhint - -```blocks -//@highlight -mp.onControllerEvent(ControllerEvent.Connected, function (thisPlayer) { - pizza.setPlayersWith(characters, mp.getPlayerProperty(thisPlayer, mp.PlayerProperty.Number)) -}) -``` - - - -## {7. Add Pizza} - -**Let the Pizza Fly!** - -- :circle: Open the ``||game:Game||`` category and drag the
-``||game: on game update every [500] ms||``
-bundle into **an empty** area of the workspace. - - -- :mouse pointer: Click the empty grey square inside the bundle to select an image for the projectile. -
Switch to the **Gallery** tab to choose the **pizza**. - +πŸ’‘ _To change sprites, click the character in the box and look under the **Gallery** tab._ #### ~ tutorialhint ```blocks +bubble.createBoard() +bubble.load_bubble() //@highlight -game.onUpdateInterval(500, function () { - projectile = sprites.createProjectileFromSide(img` - . . . . . . b b b b . . . . . . - . . . . . . b 4 4 4 b . . . . . - . . . . . . b b 4 4 4 b . . . . - . . . . . b 4 b b b 4 4 b . . . - . . . . b d 5 5 5 4 b 4 4 b . . - . . . . b 3 2 3 5 5 4 e 4 4 b . - . . . b d 2 2 2 5 7 5 4 e 4 4 e - . . . b 5 3 2 3 5 5 5 5 e e e e - . . b d 7 5 5 5 3 2 3 5 5 e e e - . . b 5 5 5 5 5 2 2 2 5 5 d e e - . b 3 2 3 5 7 5 3 2 3 5 d d e 4 - . b 2 2 2 5 5 5 5 5 5 d d e 4 . - b d 3 2 d 5 5 5 d d d 4 4 . . . - b 5 5 5 5 d d 4 4 4 4 . . . . . - 4 d d d 4 4 4 . . . . . . . . . - 4 4 4 4 . . . . . . . . . . . . - `, randint(-100, 100), randint(-100, 100)) -}) +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) ``` +## {6. Check Your Game!} -## {8. Take a look} - - -- :binoculars: Take another look at your project. - -You should see pizza flying every which way! - -~hint Why is this happening? πŸ€·πŸ½β€β™‚οΈ ---- - -Let's take a look at the blocks you just added. - ---- - -
-This **event** block triggers an action every 500 milliseconds. (That means, every half second, the code inside of this container will run.) +- :binoculars: Take a look at the game window again. +Your sprite should be in the middle of the screen. -```block -game.onUpdateInterval(500, function () { }) -``` +In the next step, we'll move it to a location that makes it look like it's aiming the bubble. ---- -
-This block launches the ** projectile** of your choosing from the side of the screen with a **velocity** that's randomly assigned each time the code runs. -```block - projectile = sprites.createProjectileFromSide(img` - . . . . . . b b b b . . . . . . - . . . . . . b 4 4 4 b . . . . . - . . . . . . b b 4 4 4 b . . . . - . . . . . b 4 b b b 4 4 b . . . - . . . . b d 5 5 5 4 b 4 4 b . . - . . . . b 3 2 3 5 5 4 e 4 4 b . - . . . b d 2 2 2 5 7 5 4 e 4 4 e - . . . b 5 3 2 3 5 5 5 5 e e e e - . . b d 7 5 5 5 3 2 3 5 5 e e e - . . b 5 5 5 5 5 2 2 2 5 5 d e e - . b 3 2 3 5 7 5 3 2 3 5 d d e 4 - . b 2 2 2 5 5 5 5 5 5 d d e 4 . - b d 3 2 d 5 5 5 d d d 4 4 . . . - b 5 5 5 5 d d 4 4 4 4 . . . . . - 4 d d d 4 4 4 . . . . . . . . . - 4 4 4 4 . . . . . . . . . . . . - `, randint(-100, 100), randint(-100, 100)) -``` +## {7. Gaming with Joy} +**Move your sprite.** -hint~ - - -~hint Tell me about events! πŸ•΅πŸΏβ€β™‚οΈ - ---- - -**EVENTS** are things that might or might not happen while the code is running. -A player might press a button, a timer might run out, or one sprite might overlap with another. - -Each of those things is an event that you can assign a special action to in Arcade. - -hint~ +Let's add a block to make sure that the top of the sprite is right below the memory bubble. -~hint What are projectiles? πŸ•΅οΈ +- :paper plane: Open the ``||sprites:Sprites||`` category and drag
+``||sprites:set [mySprite] [top] to [102]||``
+into the **end of** the
+``||loops(noclick): on start||``
+container already in the workspace. --- -In MakeCode Arcade, **PROJECTILES** are sprites that move on their own, -often in large quantities. - -Projectiles have extra properties that normal sprites don't have. -For example, they destroy themselves once they leave the screen so -the user's computer doesn't get overwhelmed. - -hint~ - - -~hint What is velocity? πŸ•΅πŸ»β€β™€οΈ +~hint Why 102? πŸ€·πŸ½β€β™€οΈ --- -**VELOCITY** is the speed that something is moving in a certain direction. - -In MakeCode, we have velocity in two directions, **vx** and **vy**. - -The field **vx** is for the velocity going side to side.
- -_Velocity in the x (horizontal) direction_ +The coordinates of our screen go from **0** at the top to **120** at the very bottom. -- A **vx** greater than 0 will send something moving right. -- A **vx** less than 0 will send something moving left. -- A **vx** of 0 will not change its position. +Since we want just a little bit of our character peeking up from below, we'll set the top of our character to **102** so it rests just below the bubble that we will be aiming. -The field **vy** is for the velocity going up and down.
- -_Velocity in the y (vertical) direction_ - -- A **vy** greater than 0 will send something moving down. -- A **vy** less than 0 will send something moving up. -- A **vy** of 0 will not change its position. - hint~ +#### ~ tutorialhint -## {9. Add points} - -**Add points when a player overlaps with a projectile.** - -- :paper plane: Open the ``||sprites:Sprites||`` category and drag the
-``||sprites:on [sprite] of kind [Player] overlaps...||`` -
bundle into **an empty** area of the workspace. - - -~hint What does this bundle do? πŸ€·πŸ½β€β™‚οΈ - ---- - -Let's take a look at the blocks you just added. - ---- - -
-This **event** block triggers an action every time one of your Player sprites overlaps one of the projectile sprites. (Whenever a character overlaps the pizza.) +```blocks +bubble.createBoard() +bubble.load_bubble() +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) +//@highlight +mySprite.top = 102 -```block -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { }) ``` ---- -
-This block deletes the pizza sprite (otherSprite) which was overlapped. It also -adds a special disintigrate effect to the image while it's happening. - -```block - sprites.destroy(otherSprite, effects.disintegrate, 100) -``` ---- +## {8. Aim the Bubble Right} -
-This block adds one point to the score of the Player that overlapped the pizza. +**Now that everything is on screen, it's time to aim your shot.** -```block - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) -``` +- :game: Open the ``||controller:Controller||`` category and drag the
+``||controller:on [right] button [repeat]||``
+bundle into **an empty area** of the workspace.
+--- -hint~ +You should be able to aim your bubble further to the right. #### ~ tutorialhint ```blocks +bubble.createBoard() +bubble.load_bubble() +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) +mySprite.top = 102 //@highlight -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { - sprites.destroy(otherSprite, effects.disintegrate, 100) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) +controller.right.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle(bubble.Choice.Right) }) ``` +## {9. Aim the Bubble Left} -## {10. Test!} - - -- :binoculars: Test your project! - -Use the multiplayer icons to test your game with each player. - -Each character should get a point when they overlap pizza. - - - - - -## {11. First to 20 Wins!} - -**First to 20 wins!** - -- :users: Open the ``||mp:Multiplayer||`` category and drag the
-``||mp:on score [20] for [thisPlayer]||`` -
bundle into **an empty** area of the workspace. - - -~hint What does this bundle do? πŸ€·πŸ½β€β™‚οΈ - ---- - -Let's take a look at the blocks you just added. - ---- - -
-This **event** block triggers an action when a player's score reaches 20. (It even has the potential to tell which player reached that score, though we won't use that feature.) - -```block -mp.onScore(20, function (thisPlayer) { }) -``` +- :mouse pointer: Right-click to **Duplicate** your
+``||controller:on [right] button [repeat]||``
+bundle, then change both **right** options to **left**.
--- -
-This block signals that the game should immediatedly end in a win. - -```block - game.gameOver(true) -``` - - -hint~ +You should now be able to aim your bubble further to the left. #### ~ tutorialhint ```blocks +bubble.createBoard() +bubble.load_bubble() +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) +mySprite.top = 102 +controller.right.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle(bubble.Choice.Right) +}) //@highlight -mp.onScore(20, function (thisPlayer) { - game.gameOver(true) +controller.left.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle(bubble.Choice.Left) }) ``` +## {10. Time to Toss} +**Time to toss!** -## {12. Shake it up!} - -**Let's shake things up!** - -Let's make things a little more competitive by allowing sprites to bump one another out of the way. - -- :paper plane: Open the ``||sprites:Sprites||`` category and drag the
-``||sprites:on sprite of kind [Player] overlaps...||`` -
bundle into **an empty** area of the workspace. - - -~hint What does this bundle do? πŸ€·πŸ½β€β™‚οΈ - ---- - -Let's take a look at the blocks you just added. - ---- - -
-This **event** block triggers an action whenever two Players (characters) overlap. - -```block -sprites.onOverlap(SpriteKind.Player, SpriteKind.Player, function (sprite, otherSprite) { }) -``` - ---- - -
-This block checks to see **if** the first player is holding down their (A) button. If so, the code inside will run. - -```block - if (mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A)) {} -``` - ---- - -
-This code makes it look like the camera is shaking around by 4 pixels for half a second. +- :game: Open the ``||controller:Controller||`` category and drag the
+``||controller:on [A] button [pressed]||``
+bundle into **an empty area** of the workspace.
-```block - scene.cameraShake(4, 500) -``` ---- - -
-This is a custom block made for this tutorial. It bumps the other sprite to the opposite side of the screen from where the first sprite is located. - -```block - pizza.bumpSprite(sprite, otherSprite) -``` - ---- - -
-This block takes a point away from the other sprite. - -```block - mp.changePlayerStateBy(mp.getPlayerBySprite(otherSprite), MultiplayerState.score, -1) +```blockconfig.local +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + bubble.tossBubble() +}) ``` - -hint~ - - #### ~ tutorialhint ```blocks -sprites.onOverlap(SpriteKind.Player, SpriteKind.Player, function (sprite, otherSprite) { - if (mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A)) { - scene.cameraShake(4, 500) - pizza.bumpSprite(sprite, otherSprite) - mp.changePlayerStateBy(mp.getPlayerBySprite(otherSprite), MultiplayerState.score, -1) - } -}) -``` -```blockconfig.local -sprites.onOverlap(SpriteKind.Player, SpriteKind.Player, function (sprite, otherSprite) { - if (mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A)) { - scene.cameraShake(4, 500) - pizza.bumpSprite(sprite, otherSprite) - mp.changePlayerStateBy(mp.getPlayerBySprite(otherSprite), MultiplayerState.score, -1) - } +//@highlight +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + bubble.tossBubble() }) ``` +## {11. Test!} +- :binoculars: Test your game. -## {13. Test!} - - -- :binoculars: Test your project with two or more players. - -As **Player 1**, try holding down the (A) button (or space bar) and running into another player. What happens? +You should be able to toss a bubble in the direction it's aimed when you press either the (A) button or the **space bar**. +Give it a try! -πŸ“ _Note: At the moment, a player can only bump someone with a higher number. We'll fix that in the next step._ +πŸ’‘ _ Notice that your bubble doesn't properly stick where it hits, yet. There's also no option to throw another bubble. We'll fix both of those things in the steps that follow._ +## {12. Need a Refill?} +**Let's load a new bubble every time we toss the old one.** +--- +- :dot circle: Open the ``||bubble: Bubble||`` category **in the toolbox** and grab
+``||bubble:load new bubble||``
+then snap it inside at **the end of** the
+``||controller(noclick):on [A] button [pressed]||``
+block already in the workspace. -## {14. Again} - -What if the other player is holding down _their_ (A) button? Let's add code that reverses the whammy. - -- :mouse pointer: Right click on the ``||logic(noclick):if||`` statement and when the dropdown menu appears, select **Duplicate**. - -- :mouse pointer: Grab the deactivated ``||logic(noclick):if||`` statement and snap it in beneath the original. - -- :mouse pointer: Swap all of the ``||variables(noclick):sprite||`` and ``||variables(noclick):otherSprite||`` variables within the second ``||logic(noclick):if||`` statement. - - -![Duplicated the if-statement and swap sprite variables](/static/tutorials/pizza-party/duplicate.gif "Duplicate the if-statement and swap the sprite variables.") - - -#### ~ tutorialhint -```blocks -sprites.onOverlap(SpriteKind.Player, SpriteKind.Player, function (sprite, otherSprite) { - if (mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A)) { - scene.cameraShake(4, 500) - pizza.bumpSprite(sprite, otherSprite) - mp.changePlayerStateBy(mp.getPlayerBySprite(otherSprite), MultiplayerState.score, -1) - } - if (mp.isButtonPressed(mp.getPlayerBySprite(otherSprite), mp.MultiplayerButton.A)) { - scene.cameraShake(4, 500) - pizza.bumpSprite(otherSprite, sprite) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, -1) - } -}) -``` ```blockconfig.local -sprites.onOverlap(SpriteKind.Player, SpriteKind.Player, function (sprite, otherSprite) { - if (mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A)) { - scene.cameraShake(4, 500) - pizza.bumpSprite(sprite, otherSprite) - mp.changePlayerStateBy(mp.getPlayerBySprite(otherSprite), MultiplayerState.score, -1) - } - if (mp.isButtonPressed(mp.getPlayerBySprite(otherSprite), mp.MultiplayerButton.A)) { - scene.cameraShake(4, 500) - pizza.bumpSprite(otherSprite, sprite) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, -1) - } +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + bubble.tossBubble() + bubble.load_bubble() }) ``` - -## {15. NOOP} - -The game won't be fun if everyone holds (A) the whole time! Let's make it so players only get a point if they're **not** holding the (A) button. - -- :binoculars: Find the **Player/Projectile** ``||sprites(noclick):on overlap||`` event that's **already in your workspace.** +#### ~ tutorialhint ```blocks -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { - sprites.destroy(otherSprite, effects.disintegrate, 100) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) + +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + bubble.tossBubble() + //@highlight + bubble.load_bubble() }) ``` -- :random: from the``||logic:Logic||`` category, grab an empty
-``||logic:if then||`` statement and snap it in **above** the
-``||sprites(noclick):destroy [otherSprite]...||`` block in your workspace. -- :random: from the``||logic:Logic||`` category, grab
-``||logic:not < >||`` and snap it into the
-``||logic(noclick):if then||`` statement to replace ``||logic(noclick):||`` +## {13. Connecting Bubbles} +**Time to make the memories stick!** +We want the bubbles to stick whenever they connect to the top wall or to another bubble. -#### ~ tutorialhint +--- -```blocks -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { - if (!(mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A))) { } - sprites.destroy(otherSprite, effects.disintegrate, 100) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) -}) -``` +- :tree: Open the ``||scene: Scene||`` category and grab the
+``||scene:on [sprite] of kind [Bubble] ...||``
+bundle and drop it into **an empty** area of the workspace.
```blockconfig.local -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { }) -``` - - - - -## {16. NOOP Cont.} - +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + bubble.tossBubble() + bubble.load_bubble() +}) -- :mouse pointer: Right click on the -```block -let sprite: Sprite = null -mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A ``` -block already in the workspace and choose **Duplicate**. -Drag the copy into the empty area inside
``||logic(noclick):not < > ||``. - - -- :mouse pointer: Drag both of the blocks that were connected below the empty
-``||logic(noclick):if||`` statement and move them inside. #### ~ tutorialhint ```blocks -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { - if (!(mp.isButtonPressed(mp.getPlayerBySprite(sprite), mp.MultiplayerButton.A))) { - sprites.destroy(otherSprite, effects.disintegrate, 100) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) - } +//@highlight +scene.onHitWall(SpriteKind.Bubble, function (sprite, location) { + bubble.stick_to_wall(sprite, location) }) ``` -## {17. Ready, Set, Go} - -Make sure everyone is prepared to play by adding a holding screen with sound effects at the beginning of the game. - -- :circle: From the ``||game:Game||`` category, drag
-``||game:splash ["Press (A) when everyone is"]...||`` into the end of the
-``||loops(noclick): on start||``
-container already in the workspace. - - -- :headphones: From the ``||music:Music||`` category, drag
-``||music:play [song ] [until done]||`` into the end of the
-``||loops(noclick): on start||``
-container already in the workspace. - -- :mouse pointer: Click the empty rectagle in the
-``||music(noclick):play song...||`` block and switch to **My Assets** to choose the **countdown**. - - - -#### ~ tutorialhint - -```blocks -let characters = [ -pizzaassets.P1, -pizzaassets.P2, -pizzaassets.P3, -pizzaassets.P4 -] -scene.setBackgroundImage(assets.image`cityscape`) -pizza.setPlayersWith (characters, 1) -game.splash("Press (A) when everyone is", "ready to start the game") - -music.play(music.createSong(assets.song`countdown`), music.PlaybackMode.UntilDone) - - -``` +## {18. Test It} +- :binoculars: **Time to play your finished game!** +Aim your bubble using the arrow keys, then toss with the (A) button or **space bar**. +Can you clear the board fast enough to get a bonus? -## {18. Test It} +~hint Want to add more? 🫧 +--- -- :binoculars: Test your final experience. +Feel like going above and beyond? There are enough blocks in the toolbox to make these customizations: -You should be able to rack up points as you grab pizza until you press the (A) button, then the pizza should fly right by you. +- Add music in the background +- Add a background color to the board +- Win the game by reaching a score instead of clearing the board +- Change your character with each new ball -**For extra fun, login so you can play online with friends!** +hint~ @@ -775,74 +402,33 @@ You should be able to rack up points as you grab pizza until you press the (A) b ## {Finale} -**πŸ• Cowabunga πŸ•** +**πŸ₯³ Great Job πŸ₯³** -You have finished your multiplayer experience! +You have finished the tutorial! -When you're ready, sign-in, then select **Done** to start an online multiplayer session with up to three friends. +When you're ready, click **Done** to share your game with family and friends! -**Who will be the first to score 20 points?** ```blockconfig.global -game.onUpdateInterval(500, function () { - projectile = sprites.createProjectileFromSide(img` - . . . . . . b b b b . . . . . . - . . . . . . b 4 4 4 b . . . . . - . . . . . . b b 4 4 4 b . . . . - . . . . . b 4 b b b 4 4 b . . . - . . . . b d 5 5 5 4 b 4 4 b . . - . . . . b 3 2 3 5 5 4 e 4 4 b . - . . . b d 2 2 2 5 7 5 4 e 4 4 e - . . . b 5 3 2 3 5 5 5 5 e e e e - . . b d 7 5 5 5 3 2 3 5 5 e e e - . . b 5 5 5 5 5 2 2 2 5 5 d e e - . b 3 2 3 5 7 5 3 2 3 5 d d e 4 - . b 2 2 2 5 5 5 5 5 5 d d e 4 . - b d 3 2 d 5 5 5 d d d 4 4 . . . - b 5 5 5 5 d d 4 4 4 4 . . . . . - 4 d d d 4 4 4 . . . . . . . . . - 4 4 4 4 . . . . . . . . . . . . - `, randint(-100, 100), randint(-100, 100)) -}) let characters: Image[] = [] -pizza.setPlayersWith(characters, 1) - -mp.onControllerEvent(ControllerEvent.Connected, function (thisPlayer) { - pizza.setPlayersWith(characters, mp.getPlayerProperty(thisPlayer, mp.PlayerProperty.Number)) -}) - -sprites.onOverlap(SpriteKind.Player, SpriteKind.Projectile, function (sprite, otherSprite) { - sprites.destroy(otherSprite, effects.disintegrate, 100) - mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) +mySprite.top = 102 +controller.right.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle(bubble.Choice.Right) }) +scene.setBackgroundColor(14) -mp.changePlayerStateBy(mp.getPlayerBySprite(sprite), MultiplayerState.score, 1) - -mp.onScore(20, function (thisPlayer) { - game.gameOver(true) +music.play(music.createSong(hex`0096000408080106001c00010a006400f401640000040000000000000000000000000000000002d80000000200011608000a00011110001200011618001a00011120002200011628002a00011130003200011638003a00011140004200011848004a00011150005200011858005a00011160006200011868006a00011170007200011878007a00011180008200011288008a00010d90009200011298009a00010da000a2000112a800aa00010db000b2000112b800ba00010dc000c2000118c400c6000118cc00ce000118d000d2000118d800da00011ddc00de00011de400e600011de800ea00011df000f2000120f400f6000120f800fa000120fc00fe000120`), music.PlaybackMode.LoopingInBackground) +scene.onHitWall(SpriteKind.Bubble, function (sprite, location) { + bubble.stick_to_wall(sprite, location) }) - -game.splash("Press (A) when everyone is", "ready to start the game") - -``` - - - - -```template -let characters: Image[] = [] - -characters = [ -pizzaassets.P1, -pizzaassets.P2, -pizzaassets.P3, -pizzaassets.P4 -] - +mySprite.setImage(io2_images.fear) +characters = [io2_images.joy, io2_images.anger, io2_images.envy, io2_images.fear] +mySprite.setImage(characters[randint(0, characters.length - 1)]) ``` @@ -850,7 +436,36 @@ pizzaassets.P4 ```ghost -scene.setBackgroundColor(1) +let characters: Image[] = [] +scene.onHitWall(SpriteKind.Bubble, function (sprite, location) { + bubble.stick_to_wall(sprite, location) + music.play(music.melodyPlayable(music.baDing), music.PlaybackMode.UntilDone) +}) +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + bubble.tossBubble() + bubble.load_bubble() +}) +controller.right.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle(bubble.Choice.Right) +}) +info.onScore(100, function () { + game.setGameOverEffect(true, effects.confetti) + game.setGameOverPlayable(true, music.melodyPlayable(music.powerUp), false) + game.setGameOverMessage(true, "GAME OVER!") +}) +controller.left.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle(bubble.Choice.Left) +}) +scene.setBackgroundColor(14) +music.play(music.createSong(hex`0096000408080106001c00010a006400f401640000040000000000000000000000000000000002d80000000200011608000a00011110001200011618001a00011120002200011628002a00011130003200011638003a00011140004200011848004a00011150005200011858005a00011160006200011868006a00011170007200011878007a00011180008200011288008a00010d90009200011298009a00010da000a2000112a800aa00010db000b2000112b800ba00010dc000c2000118c400c6000118cc00ce000118d000d2000118d800da00011ddc00de00011de400e600011de800ea00011df000f2000120f400f6000120f800fa000120fc00fe000120`), music.PlaybackMode.LoopingInBackground) +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) +mySprite.top = 102 +mySprite.startEffect(effects.fountain) +bubble.createBoard() +bubble.load_bubble() +mySprite.setImage(io2_images.fear) +characters = [io2_images.joy, io2_images.anger, io2_images.envy, io2_images.fear] +mySprite.setImage(characters[randint(0, characters.length - 1)]) ``` @@ -858,140 +473,31 @@ scene.setBackgroundColor(1) ```package multiplayer -pizza-assets=github:kiki-lee/pizza-assets#v0.0.4 +io2_images=github:kiki-lee/io2_images#v0.0.1 +bubble=github:kiki-lee/bubble_ext#v0.1.0 ``` -```customts - -//% color=#b79900 icon="\uf1ce" -namespace pizza { - - // Make sure not to remove later player when earlier player tested - export let playersConnected=0; - - //% blockId=set_players - //% block="set game for $num player(s) with $list" - //% num.defl=1 - //% list.shadow=variables_get - //% list.defl=characters - - export function setPlayersWith(list: Image[], num: number) { - if(num >= pizza.playersConnected){ - pizza.playersConnected = num; - sprites.destroyAllSpritesOfKind(SpriteKind.Player) - let xloc = [ - 40, - 120, - 40, - 120 - ] - let yloc = [ - 30, - 30, - 90, - 90 - ] - for (let index = 0; index <= num - 1; index++) { - mp.setPlayerSprite(mp.getPlayerByIndex(index), sprites.create(list[index], SpriteKind.Player)) - mp.getPlayerSprite(mp.getPlayerByIndex(index)).setStayInScreen(true) - mp.getPlayerSprite(mp.getPlayerByIndex(index)).setPosition(xloc.shift(), yloc.shift()) - mp.getPlayerSprite(mp.getPlayerByIndex(index)).z = 1000 - mp.moveWithButtons(mp.getPlayerByIndex(index)) - } - } - } - - //% blockId=bump_sprite - //% block="$thisSprite bump $thatSprite" - //% thisSprite.shadow=variables_get - //% thisSprite.defl=sprite - //% thatSprite.shadow=variables_get - //% thatSprite.defl=otherSprite - export function bumpSprite(thisSprite: Sprite, thatSprite: Sprite) { - thatSprite.setPosition((thisSprite.x + 80) % 160, thisSprite.y) - } - -} - -namespace logic{ - /** - * this just holds code - */ - //% block="check if A button pressed" weight=300 - //% handlerStatement=1 - export function wrap1(handler: () => void) { - handler(); - } -} - - -//% color=#6d5ba4 icon="\uf0f2" -namespace bundles{ - /** - * this just holds code - */ - //% block="check if A button pressed" weight=300 - //% handlerStatement=1 - export function wrap1(handler: () => void) { - handler(); - } - - /** - * this just holds code - */ - //% block="create finish line" weight=300 - //% handlerStatement=1 - export function wrap2(handler: () => void) { - handler(); - } - - /** - * this just holds code - */ - //% block="create players" weight=300 - //% handlerStatement=1 - export function wrap3(handler: () => void) { - handler(); - } - -} - -``` - ```simtheme { "palette": [ "#000000", "#FFFFFF", - "#FF2121", - "#DFDDDE", - "#FF8135", - "#FFF609", - "#8E2EC4", - "#408325", - "#003FAD", - "#87F2FF", - "#EBF8F9", + "#E40C0C", + "#FF8FDB", + "#FFF700", + "#3AF2B5", + "#0B9EF9", + "#56E3F5", + "#C4C3F4", + "#E0E6E6", + "#729280", "#A4839F", - "#F9F6E1", + "#5C406c", "#E5CDC4", - "#91463d", + "#8A0A0A", "#000000" ] } ``` - -```assetjson -{ - "assets.json": "", - "images.g.jres": "{\n \"EM~exxT809P9NBm_MJip\": {\n \"data\": \"003c000408010204001c00100500640000041e000004000000000000000000000000000a000004120000000400012408000c00012410001400012407001c00020a006400f401640000040000000000000000000000000000000003060018001c000124\",\n \"mimeType\": \"application/mkcd-song\",\n \"displayName\": \"countdown\",\n \"namespace\": \"mySongs.\"\n },\n \"*\": {\n \"mimeType\": \"image/x-mkcd-f4\",\n \"dataEncoding\": \"base64\",\n \"namespace\": \"myImages\"\n }\n}", - "images.g.ts": "// Auto-generated code. Do not edit.\nnamespace myImages {\n\n helpers._registerFactory(\"image\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n\n }\n return null;\n })\n\n helpers._registerFactory(\"animation\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n\n }\n return null;\n })\n\n helpers._registerFactory(\"song\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n case \"EM~exxT809P9NBm_MJip\":\n case \"countdown\":return hex`003c000408010204001c00100500640000041e000004000000000000000000000000000a000004120000000400012408000c00012410001400012407001c00020a006400f401640000040000000000000000000000000000000003060018001c000124`;\n }\n return null;\n })\n\n}\n// Auto-generated code. Do not edit.\n", - "main.blocks": "PlayerProjectileFoodEnemyTextStatusBarBallBoothMouseCrosshairMoonscorelifelocationsprojectilecharactersindexmySpritemyBallx-locy-loclistnumber", - "main.ts": "\n", - "pxt.json": "{\n \"name\": \"TMNT_Music\",\n \"description\": \"\",\n \"dependencies\": {\n \"device\": \"*\"\n },\n \"files\": [\n \"main.blocks\",\n \"main.ts\",\n \"assets.json\",\n \"images.g.jres\",\n \"images.g.ts\",\n \"tilemap.g.jres\",\n \"tilemap.g.ts\"\n ],\n \"targetVersions\": {\n \"branch\": \"v1.12.30\",\n \"tag\": \"v1.12.30\",\n \"commits\": \"https://github.com/microsoft/pxt-arcade/commits/33228b1cc7e1bea3f728c26a6047bdef35fd2c09\",\n \"target\": \"1.12.30\",\n \"pxt\": \"8.5.41\"\n },\n \"preferredEditor\": \"tsprj\",\n \"palette\": [\n \"#000000\",\n \"#FFFFFF\",\n \"#FF2121\",\n \"#DFDDDE\",\n \"#FF8135\",\n \"#FFF609\",\n \"#8E2EC4\",\n \"#408325\",\n \"#003FAD\",\n \"#87F2FF\",\n \"#EBF8F9\",\n \"#A4839F\",\n \"#F9F6E1\",\n \"#E5CDC4\",\n \"#91463d\",\n \"#000000\"\n ]\n}\n", - "tilemap.g.jres": "{\n \"transparency16\": {\n \"data\": \"hwQQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true\n },\n \"*\": {\n \"mimeType\": \"image/x-mkcd-f4\",\n \"dataEncoding\": \"base64\",\n \"namespace\": \"myTiles\"\n }\n}", - "tilemap.g.ts": "// Auto-generated code. Do not edit.\nnamespace myTiles {\n //% fixedInstance jres blockIdentity=images._tile\n export const transparency16 = image.ofBuffer(hex``);\n\n helpers._registerFactory(\"tile\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n case \"transparency16\":return transparency16;\n }\n return null;\n })\n\n}\n// Auto-generated code. Do not edit.\n" -} -``` diff --git a/docs/test/tutorials/spy/chase-the-pizza.md b/docs/test/tutorials/spy/chase-the-pizza.md new file mode 100644 index 00000000000..3fd1363edd7 --- /dev/null +++ b/docs/test/tutorials/spy/chase-the-pizza.md @@ -0,0 +1,306 @@ +# Chase the Pizza +### @explicitHints true + +## {Introduction @unplugged} + +![Game animation](/static/tutorials/chase-the-pizza/chasing.gif) + +In this tutorial you will create a game with 2 sprites, a ``||sprites:Player||`` sprite and a ``||sprites:Food||`` sprite. The goal of the game is to eat as much pizza as you can before the time runs out! Each time your player catches the pizza, you gain points and the countdown is restarted. + +## {Step 2} + +First, **set the background color**. + + +~hint How do I do that? 🀷🏽 + +--- + +You can make this happen in two ways. + + +- :tree: Open the
+``||scene:Scene||``
+toolbox drawer and drag
+``||scene:set background color to [color]||``
+into **the first line** of your program. + + +- :keyboard: Type +```spy +scene.setBackgroundColor(0) +``` +directly into the first line of your program. + +πŸ’‘ _Feel free to choose your own color if you don't like the swatch in the block. You can replace the number **0** with anything between **0 & 15**._ + + +hint~ + + + +--- + +###### _Click the button that says "**➑ Next**" to go to the next step of the tutorial._ + + +#### ~ tutorialhint + +```spy +scene.setBackgroundColor(0) +``` + +## {Step 3} + +**Time to create a sprite!** + +Set your sprite **image** and **kind** in the second line of the program. + + + +~hint How do I do that? 🀷🏽 + +--- + +You can make this happen in two ways. + + +- :paper plane: Open the
+``||sprites:Sprites||``
+toolbox drawer and drag
+``||sprites:sprite [img] of kind [kind]||``
+into **the second line** of your program. + + +- :keyboard: Type +```spy +let mySprite = sprites.create(img` + 3 +`, SpriteKind.player) +``` +directly into the second line of your program. + +πŸ’‘ _We will choose our player sprite in the next step._ + + +hint~ + + + +#### ~ tutorialhint +```spy +scene.setBackgroundColor(7) +mySprite = sprites.create(img`. . +. .`, SpriteKind.Player) +``` + +## {Step 3} + +Draw your ``||sprites:Player||`` character by using the image editor for ``||variables(sprites):set mySprite||``. +Use the color palette and design tools to draw an image on the canvas. Click **Done** when you are finished. + +![Image editor](/static/tutorials/chase-the-pizza/image-editor-js.gif) + +## {Step 4} + +Put in the code to ``||controller:move mySprite||`` with the ``||controller:controller||``. + +#### ~ tutorialhint +```spy +scene.setBackgroundColor(7) +let mySprite = sprites.create(img` +. . . . . 5 5 5 5 5 5 . . . . . +. . . 5 5 5 5 5 5 5 5 5 5 . . . +. . 5 5 5 5 5 5 5 5 5 5 5 5 . . +. 5 5 5 5 5 5 5 5 5 5 5 5 5 5 . +. 5 5 5 f f 5 5 5 5 f f 5 5 5 . +5 5 5 5 f f 5 5 5 5 f f 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 f 5 5 5 5 5 5 5 5 5 5 f 5 5 +5 5 5 f 5 5 5 5 5 5 5 5 f 5 5 5 +. 5 5 5 f 5 5 5 5 5 5 f 5 5 5 . +. 5 5 5 5 f f f f f f 5 5 5 5 . +. . 5 5 5 5 5 5 5 5 5 5 5 5 . . +. . . 5 5 5 5 5 5 5 5 5 5 . . . +. . . . . 5 5 5 5 5 5 . . . . . +`, SpriteKind.Player) +controller.moveSprite(mySprite) +``` + +## {Step 5} + +Just like with ``||variables(noclick):mySprite||``, ``||create a sprite||`` again and set it to the a variable named +``||variables(noclick):pizza||``. This time, set the ``||sprites:sprite kind||`` to ``||sprites:food||``. This will +be the **pizza** sprite in our game. + +#### ~ tutorialhint +```spy +scene.setBackgroundColor(7) +let mySprite = sprites.create(img` +. . . . . 5 5 5 5 5 5 . . . . . +. . . 5 5 5 5 5 5 5 5 5 5 . . . +. . 5 5 5 5 5 5 5 5 5 5 5 5 . . +. 5 5 5 5 5 5 5 5 5 5 5 5 5 5 . +. 5 5 5 f f 5 5 5 5 f f 5 5 5 . +5 5 5 5 f f 5 5 5 5 f f 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 f 5 5 5 5 5 5 5 5 5 5 f 5 5 +5 5 5 f 5 5 5 5 5 5 5 5 f 5 5 5 +. 5 5 5 f 5 5 5 5 5 5 f 5 5 5 . +. 5 5 5 5 f f f f f f 5 5 5 5 . +. . 5 5 5 5 5 5 5 5 5 5 5 5 . . +. . . 5 5 5 5 5 5 5 5 5 5 . . . +. . . . . 5 5 5 5 5 5 . . . . . +`, SpriteKind.Player) +controller.moveSprite(mySprite) +let pizza = sprites.create(img` +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +. . . . . . . . . . . . . . . . +`, SpriteKind.Food) +``` + +## {Step 6} + +Use the image editor for ``||variables(noclick):pizza||`` and then select the **Gallery** view. Scroll to find the image of a small pizza (or any other image you like!) and select it to load into the image editor. + +![Image gallery](/static/tutorials/chase-the-pizza/image-gallery-spy.gif) + +## {Step 7 @resetDiff} + +Add a ``||sprites:on overlap||`` event to your code. Set the ``||sprites:sprite kind||`` that cooresponds to +``otherSprite`` as ``||sprites:Food||``. + +#### ~ tutorialhint +```spy +sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) { + +}) +``` + +## {Step 8} + +When our ``||sprites:Player||`` overlaps with the ``||variables(noclick):pizza||`` sprite, let’s add a point to our game score. Pun in the code to ``||info:change score by||`` 1`. + +#### ~ tutorialhint +```spy +sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) { + info.changeScoreBy(1) +}) +``` + +## {Step 9} + +Let’s set the position for ``||variables(noclick):pizza||`` to random locations around the screen. We use +``otherSprite`` and ``||sprites:set its position||``. Righy now, just use `0` for both `x` and `y`. + +#### ~ tutorialhint +```spy +sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) { + info.changeScoreBy(1) + otherSprite.setPosition(0, 0) +}) +``` + +## {Step 10} + +Put in code for the `x` and `y` positions of ``otherSprite`` to use a ``||math:pick a random||`` number. +The Arcade game screen is `160` pixels wide, and `120` pixels high. In the first ``||math:pick random||`` +in the `x` coordinate of the ``||sprites:otherSprite position||``, change the maximum value from **0** to +**160**. In the second ``||math:pick random||`` in the ``y`` coordinate, change the maximum value from +**0** to **120**. + +#### ~ tutorialhint +```spy +sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) { + info.changeScoreBy(1) + otherSprite.setPosition(randint(0, 160), randint(0, 120)) +}) +``` + +## {Step 11} + +Let’s restart our countdown each time. Add the code to ``||info:start countdown||`` and make the countdown +count be `10`. + +```spy +sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) { + info.changeScoreBy(1) + otherSprite.setPosition(randint(0, 160), randint(0, 120)) + info.startCountdown(10) +}) +``` + +## {Complete @resetDiff} + +Congratulations, you have completed your game! Use the Game Simulator to play by moving your ``||sprites:Player||`` around the screen to try and eat as much pizza as possible before the time runs out. What’s your high score? + +#### ~ tutorialhint +```spy +scene.setBackgroundColor(7) +let mySprite = sprites.create(img` +. . . . . 5 5 5 5 5 5 . . . . . +. . . 5 5 5 5 5 5 5 5 5 5 . . . +. . 5 5 5 5 5 5 5 5 5 5 5 5 . . +. 5 5 5 5 5 5 5 5 5 5 5 5 5 5 . +. 5 5 5 f f 5 5 5 5 f f 5 5 5 . +5 5 5 5 f f 5 5 5 5 f f 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +5 5 f 5 5 5 5 5 5 5 5 5 5 f 5 5 +5 5 5 f 5 5 5 5 5 5 5 5 f 5 5 5 +. 5 5 5 f 5 5 5 5 5 5 f 5 5 5 . +. 5 5 5 5 f f f f f f 5 5 5 5 . +. . 5 5 5 5 5 5 5 5 5 5 5 5 . . +. . . 5 5 5 5 5 5 5 5 5 5 . . . +. . . . . 5 5 5 5 5 5 . . . . . +`, SpriteKind.Player) +controller.moveSprite(mySprite) +let pizza = sprites.create(img` +. . . . . . b b b b . . . . . . +. . . . . . b 4 4 4 b . . . . . +. . . . . . b b 4 4 4 b . . . . +. . . . . b 4 b b b 4 4 b . . . +. . . . b d 5 5 5 4 b 4 4 b . . +. . . . b 3 2 3 5 5 4 e 4 4 b . +. . . b d 2 2 2 5 7 5 4 e 4 4 e +. . . b 5 3 2 3 5 5 5 5 e e e e +. . b d 7 5 5 5 3 2 3 5 5 e e e +. . b 5 5 5 5 5 2 2 2 5 5 d e e +. b 3 2 3 5 7 5 3 2 3 5 d d e 4 +. b 2 2 2 5 5 5 5 5 5 d d e 4 . +b d 3 2 d 5 5 5 d d d 4 4 . . . +b 5 5 5 5 d d 4 4 4 4 . . . . . +4 d d d 4 4 4 . . . . . . . . . +4 4 4 4 . . . . . . . . . . . . +`, SpriteKind.Food) + +sprites.onOverlap(SpriteKind.Player, SpriteKind.Food, function (sprite, otherSprite) { + info.changeScoreBy(1) + otherSprite.setPosition(randint(0, 160), randint(0, 120)) + info.startCountdown(10) +}) +``` + + +```package +chase-the-pizza=github:kiki-lee/chase-the-pizza +``` \ No newline at end of file diff --git a/docs/tutorials/bubbles.md b/docs/tutorials/bubbles.md new file mode 100644 index 00000000000..1ba45d8f496 --- /dev/null +++ b/docs/tutorials/bubbles.md @@ -0,0 +1,218 @@ +# Bubble Stacking with Joy +### @explicitHints true + + +## Intro @showdialog + +Are you ready to have an adventure with Joy and the rest of the emotions from Inside Out 2? Click **Next** to make your own game! + + +![Play Bubble Stacking with Joy](/static/tutorials/bubbles/io2_title.png "How many memories can you store?") + + + + + +## {2. Your First Block} + + +## {2. Your First Block} + +**Add your emotion!** + +To do this, we'll need to add a **sprite** to the bottom of the screen. + +~hint What's a sprite? πŸ’‘ + +--- + +In Arcade, each character or image that does something is called a **SPRITE**. + +Sprites have properties that you can use and change -- things like scale, position, and lifespan are all properties of sprites. + +Our players will be sprites, too. + +hint~ + +- :paper plane: Open the ``||sprites:Sprites||`` category and drag
+``||variables(sprites):set [mySprite] to sprite [ ] of kind [Player]||``
+into **the empty**
+``||loops(noclick): on start||``
+container already in the workspace. + + +~hint Pizza category? πŸ• + +--- + +Within special tutorials, you'll sometimes see custom categories that we don't offer in our normal interface. These categories are **Extensions**. + +When creating custom projects or tutorials, people can craft their own blocks that others can add into their toolbox as an extension. Since we can't get to the **Extensions** gallery from a tutorial, the categories you need have been provided in the toolbox by default. + +If you want to use the ``||bubble:Bubble||`` category in another tutorial someday, make sure to grab the share link for this finished project and you'll be able to import the blocks from this tutorial into another project! + +hint~ + + + + + +#### ~ tutorialhint + +```blocks +//@highlight +let mySprite = sprites.create(io2_images.joy, SpriteKind.Player) +``` + + + +## {5. Check Your Game!} + + +- :binoculars: Look at your project in the game window to see what your code has done. + +You should see a single sprite in the game window that looks like the first image in your array. + +**Click on the game window and try moving your _sprite_ using the arrow keys or joypad.** + + + + + + + + + + +## {13. Test!} + + +- :binoculars: Test your project with two or more players. + +As **Player 1**, try holding down the (A) button (or space bar) and running into another player. What happens? + + +πŸ“ _Note: At the moment, a player can only bump someone with a higher number. We'll fix that in the next step._ + + + + + +## {18. Test It} + + +- :binoculars: Test your final experience. + +You should be able to rack up points as you grab pizza until you press the (A) button, then the pizza should fly right by you. + +**For extra fun, login so you can play online with friends!** + + + + + + +## {Finale} + +**πŸ• Cowabunga πŸ•** + +You have finished your multiplayer experience! + +When you're ready, sign-in, then select **Done** to start an online multiplayer session with up to three friends. + +**Who will be the first to score 20 points?** + + + + +```blockconfig.global +let mySprite = sprites.create(img`.`, SpriteKind.Player) +mySprite.top = 102 +``` + + + +```ghost + +scene.onHitWall(SpriteKind.Bubble, function (sprite, location) { + bubble.stick_to_wall(sprite, location) + music.play(music.melodyPlayable(music.baDing), music.PlaybackMode.UntilDone) +}) +controller.A.onEvent(ControllerButtonEvent.Pressed, function () { + console.log("Calling Toss Ball") + bubble.tossBubble() + console.log("Calling load_bubble") + bubble.load_bubble() +}) +controller.right.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle_right() +}) +info.onScore(100, function () { + game.setGameOverEffect(true, effects.confetti) + game.setGameOverPlayable(true, music.melodyPlayable(music.powerUp), false) + game.setGameOverMessage(true, "GAME OVER!") +}) +controller.left.onEvent(ControllerButtonEvent.Repeated, function () { + bubble.tilt_angle_left() +}) +scene.setBackgroundColor(14) +music.play(music.createSong(hex`0078000408010105001c000f0a006400f4010a00000400000000000000000000000000000000021a0000000400011d04000800011e08000c00021e2010001400021d1e`), music.PlaybackMode.InBackground) +let mySprite = sprites.create(assets.image`myImage`, SpriteKind.Player) +mySprite.top = 102 +mySprite.startEffect(effects.fountain) +bubble.createBoard() +bubble.load_bubble() + + +``` + + + +```package +multiplayer +io2_images=github:kiki-lee/io2_images#v0.0.1 +bubble=github:kiki-lee/bubble_ext#v0.0.12 +``` + + +```simtheme +{ + "palette": [ + "#000000", + "#FFFFFF", + "#E40C0C", + "#FF8FDB", + "#FFF700", + "#3AF2B5", + "#0B9EF9", + "#56E3F5", + "#C4C3F4", + "#E0E6E6", + "#729280", + "#A4839F", + "#5C406c", + "#E5CDC4", + "#8A0A0A", + "#000000" + ] +} +``` + + +```assetjson + +{ + "README.md": " \n\n\n> Open this page at [https://kiki-lee.github.io/bubble_ext/](https://kiki-lee.github.io/bubble_ext/)\n\n## Use as Extension\n\nThis repository can be added as an **extension** in MakeCode.\n\n* open [https://arcade.makecode.com/](https://arcade.makecode.com/)\n* click on **New Project**\n* click on **Extensions** under the gearwheel menu\n* search for **https://github.com/kiki-lee/bubble_ext** and import\n\n## Edit this project ![Build status badge](https://github.com/kiki-lee/bubble_ext/workflows/MakeCode/badge.svg)\n\nTo edit this repository in MakeCode.\n\n* open [https://arcade.makecode.com/](https://arcade.makecode.com/)\n* click on **Import** then click on **Import URL**\n* paste **https://github.com/kiki-lee/bubble_ext** and click import\n\n## Blocks preview\n\nThis image shows the blocks code from the last commit in master.\nThis image may take a few minutes to refresh.\n\n![A rendered view of the blocks](https://github.com/kiki-lee/bubble_ext/raw/master/.github/makecode/blocks.png)\n\n#### Metadata (used for search, rendering)\n\n* for PXT/arcade\n\n", + "assets.json": "", + "bubble.ts": "namespace SpriteKind {\n //% isKind\n export const Bubbles = SpriteKind.create()\n}\ntiles.setCurrentTilemap(tilemap` `)\n\n\n//% color=#32c4de icon=\"\\uf192\"\nnamespace bubble {\n\n let codingThisBall = 0\n export let list: Image[] = []\n let burstBubble: Sprite = null\n let ShotNumber = 0\n let bonus = 0\n let totalBallsOut = 0\n let foundRoot = false\n let currentLocation: tiles.Location = null\n let locationsToClear: tiles.Location[] = []\n let lookingForTile: Image = null\n let clearCount = 0\n let locationQueue: tiles.Location[] = []\n let alreadyVisited: Image = null\n let aimingAngle = 0\n let myBall: Sprite = null\n\n\n /**\n * Appear to toss the bubble\n */\n //% blockId=tossBubble \n //% block=\"toss bubble\"\n //% help=bubble/toss_bubble\n export function tossBubble() {\n if (!(stateTransitions.stateIs(\"aiming\"))) {\n return\n }\n stateTransitions.changeState(\"throwing\")\n spriteutils.setVelocityAtAngle(myBall, spriteutils.degreesToRadians(aimingAngle), 300)\n sprites.setDataNumber(myBall, \"vx\", myBall.vx)\n sprites.setDataNumber(myBall, \"vy\", myBall.vy)\n }\n\n\n\n function maybeAddToQueue(column: number, row: number) {\n if (alreadyVisited.getPixel(column, row) == 0) {\n locationQueue.push(tiles.getTileLocation(column, row))\n alreadyVisited.setPixel(column, row, 15)\n }\n }\n\n function checkForMatches(thisBall: Sprite) {\n if (tiles.tileAtLocationEquals(myBall.tilemapLocation(), assets.tile`myTile0`)) {\n game.gameOver(false)\n }\n sprites.destroy(thisBall)\n tiles.setTileAt(thisBall.tilemapLocation(), thisBall.image)\n tiles.setWallAt(thisBall.tilemapLocation(), true)\n alreadyVisited = image.create(20, 15)\n clearCount = 0\n lookingForTile = thisBall.image\n locationQueue = []\n locationsToClear = []\n maybeAddToQueue(thisBall.tilemapLocation().column, thisBall.tilemapLocation().row)\n alreadyVisited.drawRect(0, 0, 20, 15, 15)\n stateTransitions.changeState(\"scoring\")\n timer.background(function () {\n while (locationQueue.length > 0) {\n currentLocation = locationQueue.removeAt(0)\n if (tileUtil.tileIs(tileUtil.currentTilemap(), currentLocation, lookingForTile)) {\n locationsToClear.push(currentLocation)\n maybeAddToQueue(currentLocation.column + 1, currentLocation.row + 0)\n maybeAddToQueue(currentLocation.column - 1, currentLocation.row + 0)\n maybeAddToQueue(currentLocation.column + 0, currentLocation.row + 1)\n maybeAddToQueue(currentLocation.column + 0, currentLocation.row - 1)\n }\n }\n if (locationsToClear.length >= 3) {\n pause(100)\n for (let value of locationsToClear) {\n clearLocation(value.column, value.row)\n info.changeScoreBy(1)\n }\n info.changeScoreBy(Math.floor(1.5 ** locationsToClear.length) - 3)\n alreadyVisited.fill(0)\n alreadyVisited.drawRect(0, 0, 20, 15, 15)\n for (let indexX = 0; indexX <= 19; indexX++) {\n for (let indexY = 0; indexY <= 14; indexY++) {\n maybeAddToQueue(indexX, indexY)\n if (locationQueue.length > 0) {\n locationsToClear = []\n while (locationQueue.length > 0) {\n currentLocation = locationQueue.removeAt(0)\n if (tiles.tileAtLocationIsWall(currentLocation)) {\n locationsToClear.push(currentLocation)\n maybeAddToQueue(currentLocation.column + 1, currentLocation.row + 0)\n maybeAddToQueue(currentLocation.column - 1, currentLocation.row + 0)\n maybeAddToQueue(currentLocation.column + 0, currentLocation.row + 1)\n maybeAddToQueue(currentLocation.column + 0, currentLocation.row - 1)\n }\n }\n foundRoot = false\n for (let value2 of locationsToClear) {\n if (value2.row == 1) {\n foundRoot = true\n break;\n }\n }\n if (!(foundRoot)) {\n for (let value3 of locationsToClear) {\n clearLocation(value3.column, value3.row)\n }\n }\n }\n }\n }\n }\n totalBallsOut = tiles.getTilesByType(assets.tile`myTile1`).length + (tiles.getTilesByType(assets.tile`myTile2`).length + (tiles.getTilesByType(assets.tile`myTile3`).length + (tiles.getTilesByType(assets.tile`myTile4`).length + tiles.getTilesByType(assets.tile`myTile5`).length)))\n if (totalBallsOut <= 0) {\n bonus = Math.round((120000 - game.runtime()) / 200)\n if (bonus > 0) {\n game.setGameOverMessage(true, \"Speed Bonus:\" + bonus + \" points!\")\n info.changeScoreBy(bonus)\n }\n game.gameOver(true)\n }\n })\n stateTransitions.changeState(\"aiming\")\n }\n\n\n\n /**\n * Appear to aim further left\n */\n //% blockId=aimLeft \n //% block=\"change angle left\"\n //% help=bubble/aim_left\n export function tilt_angle_left() {\n if (stateTransitions.stateIs(\"aiming\")) {\n aimingAngle = Math.constrain(aimingAngle - 1.5, -175, -5)\n }\n }\n\n /**\n * Appear to aim further right\n */\n //% blockId=aimRight \n //% block=\"change angle right\"\n //% help=bubble/aim_right\n export function tilt_angle_right() {\n if (stateTransitions.stateIs(\"aiming\")) {\n aimingAngle = Math.constrain(aimingAngle + 1.5, -175, -5)\n }\n }\n\n\n\n\n function clearLocation(column: number, row: number) {\n burstBubble = sprites.create(img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, SpriteKind.Player)\n tiles.placeOnTile(burstBubble, tiles.getTileLocation(column, row))\n if (tiles.tileAtLocationEquals(tiles.getTileLocation(column, row), assets.tile`myTile2`)) {\n animation.runImageAnimation(\n burstBubble,\n [img`\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . 3 3 3 . . . . . . .\n . . . . . 3 . . . 3 . . . . . .\n . . . . 3 . . . . . 3 . . . . .\n . . . . 3 . . . . . 3 . . . . .\n . . . . 3 . . . . . 3 . . . . .\n . . . . . 3 . . . 3 . . . . . .\n . . . . . . 3 3 3 . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n . . . . . . . . . . . . . . . .\n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 3 . . . . . . . . \n . . . . 3 . . . . . 3 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 3 . . . . . . . 3 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . 3 . . . . . 3 . . . . . \n . . . . . . . 3 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 3 . . . . . . . . \n . . . 3 . . . . . . . 3 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 3 . . . . . . . . . 3 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 3 . . . . . . . 3 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 3 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 3 . . . . . . 3 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 3 . . . . . . . . \n . 3 . . . . . . . . . . . 3 . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 3 . . . . . . . . . 3 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 3 . . . . . . . . \n `],\n 50,\n false\n )\n } else if (tiles.tileAtLocationEquals(tiles.getTileLocation(column, row), assets.tile`myTile1`)) {\n animation.runImageAnimation(\n burstBubble,\n [img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . 2 2 2 . . . . . . . \n . . . . . 2 . . . 2 . . . . . . \n . . . . 2 . . . . . 2 . . . . . \n . . . . 2 . . . . . 2 . . . . . \n . . . . 2 . . . . . 2 . . . . . \n . . . . . 2 . . . 2 . . . . . . \n . . . . . . 2 2 2 . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 2 . . . . . . . . \n . . . . 2 . . . . . 2 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 2 . . . . . . . 2 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . 2 . . . . . 2 . . . . . \n . . . . . . . 2 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 2 . . . . . . . . \n . . . 2 . . . . . . . 2 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 2 . . . . . . . . . 2 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 2 . . . . . . . 2 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 2 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 2 . . . . . . 2 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 2 . . . . . . . . \n . 2 . . . . . . . . . . . 2 . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 2 . . . . . . . . . 2 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 2 . . . . . . . . \n `],\n 50,\n false\n )\n } else if (tiles.tileAtLocationEquals(tiles.getTileLocation(column, row), assets.tile`myTile4`)) {\n animation.runImageAnimation(\n burstBubble,\n [img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . 5 5 5 . . . . . . . \n . . . . . 5 . . . 5 . . . . . . \n . . . . 5 . . . . . 5 . . . . . \n . . . . 5 . . . . . 5 . . . . . \n . . . . 5 . . . . . 5 . . . . . \n . . . . . 5 . . . 5 . . . . . . \n . . . . . . 5 5 5 . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 5 . . . . . . . . \n . . . . 5 . . . . . 5 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 5 . . . . . . . 5 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . 5 . . . . . 5 . . . . . \n . . . . . . . 5 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 5 . . . . . . . . \n . . . 5 . . . . . . . 5 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 5 . . . . . . . . . 5 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 5 . . . . . . . 5 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 5 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 5 . . . . . . 5 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 5 . . . . . . . . \n . 5 . . . . . . . . . . . 5 . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 5 . . . . . . . . . 5 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 5 . . . . . . . . \n `],\n 50,\n false\n )\n } else if (tiles.tileAtLocationEquals(tiles.getTileLocation(column, row), assets.tile`myTile5`)) {\n animation.runImageAnimation(\n burstBubble,\n [img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . 6 6 6 . . . . . . . \n . . . . . 6 . . . 6 . . . . . . \n . . . . 6 . . . . . 6 . . . . . \n . . . . 6 . . . . . 6 . . . . . \n . . . . 6 . . . . . 6 . . . . . \n . . . . . 6 . . . 6 . . . . . . \n . . . . . . 6 6 6 . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 6 . . . . . . . . \n . . . . 6 . . . . . 6 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 6 . . . . . . . 6 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . 6 . . . . . 6 . . . . . \n . . . . . . . 6 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 6 . . . . . . . . \n . . . 6 . . . . . . . 6 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 6 . . . . . . . . . 6 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 6 . . . . . . . 6 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 6 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 6 . . . . . . 6 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 6 . . . . . . . . \n . 6 . . . . . . . . . . . 6 . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 6 . . . . . . . . . 6 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 6 . . . . . . . . \n `],\n 50,\n false\n )\n } else if (tiles.tileAtLocationEquals(tiles.getTileLocation(column, row), assets.tile`myTile3`)) {\n animation.runImageAnimation(\n burstBubble,\n [img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . 4 4 4 . . . . . . . \n . . . . . 4 . . . 4 . . . . . . \n . . . . 4 . . . . . 4 . . . . . \n . . . . 4 . . . . . 4 . . . . . \n . . . . 4 . . . . . 4 . . . . . \n . . . . . 4 . . . 4 . . . . . . \n . . . . . . 4 4 4 . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 4 . . . . . . . . \n . . . . 4 . . . . . 4 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 4 . . . . . . . 4 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . 4 . . . . . 4 . . . . . \n . . . . . . . 4 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 4 . . . . . . . . \n . . . 4 . . . . . . . 4 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 4 . . . . . . . . . 4 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 4 . . . . . . . 4 . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 4 . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n `, img`\n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . . 4 . . . . . . 4 . . . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 4 . . . . . . . . \n . 4 . . . . . . . . . . . 4 . . \n . . . . . . . . . . . . . . . . \n . . . . . . . . . . . . . . . . \n . . 4 . . . . . . . . . 4 . . . \n . . . . . . . . . . . . . . . . \n . . . . . . . 4 . . . . . . . . \n `],\n 50,\n false\n )\n } else {\n\n }\n burstBubble.lifespan = 150\n tiles.setTileAt(tiles.getTileLocation(column, row), assets.tile`transparency8`)\n tiles.setWallAt(tiles.getTileLocation(column, row), false)\n clearCount += 1\n music.play(music.createSoundEffect(\n WaveShape.Sawtooth,\n 100 * clearCount,\n 3000 + 500 * clearCount,\n 255,\n 0,\n 100,\n SoundExpressionEffect.None,\n InterpolationCurve.Logarithmic\n ), music.PlaybackMode.UntilDone)\n }\n spriteutils.createRenderable(0, function (screen2) {\n if (stateTransitions.stateIs(\"aiming\")) {\n for (let index = 0; index <= 4; index++) {\n if(myBall){\n screen2.setPixel(myBall.x + (index + 1) * 8 * Math.cos(spriteutils.degreesToRadians(aimingAngle)), myBall.y + (index + 1) * 8 * Math.sin(spriteutils.degreesToRadians(aimingAngle)), 11)\n }\n }\n }\n })\n\n\n /**\n * Appear to load the bubble\n */\n //% blockId=loadBubble \n //% block=\"load new bubble\"\n //% help=bubble/load_bubble\n export function load_bubble() {\n pauseUntil(() => stateTransitions.stateIs(\"aiming\"))\n if (totalBallsOut < 8) {\n for (let value4 of bubble.list) {\n if (tiles.getTilesByType(value4).length == 0 && bubble.list.indexOf(value4) >= 0) {\n bubble.list.removeAt(bubble.list.indexOf(value4))\n } else if (tiles.getTilesByType(value4).length > 0 && bubble.list.indexOf(value4) < 0) {\n bubble.list.push(value4)\n }\n }\n }\n codingThisBall = randint(0, bubble.list.length - 1)\n ShotNumber += 1\n myBall = sprites.create(bubble.list[codingThisBall], SpriteKind.Bubbles)\n myBall.x = 80\n myBall.bottom = 102\n\n }\n\n\n /**\n * Set up the board grid\n */\n //% blockId=createBoard \n //% block=\"arrange board\"\n //% help=bubble/create_board\n export function createBoard() {\n tiles.setCurrentTilemap(tileUtil.createSmallMap(tilemap`level0`))\n bubble.list = [\n assets.tile`myTile1`,\n assets.tile`myTile2`,\n assets.tile`myTile3`,\n assets.tile`myTile4`,\n assets.tile`myTile5`\n ]\n aimingAngle = -90\n for (let indexX2 = 0; indexX2 <= 17; indexX2++) {\n for (let indexY2 = 0; indexY2 <= 1; indexY2++) {\n if(bubble.list.length > 0){\n tiles.setWallAt(tiles.getTileLocation(indexX2 + 1, indexY2 + 1), true)\n tiles.setTileAt(tiles.getTileLocation(indexX2 + 1, indexY2 + 1), bubble.list._pickRandom())\n }\n }\n }\n controller.configureRepeatEventDefaults(0, 30)\n ShotNumber = 0\n stateTransitions.changeState(\"aiming\")\n }\n\n\n /**\n * Decides where the bubble should stick\n * \n */\n //% blockId=stick_to_wall\n //% block=\"stick $sprite to $location\"\n //% sprite.shadow=variables_get\n //% sprite.defl=sprite\n //% location.shadow=variables_get\n //% location.defl=location\n export function stick_to_wall(sprite: Sprite, location: tiles.Location) {\n stateTransitions.changeState(\"checking\")\n if (!(tiles.tileAtLocationEquals(location, assets.tile`myTile`))) {\n if (tiles.tileAtLocationEquals(location, assets.tile`bottom_row`)) {\n sprites.destroy(sprite)\n info.changeScoreBy(-1)\n } else if (tiles.tileAtLocationIsWall(sprite.tilemapLocation().getNeighboringLocation(CollisionDirection.Bottom)) || tiles.tileAtLocationIsWall(sprite.tilemapLocation().getNeighboringLocation(CollisionDirection.Right)) || tiles.tileAtLocationIsWall(sprite.tilemapLocation().getNeighboringLocation(CollisionDirection.Top)) || tiles.tileAtLocationIsWall(sprite.tilemapLocation().getNeighboringLocation(CollisionDirection.Left))) {\n sprite.setVelocity(0, 0)\n checkForMatches(sprite)\n } else {\n sprite.setVelocity(0, 0)\n sprite.y += -8\n checkForMatches(sprite)\n }\n } else {\n if (sprite.isHittingTile(CollisionDirection.Left)) {\n sprites.setDataNumber(myBall, \"vx\", Math.abs(sprites.readDataNumber(sprite, \"vx\")))\n }\n if (sprite.isHittingTile(CollisionDirection.Right)) {\n sprites.setDataNumber(myBall, \"vx\", 0 - Math.abs(sprites.readDataNumber(sprite, \"vx\")))\n }\n if (sprite.isHittingTile(CollisionDirection.Top)) {\n sprite.setVelocity(0, 0)\n checkForMatches(sprite)\n }\n if (sprite.isHittingTile(CollisionDirection.Bottom)) {\n sprites.setDataNumber(myBall, \"vy\", 0 - Math.abs(sprites.readDataNumber(sprite, \"vy\")))\n }\n }\n }\n\n}\n", + "images.g.jres": "{\n \"*\": {\n \"mimeType\": \"image/x-mkcd-f4\",\n \"dataEncoding\": \"base64\",\n \"namespace\": \"myImages\"\n }\n}", + "images.g.ts": "// Auto-generated code. Do not edit.\nnamespace myImages {\n\n helpers._registerFactory(\"image\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n\n }\n return null;\n })\n\n helpers._registerFactory(\"animation\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n\n }\n return null;\n })\n\n helpers._registerFactory(\"song\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n\n }\n return null;\n })\n\n}\n// Auto-generated code. Do not edit.\n", + "main.blocks": "PlayerProjectileFoodEnemyBubblesspritelocation", + "main.ts": "\n", + "pxt.json": "{\n \"name\": \"bubble_ext_for_assetjson\",\n \"version\": \"0.0.10\",\n \"description\": \"\",\n \"dependencies\": {\n \"device\": \"*\",\n \"arcade-tile-util\": \"github:microsoft/arcade-tile-util#v1.2.0\",\n \"arcade-sprite-util\": \"github:jwunderl/arcade-sprite-util#v0.3.1\",\n \"arcade-state-transitions\": \"github:riknoll/arcade-state-transitions#v0.0.2\",\n \"controller\": \"*\",\n \"Timers\": \"github:microsoft/arcade-timers#v1.1.0\",\n \"arcade-sprite-data\": \"github:microsoft/arcade-sprite-data#v0.2.1\"\n },\n \"files\": [\n \"main.blocks\",\n \"main.ts\",\n \"README.md\",\n \"assets.json\",\n \"tilemap.g.jres\",\n \"tilemap.g.ts\",\n \"images.g.jres\",\n \"images.g.ts\",\n \"bubble.ts\"\n ],\n \"testFiles\": [\n \"test.ts\"\n ],\n \"targetVersions\": {\n \"branch\": \"v1.12.49\",\n \"tag\": \"v1.12.49\",\n \"commits\": \"https://github.com/microsoft/pxt-arcade/commits/8b39eda27ca91b27b57fc1f30c6b3b33d3fc2029\",\n \"target\": \"1.12.51\",\n \"pxt\": \"8.5.60\",\n \"targetId\": \"arcade\"\n },\n \"supportedTargets\": [\n \"arcade\"\n ],\n \"preferredEditor\": \"blocksprj\",\n \"palette\": [\n \"#000000\",\n \"#FFFFFF\",\n \"#DF012E\",\n \"#F696F8\",\n \"#708DFF\",\n \"#FF9500\",\n \"#5FDF5D\",\n \"#94BD84\",\n \"#3E76F9\",\n \"#87F2FF\",\n \"#FFF5FD\",\n \"#A4839F\",\n \"#5C406c\",\n \"#E5CDC4\",\n \"#E5F7FF\",\n \"#000000\"\n ]\n}\n", + "test.ts": "// tests go here; this will not be compiled when this package is used as an extension.\n", + "tilemap.g.jres": "{\n \"tile1\": {\n \"data\": \"hwQIAAgAAAC8u7y7vLu8u7y7vLvMzLy7vLu8u7y7vLu8u8zMvLu8uw==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile\"\n },\n \"tile4\": {\n \"data\": \"hwQIAAgAAAAAMwMAMDMzADMzMwMzMzMDMzMzAzAzMwAAMwMAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile2\"\n },\n \"tile5\": {\n \"data\": \"hwQIAAgAAAAARAQAQEREAERERAREREQEREREBEBERAAARAQAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile3\"\n },\n \"tile6\": {\n \"data\": \"hwQIAAgAAAAAVQUAUFVVAFVVVQVVVVUFVVVVBVBVVQAAVQUAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile4\"\n },\n \"tile7\": {\n \"data\": \"hwQIAAgAAAAAZgYAYGZmAGZmZgZmZmYGZmZmBmBmZgAAZgYAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile5\"\n },\n \"tile9\": {\n \"data\": \"hwQIAAgAAAAAAAC8AAAAvAAAALwAAADMAAAAvAAAALwAAAC8AAAAvA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"bottom_row\"\n },\n \"tile3\": {\n \"data\": \"hwQIAAgAAAAAIgIAICIiACIiIgIiIiICIiIiAiAiIgAAIgIAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile1\"\n },\n \"tile2\": {\n \"data\": \"hwQIAAgAAAAMAAAADAAAAAwAAAAAAAAADAAAAAwAAAAMAAAAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true,\n \"displayName\": \"myTile0\"\n },\n \"transparency16\": {\n \"data\": \"hwQQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true\n },\n \"transparency8\": {\n \"data\": \"hwQIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\",\n \"mimeType\": \"image/x-mkcd-f4\",\n \"tilemapTile\": true\n },\n \"level4\": {\n \"id\": \"level4\",\n \"mimeType\": \"application/mkcd-tilemap\",\n \"data\": \"MTAxMDAwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMA==\",\n \"tileset\": [\n \"myTiles.transparency16\"\n ],\n \"displayName\": \"level4\"\n },\n \"level2\": {\n \"id\": \"level2\",\n \"mimeType\": \"application/mkcd-tilemap\",\n \"data\": \"MDgxNDAwMGYwMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMTAzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMzAzMDMwMzAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMTIyMjIyMjIyMjIyMjIyMjIyMjIyMDIwMDAwMDAwMDAwMDAwMDAwMjAwMjAwMDAwMDAwMDAwMDAwMDAyMDAyMDAwMDAwMDAwMDAwMDAwMDIwMDIwMDAwMDAwMDAwMDAwMDAwMjAwMjAwMDAwMDAwMDAwMDAwMDAyMDAyMDAwMDAwMDAwMDAwMDAwMDIwMDIwMDAwMDAwMDAwMDAwMDAwMjAwMjAwMDAwMDAwMDAwMDAwMDAyMDAyMDAwMDAwMDAwMDAwMDAwMDIwMDIwMDAwMDAwMDAwMDAwMDAwMjAwMjAwMDAwMDAwMDAwMDAwMDAyMDAyMDAwMDAwMDAwMDAwMDAwMDIwMDIwMDAwMDAwMDAwMDAwMDAwMjAwMjAwMDAwMDAwMDAwMDAwMDAyMA==\",\n \"tileset\": [\n \"myTiles.transparency8\",\n \"myTiles.tile1\",\n \"myTiles.tile9\",\n \"myTiles.tile2\"\n ],\n \"displayName\": \"level0\"\n },\n \"*\": {\n \"mimeType\": \"image/x-mkcd-f4\",\n \"dataEncoding\": \"base64\",\n \"namespace\": \"myTiles\"\n }\n}", + "tilemap.g.ts": "// Auto-generated code. Do not edit.\nnamespace myTiles {\n //% fixedInstance jres blockIdentity=images._tile\n export const tile1 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile4 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile5 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile6 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile7 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile9 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile3 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const tile2 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const transparency16 = image.ofBuffer(hex``);\n //% fixedInstance jres blockIdentity=images._tile\n export const transparency8 = image.ofBuffer(hex``);\n\n helpers._registerFactory(\"tilemap\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n case \"level4\":\n case \"level4\":return tiles.createTilemap(hex`1000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000`, img`\n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n. . . . . . . . . . . . . . . . \n`, [myTiles.transparency16], TileScale.Sixteen);\n case \"level0\":\n case \"level2\":return tiles.createTilemap(hex`14000f00010101010101010101010101010101010101010101000000000000000000000000000000000000010100000000000000000000000000000000000001010000000000000000000000000000000000000101000000000000000000000000000000000000010100000000000000000000000000000000000001010000000000000000000000000000000000000101000000000000000000000000000000000000010100000000000000000000000000000000000001010000000000000000000000000000000000000101030303030303030303030303030303030303010100000000000000000000000000000000000001010000000000000000000000000000000000000101000000000000000000000000000000000000010102020202020202020202020202020202020201`, img`\n2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n2 . . . . . . . . . . . . . . . . . . 2 \n`, [myTiles.transparency8,myTiles.tile1,myTiles.tile9,myTiles.tile2], TileScale.Eight);\n }\n return null;\n })\n\n helpers._registerFactory(\"tile\", function(name: string) {\n switch(helpers.stringTrim(name)) {\n case \"myTile\":\n case \"tile1\":return tile1;\n case \"myTile2\":\n case \"tile4\":return tile4;\n case \"myTile3\":\n case \"tile5\":return tile5;\n case \"myTile4\":\n case \"tile6\":return tile6;\n case \"myTile5\":\n case \"tile7\":return tile7;\n case \"bottom_row\":\n case \"tile9\":return tile9;\n case \"myTile1\":\n case \"tile3\":return tile3;\n case \"myTile0\":\n case \"tile2\":return tile2;\n case \"transparency16\":return transparency16;\n case \"transparency8\":return transparency8;\n }\n return null;\n })\n\n}\n// Auto-generated code. Do not edit.\n" +} + +``` \ No newline at end of file