Breakout / Arkanoid – 5 versions in one (pygame)

The previous version had only three styles

Since I have made different versions of the classic Arkanoid or Breakout game, I decided to pull them all together in this version that you can find in this github repository.

Go here for the executable and the source code: arkapygame_5_0 (on itch.io).

In a future post I will show you, step by step, how to make this game with python and the pygame module.

There are 5 versions:

  • Monochrome
  • Polychrome
  • Tiny
  • Tiny 2
  • Randonoid (random stages)

Each one has his style and the last one gives you a random style for each stage. Each one has its maxscore in a txt file.

This is the code at the moment (it could be updated in the github repository). In the repository you will find the assets too.

The video with the game

In this video of the ArkaGame v.5, you will see the 5 different versions of the game.

The code

# arkanoid
import pygame
from pygame import gfxdraw
import os
from random import choice, randrange

'''
To add a new type of game
- createbricks5()
- restart5()
in the while loop of the mainmenu
            elif event.key == pygame.K_5:
                game = 5
                restart5()
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_1 or event.key == pygame.K_2 or event.key == pygame.K_3 or event.key == pygame.K_4 or event.key == pygame.K_5:
                screen.fill((0, 0, 0))
                mainloop()

in collision 1 line 135
                if game == 5:
                    bricks = create_bricks5()
in text

    if game == 4:
        scorefile = "score4.txt"

In the menu

write("4 - Arkanoid tiny 2", 150, 400)
'''

BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)


class Brick:
    "One brick class"

    def __init__(self, x, y, w=50, h=20, color=GREEN):
        self.x = x
        self.y = y
        self.w = w
        self.h = h
        self.color = color
        # This is for collision1
        self.rect = pygame.Rect(self.x, self.y, self.w, self.h)

    def update(self):
        # when you update it will go to self.x and self.y
        # bar.x is constantly equal to the mouse position in the while loop
        pygame.draw.rect(screen, self.color, self.rect)



class Bar:
    "This is the bar class"

    def __init__(self, x, y, w=60, h=10):
        self.x = x
        self.y = y
        self.w = w
        self.h = h

    def update(self):

        self.rect = pygame.Rect(self.x, self.y, self.w, self.h)
        pygame.draw.rect(screen, RED, self.rect)


velocity = 2
class Ball:
    "Draw Player 2"

    def __init__(self, x, y, size=10):
        self.x = x
        self.y = y
        self.color = RED
        self.counter = pygame.time.get_ticks()
        self.size = size

    def update(self):
        "The ball moves"
        global ball, velocity
        global ball_x, ball_y, game

        # sull'asse x Va verso sinistra
        
        if pygame.time.get_ticks() - self.counter > velocity:
            self.counter = pygame.time.get_ticks()
            if ball_x == "left":
                # sottraggo perchè vado a sinistra
                ball.x -= velx
                # se arriva a 10 rimbalza
                if ball.x < 10:
                    pygame.mixer.Sound.play(s_wall)
                    ball_x = "right"
            # va in basso
            if ball_y == 'down':
                # allora aumenta y quando va in basso (parte da 0 in alto)
                ball.y += vel_y
            if ball_y == 'up':
                # quando va in alto tolgo
                ball.y -= vel_y
                # se arriva in cima rimbalza in basso
                if ball.y < 50:
                    pygame.mixer.Sound.play(s_wall)
                    ball_y = 'down'
            # se va a destra aumenta x
            if ball_x == "right":
                ball.x += velx
                # a 480 rimbalza verso sinistra
                if ball.x > 490:
                    pygame.mixer.Sound.play(s_wall)
                    ball_x = "left"

        gfxdraw.filled_circle(screen, ball.x, ball.y, self.size // 2, self.color)
        # This is to check the collisions
        self.rect = pygame.Rect(self.x, self.y, self.size, self.size)




def collision1():
    global ball, bar, ball_y, ball_x, vely, velx, mousedir, bricks
    global diff, lives, stage, score, loop, game, randomstage
    if ball.rect.colliderect(bar):
        print("sulla barra: ", ball.x - bar.x)
        print("Diff=", diff)
        pygame.mixer.Sound.play(hitbar)
        # when the ball hit the bar, it goes up
        ball_y = "up"
        if (mousedir == "left" and ball_x == "right"):
            ball_x = "left"
        if (mousedir == "right" and ball_x == "left"):
            ball_x = "right"

        # if diff > 0:
        #     if  diff < 8:
        #         velx = diff // 2
        #         vely = diff // 2
        # print(f"you hit with diff: {diff} vel_x = {velx}")

    for n, brick in enumerate(bricks):
        if ball.rect.colliderect(brick):
            # screen.fill((0, 0, 0))
            pygame.draw.rect(screen, (0, 0, 0), brick.rect)
            screen.blit(update_fps(color="Black"), (12, 10))
            score += 20
            screen.blit(update_fps(), (12, 10))
            pygame.mixer.Sound.play(hitbrick)
            # print("You hit a brick")
            if ball_y == "up":
                # the ball is lower than the brick of 20
                if ball.y == (brick.y + brick.h - vel_y):
                    ball_y = "down"
                # if the balls hit the brick on a side
                else:
                    if ball_x == "left":
                        ball_x = "right"
                    else:
                        ball_x = "left"
            elif ball_y == "down":
                if ball.y <= brick.y - 1:
                    ball_y = "up"
                else:
                    if ball_x == "left":
                        ball_x = "right"
                    else:
                        ball_x = "left"
            bricks.pop(n)
            if bricks == []:
                write_highest_score()
                screen.fill((0, 0, 0))
                ball.y = 300
                ball.x = 100
                pygame.mixer.Sound.play(s_ready)
                if randomstage == 1:
                    game = randrange(1,5)
                if game == 1:
                    bricks = create_bricks1()
                if game == 2:
                    bricks = create_bricks2()
                if game == 3:
                    bricks = create_bricks3()
                if game == 4:
                    bricks = create_bricks4()
                if game == 5:
                    game = randrange(1, 5)
                    if game == 1:
                        create_bricks1()
                    if game == 2:
                        create_bricks2()
                    if game == 3:
                        create_bricks3()
                        ball.size, bar.w = 6, 30
                    if game == 4:
                        ball.size, bar.w = 6, 30
                        create_bricks4()
                show_bricks()

    if ball.y > 510:
        ball.x, ball.y = 500, 300
        lives -= 1
        pygame.mixer.Sound.play(s_out)
        if lives < 0:
            pygame.mixer.Sound.play(s_over)
            set_score()
            score = 0
            stage = 0
            ball_y = 'down'
            ball_x = 'left'
            back_to_menu()




def create_bricks1():
    "The bricks scheme for game 1"
    blist = []
    templ = []
    for n in range(3):
        riga = [str(choice([0, 1])) for x in range(4)]
        riga2 = riga[::-1]
        riga = riga + riga2
        # print(riga)
        templ.append(riga)
    templ.append(templ[2])
    templ.append(templ[1])
    templ.append(templ[0])
    for riga in templ:
        blist.append("".join(riga))
    bricks = []
    h = 50
    w = 0
    for line in blist:
        for brick in line:
            if brick == "1":
                bricks.append(Brick(20 + w * 60, h))
            w += 1
            if w == 8:
                w = 0
                h += 30
    return bricks


def create_bricks2():
    "The bricks scheme for game 2"
    blist = []
    for n in range(randrange(5,16)):
        riga = [str(choice([0, 1])) for x in range(4)]
        riga2 = riga[::-1]
        riga = riga + riga2
        # print(riga)
        blist.append("".join(riga))
    bricks = []
    h = 50
    w = 0
    for line in blist:
        rndclr = randrange(100, 255), randrange(100, 255), randrange(100, 255),
        for brick in line:
            if brick == "1":
                bricks.append(Brick(50 + w * 51, h, color=rndclr))
            w += 1
            if w == 8:
                w = 0
                h += 21
    return bricks


column = 10
def create_bricks3():
    "The bricks scheme"
    global column
    blist = []
    for n in range(randrange(10, 16)):
        riga = [str(choice([0, 1])) for x in range(column)]
        riga2 = riga[::-1]
        riga = riga + riga2
        # print(riga)
        blist.append("".join(riga))

    bricks = []
    h = 50
    w = 0
    for line in blist:
        rndclr = randrange(0, 100), randrange(50, 255), randrange(250, 255)
        for brick in line:
            if brick == "1":
                bricks.append(Brick(6 + w * 26, h, w=25, h=10, color=rndclr))
            w += 1
            if w == column * 2:
                w = 0
                h += 11
    return bricks


def create_bricks4():
    "The bricks scheme"
    global column
    blist = []
    templ = []
    for n in range(randrange(3,16)):
        riga = [str(choice([0, 1])) for x in range(column)]
        riga2 = riga[::-1]
        riga = riga + riga2
        templ.append(riga)
    templ.append(templ[2])
    templ.append(templ[1])
    templ.append(templ[0])
    for riga in templ:
        blist.append("".join(riga))
    bricks = []
    h = 50
    w = 0
    for line in blist:
        randomcolor = randrange(0, 255), randrange(0, 255), randrange(0, 255),
        for brick in line:
            if brick == "1":
                bricks.append(Brick(6 + w * 51, h, w=30, h=10, color=randomcolor))
            w += 1
            if w == column * 2:
                w = 0
                h += 21
    return bricks


def write_highest_score():
    "Checks highest score when game's over"
    global score, scoremax

    with open("score.txt", "w") as file:
        if scoremax < score:
            file.write(str(score))



def update_fps(color="Coral"):
    global score, scoremax

    fps = f"Max: {scoremax} Lives: {lives} Stage: {stage} Score: {score} "
    fps_text = font.render(fps, 1, pygame.Color(color))
    return fps_text






def write(text, x, y, color="Coral",):
    text = font.render(text, 1, pygame.Color(color))
    text_rect = text.get_rect(center=(500 // 2, y))
    screen.blit(text, text_rect)
    return text


def score_text():
    global game, randomstage

    if game == 1:
        scorefile = "score1.txt"
    if game == 2:
        scorefile = "score2.txt"
    if game == 3:
        scorefile = "score3.txt"
    if game == 4:
        scorefile = "score4.txt"
    if randomstage == 1:
        scorefile = "score5.txt"

    return scorefile



def get_score():
    global scoremax, game

    scorefile = score_text()
    # Se il file esiste
    if scorefile in os.listdir():
        with open(scorefile, "r") as file:
            # Se non c'è scritto nulla, ci scrive 100
            if file.readlines() == []:
                with open(scorefile, "w") as filewrite:
                    filewrite.write("100")
                    scoremax = 100
            # Se ci sono dati, li legge e mi memorizza in score max
            else:
                with open(scorefile, "r") as file:
                    # print(file.readlines())
                    scoremax = int(file.readlines()[0])
    # Se non c'è il file, lo crea e ci scrive 100
    else:
        with open(scorefile, "w") as file:
            file.write("100")

def set_score():
    global score, randomstage


    scorefile = score_text()
    with open(scorefile, "r") as file:
        scoremax = int(file.readlines()[0])
    if score > scoremax:
        with open(scorefile, "w") as file:
            file.write(str(score))



def restart_common():
    "Common restart"    
    global score, lives, stage

    stage = 0
    score = 0
    lives = 3
    screen.fill((0, 0, 0))
    ball.x, ball.y = 250, 300
    ball.update()
    bar.update()
    ball.size = 10
    bar.w = 60



def restart1():
    global bricks
    "MONOCHROME VERSION"
    restart_common()
    bricks = create_bricks1()
    show_bricks()


def restart2():
    global bricks
    "POLYCHROME VERSION"
    restart_common()
    bricks = create_bricks2()
    show_bricks()

def restart3():
    global bricks
    "TINY VERSION 1"
    restart_common()
    ball.size = 6
    bar.w = 30
    bricks = create_bricks3()
    show_bricks()

def restart4():
    global bricks
    "TINY VERSION 2"
    restart_common()
    ball.size = 6
    bar.w = 30
    bricks = create_bricks4()
    show_bricks()


def show_bricks():
    for brick in bricks:
        brick.update()
    screen.blit(barrier, (0, 0))
    screen.blit(barrier, (495, 0))

def back_to_menu():
    set_score()
    screen.fill((0, 0, 0))
    mainmenu()

# =================================================================
def mainloop():
    global startx, mousedir, diff, game
    pygame.mixer.Sound.play(s_ready)
    show_bricks()
    # screen.fill((0, 0, 0))

    get_score()
    loop = 1
    while loop:

        pygame.draw.rect(screen, (0, 0, 0), (bar.x, bar.y, bar.w, bar.h))
        gfxdraw.filled_circle(screen, ball.x, ball.y, ball.size // 2, (0, 0, 0))
        # keys = pygame.key.get_pressed()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                set_score()
                loop = 0
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    set_score()
                    loop = 0
                if event.key == pygame.K_m:
                    back_to_menu()
            if event.type == pygame.KEYUP:
                if event.type == pygame.K_ESCAPE:
                    loop = 0
        # This is the position of the mouse on the x axe

        posx = pygame.mouse.get_pos()[0]
        if pygame.mouse.get_pos()[1] > 400:
            bar.y = pygame.mouse.get_pos()[1]

        if posx > 10 and posx < 430 + 60 - bar.w:
            # il surface si muove come il mouse
            bar.x = posx
        diff = startx - posx
        mousedir = check_mouse_dir(diff)
        startx = posx
        ball.update()

        bar.update()
        collision1()
        pygame.display.update()
        clock.tick(240)
    pygame.quit()


def check_mouse_dir(diff):
    if diff < 0:
        mousedir = "right"
    elif diff > 0:
        mousedir = "left"
    else:
        mousedir = ""
    return mousedir






randomstage = 0
def mainmenu():
    "The menu to choose among different games"
    
    global game, randomstage
    
    
    screen.fill((0, 0, 0))
    write("ARKAGAME", 200, 120, color="yellow")
    write("A Game by Giovanni Gatto", 200, 20, color="red")
    write("Follow me on youtube", 200, 140)
    write("and pythonprogramming.altervista.org", 200, 160)
    write("CHOOSE YOUR GAME", 200, 300, color="green")
    write("1 - Arkanoid Monochrome", 150, 340)
    write("2 - Arkanoid Polichrome", 150, 360)
    write("3 - Arkanoid tiny", 150, 380)
    write("4 - Arkanoid tiny 2", 150, 400)
    write("5 - RANDONOID", 150, 420)
    # write("4 - Arkanoid tiny 2", 150, 400)
    write("July 2020", 150, 480, color="gray")
    loop = 1
    while loop:
        # screen.blit(background, (0, 0))
        # keys = pygame.key.get_pressed()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loop = 0
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    loop = 0
                elif event.key == pygame.K_1:
                    game = 1
                    restart1()
                elif event.key == pygame.K_2:
                    game = 2
                    restart2()
                elif event.key == pygame.K_3:
                    game = 3
                    restart3()
                elif event.key == pygame.K_4:
                    game = 4
                    restart4()
                elif event.key == pygame.K_5:
                    randomstage = 1
                    game = randrange(1, 5)
                    if game == 1:
                        restart1()
                    if game == 2:
                        restart2()
                    if game == 3:
                        restart3()
                    if game == 4:
                        restart4()
                # Next game
                # elif event.key == pygame.K_6:
                #     game = 6
                #     restart6()
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_1 or event.key == pygame.K_2 or event.key == pygame.K_3 or event.key == pygame.K_4 or event.key == pygame.K_5:
                    screen.fill((0, 0, 0))
                    mainloop()

        pygame.display.update()
    pygame.quit()

# costants
stage = 0
lives = 3

ball_x = 'left'
ball_y = 'down'
# speed horizzontal
velx = 1
# speed vertical
vel_y = 1
######################
#     sound          #
######################
pygame.mixer.pre_init(44100, -16, 1, 512)
pygame.init()
pygame.mixer.quit()
pygame.mixer.init(22050, -16, 2, 512)
pygame.mixer.set_num_channels(32)
# =========================== ([ sounds ]) ============
hitbar = pygame.mixer.Sound('sound\\hitbar2.wav')
s_out = pygame.mixer.Sound('sound\\outspeech.wav')
hitbrick = pygame.mixer.Sound('sound\\hitbrick.wav')
s_ready = pygame.mixer.Sound('sound\\ready.wav')
s_over = pygame.mixer.Sound('sound\\over.wav')
s_wall = pygame.mixer.Sound('sound\\wall.wav')

screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("ArkaGame 5.0 by pythonprogramming.altervista.org")

clock = pygame.time.Clock()
startx = 0

background = pygame.image.load("img\\background.png").convert()
barrier = pygame.image.load("img\\barrier.png").convert()
pygame.mouse.set_visible(False)
mousedir = "stop"
diff = 0
score = 0
font = pygame.font.SysFont("Arial", 14)
scoremax = 0

font = pygame.font.SysFont("Arial", 24)
bar = Bar(10, 480)
ball = Ball(100, 300)
pygame.event.set_grab(True)

mainmenu()

1.1 – Pong the father of Arkanoid

Pong v. 1.0 – Pygame example

1.2 – Starting arkanoid… from pong

Arkanoid… let’s make it better…

1.3 – Adding background

ArkaPyGame 1.3 – Adding a background

1.4 – Collision detection

ArkaPygame 1.4 – Collision detected

1.5 – Bricks collisions

Arkanoid in pygame part 5

1.6 – Still on Collisions

Arkanoid part 6 – Still on bricks collision

1.7 – Fixed strange bouncing

Arkanoid 1.7 – Fixed strange bouncing

1.8 – How to destroy the bricks

Arkanoid 1.8 – First stage almost complete: destroy bricks

1.9 – More levels

Arkanoid 1.9 – more stages

2.1 – Infinite level generator

Arkanoid 2.0 – infinite levels

2.3 – Sounds and faster frame rate tecnique

ArkaPyGame 2.1 – Arkanoid like game made with Pygame

2.5 – New nicer levels simmetric and in color and menus

Arkanoid-Pygame 2.5 – New levels and menu

2.6 – Keyboard control

ArkaGame 2.6 – Adding keyboard commands

2.7 – Mouse exclusive control

Arkanoid 2.7 with Pygame – Mouse control

2.xxx – Tiny version

TinyArka – “Mini” version of Arkanoid with pygame

5.0 – Arkagame: 5 different versions

Breakout / Arkanoid – 5 versions in one (pygame)

Github repository
https://github.com/formazione/arkapygame


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

 

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.