-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into mvc-legos
- Loading branch information
Showing
10 changed files
with
1,167 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
186 changes: 186 additions & 0 deletions
186
build-python-turtle-game-space-invaders-clone/source_code_final/turtle_invaders.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
import random | ||
import time | ||
import turtle | ||
|
||
FRAME_RATE = 30 # Frames per second | ||
TIME_FOR_1_FRAME = 1 / FRAME_RATE # Seconds | ||
|
||
CANNON_STEP = 10 | ||
LASER_LENGTH = 20 | ||
LASER_SPEED = 20 | ||
ALIEN_SPAWN_INTERVAL = 1.2 # Seconds | ||
ALIEN_SPEED = 3.5 | ||
|
||
window = turtle.Screen() | ||
window.tracer(0) | ||
window.setup(0.5, 0.75) | ||
window.bgcolor(0.2, 0.2, 0.2) | ||
window.title("The Real Python Space Invaders") | ||
|
||
LEFT = -window.window_width() / 2 | ||
RIGHT = window.window_width() / 2 | ||
TOP = window.window_height() / 2 | ||
BOTTOM = -window.window_height() / 2 | ||
FLOOR_LEVEL = 0.9 * BOTTOM | ||
GUTTER = 0.025 * window.window_width() | ||
|
||
# Create laser cannon | ||
cannon = turtle.Turtle() | ||
cannon.penup() | ||
cannon.color(1, 1, 1) | ||
cannon.shape("square") | ||
cannon.setposition(0, FLOOR_LEVEL) | ||
cannon.cannon_movement = 0 # -1, 0 or 1 for left, stationary, right | ||
|
||
# Create turtle for writing text | ||
text = turtle.Turtle() | ||
text.penup() | ||
text.hideturtle() | ||
text.setposition(LEFT * 0.8, TOP * 0.8) | ||
text.color(1, 1, 1) | ||
|
||
lasers = [] | ||
aliens = [] | ||
|
||
|
||
def draw_cannon(): | ||
cannon.clear() | ||
cannon.turtlesize(1, 4) # Base | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 10) | ||
cannon.turtlesize(1, 1.5) # Next tier | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 20) | ||
cannon.turtlesize(0.8, 0.3) # Tip of cannon | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL) | ||
|
||
|
||
def move_left(): | ||
cannon.cannon_movement = -1 | ||
|
||
|
||
def move_right(): | ||
cannon.cannon_movement = 1 | ||
|
||
|
||
def stop_cannon_movement(): | ||
cannon.cannon_movement = 0 | ||
|
||
|
||
def create_laser(): | ||
laser = turtle.Turtle() | ||
laser.penup() | ||
laser.color(1, 0, 0) | ||
laser.hideturtle() | ||
laser.setposition(cannon.xcor(), cannon.ycor()) | ||
laser.setheading(90) | ||
# Move laser to just above cannon tip | ||
laser.forward(20) | ||
# Prepare to draw the laser | ||
laser.pendown() | ||
laser.pensize(5) | ||
|
||
lasers.append(laser) | ||
|
||
|
||
def move_laser(laser): | ||
laser.clear() | ||
laser.forward(LASER_SPEED) | ||
# Draw the laser | ||
laser.forward(LASER_LENGTH) | ||
laser.forward(-LASER_LENGTH) | ||
|
||
|
||
def create_alien(): | ||
alien = turtle.Turtle() | ||
alien.penup() | ||
alien.turtlesize(1.5) | ||
alien.setposition( | ||
random.randint( | ||
int(LEFT + GUTTER), | ||
int(RIGHT - GUTTER), | ||
), | ||
TOP, | ||
) | ||
alien.shape("turtle") | ||
alien.setheading(-90) | ||
alien.color(random.random(), random.random(), random.random()) | ||
aliens.append(alien) | ||
|
||
|
||
def remove_sprite(sprite, sprite_list): | ||
sprite.clear() | ||
sprite.hideturtle() | ||
window.update() | ||
sprite_list.remove(sprite) | ||
turtle.turtles().remove(sprite) | ||
|
||
|
||
# Key bindings | ||
window.onkeypress(move_left, "Left") | ||
window.onkeypress(move_right, "Right") | ||
window.onkeyrelease(stop_cannon_movement, "Left") | ||
window.onkeyrelease(stop_cannon_movement, "Right") | ||
window.onkeypress(create_laser, "space") | ||
window.onkeypress(turtle.bye, "q") | ||
window.listen() | ||
|
||
draw_cannon() | ||
|
||
# Game loop | ||
alien_timer = 0 | ||
game_timer = time.time() | ||
score = 0 | ||
game_running = True | ||
while game_running: | ||
timer_this_frame = time.time() | ||
|
||
time_elapsed = time.time() - game_timer | ||
text.clear() | ||
text.write( | ||
f"Time: {time_elapsed:5.1f}s\nScore: {score:5}", | ||
font=("Courier", 20, "bold"), | ||
) | ||
# Move cannon | ||
new_x = cannon.xcor() + CANNON_STEP * cannon.cannon_movement | ||
if LEFT + GUTTER <= new_x <= RIGHT - GUTTER: | ||
cannon.setx(new_x) | ||
draw_cannon() | ||
# Move all lasers | ||
for laser in lasers.copy(): | ||
move_laser(laser) | ||
# Remove laser if it goes off screen | ||
if laser.ycor() > TOP: | ||
remove_sprite(laser, lasers) | ||
break | ||
# Check for collision with aliens | ||
for alien in aliens.copy(): | ||
if laser.distance(alien) < 20: | ||
remove_sprite(laser, lasers) | ||
remove_sprite(alien, aliens) | ||
score += 1 | ||
break | ||
# Spawn new aliens when time interval elapsed | ||
if time.time() - alien_timer > ALIEN_SPAWN_INTERVAL: | ||
create_alien() | ||
alien_timer = time.time() | ||
|
||
# Move all aliens | ||
for alien in aliens: | ||
alien.forward(ALIEN_SPEED) | ||
# Check for game over | ||
if alien.ycor() < FLOOR_LEVEL: | ||
game_running = False | ||
break | ||
|
||
time_for_this_frame = time.time() - timer_this_frame | ||
if time_for_this_frame < TIME_FOR_1_FRAME: | ||
time.sleep(TIME_FOR_1_FRAME - time_for_this_frame) | ||
window.update() | ||
|
||
splash_text = turtle.Turtle() | ||
splash_text.hideturtle() | ||
splash_text.color(1, 1, 1) | ||
splash_text.write("GAME OVER", font=("Courier", 40, "bold"), align="center") | ||
turtle.done() |
32 changes: 32 additions & 0 deletions
32
build-python-turtle-game-space-invaders-clone/source_code_step_1/turtle_invaders.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import turtle | ||
|
||
window = turtle.Screen() | ||
window.setup(0.5, 0.75) | ||
window.bgcolor(0.2, 0.2, 0.2) | ||
window.title("The Real Python Space Invaders") | ||
|
||
LEFT = -window.window_width() / 2 | ||
RIGHT = window.window_width() / 2 | ||
TOP = window.window_height() / 2 | ||
BOTTOM = -window.window_height() / 2 | ||
FLOOR_LEVEL = 0.9 * BOTTOM | ||
|
||
# Create laser cannon | ||
cannon = turtle.Turtle() | ||
cannon.penup() | ||
cannon.color(1, 1, 1) | ||
cannon.shape("square") | ||
cannon.setposition(0, FLOOR_LEVEL) | ||
|
||
# Draw cannon | ||
cannon.turtlesize(1, 4) # Base | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 10) | ||
cannon.turtlesize(1, 1.5) # Next tier | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 20) | ||
cannon.turtlesize(0.8, 0.3) # Tip of cannon | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL) | ||
|
||
turtle.done() |
61 changes: 61 additions & 0 deletions
61
build-python-turtle-game-space-invaders-clone/source_code_step_2/turtle_invaders.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import turtle | ||
|
||
CANNON_STEP = 10 | ||
|
||
window = turtle.Screen() | ||
window.tracer(0) | ||
window.setup(0.5, 0.75) | ||
window.bgcolor(0.2, 0.2, 0.2) | ||
window.title("The Real Python Space Invaders") | ||
|
||
LEFT = -window.window_width() / 2 | ||
RIGHT = window.window_width() / 2 | ||
TOP = window.window_height() / 2 | ||
BOTTOM = -window.window_height() / 2 | ||
FLOOR_LEVEL = 0.9 * BOTTOM | ||
GUTTER = 0.025 * window.window_width() | ||
|
||
# Create laser cannon | ||
cannon = turtle.Turtle() | ||
cannon.penup() | ||
cannon.color(1, 1, 1) | ||
cannon.shape("square") | ||
cannon.setposition(0, FLOOR_LEVEL) | ||
|
||
|
||
def draw_cannon(): | ||
cannon.clear() | ||
cannon.turtlesize(1, 4) # Base | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 10) | ||
cannon.turtlesize(1, 1.5) # Next tier | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 20) | ||
cannon.turtlesize(0.8, 0.3) # Tip of cannon | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL) | ||
window.update() | ||
|
||
|
||
def move_left(): | ||
new_x = cannon.xcor() - CANNON_STEP | ||
if new_x >= LEFT + GUTTER: | ||
cannon.setx(new_x) | ||
draw_cannon() | ||
|
||
|
||
def move_right(): | ||
new_x = cannon.xcor() + CANNON_STEP | ||
if new_x <= RIGHT - GUTTER: | ||
cannon.setx(new_x) | ||
draw_cannon() | ||
|
||
|
||
window.onkeypress(move_left, "Left") | ||
window.onkeypress(move_right, "Right") | ||
window.onkeypress(turtle.bye, "q") | ||
window.listen() | ||
|
||
draw_cannon() | ||
|
||
turtle.done() |
103 changes: 103 additions & 0 deletions
103
build-python-turtle-game-space-invaders-clone/source_code_step_3/turtle_invaders.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import turtle | ||
|
||
CANNON_STEP = 10 | ||
LASER_LENGTH = 20 | ||
LASER_SPEED = 10 | ||
|
||
window = turtle.Screen() | ||
window.tracer(0) | ||
window.setup(0.5, 0.75) | ||
window.bgcolor(0.2, 0.2, 0.2) | ||
window.title("The Real Python Space Invaders") | ||
|
||
LEFT = -window.window_width() / 2 | ||
RIGHT = window.window_width() / 2 | ||
TOP = window.window_height() / 2 | ||
BOTTOM = -window.window_height() / 2 | ||
FLOOR_LEVEL = 0.9 * BOTTOM | ||
GUTTER = 0.025 * window.window_width() | ||
|
||
# Create laser cannon | ||
cannon = turtle.Turtle() | ||
cannon.penup() | ||
cannon.color(1, 1, 1) | ||
cannon.shape("square") | ||
cannon.setposition(0, FLOOR_LEVEL) | ||
|
||
lasers = [] | ||
|
||
|
||
def draw_cannon(): | ||
cannon.clear() | ||
cannon.turtlesize(1, 4) # Base | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 10) | ||
cannon.turtlesize(1, 1.5) # Next tier | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL + 20) | ||
cannon.turtlesize(0.8, 0.3) # Tip of cannon | ||
cannon.stamp() | ||
cannon.sety(FLOOR_LEVEL) | ||
|
||
|
||
def move_left(): | ||
new_x = cannon.xcor() - CANNON_STEP | ||
if new_x >= LEFT + GUTTER: | ||
cannon.setx(new_x) | ||
draw_cannon() | ||
|
||
|
||
def move_right(): | ||
new_x = cannon.xcor() + CANNON_STEP | ||
if new_x <= RIGHT - GUTTER: | ||
cannon.setx(new_x) | ||
draw_cannon() | ||
|
||
|
||
def create_laser(): | ||
laser = turtle.Turtle() | ||
laser.penup() | ||
laser.color(1, 0, 0) | ||
laser.hideturtle() | ||
laser.setposition(cannon.xcor(), cannon.ycor()) | ||
laser.setheading(90) | ||
# Move laser to just above cannon tip | ||
laser.forward(20) | ||
# Prepare to draw the laser | ||
laser.pendown() | ||
laser.pensize(5) | ||
|
||
lasers.append(laser) | ||
|
||
|
||
def move_laser(laser): | ||
laser.clear() | ||
laser.forward(LASER_SPEED) | ||
# Draw the laser | ||
laser.forward(LASER_LENGTH) | ||
laser.forward(-LASER_LENGTH) | ||
|
||
|
||
# Key bindings | ||
window.onkeypress(move_left, "Left") | ||
window.onkeypress(move_right, "Right") | ||
window.onkeypress(create_laser, "space") | ||
window.onkeypress(turtle.bye, "q") | ||
window.listen() | ||
|
||
draw_cannon() | ||
|
||
# Game loop | ||
while True: | ||
# Move all lasers | ||
for laser in lasers.copy(): | ||
move_laser(laser) | ||
# Remove laser if it goes off screen | ||
if laser.ycor() > TOP: | ||
laser.clear() | ||
laser.hideturtle() | ||
lasers.remove(laser) | ||
turtle.turtles().remove(laser) | ||
window.update() | ||
|
||
turtle.done() |
Oops, something went wrong.