diff --git a/MP4 Write-up and Reflection.pdf b/MP4 Write-up and Reflection.pdf new file mode 100644 index 00000000..e8f72bba Binary files /dev/null and b/MP4 Write-up and Reflection.pdf differ diff --git a/Project Proposals.pdf b/Project Proposals.pdf new file mode 100644 index 00000000..ed7a277e Binary files /dev/null and b/Project Proposals.pdf differ diff --git a/README.md b/README.md index 5f822327..57f0316c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,18 @@ # InteractiveProgramming This is the base repo for the interactive programming project for Software Design, Spring 2018 at Olin College. + +Packages needed: +pygame (`pip install pygame`) + +To run `tron-master.py`, enter `python3 tron-master.py` in the terminal window. + +How to play Tron: +WASD keys are used to control the green player while the arrow keys control the orange player. +To win the game, you must be the last one standing. +You die if you hit the walls surrounding the playing grid or if you run into the walls created from both players' paths indicated by the colored strips. +After a game ends, you can press the space bar to play again. +Enjoy! + +Link to Write-up and Reflection: +https://github.com/chiunaomi/InteractiveProgramming/blob/master/MP4%20Write-up%20and%20Reflection.pdf + diff --git a/tron-hn01.py b/tron-hn01.py new file mode 100644 index 00000000..c3ab8401 --- /dev/null +++ b/tron-hn01.py @@ -0,0 +1,241 @@ +"Naomi's Working Space" +import pygame +from pygame.locals import* +import time + +class PyGameWindowView(object): + def __init__(self,model,width=640,height=480): + self.model = model + size = (width,height) + self.model.screen = pygame.display.set_mode(size) + + def _init_draw(self): + self.model.screen.fill((105,105,105)) + self.model.cells = {} + cell_size = (self.model.cell_length, self.model.cell_length) + for i in range(self.model.height): + for j in range(self.model.width): + cell_coord = (i*self.model.cell_length,j*self.model.cell_length) + self.model.cells[(i,j)] = Cellview(self.model.screen,cell_coord,cell_size) + all_cells = self.model.cells.values() + + for cell in all_cells: + cell.draw() + + def draw(self): + self.model._draw_players() + pygame.display.update() + +class TronModelView(object): + def __init__(self,cell_length=10,width=640,height=480): + pygame.init() + size = (width,height) + self.screen = pygame.display.set_mode(size) + self.width = width + self.height = height + self.cell_length = cell_length + self.cell_lst = [] + self.player_paths = [] + self.player1 = Player(self.screen,10,(self.width/2+100),(self.height/2),"r",(255,140,0)) + self.player2 = Player(self.screen,10,(self.width/2-100),(self.height/2),"l",(0,255,0)) + self.cells_loc = {} + for i in range(self.height//cell_length): + for j in range(self.width//cell_length): + cell_coords = (i*self.cell_length, j*self.cell_length) + self.cell_lst.append(Cell(cell_coords, cell_length)) + + + + + + def in_cell(self): + for cell in self.cell_lst: + if self.player1.x in cell.xrange and self.player1.y in cell.yrange: + self.player1.current_cell = cell + break + + for cell in self.cell_lst: + if self.player2.x in cell.xrange and self.player2.y in cell.yrange: + self.player2.current_cell = cell + break + + def _draw_players(self): + self.player1.draw() + self.player2.draw() + + def update(self): + self.player1.update() + self.player2.update() + if self.player1.crash(): + self.end_game("PLAYER 2 ") + self.player1.dir = "None" + self.player2.dir = "None" + if self.player2.crash(): + self.end_game("PLAYER 1 ") + self.player1.dir = "None" + self.player2.dir = "None" + + """last_seen_p1 = self.player1.current_cell + last_seen_p2 = self.player2.current_cell + self.in_cell() + if self.player1.current_cell != last_seen_p1: + self.player_paths.append(last_seen_p1) + + if self.player2.current_cell != last_seen_p2: + self.player_paths.append(last_seen_p2)""" + + + if self.player1.current_cell in self.player_paths: + self.end_game("PLAYER 2 ") + self.player1.dir = "None" + self.player2.dir = "None" + if self.player2.current_cell in self.player_paths: + self.end_game("PLAYER 1 ") + self.player1.dir = "None" + self.player2.dir = "None" + + + def end_game(self,player): + pygame.display.set_caption(player + "WINS!") + + +class Cell(object): + def __init__(self,coords, cell_length): + self.xmin = coords[0] + self.ymin = coords[1] + self.xmax = coords[0] + cell_length + self.ymax = coords[1] + cell_length + self.xrange = range(self.xmin, self.xmax) + self.yrange = range(self.ymin, self.ymax) + +class Cellview(object): + def __init__(self, draw_screen, coordinates, cell_length): + self.draw_screen = draw_screen + self.coordinates = coordinates + self.side_length = cell_length + self.color = (0, 0, 0) + + def draw(self): + line_width = 1 + rect = pygame.Rect(self.coordinates, self.side_length) + pygame.draw.rect(self.draw_screen, self.color, rect, line_width) + +class Player(object): + def __init__(self, draw_screen, dimension, start_posx, start_posy, direction, color=(255,255,255)): + self.draw_screen = draw_screen + self.width = dimension + self.height = dimension + self.x = start_posx + self.y = start_posy + self.vx = 0 + self.vy = 0 + self.dir = direction + self.color = color + self.current_cell = None + + + + def draw(self): + line_width = .5 + pygame.draw.rect(self.draw_screen,self.color,pygame.Rect(self.x,self.y,self.width,self.height)) + + def update(self): + if self.dir == "r": + self.vx = 10 + self.vy = 0 + elif self.dir == "l": + self.vx = -10 + self.vy = 0 + elif self.dir == "u": + self.vx = 0 + self.vy = -10 + elif self.dir == "d": + self.vx = 0 + self.vy = 10 + elif self.dir == "None": + self.vx = 0 + self.vy = 0 + self.x += self.vx + self.y += self.vy + + + def crash(self): + if self.x == 640 or self.x == -10: + return True + if self.y == -10 or self.y == 480: + return True + return False + +class PlayerPath(object): + def __init__(self,model): + self.model = model + self.model.cells_loc = {} + for i in range(self.model.height): + for j in range(self.model.width): + cell_coords = (i*self.model.cell_length,j*self.model.cell_length) + self.model.cells_loc[(i,j)] = Cell(self.model.screen,cell_coords,cell_size) + + self.model.hit_cells = [(self.model.player1.x, self.model.player1.y), (self.model.player2.x, self.model.player2.y)] + + def update(self): + if (self.model.player1.x, self.model.player1.y) not in self.hit_cells: + self.hit_cells.append((player1.x, player1.y)) + if (self.model.player2.x, self.model.player2.y) not in self.hit_cells: + self.hit_cells.append + + + + +class KeyControl(object): + def __init__(self, model): + self.model = model + + def handle_event(self, event): + if event.type != KEYDOWN: + return + if event.key == pygame.K_LEFT: + if self.model.player1.dir != "r": + self.model.player1.dir = "l" + if event.key == pygame.K_RIGHT: + if self.model.player1.dir != "l": + self.model.player1.dir = "r" + if event.key == pygame.K_DOWN: + if self.model.player1.dir != "u": + self.model.player1.dir = "d" + if event.key == pygame.K_UP: + if self.model.player1.dir != "d": + self.model.player1.dir = "u" + + if event.key ==pygame.K_a: + if self.model.player2.dir != "r": + self.model.player2.dir = "l" + if event.key == pygame.K_d: + if self.model.player2.dir != "l": + self.model.player2.dir = "r" + if event.key == pygame.K_s: + if self.model.player2.dir != "u": + self.model.player2.dir = "d" + if event.key == pygame.K_w: + if self.model.player2.dir != "d": + self.model.player2.dir = "u" + + +if __name__ == '__main__': + pygame.init() + model = TronModelView() + view = PyGameWindowView(model) + view._init_draw() + controller = KeyControl(model) + + running = True + while running: + view._init_draw + for event in pygame.event.get(): + if event.type == QUIT: + running = False + controller.handle_event(event) + model.update() + view.draw() + time.sleep(.2) + + pygame.quit() diff --git a/tron-master.py b/tron-master.py new file mode 100644 index 00000000..56a4a03a --- /dev/null +++ b/tron-master.py @@ -0,0 +1,242 @@ +""" +Master Copy +Tron Remake + +@author: Naomi Chiu and Hadleigh Nunes +""" +import pygame +from pygame.locals import* +import time + +class PyGameWindowView(object): + """View object containing the visual elements of the game. + Takes a game model and renders its state onscreen""" + def __init__(self,model,width,height): + self.model = model + size = (width,height) + self.model.screen = pygame.display.set_mode(size) + + def _init_draw(self): + """Draws the grid on the screen and is only called at the beginning of a game.""" + self.model.screen.fill((105,105,105)) + self.model.cells = {} + cell_size = (self.model.cell_length, self.model.cell_length) + for i in range(self.model.height): + for j in range(self.model.width): + cell_coord = (i*self.model.cell_length,j*self.model.cell_length) + self.model.cells[(i,j)] = Cellview(self.model.screen,cell_coord,cell_size) + all_cells = self.model.cells.values() + for cell in all_cells: + cell.draw() + + def draw(self): + """Draws the player paths and is updated and redrawn constantly""" + self.model._draw_players() + pygame.display.update() + +class TronModelView(object): + """Model object containing the players, the game state, all cells, and the cells that have been hit.""" + def __init__(self,cell_length,width,height): + pygame.init() + size = (width,height) + self.screen = pygame.display.set_mode(size) + self.width = width + self.height = height + self.cell_length = cell_length + self.cell_lst = [] + self.player_paths = [] + self.player1 = Player(self.screen,10,(self.width/2+100),(self.height/2),"r",(255,140,0)) + self.player2 = Player(self.screen,10,(self.width/2-100),(self.height/2),"l",(0,255,0)) + for i in range(self.height//cell_length): + for j in range(self.width//cell_length): + self.cell_lst.append(Cell((i*self.cell_length,j*self.cell_length),cell_length)) + self.game_over = False + + def _draw_players(self): + """Calls the player objects' draw functions""" + self.player1.draw() + self.player2.draw() + + def in_cell(self): + """Loops through cell_lst to find the cell whose xrange contains player.x + and whose yrange contains player.y, and sets the player location to be within that cell.""" + for cell in self.cell_lst: + if self.player1.x in cell.xrange and self.player1.y in cell.yrange: + self.player1.current_cell = cell + break + for cell in self.cell_lst: + if self.player2.x in cell.xrange and self.player2.y in cell.yrange: + self.player2.current_cell = cell + break + + def update(self): + """Checks for new inputs and updates the game model.""" + self.player1.update() + self.player2.update() + if self.player1.crash(): + self.end_game("GREEN ") + if self.player2.crash(): + self.end_game("ORANGE ") + + last_seen_p1 = self.player1.current_cell + last_seen_p2 = self.player2.current_cell + # Saving the player locations before updating in order to test to see if the players + #have entered a new cell. + self.in_cell() + if self.player1.current_cell != last_seen_p1: + self.player_paths.append(last_seen_p1) + if self.player2.current_cell != last_seen_p2: + self.player_paths.append(last_seen_p2) + #If the player has left a cell and moved into another, the vacated cell is + #added to the list of cells that have been hit + + if self.player1.current_cell in self.player_paths: + self.end_game("GREEN ") + if self.player2.current_cell in self.player_paths: + self.end_game("ORANGE ") + + def end_game(self,player): + """Contains end game protocol""" + pygame.display.set_caption(player + "WINS!") + self.game_over = True + self.player1.dir = "None" + self.player2.dir = "None" + +class Cell(object): + """Square object with area and location + Used as building block for game grid""" + def __init__(self, coords, cell_length): + self.xrange = range(coords[0],coords[0]+cell_length) + self.yrange = range(coords[1],coords[1]+cell_length) + +class Cellview(object): + """Cell object defining the visualized form of a cell. + Not used structurally to define player locations, but used to visualize the game""" + def __init__(self, draw_screen, coordinates, side_length): + self.draw_screen = draw_screen + self.coordinates = coordinates + self.side_length = side_length + self.color = (0, 0, 0) + + def draw(self): + line_width = 1 + rect = pygame.Rect(self.coordinates, self.side_length) + pygame.draw.rect(self.draw_screen, self.color, rect, line_width) + +class Player(object): + """Contains player's location, direction and speed, as well as their color""" + def __init__(self, draw_screen, dimension, start_posx, start_posy, direction, color=(255,255,255)): + self.draw_screen = draw_screen + self.width = dimension + self.height = dimension + self.x = start_posx + self.y = start_posy + self.vx = 0 + self.vy = 0 + self.dir = direction + self.color = color + self.current_cell = None + + def draw(self): + line_width = .5 + pygame.draw.rect(self.draw_screen,self.color,pygame.Rect(self.x,self.y,self.width,self.height)) + + def update(self): + """Checks if players have changed directions, and then + adds the correct number of pixels to the player's position in the relevant direction""" + if self.dir == "r": + self.vx = 10 + self.vy = 0 + elif self.dir == "l": + self.vx = -10 + self.vy = 0 + elif self.dir == "u": + self.vx = 0 + self.vy = -10 + elif self.dir == "d": + self.vx = 0 + self.vy = 10 + elif self.dir == "None": + self.vx = 0 + self.vy = 0 + self.x += self.vx + self.y += self.vy + + def crash(self): + """Determines what happens if a player runs of the screen. + Used by the model to check if a player has lost.""" + if self.x == 640 or self.x == -10: + return True + if self.y == -10 or self.y == 480: + return True + return False + + +class KeyControl(object): + """Assigns key strokes as actions and implements them in game model""" + def __init__(self, model): + self.model = model + + def handle_event(self, event): + if event.type != KEYDOWN: + return #if no keys were pressed it quits + if event.key == pygame.K_LEFT and self.model.game_over != True: + if self.model.player1.dir != "r": + self.model.player1.dir = "l" + if event.key == pygame.K_RIGHT and self.model.game_over != True: + if self.model.player1.dir != "l": + self.model.player1.dir = "r" + if event.key == pygame.K_DOWN and self.model.game_over != True: + if self.model.player1.dir != "u": + self.model.player1.dir = "d" + if event.key == pygame.K_UP and self.model.game_over != True: + if self.model.player1.dir != "d": + self.model.player1.dir = "u" + + if event.key ==pygame.K_a and self.model.game_over != True: + if self.model.player2.dir != "r": + self.model.player2.dir = "l" + if event.key == pygame.K_d and self.model.game_over != True: + if self.model.player2.dir != "l": + self.model.player2.dir = "r" + if event.key == pygame.K_s and self.model.game_over != True: + if self.model.player2.dir != "u": + self.model.player2.dir = "d" + if event.key == pygame.K_w and self.model.game_over != True: + if self.model.player2.dir != "d": + self.model.player2.dir = "u" + + if event.key == pygame.K_SPACE and self.model.game_over == True: + return True + +if __name__ == '__main__': + + def main_loop(): + """A nested loop which initializes the game and runs the model until the end game protocol is called. + Hitting the space bar after a game ends reinitializes the loop which allows for a new match""" + pygame.init() + running = True + while running: + model = TronModelView(10,640,480) + view = PyGameWindowView(model,640,480) + view._init_draw() + controller = KeyControl(model) + + game_over = False + while not game_over: + for event in pygame.event.get(): + if event.type == QUIT: #if the window is closed, break out of the two while loops and go to pygame.quit() + running = False + game_over = True + if controller.handle_event(event): #checks to see if the game has ended and the spacebar was pressed, if yes then the inner loop is broken and the game is reinitialized + game_over = True + controller.handle_event(event) #handles regular keypress events + model.update() + view.draw() + time.sleep(.1) + for event in pygame.event.get(): + if event.type == QUIT: + running = False + pygame.quit() + + main_loop() diff --git a/tron-nc01.py b/tron-nc01.py new file mode 100644 index 00000000..dbf74f8e --- /dev/null +++ b/tron-nc01.py @@ -0,0 +1,210 @@ +"Naomi's Working Space" +import pygame +from pygame.locals import* +import time + +class PyGameWindowView(object): + def __init__(self,model,width,height): + self.model = model + size = (width,height) + self.model.screen = pygame.display.set_mode(size) + + def _init_draw(self): + self.model.screen.fill((105,105,105)) + self.model.cells = {} + cell_size = (self.model.cell_length, self.model.cell_length) + for i in range(self.model.height): + for j in range(self.model.width): + cell_coord = (i*self.model.cell_length,j*self.model.cell_length) + self.model.cells[(i,j)] = Cellview(self.model.screen,cell_coord,cell_size) + all_cells = self.model.cells.values() + for cell in all_cells: + cell.draw() + + def draw(self): + self.model._draw_players() + pygame.display.update() + +class TronModelView(object): + def __init__(self,cell_length,width,height): + pygame.init() + size = (width,height) + self.screen = pygame.display.set_mode(size) + self.width = width + self.height = height + self.cell_length = cell_length + self.cell_lst = [] + self.player_paths = [] + self.player1 = Player(self.screen,10,(self.width/2+100),(self.height/2),"r",(255,140,0)) + self.player2 = Player(self.screen,10,(self.width/2-100),(self.height/2),"l",(0,255,0)) + for i in range(self.height//cell_length): + for j in range(self.width//cell_length): + self.cell_lst.append(Cell((i*self.cell_length,j*self.cell_length),cell_length)) + self.game_over = False + + def _draw_players(self): + self.player1.draw() + self.player2.draw() + + def in_cell(self): + for cell in self.cell_lst: + if self.player1.x in cell.xrange and self.player1.y in cell.yrange: + self.player1.current_cell = cell + break + for cell in self.cell_lst: + if self.player2.x in cell.xrange and self.player2.y in cell.yrange: + self.player2.current_cell = cell + break + + def update(self): + self.player1.update() + self.player2.update() + if self.player1.crash(): + self.end_game("GREEN ") + if self.player2.crash(): + self.end_game("ORANGE ") + + last_seen_p1 = self.player1.current_cell + last_seen_p2 = self.player2.current_cell + self.in_cell() + if self.player1.current_cell != last_seen_p1: + self.player_paths.append(last_seen_p1) + if self.player2.current_cell != last_seen_p2: + self.player_paths.append(last_seen_p2) + + if self.player1.current_cell in self.player_paths: + self.end_game("GREEN ") + if self.player2.current_cell in self.player_paths: + self.end_game("ORANGE ") + + def end_game(self,player): + pygame.display.set_caption(player + "WINS!") + self.game_over = True + self.player1.dir = "None" + self.player2.dir = "None" + +class Cell(object): + def __init__(self, coords, cell_length): + self.xrange = range(coords[0],coords[0]+cell_length) + self.yrange = range(coords[1],coords[1]+cell_length) + +class Cellview(object): + def __init__(self, draw_screen, coordinates, side_length): + self.draw_screen = draw_screen + self.coordinates = coordinates + self.side_length = side_length + self.color = (0, 0, 0) + + def draw(self): + line_width = 1 + rect = pygame.Rect(self.coordinates, self.side_length) + pygame.draw.rect(self.draw_screen, self.color, rect, line_width) + +class Player(object): + def __init__(self, draw_screen, dimension, start_posx, start_posy, direction, color=(255,255,255)): + self.draw_screen = draw_screen + self.width = dimension + self.height = dimension + self.x = start_posx + self.y = start_posy + self.vx = 0 + self.vy = 0 + self.dir = direction + self.color = color + self.current_cell = None + + def draw(self): + line_width = .5 + pygame.draw.rect(self.draw_screen,self.color,pygame.Rect(self.x,self.y,self.width,self.height)) + + def update(self): + if self.dir == "r": + self.vx = 10 + self.vy = 0 + elif self.dir == "l": + self.vx = -10 + self.vy = 0 + elif self.dir == "u": + self.vx = 0 + self.vy = -10 + elif self.dir == "d": + self.vx = 0 + self.vy = 10 + elif self.dir == "None": + self.vx = 0 + self.vy = 0 + self.x += self.vx + self.y += self.vy + + def crash(self): + if self.x == 640 or self.x == -10: + return True + if self.y == -10 or self.y == 480: + return True + return False + +class KeyControl(object): + def __init__(self, model): + self.model = model + + def handle_event(self, event): + if event.type != KEYDOWN: + return + if event.key == pygame.K_LEFT and self.model.game_over != True: + if self.model.player1.dir != "r": + self.model.player1.dir = "l" + if event.key == pygame.K_RIGHT and self.model.game_over != True: + if self.model.player1.dir != "l": + self.model.player1.dir = "r" + if event.key == pygame.K_DOWN and self.model.game_over != True: + if self.model.player1.dir != "u": + self.model.player1.dir = "d" + if event.key == pygame.K_UP and self.model.game_over != True: + if self.model.player1.dir != "d": + self.model.player1.dir = "u" + + if event.key ==pygame.K_a and self.model.game_over != True: + if self.model.player2.dir != "r": + self.model.player2.dir = "l" + if event.key == pygame.K_d and self.model.game_over != True: + if self.model.player2.dir != "l": + self.model.player2.dir = "r" + if event.key == pygame.K_s and self.model.game_over != True: + if self.model.player2.dir != "u": + self.model.player2.dir = "d" + if event.key == pygame.K_w and self.model.game_over != True: + if self.model.player2.dir != "d": + self.model.player2.dir = "u" + + if event.key == pygame.K_SPACE and self.model.game_over == True: + return True + +if __name__ == '__main__': + + def main_loop(): + pygame.init() + running = True + while running: + model = TronModelView(10,640,480) + view = PyGameWindowView(model,640,480) + view._init_draw() + controller = KeyControl(model) + + game_over = False + while not game_over: + for event in pygame.event.get(): + if event.type == QUIT: + running = False + game_over = True + if controller.handle_event(event): + game_over = True + controller.handle_event(event) + model.update() + view.draw() + time.sleep(.1) + for event in pygame.event.get(): + if event.type == QUIT: + running = False + pygame.quit() + + main_loop()