diff --git a/docs/courses/csintro.md b/docs/courses/csintro.md
index c4d13a31f25..8cbcbf30bd0 100644
--- a/docs/courses/csintro.md
+++ b/docs/courses/csintro.md
@@ -59,13 +59,15 @@ Labs from each unit are grouped in the tiles below.
]
```
+
+
## Individual Tutorials
Individual activities from the tiles above are provided as standalone tutorials below.
+
#### Unit 0 Activities
@@ -235,7 +237,7 @@ Individual activities from the tiles above are provided as standalone tutorials
"name": "Lab 3.4",
"description": "High scores",
"url": "https://arcade.makecode.com/--skillmap#docs:/courses/csintro/blocks/unit-3/lab-3-4-skillmap",
- "imageUrl": "https://arcade.makecode.com/api/S61379-50555-16499-36625/thumb"
+ "imageUrl": "https://arcade.makecode.com/api/_6t78hiKYxRpt/thumb"
}, {
"name": "Lab 3.5",
"description": "Animated sprites",
@@ -244,12 +246,14 @@ Individual activities from the tiles above are provided as standalone tutorials
}
]
```
+-->
## See also
[Courses Home Page](/courses),
[Arcade Tutorials](/tutorials),
[Beginner Skillmaps](/beginner-maps),
+[Kiki's Corner](https://medium.com/kikis-corner),
### ~hint
diff --git a/docs/courses/csintro/blocks/unit-3/lab0301-part1.md b/docs/courses/csintro/blocks/unit-3/lab0301-part1.md
index 94a0a05ec44..b028c14e3e5 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0301-part1.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0301-part1.md
@@ -1,4 +1,5 @@
-# Lab 3.1 Part 1: Introduction to loops
+# Lab 3.1 Part 1: Repeat That, Please
+### @explicitHints true
## Repeat that, please! @showdialog
@@ -6,7 +7,8 @@ In this lab, we will explore a family of loops called *definite loops*.
*Definite loops* are loops that run a specific number of times.
-In Part 1, we'll use one of those loops: The **repeat** loop.
+In Part 1, we'll use one of those loops: the **repeat** loop.
+
```block
let foodSprite: Sprite = null
@@ -16,29 +18,48 @@ for (let index = 0; index < 6; index++) {
}
```
+
+
+---
+
+
+
+
+
+
+
+
## Take an apple; leave an apple
-Let's create a hero character and drop food randomly on the screen.
+Let's create a hero sprite and drop food randomly on the screen.
+
+---
+
+1. Create a sprite for your hero character
+ - Give the sprite's variable an appropriate name
+ - Give the sprite an image
+1. Allow the player to move the hero sprite around the screen
+1. Whenever the player presses **A**, add a new sprite to the screen
+ - Give the new sprite's variable an appropriate name
+ - Give the sprite an image
+ - Place the sprite at a random location on the screen
+
+---
-1. Create a sprite for your hero character.
- - Give the sprite's variable an appropriate name.
- - Give the sprite an image.
-1. Allow the player to move the hero sprite around the screen.
-1. Whenever the player presses **A**, add a sprite to the screen.
- - Give the new sprite's variable an appropriate name.
- - Give the sprite an image.
- - Place the sprite at a random location on the screen.
Run your project and verify that it works as described.
+
Check the hint if you need any help.
+#### ~ tutorialhint
+
```blocks
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
foodSprite = sprites.create(sprites.food.smallApple, SpriteKind.Player)
foodSprite.setPosition(randint(8, 152), randint(8, 112))
})
let foodSprite: Sprite = null
-let heroSprite = sprites.create(sprites.food.smallTaco, SpriteKind.Player)
+let heroSprite = sprites.create(sprites.castle.princess2Right1, SpriteKind.Player)
controller.moveSprite(heroSprite)
```
@@ -49,26 +70,51 @@ wanted to drop two pieces of food. That's easy enough to do: just duplicate
the blocks that we have.
But what if we wanted to drop three? Or five?
-Or ten? Or what if you wanted to change the number of sprites throughout
+Or ten? Or what if you wanted to change the number of sprites dropped throughout
the game?
There is a better way to do this: Use a **repeat** loop.
-1. From the
-``||loops:Loops||`` drawer, drop a
-``||loops:repeat (4) times||``
-loop into your
-``||controller(noclick): on (A) button (pressed)||``
-container.
-1. Move the other blocks in that container to the **inside** of the
-``||loops(noclick):repeat||`` container.
-1. Change the number of repeats to **2**.
+~hint What is a Repeat Loop? ๐คท๐ฝโโ๏ธ
+
+---
+
+In MakeCode Arcade, we call this a **repeat loop**:
+
+```block
+for (let index = 0; index < 4; index++) { }
+```
+
+This loop allows you to tell the computer how many times you want the code inside to run, then it will repeat the code that many times before moving on.
+
+_Note: The repeat will only include the code **inside** the container.
+It will keep looping through that code until it has run the number of times that you
+asked it to, and once it's done it will immediately continue running the rest of your program._
+
+hint~
+
+---
+
+
+1. From the
+``||loops:Loops||`` drawer, drop a
+``||loops:repeat (4) times||``
+loop into **the top** of your
+``||controller(noclick): on (A) button (pressed)||``
+container
+1. Move the existing blocks from that container **into** the
+``||loops(noclick):repeat||`` loop
+1. Change the number of repeats to **2**
+
+---
Run your project and verify that the player drops **two** pieces of food
each time you press **A**.
Check the hint if you need help.
+#### ~ tutorialhint
+
```blocks
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
for (let index = 0; index < 2; index++) {
@@ -81,43 +127,71 @@ let foodSprite: Sprite = null
## Kick the tires!
-Give your new loop a try! As you try different **repeat** values,
+Experiment with your new loop! As you try different **repeat** values,
answer the questions below.
+---
+
+
**Questions**
-- Are there any numbers that are **not** allowed as a repeat value?
+- Are there any numbers that are **not** allowed to be a repeat value?
- Are there any numbers that work in unexpected ways?
- How might you use a **repeat** block in your own projects?
## Food fight!
-Instead of dropping food at random locations, let's throw projectiles
-from the player.
+Instead of dropping food at random locations, let's make it look like the hero is throwing it!
+
+---
+
1. **Delete** all of the blocks inside of the ``||loops(noclick):repeat||`` container.
Keep the loop, though!
1. Add the following blocks to your ``||loops(noclick):repeat||`` loop:
- 1. Create a variable called **speedX**.
- 1. Set **speedX** to a random value between 10 and 40.
- 1. Create another variable called **speedY**.
- 1. Add blocks so that it reads:
- ``||variables:set speedY to||`` ``||math:50 -||``
- ``||variables:speedX||``.
- 1. Create a projectile that starts at your hero sprite with
- velocities **speedX** and **speedY**.
+ 1. Create a variable called **speedX**
+ 1. Initialize **speedX** to a random value between 10 and 40
+ 1. Create another variable called **speedY**
+ 1. Set **speedY** so that it reads:
+ ``||variables:set [speedY] to [50 - speedX]||``
+ 1. Create a projectile that starts from your hero sprite with velocities of
+ **speedX** and **speedY** (for x and y respectively)
+
+These blocks will send the projectiles in random(ish) directions, but will
+keep their speeds roughly the same.
+
+
+~hint A Different Projectile ๐
-These blocks will send the projectiles in random directions, but will
-keeps their speeds roughly the same.
+---
-Run your project and see how it operates differently from before.
+In previous projects, we created projectiles as if they were normal sprites,
+then we added extra blocks to set starting positions and velocity.
-Try different repeat values!
+This time, we want to use the built-in ``||variables(sprites): set [projectile]||`` block
+to create the projectile, and have it do all the rest for us!
-How might you use this mechanism in your own projects?
+```block
+
+ let speedX = 0
+ let speedY = 0
+ let foodSprite: Sprite = sprites.createProjectileFromSprite(sprites.food.smallApple, heroSprite, speedX, speedY)
+```
+
+hint~
+
+---
+
+
+Run your project and see how it operates now.
+Try different values for the repeat!
+
+How might you use this in your own projects?
Check the hint if you need any help.
+#### ~ tutorialhint
+
```block
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
for (let index = 0; index < 2; index++) {
@@ -130,7 +204,10 @@ controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
## Complete! @showdialog
-Good work! You have worked with the **repeat** loop!
+**Good work!**
+๐๐ฝ ๐๐ฝ ๐๐ฝ
+
+You have successfully used the **repeat** loop!
Try these extensions if you have time:
diff --git a/docs/courses/csintro/blocks/unit-3/lab0301-part2.md b/docs/courses/csintro/blocks/unit-3/lab0301-part2.md
index 004fb515ace..7768d78e96d 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0301-part2.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0301-part2.md
@@ -1,15 +1,15 @@
# Lab 3.1 Part 2: Introduction to loops
+### @explicitHints true
## For! @showdialog
-In this lab, we will explore a family of loops called *definite loops*.
-
-*Definite loops* are loops that run a specific number of times.
+In this lab, we're exploring *definite loops*. Definite loops are loops that run a specific number of times.
In Part 1, we learned about the **repeat** loop.
Now, we will learn about the **for** loop.
+
```block
let foodSprite: Sprite = null
for (let index = 0; index < 6; index++) {
@@ -17,13 +17,24 @@ for (let index = 0; index < 6; index++) {
foodSprite.setPosition(10 + index * 20, 10)
}
```
+
+
+---
+
+
+
+
+
+
## What's the same? What's different?
-Sometimes, we want to repeat a set of blocks, but we need to make some
-calculations based on how many times we've been through the loop.
+Sometimes we want to make calculations in our code that require knowing how many times we've been through a loop.
+
+The simplest tool for this is the **for** loop.
+
+---
-The simplest tool for this task is the **for** loop.
Look at the code in this project. Run it and see how the sprites appear.
@@ -31,53 +42,67 @@ Now, look *closely* at the blocks that create the sprites.
Each sprite uses a pair of blocks.
-- What is the same about the blocks in each pair?
+- What is the same in each pair?
- What is different in each pair?
+---
+
+
Head to the next step when you are ready.
-## For! Again!
+## For! (Again)
+
+Did you notice that the *only* difference in each pair is the multiplier
+that goes with the **distance** variable?
+
+---
-Did you notice that the *only* difference in each pair is the number
-that is multiplied with the **distance** variable?
- In the first pair, that multiplier is **zero**.
- In the second pair, the multiplier is **one**.
-- In the next, it is **two**.
-- In the last, it is **three**.
+- In the next, it's **two**.
+- In the last, it's **three**.
-We have a loop that does *exactly* that!
-It counts starting at zero, and counts up to a number that you choose.
+We have a loop that can help us with this!
+It counts from zero to a number you choose.
It's the ``||loops(noclick):for||`` block!
-Move to the next step to learn how to use the ``||loops(noclick):for||`` loop
+---
+
+
+Move to the next step to learn how to use a ``||loops(noclick):for||`` loop
in this project.
## Step aside!
Let's replace these repetitive blocks with a **for** loop.
+---
+
+
1. Drag the blocks that create the sprites off to the side.
-We will use a couple of them shortly.
-1. At the bottom of the
-``||loops(noclick):on start||``
-container, add a
-``||loops:for||`` ``||variables(loops):index||``
-``||loops:from 0 to (4)||``
+We'll use a couple of them shortly.
+1. At the bottom of the
+``||loops(noclick):on start||``
+container, add a
+``||loops:for [index] from 0 to (4)||``
block.
-1. Change the ``||loops(noclick):for||`` loop so that
-``||variables(noclick):index||``
-counts from
-**0** to **3** (or any other number that you like).
-1. Drag **just one pair** of blocks that creates and places a sprite
-on the screen into the
+1. Change the ``||loops(noclick):for||`` loop so that
+``||variables(noclick):index||``
+counts from
+**0** to **3**.
+1. Drag **just one pair** of our sprite creation and position blocks into the
``||loops(noclick):for||`` container.
+---
+
Run your project and check the simulator. It might not look like it's
working correctly, but it is! We need to make one minor adjustment, though.
Compare your code to the hint before moving forward.
+#### ~ tutorialhint
+
```blocks
let duckSprite: Sprite = null
let spriteX = 15
@@ -91,18 +116,27 @@ for (let index = 0; index <= 4; index++) {
## Use the index!
-The ``||loops(noclick):for||`` loop uses the ``||variables(noclick):index||`` variable
-to count, but we are not using it inside of our loop! Let's fix that.
+The ``||loops(noclick):for||`` loop keeps track of how many times it has run
+and stores that number in the ``||variables(noclick):index||``
+variable...but we're not using that in our loop yet!
+
+Let's fix that.
-- From the top of the
-``||loops(noclick):for||`` container, drag a copy of the
-``||variables(noclick):index||`` variable and drop it into the place
-that is being multiplied by
+---
+
+
+- Drag a copy of the
+``||variables(noclick):index||`` variable from the title of the
+``||loops(noclick):for||`` loop, and into the space that holds the multiplier for
``||variables(noclick):distance||``.
-Run your project again and see that the ducks are in a row again!
+---
+
+Run your project again and see that the ducks are back in a row!
+
+Check the hint carefully if you need help on this step.
-Check the hint if you need help.
+#### ~ tutorialhint
```blocks
let duckSprite: Sprite = null
@@ -117,31 +151,40 @@ for (let index = 0; index <= 4; index++) {
## Complete! @showdialog
-Good work!
+**Good work!**
+๐ ๐ ๐
-Notice how much simpler your code looks now that you've used a
-**for** loop!
-How might you use this in your own projects?
+Notice how much cleaner your code looks now that you've used a
+**for** loop?
+
+How might you use this in future projects?
+
+---
+
Try these extensions if you have time:
-- Change the numbers and notice how the sprites are drawn on the screen.
+- Change the for loop number and notice how the sprites are drawn on the screen.
- Can you generate a single column of sprites instead of a row?
- Can you generate a series of sprites drawn diagonally?
- Notice that the loop control variable, ``||variables(noclick):index||``,
-is the same shape and color as any other variable.
+is the same shape and color as any other variable?
If you don't like the name of the loop control variable,
-you can drop one of your own in its place. Give it a try!
-- Let's say you want to draw a grid of sprites on the screen,
-like the image below:
-
+you can rename it, just like any other. Give it a try!
+- Let's say you want to draw a grid of sprites on the screen
+(like the image below:)
+
How might you do that?
-- Create an interesting pattern of sprites.
-Challenge your "helping trios" teammates to duplicate your pattern using loops.
+- Create an interesting pattern of sprites using loops.
+Challenge your "helping trios" teammates to duplicate your pattern.
Compare your code and see if you came up with different ways to produce
the same pattern.
+
+
+
+
```template
let spriteX = 15
let spriteY = 10
diff --git a/docs/courses/csintro/blocks/unit-3/lab0304-part1.md b/docs/courses/csintro/blocks/unit-3/lab0304-part1.md
index 175178a9f9f..e12e865b6a8 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0304-part1.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0304-part1.md
@@ -1,55 +1,108 @@
-# Lab 3.4 Part 1: High scores
+# Lab 3.4 Part 1: High Scores
+### @explicitHints true
## High scores! @showdialog
In this project, you will work with arrays in MakeCode to build a
-high scores table.
+high score table.
-You will be able to add this to other projects, too!
+You'll be able to add this to other projects, too!
+
+
## Let's start at the beginning
-We will begin with a project that you created in labs 2.1 and 2.6.
+We'll begin with a project similar to what you created in labs 2.1 and 2.6.
-If you would like to use your own project, then check with your instructor.
+If you'd like to use your own project, check with your instructor.
+You will need to have two tabs open to continue following along with the tutorial.
-Run the project to refresh your memory. When you are ready, move on to the
-next step.
+To refresh your memory, run the project that's in the workspace.
+When you're ready, move on to the next step.
## More scores! @showdialog
-MakeCode Arcade can hold a single high score for any project that you create,
-but what if you wanted to keep the top five scores and player names instead?
+By default, MakeCode Arcade can hold a single high score for any project you create.
+But, what if you want to remember the top three scores _and_ player names?
Let's build a high score table that does just that!
## Variables!
-1. Use the
+1. Open the
``||variables:Variables||`` drawer to create three variables:
- - One variable will hold the **high scores**.
- - One variable will hold the **high score names**.
- - One variable will hold the **number of high scores**.
-1. Add a block to your
-``||loops(noclick):on start||``
-container to set the
+ - One will hold **high scores**
+ - One will hold **high score names**
+ - One will hold the total **number of high scores** the program can remember
+1. Add a block to your
+``||loops(noclick):on start||``
+container to set the
**number of high scores** to `3`.
-1. Add blocks to your
-``||loops(noclick):on start||``
-container to set the
+1. Add a block to your
+``||loops(noclick):on start||``
+container to initialize the
**high scores** variable to an array with three numbers.
- Add whatever scores you like for your initial high score table!
- Make sure the scores are in *descending* order. In other words,
make sure the highest score is first and the lowest score is last.
-1. Add blocks to your
-``||loops(noclick):on start||``
-container to set the
+1. Add a block to your
+``||loops(noclick):on start||``
+container to set the
**high score names** variable to a list of three empty strings.
Add whatever names you like for your initial high score table.
+~hint Set a variable to an array? ๐ง
+
+---
+
+Remember that a variable is like a named container that can hold something you'll want to use later. In this project, we want it to hold an entire array.
+
+You can think of an array as a row of connected houses...and each house could have a value living in it (sometimes those values are even other variables or arrays!)
+
+The name of your array is like a street name (hopefully a descriptive one that lets people know what they can expect from that row of houses)
+and each house has its own address, starting with 0 and incrementing by 1 until it reaches the
+last one on the street.
+
+
+
+
+If you want to get a value from one of the houses, you need to ask for it using both its street name and address number (also known as an index).
+
+For example, if you want to announce the value living in the first house on highScore street, you would write that as:
+
+```block
+let high_scores: number[] = []
+game.splash(high_score[0])
+```
+
+For the third house on highScore street, you need to ask for:
+
+```block
+let high_scores: number[] = []
+game.splash(high_scores[2])
+```
+
+Do you see the pattern?
+
+---
+
+In this assignment, when we ask you to set the high score variable to an array with three numbers, it's like we're
+asking you to name the street something like **highScore** and put **three** houses on it, where each house contains a number.
+
+This is an example of how you would do that with blocks:
+
+```block
+let high_score = [500, 300, 100]
+```
+
+
+hint~
+
Check the hint if you need help.
-```blocks
+#### ~ tutorialhint
+
+```block
let number_of_high_scores = 3
let high_scores = [500, 300, 100]
let high_score_names = ["Charlie", "Bravo", "Alfa"]
@@ -61,71 +114,125 @@ When the game ends, we need to check the high scores table and add an entry
if needed. But how do we know when the game ends?
In our current project, the game ends when the player runs out of lives.
-We have an event handler that can run when that happens.
+Arcade has an event handler that can run when that happens.
+
+---
-- From the ``||info:Info||`` drawer, add an
-``||info:on life zero||``
+
+- From the ``||info:Info||`` drawer, add an
+``||info:on life zero||``
container to your workspace.
+---
+
Any blocks that we add to this container will run when the player runs
-out of lives. Because we added this event handler, we need to remember
-to make the game end, because it will not end on its own now!
+out of lives.
+
+โ ๏ธ _**Now that we've added this event handler, we need to remember
+to include a
`game over` block, because Arcade will no longer
+do it automatically!**_
+
+
+#### ~ tutorialhint
+
+```blocks
+info.onLifeZero(function () { })
+```
## Show me!
-Before we end the game, let's display the high scores table.
+Before we end the game, let's display the high score table.
+
+---
-1. Create a new variable called **high scores message**.
-1. In your
-``||info(noclick):on life zero||``
+
+1. Create a new variable for a **high scores message**.
+1. In your
+``||info(noclick):on life zero||``
container,
-set the value of
-**high scores message** to the string
-**High scores\n**.
- - Those special characters at the end ask MakeCode to put
-the characters on their own line.
- - Remember that you can find an empty string block in the **Text** drawer
-of the toolbox.
-1. To your
-``||info(noclick):on life zero||``
-container, add a
-``||loops:for||`` ``||variables(loops):index||``
-``||loops:from 0 to (4)||``
-container. The
-``||variables(noclick):index||``
-variable will count through the
-indexes of your array.
-1. In place of the
+set the value of
+**high scores message** to the ``||text:string||``
+**"High scores\n"**.
+(Those special characters at the end ask MakeCode to move to a new line.)
+1. To your
+``||info(noclick):on life zero||``
+container, add a
+``||loops:for [index] from 0 to (4)||``
+container.
(We'll use the loop's
+``||variables(noclick):index||`` to count through the
+indexes of your array.)
+1. In place of the
``||loops(noclick):(4)||`` value in your loop, use blocks
-to build the following expression:
+to build the following expression:
``||variables:number of high scores||``
-``||math:- (1)||``.
-Remember that computers start counting at zero, and the highest index
-for an array is one less than its size.
-1. In the
-``||loops(noclick):for||`` loop, build your high score message.
-Set the
-**high scores message** variable to join the following strings:
- 1. ``||variables:high scores text||``
- (In other words, you are adding to the existing value.)
+``||math:- (1)||``.
+(Remember that computers start counting at zero, so the highest index
+for an array is one less than its size.)
+1. Inside of the
+``||loops(noclick):for||`` loop, build your new high score message.
+SetAdd to the
+**high scores message** variable by joining the following strings:
+ 1. The existing ``||variables:high scores text||`` value.
1. ``||variables(arrays):high score names||``
``||arrays:get value at||`` ``||variables(arrays):index||``
- 1. The string
- **`: `**. (That's a colon followed by a space.)
+ 1. The string
+ **"`: `"**. (That's a colon followed by a space.)
1. ``||variables(arrays):high scores||``
``||arrays:get value at||`` ``||variables(arrays):index||``
- 1. The string
- **`\n`**. This special character
- will put each high score on a separate line.
-1. To your
-``||info(noclick):on life zero||``
-container, display
-**high scores message** with a
-``||game:show long text||``
-block, and then end the game.
-
-Run your project to see if your empty high scores table appears before
-the game ends. Check the hint if you need help.
+ 1. The string
+ **"`\n` "**. (This special character
+ will put each high score on a separate line.)
+
+~hint Ummm...What? ๐ค
+
+---
+
+Within the ``||loops(noclick):for||`` loop, you need to run through each element of each array and sew the values together into a message that can be displayed as a high score table.
+
+You're going to take the original **high score message**,
+then add on a new line that joins the first value of the **high scores text** array
+with the first value from the **high score** array. On the next line, you'll join
+the second value of the **high scores text** array
+with the second value from the **high score** array...and on and on.
+
+Fortunately, you only need to write the code once, because the ``||loops(noclick):for||`` loop
+can move through each element of the arrays using the ``||variables(noclick):index||`` variable.
+
+When you're done, your ``||loops(noclick):for||`` loop should look something like this:
+
+```block
+ let high_scores_message = null
+ for (let index = 0; index <= number_of_high_scores - 1; index++) {
+ high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
+ }
+```
+
+
+hint~
+
+
+6. At the end of your
+``||info(noclick):on life zero||``
+container, display the new
+**high scores message** using a
+``||game:show long text||``
+block
+1. Finally, make sure you have a block at the very bottom of the
+``||info(noclick):on life zero||``
container to end the game as a WIN.
+
+---
+
+
+Run your project to see how your high score table looks when the game ends.
+
+๐ก _For easier testing, consider moving the **ask** block out of the **set difficulty** block and replacing it with the value of **1**.
+You can also temporarily change the value of the initial **set life** block to **1** so that your game goes faster._
+
+
+
+(Check the hint for help.)
+
+#### ~ tutorialhint
```blocks
let high_score_names: string[] = []
@@ -138,14 +245,26 @@ info.onLifeZero(function () {
high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
}
game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.gameOver(true)
})
```
## Complete! @showdialog
-Good work! We have created a high scores table and displayed it at the end
-of the game. Now, we can add scores to it! On to Part 2!
+**Good work!**
+๐ ๐ ๐
+
+You've created a high score table and displayed it at the end
+of the game.
+
+Next, we'll show you how to add more scores to it! On to Part 2!
+
+
+
+
+```package
+betterSettings=github:sargedev/bettersettings
+```
```template
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
@@ -184,6 +303,7 @@ let projectileCount = 0
let enemyVelocity = 0
let MAX_ENEMY_VELOCITY = 0
let MAX_PROJECTILES = 0
+scene.setBackgroundColor(13)
let difficulty = game.askForNumber("Enter starting difficulty (1, 2, or 3)")
if (difficulty == 1) {
MAX_PROJECTILES = 5
@@ -229,7 +349,7 @@ info.onLifeZero(function () {
high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
}
game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.gameOver(true)
})
sprites.onCreated(SpriteKind.Projectile, function (sprite) {
music.play(music.melodyPlayable(music.pewPew), music.PlaybackMode.InBackground)
@@ -263,6 +383,7 @@ let enemyVelocity = 0
let MAX_ENEMY_VELOCITY = 0
let MAX_PROJECTILES = 0
let difficulty = game.askForNumber("Enter starting difficulty (1, 2, or 3)")
+scene.setBackgroundColor(13)
if (difficulty == 1) {
MAX_PROJECTILES = 5
MAX_ENEMY_VELOCITY = 100
diff --git a/docs/courses/csintro/blocks/unit-3/lab0304-part2.md b/docs/courses/csintro/blocks/unit-3/lab0304-part2.md
index 4915983ea88..e9626cefce9 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0304-part2.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0304-part2.md
@@ -1,74 +1,79 @@
-# Lab 3.4 Part 2: High scores
+# Lab 3.4 Part 2: My High Score
+### @explicitHints true
## My high score! @showdialog
-We've added a high scores table to our project and displayed it at the end
-of the game. Now, let's add the player's entry if they qualify!
+We've added a high score table to the end of our game.
+
+Let's add more players to that table as they receive high scores.
+
+
+
## Where does it go?
-Let's figure out where we need to insert our high score. To do that, we will
-go through the high scores table one entry at a time. If we find a score that
-is smaller, then we've found the right spot!
-
-1. **At the beginning** of your
-``||info(noclick):on life zero||``
-container, insert another
-``||loops:for||`` ``||variables(loops):index||``
-``||loops:from 0 to (4)||``
-container. Again, the
-``||variables(noclick):index||`` variable will count through the
-indexes of your array.
-1. Again, in place of the
+Let's figure out where to put our new high score.
+
+To do that, we'll go through the high scores table one entry at a time until we
+find a score that's smaller than the one we're adding. That's how we know we've
+found the right spot!
+
+---
+
+
+1. **At the beginning** of your
+``||info(noclick):on life zero||``
+container, insert another
+``||loops:for||`` loop container.
+1. Again, in place of the
``||loops(noclick):(4)||`` value in your loop, use blocks
-to build the following expression:
-``||variables:number of high scores||`` ``||math:- (1)||``.
-Feel free to duplicate the blocks from your other
-``||loops(noclick):for||`` loop for that expression.
-1. Inside of this new
-``||loops(noclick):for||``
-loop, add an
-``||logic:if (true) then||``
+to build the following expression:
+``||variables:numScores||`` ``||math:- (1)||``.
+(Feel free to duplicate the blocks from your other
+``||loops(noclick):for||`` loop using that expression.)
+1. Inside of this new
+``||loops(noclick):for||``
+loop, add an
+``||logic:if then||``
block.
-1. Replace the
-``||logic(noclick):(true)||`` value with blocks that build
-the following conditional statement:
-``||logic:if||`` ``||info:score||``
-``||logic:is greater than||`` ``||variables(arrays):high scores||``
-``||arrays:get value at||`` ``||variables(noclick):index||``
- - Remember to drag the
- ``||varibles(noclick):index||``
- variable from the top of your
- ``||loops(noclick):for||`` loop.
- - If the editor has changed the name of the variable to something
- like
- ``||variables(noclick):index2||``,
- then that's OK! Use whatever variable
- is shown in the top of your
- ``||loops(noclick):for||`` loop.
- - The ``||info:score||`` value is in the ``||info:Info||`` drawer.
-
-Feel free to check the hint to verify your code. In the next step, we'll
-be able to test your logic!
+1. Replace the
+``||logic(noclick):||`` value with blocks that build
+the following conditional statement:
+``||logic:if < [score] [>] ([highScore] get value at [index]) >||``
+
+๐ก _Remember to drag the ``||varibles(noclick):index||``
+ variable from the top of your ``||loops(noclick):for||`` loop._
+
+๐ก๐ก _If the editor changes the index variable to something
+like ``||variables(noclick):index2||``, that's OK! Use whatever variable
+is shown in the title of your ``||loops(noclick):for||`` loop._
+
+๐ก๐ก๐ก _You can find the ``||info:score||`` value in the ``||info:Info||`` drawer._
+
+---
+
+Feel free to check the hint to verify the code you have so far.
+
+#### ~ tutorialhint
```blocks
-let high_scores: number[] = []
-let high_score_names: string[] = []
-let number_of_high_scores = 0
-let high_scores_message = ""
+let highScores: number[] = []
+let highScoreNames: string[] = []
+let numScores = 0
+let highScoreMessage = ""
info.onLifeZero(function () {
// @highlight
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
}
}
- high_scores_message = "High Scores\\n"
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
+ highScoreMessage = "High Scores\\n"
+ for (let index = 0; index <= numScores - 1; index++) {
+ highScoreMessage = "" + highScoreMessage + highScoreNames[index] + ": " + highScores[index] + "\\n"
}
- game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.showLongText(highScoreMessage, DialogLayout.Center)
+ game.gameOver(true)
})
```
@@ -77,25 +82,44 @@ info.onLifeZero(function () {
If the player gets a high score, then we should collect their name.
Let's do that now!
+---
+
+
1. Create a new variable called something like **playerName**.
-1. Inside of the empty
-``||logic(noclick):if||`` block that you just added
-to your code, prompt the player for their name and place the value
+1. Inside the empty
+``||logic(noclick):if||`` block, prompt the player for their name and place the value
in your new variable.
+1. Once you've got the new name, you need to ``||loops: break||`` out of that ``||loops(noclick):for||`` loop,
+otherwise, it might ask the player for their name multiple times!
+
+---
-Now, play your game and try to get a high score! If you do, then your project
-should ask you for your name.
+Play your game and try to get a high score. If you do, your project
+should ask for your name!
Check the hint if you need help.
+---
+
+**Question**
+
+How can you edit your code so that you don't have to play as long to get a new high score?
+
+
+
+
+#### ~ tutorialhint
+
```blocks
-let high_scores: number[] = []
-let number_of_high_scores = 0
+let highScores: number[] = []
+let numScores = 0
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
// @highlight
let playerName = game.askForString("High score! What is your name?")
+ //@highlight
+ break
}
}
})
@@ -103,38 +127,44 @@ info.onLifeZero(function () {
## Add the score
-Now, let's add the player's score to the table!
+Now, let's add the player's high score to our table!
+
+---
+
+
+After asking for the player's name, add blocks to insert each of the new values into the correct array.
+
+These blocks all go inside of the ``||logic(noclick):if||`` container, before the
+``||loops(noclick):break||`` block.
-After asking for the player's name, add the blocks described below.
-These blocks all go inside of the
-``||logic(noclick):if||`` container.
+1. ``||arrays:[highScores] insert at [index] value [score]||``
+1. ``||arrays:[highScoreNames] insert at [index] value [playerName]||``
-1. ``||variables(arrays):high scores||`` ``||arrays:insert at||``
-``||variables(noclick):index||`` ``||arrays:value||``
-``||info:score||``.
-1. ``||variables(arrays):high score names||``
-``||arrays:insert at||``
-``||variables(noclick):index||`` ``||arrays:value||``
-``||variables:playerName||``.
+
+---
Again, play your game and try to get a high score! If you do, then your project
-should ask you for your name. When your project displays the high score table,
+should ask you for your name.
+
+When your project displays the high score table,
your name and score should appear in the list!
-You may notice a problem, though. We'll fix that in the next step.
-Check the hint if you need help.
+#### ~ tutorialhint
```blocks
-let high_scores: number[] = []
-let high_score_names: string[] = []
-let number_of_high_scores = 0
+let highScores: number[] = []
+let highScoreNames: string[] = []
+let numScores = 0
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
playerName = game.askForString("High score! What is your name?")
- high_scores.insertAt(index, info.score())
- high_score_names.insertAt(index, playerName)
+ //@highlight
+ highScores.insertAt(index, info.score())
+ //@highlight
+ highScoreNames.insertAt(index, playerName)
+ break
}
}
})
@@ -142,44 +172,36 @@ info.onLifeZero(function () {
## Too many!
-Inserting those values into our arrays makes them too long. Let's get rid of the
-extra entries at the end of our arrays.
+Inserting new values into our arrays will keep making them longer and longer unless we get rid of
+the extra entries at the end.
-Add the following blocks inside of your
-``||logic(noclick):if||`` container,
-beneath the ones that you already have there.
+---
-1. ``||arrays:remove last value from||``
-``||variables(arrays):high scores||``
-1. ``||arrays:remove last value from||``
-``||variables(arrays):high score names||``
-1. ``||loops:break||``
+Add the following blocks into your
+``||logic(noclick):if||`` container, right above the
+``||loops(noclick): break||`` block.
-Remember that error that we mentioned in the previous step? Once we add
-the player's name and score to the arrays, then we are done. We don't need to
-continue with the rest of the entries in the array. The
-``||loops:break||``
-block jumps out of the
-``||loops:for||`` loop early.
+1. ``||arrays:remove last value from [highScores]||``
+1. ``||arrays:remove last value from [highScoreNames]||``
-You can find that block in the ``||loops:Loops||`` drawer.
-Your new high score table should work correctly now!
-Check the hint if you need help.
+#### ~ tutorialhint
```blocks
-let high_scores: number[] = []
-let high_score_names: string[] = []
-let number_of_high_scores = 0
+let highScores: number[] = []
+let highScoreNames: string[] = []
+let numScores = 0
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
playerName = game.askForString("High score! What is your name?")
- high_scores.insertAt(index, info.score())
- high_score_names.insertAt(index, playerName)
- high_scores.pop()
- high_score_names.pop()
+ highScores.insertAt(index, info.score())
+ highScoreNames.insertAt(index, playerName)
+ //@highlight
+ highScores.pop()
+ //@highlight
+ highScoreNames.pop()
break;
}
}
@@ -188,12 +210,21 @@ info.onLifeZero(function () {
## Complete! @showdialog
-Good work! We have made a high scores table that works!
+**Good work!***
+๐ฎ ๐ฎ ๐ฎ
+
+You have a high scores table that works!
-You might notice that, when you play the game multiple times,
+When you play the game multiple times, you might notice that
the high scores table resets after each play.
-In Part 3, we will learn how to save your high scores table!
+In Part 3, we'll show you how to save your high scores table from game to game!
+
+
+
+```package
+betterSettings=github:sargedev/bettersettings
+```
```template
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
@@ -206,12 +237,12 @@ controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
}
})
info.onLifeZero(function () {
- high_scores_message = "High Scores\\n"
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
+ highScoreMessage = "High Scores\\n"
+ for (let index = 0; index <= numScores - 1; index++) {
+ highScoreMessage = "" + highScoreMessage + highScoreNames[index] + ": " + highScores[index] + "\\n"
}
- game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.showLongText(highScoreMessage, DialogLayout.Center)
+ game.gameOver(true)
})
sprites.onCreated(SpriteKind.Projectile, function (sprite) {
music.play(music.melodyPlayable(music.pewPew), music.PlaybackMode.InBackground)
@@ -234,16 +265,17 @@ sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSp
music.play(music.melodyPlayable(music.smallCrash), music.PlaybackMode.InBackground)
})
let enemySprite: Sprite = null
-let high_scores_message = ""
+let highScoreMessage = ""
let projectile: Sprite = null
-let high_score_names: string[] = []
-let high_scores: number[] = []
-let number_of_high_scores = 0
+let highScoreNames: string[] = []
+let highScores: number[] = []
+let numScores = 0
let heroSprite: Sprite = null
let projectileCount = 0
let enemyVelocity = 0
let MAX_ENEMY_VELOCITY = 0
let MAX_PROJECTILES = 0
+scene.setBackgroundColor(13)
let difficulty = game.askForNumber("Enter starting difficulty (1, 2, or 3)")
if (difficulty == 1) {
MAX_PROJECTILES = 5
@@ -265,9 +297,9 @@ controller.moveSprite(heroSprite)
heroSprite.setStayInScreen(true)
info.setScore(0)
info.setLife(3)
-number_of_high_scores = 3
-high_scores = [500, 300, 100]
-high_score_names = ["Charlie", "Bravo", "Alfa"]
+numScores = 3
+highScores = [500, 300, 100]
+highScoreNames = ["Charlie", "Bravo", "Alfa"]
game.onUpdateInterval(1000, function () {
enemySprite = sprites.create(sprites.food.smallBurger, SpriteKind.Enemy)
enemySprite.setPosition(randint(10, 150), -5)
@@ -287,22 +319,22 @@ controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
}
})
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
playerName = game.askForString("High score! What is your name?")
- high_scores.insertAt(index, info.score())
- high_score_names.insertAt(index, playerName)
- high_scores.pop()
- high_score_names.pop()
+ highScores.insertAt(index, info.score())
+ highScoreNames.insertAt(index, playerName)
+ highScores.pop()
+ highScoreNames.pop()
break;
}
}
- high_scores_message = "High Scores\\n"
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
+ highScoreMessage = "High Scores\\n"
+ for (let index = 0; index <= numScores - 1; index++) {
+ highScoreMessage = "" + highScoreMessage + highScoreNames[index] + ": " + highScores[index] + "\\n"
}
- game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.showLongText(highScoreMessage, DialogLayout.Center)
+ game.gameOver(true)
})
sprites.onCreated(SpriteKind.Projectile, function (sprite) {
music.play(music.melodyPlayable(music.pewPew), music.PlaybackMode.InBackground)
@@ -325,17 +357,18 @@ sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSp
music.play(music.melodyPlayable(music.smallCrash), music.PlaybackMode.InBackground)
})
let enemySprite: Sprite = null
-let high_scores_message = ""
+let highScoreMessage = ""
let playerName = ""
let projectile: Sprite = null
-let high_score_names: string[] = []
-let high_scores: number[] = []
-let number_of_high_scores = 0
+let highScoreNames: string[] = []
+let highScores: number[] = []
+let numScores = 0
let heroSprite: Sprite = null
let projectileCount = 0
let enemyVelocity = 0
let MAX_ENEMY_VELOCITY = 0
let MAX_PROJECTILES = 0
+scene.setBackgroundColor(13)
let difficulty = game.askForNumber("Enter starting difficulty (1, 2, or 3)")
if (difficulty == 1) {
MAX_PROJECTILES = 5
@@ -357,9 +390,9 @@ controller.moveSprite(heroSprite)
heroSprite.setStayInScreen(true)
info.setScore(0)
info.setLife(3)
-number_of_high_scores = 3
-high_scores = [500, 300, 100]
-high_score_names = ["Charlie", "Bravo", "Alfa"]
+numScores = 3
+highScores = [500, 300, 100]
+highScoreNames = ["Charlie", "Bravo", "Alfa"]
game.onUpdateInterval(1000, function () {
enemySprite = sprites.create(sprites.food.smallBurger, SpriteKind.Enemy)
enemySprite.setPosition(randint(10, 150), -5)
diff --git a/docs/courses/csintro/blocks/unit-3/lab0304-part3.md b/docs/courses/csintro/blocks/unit-3/lab0304-part3.md
index e983830228a..7f516fa9c8e 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0304-part3.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0304-part3.md
@@ -1,103 +1,111 @@
-# Lab 3.4 Part 3: High scores
+# Lab 3.4 Part 3: Don't Lose It!
+### @explicitHints true
## Don't lose it! @showdialog
-We've added a high scores table to our project, displayed it at the end
-of the game, and added the player's name if they qualify.
+We've added a high score table to our project, displayed it at the end
+of the game, and added the player's name when they qualify.
-Now, let's save the high scores table so that it doesn't get lost each
+Now, let's save the high score table so that it doesn't get lost each
time we play our game!
-## Where is the table?
+
-We've added an extension to your project, and you'll notice a new
-drawer in your toolbox called **BetterSettings**.
+## Where is the table?
-In your ``||loops(noclick):on start||`` blocks, we simply create the **high scores**
-and **high score names** arrays and add some values to it.
+We've added an extension to your project. Look for a new
+drawer in your toolbox called ``||blockSettings:BetterSettings||``.
-Instead, let's load the high score table if one has been saved.
+Right now, we're using arrays to keep track of scores, but those reset each time through.
-- First, find the two blocks where you create the
-**high scores** and
-**high score names** variables, and drag them off to the side. You'll use
-them again later.
+Instead, let's check to see if a "better" high score table has been created.
-Now, at the bottom of your
-``||loops(noclick):on start||`` container, add the
-following blocks.
+---
-1. Add an
-``||logic:if (true) then else||`` container and add blocks so that it reads
-as follows:
-``||logic:if||`` ``||blockSettings:setting with name ("high scores") exists||``
+1. First, find the two blocks where you create
+** highScores ** and
+**highScoreNames**, and drag those off to the side.
+(You'll use them again in a minute.)
+2. At the bottom of your
+``||loops(noclick):on start||`` container, add an
+``||logic:if then else||`` container and add blocks so that it reads
+as follows:
+``||logic:if||`` ``||blockSettings:setting with name (" highScores ") exists||``
``||logic:then||``
-1. In the
-``||logic(noclick):if||`` branch, add blocks that read as follows:
-``||variables:set (high scores) to||``
-``||blockSettings:read settings ("high scores") as number array||``
-1. In the
+ 1. In the
+``||logic(noclick):if||`` branch, add blocks that read as follows:
+``||variables:set ( highScores ) to||``
+``||blockSettings:read settings (" highScores ") as number array||``
+ 1. In the
``||logic:else||`` branch, place your block that you moved
off to the side that
-creates the
-**high scores** array with your starting values.
+creates the
+** highScores ** array with your starting values.
-Do something similar for your **high score names** variable.
+Repeat the steps for your **highScoreNames** variable.
-*Watch your spelling and capitalization!*
+*Watch spelling and capitalization!*
+
+---
Check the hint if you need some help.
+#### ~ tutorialhint
+
```blocks
-if (blockSettings.exists("high scores")) {
- let high_scores = blockSettings.readNumberArray("high scores")
+if (blockSettings.exists(" highScores ")) {
+ let highScores = blockSettings.readNumberArray(" highScores ")
} else {
- let high_scores = [500, 300, 100]
+ let highScores = [500, 300, 100]
}
-if (blockSettings.exists("high score names")) {
- let high_score_names = blockSettings.readStringArray("high score names")
+if (blockSettings.exists("highScoreNames")) {
+ let highScoreNames = blockSettings.readStringArray("highScoreNames")
} else {
- let high_score_names = ["Charlie", "Bravo", "Alfa"]
+ let highScoreNames = ["Charlie", "Bravo", "Alfa"]
}
```
## Save it!
-We've loaded the high score table if one has been saved. Now, we need to save
-the high score table when we change it!
+If a high score table exists, we've made sure it will load when the game starts. Now, we need to
+be able to add and remove scores from that table.
-In your
-``||info(noclick):on life zero||`` container, after we update the
-**high scores** and **high score names** variables
-and right before the
+---
+
+In your
+``||info(noclick):on life zero||`` container, right before the
``||loops:break||`` block,
-add the following blocks:
+add the following:
+
+- ``||blockSettings:set setting (" highScores ") to number array||``
+``||variables: highScores ||``
+- ``||blockSettings:set setting ("highScoreNames") to string array||``
+``||variables:highScoreNames||``
-- ``||blockSettings:set setting ("high scores") to number array||``
-``||variables:high scores||``
-- ``||blockSettings:set setting ("high score names") to string array||``
-``||variables:high score names||``
+---
Give it a try! Your high score table should save between plays!
Check the hint if you need some help.
+#### ~ tutorialhint
+
```blocks
-let number_of_high_scores = 0
-let high_scores: number [] = []
-let high_score_names: string[] = []
+let numScores = 0
+let highScores: number [] = []
+let highScoreNames: string[] = []
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
let playerName = game.askForString("High score! What is your name?")
- high_scores.insertAt(index, info.score())
- high_score_names.insertAt(index, playerName)
- high_scores.pop()
- high_score_names.pop()
+ highScores.insertAt(index, info.score())
+ highScoreNames.insertAt(index, playerName)
+ highScores.pop()
+ highScoreNames.pop()
// @highlight
- blockSettings.writeNumberArray("high scores", high_scores)
+ blockSettings.writeNumberArray("highScores", highScores)
// @highlight
- blockSettings.writeStringArray("high score names", high_score_names)
+ blockSettings.writeStringArray("highScoreNames", highScoreNames)
break;
}
}
@@ -106,12 +114,15 @@ info.onLifeZero(function () {
## Complete! @showdialog
-Good work! We have made a high scores table that works!
+**Good work!**
+๐ ๐ ๐
+
+We've made a high score table that works!
Feel free to use this in any of your projects!
-If you would like to use **BetterSettings** or its cousin, simply called
-**Settings**, in your own projects, then ask your instructor.
+If you'd like to use ``||blockSettings:BetterSettings||`` (or its cousin,
+**Settings**) in your own projects, ask your instructor for the address of the extension.
```template
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
@@ -124,22 +135,22 @@ controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
}
})
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
playerName = game.askForString("High score! What is your name?")
- high_scores.insertAt(index, info.score())
- high_score_names.insertAt(index, playerName)
- high_scores.pop()
- high_score_names.pop()
+ highScores.insertAt(index, info.score())
+ highScoreNames.insertAt(index, playerName)
+ highScores.pop()
+ highScoreNames.pop()
break;
}
}
- high_scores_message = "High Scores\\n"
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
+ highScores_message = " highScores \\n"
+ for (let index = 0; index <= numScores - 1; index++) {
+ highScores_message = "" + highScores_message + highScoreNames[index] + ": " + highScores[index] + "\\n"
}
- game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.showLongText(highScores_message, DialogLayout.Center)
+ game.gameOver(true)
})
sprites.onCreated(SpriteKind.Projectile, function (sprite) {
music.play(music.melodyPlayable(music.pewPew), music.PlaybackMode.InBackground)
@@ -162,17 +173,18 @@ sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSp
music.play(music.melodyPlayable(music.smallCrash), music.PlaybackMode.InBackground)
})
let enemySprite: Sprite = null
-let high_scores_message = ""
+let highScores_message = ""
let playerName = ""
let projectile: Sprite = null
-let high_score_names: string[] = []
-let high_scores: number[] = []
-let number_of_high_scores = 0
+let highScoreNames: string[] = []
+let highScores: number[] = []
+let numScores = 0
let heroSprite: Sprite = null
let projectileCount = 0
let enemyVelocity = 0
let MAX_ENEMY_VELOCITY = 0
let MAX_PROJECTILES = 0
+scene.setBackgroundColor(13)
let difficulty = game.askForNumber("Enter starting difficulty (1, 2, or 3)")
if (difficulty == 1) {
MAX_PROJECTILES = 5
@@ -194,9 +206,9 @@ controller.moveSprite(heroSprite)
heroSprite.setStayInScreen(true)
info.setScore(0)
info.setLife(3)
-number_of_high_scores = 3
-high_scores = [500, 300, 100]
-high_score_names = ["Charlie", "Bravo", "Alfa"]
+numScores = 3
+highScores = [500, 300, 100]
+highScoreNames = ["Charlie", "Bravo", "Alfa"]
game.onUpdateInterval(1000, function () {
enemySprite = sprites.create(sprites.food.smallBurger, SpriteKind.Enemy)
enemySprite.setPosition(randint(10, 150), -5)
@@ -216,24 +228,24 @@ controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
}
})
info.onLifeZero(function () {
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- if (info.score() > high_scores[index]) {
+ for (let index = 0; index <= numScores - 1; index++) {
+ if (info.score() > highScores[index]) {
playerName = game.askForString("High score! What is your name?")
- high_scores.insertAt(index, info.score())
- high_score_names.insertAt(index, playerName)
- high_scores.pop()
- high_score_names.pop()
- blockSettings.writeNumberArray("high scores", high_scores)
- blockSettings.writeStringArray("high score names", high_score_names)
+ highScores.insertAt(index, info.score())
+ highScoreNames.insertAt(index, playerName)
+ highScores.pop()
+ highScoreNames.pop()
+ blockSettings.writeNumberArray(" highScores ", highScores)
+ blockSettings.writeStringArray("highScoreNames", highScoreNames)
break;
}
}
- high_scores_message = "High Scores\\n"
- for (let index = 0; index <= number_of_high_scores - 1; index++) {
- high_scores_message = "" + high_scores_message + high_score_names[index] + ": " + high_scores[index] + "\\n"
+ highScores_message = " highScores \\n"
+ for (let index = 0; index <= numScores - 1; index++) {
+ highScores_message = "" + highScores_message + highScoreNames[index] + ": " + highScores[index] + "\\n"
}
- game.showLongText(high_scores_message, DialogLayout.Center)
- game.gameOver(false)
+ game.showLongText(highScores_message, DialogLayout.Center)
+ game.gameOver(true)
})
sprites.onCreated(SpriteKind.Projectile, function (sprite) {
music.play(music.melodyPlayable(music.pewPew), music.PlaybackMode.InBackground)
@@ -256,17 +268,18 @@ sprites.onOverlap(SpriteKind.Player, SpriteKind.Enemy, function (sprite, otherSp
music.play(music.melodyPlayable(music.smallCrash), music.PlaybackMode.InBackground)
})
let enemySprite: Sprite = null
-let high_scores_message = ""
+let highScores_message = ""
let playerName = ""
let projectile: Sprite = null
-let high_score_names: string[] = []
-let high_scores: number[] = []
-let number_of_high_scores = 0
+let highScoreNames: string[] = []
+let highScores: number[] = []
+let numScores = 0
let heroSprite: Sprite = null
let projectileCount = 0
let enemyVelocity = 0
let MAX_ENEMY_VELOCITY = 0
let MAX_PROJECTILES = 0
+scene.setBackgroundColor(13)
let difficulty = game.askForNumber("Enter starting difficulty (1, 2, or 3)")
if (difficulty == 1) {
MAX_PROJECTILES = 5
@@ -288,16 +301,16 @@ controller.moveSprite(heroSprite)
heroSprite.setStayInScreen(true)
info.setScore(0)
info.setLife(3)
-number_of_high_scores = 3
-if (blockSettings.exists("high scores")) {
- high_scores = blockSettings.readNumberArray("high scores")
+numScores = 3
+if (blockSettings.exists(" highScores ")) {
+ highScores = blockSettings.readNumberArray(" highScores ")
} else {
- high_scores = [500, 300, 100]
+ highScores = [500, 300, 100]
}
-if (blockSettings.exists("high score names")) {
- high_score_names = blockSettings.readStringArray("high score names")
+if (blockSettings.exists("highScoreNames")) {
+ highScoreNames = blockSettings.readStringArray("highScoreNames")
} else {
- high_score_names = ["Charlie", "Bravo", "Alfa"]
+ highScoreNames = ["Charlie", "Bravo", "Alfa"]
}
game.onUpdateInterval(1000, function () {
enemySprite = sprites.create(sprites.food.smallBurger, SpriteKind.Enemy)
diff --git a/docs/courses/csintro/blocks/unit-3/lab0305-part1.md b/docs/courses/csintro/blocks/unit-3/lab0305-part1.md
index a8001b17cc4..cc9fe12ada8 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0305-part1.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0305-part1.md
@@ -1,47 +1,48 @@
-# Lab 3.5 Part 1: Animated sprites
+# Lab 3.5 Part 1: Animated Sprites
+### @explicitHints true
## Starting difficulty @showdialog
In this lab, you'll learn different ways to create animated sprites!
-Have you created a flipbook? Flipbooks have images on each page. If you
-flip through the pages quickly, then it looks like the image is moving!
+Have you ever created a flipbook? Flipbooks have images on each page. If you
+flip through the pages quickly, it looks like the image is moving!
This is the style of animation that MakeCode Arcade uses.
-It is called *frame-based animation*.
-
+It is called *frame-based animation*.
+
Image credit: John Barnes Linnett. Public domain.
-## I like to do things the hard way!
+## I like to do things the hard way...
Let's manually animate a sprite. We'll learn some automated ways later,
-but sometimes, you will need to animate a sprite yourself.
+but occasionally, you'll need to animate a sprite yourself.
-1. Create a new variable that will hold the frames (images) of your
+---
+
+
+1. Create a new variable to hold the image array for your
animation. Name your variable something like **frameList**.
1. Set your new variable to an array of images.
- 1. Drag a
- ``||variables:set (frameList) to (0)||``
- block into your
- ``||loops(noclick):on start||`` block.
- 1. Drag an
- ``||arrays:empty array||``
- block into the block for your
- variable. This changes the variable into an array.
- 1. Select the **(+)** sign to add an element to your array.
- Notice that the new element is blank.
- 1. Drag an empty image from the
- ``||images:Images||``
- **Images**
+ 1. Drag a
+ ``||variables:set (frameList) to (0)||``
+ block into your
+ ``||loops(noclick):on start||`` container.
+ 1. Drag an
+ ``||arrays:empty array||``
+ block in to replace the **0** for your
+ inititalization. This changes the variable into an array.
+ 1. Select the **(+)** sign to add an element to your array.
+ (Notice that the new element is blank.)
+ 1. Drag an empty image from the
+ ``||images:Images||``
drawer into the blank
- space in your array. The
- ``||images:Images||``
- **Images**
- drawer is in the
- **Advanced** section of the toolbox.
+ space in your array.
+ (The ``||images:Images||`` drawer is in the
+ **Advanced** section of the toolbox.)
Your array now is an array of images!
-1. Edit the new image in your array. Choose a bright color and fill in
-a single pixel near the center of the image.
+1. Click to edit the new image in your array. Fill in
+a single pixel near the center of the image with a bright color.
1. Duplicate the image block and add it as a new element in the array.
1. Edit the new image and add a couple of pixels to each side of the
single pixel, turning it into a line.
@@ -49,8 +50,13 @@ single pixel, turning it into a line.
1. Repeat a few more times, this time removing a few pixels from the line
until it returns to a single pixel.
+---
+
+
Check the hint if you need any help.
+#### ~ tutorialhint
+
```blocks
let frameList = [
img`
@@ -182,80 +188,242 @@ img`
]
```
-## Where to hang these new images?
+## Where to put these new images?
-Now, we need a place for our images. Let's create a sprite, and then let's
-keep track of which frame in our array we're viewing.
+Now, we need a sprite that will use our images.
-1. Add a block to your
-``||loops(noclick):on start||``
+---
+
+
+1. Add a block to the end of your
+``||loops(noclick):on start||``
container that creates a
sprite.
- - Give the sprite variable an appropriate name.
+ - Give the sprite variable an appropriate name
- It does not need an image. We'll take care of that later.
-1. Create a new variable to store your
-**frameNumber**.
-1. Add a block to
-``||loops(noclick):on start||`` that sets the
-frame number to
-**zero**.
+1. Create a new variable to store your
+**frameNum**.
+1. Add a block to
+``||loops(noclick):on start||`` that initializes the
+frame number to **0**.
+
+---
+
Check the hint if you need any help.
+#### ~ tutorialhint
+
```blocks
+let frameNum = 0
+let frameList = [
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . 6 . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `,
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . 6 6 6 6 6 . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `,
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . 6 6 6 6 6 6 6 6 6 . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `,
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . 6 6 6 6 6 6 6 6 6 6 6 6 6 . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `,
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . 6 6 6 6 6 6 6 6 6 . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `,
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . 6 6 6 6 6 . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `,
+img`
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . 6 . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ `
+]
+//@highlight
let animatedSprite = sprites.create(img`
- .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
+ . . . . . . . . . . . . . . . .
`, SpriteKind.Player)
-let frameNumber = 0
+//@highlight
+frameNum = 0
```
## Time to animate!
-Now, let's animate your sprite!
+Let's animate the sprite!
+
+---
-1. Add an
-``||game:on game update every (500) ms||``
+
+1. Add an
+``||game:on game update every (500) ms||``
container to your
workspace.
1. Add these blocks to your new container:
- - Use blocks from the
- ``||sprites:Sprites||`` and the
- ``||arrays:Arrays||`` drawer to set the sprite's image to the
- current frame in the array.
- - Increment the current frame number.
- - If the current frame number is too big, then reset it to zero.
+ - Use blocks from the
+ ``||sprites:Sprites||`` and
+ ``||arrays:Arrays||`` drawers to set the sprite's image to the
+ current frame in the array (using the frame number variable)
+ - Increment the current frame number
+ - If the current frame number is too big, then reset it to zero
Run your project -- your sprite should be animated! The animation should
repeat without errors.
-Try different values in the
-``||game:on game update every (500) ms||``
+---
+
+
+Try different values in the
+``||game:on game update every (500) ms||``
container to speed up or slow down the animation.
Check the hint if you need any help.
+#### ~ tutorialhint
```blocks
-let frameNumber = 0
+let frameNum = 0
let frameList: Image[] = []
let animatedSprite: Sprite = null
game.onUpdateInterval(500, function () {
- animatedSprite.setImage(frameList[frameNumber])
- frameNumber += 1
- if (frameNumber >= frameList.length) {
- frameNumber = 0
+ animatedSprite.setImage(frameList[frameNum])
+ frameNum += 1
+ if (frameNum >= frameList.length) {
+ frameNum = 0
}
})
```
## Conclusion @showdialog
-Congratulations! You've manually animated a sprite!
+**Congratulations! You've manually animated a sprite!**
+๐ฃ ๐ฅ ๐
-Try some other animations of your own creation.
+Try creating more animations.
There are several frame-based animations available in the gallery, too.
Be sure to take a look at those!
+
+
Have fun!
```ghost
@@ -405,12 +573,12 @@ let animatedSprite = sprites.create(img`
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
`, SpriteKind.Player)
-let frameNumber = 0
+let frameNum = 0
game.onUpdateInterval(500, function () {
- animatedSprite.setImage(frameList[frameNumber])
- frameNumber += 1
- if (frameNumber >= frameList.length) {
- frameNumber = 0
+ animatedSprite.setImage(frameList[frameNum])
+ frameNum += 1
+ if (frameNum >= frameList.length) {
+ frameNum = 0
}
})
```
diff --git a/docs/courses/csintro/blocks/unit-3/lab0305-part2.md b/docs/courses/csintro/blocks/unit-3/lab0305-part2.md
index 731df530dcf..80392fffc3a 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0305-part2.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0305-part2.md
@@ -1,38 +1,46 @@
-# Lab 3.5 Part 2: Animated sprites
+# Lab 3.5 Part 2: More Animations
+### @explicitHints true
-## Built-in animations! @showdialog
+## Built-In Animations @showdialog
In the previous tutorial, you learned how to manually animate a sprite.
In this tutorial, you will use a built-in block to do the same thing.
+
+
## Two simple steps!
-To create an animated sprite using the built-in blocks takes just two
-simple steps!
+You can create an animated sprite in just two simple steps using built-in blocks!
+
+---
-1. In your
-``||loops(noclick):on start||``
+
+1. In your
+``||loops(noclick):on start||``
container, create a new sprite.
- - Name your sprite anything you like.
- - As before, don't worry about setting an image. We will do that
- next.
-1. Open the
-**Advanced**
-section of the toolbox. From the
-``||animation:Animation||``
-drawer, add an
-``||animation:animate||`` ``||variables(animation):mySprite||``
-``||animation:frames [ ] interval (ms) (500) loop (OFF)||``
+ - Name your sprite anything you like
+ - We'll set the image in the next step
+1. From the
+``||animation:Animation||``
+drawer, add an
+``||animation:animate||`` ``||variables(noclick):[mySprite]||``
+``||animation(noclick):frames [ ]||``
+``||animation(noclick):interval (ms) [500]||``
+``||animation(noclick):loop ||``
block.
- - Set the variable name to your sprite's variable name.
- - Select the blank animation. (It's the block next to the word
- *frames*.) Switch to the gallery and select any of the built-in
- animations.
+ - Set the variable name to your sprite's variable name
+ - Select the blank animation and switch to the gallery
+ - Select any of the built-in animations
- Notice that, in this block, you also can set the speed of the
- animation and whether the animation repeats.
+ animation and whether the animation repeats
+
+---
+
That's it! Give it a try! Check the hint if you need help.
+#### ~ tutorialhint
+
```blocks
let animatedSprite = sprites.create(img`
. . . . . . . . . . . . . . . .
@@ -132,23 +140,156 @@ true
Select the animation again to open the animation editor. Take a look around.
+---
+
- Notice that it looks just like the image editor. After all, each frame
in an animation is just an image!
- Notice the extra toolbar on the right side of the screen. That is the
*frame list*. You can change the order of the frames, add frames, and delete
frames with this tool.
-
-Give the animation editor a try! Change some of the frames of the animation,
+- Give the animation editor a try! Change some of the frames of the animation,
click **Done** (just like in the image editor), and then watch your new
animation in the simulator.
## Conclusion @showdialog
-Congratulations! You've animated a sprite using the built-in block!
-You also learned how to use the animation editor.
+**Congratulations!**
+๐ ๐ ๐
-Try some other animations of your own creation.
+You've animated a sprite using the built-in block!
+You also learned how to use the animation editor.
In Part 3, you'll try something a bit more challenging.
Have fun!
+
+
+```ghost
+
+scene.setBackgroundColor(13)
+music.play(music.createSong(hex`00780004080200`), music.PlaybackMode.UntilDone)
+game.showLongText(highScoreMessage, DialogLayout.Center)
+game.splash("This is cool.")
+scene.setBackgroundImage(img`
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
+ 3333333333d111d33333333333333333333333333333333333d111d33333333333333333333333333333333333d111d33333333333333333333333333333333333d111d3333333333333333333333333
+ 33333333d1111111d3333333333333333333333333333333d1111111d3333333333333333333333333333333d1111111d3333333333333333333333333333333d1111111d33333333333333333333333
+ 3333333d111111111d33333333333333333333333333333d111111111d33333333333333333333333333333d111111111d33333333333333333333333333333d111111111d3333333333333333333333
+ 3333333111111111113d111d33333333333333333333333111111111113d111d33333333333333333333333111111111113d111d33333333333333333333333111111111113d111d3333333333333333
+ 333333d11111111111d111111333333333333333333333d11111111111d111111333333333333333333333d11111111111d111111333333333333333333333d11111111111d111111333333333333333
+ 33333dd111111111111111111d33d111111d333333333dd111111111111111111d33d111111d333333333dd111111111111111111d33d111111d333333333dd111111111111111111d33d111111d3333
+ 33d11ddd11111111111111111dd1111111111d3333d11ddd11111111111111111dd1111111111d3333d11ddd11111111111111111dd1111111111d3333d11ddd11111111111111111dd1111111111d33
+ 3111111d11111111111111111d111111111111d33111111d11111111111111111d111111111111d33111111d11111111111111111d111111111111d33111111d11111111111111111d111111111111d3
+ 11111111d111111111113111111111111111111d11111111d111111111113111111111111111111d11111111d111111111113111111111111111111d11111111d111111111113111111111111111111d
+ 1111111111111111111a5a1111111119111111111111111111111111111a5a1111111119111111111111111111111111111a5a1111111119111111111111111111111111111a5a111111111911111111
+ 111111111111111133a353a33111119991111111111111111111111133a353a33111119991111111111111111111111133a353a33111119991111111111111111111111133a353a33111119991111111
+ 3111111111111111a3555553a11111191111113a3111111111111111a3555553a11111191111113a3111111111111111a3555553a11111191111113a3111111111111111a3555553a11111191111113a
+ a1111111911111111a55555a11111111111111a5a1111111911111111a55555a11111111111111a5a1111111911111111a55555a11111111111111a5a1111111911111111a55555a11111111111111a5
+ 3a3111199911111111a555a11111111111113a353a3111199911111111a555a11111111111113a353a3111199911111111a555a11111111111113a353a3111199911111111a555a11111111111113a35
+ 55a111119111111111a535a1111111111111a55555a111119111111111a535a1111111111111a55555a111119111111111a535a1111111111111a55555a111119111111111a535a1111111111111a555
+ 5a11111111111111113a3a311111111111111a555a11111111111111113a3a311111111111111a555a11111111111111113a3a311111111111111a555a11111111111111113a3a311111111111111a55
+ 5a11111111111111111111111111111111111a535a11111111111111111111111111111111111a535a11111111111111111111111111111111111a535a11111111111111111111111111111111111a53
+ a31111111111111111111111aaaa1111111113a3a31111111111111111111111aaaa1111111113a3a31111111111111111111111aaaa1111111113a3a31111111111111111111111aaaa1111111113a3
+ 1111111111aa11111111111a355aa111111111111111111111aa11111111111a355aa111111111111111111111aa11111111111a355aa111111111111111111111aa11111111111a355aa11111111111
+ 111111111a35a1111191111a5555aa11aaaaa111111111111a35a1111191111a5555aa11aaaaa111111111111a35a1111191111a5555aa11aaaaa111111111111a35a1111191111a5555aa11aaaaa111
+ 11111111a555a1111999111a55555aaa35555a1111111111a555a1111999111a55555aaa35555a1111111111a555a1111999111a55555aaa35555a1111111111a555a1111999111a55555aaa35555a11
+ 111aaaaaa555a1111191111a5555533555555a11111aaaaaa555a1111191111a5555533555555a11111aaaaaa555a1111191111a5555533555555a11111aaaaaa555a3111191111a5555533555555a11
+ 11a555533955a1111111111a3555555995555a1111a555533955a1111111111a3555555995555a1111a555533955a1111111111a3555555995555a1111a555533955a3111111111a3555555995555a11
+ 11a5555555553a111111111aa55555599555aa1111a5555555553a311111111aa55555599555aa1111a5555555553a311111111aa55555599555aa1111a5555555553a311111111aa55555599555aa11
+ 11aa5555555553a11111111aa55555555553a31111aa5555555553a11111111aa55555555553a11111aa5555555553a31111111aa55555555553a11111aa5555555553a11111111aa55555555553a111
+ 111aa5555555555a111111aa355555555553aa11113aa5555555555a111111aa355555555553aa11111aa5555555555a111111aa355555555553aa11111aa5555555555a111111aa355555555553aa11
+ 111aa55555555555a1111aa55555555555553aa1113aa55555555555a1111aa55555555555553aa1111aa55555555555a1111aa55555555555553aa1111aa55555555555a1111aa55555555555553aa1
+ 11aa55555555555aaa11a35555555555555555a313aa55555555555aaa11a35555555555555555a111aa55555555555aaa11a35555555555555555a111aa55555555555aaa11a35555555555555555a1
+ 11a555555555553a39aa3555555555555555553399a555555555553a39aa3555555555555555553399a555555555553a39aa3555555555555555553311a555555555553a39aa35555555555555555533
+ 31a5555555553aaa993a5555555555555555539939a5555555553aaa993a5555555555555555539939a5555555553aaa993a5555555555555555539939a5555555553aaa993a55555555555555555399
+ 3333555335553339999a355555555555555533993333555335553339999a355555555555555533993333555335553339999a355555555555555533993333555335553339999a35555555555555553399
+ 9333aaaa35553335599a333aaa355555555539999333aaaa35553335599a333aaa355555555539999333aaaa35553335599a333aaa355555555539999333aaaa35553335599a333aaa35555555553999
+ 9333399aa55999955993aaaaaaa55555333339999333399aa55999955993aaaaaaa55555333339999333399aa55999955993aaaaaaa55555333339999333399aa55999955993aaaaaaa5555533333999
+ 99999399aa5999999999999a9aa55555a999999999999399aa5999999999999a9aa55555a999999999999399aa5999999999999a9aa55555a999999999999399aa5999999999999a9aa55555a9999999
+ 999933999aa399999999999393a55553a3999999999933999aa399999999999393a55553a3999999999933999aa399999999999393a55553a3999999999933999aa399999999999393a55553a3999999
+ 9993339999933999999999939335555a333999999993339999933999999999939335555a333999999993339999933999999999939335555a333999999993339999933999999999939335555a33399999
+ 9933399999933999999993339333553399339999993339999993399999999333933355339933999999333999999339999999933393335533993399999933399999933999999993339333553399339999
+ 9933999999939999999993399933333999339999993399999993999999999339993333399933999999339999999399999999933999333339993399999933999999939999999993399933333999339999
+ 9993999999939993399993999999339999399933999399999993999339999399999933999939993399939999999399933999939999993399993999339993999999939993399993999999339999399933
+ 3993999999939933339993999999999999399333399399999993993333999399999999999939933339939999999399333399939999999999993993333993999999939933339993999999999999399333
+ 3333999999933333333993999999999999333399333399999993333333399399999999999933339933339999999333333339939999999999993333993333999999933333333993999999999999333399
+ 3333999999933399933333999999999999333999333399999993339993333399999999999933399933339999999333999333339999999999993339993333999999933399933333999999999999333999
+ 9999999999999999993339999999999999999999999999999999999999333999999999999999999999999999999999999933399999999999999999999999999999999999993339999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+ 9999999999999999999999999991119999999999999999999999999999999999999111999999999999999999999999999999999999911199999999999999999999999999999999999991119999999999
+ 9999999999999999999999999111111199999999999999999999999999999999911111119999999999999999999999999999999991111111999999999999999999999999999999999111111199999999
+ 9999999999999999999999991111111119999999999999999999999999999999111111111999999999999999999999999999999911111111199999999999999999999999999999991111111119999999
+ 9999999999999999999999911111111111991119999999999999999999999991111111111199111999999999999999999999999111111111119911199999999999999999999999911111111111991119
+ 1999999999999999999999911111111111911111199999999999999999999991111111111191111119999999999999999999999111111111119111111999999999999999999999911111111111911111
+ 1999911111199999999999911111111111111111199991111119999999999991111111111111111119999111111999999999999111111111111111111999911111199999999999911111111111111111
+ 1991111111111999999119991111111111111111199111111111199999911999111111111111111119911111111119999991199911111111111111111991111111111999999119991111111111111111
+ 1911111111111199911111191111111111111111191111111111119991111119111111111111111119111111111111999111111911111111111111111911111111111199911111191111111111111111
+ 1111111111111119111111119111111111111111111111111111111911111111911111111111111111111111111111191111111191111111111111111111111111111119111111119111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+ 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
+`)
+```
\ No newline at end of file
diff --git a/docs/courses/csintro/blocks/unit-3/lab0305-part3.md b/docs/courses/csintro/blocks/unit-3/lab0305-part3.md
index fa6c93a167d..ba03245c35b 100644
--- a/docs/courses/csintro/blocks/unit-3/lab0305-part3.md
+++ b/docs/courses/csintro/blocks/unit-3/lab0305-part3.md
@@ -1,96 +1,212 @@
-# Lab 3.5 Part 3: Animated sprites
+# Lab 3.5 Part 3: What a Great Character
+### @explicitHints true
## What a great character! @showdialog
-In the previous tutorial, you learned use a built-in block to animate a sprite.
+In the previous tutorial, you learned to use a built-in block to animate a sprite.
-In this tutorial, we will use an extension to do some more complex actions!
+In this tutorial, we'll use an extension to do some more complex actions!
+
+
## One sprite to start!
First, we need a hero sprite for our project.
-1. In your
-``||loops(noclick):on start||``
+---
+
+
+1. In your
+``||loops(noclick):on start||``
container, add blocks that
do the following:
- - Create a hero sprite for your player.
- - Give the sprite an appropriate image and variable name.
- - Let the player control the hero sprite using the d-pad.
- - Keep the hero sprite on the screen.
+ - Create a hero sprite for your player
+ - Give the sprite an appropriate image and variable name
+ - Let the player control the hero sprite using the d-pad
+ - Keep the hero sprite on the screen
+
+---
+
Check the hint if you need any help.
+#### ~ tutorialhint
+
```blocks
-let movingSprite = sprites.create(sprites.builtin.forestMonkey0, SpriteKind.Player)
-controller.moveSprite(movingSprite)
-movingSprite.setStayInScreen(true)
+let monkiki = sprites.create(sprites.builtin.forestMonkey0, SpriteKind.Player)
+controller.moveSprite(monkiki)
+monkiki.setStayInScreen(true)
```
## Show some character!
-We've added an extension for this tutorial. Notice the new
+We've added an extension for this tutorial. Notice the new
``||characterAnimations:Character||`` drawer in your toolbox.
-1. Add a
-``||variables(characterAnimations):mySprite||``
-``||characterAnimations:loop frames [ ] (500) when (not moving)||``
-block to the bottom of your
-``||loops(noclick):on start||``
+---
+
+
+1. Add a
+``||characterAnimations: ||`` ``||variables(noclick):mySprite||``
+``||characterAnimations(noclick):loop frames [ ]||``
``||characterAnimations(noclick): (500)||``
+``|| when (not moving)||``
+block to the bottom of your
+``||loops(noclick):on start||``
container.
1. Change the variable name to your hero sprite's variable name.
+---
+
+
Give this new block a try! Use the built-in images and animations in the
gallery to learn about this new block.
Can you make your hero sprite animate appropriately when it is moving
in any of the four directions on the screen?
+#### ~ tutorialhint
+
```blocks
-let movingSprite = sprites.create(sprites.builtin.forestMonkey0, SpriteKind.Player)
-controller.moveSprite(movingSprite)
-movingSprite.setStayInScreen(true)
+let monkiki = sprites.create(img`
+ . . . . f f f f f . . . . . . .
+ . . . f e e e e e f . . . . . .
+ . . f d d d d e e e f . . . . .
+ . c d f d d f d e e f f . . . .
+ . c d f d d f d e e d d f . . .
+ c d e e d d d d e e b d c . . .
+ c d d d d c d d e e b d c . . .
+ c c c c c d d e e e f c . . . .
+ . f d d d d e e e f f . . . . .
+ . . f f f f f e e e e f . . . .
+ . . . . f f e e e e e e f . f f
+ . . . f e e f e e f e e f . e f
+ . . f e e f e e f e e e f . e f
+ . f b d f d b f b b f e f f e f
+ . f d d f d d f d d b e f f f f
+ . . f f f f f f f f f f f f f .
+ `, SpriteKind.Player)
+controller.moveSprite(monkiki)
+monkiki.setStayInScreen(true)
+//@highlight
characterAnimations.loopFrames(
-movingSprite,
+monkiki,
[img`
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
- . . . . . . . . . . . . . . . .
+ . . . . . . . f f f f f . . . .
+ . . . . . . f e e e e e f . . .
+ . . . . . f e e e d d d d f . .
+ . . . . f f e e d f d d f d c .
+ . . . f d d e e d f d d f d c .
+ . . . c d b e e d d d d e e d c
+ f f . c d b e e d d c d d d d c
+ f e f . c f e e d d d c c c c c
+ f e f . . f f e e d d d d d f .
+ f e f . f e e e e f f f f f . .
+ f e f f e e e e e e e f . . . .
+ . f f e e e e f e f f e f . . .
+ . . f e e e e f e f f e f . . .
+ . . . f e f f b d f b d f . . .
+ . . . f d b b d d c d d f . . .
+ . . . f f f f f f f f f . . . .
`],
-500,
-characterAnimations.rule(Predicate.NotMoving)
+100,
+characterAnimations.rule(Predicate.MovingRight)
+)
+//@highlight
+characterAnimations.loopFrames(
+monkiki,
+[img`
+ . . . . f f f f f . . . . . . .
+ . . . f e e e e e f . . . . . .
+ . . f d d d d e e e f . . . . .
+ . c d f d d f d e e f f . . . .
+ . c d f d d f d e e d d f . . .
+ c d e e d d d d e e b d c . . .
+ c d d d d c d d e e b d c . f f
+ c c c c c d d d e e f c . f e f
+ . f d d d d d e e f f . . f e f
+ . . f f f f f e e e e f . f e f
+ . . . . f e e e e e e e f f e f
+ . . . f e f f e f e e e e f f .
+ . . . f e f f e f e e e e f . .
+ . . . f d b f d b f f e f . . .
+ . . . f d d c d d b b d f . . .
+ . . . . f f f f f f f f f . . .
+ `],
+100,
+characterAnimations.rule(Predicate.MovingLeft)
+)
+//@highlight
+characterAnimations.loopFrames(
+monkiki,
+[img`
+ . . . . . . . f f f f f . . . .
+ . . . . . . f e e e e e f . . .
+ . . . . . f e e e d d d d f . .
+ . . . . f f e e d f d d f d c .
+ . . . f d d e e d f d d f d c .
+ . . . c d b e e d d d d e e d c
+ . . . c d b e e d d c d d d d c
+ . . . . c f e e e d d c c c c c
+ . . . . . f f e e e d d d d f .
+ . . . . f e e e e f f f f f . .
+ f f . f e e e e e e f f . . . .
+ f e . f e e f e e f e e f . . .
+ f e . f e e e f e e f e e f . .
+ f e f f e f b b f b d f d b f .
+ f f f f e b d d f d d f d d f .
+ . f f f f f f f f f f f f f . .
+ `],
+100,
+characterAnimations.rule(Predicate.MovingUp)
)
+//@highlight
+characterAnimations.loopFrames(
+monkiki,
+[img`
+ . . . . f f f f f . . . . . . .
+ . . . f e e e e e f . . . . . .
+ . . f d d d d e e e f . . . . .
+ . c d f d d f d e e f f . . . .
+ . c d f d d f d e e d d f . . .
+ c d e e d d d d e e b d c . . .
+ c d d d d c d d e e b d c . . .
+ c c c c c d d e e e f c . . . .
+ . f d d d d e e e f f . . . . .
+ . . f f f f f e e e e f . . . .
+ . . . . f f e e e e e e f . f f
+ . . . f e e f e e f e e f . e f
+ . . f e e f e e f e e e f . e f
+ . f b d f d b f b b f e f f e f
+ . f d d f d d f d d b e f f f f
+ . . f f f f f f f f f f f f f .
+ `],
+100,
+characterAnimations.rule(Predicate.MovingDown)
+)
+
```
## Conclusion @showdialog
-Congratulations! You've used the **Character** extension to do some complex
+**Congratulations!**
+๐ฅณ ๐ฅณ ๐ฅณ
+
+You've used the **Character** extension to do some complex
animations with sprites! If you want to use the **Character** extension in
-your own projects, then check with your instructor.
+your own projects, check with your instructor to get the extension URL.
-Try some other animations of your own creation.
+Try creating more animations on your own.
Have fun!
+
+
```ghost
-let movingSprite = sprites.create(sprites.builtin.forestMonkey0, SpriteKind.Player)
-controller.moveSprite(movingSprite)
-movingSprite.setStayInScreen(true)
+let monkiki = sprites.create(sprites.builtin.forestMonkey0, SpriteKind.Player)
+controller.moveSprite(monkiki)
+monkiki.setStayInScreen(true)
characterAnimations.loopFrames(
-movingSprite,
+monkiki,
[img`
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
diff --git a/docs/courses/csintro/blocks/unit-3/skillmap.md b/docs/courses/csintro/blocks/unit-3/skillmap.md
index bd1c4c67f79..cc40a9bddbf 100644
--- a/docs/courses/csintro/blocks/unit-3/skillmap.md
+++ b/docs/courses/csintro/blocks/unit-3/skillmap.md
@@ -2,10 +2,12 @@
* name: Unit 3 Skillmap
* description: Learn about loops, arrays, and animations!
-* primarycolor: #2EA9B0
+* primarycolor: #897894
* secondarycolor: #F392BD
-* tertiarycolor: #83C252
+* tertiarycolor: #88f2ff
* highlightcolor: #FAED28
+* bannerUrl: https://arcade.makecode.com/api/_d1DiUyMim6M6/thumb
+* backgroundurl: /static/skillmap/backgrounds/lab3bg.gif
## lab-03-01
@@ -14,18 +16,21 @@
### lab-03-01-part-1
-* name: Lab 3.1 Part 1 Repeat that, please!
+* name: Lab 3.1 Part 1 Repeat That, Please!
* description: Use the repeat loop to launch projectiles from a sprite.
* type: tutorial
* next: lab-03-01-part-2
* url: /courses/csintro/blocks/unit-3/lab0301-part1
+* imageUrl: https://arcade.makecode.com/api/_KLfa0XDaz1Vo/thumb
### lab-03-01-part-2
* name: Lab 3.1 Part 2 For!
* description: Use the for loop to arrange sprites in a pattern.
* type: tutorial
+* allowcodecarryover: false
* url: /courses/csintro/blocks/unit-3/lab0301-part2
+* imageUrl: https://arcade.makecode.com/api/_9McPiWefHahc/thumb
## lab-03-04
@@ -34,26 +39,29 @@
### lab-03-04-part-1
-* name: Lab 3.4 Part 1 High scores!
+* name: Lab 3.4 Part 1 - High Scores
* description: Build an empty high scores table and display it at the end of the game.
* type: tutorial
* next: lab-03-04-part-2
* url: /courses/csintro/blocks/unit-3/lab0304-part1
+* imageUrl: https://arcade.makecode.com/api/_RdC9TMWEuKR1/thumb
### lab-03-04-part-2
-* name: Lab 3.4 Part 2 My high score!
+* name: Lab 3.4 Part 2 - My High Score
* description: Add the player's entry to the high score table.
* type: tutorial
* next: lab-03-04-part-3
* url: /courses/csintro/blocks/unit-3/lab0304-part2
+* imageUrl: https://arcade.makecode.com/api/_FPvhi4cmhYod/thumb
### lab-03-04-part-3
-* name: Lab 3.4 Part 3 Don't lose it!
+* name: Lab 3.4 Part 3 - Don't Lose It!
* description: Use the Better Settings extension to save your high scores table.
* type: tutorial
* url: /courses/csintro/blocks/unit-3/lab0304-part3
+* imageUrl: https://arcade.makecode.com/api/_6t78hiKYxRpt/thumb
## lab-03-05
@@ -62,23 +70,26 @@
### lab-03-05-part-1
-* name: Lab 3.5 Part 1 Starting difficulty
+* name: Lab 3.5 Part 1 - Animated Sprites
* description: Use an array of images to manually animate a sprite.
* type: tutorial
* next: lab-03-05-part-2
* url: /courses/csintro/blocks/unit-3/lab0305-part1
+* imageUrl: https://arcade.makecode.com/api/_H0zMKtd9Wh6s/thumb
### lab-03-05-part-2
-* name: Lab 3.5 Part 2 Built-in animations!
+* name: Lab 3.5 Part 2 - More Animations
* description: Use the built-in animation block to animate a sprite.
* type: tutorial
* next: lab-03-05-part-3
* url: /courses/csintro/blocks/unit-3/lab0305-part2
+* imageUrl: https://arcade.makecode.com/api/_d1DiUyMim6M6/thumb
### lab-03-05-part-3
-* name: Lab 3.5 Part 3 What a great character!
+* name: Lab 3.5 Part 3 - What a Great Character
* description: Use the Character extension to give sprites complex animations.
* type: tutorial
* url: /courses/csintro/blocks/unit-3/lab0305-part3
+* imageUrl: https://arcade.makecode.com/api/_WfpV16DDwUTU/thumb
diff --git a/docs/courses/educator-trainings.md b/docs/courses/educator-trainings.md
index 338a97852ad..0a7a0da7bba 100644
--- a/docs/courses/educator-trainings.md
+++ b/docs/courses/educator-trainings.md
@@ -3,12 +3,35 @@
A collection of courses that provide professional learning opportunities for Microsoft MakeCode.
-## CSEd Week Webinars
+## MakeCode General Trainings
_(Click tile to register for free)_
-```codecard
[
{
+ "name": "MakeCode Arcade-Con!",
+ "description": "Save the date for this 6-hour online professional learning conference, centered around Microsoft MakeCode Arcade.",
+ "label": "April 23, 2024",
+ "labelClass": "purple ribbon large",
+ "url":"https://youtu.be/zFqY9P5KtcA",
+ "imageUrl": "https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RWOYCd?ver=bf04&q=90&m=6&h=291&w=517&b=%23FFFFFFFF&l=f&o=t"
+ }
+
+]
+
+
+## Intro to CS with Arcade
+_(Click tile to register for free)_
+
+
+[
+ {
+ "name": "Tips and Tricks for Intro to CS with Arcade",
+ "description": "Discover exciting tips, tricks, and features meant to make your classroom experience as smooth as possible",
+ "label": "View the Recording",
+ "labelClass": "purple ribbon large",
+ "url":"https://youtu.be/zFqY9P5KtcA",
+ "imageUrl": "https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RWOYCd?ver=bf04&q=90&m=6&h=291&w=517&b=%23FFFFFFFF&l=f&o=t"
+ },{
"name": "Intro to MakeCode for CSEd Week 2024",
"description": "Join us for an engaging 50-minute webinar where we'll explore the best MakeCode Hour of Code activities, perfect for Computer Science Education Week!",
"label": "View the Recording",
@@ -23,13 +46,12 @@ _(Click tile to register for free)_
"url":"https://youtu.be/sG7XMH2WaGs",
"imageUrl": "/static/skillmap/balloon/balloon4.gif"
}
+
]
-```
-## Intro to CS with Arcade
-_(Click tile to register for free)_
+## Previous Recordings
```codecard
[
@@ -40,14 +62,22 @@ _(Click tile to register for free)_
"labelClass": "purple ribbon large",
"url":"https://youtu.be/zFqY9P5KtcA",
"imageUrl": "https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RWOYCd?ver=bf04&q=90&m=6&h=291&w=517&b=%23FFFFFFFF&l=f&o=t"
+ },{
+ "name": "Intro to MakeCode for CSEd Week 2024",
+ "description": "Join us for an engaging 50-minute webinar where we'll explore the best MakeCode Hour of Code activities, perfect for Computer Science Education Week!",
+ "label": "View the Recording",
+ "labelClass": "purple ribbon large",
+ "url":"https://youtu.be/sT5o01rIQZw",
+ "imageUrl": "/static/tutorials/bubbles/card.jpg"
}, {
- "name": "Intro to CS - Ask Me Anything",
- "description": "This session is your chance to ask the curriculum developers about whatever is on your mindโfrom coding conundrums to classroom challenges.",
- "label": "02/25/25 at 4pm PST",
+ "name": "Instant CSEd Week Prep",
+ "description": "From activity selection to class runtime, you'll leave this session with all the knowledge and resources necessary to make CS Education Week fun, engaging, and stress-free for you and your students. ",
+ "label": "View the Recording",
"labelClass": "purple ribbon large",
- "url":"https://msit.events.teams.microsoft.com/event/b12482d0-cef6-4159-8324-7f751f56048a@72f988bf-86f1-41af-91ab-2d7cd011db47",
- "imageUrl": "https://arcade.makecode.com/api/S02325-67229-86604-38896/thumb"
+ "url":"https://youtu.be/sG7XMH2WaGs",
+ "imageUrl": "/static/skillmap/balloon/balloon4.gif"
}
+
]
```
diff --git a/docs/gamejam/lessons/box.md b/docs/gamejam/lessons/box.md
index 7f542e4e7f7..d260fd34afb 100644
--- a/docs/gamejam/lessons/box.md
+++ b/docs/gamejam/lessons/box.md
@@ -59,20 +59,21 @@ Decide how participants will submit their games to you.
## Celebrate
-Will you just be awarding participation certificates or calling out specific projects for their creativity, complexity, or alignment with the assigned theme? Download, customize and award [certificates of achievement](https://aka.ms/GameJamBoxCert).
+Will you be awarding participation certificates to everyone or calling out specific projects for creativity, complexity, or alignment with the assigned theme? Download, customize and award [certificates of achievement](https://aka.ms/GameJamBoxCert).
## Educator Resources
If youโre a teacher, we got you covered! Here are some additional resources to get you started:
- [Game Jam in a Box Lesson Teacher Guide Word Document](https://1drv.ms/w/s!AqsgsTyHBmRBknY1ENeC4jdrPg81?e=7W1Guq)
-- [Game Jam in a Box Lesson Teacher Guide PDF](https://1drv.ms/b/s!AqsgsTyHBmRBkng3YIHQUvorRPe0?e=ikYw4I)
-- [Game Jam in a Box Presentation Template](https://1drv.ms/p/s!AqsgsTyHBmRBknTT2xRpZ2upij4v?e=bWiGb6)
+- [Game Jam in a Box Lesson Teacher Guide PDF](https://1drv.ms/b/c/416406873cb120ab/EasgsTyHBmQggEF4CQAAAAAB6uKGXZ9l_abiPWfnSl2x5g?e=3HFlVH)
+- [Game Jam in a Box Presentation Template](https://1drv.ms/p/c/416406873cb120ab/EQAKJIOoCw1Kjpxd7VQyA-0BpT4PFtRqEt1g7oS5sIb0hQ?e=IyUzEu)
## Resources
- [Block Documentation](https://arcade.makecode.com/block-gallery): General documentation for MakeCode Arcade blocks
-- [Sharing Code](https://1drv.ms/b/s!AqsgsTyHBmRBkgY6P-ecQ1ZWulzc?e=s6fcgw): How participants in groups can share their code with each other
+- [Kiki's Corner](https://medium.com/kikis-corner): How-To blog for all things MakeCode Arcade
+- [Building Projects Together in MakeCode Arcade](https://medium.com/kikis-corner/building-projects-together-in-makecode-arcade-9cf70e57aecc): How participants in groups can share their code
- [Forums](http://forum.makecode.com/): We have forums for educators to ask questions or share MakeCode tips and tricks
- [Twitter](https://twitter.com/msmakecode): The team can be contacted on our forums or Twitter account.
diff --git a/docs/static/courses/csintro/arrays_highscore_pl.jpg b/docs/static/courses/csintro/arrays_highscore_pl.jpg
new file mode 100644
index 00000000000..7933a0be9b2
Binary files /dev/null and b/docs/static/courses/csintro/arrays_highscore_pl.jpg differ
diff --git a/docs/static/courses/csintro/lab3bg.gif b/docs/static/courses/csintro/lab3bg.gif
new file mode 100644
index 00000000000..35e36f03910
Binary files /dev/null and b/docs/static/courses/csintro/lab3bg.gif differ