From 2de033a7ab800be6ad7fa00a1a9dc1303e1b0b76 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Wed, 18 Oct 2017 19:34:19 -0400 Subject: [PATCH 01/35] Create main game class --- Game4.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ misc.py | 24 ++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 Game4.py create mode 100644 misc.py diff --git a/Game4.py b/Game4.py new file mode 100644 index 0000000..70537e4 --- /dev/null +++ b/Game4.py @@ -0,0 +1,62 @@ +import os, sys +import pygame +from random import randint +from misc import Obstacle, colors + + +class Game4Main: + """The Main Game4 Class - This class handles the main + initialization and creating of the Game.""" + + def __init__(self, width=360,height=240): + """Initialize""" + """Initialize PyGame""" + pygame.init() + """Set the window Size""" + self.width = width + self.height = height + """Create the Screen""" + self.screen = pygame.display.set_mode((self.width + , self.height)) + + self.clock = pygame.time.Clock() + + + def mainLoop(self): + done = False + + rect_side = 10 + rect_x = self.width + rect_y = self.height - rect_side + + prev_time = 0 + obstacles = [Obstacle(rect_x, rect_y, rect_side, self.screen)] + delta = 500 + + while not done: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + done = True + + self.screen.fill(colors['BLACK']) + + current_time = pygame.time.get_ticks() + + if current_time - prev_time > delta: + obstacles.append(Obstacle(rect_x, rect_y, rect_side, self.screen)) + prev_time = current_time + delta = randint(500, 3000) + + for obstacle in obstacles: + obstacle.moveForward() + + obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] + #print(obstacles) + + pygame.display.flip() + self.clock.tick(60) + + +if __name__ == "__main__": + MainWindow = Game4Main() + MainWindow.mainLoop() diff --git a/misc.py b/misc.py new file mode 100644 index 0000000..7d41204 --- /dev/null +++ b/misc.py @@ -0,0 +1,24 @@ +import os, sys +import pygame + +colors = {'BLACK': (0, 0, 0), + 'WHITE' : (255, 255, 255), + 'GREEN' : (0, 255, 0), + 'RED' : (255, 0, 0), + 'BLUE' : (0, 0, 255), + } + +class Obstacle: + + def __init__(self, rect_x, rect_y, rect_side, screen): + self.rect_x = rect_x + self.rect_y = rect_y + self.rect_side = rect_side + self.screen = screen + + def moveForward(self): + self.rect_x -= 2 + pygame.draw.rect(self.screen, colors['BLUE'], [self.rect_x, self.rect_y, self.rect_side, self.rect_side]) + + def isGone(self): + return self.rect_x < 0 From 7d4d56abe7e542cd80a7b72d40786412542faedb Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Thu, 19 Oct 2017 11:11:56 -0400 Subject: [PATCH 02/35] Jumping Dot That Moves Side To Side --- playermoves.py | 25 +++++++++ pygame_base_template.py | 115 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 playermoves.py create mode 100644 pygame_base_template.py diff --git a/playermoves.py b/playermoves.py new file mode 100644 index 0000000..6121815 --- /dev/null +++ b/playermoves.py @@ -0,0 +1,25 @@ +import pygame +from pygame.locals import * +import time +from sys import exit +pygame.init() +def jump(ctime, startloc): + """ + Changes the y position up one frame + #for i in range(21): + + #print(jump(i,0)[1]) + """ + over = False + h = 100 + t = 20 + b = startloc + c = t/2 + a = h/((t/2)**2) + x = (ctime%20) + recty = (a*(x - c)**2)+b + + + if (x == 0): + over = True + return [recty, over] diff --git a/pygame_base_template.py b/pygame_base_template.py new file mode 100644 index 0000000..94b378f --- /dev/null +++ b/pygame_base_template.py @@ -0,0 +1,115 @@ +""" + Pygame base template for opening a window + + Sample Python/Pygame Programs + Simpson College Computer Science + http://programarcadegames.com/ + http://simpson.edu/computer-science/ + + Explanation video: http://youtu.be/vRB_983kUMc +""" + + + +import pygame +from playermoves import * + + +# Define some colors +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +GREEN = (0, 255, 0) +RED = (255, 0, 0) +jumping = False +pygame.init() + +# Set the width and height of the screen [width, height] +size = (700, 500) +screen = pygame.display.set_mode(size) + +pygame.display.set_caption("My Game") + +# Loop until the user clicks the close button. +done = False + +# Used to manage how fast the screen updates +clock = pygame.time.Clock() +frames = 0; +startjump = 0 +x_min = 0 +x_max = 200 +rectx = 100 +recty = 400 + +# -------- Main Program Loop ----------- +while not done: + + # --- Main event loop + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + done = True + #if event.type == pygame.KEYDOWN: +# + # if event.key == pygame.K_SPACE: + # if frames - startjump > 20: + # jumping = True + # startjump = frames + + pressed = pygame.key.get_pressed() + if pressed[pygame.K_UP]: + if frames - startjump > 20: + jumping = True + startjump = frames + if pressed[pygame.K_LEFT]: + if rectx > x_min: + rectx -= 5 + if pressed[pygame.K_RIGHT]: + if rectx < x_max: + rectx += 5 + + + + + + # --- Game logic should go here + + # --- Screen-clearing code goes here + + # Here, we clear the screen to white. Don't put other drawing commands + # above this, or they will be erased with this command. + + # If you want a background image, replace this clear with blit'ing the + # background image. + screen.fill(BLACK) + pygame.draw.rect(screen, RED, [0,425,700,100]) + jumpclock = frames%21 + + # --- Drawing code should go here + # --- Drawing code should go here + + jumpover = False + + #if False:#if detect_key_press() == 'space': + # jumping = True #if the spacebar is pressed start the jump + # print("boing") + #else: + # print(detect_key_press()) + if jumping == True: + recty = jump(frames-startjump+1,300)[0] + jumpover = jump(frames-startjump+1,300)[1] + if jumpover == True: + + jumping = False + + pygame.draw.rect(screen, WHITE, [rectx,recty,25,25]) + # --- Go ahead and update the screen with what we've drawn + pygame.display.flip() + frames+=1 # increments frame count + + # --- Limit to 60 frames per second + clock.tick(60) + + +# Close the window and quit. +pygame.quit() From 7881c0995373ad763ec8b8a815bbeb40b9ab0d88 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Thu, 19 Oct 2017 17:12:51 -0400 Subject: [PATCH 03/35] Add player and keyboard control --- Game4.py | 84 +++++++++++++++++++++++++++++++++++++++++++------------- misc.py | 52 ++++++++++++++++++++++++++++++----- 2 files changed, 110 insertions(+), 26 deletions(-) diff --git a/Game4.py b/Game4.py index 70537e4..9598e40 100644 --- a/Game4.py +++ b/Game4.py @@ -1,62 +1,108 @@ import os, sys import pygame from random import randint -from misc import Obstacle, colors +from misc import Obstacle, Player, colors, jump class Game4Main: """The Main Game4 Class - This class handles the main initialization and creating of the Game.""" - def __init__(self, width=360,height=240): - """Initialize""" - """Initialize PyGame""" + def __init__(self, width=600,height=480): + # initialize pygame pygame.init() - """Set the window Size""" + # set window size self.width = width self.height = height - """Create the Screen""" + # create screen self.screen = pygame.display.set_mode((self.width , self.height)) - + # initialize clock self.clock = pygame.time.Clock() def mainLoop(self): done = False - rect_side = 10 - rect_x = self.width - rect_y = self.height - rect_side - + # initialize player + jumping = False + frames = 0 + startjump = 0 + x_min = 0 + x_max = 200 + play_len = 25 + play_x = 100 + play_y = self.height - play_len + + # initialize obstacle length, x and y coordinates + obs_len = 25 + obs_x = self.width + obs_y = self.height - obs_len + # create list of obstacles with first obstacle + obstacles = [Obstacle(obs_x, obs_y, obs_len, self.screen)] + + # initialize time variables prev_time = 0 - obstacles = [Obstacle(rect_x, rect_y, rect_side, self.screen)] - delta = 500 + obs_dt = 500 + # main event loop while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True + # keyboard stuff + pressed = pygame.key.get_pressed() + if pressed[pygame.K_UP]: + if frames - startjump > 20: + jumping = True + startjump = frames + if pressed[pygame.K_LEFT]: + if play_x > x_min: + play_x -= 5 + if pressed[pygame.K_RIGHT]: + if play_x < x_max: + play_x += 5 + + # refresh screen self.screen.fill(colors['BLACK']) + #pygame.draw.rect(self.screen, colors['RED'], [0,self.height-(self.height/5),self.width,self.height/5]) + + jumpclock = frames%21 + jumpover = False + if jumping == True: + play_y = jump(frames-startjump+1,self.height-125, self.height)[0] + jumpover = jump(frames-startjump+1,self.height-125, self.height)[1] + if jumpover == True: + jumping = False + + pygame.draw.rect(self.screen, colors['WHITE'], [play_x,play_y,play_len,play_len]) + + # update current time current_time = pygame.time.get_ticks() - if current_time - prev_time > delta: - obstacles.append(Obstacle(rect_x, rect_y, rect_side, self.screen)) + # generate obstacle at random time + if current_time - prev_time > obs_dt: + obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen)) prev_time = current_time - delta = randint(500, 3000) + obs_dt = randint(500, 2000) + # move each obstacle forward for obstacle in obstacles: obstacle.moveForward() + # remove obstacle from list if off screen obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] - #print(obstacles) +# if player.isDead(): +# pygame.image.load("game_over.png") + + # update screen pygame.display.flip() + frames+=1 self.clock.tick(60) if __name__ == "__main__": - MainWindow = Game4Main() - MainWindow.mainLoop() + Game4Main().mainLoop() diff --git a/misc.py b/misc.py index 7d41204..724a079 100644 --- a/misc.py +++ b/misc.py @@ -1,6 +1,7 @@ import os, sys import pygame + colors = {'BLACK': (0, 0, 0), 'WHITE' : (255, 255, 255), 'GREEN' : (0, 255, 0), @@ -8,17 +9,54 @@ 'BLUE' : (0, 0, 255), } + class Obstacle: - def __init__(self, rect_x, rect_y, rect_side, screen): - self.rect_x = rect_x - self.rect_y = rect_y - self.rect_side = rect_side + def __init__(self, obs_x, obs_y, obs_len, screen): + self.obs_x = obs_x + self.obs_y = obs_y + self.obs_len = obs_len self.screen = screen + def __repr__(self): + return 'Obstacle({}, {}, {}, {})'.format(self.obs_x, self.obs_y, self.obs_len, self.screen) + def moveForward(self): - self.rect_x -= 2 - pygame.draw.rect(self.screen, colors['BLUE'], [self.rect_x, self.rect_y, self.rect_side, self.rect_side]) + self.obs_x -= 2 + pygame.draw.rect(self.screen, colors['BLUE'], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) def isGone(self): - return self.rect_x < 0 + return self.obs_x < -self.obs_len + + +class Player: + + def __init__(self, play_x, play_y, play_len, screen): + self.play_x = play_x + self.play_y = play_y + self.play_len = play_len + self.screen = screen + +# def __repr__(self): +# return 'Player({}, {}, {}, {})'.format(self.rect_x, self.rect_y, self.rect_side, self.screen) + +def jump(ctime, startloc, height): + """ + Changes the y position up one frame + #for i in range(21): + #print(jump(i,0)[1]) + """ + over = False + h = 100 + t = 20 + b = startloc + c = t/2 + a = h/((t/2)**2) + x = (ctime%20) + play_y = ((a*(x - c)**2)+b) + + + if (x == 0): + over = True + return [play_y, over] + #pygame.draw.rect(self.screen, colors['BLUE'], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) From ae5ded336279a66279897405fa96f8a257315f72 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sat, 21 Oct 2017 12:05:43 -0400 Subject: [PATCH 04/35] Add player class, collision detection, and game over --- Game4.py | 72 +++++++++++++++++++++++++-------------------------- gameover.png | Bin 0 -> 17263 bytes misc.py | 48 +++++++++++++++++++++++++++++++--- 3 files changed, 80 insertions(+), 40 deletions(-) create mode 100644 gameover.png diff --git a/Game4.py b/Game4.py index 9598e40..d8c69c6 100644 --- a/Game4.py +++ b/Game4.py @@ -8,31 +8,24 @@ class Game4Main: """The Main Game4 Class - This class handles the main initialization and creating of the Game.""" - def __init__(self, width=600,height=480): + def __init__(self, width=480,height=360): # initialize pygame pygame.init() # set window size self.width = width self.height = height # create screen - self.screen = pygame.display.set_mode((self.width - , self.height)) - # initialize clock + self.screen = pygame.display.set_mode((self.width, self.height)) + # create clock self.clock = pygame.time.Clock() def mainLoop(self): - done = False - # initialize player - jumping = False - frames = 0 - startjump = 0 - x_min = 0 - x_max = 200 play_len = 25 play_x = 100 play_y = self.height - play_len + player = Player(play_x, play_y, play_len, self.screen) # initialize obstacle length, x and y coordinates obs_len = 25 @@ -46,38 +39,26 @@ def mainLoop(self): obs_dt = 500 # main event loop - while not done: + while 1: for event in pygame.event.get(): if event.type == pygame.QUIT: - done = True + sys.exit() - # keyboard stuff + # check keyboard pressed = pygame.key.get_pressed() if pressed[pygame.K_UP]: - if frames - startjump > 20: - jumping = True - startjump = frames + player.jump() if pressed[pygame.K_LEFT]: - if play_x > x_min: - play_x -= 5 + player.moveLeft() if pressed[pygame.K_RIGHT]: - if play_x < x_max: - play_x += 5 + player.moveRight() # refresh screen self.screen.fill(colors['BLACK']) #pygame.draw.rect(self.screen, colors['RED'], [0,self.height-(self.height/5),self.width,self.height/5]) - jumpclock = frames%21 - jumpover = False - - if jumping == True: - play_y = jump(frames-startjump+1,self.height-125, self.height)[0] - jumpover = jump(frames-startjump+1,self.height-125, self.height)[1] - if jumpover == True: - jumping = False - - pygame.draw.rect(self.screen, colors['WHITE'], [play_x,play_y,play_len,play_len]) + player.update() + player.draw() # update current time current_time = pygame.time.get_ticks() @@ -86,23 +67,40 @@ def mainLoop(self): if current_time - prev_time > obs_dt: obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen)) prev_time = current_time - obs_dt = randint(500, 2000) + obs_dt = randint(1000, 3000) # move each obstacle forward for obstacle in obstacles: obstacle.moveForward() - + # check for collision between player and obstacles + if player.isCollide(obstacle.obs_x, obstacle.obs_y, obstacle.obs_len): + self.gameOver() # remove obstacle from list if off screen obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] -# if player.isDead(): -# pygame.image.load("game_over.png") - # update screen pygame.display.flip() - frames+=1 self.clock.tick(60) + def gameOver(self): + # main event loop + while 1: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + # check keyboard + pressed = pygame.key.get_pressed() + if pressed[pygame.K_UP]: + self.mainLoop() + + gameover = pygame.image.load("gameover.png") + gameover = pygame.transform.scale(gameover, (int(3*self.width/4), int(self.height/2))) + self.screen.blit(gameover, (int(self.width/8), int(self.height/4))) + + pygame.display.flip() + + if __name__ == "__main__": Game4Main().mainLoop() diff --git a/gameover.png b/gameover.png new file mode 100644 index 0000000000000000000000000000000000000000..24035b817faf14f23755faf631583366ebde484f GIT binary patch literal 17263 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 icRx_x`8#_~@Gv@=i*p6 0: + self.play_x -= self.speed + + def jump(self): + self.jumpInProgress = True + + def update(self): + if self.jumpInProgress: + dy = self.m * self.v + + self.play_y -= dy + self.v -= .75 + + if self.play_y >= self.floor: + self.play_y = self.floor + self.jumpInProgress = False + self.v = 10 + + def isCollide(self, obs_x, obs_y, obs_len): + obs_x0 = obs_x + obs_x1 = obs_x + obs_len + obs_y0 = obs_y + obs_y1 = obs_y + obs_len + play_x0 = self.play_x + play_x1 = self.play_x + self.play_len + play_y0 = self.play_y + play_y1 = self.play_y + self.play_len + if play_x0 in range(obs_x0, obs_x1) or play_x1 in range(obs_x0, obs_x1): + if play_y0 in range(obs_y0, obs_y1) or play_y1 in range(obs_y0, obs_y1): + return True + return False -# def __repr__(self): -# return 'Player({}, {}, {}, {})'.format(self.rect_x, self.rect_y, self.rect_side, self.screen) def jump(ctime, startloc, height): """ @@ -59,4 +102,3 @@ def jump(ctime, startloc, height): if (x == 0): over = True return [play_y, over] - #pygame.draw.rect(self.screen, colors['BLUE'], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) From 035bf5dd8d7b7e5aac34b207c21c303e2443ad8c Mon Sep 17 00:00:00 2001 From: Harrison Young Date: Sun, 22 Oct 2017 01:55:59 -0400 Subject: [PATCH 05/35] Added player summuned obsticals --- Game4.py | 11 +++++++++-- misc.py | 8 ++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Game4.py b/Game4.py index d8c69c6..4ddbbb2 100644 --- a/Game4.py +++ b/Game4.py @@ -32,6 +32,7 @@ def mainLoop(self): obs_x = self.width obs_y = self.height - obs_len # create list of obstacles with first obstacle + new_obstical = False obstacles = [Obstacle(obs_x, obs_y, obs_len, self.screen)] # initialize time variables @@ -43,8 +44,12 @@ def mainLoop(self): for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + new_obstical = True # check keyboard + down = pygame.key pressed = pygame.key.get_pressed() if pressed[pygame.K_UP]: player.jump() @@ -52,6 +57,7 @@ def mainLoop(self): player.moveLeft() if pressed[pygame.K_RIGHT]: player.moveRight() + # refresh screen self.screen.fill(colors['BLACK']) @@ -64,8 +70,9 @@ def mainLoop(self): current_time = pygame.time.get_ticks() # generate obstacle at random time - if current_time - prev_time > obs_dt: + if (current_time - prev_time > obs_dt) | new_obstical==True: obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen)) + new_obstical = False prev_time = current_time obs_dt = randint(1000, 3000) @@ -80,7 +87,7 @@ def mainLoop(self): # update screen pygame.display.flip() - self.clock.tick(60) + self.clock.tick(30) def gameOver(self): diff --git a/misc.py b/misc.py index d60d7c9..217fa81 100644 --- a/misc.py +++ b/misc.py @@ -22,7 +22,7 @@ def __repr__(self): return 'Obstacle({}, {}, {}, {})'.format(self.obs_x, self.obs_y, self.obs_len, self.screen) def moveForward(self): - self.obs_x -= 2 + self.obs_x -= 20 pygame.draw.rect(self.screen, colors['BLUE'], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) def isGone(self): @@ -46,7 +46,7 @@ def draw(self): pygame.draw.rect(self.screen, colors['WHITE'], [self.play_x, self.play_y, self.play_len, self.play_len]) def moveRight(self): - if self.play_x < 100: + if self.play_x < 200: self.play_x += self.speed def moveLeft(self): @@ -66,7 +66,7 @@ def update(self): if self.play_y >= self.floor: self.play_y = self.floor self.jumpInProgress = False - self.v = 10 + self.v = 7.5 def isCollide(self, obs_x, obs_y, obs_len): obs_x0 = obs_x @@ -90,7 +90,7 @@ def jump(ctime, startloc, height): #print(jump(i,0)[1]) """ over = False - h = 100 + h = hight t = 20 b = startloc c = t/2 From 860cf7cfb2901468c8e875fe90ec91c06a1a7c94 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Mon, 23 Oct 2017 19:36:58 -0400 Subject: [PATCH 06/35] Add stamina bar --- Game4.py | 14 +++++++++++--- misc.py | 45 +++++++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Game4.py b/Game4.py index 4ddbbb2..c9f3a99 100644 --- a/Game4.py +++ b/Game4.py @@ -1,7 +1,7 @@ import os, sys import pygame from random import randint -from misc import Obstacle, Player, colors, jump +from misc import Obstacle, Player, StaminaBar, colors class Game4Main: @@ -27,6 +27,9 @@ def mainLoop(self): play_y = self.height - play_len player = Player(play_x, play_y, play_len, self.screen) + # initialize stamina bar + stamina_bar = StaminaBar(self.screen) + # initialize obstacle length, x and y coordinates obs_len = 25 obs_x = self.width @@ -49,15 +52,17 @@ def mainLoop(self): new_obstical = True # check keyboard + pygame.key.set_repeat(500, 30) down = pygame.key pressed = pygame.key.get_pressed() - if pressed[pygame.K_UP]: + if pressed[pygame.K_UP] and stamina_bar.bars >= 10: player.jump() + stamina_bar.decreaseBar() + stamina_bar.draw() if pressed[pygame.K_LEFT]: player.moveLeft() if pressed[pygame.K_RIGHT]: player.moveRight() - # refresh screen self.screen.fill(colors['BLACK']) @@ -66,6 +71,9 @@ def mainLoop(self): player.update() player.draw() + stamina_bar.increaseBar() + stamina_bar.draw() + # update current time current_time = pygame.time.get_ticks() diff --git a/misc.py b/misc.py index 217fa81..96f5351 100644 --- a/misc.py +++ b/misc.py @@ -38,7 +38,7 @@ def __init__(self, play_x, play_y, play_len, screen): self.screen = screen self.speed = 5 self.jumpInProgress = False - self.v = 10 + self.v = 7.5 self.m = 2.5 self.floor = play_y @@ -83,22 +83,27 @@ def isCollide(self, obs_x, obs_y, obs_len): return False -def jump(ctime, startloc, height): - """ - Changes the y position up one frame - #for i in range(21): - #print(jump(i,0)[1]) - """ - over = False - h = hight - t = 20 - b = startloc - c = t/2 - a = h/((t/2)**2) - x = (ctime%20) - play_y = ((a*(x - c)**2)+b) - - - if (x == 0): - over = True - return [play_y, over] +class StaminaBar: + + def __init__(self, screen): + self.screen = screen + self.bars = 100 + self.clock = pygame.time.Clock() + self.prev_time = 0 + self.player_jump = False + + def draw(self): + pygame.draw.rect(self.screen, colors['WHITE'], [20, 20, self.bars, 10]) + + def decreaseBar(self): + current_time = pygame.time.get_ticks() + if current_time - self.prev_time >= 100: + self.bars -= 10 + self.prev_time = current_time + + def increaseBar(self): + if self.bars < 100: + current_time = pygame.time.get_ticks() + if current_time - self.prev_time >= 250: + self.bars += 1 + self.prev_time = current_time From dd67c711d3bc4212efdfa8ca8b882868482a2c37 Mon Sep 17 00:00:00 2001 From: Harrison Young Date: Mon, 23 Oct 2017 19:40:55 -0400 Subject: [PATCH 07/35] player two spawns obsticals at different hights --- Game4.py | 25 ++++++++++++++++++++----- misc.py | 25 ++++--------------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/Game4.py b/Game4.py index 4ddbbb2..8bfd276 100644 --- a/Game4.py +++ b/Game4.py @@ -1,7 +1,7 @@ import os, sys import pygame from random import randint -from misc import Obstacle, Player, colors, jump +from misc import * class Game4Main: @@ -31,9 +31,14 @@ def mainLoop(self): obs_len = 25 obs_x = self.width obs_y = self.height - obs_len + obstical_height = self.height - obs_len # create list of obstacles with first obstacle new_obstical = False - obstacles = [Obstacle(obs_x, obs_y, obs_len, self.screen)] + #Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE') + obstacles = [] + player_obsticals = [] + + # initialize time variables prev_time = 0 @@ -45,8 +50,15 @@ def mainLoop(self): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.KEYDOWN: - if event.key == pygame.K_SPACE: + if event.key == pygame.K_z: + new_obstical = True + obstical_height = obs_y + if event.key == pygame.K_x: new_obstical = True + obstical_height = obs_y-25 + if event.key == pygame.K_c: + new_obstical = True + obstical_height = obs_y-50 # check keyboard down = pygame.key @@ -70,11 +82,14 @@ def mainLoop(self): current_time = pygame.time.get_ticks() # generate obstacle at random time - if (current_time - prev_time > obs_dt) | new_obstical==True: - obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen)) + if (current_time - prev_time > obs_dt): + # obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE')) new_obstical = False prev_time = current_time obs_dt = randint(1000, 3000) + if (new_obstical == True): + new_obstical = False + obstacles.append(Obstacle(obs_x, obstical_height, obs_len, self.screen,'RED')) # move each obstacle forward for obstacle in obstacles: diff --git a/misc.py b/misc.py index 217fa81..f514f16 100644 --- a/misc.py +++ b/misc.py @@ -12,18 +12,20 @@ class Obstacle: - def __init__(self, obs_x, obs_y, obs_len, screen): + def __init__(self, obs_x, obs_y, obs_len, screen,color): self.obs_x = obs_x self.obs_y = obs_y self.obs_len = obs_len self.screen = screen + self.color = color def __repr__(self): return 'Obstacle({}, {}, {}, {})'.format(self.obs_x, self.obs_y, self.obs_len, self.screen) def moveForward(self): self.obs_x -= 20 - pygame.draw.rect(self.screen, colors['BLUE'], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) + # self.obs_y = height + pygame.draw.rect(self.screen, colors[self.color], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) def isGone(self): return self.obs_x < -self.obs_len @@ -83,22 +85,3 @@ def isCollide(self, obs_x, obs_y, obs_len): return False -def jump(ctime, startloc, height): - """ - Changes the y position up one frame - #for i in range(21): - #print(jump(i,0)[1]) - """ - over = False - h = hight - t = 20 - b = startloc - c = t/2 - a = h/((t/2)**2) - x = (ctime%20) - play_y = ((a*(x - c)**2)+b) - - - if (x == 0): - over = True - return [play_y, over] From a98883ffe1df6fa256364ee00e79bb62be694e8f Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Mon, 23 Oct 2017 20:05:43 -0400 Subject: [PATCH 08/35] Ad project writeup and reflection --- Project_Writeup_and_Reflection.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Project_Writeup_and_Reflection.md diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md new file mode 100644 index 0000000..4a9eb11 --- /dev/null +++ b/Project_Writeup_and_Reflection.md @@ -0,0 +1,25 @@ +# Project Writeup and Reflection + +### Project Overview [Maximum 100 words] + +*Write a short abstract describing your project.* + + + +### Results [~2-3 paragraphs + figures/examples] + +*Present what you accomplished. This will be different for each project, but screenshots are likely to be helpful.* + + + +### Implementation [~2-3 paragraphs + UML diagram] + +*Describe your implementation at a system architecture level. Include a UML class diagram, and talk about the major components, algorithms, data structures and how they fit together. You should also discuss at least one design decision where you had to choose between multiple alternatives, and explain why you made the choice you did.* + + + +### Reflection [~2 paragraphs] + +*From a process point of view, what went well? What could you improve? Other possible reflection topics: Was your project appropriately scoped? Did you have a good plan for unit testing? How will you use what you learned going forward? What do you wish you knew before you started that would have helped you succeed?* + +*Also discuss your team process in your reflection. How did you plan to divide the work (e.g. split by class, always pair program together, etc.) and how did it actually happen? Were there any issues that arose while working together, and how did you address them? What would you do differently next time?* From 41fc44836c8f33aace51d1c4d20a1bec47861b33 Mon Sep 17 00:00:00 2001 From: Harrison Young Date: Mon, 23 Oct 2017 21:13:21 -0400 Subject: [PATCH 09/35] added player 2 stamia bar --- Game4.py | 23 +++++++++++++++-------- misc.py | 16 +++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Game4.py b/Game4.py index 93950fd..1fa2e39 100644 --- a/Game4.py +++ b/Game4.py @@ -29,7 +29,8 @@ def mainLoop(self): player = Player(play_x, play_y, play_len, self.screen) # initialize stamina bar - stamina_bar = StaminaBar(self.screen) + P1_stamina_bar = StaminaBar(self.screen,25,"WHITE") + P2_stamina_bar = StaminaBar(self.screen,350,"RED") # initialize obstacle length, x and y coordinates obs_len = 25 @@ -68,10 +69,10 @@ def mainLoop(self): pygame.key.set_repeat(500, 30) down = pygame.key pressed = pygame.key.get_pressed() - if pressed[pygame.K_UP] and stamina_bar.bars >= 10: + if pressed[pygame.K_UP] and P1_stamina_bar.bars >= 25: player.jump() - stamina_bar.decreaseBar() - stamina_bar.draw() + P1_stamina_bar.decreaseBarleft(15) + P1_stamina_bar.draw() if pressed[pygame.K_LEFT]: player.moveLeft() if pressed[pygame.K_RIGHT]: @@ -84,20 +85,21 @@ def mainLoop(self): player.update() player.draw() - stamina_bar.increaseBar() - stamina_bar.draw() + + # update current time current_time = pygame.time.get_ticks() # generate obstacle at random time if (current_time - prev_time > obs_dt): - # obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE')) + #obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE')) new_obstical = False prev_time = current_time obs_dt = randint(1000, 3000) - if (new_obstical == True): + if (new_obstical == True and P2_stamina_bar.bars >= 33): new_obstical = False + P2_stamina_bar.decreaseBarleft(33) obstacles.append(Obstacle(obs_x, obstical_height, obs_len, self.screen,'RED')) # move each obstacle forward @@ -108,7 +110,12 @@ def mainLoop(self): self.gameOver() # remove obstacle from list if off screen obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] + P1_stamina_bar.increaseBarleft() + P1_stamina_bar.draw() + P2_stamina_bar.increaseBarleft() + P2_stamina_bar.increaseBarleft() + P2_stamina_bar.draw() # update screen pygame.display.flip() self.clock.tick(30) diff --git a/misc.py b/misc.py index cf07bb2..12e9d8e 100644 --- a/misc.py +++ b/misc.py @@ -68,7 +68,7 @@ def update(self): if self.play_y >= self.floor: self.play_y = self.floor self.jumpInProgress = False - self.v = 7.5 + self.v = 6 def isCollide(self, obs_x, obs_y, obs_len): obs_x0 = obs_x @@ -88,25 +88,27 @@ def isCollide(self, obs_x, obs_y, obs_len): class StaminaBar: - def __init__(self, screen): + def __init__(self, screen, start, color): self.screen = screen self.bars = 100 self.clock = pygame.time.Clock() self.prev_time = 0 self.player_jump = False + self.color = color + self.start = start def draw(self): - pygame.draw.rect(self.screen, colors['WHITE'], [20, 20, self.bars, 10]) + pygame.draw.rect(self.screen, colors[self.color], [self.start, 20, self.bars, 10]) - def decreaseBar(self): + def decreaseBarleft(self, decrease): current_time = pygame.time.get_ticks() if current_time - self.prev_time >= 100: - self.bars -= 10 + self.bars -= decrease self.prev_time = current_time - def increaseBar(self): + def increaseBarleft(self): if self.bars < 100: current_time = pygame.time.get_ticks() if current_time - self.prev_time >= 250: - self.bars += 1 + self.bars += 6 self.prev_time = current_time From 7bab5b1c11aa2893b0000f7f62863bbdbb97b97e Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Wed, 25 Oct 2017 17:11:31 -0400 Subject: [PATCH 10/35] Fix isCollide to work at different heights --- Game4.py | 2 -- misc.py | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Game4.py b/Game4.py index 1fa2e39..b4a3216 100644 --- a/Game4.py +++ b/Game4.py @@ -85,8 +85,6 @@ def mainLoop(self): player.update() player.draw() - - # update current time current_time = pygame.time.get_ticks() diff --git a/misc.py b/misc.py index 12e9d8e..b56eb13 100644 --- a/misc.py +++ b/misc.py @@ -12,7 +12,7 @@ class Obstacle: - def __init__(self, obs_x, obs_y, obs_len, screen,color): + def __init__(self, obs_x, obs_y, obs_len, screen, color): self.obs_x = obs_x self.obs_y = obs_y self.obs_len = obs_len @@ -79,10 +79,8 @@ def isCollide(self, obs_x, obs_y, obs_len): play_x1 = self.play_x + self.play_len play_y0 = self.play_y play_y1 = self.play_y + self.play_len - if play_x0 in range(obs_x0, obs_x1) or play_x1 in range(obs_x0, obs_x1): - if play_y0 in range(obs_y0, obs_y1) or play_y1 in range(obs_y0, obs_y1): - return True - return False + if (play_x0 in range(obs_x0, obs_x1) or play_x1 in range(obs_x0, obs_x1)) and (int(play_y0) in range(obs_y0, obs_y1) or int(play_y1) in range(obs_y0, obs_y1)): + return True From 0ede561ae0e7083b3dab831e8316965418e7c32c Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Thu, 26 Oct 2017 11:40:33 -0400 Subject: [PATCH 11/35] Change restart game key to space bar --- Game4.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Game4.py b/Game4.py index b4a3216..a3e6cf7 100644 --- a/Game4.py +++ b/Game4.py @@ -128,7 +128,7 @@ def gameOver(self): # check keyboard pressed = pygame.key.get_pressed() - if pressed[pygame.K_UP]: + if pressed[pygame.K_SPACE]: self.mainLoop() gameover = pygame.image.load("gameover.png") From 3d5ef9d7a90fc78a8b600fdf1cfe8ea89c3e31ae Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Thu, 26 Oct 2017 12:27:24 -0400 Subject: [PATCH 12/35] Add docstrings and comments --- Game4.py | 8 ++---- misc.py | 86 ++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/Game4.py b/Game4.py index a3e6cf7..8fd6f52 100644 --- a/Game4.py +++ b/Game4.py @@ -22,6 +22,7 @@ def __init__(self, width=480,height=360): def mainLoop(self): + """Main screen for game.""" # initialize player play_len = 25 play_x = 100 @@ -43,8 +44,6 @@ def mainLoop(self): obstacles = [] player_obsticals = [] - - # initialize time variables prev_time = 0 obs_dt = 500 @@ -66,10 +65,8 @@ def mainLoop(self): obstical_height = obs_y-50 # check keyboard - pygame.key.set_repeat(500, 30) - down = pygame.key pressed = pygame.key.get_pressed() - if pressed[pygame.K_UP] and P1_stamina_bar.bars >= 25: + if pressed[pygame.K_UP] and P1_stamina_bar.bars >= 15: player.jump() P1_stamina_bar.decreaseBarleft(15) P1_stamina_bar.draw() @@ -120,6 +117,7 @@ def mainLoop(self): def gameOver(self): + """Game over screen.""" # main event loop while 1: for event in pygame.event.get(): diff --git a/misc.py b/misc.py index b56eb13..4f383c1 100644 --- a/misc.py +++ b/misc.py @@ -11,66 +11,85 @@ class Obstacle: - + """A square obstacle, defined by its top left hand coordinate, length, and color. + Also takes in screen as an argument to draw the obstacle.""" def __init__(self, obs_x, obs_y, obs_len, screen, color): - self.obs_x = obs_x - self.obs_y = obs_y - self.obs_len = obs_len - self.screen = screen - self.color = color + """Initialize the instance.""" + self.obs_x = obs_x # top left hand x coordinate + self.obs_y = obs_y # top left hand y coordinate + self.obs_len = obs_len # side length + self.screen = screen # game screen + self.color = color # color of obstacle def __repr__(self): return 'Obstacle({}, {}, {}, {})'.format(self.obs_x, self.obs_y, self.obs_len, self.screen) def moveForward(self): + """Update horizontal location and draw obstacle.""" self.obs_x -= 20 - # self.obs_y = height pygame.draw.rect(self.screen, colors[self.color], [self.obs_x, self.obs_y, self.obs_len, self.obs_len]) def isGone(self): + """Check if obstacle is completely off screen.""" return self.obs_x < -self.obs_len class Player: - + """A square player, defined by its top left hand coordinate and length. + Also takes in screen as an argument to draw the player.""" def __init__(self, play_x, play_y, play_len, screen): - self.play_x = play_x - self.play_y = play_y - self.play_len = play_len - self.screen = screen - self.speed = 5 - self.jumpInProgress = False - self.v = 7.5 - self.m = 2.5 - self.floor = play_y + """Initialize the instance.""" + self.play_x = play_x # top left hand x coordinate + self.play_y = play_y # top left hand y coordinate + self.play_len = play_len # side length + self.screen = screen # game screen + self.speed = 5 # right/left speed + self.jumpInProgress = False # initialize to False + self.v = 7.5 # "velocity" for jump + self.m = 2.5 # "mass" for jump + self.floor = play_y # location of player before jump, used for comparison def draw(self): + """Draw player based on top left hand coordinate and length.""" pygame.draw.rect(self.screen, colors['WHITE'], [self.play_x, self.play_y, self.play_len, self.play_len]) def moveRight(self): + """Update horizontal location of player after moving right.""" if self.play_x < 200: self.play_x += self.speed def moveLeft(self): + """Update horizontal location of player after moving left.""" if self.play_x > 0: self.play_x -= self.speed def jump(self): + """Set jumping status.""" self.jumpInProgress = True def update(self): + """Update height of player during jump.""" if self.jumpInProgress: + # change in height = "mass" times "velocity" dy = self.m * self.v + # subtract height by change in height self.play_y -= dy + # decrease velocity self.v -= .75 + # stop jumping if player has landed if self.play_y >= self.floor: + # prevent player from falling through the floor self.play_y = self.floor + # no longer jumping self.jumpInProgress = False - self.v = 6 + # reset velocity + self.v = 7.5 def isCollide(self, obs_x, obs_y, obs_len): + """Check collision of player with obstacle.""" + # set coordinates for top left hand corner (0) and bottom right hand corner (1) obs_x0 = obs_x obs_x1 = obs_x + obs_len obs_y0 = obs_y @@ -79,34 +98,41 @@ def isCollide(self, obs_x, obs_y, obs_len): play_x1 = self.play_x + self.play_len play_y0 = self.play_y play_y1 = self.play_y + self.play_len + # check if player coordinates within obstacle coordinates if (play_x0 in range(obs_x0, obs_x1) or play_x1 in range(obs_x0, obs_x1)) and (int(play_y0) in range(obs_y0, obs_y1) or int(play_y1) in range(obs_y0, obs_y1)): return True class StaminaBar: - + """A stamina bar, defined by its starting location and color. + Also takes in screen as an argument to draw the stamina bar.""" def __init__(self, screen, start, color): - self.screen = screen - self.bars = 100 - self.clock = pygame.time.Clock() - self.prev_time = 0 + self.screen = screen # game screen + self.start = start # starting location of stamina bar + self.color = color # color of stamina bar + self.bars = 100 # initialize number of health bars + self.clock = pygame.time.Clock()# initialize clock + self.prev_time = 0 # initialize previous time self.player_jump = False - self.color = color - self.start = start def draw(self): + """Draw stamina bar based on color, starting location, and number of health bars.""" pygame.draw.rect(self.screen, colors[self.color], [self.start, 20, self.bars, 10]) - def decreaseBarleft(self, decrease): + def decreaseBarleft(self, num_bars): + """Decrease health bar by num_bars.""" current_time = pygame.time.get_ticks() - if current_time - self.prev_time >= 100: - self.bars -= decrease + # debounce decreasing bars + if current_time - self.prev_time >= 50: + self.bars -= num_bars self.prev_time = current_time def increaseBarleft(self): + """Increase health bar continuously if number of bars is lower than 100.""" if self.bars < 100: current_time = pygame.time.get_ticks() - if current_time - self.prev_time >= 250: - self.bars += 6 + # increase stamina bar by 1 every .05 seconds + if current_time - self.prev_time >= 50: + self.bars += 1 self.prev_time = current_time From 6b22ee88526933de7aef9969e2630a545e5166aa Mon Sep 17 00:00:00 2001 From: Harrison Young Date: Sat, 28 Oct 2017 19:57:15 -0400 Subject: [PATCH 13/35] Fixed stamina bar regeneration --- Game4.py | 19 +++++++++++-------- misc.py | 23 ++++++++++++----------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/Game4.py b/Game4.py index 8fd6f52..1141353 100644 --- a/Game4.py +++ b/Game4.py @@ -65,11 +65,15 @@ def mainLoop(self): obstical_height = obs_y-50 # check keyboard + pressed = pygame.key.get_pressed() - if pressed[pygame.K_UP] and P1_stamina_bar.bars >= 15: - player.jump() - P1_stamina_bar.decreaseBarleft(15) - P1_stamina_bar.draw() + if pressed[pygame.K_UP] and P1_stamina_bar.bars >= player.jumpcost: + if player.play_y == (360 - player.play_len) : + P1_stamina_bar.decreaseBarleft(player.jumpcost) + player.jump() + + P1_stamina_bar.draw() + if pressed[pygame.K_LEFT]: player.moveLeft() if pressed[pygame.K_RIGHT]: @@ -78,7 +82,7 @@ def mainLoop(self): # refresh screen self.screen.fill(colors['BLACK']) #pygame.draw.rect(self.screen, colors['RED'], [0,self.height-(self.height/5),self.width,self.height/5]) - + player.update() player.draw() @@ -106,10 +110,9 @@ def mainLoop(self): # remove obstacle from list if off screen obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] P1_stamina_bar.increaseBarleft() - P1_stamina_bar.draw() - P2_stamina_bar.increaseBarleft() - P2_stamina_bar.increaseBarleft() + P2_stamina_bar.increaseBarleft(1.5) + P1_stamina_bar.draw() P2_stamina_bar.draw() # update screen pygame.display.flip() diff --git a/misc.py b/misc.py index 4f383c1..b0457ba 100644 --- a/misc.py +++ b/misc.py @@ -43,19 +43,19 @@ def __init__(self, play_x, play_y, play_len, screen): self.play_y = play_y # top left hand y coordinate self.play_len = play_len # side length self.screen = screen # game screen - self.speed = 5 # right/left speed + self.speed = 10 # right/left speed self.jumpInProgress = False # initialize to False self.v = 7.5 # "velocity" for jump self.m = 2.5 # "mass" for jump self.floor = play_y # location of player before jump, used for comparison - + self.jumpcost = 30 def draw(self): """Draw player based on top left hand coordinate and length.""" pygame.draw.rect(self.screen, colors['WHITE'], [self.play_x, self.play_y, self.play_len, self.play_len]) def moveRight(self): """Update horizontal location of player after moving right.""" - if self.play_x < 200: + if self.play_x < 300: self.play_x += self.speed def moveLeft(self): @@ -94,6 +94,7 @@ def isCollide(self, obs_x, obs_y, obs_len): obs_x1 = obs_x + obs_len obs_y0 = obs_y obs_y1 = obs_y + obs_len + play_x0 = self.play_x play_x1 = self.play_x + self.play_len play_y0 = self.play_y @@ -124,15 +125,15 @@ def decreaseBarleft(self, num_bars): """Decrease health bar by num_bars.""" current_time = pygame.time.get_ticks() # debounce decreasing bars - if current_time - self.prev_time >= 50: - self.bars -= num_bars - self.prev_time = current_time + #if current_time - self.prev_time >= 50: + self.bars -= num_bars + self.prev_time = current_time - def increaseBarleft(self): + def increaseBarleft(self, speed = 1): """Increase health bar continuously if number of bars is lower than 100.""" if self.bars < 100: - current_time = pygame.time.get_ticks() + # current_time = pygame.time.get_ticks() # increase stamina bar by 1 every .05 seconds - if current_time - self.prev_time >= 50: - self.bars += 1 - self.prev_time = current_time + #if current_time - self.prev_time >= 10/self.speed: + self.bars += 1 * speed + #self.prev_time = current_time From d55ede1139c6723b381c4cbb177a742a98021116 Mon Sep 17 00:00:00 2001 From: Harrison Young Date: Sat, 28 Oct 2017 20:43:52 -0400 Subject: [PATCH 14/35] Added score and changed endgame scene --- Game4.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/Game4.py b/Game4.py index 1141353..c3f6156 100644 --- a/Game4.py +++ b/Game4.py @@ -19,11 +19,13 @@ def __init__(self, width=480,height=360): self.screen = pygame.display.set_mode((self.width, self.height)) # create clock self.clock = pygame.time.Clock() + self.score = 0 def mainLoop(self): """Main screen for game.""" # initialize player + count = 0 play_len = 25 play_x = 100 play_y = self.height - play_len @@ -50,6 +52,7 @@ def mainLoop(self): # main event loop while 1: + count+=1 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() @@ -106,7 +109,7 @@ def mainLoop(self): obstacle.moveForward() # check for collision between player and obstacles if player.isCollide(obstacle.obs_x, obstacle.obs_y, obstacle.obs_len): - self.gameOver() + self.gameOver(str(count)) # remove obstacle from list if off screen obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] P1_stamina_bar.increaseBarleft() @@ -114,12 +117,18 @@ def mainLoop(self): P2_stamina_bar.increaseBarleft(1.5) P1_stamina_bar.draw() P2_stamina_bar.draw() + + + font = pygame.font.SysFont("comicsansms", 72) + text = font.render(str(count), True, (255,255,255)) + self.screen.blit(text,[200,10]) # update screen pygame.display.flip() self.clock.tick(30) + - def gameOver(self): + def gameOver(self,score): """Game over screen.""" # main event loop while 1: @@ -131,10 +140,15 @@ def gameOver(self): pressed = pygame.key.get_pressed() if pressed[pygame.K_SPACE]: self.mainLoop() - - gameover = pygame.image.load("gameover.png") - gameover = pygame.transform.scale(gameover, (int(3*self.width/4), int(self.height/2))) - self.screen.blit(gameover, (int(self.width/8), int(self.height/4))) + self.screen.fill(colors['BLACK']) + font = pygame.font.SysFont("comicsansms", 28) + text = font.render("Player 1 recived a score of " + str(score), True, (255,255,255)) + self.screen.blit(text,[50,140]) + text = font.render("Press Space Bar to play again", True, (255,255,255)) + self.screen.blit(text,[50,178]) + #gameover = pygame.image.load("gameover.png") + #gameover = pygame.transform.scale(gameover, (int(3*self.width/4), int(self.height/2))) + #self.screen.blit(gameover, (int(self.width/8), int(self.height/4))) pygame.display.flip() From a4057a25c6738be6d1473966dc9880beefc85a2b Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 18:37:16 -0400 Subject: [PATCH 15/35] Update project writeup and reflection --- Project_Writeup_and_Reflection.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 4a9eb11..c3dccbd 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -4,22 +4,34 @@ *Write a short abstract describing your project.* - +Blockade is competitive arcade game. It has two players. Player 1 is a white block that is continually moving forward. Player 2’s job is to stop Player 1 by throwing obstacles in its way. Player 1 can avoid obstacles by jumping over or ducking under them. Both players are limited by a stamina bar. Actions such jumping or throwing obstacles depletes player’s stamina and if the stamina gets too low players cannot perform actions. The game uses keyboard inputs as commands. ### Results [~2-3 paragraphs + figures/examples] *Present what you accomplished. This will be different for each project, but screenshots are likely to be helpful.* +The game starts with Player 1 on the bottom left corner of the screen. Player 1’s objective is simple, avoid obstacles and get as far as you can. Player 1 can avoid obstacles by moving left, right or jumping. These actions are performed by pressing the Left, Right, and Up arrow keys respectively. Player 2 does not show up on screen but can make is presence known by throwing obstacles at Player 1. These obstacles can be thrown at three heights: ground level, just over Player 1 and High in the air. Player 2 can control the height of the obstacles thrown by pressing the Z, X, and C keys. The game ends when Player 1 collides with an obstacle and dies, Player 1’s score is determined by how long they survived. The competitive nature of the game come when the human players swap roles. With both trying to ensure the other gets a lower score. +Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. ### Implementation [~2-3 paragraphs + UML diagram] *Describe your implementation at a system architecture level. Include a UML class diagram, and talk about the major components, algorithms, data structures and how they fit together. You should also discuss at least one design decision where you had to choose between multiple alternatives, and explain why you made the choice you did.* +Our minimum viable product was a one player game similar to Google Chrome's dino run, in which the player jumps over randomly generated obstacles. The first class we created was for the main game. Its init handled the main initialization of the game. The mainLoop was a method that ran the main loop of the game, which got keyboard inputs and used them to control the player (and later the obstacles). We created two other classes. Unsurprisingly, they were the player and the obstacle. The obstacle only needed to move forward, so it had a moveForward method aside from init and repr, as well as isGone, used to delete obstacles off screen to prevent the programming from crashing from having to keep track of too many obstacles. The player had more requirements, such as moving left, moving right, and jumping, so we created the methods accordingly. We also added a method for collision detection in order to determine when game over should happen. We then created a gameOver method inside the main class game. We included a conditional statement in the mainLoop to direct the program to gameOver when the player collides with any obstacle and a conditional in gameOver to direct the program back to mainLoop when the space key is pressed. + +We got our MVP done by the mid-project check-in, so we added additional features to allow a second player to control the obstacles. We then created another class for the stamina bar, with one method to decrease the bar with every action (i.e. when the player jumps for the player's stamina bar and when an obstacle is generated for the second player's stamina bar) and increase the bar over time up to a certain length. +At one point, we considered implementing Model View Control. However, given the simplicity of our game, it wasn't worth rewriting whole sections just to split up the view and control into different classes. It would have cut down on the length of our mainLoop, but the pros just didn't outweigh the cons. Another decision that we made was to not create a subclass for each of the stamina bars since we only needed two and their only differences were their color and location, so we took them as arguments instead. ### Reflection [~2 paragraphs] *From a process point of view, what went well? What could you improve? Other possible reflection topics: Was your project appropriately scoped? Did you have a good plan for unit testing? How will you use what you learned going forward? What do you wish you knew before you started that would have helped you succeed?* *Also discuss your team process in your reflection. How did you plan to divide the work (e.g. split by class, always pair program together, etc.) and how did it actually happen? Were there any issues that arose while working together, and how did you address them? What would you do differently next time?* + +Our project was appropriately scoped. We were able to produce a minimum viable product by the mid-project check-in, so we used the second week to reach our stretch goal of allowing a second player to generate obstacles and adding stamina bars, a scorekeeper, and a display of the score on the game over screen. Unfortunately, Vivien's family came to visit the weekend before the project was due, so she could not spend as much time adding more features to the game as Harry really wanted to do. However, since we got quite a lot done early on, Vivien was able to spend time with her family and Harry just added some of the things he wanted to add. + +For the most part, we planned on dividing up the work based on what we wanted to complete within a period of time. We didn't look that far ahead, but planned at the beginning of each of our meetings what we wanted accomplished and divided the work sort of randomly. For example, to produce our MVP in our first round, one person created the player while the other created the randomly generated obstacles. The obstacle was created as an object, while the player was not, so the second person refactored the player into an object later on, as well as added a game over method in the main class. Then the first person added various features such as allowing a second player to control the obstacles, while the second person created the stamina bar. + +Since we were creating a game, which contained visuals, we were able to unit test by running the game every time we added something to make sure it worked. From c6a297ce93bd926431d3b9218a2b98b7b47b0dc7 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 20:32:59 -0400 Subject: [PATCH 16/35] Add screenshots of game --- screenshot1.png | Bin 0 -> 11364 bytes screenshot2.png | Bin 0 -> 13708 bytes screenshot3.png | Bin 0 -> 32450 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshot1.png create mode 100644 screenshot2.png create mode 100644 screenshot3.png diff --git a/screenshot1.png b/screenshot1.png new file mode 100644 index 0000000000000000000000000000000000000000..ee37f1ad8cfa055d0f8ddd406442c1709d9f984c GIT binary patch literal 11364 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 literal 0 HcmV?d00001 diff --git a/screenshot3.png b/screenshot3.png new file mode 100644 index 0000000000000000000000000000000000000000..1a340f9055cc588956b61ec669dcb1b254b32ea5 GIT binary patch literal 32450 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 bUqMAHat(^_Sbo5J=dn~3H56XUnTGx!Sq+ZD literal 0 HcmV?d00001 From 522df62e0d3471899d29643b7aaad00ed19759da Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 20:35:56 -0400 Subject: [PATCH 17/35] Add screenshots of game --- Project_Writeup_and_Reflection.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index c3dccbd..7c3393c 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -14,6 +14,12 @@ The game starts with Player 1 on the bottom left corner of the screen. Player 1 Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. +![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) + +![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot2.png) + +![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot3.png) + ### Implementation [~2-3 paragraphs + UML diagram] *Describe your implementation at a system architecture level. Include a UML class diagram, and talk about the major components, algorithms, data structures and how they fit together. You should also discuss at least one design decision where you had to choose between multiple alternatives, and explain why you made the choice you did.* From ea85407d4119f1b52696ab5b0f751d47b29b0f55 Mon Sep 17 00:00:00 2001 From: vivienyuwenchen Date: Sun, 29 Oct 2017 20:40:40 -0400 Subject: [PATCH 18/35] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 825cba1..37d5e73 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ # InteractiveProgramming This is the base repo for the interactive programming project for Software Design at Olin College. + +[Project Writeup and Reflection](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/Project_Writeup_and_Reflection.md) + +Required packages: +- pip install pygame + +To run the game: +- python Game4.py From 734db7c658f45a6e61dfd82c8372e40adedb3635 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 21:52:54 -0400 Subject: [PATCH 19/35] Update project writeup and reflection --- Project_Writeup_and_Reflection.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 7c3393c..2e5d4c5 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -28,7 +28,7 @@ Our minimum viable product was a one player game similar to Google Chrome's dino We got our MVP done by the mid-project check-in, so we added additional features to allow a second player to control the obstacles. We then created another class for the stamina bar, with one method to decrease the bar with every action (i.e. when the player jumps for the player's stamina bar and when an obstacle is generated for the second player's stamina bar) and increase the bar over time up to a certain length. -At one point, we considered implementing Model View Control. However, given the simplicity of our game, it wasn't worth rewriting whole sections just to split up the view and control into different classes. It would have cut down on the length of our mainLoop, but the pros just didn't outweigh the cons. Another decision that we made was to not create a subclass for each of the stamina bars since we only needed two and their only differences were their color and location, so we took them as arguments instead. +At one point, we considered implementing Model View Control. However, given the simplicity of our game, it wasn't worth rewriting whole sections just to split up the view and control into different classes. It would have cut down on the length of our mainLoop, but the pros just didn't outweigh the cons. Another decision that we made was to not create a subclass for each of the stamina bars since we only needed two and their only differences were their color and location, so we took those parameters as arguments instead. ### Reflection [~2 paragraphs] @@ -36,8 +36,10 @@ At one point, we considered implementing Model View Control. However, given the *Also discuss your team process in your reflection. How did you plan to divide the work (e.g. split by class, always pair program together, etc.) and how did it actually happen? Were there any issues that arose while working together, and how did you address them? What would you do differently next time?* -Our project was appropriately scoped. We were able to produce a minimum viable product by the mid-project check-in, so we used the second week to reach our stretch goal of allowing a second player to generate obstacles and adding stamina bars, a scorekeeper, and a display of the score on the game over screen. Unfortunately, Vivien's family came to visit the weekend before the project was due, so she could not spend as much time adding more features to the game as Harry really wanted to do. However, since we got quite a lot done early on, Vivien was able to spend time with her family and Harry just added some of the things he wanted to add. +Overall, this project went pretty well. We were able to deliver our MVP as well as a few of our stretch goals, like allowing a second player to generate obstacles and adding stamina bars, a scorekeeper, and a display of the score on the game over screen. For the most part, we planned on and were able to divide up the work based on what we wanted to complete within a period of time. We didn't look that far ahead, but planned at the beginning of each of our meetings what we wanted accomplished and divided the work as evenly as possible. Harry developed the main player and Vivien developed the obstacles. Once we made the two players, we both fixed bugs as they came up. -For the most part, we planned on dividing up the work based on what we wanted to complete within a period of time. We didn't look that far ahead, but planned at the beginning of each of our meetings what we wanted accomplished and divided the work sort of randomly. For example, to produce our MVP in our first round, one person created the player while the other created the randomly generated obstacles. The obstacle was created as an object, while the player was not, so the second person refactored the player into an object later on, as well as added a game over method in the main class. Then the first person added various features such as allowing a second player to control the obstacles, while the second person created the stamina bar. +One problem we ran into was keeping a consistent class format. We developed the two players independently and as a result each player was done a little differently. We refactored the main player into an object in order to keep them consistent with each other. For the most part, we were able to effectively work independently and met up to either discuss future features for the project or how to fix bugs. -Since we were creating a game, which contained visuals, we were able to unit test by running the game every time we added something to make sure it worked. +For a project of this scope our teamwork strategy was appropriate. However, it is not scalable. For larger projects we should spend more time planning out the classes so they can be easily integrated. We also tried to implement a CMV structure into the game; however, by that point most of the game had been written and changing the structure was deemed not worth the effort. If we were to do this project again we would have implement CMV from the beginning. + +Unfortunately, Vivien's family came to visit the weekend before the project was due, so she could not spend as much time adding more features to the game as Harry really wanted to do. However, since we got quite a lot done early on, Vivien was able to spend time with her family and Harry just added some of the things he wanted to add. From 58d7c1ba4b174cd2d46a46a7d196b5c97e62aa24 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:10:38 -0400 Subject: [PATCH 20/35] Added Captions To figures --- Project_Writeup_and_Reflection.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 2e5d4c5..3f08f73 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -15,10 +15,13 @@ The game starts with Player 1 on the bottom left corner of the screen. Player 1 Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) +Figure 1: This is how the game starts. Player 1 is the white square in the bottom left corner. PLayer 1’s distance is in the top center of the screen. The stamina bars for Player 1 and 2 are in the top left and right screen respectively. ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot2.png) +Figure 2: During the game Player 1 avoids the red obstacles by jumping. Player 2 can spawn red obstacles at multiple heights. Player 2’s staminal bar(red) has almost been depleted. ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot3.png) +Figure 3: Game over screen reports the distance Player 1 traveled and gives instructions for how to play again. ### Implementation [~2-3 paragraphs + UML diagram] From af2ed11650e49c51fcffdd438456090c4252e8a4 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:11:49 -0400 Subject: [PATCH 21/35] Fixed Caption Spacing --- Project_Writeup_and_Reflection.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 3f08f73..ef1e81e 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -15,12 +15,15 @@ The game starts with Player 1 on the bottom left corner of the screen. Player 1 Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) + Figure 1: This is how the game starts. Player 1 is the white square in the bottom left corner. PLayer 1’s distance is in the top center of the screen. The stamina bars for Player 1 and 2 are in the top left and right screen respectively. ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot2.png) + Figure 2: During the game Player 1 avoids the red obstacles by jumping. Player 2 can spawn red obstacles at multiple heights. Player 2’s staminal bar(red) has almost been depleted. ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot3.png) + Figure 3: Game over screen reports the distance Player 1 traveled and gives instructions for how to play again. ### Implementation [~2-3 paragraphs + UML diagram] From 0f268098ce6a2c6a6769b58c89fdb946c2da972d Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 22:16:17 -0400 Subject: [PATCH 22/35] Update inline comments --- Game4.py | 50 +++++++++++++++++++++++++++++--------------------- misc.py | 16 ++-------------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/Game4.py b/Game4.py index c3f6156..e91b5f0 100644 --- a/Game4.py +++ b/Game4.py @@ -31,7 +31,7 @@ def mainLoop(self): play_y = self.height - play_len player = Player(play_x, play_y, play_len, self.screen) - # initialize stamina bar + # initialize stamina bars P1_stamina_bar = StaminaBar(self.screen,25,"WHITE") P2_stamina_bar = StaminaBar(self.screen,350,"RED") @@ -40,11 +40,13 @@ def mainLoop(self): obs_x = self.width obs_y = self.height - obs_len obstical_height = self.height - obs_len - # create list of obstacles with first obstacle - new_obstical = False - #Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE') + + # create list of obstacles obstacles = [] - player_obsticals = [] + new_obstical = False + # uncomment and place line below in [] of obstacles = [] to generate random obstacles: + # Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE') + # initialize time variables prev_time = 0 @@ -56,49 +58,54 @@ def mainLoop(self): for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() + # check keyboard for obstacle player if event.type == pygame.KEYDOWN: + # z to create obstacle at ground level if event.key == pygame.K_z: new_obstical = True obstical_height = obs_y + # x to create obstacle at second level if event.key == pygame.K_x: new_obstical = True obstical_height = obs_y-25 + # c to create obstacle at third level if event.key == pygame.K_c: new_obstical = True obstical_height = obs_y-50 - # check keyboard - + # check keyboard for main player pressed = pygame.key.get_pressed() + # up to jump if pressed[pygame.K_UP] and P1_stamina_bar.bars >= player.jumpcost: - if player.play_y == (360 - player.play_len) : + if player.play_y == (360 - player.play_len): P1_stamina_bar.decreaseBarleft(player.jumpcost) player.jump() - P1_stamina_bar.draw() - + # left to move left if pressed[pygame.K_LEFT]: player.moveLeft() + # right to move right if pressed[pygame.K_RIGHT]: player.moveRight() # refresh screen self.screen.fill(colors['BLACK']) - #pygame.draw.rect(self.screen, colors['RED'], [0,self.height-(self.height/5),self.width,self.height/5]) - + + # update and draw player player.update() player.draw() - # update current time current_time = pygame.time.get_ticks() # generate obstacle at random time if (current_time - prev_time > obs_dt): - #obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE')) + # uncomment below to generate random obstacles: + # obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE')) new_obstical = False prev_time = current_time obs_dt = randint(1000, 3000) + # generate obstacle player's obstacle at appropriate height if (new_obstical == True and P2_stamina_bar.bars >= 33): new_obstical = False P2_stamina_bar.decreaseBarleft(33) @@ -112,20 +119,21 @@ def mainLoop(self): self.gameOver(str(count)) # remove obstacle from list if off screen obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] - P1_stamina_bar.increaseBarleft() + # update stamina bars + P1_stamina_bar.increaseBarleft() P2_stamina_bar.increaseBarleft(1.5) P1_stamina_bar.draw() P2_stamina_bar.draw() - + # display score font = pygame.font.SysFont("comicsansms", 72) text = font.render(str(count), True, (255,255,255)) self.screen.blit(text,[200,10]) + # update screen pygame.display.flip() self.clock.tick(30) - def gameOver(self,score): @@ -136,20 +144,20 @@ def gameOver(self,score): if event.type == pygame.QUIT: sys.exit() - # check keyboard + # check keyboard for space key to restart game pressed = pygame.key.get_pressed() if pressed[pygame.K_SPACE]: self.mainLoop() + + # display game over screen self.screen.fill(colors['BLACK']) font = pygame.font.SysFont("comicsansms", 28) text = font.render("Player 1 recived a score of " + str(score), True, (255,255,255)) self.screen.blit(text,[50,140]) text = font.render("Press Space Bar to play again", True, (255,255,255)) self.screen.blit(text,[50,178]) - #gameover = pygame.image.load("gameover.png") - #gameover = pygame.transform.scale(gameover, (int(3*self.width/4), int(self.height/2))) - #self.screen.blit(gameover, (int(self.width/8), int(self.height/4))) + # update screen pygame.display.flip() diff --git a/misc.py b/misc.py index b0457ba..5aa33a9 100644 --- a/misc.py +++ b/misc.py @@ -89,12 +89,12 @@ def update(self): def isCollide(self, obs_x, obs_y, obs_len): """Check collision of player with obstacle.""" - # set coordinates for top left hand corner (0) and bottom right hand corner (1) + # set coordinates for top left hand corner (0) and bottom right hand corner (1) of obstacle obs_x0 = obs_x obs_x1 = obs_x + obs_len obs_y0 = obs_y obs_y1 = obs_y + obs_len - + # and of player play_x0 = self.play_x play_x1 = self.play_x + self.play_len play_y0 = self.play_y @@ -104,7 +104,6 @@ def isCollide(self, obs_x, obs_y, obs_len): return True - class StaminaBar: """A stamina bar, defined by its starting location and color. Also takes in screen as an argument to draw the stamina bar.""" @@ -113,9 +112,6 @@ def __init__(self, screen, start, color): self.start = start # starting location of stamina bar self.color = color # color of stamina bar self.bars = 100 # initialize number of health bars - self.clock = pygame.time.Clock()# initialize clock - self.prev_time = 0 # initialize previous time - self.player_jump = False def draw(self): """Draw stamina bar based on color, starting location, and number of health bars.""" @@ -123,17 +119,9 @@ def draw(self): def decreaseBarleft(self, num_bars): """Decrease health bar by num_bars.""" - current_time = pygame.time.get_ticks() - # debounce decreasing bars - #if current_time - self.prev_time >= 50: self.bars -= num_bars - self.prev_time = current_time def increaseBarleft(self, speed = 1): """Increase health bar continuously if number of bars is lower than 100.""" if self.bars < 100: - # current_time = pygame.time.get_ticks() - # increase stamina bar by 1 every .05 seconds - #if current_time - self.prev_time >= 10/self.speed: self.bars += 1 * speed - #self.prev_time = current_time From dd5ea39e99761e7fe413e81f71e2cb0b812426d1 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 22:29:40 -0400 Subject: [PATCH 23/35] Replace Barleft with Bar --- Game4.py | 8 ++++---- misc.py | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Game4.py b/Game4.py index e91b5f0..a55d8d1 100644 --- a/Game4.py +++ b/Game4.py @@ -78,7 +78,7 @@ def mainLoop(self): # up to jump if pressed[pygame.K_UP] and P1_stamina_bar.bars >= player.jumpcost: if player.play_y == (360 - player.play_len): - P1_stamina_bar.decreaseBarleft(player.jumpcost) + P1_stamina_bar.decreaseBar(player.jumpcost) player.jump() P1_stamina_bar.draw() # left to move left @@ -108,7 +108,7 @@ def mainLoop(self): # generate obstacle player's obstacle at appropriate height if (new_obstical == True and P2_stamina_bar.bars >= 33): new_obstical = False - P2_stamina_bar.decreaseBarleft(33) + P2_stamina_bar.decreaseBar(33) obstacles.append(Obstacle(obs_x, obstical_height, obs_len, self.screen,'RED')) # move each obstacle forward @@ -121,8 +121,8 @@ def mainLoop(self): obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] # update stamina bars - P1_stamina_bar.increaseBarleft() - P2_stamina_bar.increaseBarleft(1.5) + P1_stamina_bar.increaseBar() + P2_stamina_bar.increaseBar(1.5) P1_stamina_bar.draw() P2_stamina_bar.draw() diff --git a/misc.py b/misc.py index 5aa33a9..a48d400 100644 --- a/misc.py +++ b/misc.py @@ -49,6 +49,7 @@ def __init__(self, play_x, play_y, play_len, screen): self.m = 2.5 # "mass" for jump self.floor = play_y # location of player before jump, used for comparison self.jumpcost = 30 + def draw(self): """Draw player based on top left hand coordinate and length.""" pygame.draw.rect(self.screen, colors['WHITE'], [self.play_x, self.play_y, self.play_len, self.play_len]) @@ -117,11 +118,11 @@ def draw(self): """Draw stamina bar based on color, starting location, and number of health bars.""" pygame.draw.rect(self.screen, colors[self.color], [self.start, 20, self.bars, 10]) - def decreaseBarleft(self, num_bars): + def decreaseBar(self, num_bars): """Decrease health bar by num_bars.""" self.bars -= num_bars - def increaseBarleft(self, speed = 1): + def increaseBar(self, speed = 1): """Increase health bar continuously if number of bars is lower than 100.""" if self.bars < 100: self.bars += 1 * speed From f87798864778ede72cbba895ecf149ffe450e0b6 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:37:24 -0400 Subject: [PATCH 24/35] Added Player reviews --- Project_Writeup_and_Reflection.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index ef1e81e..dabd63f 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -14,6 +14,8 @@ The game starts with Player 1 on the bottom left corner of the screen. Player 1 Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. +We playtested the game with around 9 individuals. Each person played at least one game as both players. Reviews were generally positive with testers describing it as "fascinating" and "A few minutes of mindless fun". + ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) Figure 1: This is how the game starts. Player 1 is the white square in the bottom left corner. PLayer 1’s distance is in the top center of the screen. The stamina bars for Player 1 and 2 are in the top left and right screen respectively. From a89650644894d5c456abf8ee05f085790abe024c Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:37:58 -0400 Subject: [PATCH 25/35] Added Player reviews From 20ba136749dbfc17232a37b70c2ed7afb957d645 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:37:59 -0400 Subject: [PATCH 26/35] Added Player reviews From d33d9c26eedb6e552eb3e36321b0582a926859d5 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:38:00 -0400 Subject: [PATCH 27/35] Added Player reviews From 4441f05eaa0b3704eccba71262d906fe79654e39 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:38:01 -0400 Subject: [PATCH 28/35] Added Player reviews From 6a55531a9d13190476c55d947208bba02353cb51 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:38:02 -0400 Subject: [PATCH 29/35] Added Player reviews From 5fb8cc9252c20d3f9627319ee6bf95aff6e2b864 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:38:32 -0400 Subject: [PATCH 30/35] Added Player reviews --- Project_Writeup_and_Reflection.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index dabd63f..2441acf 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -14,7 +14,6 @@ The game starts with Player 1 on the bottom left corner of the screen. Player 1 Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. -We playtested the game with around 9 individuals. Each person played at least one game as both players. Reviews were generally positive with testers describing it as "fascinating" and "A few minutes of mindless fun". ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) From ce5b8eb4e66f08e3d00350bf99109a6e2747bcd0 Mon Sep 17 00:00:00 2001 From: hthomas60 Date: Sun, 29 Oct 2017 22:38:56 -0400 Subject: [PATCH 31/35] Same --- Project_Writeup_and_Reflection.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 2441acf..83dbc9d 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -14,6 +14,8 @@ The game starts with Player 1 on the bottom left corner of the screen. Player 1 Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. +We playtested the game with around 9 individuals. Each person played at least one game as both players. Reviews were generally positive with testers describing it as "fascinating" and "A few minutes of mindless fun". + ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) From 886ec96b30db2a2f69723f5521a8bcecb0ce638f Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 22:47:00 -0400 Subject: [PATCH 32/35] Add UML diagram --- UML.png | Bin 0 -> 30098 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 UML.png diff --git a/UML.png b/UML.png new file mode 100644 index 0000000000000000000000000000000000000000..85fbb66285b310c9f6ff71c5f20671ee7aa9dae7 GIT binary patch literal 30098 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 F`X7L~pW6Tc literal 0 HcmV?d00001 From eea96f3df9437f9d5871c9a4a56954f303e592e1 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 22:48:59 -0400 Subject: [PATCH 33/35] Add UML diagram --- Project_Writeup_and_Reflection.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 83dbc9d..30c482a 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -21,13 +21,13 @@ We playtested the game with around 9 individuals. Each person played at least on Figure 1: This is how the game starts. Player 1 is the white square in the bottom left corner. PLayer 1’s distance is in the top center of the screen. The stamina bars for Player 1 and 2 are in the top left and right screen respectively. -![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot2.png) +![screenshot2](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot2.png) Figure 2: During the game Player 1 avoids the red obstacles by jumping. Player 2 can spawn red obstacles at multiple heights. Player 2’s staminal bar(red) has almost been depleted. -![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot3.png) +![screenshot3](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot3.png) -Figure 3: Game over screen reports the distance Player 1 traveled and gives instructions for how to play again. +Figure 3: Game over screen reports the distance Player 1 traveled and gives instructions for how to play again. ### Implementation [~2-3 paragraphs + UML diagram] @@ -39,6 +39,8 @@ We got our MVP done by the mid-project check-in, so we added additional features At one point, we considered implementing Model View Control. However, given the simplicity of our game, it wasn't worth rewriting whole sections just to split up the view and control into different classes. It would have cut down on the length of our mainLoop, but the pros just didn't outweigh the cons. Another decision that we made was to not create a subclass for each of the stamina bars since we only needed two and their only differences were their color and location, so we took those parameters as arguments instead. +![UML](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/UML.png) + ### Reflection [~2 paragraphs] *From a process point of view, what went well? What could you improve? Other possible reflection topics: Was your project appropriately scoped? Did you have a good plan for unit testing? How will you use what you learned going forward? What do you wish you knew before you started that would have helped you succeed?* From b97a0c07967ebefd734ea6930e21794b15ed4377 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 29 Oct 2017 22:57:06 -0400 Subject: [PATCH 34/35] Update project writeup and reflection --- Project_Writeup_and_Reflection.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Project_Writeup_and_Reflection.md b/Project_Writeup_and_Reflection.md index 30c482a..7be4f5d 100644 --- a/Project_Writeup_and_Reflection.md +++ b/Project_Writeup_and_Reflection.md @@ -10,20 +10,20 @@ Blockade is competitive arcade game. It has two players. Player 1 is a white blo *Present what you accomplished. This will be different for each project, but screenshots are likely to be helpful.* -The game starts with Player 1 on the bottom left corner of the screen. Player 1’s objective is simple, avoid obstacles and get as far as you can. Player 1 can avoid obstacles by moving left, right or jumping. These actions are performed by pressing the Left, Right, and Up arrow keys respectively. Player 2 does not show up on screen but can make is presence known by throwing obstacles at Player 1. These obstacles can be thrown at three heights: ground level, just over Player 1 and High in the air. Player 2 can control the height of the obstacles thrown by pressing the Z, X, and C keys. The game ends when Player 1 collides with an obstacle and dies, Player 1’s score is determined by how long they survived. The competitive nature of the game come when the human players swap roles. With both trying to ensure the other gets a lower score. +The game starts with Player 1 on the bottom left corner of the screen. Player 1’s objective is simple, avoid obstacles and get as far as you can. Player 1 can avoid obstacles by moving left, right or jumping. These actions are performed by pressing the Left, Right, and Up arrow keys respectively. Player 2 does not show up on screen but can make is presence known by throwing obstacles at Player 1. These obstacles can be thrown at three heights: ground level, just over Player 1 and High in the air. Player 2 can control the height of the obstacles thrown by pressing the Z, X, and C keys. The game ends when Player 1 collides with an obstacle and dies, Player 1’s score is determined by how long they survived. The competitive nature of the game come when the human players swap roles. With both trying to ensure the other gets a lower score. -Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. +Player actions cost stamina. If a player’s stamina gets too low, they cannot perform any actions until it regenerates. This adds another level of strategy to the game with each player trying to force the other to deplete their stamina bar. In the game, Player 2’s strategy heavily relies on forcing Player 1 to run out of stamina. -We playtested the game with around 9 individuals. Each person played at least one game as both players. Reviews were generally positive with testers describing it as "fascinating" and "A few minutes of mindless fun". +We playtested the game with around 9 individuals. Each person played at least one game as both players. Reviews were generally positive with testers describing it as "fascinating" and "a few minutes of mindless fun". ![screenshot1](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot1.png) -Figure 1: This is how the game starts. Player 1 is the white square in the bottom left corner. PLayer 1’s distance is in the top center of the screen. The stamina bars for Player 1 and 2 are in the top left and right screen respectively. +Figure 1: This is how the game starts. Player 1 is the white square in the bottom left corner. PLayer 1’s distance is in the top center of the screen. The stamina bars for Player 1 and 2 are in the top left and right screen respectively. ![screenshot2](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot2.png) -Figure 2: During the game Player 1 avoids the red obstacles by jumping. Player 2 can spawn red obstacles at multiple heights. Player 2’s staminal bar(red) has almost been depleted. +Figure 2: During the game Player 1 avoids the red obstacles by jumping. Player 2 can spawn red obstacles at multiple heights. Player 2’s staminal bar (red) has almost been depleted. ![screenshot3](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/screenshot3.png) @@ -37,10 +37,12 @@ Our minimum viable product was a one player game similar to Google Chrome's dino We got our MVP done by the mid-project check-in, so we added additional features to allow a second player to control the obstacles. We then created another class for the stamina bar, with one method to decrease the bar with every action (i.e. when the player jumps for the player's stamina bar and when an obstacle is generated for the second player's stamina bar) and increase the bar over time up to a certain length. -At one point, we considered implementing Model View Control. However, given the simplicity of our game, it wasn't worth rewriting whole sections just to split up the view and control into different classes. It would have cut down on the length of our mainLoop, but the pros just didn't outweigh the cons. Another decision that we made was to not create a subclass for each of the stamina bars since we only needed two and their only differences were their color and location, so we took those parameters as arguments instead. - ![UML](https://github.com/vivienyuwenchen/InteractiveProgramming/blob/master/UML.png) +Figure 4: UML diagram of game + +At one point, we considered implementing Model View Control. However, given the simplicity of our game, it wasn't worth rewriting whole sections just to split up the view and control into different classes. It would have cut down on the length of our mainLoop, but the pros just didn't outweigh the cons. Another decision that we made was to not create a subclass for each of the stamina bars since we only needed two and their only differences were their color and location, so we took those parameters as arguments instead. We also kept remnants of the code that randomized obstacles from our MVP in case we wanted to revise the code to allow the player choose their mode: one-player or two-player. + ### Reflection [~2 paragraphs] *From a process point of view, what went well? What could you improve? Other possible reflection topics: Was your project appropriately scoped? Did you have a good plan for unit testing? How will you use what you learned going forward? What do you wish you knew before you started that would have helped you succeed?* From cea81cc570d78ba2916dc11b7492f8be4074ede5 Mon Sep 17 00:00:00 2001 From: Vivien Chen Date: Sun, 10 Dec 2017 16:44:54 -0500 Subject: [PATCH 35/35] Revised for MP5 with suggestions from feedback and start menu --- Game4.py | 216 ++++++++++------ Old Files/gameover.png | Bin 0 -> 18210 bytes playermoves.py => Old Files/playermoves.py | 50 ++-- .../pygame_base_template.py | 230 +++++++++--------- config.py | 21 ++ gameover.png | Bin 17263 -> 0 bytes misc.py => models.py | 32 ++- 7 files changed, 316 insertions(+), 233 deletions(-) create mode 100644 Old Files/gameover.png rename playermoves.py => Old Files/playermoves.py (94%) rename pygame_base_template.py => Old Files/pygame_base_template.py (95%) create mode 100644 config.py delete mode 100644 gameover.png rename misc.py => models.py (87%) diff --git a/Game4.py b/Game4.py index a55d8d1..dae9271 100644 --- a/Game4.py +++ b/Game4.py @@ -1,8 +1,21 @@ +""" +Blockade is competitive arcade game. It has two players. Player 1 is a white +block that is continually moving forward. Player 2’s job is to stop Player 1 by +throwing obstacles in its way. Player 1 can avoid obstacles by jumping over or +ducking under them. Both players are limited by a stamina bar. Actions such +jumping or throwing obstacles depletes player’s stamina and if the stamina gets +too low players cannot perform actions. The game uses keyboard inputs as commands. + +@author: Vivien Chen and Harrison Young +""" + + import os, sys import pygame from random import randint -from misc import * +from models import * +from config import * class Game4Main: @@ -20,73 +33,96 @@ def __init__(self, width=480,height=360): # create clock self.clock = pygame.time.Clock() self.score = 0 + self.oneplayer = True - def mainLoop(self): + def start_menu(self): + """Start screen for game.""" + while True: + if pygame.QUIT in {event.type for event in pygame.event.get()}: + sys.exit() + + # display start menu + self.screen.fill(colors['BLACK']) + # title + font = pygame.font.SysFont("comicsansms", int(self.width/8)) + text = font.render("Blockade", True, colors['WHITE']) + text_rect = text.get_rect(center=(self.width/2, self.height/3)) + self.screen.blit(text, text_rect) + # instructions + font = pygame.font.SysFont("comicsansms", int(self.width/30)) + text = font.render("Player 1: Arrow Keys, Player 2: ZXC", True, colors['WHITE']) + text_rect = text.get_rect(center=(self.width/2, self.height/2)) + self.screen.blit(text, text_rect) + # buttons + self.button("One Player",self.width*1/8-20,self.height*3/4,colors['GREEN'],True,self.main_loop) + self.button("Two Player",self.width*5/8-20,self.height*3/4,colors['RED'],False,self.main_loop) + + # update screen + pygame.display.flip() + + + def main_loop(self): """Main screen for game.""" - # initialize player + # start count count = 0 - play_len = 25 - play_x = 100 - play_y = self.height - play_len - player = Player(play_x, play_y, play_len, self.screen) + + # initialize player + player = Player(PLAY_X, self.height-PLAY_LEN, PLAY_LEN, self.screen) # initialize stamina bars - P1_stamina_bar = StaminaBar(self.screen,25,"WHITE") - P2_stamina_bar = StaminaBar(self.screen,350,"RED") + P1_stamina_bar = StaminaBar(self.screen, P1_STAMINA_BAR_OFFSET, 'WHITE') + P2_stamina_bar = StaminaBar(self.screen, self.width - P2_STAMINA_BAR_OFFSET, 'RED') # initialize obstacle length, x and y coordinates - obs_len = 25 - obs_x = self.width - obs_y = self.height - obs_len - obstical_height = self.height - obs_len + OBS_X = self.width + OBS_Y = self.height - OBS_LEN # create list of obstacles - obstacles = [] - new_obstical = False - # uncomment and place line below in [] of obstacles = [] to generate random obstacles: - # Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE') - + if self.oneplayer: + obstacles = [Obstacle(OBS_X, OBS_Y, OBS_LEN, self.screen,'BLUE')] + else: + obstacles = [] + new_obstacle = False + obstacle_height = OBS_Y # initialize time variables prev_time = 0 obs_dt = 500 # main event loop - while 1: + while True: count+=1 + # if pygame.QUIT in {event.type for event in pygame.event.get()}: + # sys.exit() + # elif pygame.KEYDOWN in {event.type for event in pygame.event.get()}: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() - # check keyboard for obstacle player - if event.type == pygame.KEYDOWN: - # z to create obstacle at ground level - if event.key == pygame.K_z: - new_obstical = True - obstical_height = obs_y - # x to create obstacle at second level - if event.key == pygame.K_x: - new_obstical = True - obstical_height = obs_y-25 - # c to create obstacle at third level - if event.key == pygame.K_c: - new_obstical = True - obstical_height = obs_y-50 + if not self.oneplayer: + # check keyboard for obstacle player + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_z: + new_obstacle = True + obstacle_height = OBS_Y-LEVEL_OFFSETS['ground'] + if event.key == pygame.K_x: + new_obstacle = True + obstacle_height = OBS_Y-LEVEL_OFFSETS['first'] + if event.key == pygame.K_c: + new_obstacle = True + obstacle_height = OBS_Y-LEVEL_OFFSETS['second'] # check keyboard for main player pressed = pygame.key.get_pressed() - # up to jump - if pressed[pygame.K_UP] and P1_stamina_bar.bars >= player.jumpcost: - if player.play_y == (360 - player.play_len): - P1_stamina_bar.decreaseBar(player.jumpcost) + if pressed[pygame.K_UP] and P1_stamina_bar.bars >= JUMP_COST: + if player.play_y == (self.height - player.play_len): + P1_stamina_bar.decrease_bar(JUMP_COST) player.jump() P1_stamina_bar.draw() - # left to move left if pressed[pygame.K_LEFT]: - player.moveLeft() - # right to move right + player.move_left() if pressed[pygame.K_RIGHT]: - player.moveRight() + player.move_right() # refresh screen self.screen.fill(colors['BLACK']) @@ -98,68 +134,98 @@ def mainLoop(self): # update current time current_time = pygame.time.get_ticks() - # generate obstacle at random time - if (current_time - prev_time > obs_dt): - # uncomment below to generate random obstacles: - # obstacles.append(Obstacle(obs_x, obs_y, obs_len, self.screen,'BLUE')) - new_obstical = False - prev_time = current_time - obs_dt = randint(1000, 3000) - # generate obstacle player's obstacle at appropriate height - if (new_obstical == True and P2_stamina_bar.bars >= 33): - new_obstical = False - P2_stamina_bar.decreaseBar(33) - obstacles.append(Obstacle(obs_x, obstical_height, obs_len, self.screen,'RED')) + if self.oneplayer: + # generate obstacle at random time + if (current_time - prev_time > obs_dt): + obstacles.append(Obstacle(OBS_X, OBS_Y, OBS_LEN, self.screen,'GREEN')) + prev_time = current_time + obs_dt = randint(250, 1000) + if not self.oneplayer: + # generate obstacle player's obstacle at appropriate height + if (new_obstacle == True and P2_stamina_bar.bars >= OBSTACLE_COST): + new_obstacle = False + P2_stamina_bar.decrease_bar(OBSTACLE_COST) + obstacles.append(Obstacle(OBS_X, obstacle_height, OBS_LEN, self.screen,'RED')) # move each obstacle forward for obstacle in obstacles: - obstacle.moveForward() + obstacle.move_forward() + obstacle.draw() # check for collision between player and obstacles - if player.isCollide(obstacle.obs_x, obstacle.obs_y, obstacle.obs_len): - self.gameOver(str(count)) + if player.is_collide(obstacle.obs_x, obstacle.obs_y, obstacle.obs_len): + self.game_over(str(count)) # remove obstacle from list if off screen - obstacles = [obstacle for obstacle in obstacles if not obstacle.isGone()] + obstacles = [obstacle for obstacle in obstacles if not obstacle.is_gone()] # update stamina bars - P1_stamina_bar.increaseBar() - P2_stamina_bar.increaseBar(1.5) + P1_stamina_bar.increase_bar() P1_stamina_bar.draw() - P2_stamina_bar.draw() + if not self.oneplayer: + P2_stamina_bar.increase_bar(1.5) + P2_stamina_bar.draw() # display score - font = pygame.font.SysFont("comicsansms", 72) - text = font.render(str(count), True, (255,255,255)) - self.screen.blit(text,[200,10]) + font = pygame.font.SysFont("comicsansms", int(self.width/8)) + text = font.render(str(count), True, colors['WHITE']) + text_rect = text.get_rect(center=(self.width/2, self.height/8)) + self.screen.blit(text, text_rect) # update screen pygame.display.flip() self.clock.tick(30) - def gameOver(self,score): + def game_over(self, score): """Game over screen.""" # main event loop - while 1: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - sys.exit() + while True: + if pygame.QUIT in {event.type for event in pygame.event.get()}: + sys.exit() # check keyboard for space key to restart game pressed = pygame.key.get_pressed() if pressed[pygame.K_SPACE]: - self.mainLoop() + self.main_loop() + if pressed[pygame.K_v]: + self.start_menu() # display game over screen self.screen.fill(colors['BLACK']) - font = pygame.font.SysFont("comicsansms", 28) - text = font.render("Player 1 recived a score of " + str(score), True, (255,255,255)) - self.screen.blit(text,[50,140]) - text = font.render("Press Space Bar to play again", True, (255,255,255)) - self.screen.blit(text,[50,178]) + font = pygame.font.SysFont("comicsansms", int(self.width/16)) + text = font.render("Score: " + str(score), True, colors['WHITE']) + text_rect = text.get_rect(center=(self.width/2, self.height*1/3)) + self.screen.blit(text,text_rect) + text = font.render("Press Space Bar to play again", True, colors['WHITE']) + text_rect = text.get_rect(center=(self.width/2, self.height*1/2)) + self.screen.blit(text,text_rect) + text = font.render("Press V to go to home screen", True, colors['WHITE']) + text_rect = text.get_rect(center=(self.width/2, self.height*2/3)) + self.screen.blit(text,text_rect) # update screen pygame.display.flip() + def button(self, msg, x, y, color, oneplayer, action=None): + "Button for start screen." + mouse = pygame.mouse.get_pos() + click = pygame.mouse.get_pressed() + font = pygame.font.SysFont("comicsansms", int(self.width/20)) + text = font.render(msg, True, colors['WHITE']) + w = self.width/3 + h = self.width/12 + + if x+w > mouse[0] > x and y+h > mouse[1] > y: + pygame.draw.rect(self.screen, color, (x,y,w,h)) + + if click[0] == 1 and action != None: + self.oneplayer = oneplayer + action() + else: + pygame.draw.rect(self.screen, colors['BLACK'], (x,y,w,h)) + + self.screen.blit(text,[x+20,y]) + + if __name__ == "__main__": - Game4Main().mainLoop() + Game4Main().start_menu() diff --git a/Old Files/gameover.png b/Old Files/gameover.png new file mode 100644 index 0000000000000000000000000000000000000000..ef7e1132387b3e72ac50d740d740a04b2dc5eb69 GIT binary patch literal 18210 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 Y^8^#gz7;O;y*4)#WK?05QYLTz57dXai~s-t literal 0 HcmV?d00001 diff --git a/playermoves.py b/Old Files/playermoves.py similarity index 94% rename from playermoves.py rename to Old Files/playermoves.py index 6121815..75b681d 100644 --- a/playermoves.py +++ b/Old Files/playermoves.py @@ -1,25 +1,25 @@ -import pygame -from pygame.locals import * -import time -from sys import exit -pygame.init() -def jump(ctime, startloc): - """ - Changes the y position up one frame - #for i in range(21): - - #print(jump(i,0)[1]) - """ - over = False - h = 100 - t = 20 - b = startloc - c = t/2 - a = h/((t/2)**2) - x = (ctime%20) - recty = (a*(x - c)**2)+b - - - if (x == 0): - over = True - return [recty, over] +import pygame +from pygame.locals import * +import time +from sys import exit +pygame.init() +def jump(ctime, startloc): + """ + Changes the y position up one frame + #for i in range(21): + + #print(jump(i,0)[1]) + """ + over = False + h = 100 + t = 20 + b = startloc + c = t/2 + a = h/((t/2)**2) + x = (ctime%20) + recty = (a*(x - c)**2)+b + + + if (x == 0): + over = True + return [recty, over] diff --git a/pygame_base_template.py b/Old Files/pygame_base_template.py similarity index 95% rename from pygame_base_template.py rename to Old Files/pygame_base_template.py index 94b378f..5eb8bcc 100644 --- a/pygame_base_template.py +++ b/Old Files/pygame_base_template.py @@ -1,115 +1,115 @@ -""" - Pygame base template for opening a window - - Sample Python/Pygame Programs - Simpson College Computer Science - http://programarcadegames.com/ - http://simpson.edu/computer-science/ - - Explanation video: http://youtu.be/vRB_983kUMc -""" - - - -import pygame -from playermoves import * - - -# Define some colors -BLACK = (0, 0, 0) -WHITE = (255, 255, 255) -GREEN = (0, 255, 0) -RED = (255, 0, 0) -jumping = False -pygame.init() - -# Set the width and height of the screen [width, height] -size = (700, 500) -screen = pygame.display.set_mode(size) - -pygame.display.set_caption("My Game") - -# Loop until the user clicks the close button. -done = False - -# Used to manage how fast the screen updates -clock = pygame.time.Clock() -frames = 0; -startjump = 0 -x_min = 0 -x_max = 200 -rectx = 100 -recty = 400 - -# -------- Main Program Loop ----------- -while not done: - - # --- Main event loop - - for event in pygame.event.get(): - if event.type == pygame.QUIT: - done = True - #if event.type == pygame.KEYDOWN: -# - # if event.key == pygame.K_SPACE: - # if frames - startjump > 20: - # jumping = True - # startjump = frames - - pressed = pygame.key.get_pressed() - if pressed[pygame.K_UP]: - if frames - startjump > 20: - jumping = True - startjump = frames - if pressed[pygame.K_LEFT]: - if rectx > x_min: - rectx -= 5 - if pressed[pygame.K_RIGHT]: - if rectx < x_max: - rectx += 5 - - - - - - # --- Game logic should go here - - # --- Screen-clearing code goes here - - # Here, we clear the screen to white. Don't put other drawing commands - # above this, or they will be erased with this command. - - # If you want a background image, replace this clear with blit'ing the - # background image. - screen.fill(BLACK) - pygame.draw.rect(screen, RED, [0,425,700,100]) - jumpclock = frames%21 - - # --- Drawing code should go here - # --- Drawing code should go here - - jumpover = False - - #if False:#if detect_key_press() == 'space': - # jumping = True #if the spacebar is pressed start the jump - # print("boing") - #else: - # print(detect_key_press()) - if jumping == True: - recty = jump(frames-startjump+1,300)[0] - jumpover = jump(frames-startjump+1,300)[1] - if jumpover == True: - - jumping = False - - pygame.draw.rect(screen, WHITE, [rectx,recty,25,25]) - # --- Go ahead and update the screen with what we've drawn - pygame.display.flip() - frames+=1 # increments frame count - - # --- Limit to 60 frames per second - clock.tick(60) - - -# Close the window and quit. -pygame.quit() +""" + Pygame base template for opening a window + + Sample Python/Pygame Programs + Simpson College Computer Science + http://programarcadegames.com/ + http://simpson.edu/computer-science/ + + Explanation video: http://youtu.be/vRB_983kUMc +""" + + + +import pygame +from playermoves import * + + +# Define some colors +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +GREEN = (0, 255, 0) +RED = (255, 0, 0) +jumping = False +pygame.init() + +# Set the width and height of the screen [width, height] +size = (700, 500) +screen = pygame.display.set_mode(size) + +pygame.display.set_caption("My Game") + +# Loop until the user clicks the close button. +done = False + +# Used to manage how fast the screen updates +clock = pygame.time.Clock() +frames = 0; +startjump = 0 +x_min = 0 +x_max = 200 +rectx = 100 +recty = 400 + +# -------- Main Program Loop ----------- +while not done: + + # --- Main event loop + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + done = True + #if event.type == pygame.KEYDOWN: +# + # if event.key == pygame.K_SPACE: + # if frames - startjump > 20: + # jumping = True + # startjump = frames + + pressed = pygame.key.get_pressed() + if pressed[pygame.K_UP]: + if frames - startjump > 20: + jumping = True + startjump = frames + if pressed[pygame.K_LEFT]: + if rectx > x_min: + rectx -= 5 + if pressed[pygame.K_RIGHT]: + if rectx < x_max: + rectx += 5 + + + + + + # --- Game logic should go here + + # --- Screen-clearing code goes here + + # Here, we clear the screen to white. Don't put other drawing commands + # above this, or they will be erased with this command. + + # If you want a background image, replace this clear with blit'ing the + # background image. + screen.fill(BLACK) + pygame.draw.rect(screen, RED, [0,425,700,100]) + jumpclock = frames%21 + + # --- Drawing code should go here + # --- Drawing code should go here + + jumpover = False + + #if False:#if detect_key_press() == 'space': + # jumping = True #if the spacebar is pressed start the jump + # print("boing") + #else: + # print(detect_key_press()) + if jumping == True: + recty = jump(frames-startjump+1,300)[0] + jumpover = jump(frames-startjump+1,300)[1] + if jumpover == True: + + jumping = False + + pygame.draw.rect(screen, WHITE, [rectx,recty,25,25]) + # --- Go ahead and update the screen with what we've drawn + pygame.display.flip() + frames+=1 # increments frame count + + # --- Limit to 60 frames per second + clock.tick(60) + + +# Close the window and quit. +pygame.quit() diff --git a/config.py b/config.py new file mode 100644 index 0000000..6190651 --- /dev/null +++ b/config.py @@ -0,0 +1,21 @@ +colors = {'BLACK': (0, 0, 0), + 'WHITE' : (255, 255, 255), + 'GREEN' : (0, 255, 0), + 'RED' : (255, 0, 0), + 'BLUE' : (0, 0, 255), + } + +PLAY_LEN = 25 +PLAY_X = 100 + +P1_STAMINA_BAR_OFFSET = 25 +P2_STAMINA_BAR_OFFSET = 125 +JUMP_COST = 33 +OBSTACLE_COST = 33 + +OBS_LEN = 25 + +LEVEL_OFFSETS = {'ground': 0, + 'first': 25, + 'second': 50, + } diff --git a/gameover.png b/gameover.png deleted file mode 100644 index 24035b817faf14f23755faf631583366ebde484f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17263 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 icRx_x`8#_~@Gv@=i*p6 0: self.play_x -= self.speed @@ -88,7 +84,7 @@ def update(self): # reset velocity self.v = 7.5 - def isCollide(self, obs_x, obs_y, obs_len): + def is_collide(self, obs_x, obs_y, obs_len): """Check collision of player with obstacle.""" # set coordinates for top left hand corner (0) and bottom right hand corner (1) of obstacle obs_x0 = obs_x @@ -101,7 +97,7 @@ def isCollide(self, obs_x, obs_y, obs_len): play_y0 = self.play_y play_y1 = self.play_y + self.play_len # check if player coordinates within obstacle coordinates - if (play_x0 in range(obs_x0, obs_x1) or play_x1 in range(obs_x0, obs_x1)) and (int(play_y0) in range(obs_y0, obs_y1) or int(play_y1) in range(obs_y0, obs_y1)): + if (obs_x0 <= play_x0 <= obs_x1 or obs_x0 <= play_x1 <= obs_x1) and (obs_y0 <= play_y0 < obs_y1 or obs_y0 < play_y1 <= obs_y1): return True @@ -118,11 +114,11 @@ def draw(self): """Draw stamina bar based on color, starting location, and number of health bars.""" pygame.draw.rect(self.screen, colors[self.color], [self.start, 20, self.bars, 10]) - def decreaseBar(self, num_bars): + def decrease_bar(self, num_bars): """Decrease health bar by num_bars.""" self.bars -= num_bars - def increaseBar(self, speed = 1): + def increase_bar(self, speed = 1): """Increase health bar continuously if number of bars is lower than 100.""" if self.bars < 100: self.bars += 1 * speed