Reputation: 11
I've completed a small game project of the breakout game, but my main problem is that the ball seems to get stuck going side to side much more often than i would be okay with it happening. It's definitely a problem with the ball velocity and I've tried messing around with the numbers but I can't seem to make it stop getting stuck. Any ideas on how to fix it ,or even improve any of the code, would be greatly appreciated.
import sys
import pygame as pg
from random import randint
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
score = 0
lives = 3
def run_game():
pg.init()
screen = pg.display.set_mode((800,600))
pg.display.set_caption("Brick Breaker")
bg_color = (0, 0, 0)
screen.fill(bg_color)
class Paddle(pg.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pg.Surface([width, height])
self.image.fill(black)
self.image.set_colorkey(black)
pg.draw.rect(self.image, color, [0, 0, width, height])
self.rect = self.image.get_rect()
def moveLeft(self,pixels):
self.rect.x -= pixels
if self.rect.x < 0:
self.rect.x = 0
def moveRight(self,pixels):
self.rect.x += pixels
if self.rect.x > 700:
self.rect.x = 700
class Ball(pg.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pg.Surface([width, height])
self.image.fill(black)
self.image.set_colorkey(black)
pg.draw.rect(self.image, color, [0, 0, width, height])
self.velocity = [randint(4,8),randint(-8,8)]
self.rect = self.image.get_rect()
def update(self):
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
def bounce(self):
self.velocity[0] = -self.velocity[0]
self.velocity[1] = randint(-8,10)
class Brick(pg.sprite.Sprite):
def __init__(self, color, width, height):
super().__init__()
self.image = pg.Surface([width, height])
self.image.fill(black)
self.image.set_colorkey(black)
pg.draw.rect(self.image, color, [0, 0, width, height])
self.rect = self.image.get_rect()
clock = pg.time.Clock()
all_sprites_list = pg.sprite.Group()
paddle = Paddle(white,100,10)
paddle.rect.x = 350
paddle.rect.y = 560
ball = Ball(white,10,10)
ball.rect.x = 345
ball.rect.y = 195
all_bricks = pg.sprite.Group()
for i in range(7):
brick = Brick(red,80,30)
brick.rect.x = 60 + i* 100
brick.rect.y = 60
all_sprites_list.add(brick)
all_bricks.add(brick)
for i in range(7):
brick = Brick(blue,80,30)
brick.rect.x = 60 + i* 100
brick.rect.y = 100
all_sprites_list.add(brick)
all_bricks.add(brick)
for i in range(7):
brick = Brick(green,80,30)
brick.rect.x = 60 + i* 100
brick.rect.y = 140
all_sprites_list.add(brick)
all_bricks.add(brick)
all_sprites_list.add(paddle)
all_sprites_list.add(ball)
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
sys.exit()
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
paddle.moveLeft(10)
if keys[pg.K_RIGHT]:
paddle.moveRight(10)
all_sprites_list.update()
if ball.rect.x>=790:
ball.velocity[0] = -ball.velocity[0]
if ball.rect.x<=0:
ball.velocity[0] = -ball.velocity[0]
if ball.rect.y>590:
ball.velocity[1] = -ball.velocity[1]
global lives
lives-=1
if lives == 0:
font = pg.font.Font(None, 74)
text = font.render("YOU LOSE", 1, red)
screen.blit(text,(280,250))
pg.display.flip()
sys.exit()
if ball.rect.y<40:
ball.velocity[1] = -ball.velocity[1]
if pg.sprite.collide_mask(ball, paddle):
ball.rect.x -= ball.velocity[0]
ball.rect.y -= ball.velocity[1]
ball.bounce()
brick_collision_list = pg.sprite.spritecollide(ball,all_bricks,False)
for brick in brick_collision_list:
ball.bounce()
brick.kill()
if len(all_bricks)==0:
font = pg.font.Font(None, 74)
text = font.render("YOU WIN", 1, green)
screen.blit(text,(280,250))
pg.display.flip()
sys.exit()
screen.fill(black)
font = pg.font.Font(None, 40)
text = font.render("lives: " + str(lives), 1, white)
screen.blit(text, (10,10))
all_sprites_list.draw(screen)
pg.display.flip()
clock.tick(50)
run_game()
Upvotes: 1
Views: 641
Reputation: 210968
When the ball hits the paddle, then set the bottom of the ball to the top of the paddle. It is not necessary to change the direction of the ball, because it's direction is changed in ball.bounce()
if pg.sprite.collide_mask(ball, paddle):
ball.rect.bottom = paddle.rect.top
#ball.rect.x -= ball.velocity[0]
#ball.rect.y -= ball.velocity[1]
ball.bounce()
In Ball.bounce
invert the y direction of the ball and compute a new random x direction:
class Ball(pg.sprite.Sprite):
def __init__(self, color, width, height):
# [...]
self.velocity = [randint(-8,8), randint(4,8)]
def bounce(self):
# invert y
self.velocity[1] = -self.velocity[1]
# either random x
# self.velocity[0] = randint(-8, 8)
# or slightly changed x
self.velocity[0] = max(-8, min(8, self.velocity[0] + randint(-3, 3)))
Upvotes: 1