# For Python 3 only. # Program for a simple car game. # The game has a collection of cars that move in a rectangular # region, bounded by walls. # # If the car hits a wall, it crashes and won't move again. # The goal is to keep the cars away from the walls; the game ends # when all the cars have crashed and there are no moving cars. # The game starts with just a single car. # The user can click on a car to make it turn to the left # or the right (left button or right button) # The user can click on empty space to create a new car # As the game progresses, the cars gradually get faster. # The fewer cars there are, the more they accelerate. # Has two classes: # The Car class: # Represents an individual car. # A car has several methods: # __init__(x, y, direction) the constructor: # draw(): draws the car in its current position and direction # move(): makes the car move forward one pixel in its current direction # If it has hit one of the walls, the car crashes, and won't move # any more. # turn_left() makes the car change its direction to the left # turn_right() makes the car change its direction to the right # on(x, y) determines whether the position (x, y) is on top of the car # The CarGame class: # It has a constructor which sets up a window with a restart button and a canvas area, # and set up the responses to the left and right mouse buttons # The restart button will restart the game, by calling the start method. # start() will make a new list containing a single new car. # then loop until all the cars have crashed: # moving each car in the list # increasing the speed a little bit # sleeping for a short period (1/speed) # do_left() [to respond to left mouse button] # check through the list of cars to see if mouse was clicked on a car # if so, make the car turn to the left. # if not on any car, create a new car and add to the list # do_right() [to respond to right mouse button] # check through the list of cars to see if mouse was clicked on a car # if so, make the car turn to the right. # if not on any car, create a new car and add to the list # make_new_car() creates a new car at a random position and direction. # called by the previous three methods. from tkinter import * from random import randint import time game_size = 400 left_wall = 10 right_wall = left_wall+game_size top_wall = 10 bot_wall = top_wall+game_size directions = ["north", "south", "east", "west"] car_size = 10 # half the width of the car #------------------------------------------------------- class Car: # Constructor. Creates a car at a random position and direction in the game def __init__(self, xpos, ypos, dir): self.x = xpos self.y = ypos self.direction = dir self.crashed = False # is the car in a crashed state def is_crashed(self): return self.crashed # is the position (x, y) on the car def on(self, x, y) : left = self.x - car_size right = self.x + car_size top = self.y - car_size bot = self.y + car_size return x >= left and x <= right and y >= top and y <= bot # Move the car forward one pixel def move(self): if self.crashed : return if self.direction=="north" : self.y -= 1 elif self.direction=="south" : self.y += 1 elif self.direction=="east" : self.x += 1 elif self.direction=="west" : self.x -= 1 # check if crashed if self.y-car_size < top_wall or self.y+car_size > bot_wall or self.x-car_size < left_wall or self.x+car_size > right_wall : self.crashed = True # Draw the car def draw(self, canvas): left = self.x - car_size right = self.x + car_size top = self.y - car_size bot = self.y + car_size if self.crashed : canvas.create_rectangle(left, top, right, bot, fill="black") else : canvas.create_rectangle(left, top, right, bot, fill="red") if self.direction=="north" : top -= 4 elif self.direction=="south" : bot += 4 elif self.direction=="east" : right += 4 elif self.direction=="west" : left -= 4 canvas.create_rectangle(left, top, right, bot, fill="") def turn_left(self) : if self.direction=="north" : self.direction = "west" elif self.direction=="south" : self.direction = "east" elif self.direction=="east" : self.direction = "north" elif self.direction=="west" : self.direction = "south" def turn_right(self) : if self.direction=="north" : self.direction = "east" elif self.direction=="south" : self.direction = "west" elif self.direction=="east" : self.direction = "south" elif self.direction=="west" : self.direction = "north" #------------------------------------------------------- class CarGame: def __init__(self): self.cars = [] window = Tk() Button(window, text="Restart", command=self.start).pack() self.canvas = Canvas(window, height=game_size+20, width=game_size+20, bg="white") self.canvas.pack() self.canvas.bind("", self.do_left) self.canvas.bind("", self.do_right) self.redraw() window.mainloop() def redraw(self): self.canvas.delete(ALL) self.canvas.create_rectangle(10, 10, 10+game_size, 10+game_size) for car in self.cars : car.draw(self.canvas) self.canvas.update() # set the list of cars to contain just one car then loop, # moving the cars, then redrawing until there are no cars left def start(self) : self.cars = [] self.cars.append(self.make_new_car()) self.redraw() speed = 10 while True : for car in self.cars: car.move() self.redraw() num_live = 0 for car in self.cars: if not car.crashed : num_live += 1 if num_live <= 0: return speed += 0.1/num_live # make the speed a little bit bigger time.sleep(1/speed) # If clicked on car, make it turn left. Otherwise, make a new car at a random place def do_left(self, event): for car in self.cars : if car.on(event.x, event.y) : car.turn_left() return car = self.make_new_car() self.cars.append(car) # If clicked on car, make it turn right. Otherwise, make a new car at a random place def do_right(self, event): for car in self.cars : if car.on(event.x, event.y) : car.turn_right() return # if not clicked on any car, make a new one car = self.make_new_car() self.cars.append(car) def make_new_car(self): xpos = randint(left_wall + car_size, right_wall - car_size) ypos = randint(top_wall + car_size, bot_wall - car_size) dir = directions[randint(0,3)] return Car(xpos, ypos, dir) #This is necessary to start the program CarGame()