Added Turtle Crossing (finished), also added start of Drone Invaders (very unfinished)
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
## Ben's Python Notes
|
||||||
|
This is my python notes, organized into a PyCharm project
|
19
Turtle/Drone Invaders/bomb.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from boundedturtle import BoundedTurtle
|
||||||
|
import math
|
||||||
|
from drone import Drone
|
||||||
|
from pygame import mixer
|
||||||
|
|
||||||
|
class Bomb(BoundedTurtle):
|
||||||
|
def __init__(self, initHeading, speed, xMin, xMax, yMin, yMax, scoreboard):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def move(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def distance(self, other):
|
||||||
|
p1 = self.position()
|
||||||
|
p2 = other.position()
|
||||||
|
return math.dist(p1, p2)
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
pass
|
50
Turtle/Drone Invaders/boundedturtle.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from abc import abstractmethod
|
||||||
|
from turtle import Turtle
|
||||||
|
|
||||||
|
class BoundedTurtle(Turtle):
|
||||||
|
def __init__(self, speed, xMin, xMax, yMin, yMax):
|
||||||
|
super().__init__()
|
||||||
|
self.__xMin = xMin
|
||||||
|
self.__xMax = xMax
|
||||||
|
self.__yMin = yMin
|
||||||
|
self.__yMax = yMax
|
||||||
|
self.__speed = speed
|
||||||
|
|
||||||
|
def outOfBounds(self):
|
||||||
|
xPos, yPos = self.position()
|
||||||
|
out = False
|
||||||
|
if xPos < self.__xMin or xPos > self.__xMax:
|
||||||
|
out = True
|
||||||
|
if yPos < self.__yMin or yPos > self.__yMax:
|
||||||
|
out = True
|
||||||
|
return out
|
||||||
|
|
||||||
|
def belowBottomBound(self):
|
||||||
|
x_pos, y_pos = self.position()
|
||||||
|
out = False
|
||||||
|
if y_pos < self.__yMin:
|
||||||
|
out = True
|
||||||
|
return out
|
||||||
|
|
||||||
|
def getSpeed(self):
|
||||||
|
return self.__speed
|
||||||
|
|
||||||
|
def getXMin(self):
|
||||||
|
return self.__xMin
|
||||||
|
|
||||||
|
def getXMax(self):
|
||||||
|
return self.__xMax
|
||||||
|
|
||||||
|
def getYMin(self):
|
||||||
|
return self.__yMin
|
||||||
|
|
||||||
|
def getYMax(self):
|
||||||
|
return self.__yMax
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def remove(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def move(self):
|
||||||
|
pass
|
29
Turtle/Drone Invaders/drone.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from boundedturtle import BoundedTurtle
|
||||||
|
import random
|
||||||
|
|
||||||
|
class Drone(BoundedTurtle):
|
||||||
|
|
||||||
|
droneList = [] #static variable
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getDrones():
|
||||||
|
return [x for x in Drone.droneList if x.__alive]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def destory_all():
|
||||||
|
for drone in Drone.droneList:
|
||||||
|
drone.remove()
|
||||||
|
Drone.droneList = []
|
||||||
|
|
||||||
|
def __init__(self, speed, xMin, xMax, yMin, yMax):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def move(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def alive(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
pass
|
21
Turtle/Drone Invaders/droneinvaders.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from turtle import Screen
|
||||||
|
from drone import Drone
|
||||||
|
from lasercannon import LaserCannon
|
||||||
|
from scoreboard import Scoreboard
|
||||||
|
import time
|
||||||
|
|
||||||
|
class DroneInvaders:
|
||||||
|
def __init__(self, xMin, xMax, yMin, yMax):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def addDrone(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
BIN
Turtle/Drone Invaders/images/Drone.gif
Normal file
After Width: | Height: | Size: 139 B |
BIN
Turtle/Drone Invaders/images/Drone64.gif
Normal file
After Width: | Height: | Size: 289 B |
BIN
Turtle/Drone Invaders/images/Drone64.png
Normal file
After Width: | Height: | Size: 425 B |
15
Turtle/Drone Invaders/lasercannon.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from turtle import Turtle
|
||||||
|
from bomb import Bomb
|
||||||
|
from pygame import mixer
|
||||||
|
|
||||||
|
class LaserCannon(Turtle):
|
||||||
|
def __init__(self, xMin, xMax, yMin, yMax, screen, scoreboard):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def aim(self, x, y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def shoot(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
14
Turtle/Drone Invaders/main.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from droneinvaders import DroneInvaders
|
||||||
|
import pygame
|
||||||
|
from pygame import mixer
|
||||||
|
|
||||||
|
pygame.init()
|
||||||
|
|
||||||
|
mixer.music.load('sounds/mixed_themes.ogg')
|
||||||
|
mixer.music.set_volume(0.05)
|
||||||
|
mixer.music.play(loops=-1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
di = DroneInvaders(-1, 1, -1, 1)
|
||||||
|
di.play()
|
18
Turtle/Drone Invaders/scoreboard.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
from turtle import Turtle
|
||||||
|
|
||||||
|
class Scoreboard(Turtle):
|
||||||
|
|
||||||
|
def __init__(self, x, y):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw_scoreboard(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def game_over(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def increment(self, amount):
|
||||||
|
pass
|
BIN
Turtle/Drone Invaders/sounds/explosion.wav
Normal file
BIN
Turtle/Drone Invaders/sounds/laser.wav
Normal file
BIN
Turtle/Drone Invaders/sounds/mixed_themes.ogg
Normal file
14
Turtle/Turtle Crossing/car.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from turtle import Turtle
|
||||||
|
|
||||||
|
|
||||||
|
class Car(Turtle):
|
||||||
|
|
||||||
|
def __init__(self, shape, start_position, direction, speed):
|
||||||
|
super().__init__(shape)
|
||||||
|
self.penup()
|
||||||
|
self.goto(start_position)
|
||||||
|
self.setheading(direction)
|
||||||
|
self.car_speed = speed
|
||||||
|
|
||||||
|
def move(self):
|
||||||
|
self.forward(self.car_speed)
|
87
Turtle/Turtle Crossing/car_manager.py
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
from car import Car
|
||||||
|
import random
|
||||||
|
import turtle
|
||||||
|
|
||||||
|
COLORS = ["red", "orange", "yellow", "green", "blue", "purple"]
|
||||||
|
CAR_TYPES = [["BlueCarRight.gif", "BrightGreenCarRight.gif", "DarkBlueCarRight.gif",
|
||||||
|
"GreenCarRight.gif", "BMW-Z4Right.gif"],
|
||||||
|
["BlueCarLeft.gif", "BrightGreenCarLeft.gif", "DarkBlueCarLeft.gif", "GreenCarLeft.gif", "BMW-Z4Left.gif"]]
|
||||||
|
STARTING_POSITIONS = [(0, (-350, -205)), (0, (-350, -145)), (0, (-350, -80)),
|
||||||
|
(180, (350, 80)), (180, (350, 145)), (180, (350, 205))]
|
||||||
|
BASE_MOVE_DISTANCE = 5
|
||||||
|
MOVE_INCREMENT = 10
|
||||||
|
|
||||||
|
|
||||||
|
class CarManager:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.cars = []
|
||||||
|
self.lanes = [0, 1, 2, 3, 4, 5]
|
||||||
|
self.last_lane = -1
|
||||||
|
for car_shape_list in CAR_TYPES:
|
||||||
|
for car_shape in car_shape_list:
|
||||||
|
car_shape = 'graphics/' + car_shape
|
||||||
|
turtle.register_shape(car_shape)
|
||||||
|
|
||||||
|
def create_car(self):
|
||||||
|
# Makes sure don't get 2 cars in a row in same lane
|
||||||
|
if len(self.lanes) == 0:
|
||||||
|
self.lanes = [0, 1, 2, 3, 4, 5]
|
||||||
|
lane = random.choice(self.lanes)
|
||||||
|
while lane == self.last_lane:
|
||||||
|
lane = random.choice(self.lanes)
|
||||||
|
self.lanes.remove(lane)
|
||||||
|
self.last_lane = lane
|
||||||
|
|
||||||
|
# Set up the car
|
||||||
|
starting_info = STARTING_POSITIONS[lane]
|
||||||
|
# Get car type (left or right) by using first index in starting_info, then set random shape (gif) accordingly
|
||||||
|
index = 0 if starting_info[0] == 0 else 1
|
||||||
|
shape = random.choice(CAR_TYPES[index])
|
||||||
|
shape = 'graphics/' + shape
|
||||||
|
|
||||||
|
# Create and add car
|
||||||
|
self.cars.append(Car(shape, starting_info[1], starting_info[0], BASE_MOVE_DISTANCE + random.randint(-1, 5)))
|
||||||
|
|
||||||
|
def update_cars(self):
|
||||||
|
# Remove cars that are finished going on road (off-screen and not coming back)
|
||||||
|
self.cars = [car for car in self.cars if (car.heading() == 0 and car.xcor() < 350)
|
||||||
|
or (car.heading() == 180 and car.xcor() > -350)]
|
||||||
|
# Iterate over remaining cars, and move them
|
||||||
|
for car in self.cars:
|
||||||
|
car.move()
|
||||||
|
|
||||||
|
def is_collision(self, other):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param other: A turtle object, or object of a child class of turtle
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# Get edges of other
|
||||||
|
other_top_edge = other.ycor() + 12
|
||||||
|
other_bottom_edge = other.ycor() - 12
|
||||||
|
other_left_edge = other.xcor() - 12
|
||||||
|
other_right_edge = other.xcor() + 12
|
||||||
|
|
||||||
|
# Check each car for whether the distance between edges overlaps
|
||||||
|
for car in self.cars:
|
||||||
|
car_top_edge = car.ycor() + 11
|
||||||
|
car_bottom_edge = car.ycor() - 11
|
||||||
|
car_left_edge = car.xcor() - 20
|
||||||
|
car_right_edge = car.xcor() + 20
|
||||||
|
# It's mom's spaghetti (code)
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
(other_top_edge - car_bottom_edge > 0 and car_top_edge - other_top_edge > 0)
|
||||||
|
or
|
||||||
|
(car_top_edge - other_bottom_edge > 0 and other_bottom_edge - car_bottom_edge > 0)
|
||||||
|
)
|
||||||
|
and
|
||||||
|
(
|
||||||
|
(other_left_edge - car_left_edge > 0 and car_right_edge - other_left_edge > 0)
|
||||||
|
or
|
||||||
|
(other_right_edge - car_left_edge > 0 and car_right_edge - other_right_edge > 0)
|
||||||
|
)
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
BIN
Turtle/Turtle Crossing/graphics/BMW-Z4Left.gif
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Turtle/Turtle Crossing/graphics/BMW-Z4Right.gif
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Turtle/Turtle Crossing/graphics/BlueCarLeft.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/BlueCarRight.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/BrightGreenCarLeft.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/BrightGreenCarRight.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/DarkBlueCarLeft.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/DarkBlueCarRight.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/GreenCarLeft.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/GreenCarRight.gif
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Turtle/Turtle Crossing/graphics/highway_lanes.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
21
Turtle/Turtle Crossing/player.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from turtle import Turtle
|
||||||
|
|
||||||
|
STARTING_POSITION = (0, -280)
|
||||||
|
MOVE_DISTANCE = 10
|
||||||
|
FINISH_LINE_Y = 280
|
||||||
|
|
||||||
|
|
||||||
|
class Player(Turtle):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__('turtle')
|
||||||
|
self.penup()
|
||||||
|
self.setheading(90)
|
||||||
|
self.reset_player()
|
||||||
|
|
||||||
|
def reset_player(self):
|
||||||
|
self.goto(STARTING_POSITION)
|
||||||
|
|
||||||
|
def move(self):
|
||||||
|
if self.ycor() <= FINISH_LINE_Y:
|
||||||
|
self.forward(MOVE_DISTANCE)
|
33
Turtle/Turtle Crossing/scoreboard.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
from turtle import Turtle
|
||||||
|
|
||||||
|
FONT = ("Courier", 20, "bold")
|
||||||
|
GAMEOVER_FONT = ("Courier", 28, "bold")
|
||||||
|
|
||||||
|
|
||||||
|
class Scoreboard(Turtle):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.level = 1
|
||||||
|
self.penup()
|
||||||
|
self.hideturtle()
|
||||||
|
self.goto(-280, 280 - 15)
|
||||||
|
self.delay = 0.1
|
||||||
|
self.car_prob = 0.1
|
||||||
|
self.display()
|
||||||
|
|
||||||
|
def update_level(self):
|
||||||
|
self.level += 1
|
||||||
|
self.delay *= 0.9
|
||||||
|
self.car_prob *= 1.02
|
||||||
|
self.display()
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
self.clear()
|
||||||
|
self.write(f'Level: {self.level}', font=FONT)
|
||||||
|
print(f'Delay: {self.delay}')
|
||||||
|
print(f'Car probability {self.car_prob}')
|
||||||
|
|
||||||
|
def game_over(self):
|
||||||
|
self.goto(0, -20)
|
||||||
|
self.write('GAME OVER', align='center')
|
53
Turtle/Turtle Crossing/turtle_crossing.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import time
|
||||||
|
from turtle import Screen
|
||||||
|
from player import Player, FINISH_LINE_Y
|
||||||
|
from car_manager import CarManager
|
||||||
|
from scoreboard import Scoreboard
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def soft_exit():
|
||||||
|
screen.bye()
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
screen = Screen()
|
||||||
|
screen.setup(width=600, height=600)
|
||||||
|
screen.bgpic('graphics/highway_lanes.png')
|
||||||
|
screen.tracer(False) # Turns off auto screen updates
|
||||||
|
screen.title('Turtle Crossing - *Definitely* not Frogger')
|
||||||
|
|
||||||
|
player = Player()
|
||||||
|
scoreboard = Scoreboard()
|
||||||
|
car_manager = CarManager()
|
||||||
|
|
||||||
|
car_manager.create_car()
|
||||||
|
screen.listen()
|
||||||
|
screen.onkey(fun=player.move, key='u') # Listens for 'w' key, and moves
|
||||||
|
screen.onkey(fun=soft_exit, key='q')
|
||||||
|
|
||||||
|
game_is_on = True
|
||||||
|
# The game loop
|
||||||
|
while game_is_on:
|
||||||
|
time.sleep(scoreboard.delay)
|
||||||
|
|
||||||
|
# Update cars (move the cars)
|
||||||
|
car_manager.update_cars()
|
||||||
|
|
||||||
|
# Check if turtle made it across
|
||||||
|
if player.ycor() >= FINISH_LINE_Y:
|
||||||
|
scoreboard.update_level()
|
||||||
|
player.reset_player()
|
||||||
|
|
||||||
|
# Check if another car should be added (10% chance at level 1)
|
||||||
|
if random.random() < scoreboard.car_prob:
|
||||||
|
car_manager.create_car()
|
||||||
|
|
||||||
|
# Check for collision with car
|
||||||
|
if car_manager.is_collision(player):
|
||||||
|
scoreboard.game_over()
|
||||||
|
game_is_on = False
|
||||||
|
|
||||||
|
screen.update()
|
||||||
|
|
||||||
|
screen.exitonclick()
|
|
@ -8,4 +8,4 @@
|
||||||
- Move forward: `turtle.forward(num_pixels)`
|
- Move forward: `turtle.forward(num_pixels)`
|
||||||
- Turn right: `turtle.right(degrees)`
|
- Turn right: `turtle.right(degrees)`
|
||||||
|
|
||||||
- For usage of turtle, look in Etch class. It's pretty self-explanatory.
|
- For usage of turtle, look in the example programs (Etch is simplest). It's pretty self-explanatory.
|