diff --git a/src/ball.py b/src/ball.py index 20e2792..371cf6e 100644 --- a/src/ball.py +++ b/src/ball.py @@ -5,6 +5,8 @@ from block import KineticBlock +from block import BreakBlock + class Ball: """ base class for bouncing objects @@ -32,7 +34,11 @@ def update(self, **kwargs): if self.position.y <= 0 + self.radius: # screen height self.position.y = self.radius + 1 self.velocity.y *= -1 + print("you are the hero sir!") + exit() if self.position.y >= self.bounds[1] - self.radius: + print("you done mate") + exit() self.position.y = self.bounds[1] - self.radius - 1 self.velocity.y *= -1 @@ -75,6 +81,98 @@ def collide_with_ball(self, object, relative_vector): self.position += self.velocity object.position += object.velocity + + def collide_with_breakable_rectangle(self, object): + # This function is called after a first-pass test, that is the collision + # rectangles overlap. + + left, right, top, bottom = False, False, False, False + # TODO: This can probably be optimized + if ( + object.position.x > self.position.x and + object.position.x - object.rectangle.width/2 <= self.position.x + self.radius and + self.position.y <= object.position.y+object.rectangle.height/2 and + self.position.y >= object.position.y - object.rectangle.height/2 + ): + left = True + + if ( + object.position.x < self.position.x and + object.position.x + object.rectangle.width/2 >= self.position.x - self.radius and + self.position.y <= object.position.y+object.rectangle.height/2 and + self.position.y >= object.position.y - object.rectangle.height/2 + ): + right = True + + if ( + object.position.y > self.position.y and + object.position.y - object.rectangle.height/2 <= self.position.y + self.radius and + self.position.x <= object.position.x+object.rectangle.width/2 and + self.position.x >= object.position.x - object.rectangle.width/2 + ): + top = True + + if ( + object.position.y < self.position.y and + object.position.y + object.rectangle.width/2 >= self.position.y - self.radius and + self.position.x <= object.position.x+object.rectangle.width/2 and + self.position.x >= object.position.x - object.rectangle.width/2 + ): + bottom = True + + test = left + right + top + bottom + + if test == 1: + object.touched_by_ball = True + # the ball has collided with an edge + # TODO: # fix sticky edges + if left or right: + self.velocity.x *= -1 + if left: + self.position.x = object.position.x - object.rectangle.width/2 - self.radius - 1 + object.color = [255, 255, 255, 0] + del object + else: + self.position.x = object.position.x + object.rectangle.width/2 + self.radius + 1 + object.color = [255, 255, 255, 0] + del object + + if top or bottom: + self.velocity.y *= -1 + if top: + self.position.y = object.position.y - object.rectangle.height/2 - self.radius - 1 + object.color = [255, 255, 255, 0] + del object + else: + self.position.y = object.position.y + object.rectangle.height/2 + self.radius + 1 + object.color = [255, 255, 255, 0] + del object + + + elif test == 4: + # TODO: Better error handling + print('error: ball inside rectangle') + + elif test == 0: + # We are at a corner. Either it narrowly missed, or it hit the corner + corners = [ + Vector2(object.position.x - object.rectangle.width/2, object.position.y - object.rectangle.height/2), + Vector2(object.position.x + object.rectangle.width/2, object.position.y - object.rectangle.height/2), + Vector2(object.position.x - object.rectangle.width/2, object.position.y + object.rectangle.height/2), + Vector2(object.position.x + object.rectangle.width/2, object.position.y + object.rectangle.height/2) + ] + + for corner in corners: + relative_vector = self.position - corner + if relative_vector.length() <= self.radius: + object.touched_by_ball = True + # Create a dummy object to make use of ball to ball collision, because the math is the same + # Give it a velocity of the same magnitude as the current ball to cause it to reflect at + # the same speed + stand_in = Ball(self.bounds, corner, Vector2(0, self.velocity.length()), [0,0,0], 0) + self.collide_with_ball(stand_in, relative_vector) + + def collide_with_rectangle(self, object): # This function is called after a first-pass test, that is the collision @@ -167,3 +265,9 @@ def check_collision(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 issubclass(type(object), BreakBlock) 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_breakable_rectangle(object) + diff --git a/src/block.py b/src/block.py index f7966e2..5a7a927 100644 --- a/src/block.py +++ b/src/block.py @@ -22,7 +22,7 @@ def __init__(self, position, width, height, color): def update(self, **kwargs): self.touched_by_ball = False - + def check_collision(self): pass @@ -32,6 +32,27 @@ def draw(self, screen, pygame): class KineticBlock(Block): # No custom code needed here, just want to be able to differentiate # KineticBall will handle the collison - pass - - + def update(self, **kwargs): + self.touched_by_ball = False + + + if kwargs is not None: + print(kwargs) + print(self.position.x) + if kwargs["left"] == True: + self.position.x = self.position.x - 5 + elif kwargs["right"] == True: + self.position.x = self.position.x + 5 + else: + pass + + if self.position.x < 600 and self.position.x > 40: + self.rectangle = pygame.Rect( + self.position.x - (50/2), + self.position.y - (25/2), + 50, + 25) + +class BreakBlock(Block): + def update(self, **kwargs): + self.touched_by_ball = True \ No newline at end of file diff --git a/src/draw.py b/src/draw.py index 14ff036..50fc8f7 100644 --- a/src/draw.py +++ b/src/draw.py @@ -13,11 +13,24 @@ 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), - [255, 10, 0], 20) + [10, 10, 10], 5) object_list.append(kinetic) - block = KineticBlock(Vector2(200,200), 100, 100, [0, 0, 255]) + block = KineticBlock(Vector2(200,450), 100, 100, [0, 0, 255]) object_list.append(block) + + for j in range(0,10): + for i in range(0,17): + x = 0 + i * 40 + 10 + y = 0 + j * 20 + 10 + r = random.randint(1,250) + g = random.randint(1,250) + b = random.randint(1,250) + block2 = BreakBlock(Vector2(x,y), 40, 20, [r, g, b]) + object_list.append(block2) + + + def main(): pygame.init() @@ -44,7 +57,7 @@ def main(): if keys[pygame.K_RIGHT]: right = True for object in object_list: - object.update() + object.update(left=left, right=right) object.check_collision() # Draw Updates