1

I have been trying to make a car football game with pygame, and have almost finished, but I would like some help with goal scoring and border detection. I wasn't able to get something to happen if the ball touched the net(I tried with the red net. Anything with the name "redsurf" is the goal). Also, when I try to make the ball and car bounce off the edge, nothing happens, but the ball strangely moves at the beginning. "Borderline" is what I am trying to use to make the ball bounce off the side". Additionally, I can't get the boosted speed to work, not sure why though. I really hope someone can help and edit my code so it works.

import pygame
from pygame.math import Vector2


pygame.init()
WIDTH = 1150
HEIGHT = 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

bgImg = pygame.image.load("Football_pitch.png")
redsurf = pygame.Surface((50,125))
redsurf.fill((255,0,0))
redsurfpos = Vector2(50,125)
bluesurf = pygame.Surface((50,125))
bluesurf.fill((0,0,255))
bluesurfpos = Vector2(50,125)
borderline = pygame.draw.rect(screen, (0,0,0),[10,10,10,10],0)

BLUECAR_ORIGINAL = pygame.Surface((50, 30), pygame.SRCALPHA)
pygame.draw.polygon(
    BLUECAR_ORIGINAL, (0, 0, 255), [(0, 30), (50, 20), (50, 10), (0, 0)])
bluecar = BLUECAR_ORIGINAL
REDCAR_ORIGINAL = pygame.Surface((50, 30), pygame.SRCALPHA)
pygame.draw.polygon(
    REDCAR_ORIGINAL, (255, 0, 0), [(0, 0), (50, 10), (50, 20), (0, 30)])
redcar = REDCAR_ORIGINAL

score = 0
redspeed = 7
bluespeed = 7
ball_x = 575
ball_y = 400
dx = 1
dy = 0

BALL = pygame.Surface((30, 30), pygame.SRCALPHA)
pygame.draw.circle(BALL, [0,0,0], [15, 15], 15)

ball_pos = Vector2(ball_x, ball_y)
ballrect = BALL.get_rect(center=ball_pos)
redsurfrect = redsurf.get_rect(center=redsurfpos)
bluesurfrect = redsurf.get_rect(center=bluesurfpos)
ball_vel = Vector2(dx, dy)

pos_red = Vector2(1000,370)
vel_red = Vector2(redspeed,0)
redrect = redcar.get_rect(center=pos_red)
redangle = 0
pos_blue = Vector2(70,70)
vel_blue = Vector2(bluespeed,0)
bluerect = bluecar.get_rect(center=pos_red)
blueangle = 0

mask_blue = pygame.mask.from_surface(bluecar)
mask_red = pygame.mask.from_surface(redcar)
mask_ball = pygame.mask.from_surface(BALL)
mask_redsurfgoal = pygame.mask.from_surface(redsurf)
mask_bluesurfgoal = pygame.mask.from_surface(bluesurf)


run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False




    ball_x += dx
    ball_y += dy

    if ball_y<0 or ball_y>HEIGHT - 40:
        dy *= -1
    if ball_x<0 or ball_x>WIDTH  - 40:
        dx *= -1

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        redangle += 5
        vel_red.rotate_ip(-5)
        redcar = pygame.transform.rotate(REDCAR_ORIGINAL, redangle)
        redrect = redcar.get_rect(center=redrect.center)

        mask_red = pygame.mask.from_surface(redcar)
    elif keys[pygame.K_RIGHT]:
        redangle -= 5
        vel_red.rotate_ip(5)
        redcar = pygame.transform.rotate(REDCAR_ORIGINAL, redangle)
        redrect = redcar.get_rect(center=redrect.center)
        mask_red = pygame.mask.from_surface(redcar)
    elif keys[pygame.K_l]:
        redspeed = 20


    if keys[pygame.K_a]:
        blueangle += 5
        vel_blue.rotate_ip(-5)
        bluecar = pygame.transform.rotate(BLUECAR_ORIGINAL, blueangle)
        bluerect = bluecar.get_rect(center=bluerect.center)
        mask_blue = pygame.mask.from_surface(bluecar)
    elif keys[pygame.K_d]:
        blueangle -= 5
        vel_blue.rotate_ip(5)
        bluecar = pygame.transform.rotate(BLUECAR_ORIGINAL, blueangle)
        bluerect = bluecar.get_rect(center=bluerect.center)
        mask_blue = pygame.mask.from_surface(bluecar)



    pos_red += vel_red
    redrect.center = pos_red
    pos_blue += vel_blue
    bluerect.center = pos_blue

    ball_vel *= .95  
    ball_pos += ball_vel
    ballrect.center = ball_pos


    offset_red = redrect[0] - ballrect[0], redrect[1] - ballrect[1]
    offset_redgoal = ballrect[0] - redsurfrect[0], ballrect[1] - redsurfrect[1]

    overlap_red = mask_ball.overlap(mask_red, offset_red)

    offset_blue = bluerect[0] - ballrect[0], bluerect[1] - ballrect[1]
    overlap_blue = mask_ball.overlap(mask_blue, offset_blue)
    offset_rednetgoal = ballrect[0] - redsurfrect[0], ballrect[1] - redsurfrect[1]
    overlap_redgoal = mask_ball.overlap(redsurfrect, offset_rednetgoal)

    if overlap_red and overlap_blue:  
        ball_vel = vel_red + vel_blue * 1.4
    elif overlap_red:  
        ball_vel = Vector2(vel_red) * 1.4
    elif overlap_blue:  
        ball_vel = Vector2(vel_blue) * 1.4
    elif overlap_redgoal:
        print("goal")



    screen.blit(bgImg, (0, 0))
    screen.blit(BALL, ballrect)
    screen.blit(redcar, redrect)
    screen.blit(bluecar, bluerect)
    screen.blit(redsurf, (0,340))
    screen.blit(bluesurf,(1100,340))

    pygame.display.flip()
    pygame.display.update()
    clock.tick(60)

pygame.quit()
Hussain Hammad
  • 125
  • 2
  • 14

1 Answers1

1

To bounce off the screen edges, you can just invert the velocity of the ball when the rect is outside of the screen area.

if ballrect.top < 0 and ball_vel.y < 0:
    ball_vel.y *= -1
elif ballrect.bottom > screen.get_height() and ball_vel.y > 0:
    ball_vel.y *= -1
if ballrect.left < 0 and ball_vel.x < 0:
    ball_vel.x *= -1
elif ballrect.right > screen.get_width() and ball_vel.x > 0:
    ball_vel.x *= -1

To implement the goal collision detection, you could just call the colliderect method of the rects of the ball and the goals. Of course that's not perfectly accurate, but won't be noticeable most of the time.

if ballrect.colliderect(redgoal_rect):

If you rather want to use mask collision, you need to calculate the offset by subtracting the x- and y-coords of one object from the coords of the other object and then call the overlap method of the second object's mask and pass the mask of the first object.

import pygame as pg
from pygame.math import Vector2


pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color(30, 90, 0)

# You need surfaces with an alpha channel to
# create masks, therefore pass `pg.SRCALPHA`.
REDGOAL = pg.Surface((90, 150), pg.SRCALPHA)
REDGOAL.fill((255, 0, 0))
redgoal_rect = REDGOAL.get_rect(topleft=(100, 200))
redgoal_mask = pg.mask.from_surface(REDGOAL)

BALL = pg.Surface((30, 30), pg.SRCALPHA)
pg.draw.circle(BALL, [250, 250, 250], [15, 15], 15)
# Ball variables.
ball_pos = Vector2(275, 200)
ballrect = BALL.get_rect(center=ball_pos)
ball_vel = Vector2(0, 0)
ball_mask = pg.mask.from_surface(BALL)

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == pg.KEYDOWN:
            if event.key == pg.K_a:
                ball_vel.x = -7
            elif event.key == pg.K_d:
                ball_vel.x = 8
            elif event.key == pg.K_w:
                ball_vel.y = -3
            elif event.key == pg.K_s:
                ball_vel.y = 5

    ball_vel *= .94  # Friction.
    ball_pos += ball_vel
    ballrect.center = ball_pos

    if ballrect.top < 0 and ball_vel.y < 0:
        ball_vel.y *= -1
    elif ballrect.bottom > screen.get_height() and ball_vel.y > 0:
        ball_vel.y *= -1
    if ballrect.left < 0 and ball_vel.x < 0:
        ball_vel.x *= -1
    elif ballrect.right > screen.get_width() and ball_vel.x > 0:
        ball_vel.x *= -1

    # Rect collision.
    # if ballrect.colliderect(redgoal_rect):
    #     print('goal!')

    # Calculate the offset between the objects.
    offset = redgoal_rect[0] - ballrect[0], redgoal_rect[1] - ballrect[1]
    # Pass the offset to the `overlap` method. If the masks collide,
    # overlap will return a single point, otherwise `None`.
    overlap = ball_mask.overlap(redgoal_mask, offset)

    if overlap:
        print('goal!')

    screen.fill(BG_COLOR)
    screen.blit(BALL, ballrect)
    screen.blit(REDGOAL, redgoal_rect)
    pg.display.flip()
    clock.tick(60)

pg.quit()

It would actually be a good idea to use colliderect first and if the rects collide, use the overlap method of the masks (that would be more efficient).

skrx
  • 19,980
  • 5
  • 34
  • 48