Breakout

Breakout is an arcade game developed and published by Atari and released in 1976.

Breakout begins with eight rows of bricks, with each two rows a different color. The color order from the bottom up is - yellow, - green, - orange and - red.

Using a single ball, the player must knock down as many bricks as possible by using the walls and/or the paddle below to ricochet the ball against the bricks and eliminate them.

If the player’s paddle misses the ball’s rebound, they will lose a turn. The player has three turns to try to clear two screens of bricks. Yellow bricks earn one point each, green bricks earn three points, orange bricks earn five points and the top-level red bricks score seven points each. The paddle shrinks to one-half its size after the ball has broken through the red row and hit the upper wall.

Ball speed increases at specific intervals: after four hits, after twelve hits, and after making contact with the orange and red rows. The highest score achievable for one player is 896; this is done by eliminating two screens of bricks worth 448 points per screen.

https://upload.wikimedia.org/wikipedia/en/c/cd/Breakout_game_screenshot.png

Making an app

The first step is to create a frame work which creates a window

10_games/breakout/pong1.png
from pygame.locals import *
import numpy as np

class Sprite:
    def __init__(self, file=None, pos=(0, 0), size=None):
        self.parent = None
        self.size = size
        self.rect = Rect(pos, (20, 20))
        self.position = np.array(pos, dtype=float)
        self.velocity = np.array([1.5, 0.5], dtype=float)

        self.angle = 0
        self.angular_velocity = 0

        self.color = 'red'
        self.speed = [0, 0]
        if file:
            self.image = pygame.image.load(file)
            if self.size:
                self.image = pygame.transform.scale(self.image, size)
                self.rect.size = self.image.get_size()
        else:
            self.image = pygame.Surface(self.rect.size)
            self.image.fill(self.color)
        self.image0 = self.image.copy()

    def set_pos(self, pos):
        self.position = np.array(pos, dtype=float)
        self.rect.center = pos
 
    def set_angle(self, angle):
        self.angle = angle
        self.image = pygame.transform.rotate(self.image0, self.angle)
        self.rect.size = self.image.get_size()

    def do(self, event):
        pass

    def update(self):
        self.move()

    def move(self):
        self.position += self.velocity

        if self.angular_velocity:
            self.angle += self.angular_velocity
            self.image = pygame.transform.rotate(self.image0, self.angle)
            self.rect.size = self.image.get_size()

        self.rect.center = self.position
    
    def draw(self, surf):
        surf.blit(self.image, self.rect)

    def distance(self, other):
        distance = self.position - other.position
        distance *= distance
        d = np.sqrt(np.sum(distance))
        return d


class App:
    def __init__(self, file=None, caption='Pygame'):
        pygame.init()
        pygame.display.set_caption(caption)
        self.flags = RESIZABLE
        self.size = (640, 240)
        self.screen = pygame.display.set_mode(self.size, self.flags)
        self.running = True
        self.updating = True
        self.objects = []
        self.bg_color = 'gray'
        if file:
            self.load_image(file)
        else:
            self.image = pygame.Surface(self.size)
            self.image.fill(self.bg_color)
            self.rect = self.image.get_rect()
        self.key_cmd = {}

    def load_image(self, file):
        self.image = pygame.image.load(file).convert()
        self.rect = self.image.get_rect()
        self.screen = pygame.display.set_mode(self.rect.size, self.flags)

    def run(self):
        while self.running:
            for event in pygame.event.get():
                self.do(event)
            self.update()
            self.draw()

    def add_cmd(self, key, cmd):
        self.key_cmd[key] = cmd
        print(self.key_cmd)

    def add(self, object):
        self.objects.append(object)
        object.parent = self

    def do(self, event):
        if event.type == QUIT:
            self.running = False
            pygame.quit()
        elif event.type == KEYDOWN:
            if event.key == K_SPACE:
                self.updating = not self.updating

            if event.key in self.key_cmd:
                cmd = self.key_cmd[event.key]
                eval(cmd)

        for obj in self.objects:
            obj.do(event)

    def update(self):
        if self.updating:
            for obj in self.objects:
                obj.update()

    def draw(self):
        self.screen.blit(self.image, self.rect)
        for obj in self.objects:
            obj.draw(self.screen)
        pygame.display.update()
        
if __name__ == '__main__':
    app = App('space.png', 'Asteroids')

    ship = Sprite('spaceship.png', size=(100, 50), pos=(300, 200))
    app.add(ship)
    app.add(Sprite('asteroid.png', size=(100, 100), pos=(100, 300)))
    app.add(Sprite('asteroid.png', size=(150, 150), pos=(400, 100)))
    
    app.add_cmd(K_a, 'print(123)')
    app.add_cmd(K_b, "self.load_image('space.png')")
    app.run()

app.py