Level 6: Challenge 1 - IncrediCoders/Python1 GitHub Wiki
Queen Cobra added this page on June 6, 2023
Let's begin your first challenge for Level 6!
You're going to add in sound files to the game, so that you can hear when Paul and the Cryptic Creeper attack!
To find the Level 6 Challenge 1 code template, open the Level 6 folder, the Challenges folder, and then the Challenge 1 folder. You should already have the files downloaded onto your computer (see Load the IncrediCoders Files). Open the BossBattle_Challenge1.py file in Visual Studio Code to build the program by following along with my instructions below!
I broke these instructions down into a few sections:
On Line 2, from init import *
initializes the program by running the init file. This includes code that sets up the file path for the images and text file, gets the fonts ready for this game, sets the window size, and loads the images. This statement allows you to use all the information in that file, for the rest of your program.
On Line 4, def update(delta_time)
updates each time a key is pressed or a button is clicked (these are called an events). This method will continuously check for these events while the game is running.
The comment on Line 5 says, # Check if Paul collides with the walls
. Lines 6-13 check whether or not the Paul Python sprite collides with the four walls. They make sure the Paul sprite doesn't appear inside of the walls.
On Line 6, if MY.player.location.x < MY.wall_height:
checks to see if the current location of the player sprite is less than the maximum height from the dimensions of the wall. This code makes sure that the character is rendered to the right side of the left wall.
On Line 7, MY.player.location.x = MY.wall_height
is run if the if
statement on Line 6 is true, and it sets the player's location to the maximum height set by the dimensions of the wall.
On Line 8, if MY.player.location.x > WINDOW_WIDTH - MY.wall_height:
checks to see if the current location of the player sprite is greater than the width of the window, subtracted by the maximum height from the dimensions of the wall. This code makes sure that the character is rendered to the left side of the right wall.
On Line 9, MY.player.location.x = WINDOW_WIDTH - MY.wall_height
is run if the if
statement on Line 8 is true, and it sets the player's location to the location that is the width of the window, subtracted by the height of the wall.
On Line 10, if MY.player.location.y < MY.wall_height:
checks to see if the current location of the player sprite is less than the maximum height from the dimensions of the wall. This code makes sure that the character is rendered below the top wall.
On Line 11, MY.player.location.y = MY.wall_height
is run if the if
statement on Line 10 is true, and it sets the player's location to the maximum height set by the dimensions of the wall.
On Line 12, if MY.player.location.y > WINDOW_LENGTH - (MY.wall_height + 15):
checks to see if the current location of the player sprite is greater than the length of the window, subtracted by the height of the wall plus 15. This code makes sure that the character is rendered above the bottom wall.
On Line 13, MY.player.location.y = WINDOW_LENGTH - (MY.wall_height + 15)
is run if the if
statement on Line 12 is true, and it sets the player's location to the length of the window, subtracted by the height of the wall plus 15.
On Line 15, the handle_pillar_collision()
function runs when Paul collides with a pillar. There's code in this function that checks to see the location of Paul's sprite.
On Line 18, if MY.player.collides_with_boss():
checks to see if Paul has collided with the Creeper, which is the boss. In this code block (Lines 18-21), if Paul does collide with the Creeper, then Paul's pain animation plays, he loses one health, and his hitbox isn't active for a short time (to give the player a chance to run away).
On Line 19, the player_pain_anim()
function runs, if the above statement is true on Line 18. This function displays Paul's pain animation.
On Line 20, MY.player_health -= 1
subtracts one health from the player's current health, so the player's health goes down one hit point from its current value.
On Line 21, MY.player_hitbox.active = False
allows the player time to recover and move away from the boss by removing the active hitbox for a few seconds.
NEW CODE: On Lines 24-27, you're going to write your own code that plays a sound when Paul gets hit by the Creeper or the Creeper's projectiles. See the next section, "Write Your Own Code", for guidance.
On Line 30, if MY.player_dir == UP:
checks to see if the direction that the player is facing up. This code block (Lines 30-32) places Paul's hit box above him, when he's facing up.
On Lines 31-32, MY.player_hitbox.location = pygame.math.Vector2(MY.player.location.x + 20, MY.player.location.y - 20)
runs. We put this on two lines code because it's a long code statement! We want to make sure each line of code is short enough, so that we can refer to it in the book. If this statement is true, then it will set the hitbox for when the player goes up.
On Line 33, elif MY.player_dir == DOWN:
checks to see if the direction that the player is going is down.
On Lines 34-35, MY.player_hitbox.location = pygame.math.Vector2(MY.player.location.x - 10, MY.player.location.y + 25)
runs if the if
statement on Line 33 is true. It sets the hitbox below the character for when the player goes down.
On Line 36, elif MY.player_dir == LEFT:
checks to see if the direction that the player is going is to the left.
On Lines 37-38, MY.player_hitbox.location = pygame.math.Vector2(MY.player.location.x - 20, MY.player.location.y)
checks if Line 36 is true. It so, it sets the hitbox to the left of the player, for when the player goes to the left.
On Line 39, elif MY.player_dir == RIGHT:
checks to see if the direction that the player is going is to the right.
On Lines 40-41, MY.player_hitbox.location = pygame.math.Vector2(MY.player.location.x + 20, MY.player.location.y)
runs if the Line 39 is true. It sets the hitbox for when the player goes to the left.
On Line 44, if MY.player_hitbox.active and MY.boss.collides_with_hitbox():
checks to see if the player attacks the Creeper (the boss).
NEW CODE: On Lines 46-48, you're going to write your own code that plays a sound when Paul attacks the Creeper. See the next section, "Write Your Own Code", for guidance.
On Line 49, MY.boss_health -= 1
runs, after the sound is played that you wrote the code for. The Creeper's health is reduced by one hit point.
On Line 50, MY.player_hitbox.active = False
gives the boss time to recover. This prevents the player from hitting the Creeper a lot repeatedly, to do a lot of damage at once.
On Line 52, player_attack_update()
makes sure we run all of the attack animations for both the player and the Creeper.
On Line 54, update_assets(delta_time)
updates all the animations and other information about the level, according to delta_time
. This keeps all the animations on the level in sync.
On Line 56, the check_win()
function runs. It checks to see if the player has won. If so, it runs the ending code that starts on Line 66.
NEW CODE: On Lines 59-64, you're going to write your own code that plays a sound when Paul wins or loses. See the next section, "Write Your Own Code", for guidance.
On Line 66, check_events()
, this line will go through each of the separate coding events, and it runs each event when it come up in the game.
Lines 69-72 register the game states. Line 69, Manager.register(sys.modules[__name__])
the current file. Line 70, Manager.register(GameOver)
, registers the game over screen (at the end of the game). Line 71, Manager.register(PlayAgain)
, registers the play again option. Line 72, _Manager.register(Intro)_
, registers the intro screen.
On Line 74, Manager.run(SCREEN, WINDOW, BLACK, "CHALLENGE1")
, runs the game and opens a new window for the game.
On Lines 23-27, you're going to write the code to play a sound when Paul gets hit:
-
On Line 24, start with an
_if_
statement that checks to see if Paul has collided with an object (or projectile).- Use the
_MY.player.collides_with_projectile()_
function. - Be sure to include a colon at the end of the statement.
- Use the
-
On Line 25, make sure you indent this line to the right of Line 24. If the statement from Line 24 is true, then when Paul gets hit by one of Creeper's projectiles, the mixer function loads the sound file.
- Use the
_mixer.music.load()_
function. - In the function, call the "Assets/PaulHit.wav" file. Be sure to include the parentheses.
- Use the
-
On Line 26, you also use the mixer module. (In the init.py file, we imported the
_mixer_
module from_pygame_
.) You will now play the sound that you just loaded for Paul getting hit.- Make sure you're at the same indentation level as Line 25.
- Type
_mixer_
, a period,_music_
,_play_
, and end with the double parentheses (since it's a function). You don't have a parameter to include in the parentheses (so they are empty). - The final code is
_mixer.music.play()_
on Line 26.
-
On Line 27, the last step is to return the value
_True_
. We return_True_
in order to use this information (that Paul got hit) in other places in this level. You should be at the same indentation level as on Lines 25-26. Type_return True_
on Line 27.
On Lines 46-48, you are going to be writing the code to play a sound when the Creeper is attacked:
-
On Line 46, you are already inside an
_if_
block. The initial_if_
statement (on Line 44) checks if the Creeper was attacked. On this line (Line 46), you'll load another sound file using the mixer module.- Indent four spaces to the right (from the
_if_
statement; this should be at the same indentation level as the comment on Line 45). - Type in the
_mixer.music.load()_
function, like you did on Line 25. - Inside the parentheses, add the
_Assets/BossHit.wav_
file name as the parameter. - Be sure to include quotation marks around the file name, inside the parentheses.
- Indent four spaces to the right (from the
-
On Line 47, you'll set the volume. In this case,
_0.4_
works well. We use the mixer module once again to set the volume of this sound file.- At the same indentation level, type in the
_mixer.music.set_volume()_
function. - Enter
_0.4_
as the parameter in the parentheses, to set the volume of our BossHit.wav file.
- At the same indentation level, type in the
On Line 48, you're going use the mixer module to play the loaded sound file. This is the same code that you used on Line 26.
On Lines 59-64, you're going to write the code to play a sound when Paul wins and a different sound when Paul loses:
-
On Line 59, we start by checking to see if the boss health is less than or equal to zero:
- Type
_if_
on the line. - In this case, we're going to include the conditional statement in parentheses. This is another way to write an
_if_
statement. Type in the two parentheses right after_if_
. - Inside the parentheses, type in the
_MY.boss_health_
variable. - After the variable, add a space, then type in the "less than or equal to" operator, which looks like
_<=_
in the code. - Type another space and type in
_0_
while you're still inside the parentheses. As mentioned, this will check if Creeper's health is less than or equal to zero, which means the Creeper lost the battle. - Be sure to include a colon at the end of Line 59, because you're starting your
_if_
block. - The final code on Line 59 is
_if(MY.boss_health <= 0):_
- Type
-
On Line 60, make sure you start by indenting four spaces to the right. If the above statement is true (Creeper lost all his life), you will now load the sound file that plays the winning music for Paul:
- This line of code is the same as what you wrote on Line 46.
- Replace the previous sound file with the
_Assets/Win.wav_
file name. - Be sure to include the file name in quotation marks, inside the parentheses.
-
On Line 61, using the same mixer module, you'll play the sound, since you loaded the file on Line 60. This is the same line of code that you wrote on Line 48.
-
On Line 62, now you'll write the code to determine what happens if Paul loses (if he runs out of health). You'll use an
_elif_
statement to check if the player's health is less than or equal to zero:- This line of code is similar to Line 59.
- After
_elif_
, add parentheses. - Inside the
_elif()_
parentheses, add the_MY.player_health_
variable. - After the variable, add a space, and then add the "less than or equal to" operator:
_<=_
- After the parentheses, end with a colon.
-
If the statement on Line 62 is true (if Paul ran out of health), then Line 63 will use the
_mixer.music_
library to load the sound file for when Paul loses:- Make sure you indented at the same level as Lines 45-50, and Lines 60-91. You should be indented to the right of Line 62.
- Use the
_mixer.music.load()_
function. - Inside the parentheses, type
_"Assets/Lose.wav"_
(including the quotation marks). This will load the Lose.wav file to play the music for Paul losing.
-
On Line 64, at the same indentation level as Line 63, use
_mixer.music.play()_
function. You don't need to add anything into the parentheses. This will play the Lose.wav file.
That's it! Run the code and see if it works!
I included a solution file for Level 6: Boss Battle Challenge 1. This file has all the code filled in, so if you run into any issues with your code (for example, it doesn't compile/run, or something isn't working correctly in your program), then you can take a look at the final code file to see what you did differently:
IMPORTANT: Please don't cheat yourself! Finish the game first!
Next, you can take on the other challenge to battle the Creeper and learn more! When you're done, you can move on to Level 7, IncrediCards!
Challenge 2: In this challenge, you are going to add in another plasma ball projectile for the Cryptic Creeper to attack with.
In addition to this Online Articles page and the instructions for our Level 6 challenges, we also have a Help Page, a Learning Quiz, an Unplugged Activity, and a Rewards article:
-
Level 6: Help - This page helps you complete the instructions in the book, in case you get stuck.
-
Level 6: Learning Quiz - I wrote some questions in case you want to quiz yourself about what you learned. Or you can teach others and quiz them!
-
Level 6: Unplugged Activity - I wrote this page with more details than what you saw in the book. In this game,
-
Level 6: Rewards - If you completed the Boss Battle program that we talked about, then I set up this page to act as a reward. You can see some illustrations of me and learn more about who I am! You'll also find the Mech Award digital download, to show off your accomplishment!
After you're completely done with Level 6 (did you do the challenges?), then it's time to move on to Level 7! While you read through Level 7 in your book, you can check out the resources from Grafika & Syntax, as they teach you how to build the IncrediCards program:
I hope you had fun learning about the Boss Battle!
--Queen Cobra