Review: Functionally the Same
Functions allow for code to be structured and reused. In this example, start by refactoring (restructuring) the provided code, and then adding some additional functionality on top.
![Functions Review](https://cdn.makecode.com/blob/b7777d9734179813efa50e857372b6464c11e9b2/static/courses/csintro2/review/functions.gif)
Starter Code
let mySprite: Sprite = null
let index = 0
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
mySprite.say("teleporting!", 1000)
pause(1000)
for (let index = 0; index <= 40; index++) {
mySprite.image.flipX()
pause(Math.max(300 - 15 * index, 30))
}
mySprite.setPosition(randint(10, scene.screenWidth() - 10), randint(10, scene.screenHeight() - 10))
})
controller.left.onEvent(ControllerButtonEvent.Pressed, function () {
mySprite.say("teleporting!", 1000)
pause(1000)
for (let index = 0; index <= 40; index++) {
mySprite.image.flipX()
pause(Math.max(300 - 15 * index, 30))
}
mySprite.setPosition(randint(10, scene.screenWidth() - 10), randint(10, scene.screenHeight() - 10))
})
controller.right.onEvent(ControllerButtonEvent.Pressed, function () {
mySprite.say("teleporting!", 1000)
pause(1000)
for (let index = 0; index <= 40; index++) {
mySprite.image.flipX()
pause(Math.max(300 - 15 * index, 30))
}
mySprite.setPosition(randint(10, scene.screenWidth() - 10), randint(10, scene.screenHeight() - 10))
})
controller.down.onEvent(ControllerButtonEvent.Pressed, function () {
mySprite.say("teleporting!", 1000)
pause(1000)
for (let index = 0; index <= 40; index++) {
mySprite.image.flipX()
pause(Math.max(300 - 15 * index, 30))
}
mySprite.setPosition(randint(10, scene.screenWidth() - 10), randint(10, scene.screenHeight() - 10))
})
mySprite = sprites.create(img`
. . . . . . . . . . . . . . . .
. . . . . . f f f f . . . . . .
. . . . f f f 2 2 f f f . . . .
. . . f f f 2 2 2 2 f f f . . .
. . f f f e e e e e e f f f . .
. . f f e 2 2 2 2 2 2 e e f . .
. f f e 2 f f f f f f 2 e f f .
. f f f f f e e e e f f f f f .
. . f e f b f 4 4 f b f e f . .
. f f e 4 1 f d d f 1 4 e f . .
f d f f e 4 d d d d 4 e f e . .
f b f e f 2 2 2 2 e d d 4 e . .
f b f 4 f 2 2 2 2 e d d e . . .
f c f . f 4 4 5 5 f e e . . . .
. f f . f f f f f f f . . . . .
. . . . f f f . . . . . . . . .
`, SpriteKind.Player)
Student Task #1: Refactoring
Start with the code above. It has the same action described for when any of the arrow keys are pressed, but cannot use ||controller:on any button pressed||
because the player is not suppposed to teleport when ||controller:A||
or ||controller:B||
is pressed.
- Create a function,
||functions:teleport||
, and duplicate the code from the ||controller:on left button pressed||
event into that event
- Replace the blocks inside the
||controller:on left button pressed||
event with ||functions:call function teleport||
- Identify whether the code will behave the same way now as it did before
||functions:teleport||
was created
- Replace the blocks in the 3 other
||controller:controller||
events with ||functions:call function teleport||
At this point, compare your solution to this task to the provided code:
- is it easier or harder to identify what the
||controller:controller events||
do?
- which version has more blocks?
- if you wanted to make the player spin less before teleporting by changing the value in the
||loops:for index||
loop, which version is easier to change?
Student Task #2: ||controller:A||
and ||controller:B||
Add behavior for a ||controller:A||
and ||controller:B||
to the game
- Create a new function called
||functions:wizard||
. Place ||functions:call function wizard||
in both a ||controller:on A button pressed||
and a ||controller:on B button pressed||
- In
||functions:wizard||
, create a ||logic:if then ... else||
. Replace ||logic:true||
with ||math:0 % chance||
, and change 0 to 50
- In the
||logic:if then||
section, make ||variables:mySprite||
move in a square
- In the
||logic:else||
section, make ||variables:mySprite||
fire out a blast of sunshine
The exact way you choose to implement steps 3 and 4 is up to you, but the way we did it is listed below
To make the sprite move in a square, you can:
||sprites:change mySprite x by -10||
, then ||loops:pause||
for 250 ms
||sprites:change mySprite y by -10||
, then ||loops:pause||
for 250 ms
||sprites:change mySprite x by 10||
, then ||loops:pause||
for 250 ms
||sprites:change mySprite y by 10||
To fire out a blast of sunshine:
- Get a
||loops:repeat 40 times||
loop
- Inside the loop, create a
||sprites:projectile||
, with an image of a single yellow pixel
- Set the
||sprites:vx||
and ||sprites:vy||
in the ||sprites:projectile||
to be random values using ||math:pick random -75 to 75||
- Click the
+
in ||sprites:projectile||
and make the projectile come ||sprites:from sprite||
||variables:mySprite||
- Get
||sprites:set mySprite auto destroy||
, change ||variables:mySprite||
to ||variables:projectile||
, change ||sprites:auto destroy||
to ||sprites:ghost||
, and turn it on
Student Task #3: Teleport Sunshine
After seeing the blast of sunshine from the ||functions:wizard||
, we want to add it to the teleportation. To do so, we will move both the possible actions from ||functions:wizard||
into separate functions - that way, anyone who reads the function can get an idea of what’s going on without guessing what it was intended to do.
- Create a new function
||functions:move in a square||
, and move the code from the ||logic:if then||
section in ||functions:wizard||
into it. Add ||functions:call function move in a square||
to replace the code taken from ||functions:wizard||
- Create a new function
||functions:blast of sunshine||
, and move the code from the ||logic:else||
section in ||functions:wizard||
into it. Add ||functions:call function blast of sunshine||
to replace the code taken from ||functions:wizard||
- Add
||functions:call function blast of sunshine||
to ||functions:teleport||
, right before the ||sprites:set mySprite position to||
block, so that immediately before ||variables:mySprite||
moves, there is a ||functions:blast of sunshine||