Template
1
0
Files
myrepo123/dodge_astroid_game/Introduction to Python_ Variables Functions and Loops.html
2025-12-05 10:53:17 +03:00

1405 lines
59 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Introduction to Python: Variables, Functions, and Loops</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
color: #f1f1f1;
overflow-x: hidden;
}
.presentation-container {
display: flex;
flex-direction: column;
min-height: 100vh;
padding: 20px;
}
.slide {
display: none;
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 40px;
margin: 20px auto;
max-width: 1200px;
width: 90%;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
border: 1px solid rgba(255, 255, 255, 0.1);
animation: fadeIn 0.5s ease-out;
}
.slide.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
h1, h2, h3 {
color: #4cc9f0;
margin-bottom: 20px;
}
h1 {
font-size: 2.8rem;
text-align: center;
margin-bottom: 10px;
background: linear-gradient(90deg, #4cc9f0, #4361ee);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
h2 {
font-size: 2.2rem;
border-bottom: 2px solid #4361ee;
padding-bottom: 10px;
}
h3 {
font-size: 1.6rem;
color: #f72585;
margin-top: 25px;
}
p {
line-height: 1.7;
margin-bottom: 15px;
font-size: 1.1rem;
}
ul, ol {
margin-left: 30px;
margin-bottom: 20px;
}
li {
margin-bottom: 10px;
line-height: 1.6;
}
.code-block {
background: #1e1e2e;
border-radius: 10px;
padding: 20px;
margin: 20px 0;
border-left: 5px solid #4361ee;
font-family: 'Courier New', monospace;
overflow-x: auto;
}
.code-block code {
color: #8be9fd;
font-size: 1rem;
line-height: 1.5;
}
.code-to-type {
background-color: rgba(244, 114, 182, 0.2);
padding: 2px 6px;
border-radius: 4px;
font-weight: bold;
color: #f72585;
border: 1px solid #f72585;
}
.highlight {
background-color: rgba(244, 114, 182, 0.2);
padding: 2px 6px;
border-radius: 4px;
font-weight: bold;
}
.instruction-box {
background: rgba(67, 97, 238, 0.1);
border-radius: 10px;
padding: 20px;
margin: 20px 0;
border-left: 5px solid #4361ee;
}
.instruction-box h4 {
color: #4cc9f0;
margin-bottom: 10px;
font-size: 1.2rem;
}
.emoji-instructions {
background: rgba(247, 37, 133, 0.1);
border-radius: 10px;
padding: 20px;
margin: 20px 0;
border-left: 5px solid #f72585;
}
.emoji-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
gap: 10px;
max-height: 200px;
overflow-y: auto;
background: rgba(0, 0, 0, 0.2);
padding: 15px;
border-radius: 10px;
margin: 15px 0;
}
.emoji-item {
font-size: 1.8rem;
text-align: center;
cursor: pointer;
transition: transform 0.2s;
}
.emoji-item:hover {
transform: scale(1.3);
}
.quiz-question {
background: rgba(67, 97, 238, 0.1);
border-radius: 10px;
padding: 20px;
margin: 20px 0;
}
.quiz-options {
margin: 15px 0;
}
.quiz-option {
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
padding: 12px 15px;
margin: 10px 0;
cursor: pointer;
transition: background 0.2s;
border: 1px solid transparent;
}
.quiz-option:hover {
background: rgba(67, 97, 238, 0.2);
}
.quiz-option.selected {
background: rgba(67, 97, 238, 0.3);
border-color: #4361ee;
}
.quiz-option.correct {
background: rgba(72, 187, 120, 0.3);
border-color: #48bb78;
}
.quiz-option.incorrect {
background: rgba(245, 101, 101, 0.3);
border-color: #f56565;
}
.quiz-feedback {
padding: 15px;
border-radius: 8px;
margin-top: 15px;
display: none;
}
.quiz-feedback.correct {
background: rgba(72, 187, 120, 0.2);
border-left: 5px solid #48bb78;
display: block;
}
.quiz-feedback.incorrect {
background: rgba(245, 101, 101, 0.2);
border-left: 5px solid #f56565;
display: block;
}
.challenge-item {
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
padding: 15px;
margin: 10px 0;
display: flex;
align-items: center;
}
.challenge-checkbox {
width: 24px;
height: 24px;
margin-right: 15px;
border-radius: 4px;
border: 2px solid #4361ee;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.challenge-checkbox.checked {
background: #4361ee;
}
.challenge-checkbox.checked::after {
content: "✓";
color: white;
font-weight: bold;
}
.nav-buttons {
display: flex;
justify-content: space-between;
margin-top: 30px;
}
.nav-button {
background: linear-gradient(90deg, #4361ee, #3a0ca3);
color: white;
border: none;
padding: 12px 25px;
border-radius: 50px;
cursor: pointer;
font-size: 1rem;
font-weight: bold;
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
align-items: center;
gap: 8px;
}
.nav-button:hover {
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(67, 97, 238, 0.4);
}
.nav-button:disabled {
background: #6c757d;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.slide-indicator {
display: flex;
justify-content: center;
gap: 10px;
margin-top: 20px;
}
.indicator-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
cursor: pointer;
transition: background 0.3s;
}
.indicator-dot.active {
background: #4cc9f0;
transform: scale(1.2);
}
.slide-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.slide-number {
background: rgba(67, 97, 238, 0.2);
padding: 5px 15px;
border-radius: 20px;
font-weight: bold;
}
.learning-outcomes {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin: 25px 0;
}
.outcome-card {
background: rgba(67, 97, 238, 0.1);
border-radius: 10px;
padding: 20px;
border-top: 4px solid #f72585;
}
.game-preview {
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 20px;
margin: 20px 0;
text-align: center;
}
.game-emoji {
font-size: 4rem;
margin: 20px 0;
}
.mentor-info {
background: linear-gradient(135deg, rgba(67, 97, 238, 0.1), rgba(247, 37, 133, 0.1));
border-radius: 15px;
padding: 25px;
margin: 25px 0;
}
.path-structure {
display: flex;
justify-content: space-between;
margin: 25px 0;
gap: 20px;
}
.path-step {
background: rgba(67, 97, 238, 0.1);
border-radius: 10px;
padding: 20px;
flex: 1;
text-align: center;
border-top: 4px solid #4cc9f0;
}
.path-step-number {
font-size: 2.5rem;
font-weight: bold;
color: #4cc9f0;
margin-bottom: 10px;
}
@media (max-width: 768px) {
.slide {
padding: 25px;
width: 95%;
}
h1 {
font-size: 2.2rem;
}
h2 {
font-size: 1.8rem;
}
.learning-outcomes {
grid-template-columns: 1fr;
}
.emoji-grid {
grid-template-columns: repeat(auto-fill, minmax(35px, 1fr));
}
.path-structure {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="presentation-container">
<!-- Slide 0: Introduction -->
<div class="slide active" id="slide0">
<div class="slide-header">
<h1>Introduction to Python</h1>
<div class="slide-number">Slide 1 of 11</div>
</div>
<h2>Variables, Functions, and Loops</h2>
<div class="game-preview">
<div class="game-emoji">🐍</div>
<p>In this introduction to coding in Python for beginners, you will learn how to use variables, loops, and functions to create visual and interactive artwork, animations, simulations, games, and more.</p>
</div>
<h3>What will I create?</h3>
<p>Make interactive projects, art, games, and a simulation. By the end of this path you will have created a scalable piece of geometric art.</p>
<div class="mentor-info">
<h3>321…Make! Learning Path</h3>
<p>This path follows 321…Make! methodology:</p>
<div class="path-structure">
<div class="path-step">
<div class="path-step-number">3</div>
<h4>Explore projects</h4>
<p>Introduce creators to a set of skills and provide step-by-step instructions to help them develop initial confidence.</p>
</div>
<div class="path-step">
<div class="path-step-number">2</div>
<h4>Design projects</h4>
<p>Allow creators to practise skills from the Explore projects, and express themselves creatively while they grow in independence.</p>
</div>
<div class="path-step">
<div class="path-step-number">1</div>
<h4>Invent project</h4>
<p>Encourages creators to use their skills to create a unique project that meets a project brief for a particular audience.</p>
</div>
</div>
</div>
<h3>What do I need to know?</h3>
<ul>
<li>Basic typing and computer navigation skills</li>
<li>Experience coding in Scratch may be useful</li>
</ul>
<h3>What do I need?</h3>
<ul>
<li>A computer or mobile device capable of running an online coding platform.</li>
<li>Optionally, an account to save projects.</li>
</ul>
<div class="instruction-box">
<h4>Quick Quiz Instructions</h4>
<p>Each project contains a quick quiz with three multiple choice questions. You are guided to the correct answer through useful feedback and are awarded a project badge.</p>
</div>
<div class="instruction-box">
<h4>This Design Project</h4>
<p>This Design project guides you to use your new skills and encourages you to make design choices based on your interests.</p>
<p><strong>You will make:</strong> Build a scrolling endless runner game where your character has to avoid obstacles - "Dodge asteroids"</p>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)" disabled>
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 1: Set the Scene -->
<div class="slide" id="slide1">
<div class="slide-header">
<h2>Set the Scene</h2>
<div class="slide-number">Slide 2 of 11</div>
</div>
<div class="instruction-box">
<h4>Step 1: Open the starter project</h4>
<p>Create a variable called <span class="code-to-type">safe</span> to store the background colour.</p>
</div>
<p>In the game, the player is safe if they are touching the background colour.</p>
<div class="code-block">
<code>def draw():<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type"># Put code to run every frame here</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">global safe</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">safe = Color(200, 100, 0)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">background(safe)</span></code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and you should see a coloured square.</p>
<p>The colour is three numbers - the amount of red, green and blue. Try changing the numbers to any whole number between 0 and 255 to get a different colour.</p>
</div>
<h3>Define a draw_player function</h3>
<div class="code-block">
<code><span class="code-to-type"># Draw player function goes here</span><br>
<span class="code-to-type">def draw_player():</span><br>
<span class="code-to-type">&nbsp;&nbsp;&nbsp;&nbsp;text('🤠', 200, 320)</span></code>
</div>
<p>Call the draw_player function so that the player is drawn on the screen.</p>
<div class="code-block">
<code>def draw():<br>
&nbsp;&nbsp;&nbsp;&nbsp;# Put code to run every frame here<br>
&nbsp;&nbsp;&nbsp;&nbsp;global safe<br>
&nbsp;&nbsp;&nbsp;&nbsp;safe = Color(200, 100, 0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;background(safe)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">draw_player()</span></code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and you should see the emoji appear near the bottom of the screen.</p>
<p>You can paste in a different emoji if you want to.</p>
</div>
<div class="emoji-instructions">
<h4>The Emoji Keyboard</h4>
<p>Your device might have an emoji keyboard that you can use to select an emoji:</p>
<ul>
<li><strong>Mobile or tablet:</strong> Press the emoji icon (this is typically a smiley face)</li>
<li><strong>Windows:</strong> Windows key + Full stop</li>
<li><strong>Mac:</strong> CTRL + CMD + Space</li>
<li><strong>Linux:</strong> Ctrl + Alt + E</li>
</ul>
<p>Below are some of the most popular emojis that you could use in your project. You can copy them from here.</p>
</div>
<div class="emoji-grid" id="playerEmojiGrid">
<!-- Emojis will be added by JavaScript -->
</div>
<div class="instruction-box">
<h4>Important:</h4>
<p>There are over 3,000 emojis available for you to use. They cover a wide variety of emotions, themes, and activities.</p>
<p><strong>Tip:</strong> Emojis look slightly different on different devices, so someone else may not see exactly the same image as you. Some emojis are not supported on some devices and these appear as a square instead.</p>
</div>
<p>To make the player follow the mouse as it moves from side to side, change the player's x position to <span class="code-to-type">mouse_x</span>.</p>
<div class="code-block">
<code># Draw player function goes here<br>
def draw_player():<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">text('🤠', mouse_x, 320)</span></code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and check that the player moves left and right when you move the mouse.</p>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 2: Create an Obstacle -->
<div class="slide" id="slide2">
<div class="slide-header">
<h2>Create an Obstacle</h2>
<div class="slide-number">Slide 3 of 11</div>
</div>
<p>Create the obstacles that you will have to avoid to keep playing the game.</p>
<div class="instruction-box">
<h4>Step 1: Define a draw_obstacles function</h4>
<p>Define a <span class="code-to-type">draw_obstacles</span> function to draw a cactus emoji 🌵.</p>
</div>
<div class="code-block">
<code><span class="code-to-type"># Draw obstacles function goes here</span><br>
<span class="code-to-type">def draw_obstacles():</span><br>
<span class="code-to-type">&nbsp;&nbsp;&nbsp;&nbsp;text('🌵', 200, 200)</span></code>
</div>
<p>Call the draw_obstacles function so that the cactus is drawn on the screen.</p>
<div class="code-block">
<code>def draw():<br>
&nbsp;&nbsp;&nbsp;&nbsp;# Put code to run every frame here<br>
&nbsp;&nbsp;&nbsp;&nbsp;global safe<br>
&nbsp;&nbsp;&nbsp;&nbsp;safe = Color(200, 100, 0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;background(safe)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">draw_obstacles()</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;draw_player()</code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and you should see a cactus as well as your player.</p>
</div>
<h3>Add Variables for Obstacle Position</h3>
<div class="code-block">
<code>def draw_obstacles():<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_x = 200</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_y = 200</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;text('🌵', <span class="code-to-type">obstacle_x</span>, <span class="code-to-type">obstacle_y</span>)</code>
</div>
<p>Now, add <span class="code-to-type">frame_count</span> to the obstacle's y (vertical) position.</p>
<div class="code-block">
<code>def draw_obstacles():<br>
&nbsp;&nbsp;&nbsp;&nbsp;obstacle_x = 200<br>
&nbsp;&nbsp;&nbsp;&nbsp;obstacle_y = <span class="code-to-type">200 + frame_count</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;text('🌵', obstacle_x, obstacle_y)</code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and the cactus emoji should move down the screen until it reaches the bottom.</p>
</div>
<div class="emoji-instructions">
<h4>Choose Your Obstacle Emoji</h4>
<p>Select an emoji for your obstacles:</p>
</div>
<div class="emoji-grid" id="obstacleEmojiGrid">
<!-- Emojis will be added by JavaScript -->
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 3: Random Obstacles -->
<div class="slide" id="slide3">
<div class="slide-header">
<h2>Random Obstacles</h2>
<div class="slide-number">Slide 4 of 11</div>
</div>
<p>Currently, the obstacle disappears off the bottom of the screen, because its obstacle_y position becomes larger than the screen size.</p>
<div class="instruction-box">
<h4>Step 1: Use the modulo operator</h4>
<p>Use the modulo (<span class="code-to-type">%</span>) operator to divide the y position by the screen size and give you the remainder. This makes the obstacle reappear at the top!</p>
</div>
<div class="code-block">
<code>def draw_obstacles():<br>
&nbsp;&nbsp;&nbsp;&nbsp;obstacle_x = 200<br>
&nbsp;&nbsp;&nbsp;&nbsp;obstacle_y = 200 + frame_count<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_y = obstacle_y % screen_size</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;text('🌵', obstacle_x, obstacle_y)</code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and you should see the obstacle reach the bottom of the screen and then restart from the top.</p>
</div>
<h3>Add Random Generation</h3>
<div class="instruction-box">
<h4>Step 2: Add a random seed</h4>
<p>Add a line of code for a random seed. A seed lets you generate the same random numbers in each frame.</p>
</div>
<div class="code-block">
<code># Draw obstacles function goes here<br>
def draw_obstacles():<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">seed(1234)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;obstacle_x = 200<br>
&nbsp;&nbsp;&nbsp;&nbsp;obstacle_y = 200 + frame_count</code>
</div>
<div class="instruction-box">
<h4>Step 3: Generate random coordinates</h4>
<p>Update the code so that the x, y coordinates for the obstacle are generated randomly.</p>
</div>
<div class="code-block">
<code># Draw obstacles function goes here<br>
def draw_obstacles():<br>
&nbsp;&nbsp;&nbsp;&nbsp;seed(1234)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_x = randint(0, screen_size)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_y = randint(0, screen_size) + frame_count</span></code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and you should see the cactus appear at a random position. Change the 1234 value inside the seed to another number and it will appear somewhere else.</p>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 4: Lots of Obstacles -->
<div class="slide" id="slide4">
<div class="slide-header">
<h2>Lots of Obstacles</h2>
<div class="slide-number">Slide 5 of 11</div>
</div>
<p>Now you will add code to make lots of obstacles to avoid.</p>
<div class="instruction-box">
<h4>Step 1: Add a loop</h4>
<p>Add a loop and indent the code to draw an obstacle. The loop will run this code multiple times.</p>
</div>
<div class="code-block">
<code>def draw_obstacles():<br>
&nbsp;&nbsp;&nbsp;&nbsp;seed(1234)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">for i in range(8):</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_x = randint(0, screen_size)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_y = randint(0, screen_size) + frame_count</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">obstacle_y = obstacle_y % screen_size</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">text('🌵', obstacle_x, obstacle_y)</span></code>
</div>
<div class="instruction-box">
<h4>Important:</h4>
<p>Make sure that the code for the seed is before the loop, otherwise all of your obstacles will be generated on top of each other!</p>
<p>Change the number inside <span class="code-to-type">range()</span> to control how many obstacles are created.</p>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and you should see several obstacles.</p>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 5: Collisions -->
<div class="slide" id="slide5">
<div class="slide-header">
<h2>Collisions</h2>
<div class="slide-number">Slide 6 of 11</div>
</div>
<p>Recall that in the first step you created a 'safe' colour.</p>
<div class="instruction-box">
<h4>Step 1: Create a variable for collision detection</h4>
<p>Create a variable to store the colour the player emoji is currently touching.</p>
</div>
<div class="code-block">
<code>def draw_player():<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">player_on = get(mouse_x, 320).hex</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;text('🤠', mouse_x, 320)</code>
</div>
<div class="instruction-box">
<h4>Step 2: Check for collisions</h4>
<p>If the player is touching the safe colour, draw the player emoji. If it is not, draw an explosion emoji to show they have crashed.</p>
</div>
<div class="code-block">
<code>def draw_player():<br>
&nbsp;&nbsp;&nbsp;&nbsp;player_on = get(mouse_x, 320).hex<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">if player_on == safe.hex:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">text('🤠', mouse_x, 320)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">else:</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-to-type">text('💥', mouse_x, 320)</span></code>
</div>
<div class="instruction-box">
<h4>Test:</h4>
<p>Run your code and move the player. You should see the explosion emoji if your player touches an obstacle.</p>
</div>
<div class="instruction-box">
<h4>Important Ordering:</h4>
<p>Make sure that in <span class="code-to-type">draw()</span>, the line of code to <span class="code-to-type">draw_obstacles()</span> is <strong>before</strong> <span class="code-to-type">draw_player()</span>. If you check for collisions before drawing the obstacles in a frame, then there won't be any obstacles to collide with!</p>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 6: Quick Quiz - Question 1 -->
<div class="slide" id="slide6">
<div class="slide-header">
<h2>Quick Quiz</h2>
<div class="slide-number">Slide 7 of 11</div>
</div>
<div class="instruction-box">
<h4>Quiz Instructions:</h4>
<p>Answer the three questions. There are hints to guide you to the correct answer.</p>
<p>When you have answered each question, click on your chosen answer to see feedback.</p>
<p>Have fun!</p>
</div>
<div class="quiz-question">
<h3>Question 1 of 3</h3>
<p>You have used a lot of if statements to control your game's behaviour. Some of them might have had more complex conditions, using <span class="highlight">and</span> to make multiple tests at once. If you ran the following piece of conditional code, what would you expect the output to be?</p>
<div class="code-block">
<code>score = 5000<br>
lives = 2<br><br>
if score >= 5000 and lives >= 3:<br>
&nbsp;&nbsp;&nbsp;&nbsp;print('Great flying!')<br><br>
if score >= 5000:<br>
&nbsp;&nbsp;&nbsp;&nbsp;print('Doing well!')<br>
&nbsp;&nbsp;&nbsp;&nbsp;if lives > 1:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print('Keep going!')<br>
&nbsp;&nbsp;&nbsp;&nbsp;else:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print('But be careful!')<br><br>
elif lives > 1:<br>
&nbsp;&nbsp;&nbsp;&nbsp;print('Push harder!')<br><br>
else:<br>
&nbsp;&nbsp;&nbsp;&nbsp;print('Head for base!')</code>
</div>
<div class="quiz-options">
<div class="quiz-option" onclick="selectAnswer(this, 1, 'A')">
A) Great flying!
</div>
<div class="quiz-option" onclick="selectAnswer(this, 1, 'B')">
B) Doing well! Keep going!
</div>
<div class="quiz-option" onclick="selectAnswer(this, 1, 'C')">
C) Doing well!
</div>
<div class="quiz-option" onclick="selectAnswer(this, 1, 'D')">
D) Push harder!
</div>
</div>
<div class="quiz-feedback incorrect" id="feedback1A">
<strong>Try again!</strong> While score >= 5000 is true, for an <span class="highlight">and</span> condition both parts must be true, and lives >= 3 is false.
</div>
<div class="quiz-feedback correct" id="feedback1B">
<strong>Correct!</strong> This is correct — score >= 5000 is true, and so is lives > 1 on the nested if statement.
</div>
<div class="quiz-feedback incorrect" id="feedback1C">
<strong>Try again!</strong> Close, but score >= 5000 isn't the only condition the program would find true as it ran.
</div>
<div class="quiz-feedback incorrect" id="feedback1D">
<strong>Try again!</strong> While lives > 1 is true, only the code inside the first true condition in an if/elif/else statement is executed, and lives > 1 is not the first condition that is true.
</div>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 7: Quick Quiz - Question 2 -->
<div class="slide" id="slide7">
<div class="slide-header">
<h2>Quick Quiz (Continued)</h2>
<div class="slide-number">Slide 8 of 11</div>
</div>
<div class="quiz-question">
<h3>Question 2 of 3</h3>
<p>In this project you used procedural generation — having the computer create and place parts of your world for you. While doing this is a great time saver, particularly if you're creating very large levels, it can create some issues. Which of these issues should you look out for when testing your procedural generation?</p>
<div class="quiz-options">
<div class="quiz-option" onclick="selectAnswer(this, 2, 'A')">
A) All of them
</div>
<div class="quiz-option" onclick="selectAnswer(this, 2, 'B')">
B) Obstacles could be generated that leave the player with no route forward.
</div>
<div class="quiz-option" onclick="selectAnswer(this, 2, 'C')">
C) Obstacles appear directly underneath the player.
</div>
<div class="quiz-option" onclick="selectAnswer(this, 2, 'D')">
D) The obstacles are all grouped together, leaving too much open space elsewhere.
</div>
</div>
<div class="quiz-feedback correct" id="feedback2A">
<strong>Correct!</strong> All of these can happen when using procedural generation. You can either add more code to check for and work around these issues, or try different seeds until you find one that works.
</div>
<div class="quiz-feedback incorrect" id="feedback2B">
<strong>Try again!</strong> This can happen with procedurally generated obstacles, particularly when the game first starts.<br><br>
<strong>Tip:</strong> You could work around this issue by preventing obstacles from appearing too close to the player's starting position. Can you think of other solutions?
</div>
<div class="quiz-feedback incorrect" id="feedback2C">
<strong>Try again!</strong> This can happen either at the start of the game, or when new obstacles are added as a result of increasing the difficulty level, if they happen to choose a position close to the player's.<br><br>
<strong>Tip:</strong> A potential solution might be to make the player temporarily immune to collision with all obstacles, or even only newly created obstacles, for a short time after a level increase. What problems might having the obstacle choose a new position create if it was too close to the player?
</div>
<div class="quiz-feedback incorrect" id="feedback2D">
<strong>Try again!</strong> Because random generation can choose groups of numbers that are close together, this can be a problem.<br><br>
<strong>Tip:</strong> One solution might be to switch to semi-random generation — break the screen up in to pieces and use random numbers to generate obstacles inside each of those pieces. Can you think of how you could use this sort of procedural generation to make your game more interesting, or more challenging?
</div>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 8: Quick Quiz - Question 3 -->
<div class="slide" id="slide8">
<div class="slide-header">
<h2>Quick Quiz (Continued)</h2>
<div class="slide-number">Slide 9 of 11</div>
</div>
<div class="quiz-question">
<h3>Question 3 of 3</h3>
<p>You made a game that you're really pleased with and shared it. A player has reviewed it and has shared some thoughtful feedback with some changes they would like to see.</p>
<p>What would be the best way to react to their suggestions?</p>
<div class="quiz-options">
<div class="quiz-option" onclick="selectAnswer(this, 3, 'A')">
A) Immediately make all the changes they have suggested.
</div>
<div class="quiz-option" onclick="selectAnswer(this, 3, 'B')">
B) Ignore the suggestions because you know best.
</div>
<div class="quiz-option" onclick="selectAnswer(this, 3, 'C')">
C) Consider their feedback with other feedback and decide how to improve your game.
</div>
<div class="quiz-option" onclick="selectAnswer(this, 3, 'D')">
D) Feel really sad that the player didn't think your game was perfect.
</div>
</div>
<div class="quiz-feedback incorrect" id="feedback3A">
<strong>Try again!</strong> It's great to get feedback, but you shouldn't change your game just to keep one player happy, maybe other players might give different feedback.
</div>
<div class="quiz-feedback incorrect" id="feedback3B">
<strong>Try again!</strong> Not quite. It's usually worth listening to what your users have to say about your work. If a player has given constructive feedback, then you should consider it.
</div>
<div class="quiz-feedback correct" id="feedback3C">
<strong>Correct!</strong> You should consider any feedback you get — while always trying to get more than one point of view — and make decisions to improve the game for all players.
</div>
<div class="quiz-feedback incorrect" id="feedback3D">
<strong>Try again!</strong> No! You shouldn't feel sad if someone suggests improvements to your game. Constructive feedback is really useful and can help improve your game. You should be pleased that they were interested enough in your game to give feedback.
</div>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 9: Learning Outcomes -->
<div class="slide" id="slide9">
<div class="slide-header">
<h2>Learning Outcomes</h2>
<div class="slide-number">Slide 10 of 11</div>
</div>
<div class="learning-outcomes">
<div class="outcome-card">
<h3>Variables Mastered</h3>
<p>✓ Create and use variables like <span class="highlight">safe</span>, <span class="highlight">player_on</span>, <span class="highlight">obstacle_x</span>, <span class="highlight">obstacle_y</span></p>
<p>✓ Understand RGB color values (0-255)</p>
<p>✓ Use <span class="highlight">frame_count</span> for animation</p>
</div>
<div class="outcome-card">
<h3>Functions Implemented</h3>
<p>✓ Create functions: <span class="highlight">draw_player()</span>, <span class="highlight">draw_obstacles()</span></p>
<p>✓ Call functions in proper order</p>
<p>✓ Use <span class="highlight">def</span> keyword to define functions</p>
</div>
<div class="outcome-card">
<h3>Loops & Control Flow</h3>
<p>✓ Use <span class="highlight">for</span> loops with <span class="highlight">range()</span></p>
<p>✓ Implement <span class="highlight">if/else</span> statements for collision detection</p>
<p>✓ Use modulo operator (<span class="highlight">%</span>) for wrapping</p>
</div>
<div class="outcome-card">
<h3>Game Development Skills</h3>
<p>✓ Procedural generation with <span class="highlight">randint()</span> and <span class="highlight">seed()</span></p>
<p>✓ Collision detection using color checking</p>
<p>✓ Player movement with <span class="highlight">mouse_x</span></p>
<p>✓ Game state management</p>
</div>
</div>
<div class="instruction-box">
<h4>What You've Accomplished</h4>
<p>You've built a complete endless runner game with:</p>
<ul>
<li>Player character that follows mouse movement</li>
<li>Randomly generated obstacles that scroll down the screen</li>
<li>Collision detection system</li>
<li>Visual feedback for collisions (explosion emoji)</li>
<li>Wrap-around obstacle system using modulo operator</li>
</ul>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)">
Next →
</button>
</div>
</div>
<!-- Slide 10: Challenge -->
<div class="slide" id="slide10">
<div class="slide-header">
<h2>Challenge</h2>
<div class="slide-number">Slide 11 of 11</div>
</div>
<p>Now it is over to you! Use the skills you have learned to finish the game.</p>
<div id="challengeList">
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Use different emojis to represent the player and the obstacles.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Draw the player or the obstacles using shapes instead (you learned this in the Make a face project).</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Draw the player or the obstacles using images instead (you learned this in the Rocket launch project).</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Change one line of code to make the obstacles move faster.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Create a variable and add one to it each time the player crashes.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Make the obstacles move faster after every crash.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Add an item for the player to pick up, which disappears when the player touches it.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Add a variable to keep track of the player's score.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Stop the game if the player crashes.</span>
</div>
<div class="challenge-item">
<div class="challenge-checkbox" onclick="toggleChallenge(this)"></div>
<span>Display a text message on the screen to say 'Game over'.</span>
</div>
</div>
<div class="game-preview">
<h3>Your Game Progress</h3>
<p id="progressText">0/10 challenges completed</p>
<div style="background: rgba(255,255,255,0.1); height: 20px; border-radius: 10px; margin: 15px 0;">
<div id="progressBar" style="background: linear-gradient(90deg, #4361ee, #3a0ca3); height: 100%; width: 0%; border-radius: 10px;"></div>
</div>
<p>Complete these challenges to enhance your game!</p>
</div>
<div class="instruction-box">
<h4>Tips for Success</h4>
<ul>
<li>Start with one challenge at a time</li>
<li>Test your code after each change</li>
<li>Use the emoji keyboard shortcuts provided earlier</li>
<li>Remember to save your project regularly</li>
<li>Share your completed game with others for feedback!</li>
</ul>
</div>
<div class="nav-buttons">
<button class="nav-button" onclick="changeSlide(-1)">
← Previous
</button>
<button class="nav-button" onclick="changeSlide(1)" disabled>
Next →
</button>
</div>
</div>
<!-- Slide Indicator -->
<div class="slide-indicator">
<div class="indicator-dot active" onclick="goToSlide(0)"></div>
<div class="indicator-dot" onclick="goToSlide(1)"></div>
<div class="indicator-dot" onclick="goToSlide(2)"></div>
<div class="indicator-dot" onclick="goToSlide(3)"></div>
<div class="indicator-dot" onclick="goToSlide(4)"></div>
<div class="indicator-dot" onclick="goToSlide(5)"></div>
<div class="indicator-dot" onclick="goToSlide(6)"></div>
<div class="indicator-dot" onclick="goToSlide(7)"></div>
<div class="indicator-dot" onclick="goToSlide(8)"></div>
<div class="indicator-dot" onclick="goToSlide(9)"></div>
<div class="indicator-dot" onclick="goToSlide(10)"></div>
</div>
</div>
<script>
// Presentation state
let currentSlide = 0;
const totalSlides = 11;
let playerEmoji = '🤠';
let obstacleEmoji = '🌵';
// Initialize presentation
document.addEventListener('DOMContentLoaded', function() {
// Initialize emoji grids
initializeEmojiGrids();
// Set up slide navigation
updateSlideNavigation();
});
// Change slide
function changeSlide(direction) {
const newSlide = currentSlide + direction;
if (newSlide >= 0 && newSlide < totalSlides) {
// Hide current slide
document.getElementById(`slide${currentSlide}`).classList.remove('active');
// Update indicator
document.querySelectorAll('.indicator-dot')[currentSlide].classList.remove('active');
// Show new slide
currentSlide = newSlide;
document.getElementById(`slide${currentSlide}`).classList.add('active');
// Update indicator
document.querySelectorAll('.indicator-dot')[currentSlide].classList.add('active');
// Update navigation buttons
updateSlideNavigation();
// Update slide numbers
updateSlideNumbers();
}
}
// Go to specific slide
function goToSlide(slideIndex) {
if (slideIndex >= 0 && slideIndex < totalSlides) {
// Hide current slide
document.getElementById(`slide${currentSlide}`).classList.remove('active');
// Update indicator
document.querySelectorAll('.indicator-dot')[currentSlide].classList.remove('active');
// Show new slide
currentSlide = slideIndex;
document.getElementById(`slide${currentSlide}`).classList.add('active');
// Update indicator
document.querySelectorAll('.indicator-dot')[currentSlide].classList.add('active');
// Update navigation buttons
updateSlideNavigation();
// Update slide numbers
updateSlideNumbers();
}
}
// Update navigation buttons
function updateSlideNavigation() {
const prevButtons = document.querySelectorAll('.nav-button');
prevButtons.forEach(button => {
if (button.textContent.includes('Previous')) {
button.disabled = currentSlide === 0;
} else if (button.textContent.includes('Next')) {
button.disabled = currentSlide === totalSlides - 1;
}
});
}
// Update slide numbers
function updateSlideNumbers() {
const slideNumbers = document.querySelectorAll('.slide-number');
slideNumbers.forEach((number, index) => {
// Update only active slide's number
if (index === currentSlide) {
number.textContent = `Slide ${currentSlide + 1} of ${totalSlides}`;
}
});
}
// Initialize emoji grids
function initializeEmojiGrids() {
const playerEmojis = ['🤠', '🐱', '🐶', '🦊', '🐯', '👾', '🚀', '👨‍🚀', '👩‍🚀', '🦸', '🦸‍♂️', '🦸‍♀️', '🧙', '🧚', '🐉', '😀', '😎', '🤖', '👻', '🐲'];
const obstacleEmojis = ['🌵', '💥', '🔥', '⭐', '🌟', '💎', '🪨', '🌋', '☄️', '🧨', '💣', '🧿', '⚡', '❄️', '🌀', '💀', '☠️', '👹', '👺', '🕷️'];
const playerGrid = document.getElementById('playerEmojiGrid');
const obstacleGrid = document.getElementById('obstacleEmojiGrid');
// Clear any existing content
playerGrid.innerHTML = '';
obstacleGrid.innerHTML = '';
// Add player emojis
playerEmojis.forEach(emoji => {
const emojiElement = document.createElement('div');
emojiElement.className = 'emoji-item';
emojiElement.textContent = emoji;
emojiElement.title = `Click to select ${emoji} as player`;
emojiElement.onclick = () => {
playerEmoji = emoji;
highlightSelectedEmoji(playerGrid, emojiElement);
alert(`Player emoji set to: ${emoji}\n\nNow update your code:\nChange text('🤠', mouse_x, 320) to:\ntext('${emoji}', mouse_x, 320)`);
};
playerGrid.appendChild(emojiElement);
});
// Add obstacle emojis
obstacleEmojis.forEach(emoji => {
const emojiElement = document.createElement('div');
emojiElement.className = 'emoji-item';
emojiElement.textContent = emoji;
emojiElement.title = `Click to select ${emoji} as obstacle`;
emojiElement.onclick = () => {
obstacleEmoji = emoji;
highlightSelectedEmoji(obstacleGrid, emojiElement);
alert(`Obstacle emoji set to: ${emoji}\n\nNow update your code:\nChange text('🌵', obstacle_x, obstacle_y) to:\ntext('${emoji}', obstacle_x, obstacle_y)`);
};
obstacleGrid.appendChild(emojiElement);
});
}
// Highlight selected emoji
function highlightSelectedEmoji(grid, selectedElement) {
// Remove highlight from all emojis in the grid
const allEmojis = grid.querySelectorAll('.emoji-item');
allEmojis.forEach(emoji => {
emoji.style.backgroundColor = '';
emoji.style.borderRadius = '';
emoji.style.border = '';
});
// Highlight the selected one
selectedElement.style.backgroundColor = 'rgba(67, 97, 238, 0.3)';
selectedElement.style.borderRadius = '8px';
selectedElement.style.border = '2px solid #4361ee';
}
// Quiz functionality
function selectAnswer(element, questionNumber, answer) {
// Remove selected class from all options in this question
const parent = element.parentElement;
const allOptions = parent.querySelectorAll('.quiz-option');
allOptions.forEach(opt => {
opt.classList.remove('selected', 'correct', 'incorrect');
});
// Hide all feedback for this question
for (let i = 1; i <= 4; i++) {
const feedback = document.getElementById(`feedback${questionNumber}${String.fromCharCode(64 + i)}`);
if (feedback) feedback.style.display = 'none';
}
// Add selected class to clicked option
element.classList.add('selected');
// Show appropriate feedback based on answer
const feedbackId = `feedback${questionNumber}${answer}`;
const feedbackElement = document.getElementById(feedbackId);
if (feedbackElement) {
feedbackElement.style.display = 'block';
// Add correct/incorrect class to option based on feedback
if (feedbackElement.classList.contains('correct')) {
element.classList.add('correct');
} else {
element.classList.add('incorrect');
}
}
}
// Challenge checklist
function toggleChallenge(checkbox) {
checkbox.classList.toggle('checked');
updateProgress();
}
// Update challenge progress
function updateProgress() {
const checkedBoxes = document.querySelectorAll('.challenge-checkbox.checked').length;
const totalChallenges = 10;
const percentage = (checkedBoxes / totalChallenges) * 100;
document.getElementById('progressBar').style.width = `${percentage}%`;
document.getElementById('progressText').textContent = `${checkedBoxes}/${totalChallenges} challenges completed`;
// Add celebratory message if all completed
if (checkedBoxes === totalChallenges) {
document.getElementById('progressText').innerHTML = `🎉 <strong>Congratulations! All challenges completed!</strong> 🎉`;
}
}
// Keyboard navigation
document.addEventListener('keydown', function(event) {
if (event.key === 'ArrowRight' || event.key === ' ') {
changeSlide(1);
} else if (event.key === 'ArrowLeft') {
changeSlide(-1);
} else if (event.key >= '1' && event.key <= '9') {
const slideNum = parseInt(event.key) - 1;
if (slideNum < totalSlides) {
goToSlide(slideNum);
}
} else if (event.key === '0') {
goToSlide(9);
}
});
</script>
</body>
</html>