From d8546f945ce8f6e4bd9f54e260610f7868115108 Mon Sep 17 00:00:00 2001 From: Tramane Hall Date: Fri, 13 Jul 2018 13:12:07 -0400 Subject: [PATCH 1/4] created paddle and two kinds of blocks --- src/block.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/block.py b/src/block.py index f7966e2..0c3cb02 100644 --- a/src/block.py +++ b/src/block.py @@ -33,5 +33,46 @@ class KineticBlock(Block): # No custom code needed here, just want to be able to differentiate # KineticBall will handle the collison pass + +class Paddle(KineticBlock) + SPEED = 4 + def update(self, **input): + self.left = input['left'] + self.right = inmput['right'] + if self.left: + self.position.x -= self.SPEED + + if self.right: + self.position.x += self.SPEED + + self.rectangle = pygame.Rect( + self.position.x - (self.rectangle.width/2), + self.position.y - (self.rectangle.height/2), + self.rectangle.width, + self.rectangle.height + ) + super().update() + +class EasyBlock(KineticBlock): + def update(self, **kwargs): + if self.touched_by_ball: + kwargs['object_list'].pop(kwargs['object_list'].index(self)) + + +class HardBlock(EasyBlock): + def __init__(self, life, position, width, height, color): + self.life = life + super().__init__(position, width, height, color) + + random_color = [random.randint(0, 255), random.randint(0, 255), random.randint(0,255)] + + def update(self, **kwargs): + if self.touched_by_ball: + self.life -= 1 + self.color = self.random_color + if self.life <= 0: + super().update(object_list = kwargs['object_list']) + else: + self.touched_by_ball = False \ No newline at end of file From 9d8864a0fd696967ac84d85d04b50ec6f269cd83 Mon Sep 17 00:00:00 2001 From: Tramane Hall Date: Fri, 13 Jul 2018 13:29:28 -0400 Subject: [PATCH 2/4] Features Added: Color changes, moving paddle, screen size (MVP) --- src/draw.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/draw.py b/src/draw.py index 14ff036..0d7cdf4 100644 --- a/src/draw.py +++ b/src/draw.py @@ -6,8 +6,8 @@ from ball import * from block import * -SCREEN_SIZE = [640, 480] -BACKGROUND_COLOR = [255, 255, 255] +SCREEN_SIZE = [400, 800] +BACKGROUND_COLOR = [0, 0, 70] def debug_create_objects(object_list): kinetic = GameBall(1, object_list, SCREEN_SIZE, @@ -16,8 +16,12 @@ def debug_create_objects(object_list): [255, 10, 0], 20) object_list.append(kinetic) - block = KineticBlock(Vector2(200,200), 100, 100, [0, 0, 255]) + block = HardBlock(4, Vector2(200,200), 100, 100, [0, 0, 255]) object_list.append(block) + +paddle = Paddle( + Vector2(SCREEN_SIZE[0]/2, SCREEN_SIZE[1] - 50), 100, 25 [55, 255, 20] )) +object_list.append(paddle) def main(): pygame.init() @@ -44,7 +48,7 @@ def main(): if keys[pygame.K_RIGHT]: right = True for object in object_list: - object.update() + object.update(left = left, right = right, pygame = pygame, object_list = objectlist) object.check_collision() # Draw Updates From 8e0d597af0c563e571679301bd2e44d77ba34e9f Mon Sep 17 00:00:00 2001 From: Tramane Hall Date: Sat, 18 Aug 2018 22:54:51 -0400 Subject: [PATCH 3/4] refactored ball.py and block.py with comments to show whats going on --- .vscode/settings.json | 3 +++ src/ball.py | 33 ++++++++++++++++++++++---- src/block.py | 55 +++++++++++++++++++++++++++++++++++-------- src/draw.py | 5 ++-- 4 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..919209f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "C:\\Users\\Me\\.virtualenvs\\Sprint-Challenge--Graphs-zXtD9vvw\\Scripts\\python.exe" +} \ No newline at end of file diff --git a/src/ball.py b/src/ball.py index 20e2792..e021f70 100644 --- a/src/ball.py +++ b/src/ball.py @@ -1,14 +1,15 @@ -import math +import math from pygame.math import Vector2 from pygame import Rect -from block import KineticBlock +from block import KineticBlock, UnbreakableBlock, GhostBlock class Ball: """ base class for bouncing objects """ + #This class is the "template" for the various types of balls that are playable in the game def __init__(self, bounds, position, velocity, color, radius): self.position = position self.velocity = velocity @@ -16,6 +17,8 @@ def __init__(self, bounds, position, velocity, color, radius): self.color = color self.radius = radius self.collision_rectangle = self.update_rectangle() + self.game_over = False + self.points = 0 def update_rectangle(self): return Rect(self.position.x - self.radius, @@ -29,13 +32,21 @@ def update(self, **kwargs): if self.position.x >= self.bounds[0] - self.radius: self.position.x = self.bounds[0] - self.radius - 1 self.velocity.x *= -1 + + #The ball has reached the top of the screen and a point is awarded if self.position.y <= 0 + self.radius: # screen height self.position.y = self.radius + 1 self.velocity.y *= -1 + self.points += 1 + print("Score: ", self.points) + + #The ball has hit the bottom of the screen, GAME OVER :( if self.position.y >= self.bounds[1] - self.radius: self.position.y = self.bounds[1] - self.radius - 1 - self.velocity.y *= -1 - + self.velocity.y = 0 + self.velocity.x = 0 + self.game_over = True + self.position += self.velocity self.collision_rectangle = self.update_rectangle() @@ -118,6 +129,7 @@ def collide_with_rectangle(self, object): if test == 1: object.touched_by_ball = True + object.check_collision() # the ball has collided with an edge # TODO: # fix sticky edges if left or right: @@ -163,7 +175,18 @@ def check_collision(self): index = self.object_list.index(self) for object in self.object_list[index+1:]: # TODO: Check effeciency # Balls colliding with blocks - if issubclass(type(object), KineticBlock) and object != self: + kinetic = issubclass(type(object), KineticBlock) + paddle = issubclass(type(object), Paddle) + unbreakable = issubclass(type(object), UnbreakableBlock) + ghost = issubclass(type(object), GhostBlock) + + + if (kinetic and paddle or unbreakable) and object != self: # Do a first round pass for collision (we know object is a KineticBlock) if self.collision_rectangle.colliderect(object.rectangle): self.collide_with_rectangle(object) + if ghost: + if self.collision_rectangle.colliderect(object.rectangle): + print("GHOSTBUSTER") + object.touched_by_ball = True + object.check_collision() diff --git a/src/block.py b/src/block.py index 0c3cb02..f42ce4a 100644 --- a/src/block.py +++ b/src/block.py @@ -30,22 +30,57 @@ def draw(self, screen, pygame): pygame.draw.rect(screen, self.color, self.rectangle) class KineticBlock(Block): - # No custom code needed here, just want to be able to differentiate - # KineticBall will handle the collison - pass + def __init__(self, position, width, height, color, hits): + super().__init__(position, width, height, color) + self.hits_to_break = hits + self.broken = False + self.colors = [[255, 0, 0], [255,140,0], [0, 255, 0]] + self.color = self.colors[-hits] + + def check_collision(self): + if self.touched_by_ball: + self.hits_to_break -= 1 + self.color = self.colors[-self.hits_to_break] + if self.hits_to_break == 0: + self.broken = True + +class UnbreakableBlock(Block): + #This a block that is bounceable but not breakable + + def __init__(self, position, width, height, color): + super().__init__(position, width, height, color) + self.color = [75, 75, 75] + +class GhostBlock(Block): + #The block is destroyed when hit but the ball can't bounce off of it + def __init__(self, position, width, height, color): + super().__init__(position, width, height, color) + self.color = [200, 200, 200] + self.broken = False -class Paddle(KineticBlock) - SPEED = 4 + def check_collision(self): + if self.touched_by_ball: + self.broken = True + +class Paddle(KineticBlock): + #this is the paddle that the player controls at the bottom of the screen - def update(self, **input): - self.left = input['left'] - self.right = inmput['right'] + def update(self, **kwargs): + distance = 2 + for k, v in kwargs.items(): + if k == "left" and v == True: + self.rectangle = self.rectangle.move(-distance, 0) + self.position.x -= distance + if k == "right" and v == True: + self.rectangle = self.rectangle.move(distance, 0) + self.position.x += distance + if self.left: self.position.x -= self.SPEED if self.right: - self.position.x += self.SPEED + self.position.x += self.SPEED self.rectangle = pygame.Rect( self.position.x - (self.rectangle.width/2), @@ -66,7 +101,7 @@ def __init__(self, life, position, width, height, color): self.life = life super().__init__(position, width, height, color) - random_color = [random.randint(0, 255), random.randint(0, 255), random.randint(0,255)] + rand_color = [random.randint(0, 255), random.randint(0, 255), random.randint(0,255)] def update(self, **kwargs): if self.touched_by_ball: diff --git a/src/draw.py b/src/draw.py index 0d7cdf4..81c0f88 100644 --- a/src/draw.py +++ b/src/draw.py @@ -19,9 +19,8 @@ def debug_create_objects(object_list): block = HardBlock(4, Vector2(200,200), 100, 100, [0, 0, 255]) object_list.append(block) -paddle = Paddle( - Vector2(SCREEN_SIZE[0]/2, SCREEN_SIZE[1] - 50), 100, 25 [55, 255, 20] )) -object_list.append(paddle) + paddle = Paddle(Vector2(SCREEN_SIZE[0] // 2, SCREEN_SIZE[1] - 50), 100, 25 [55, 255, 20], []) + object_list.append(paddle) def main(): pygame.init() From b5fe71c0980c7e8677df43e615e54f7cc73ac93e Mon Sep 17 00:00:00 2001 From: Tramane Hall Date: Sat, 18 Aug 2018 23:26:27 -0400 Subject: [PATCH 4/4] refactored draw.py --- src/draw.py | 82 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/src/draw.py b/src/draw.py index 81c0f88..63b1eef 100644 --- a/src/draw.py +++ b/src/draw.py @@ -7,21 +7,64 @@ from block import * SCREEN_SIZE = [400, 800] -BACKGROUND_COLOR = [0, 0, 70] +BACKGROUND_COLOR = [255, 255, 255] def debug_create_objects(object_list): kinetic = GameBall(1, object_list, SCREEN_SIZE, - Vector2(random.randint(20, SCREEN_SIZE[0] - 20), random.randint(20, SCREEN_SIZE[1] - 20)), - Vector2(4*random.random() - 2, 4*random.random() - 2), + Vector2(random.randint(20, SCREEN_SIZE[0] - 20), random.randint(20, SCREEN_SIZE[1] - 350)), + Vector2(4*random.random() - 2, 4), [255, 10, 0], 20) object_list.append(kinetic) - block = HardBlock(4, Vector2(200,200), 100, 100, [0, 0, 255]) - object_list.append(block) + block1_size = random.randint(40, 100) + block1_hits = 1 + block1_color = [0, 0, 255] + block1 = KineticBlock( + Vector2(random.randint(block1_size, SCREEN_SIZE[0]-block1_size), + random.randint(block1_size, SCREEN_SIZE[1]-300)), + block1_size, block1_size, block1_color, block1_hits) + object_list.append(block1) - paddle = Paddle(Vector2(SCREEN_SIZE[0] // 2, SCREEN_SIZE[1] - 50), 100, 25 [55, 255, 20], []) + block2_size = random.randint(40, 100) + block2_hits = 3 + block2_color = [0, 125, 0] + block2 = KineticBlock( + Vector2(random.randint(block2_size, SCREEN_SIZE[0]-block2_size), + random.randit(block2_size, SCREEN_SIZE[1]-300)), + block2_size, block2_size, block2_color, block2_hits) + object_list.append(block2) + + block3_size = random.randint(40, 100) + block3_hits = 2 + block3_color = [125, 0, 125] + block3 = KineticBlock( + Vector2(random.randint(int(block3_size/2), SCREEN_SIZE[0]-int(block3_size/2)), + random.randint(block3_size, SCREEN_SIZE[1]-300)), + block3_size, block3_size, block3_color, block3_hits) + object_list.append(block3) + unbreakable_size = random.randint(40, 100) + unbreakable = UnbreakableBlock( + Vector2(random.randint(int(unbreakable_size/2), SCREEN_SIZE[0]-int(unbreakable_size/2)), + random.randint(unbreakable_size, SCREEN_SIZE[1]-300)), + unbreakable_size, unbreakable_size, [0, 0, 0]) + object_list.append(unbreakable) + + ghost_size = random.randint(40, 100) + ghost = GhostBlock( + Vector2(random.randint(int(ghost_size/2), SCREEN_SIZE[0]-int(ghost_size/2)), + random.randint(ghost_size, SCREEN_SIZE[1]-300)), + ghost_size, ghost_size, [0, 0, 0]) + object_list.append(ghost) + paddle = Paddle(Vector2(SCREEN_SIZE[0]/2, SCREEN_SIZE[1]-15), 100, 30, [0, 0, 0]) object_list.append(paddle) - + +def continue_playing(obj_list): + for obj in obj_list: + if isinstance(obj, KineticBlock): + return True + print("YOU WIN!") + return False + def main(): pygame.init() screen = pygame.display.set_mode(SCREEN_SIZE) @@ -32,23 +75,36 @@ def main(): object_list = [] # list of objects of all types in the toy debug_create_objects(object_list) + + playing = True - while True: # TODO: Create more elegant condition for loop + while playing: left = False right = False + playing = continue_playing(object_list) + for event in pygame.event.get(): - if event.type == pygame.QUIT: sys.exit() - - #TODO: Feed input variables into update for objects that need it. + if event.type == pygame.QUIT: + playing = False + break + keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: left = True if keys[pygame.K_RIGHT]: right = True for object in object_list: - object.update(left = left, right = right, pygame = pygame, object_list = objectlist) + if hasattr(object, 'defeated'): + if object.defeated == True: + object_list.remove(object) + object.update(left=left, right=right) object.check_collision() + + if hasattr(object, 'game_over'): + if object.game_over == True: + print('GAME OVER') + playing = False # Draw Updates screen.fill(BACKGROUND_COLOR) @@ -62,4 +118,4 @@ def main(): pygame.quit() if __name__ == "__main__": - main() + main() \ No newline at end of file