2

I am fairly new to python and the module pygame. I also recently started work on a small project where the purpose of the game is to if a circle touches the "player" (the square) then the game will end or present a message saying you loose (still trying to solve the hitbox issue so still thinking of what to do after). The problem I am having is I am having trouble creating a way to detect the collision of the hitboxes and every time I try to make a way to test if the hitboxes I have collided it just won't work, so if someone can tell me how to make the classes and hitbox, another method, or even how to fix my code so it won't crash with a player class. Thank you, for any help, I may receive.

Here is the code (apologies if it is horrible on the eyes I kept on deleting and adding stuff while trying to find a solution and also sorry if I did something improper this is one of my first questions).

import pygame
import random

pygame.init()

width, height = 800, 800
hbox, vbox = 15, 15
rect = pygame.Rect(500, 600, hbox, vbox)
velocity = (0, 0)
frames = 40
ball_size = 12
white = (255, 255, 255)
black = (0, 0, 0)
hp = 100

screen = pygame.display.set_mode((width, height))


pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)

is_blue = True


clock = pygame.time.Clock()


class Ball:


    def __init__(self):
        self.x = 0
        self.y = 0
        self.change_x = 0
        self.change_y = 0
        self.hitbox = (self.x + 1, self.y + 2, 31, 57)


def make_ball():

    ball = Ball()
    Ball.hitbox = ball.hitbox

    ball.x = random.randrange(ball_size, width - ball_size)
    ball.y = random.randrange(ball_size, height - ball_size)

    ball.change_x = random.randrange(-2, 3)
    ball.change_y = random.randrange(-2, 3)

    return ball


ball_list = []

ball = make_ball()
ball_list.append(ball)


class player(object):
    def __init__(self, ):
        self.x = rect.x
        self.y = rect.y
        self.box_width = hbox
        self.box_hieght = vbox
        self.speed = move
        player.hitbox = (self.x + 1, self.y + 11, 29, 52)

    def draw(self, is_blue):
        if is_blue:
            color = (0, 128, 255)
        else:
            color = (255, 100, 0)
        if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
            is_blue = not is_blue
        Player = player
        Player = pygame.draw.rect(screen, color, rect)

    def move(self):
        surface = pygame.Surface((100, 100))

        keys = pygame.key.get_pressed()
        if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
            move = 8
        else:
            move = 4
        if keys[pygame.K_w]:
            rect.y -= move
        if rect.y < 0:
            rect.y = 0
        if keys[pygame.K_s]:
            rect.y += move
        if rect.y > height - hbox:
            rect.y = height - vbox
        if keys[pygame.K_a]:
            rect.x -= move
        if rect.x < 0:
            rect.x = 0
        if keys[pygame.K_d]:
            rect.x += move
        if rect.x > width - hbox:
            rect.x = width - hbox



running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            # Space bar! Spawn a new ball.
            if event.key == pygame.K_SPACE:
                ball = make_ball()
                ball_list.append(ball)
        if rect.x == ball.x and rect.y == ball.y:
            hp -100
            if hp == 0:
                pygame.quit()


    if event.type == pygame.KEYDOWN and event.key == pygame.K_c:
        is_blue = not is_blue

    surface = pygame.Surface((100, 100))

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]:
        move = 8
    else:
        move = 4
    if keys[pygame.K_w]:
        rect.y -= move
    if rect.y < 0:
        rect.y = 0
    if keys[pygame.K_s]:
        rect.y += move
    if rect.y > height - hbox:
        rect.y = height - vbox
    if keys[pygame.K_a]:
        rect.x -= move
    if rect.x < 0:
        rect.x = 0
    if keys[pygame.K_d]:
        rect.x += move
    if rect.x > width - hbox:
        rect.x = width - hbox


    screen.fill((0, 0, 0))

    if is_blue:
        color = (0, 128, 255)
    else:
        color = (255, 100, 0)

    color_2 = (255, 0, 0)
    for ball in ball_list:

        ball.x += ball.change_x
        ball.y += ball.change_y

        if ball.y > height - ball_size or ball.y < ball_size:
            ball.change_y *= -1
        if ball.x > width - ball_size or ball.x < ball_size:
            ball.change_x *= -1



    screen.fill(black)


    for ball in ball_list:
        pygame.draw.circle(screen, white, [ball.x, ball.y], ball_size)


    Rectangle = pygame.draw.rect(screen, color, rect)


    pygame.display.flip()

    clock.tick(30)


` 
Odin2318
  • 35
  • 1
  • 4
  • 1
    pygame has [pygame.Rect()](https://www.pygame.org/docs/ref/rect.html) to keep item's position and size - and `Rect` has function to check collision between two rectangles, etc.. – furas Nov 19 '19 at 18:03
  • `Rect` has also properties like `top`, `bottom`, `left`, `right`,etc - so you can write `rect.bottom > width` instead of `rect.x > width - hbox` – furas Nov 19 '19 at 18:08
  • @furas, thank you so much for the help and I got it to work – Odin2318 Nov 19 '19 at 18:49

1 Answers1

1

In general I recommend to use pygame.sprite.Sprite and pygame.sprite.Group, but I'll show you a solution, which is closer to your current code.

Create a Ball class, which can move and draw the ball object. The class has a .rect attribute of type pygame.Rect instead of the attributes .x and .y and can be used for the "hitbox", too.
The rectangle is updated in the instance method move():

class Ball:

    def __init__(self):
        x = random.randrange(ball_size, width - ball_size)
        y = random.randrange(ball_size, height - ball_size)
        self.change_x, self.change_y = 0, 0
        while self.change_x == 0 and self.change_y == 0:
            self.change_x = random.randrange(-2, 3)
            self.change_y = random.randrange(-2, 3)
        self.rect = pygame.Rect(x-ball_size, y-ball_size, ball_size*2, ball_size*2)

    def move(self):
        self.rect = self.rect.move(self.change_x, self.change_y)
        if self.rect.right >= height or self.rect.left < 0:
            self.change_x *= -1
        if self.rect.bottom >= width or self.rect.top <= 0:
            self.change_y *= -1

    def draw(self, surface): 
        pygame.draw.circle(surface, white, self.rect.center, ball_size)

def make_ball():
    ball = Ball()
    return ball

In the main application loop, the balls can be moved and drawn in a for-loop and the collision test can be done by .colliderect():

hits = 0
running = True
while running:

    # [...]

    for ball in ball_list:
        if ball.rect.colliderect(rect):
            hits += 1
            print("hit " + str(hits))   

    # [...]

    for ball in ball_list:
        ball.move()

    screen.fill(black)

    for ball in ball_list:
        ball.draw(screen)

    Rectangle = pygame.draw.rect(screen, color, rect)

    pygame.display.flip()
    clock.tick(30)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174