from engine import * from engine.event import * import pygame import random from breakout_event import * class visual_object: def __init__(self): self.rect = pygame.Rect(0,0,0,0) def set_pos(self, pos): self.rect.left, self.rect.top = pos def set_size(self, size): self.rect.size = size def get_pos(self): return (self.rect.left, self.rect.top) def get_size(self): return self.rect.size def get_rect(self): return self.rect def draw(self, screen): abstract class wall(visual_object): def __init__(self): ## super(wall, self).__init__() visual_object.__init__(self) self.color = (0,0,0) def set_color(self, color): self.color = color def draw(self, screen): pygame.draw.rect(screen, self.color, self.get_rect()) def update(self): pass def set_update(self, update_method): self.update = update_method ## A breakout-specific sprite, which inherits from Pygame.sprite.Sprite.sprite.Sprite...Sprite. class breakout_sprite(pygame.sprite.Sprite): def __init__(self): super(breakout_sprite,self).__init__() self.rect = pygame.Rect(0,0,0,0) def update(self, announce_method): pass def set_pos(self, pos): self.rect.left, self.rect.top = pos def get_pos(self): return (self.rect.left, self.rect.top) def get_size(self): return self.rect.size def get_rect(self): return self.rect def set_image(self, image): pos = self.get_pos() self.image = image self.rect = image.get_rect() self.set_pos(pos) def draw(self, screen): screen.blit(self.image, self.get_pos()) class breakout_sprites(pygame.sprite.Group): pass ## This is a brick that resides in our level. When something hits it, ## update() will be called, telling the level to remove the brick ## and to increase the score. class brick(breakout_sprite): def __init__(self): super(brick,self).__init__() self.filename = "brick.png" def update(self, announce_method): announce_method(remove_brick_event(self)) announce_method(increase_score_event(10)) def load(self): pos = self.get_pos() self.set_image(misc.load_image(self.filename)) self.set_pos(pos) def clear(self): self.image = None class red_brick(brick): def __init__(self): super(red_brick, self).__init__() self.files = ["red_brick.png", "red_brick2.png", "brick.png"] self.hitcount = 0 def update(self, announce_method): if self.hitcount == 2: announce_method(remove_brick_event(self)) announce_method(increase_score_event(20)) announce_method(ball_increase_speed_event(1)) else: self.hitcount += 1 self.set_image(misc.load_image(self.files[self.hitcount])) announce_method(increase_score_event(5)) def load(self): pos = self.get_pos() self.set_image(misc.load_image(self.files[0])) self.set_pos(pos) class blue_brick(brick): def __init__(self): super(blue_brick, self).__init__() self.filename = "blue_brick.png" def update(self, announce_method): announce_method(remove_brick_event(self)) announce_method(increase_score_event(20)) announce_method(ball_increase_speed_event(2)) class orange_brick(brick): def __init__(self): super(orange_brick, self).__init__() self.filename = "orange_brick.png" def update(self, announce_method): announce_method(remove_brick_event(self)) announce_method(increase_score_event(1)) announce_method(paddle_increase_size_event()) ## The paddle is controlled by the player. Since update() gets ## called on a collision, it will make the ball go upwards. class paddle(breakout_sprite): def __init__(self, *args): super(paddle,self).__init__(*args) def update(self, announce_method): announce_method(ball_bounce_up()) announce_method(increase_score()) ##pass ## This is our ball. It contains methods for changing direction, ## moving, freezing and it's current speed. class ball(breakout_sprite, listener): def __init__(self): super(ball,self).__init__() self.reset((200, 200)) ## Catch some events that comes from our event ## handler. Basically, the ball takes care of ## its own behaviour. def notify(self, event): if isinstance(event, tick_event): self.move() if isinstance(event, draw_event): self.draw(event.get_screen()) elif isinstance(event, ball_up_event): self.ydir = -abs(self.ydir) elif isinstance(event, ball_down_event): self.ydir = abs(self.ydir) elif isinstance(event, ball_right_event): self.xdir = abs(self.xdir) elif isinstance(event, ball_left_event): self.xdir = -abs(self.xdir) elif isinstance(event, mouse_moved_event): if self.active == False: x,y = self.get_pos() self.set_pos((event.pos[0]-5, y)) elif isinstance(event, mouse_pressed_event): self.active = True elif isinstance(event, ball_increase_speed_event): self.speed += event.speed def move(self): if self.active == True: for i in range (0, self.speed): self.rect = self.rect.move(self.xdir, self.ydir) self.event_handler.announce(ball_moved_event(self)) def init_direction(self): ## This just sets a random direction of the ball. ## However, it should always go upwards. self.xdir = 1 * (-2*(random.randint(1, 2) % 2)+1 ) self.ydir = -2 ## Sets some default values of the ball, so that we can ## reset it at any time. def reset(self, pos): self.active = False self.init_direction() self.speed = 3 self.set_pos(pos) ## This is a helper function to detect collisions ## between sprites. It is mainly used in breakout_level ## and the breakout_ingame state. ## def ball_collide(ball, sprite, announce_method): ## collided = False ## def c1(): ## announce_method(ball_down_event()) ## announce_method(ball_right_event()) ## return True ## def c2(): ## announce_method(ball_down_event()) ## announce_method(ball_left_event()) ## return True ## def c4(): ## announce_method(ball_up_event()) ## announce_method(ball_left_event()) ## return True ## def c8(): ## announce_method(ball_down_event()) ## announce_method(ball_right_event()) ## return True ## def c3(): ## announce_method(ball_down_event()) ## return True ## def c10(): ## announce_method(ball_left_event()) ## return True ## def c12(): ## announce_method(ball_up_event()) ## return True ## def c5(): ## announce_method(ball_right_event()) ## return True ## def c0(): ## pass ## x,y = ball.get_pos() ## width,height = ball.get_size() ## ## The following somewhat cryptic four lines ORs ## ## together the collisions with sprite's four ## ## vertices. ## collide_type = sprite.get_rect().collidepoint(x,y) | \ ## sprite.get_rect().collidepoint(x+width,y)*2 | \ ## sprite.get_rect().collidepoint(x,y+height)*4 | \ ## sprite.get_rect().collidepoint(x+width,y+height)*8 ## collide_action = { ## 0: c0, ## 1: c1, ## 2: c2, ## 3: c3, ## 4: c4, ## 5: c5, ## 6: c0, ## 7: c0, ## 8: c8, ## 9: c0, ## 10: c10, ## 11: c0, ## 12: c12, ## 13: c0, ## 14: c0, ## 15: c0 } ## collided = collide_action.get(collide_type)() ## print "breakout_graphics: Collided:",str(collided) ## return collided def ball_collide(ball, sprite, announce_method): collided = False def c1(): announce_method(ball_down_event()) announce_method(ball_right_event()) return True def c2(): announce_method(ball_down_event()) announce_method(ball_left_event()) return True def c4(): announce_method(ball_up_event()) announce_method(ball_right_event()) return True def c8(): announce_method(ball_up_event()) announce_method(ball_left_event()) return True def c3(): announce_method(ball_down_event()) return True def c10(): announce_method(ball_left_event()) return True def c12(): announce_method(ball_up_event()) return True def c5(): announce_method(ball_right_event()) return True def c0(): pass x,y = ball.get_pos() width,height = ball.get_size() ## The following somewhat cryptic four lines ORs ## together the collisions with sprite's four ## vertices. collide_type = sprite.get_rect().collidepoint(x,y) | \ sprite.get_rect().collidepoint(x+width,y)*2 | \ sprite.get_rect().collidepoint(x,y+height)*4 | \ sprite.get_rect().collidepoint(x+width,y+height)*8 collide_action = { 0: c0, 1: c1, 2: c2, 3: c3, 4: c4, 5: c5, 6: c0, 7: c0, 8: c8, 9: c0, 10: c10, 11: c0, 12: c12, 13: c0, 14: c0, 15: c0 } collided = collide_action.get(collide_type)() if collide_type != 0: print "breakout_graphics: Collided:",collide_type ##str(collided) return collided