Arkanoid part 6 – Still on bricks collision

Arkanoid made with pygame, part 6.

Now it collides up and down, but in a strange way when it hits the middle of a brick (the ball goes inside the brick, because it goes both up and down util it collides with the brick, so it moves horizzontally for the lenght of the brick).

I just added a couple of lines in the collision function

def collision():
    global ball, bar, ball_y

    if ball.rect.colliderect(bar):
        print("Collision detected")
        ball_y = "up"
        print(ball_y)
        print(ball.yb)
        speed_up()

    for brick in bricks:
        if ball.rect.colliderect(brick):
            if ball_y == "up":
                ball_y = "down"
            else:
                ball_y = "up"

    if ball.yb > 500:
        ball.xb, ball.yb = 500, 300

Another small change: a function to show the bricks

In the while loop now there is this function call

    show_bricks()

and the function is simply this (nothing changed in the showing of the bricks)

def show_bricks():
    for brick in bricks:
        brick.update()

How the list of bricks is made

I memorize into this the bricks sprites

bricks = create_bricks()

that calls this function that returns the list

def create_bricks():
    "The bricks scheme"
    blist = """
11001
11111
01111
01010
""".splitlines()[1:]
    bricks = []
    h = 30
    w = 0
    for line in blist:
        for brick in line:
            if brick == "1":
                bricks.append(Brick(20 + w * 100, h))
            w += 1
            if w == 5:
                w = 0
                h += 50
    return bricks

h = 30 is the vertical position of the first line of the bricks.

As you see in h += 50, the other lines of bricks are now 50 pixels distant from each other. I also added another line of bricks that now are also more distant horizzontally and there are just 5 bricks for line.

The bricks are built on this class:

class Brick:
    "Draw Player 2"

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.rect = pygame.Rect(self.x, self.y, 60, 20)

    def update(self):
        pygame.draw.rect(screen, GREEN, (self.x, self.y, 60, 20))

As you can see there is the self.rect attribute that contains a Rect object with the position of each brick. Being them listed in the bricks list the collision is detected in the function collision like this (as I showed before)

    for brick in bricks:
        if ball.rect.colliderect(brick):
            if ball_y == "up":
                ball_y = "down"
            else:
                ball_y = "up"

 

The whole code

# pong!
import pygame
from pygame import gfxdraw


class Brick:
    "Draw Player 2"

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.rect = pygame.Rect(self.x, self.y, 60, 20)

    def update(self):
        pygame.draw.rect(screen, GREEN, (self.x, self.y, 60, 20))


class Bar:
    "Draw Player 2"

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def update(self):
        pygame.draw.rect(screen, RED, (self.x, self.y, 60, 10))
        self.rect = pygame.Rect(self.x, self.y, 60, 10)


class Ball:
    "Draw Player 2"

    def __init__(self, xb, yb):
        self.xb = xb
        self.yb = yb

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

        # sull'asse x Va verso sinistra
        if ball_x == "left":
            # sottraggo perchè vado a sinistra
            ball.xb -= vel_bal
            # se arriva a 10 rimbalza
            if ball.xb < 10:
                ball_x = "right"
        # va in basso
        if ball_y == 'down':
            # allora aumenta y quando va in basso (parte da 0 in alto)
            ball.yb += vel_bal
        if ball_y == 'up':
            # quando va in alto tolgo
            ball.yb -= vel_bal
            # se arriva in cima rimbalza in basso
            if ball.yb < 10:
                ball_y = 'down'
        # se va a destra aumenta x
        if ball_x == "right":
            ball.xb += vel_bal
            # a 480 rimbalza verso sinistra
            if ball.xb > 480:
                ball_x = "left"
        gfxdraw.filled_circle(screen, ball.xb, ball.yb, 5, GREEN)
        self.rect = pygame.Rect(self.xb, self.yb, 10, 10)


def collision():
    global ball, bar, ball_y

    if ball.rect.colliderect(bar):
        print("Collision detected")
        ball_y = "up"
        print(ball_y)
        print(ball.yb)
        speed_up()

    for brick in bricks:
        if ball.rect.colliderect(brick):
            if ball_y == "up":
                ball_y = "down"
            else:
                ball_y = "up"

    if ball.yb > 500:
        ball.xb, ball.yb = 500, 300


def exit(event):
    global loop

    if event.type == pygame.QUIT:
        loop = 0
    if event.type == pygame.KEYUP:
        if event.key == pygame.K_ESCAPE:
            loop = 0
    return loop


def speed_up():
    global bar, vel_bal
    bar.x = pygame.mouse.get_pos()[0]
    if startx == bar.x:
        vel_bal = 2
        print("Normal speed")
    else:
        vel_bal = 3
        print("Speed up")


def create_bricks():
    "The bricks scheme"
    blist = """
11001
11111
01111
01010
""".splitlines()[1:]
    bricks = []
    h = 30
    w = 0
    for line in blist:
        for brick in line:
            if brick == "1":
                bricks.append(Brick(20 + w * 100, h))
            w += 1
            if w == 5:
                w = 0
                h += 50
    return bricks

def show_bricks():
    for brick in bricks:
        brick.update()

BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
ball_x = 'left'
ball_y = 'down'
scorep1 = 0
scorep2 = 0
vel_bal = 2
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Game")
startx = 0
bar = Bar(10, 480)
ball = Ball(100, 100)
bricks = create_bricks()
background = pygame.image.load("img\\background.png")
pygame.mouse.set_visible(False)
loop = 1
while loop:
    screen.blit(background, (0, 0))
    keys = pygame.key.get_pressed()
    for event in pygame.event.get():
        loop = exit(event)
    if pygame.mouse.get_pos()[0] > 10 and pygame.mouse.get_pos()[0] < 430:
        bar.x = pygame.mouse.get_pos()[0]
    ball.update()
    bar.update()
    collision()
    startx = bar.x
    show_bricks()
    pygame.display.update()
    clock.tick(120)


pygame.quit()

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.