Before you criticize me for not Googling or doing research before asking, I did research beforehand but to no avail.
I am trying to create the Atari Breakout game. I am currently stuck with making the ball bounce off walls. I did research on this and I found a lot of blogs and YouTube videos (and also Stack Overflow questions: this and this) talking about PyGame's vector2 class. I also read the PyGame documentation on vector2 but I can't figure out how to make it work.
I am currently writing a script to make the ball bounce off walls. In the beginning, the player is requested to press the spacebar and the ball will automatically move towards the north-east direction. It should bounce off the top wall when it hits it, but instead, it went inside. This is my approach:
import pygame
pygame.init()
screenWidth = 1200
screenHeight = 700
window = pygame.display.set_mode((screenWidth,screenHeight))
pygame.display.set_caption('Atari Breakout')
class Circle():
def __init__(self, x, y, radius):
self.x = x
self.y = y
self.radius = radius
self.vel_x = 1
self.vel_y = 1
def check_hit():
global hit
if (((screenWidth-box.x)<=box.radius) or ((box.x)<=box.radius) or ((box.y)<=box.radius) or ((screenHeight-box.y)<=box.radius)):
# meaning hit either four walls
if (((screenWidth-box.x)<=box.radius) or ((box.x)<=box.radius)):
# hit right, left
print('hit right, left')
hit = True
elif (((box.y)<=box.radius) or ((screenHeight-box.y)<=box.radius)):
# hit top, bottom
print('hit top, bottom')
hit = True
# main loop
run = True
box = Circle(600,300,10)
hit = False
# (screenWidth-box.x)<=box.radius hit right wall
while run: # (box.x)<=box.radius hit left wall
# (box.y)<=box.radius hit top wall
pygame.time.Clock().tick(60) # (screenHeight-box.y)<=box.radius hit bottom wall
for event in pygame.event.get():
if event == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and (box.y)>box.radius:
while True:
box.y -= box.vel_y
box.x += box.vel_x
window.fill((0,0,0))
pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
pygame.display.update()
check_hit()
if hit == False:
continue
elif hit == True:
break
if (box.y)<=box.radius or (screenHeight-box.y)<=box.radius:
# hit top, bottom
box.vel_x *= 1
box.vel_y *= -1
print('changed')
if (box.y)<=box.radius:
# hit top
print('hi')
while True:
box.x += box.vel_x # <-- myguess is this is the problem
box.y += box.vel_y
window.fill((0,0,0))
pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
pygame.display.update()
elif (screenWidth-box.x)<=box.radius or (box.x)<=box.radius:
# hit right, left
box.vel_x *= -1
box.vel_y *= 1
window.fill((0,0,0))
pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
pygame.display.update()
print('Where are you going')
pygame.quit()
I guess the problem is where I marked. Which is here:
if (box.y)<=box.radius or (screenHeight-box.y)<=box.radius:
# hit top, bottom
box.vel_x *= 1
box.vel_y *= -1
print('changed')
if (box.y)<=box.radius:
# hit top
print('hi')
while True:
box.x += box.vel_x # <-- myguess is this is the problem
box.y += box.vel_y
window.fill((0,0,0))
pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
pygame.display.update()
but I don't know why. My theory is: the ball travels upwards, it hit the top wall, check_hit() kicks in and make hit = True, then the vel_x and vel_y is changed accordingly (if hit top wall, vel_x should remain the same while vel_y should be multiplied by -1). Then it will move down, hence "bounce" off the top wall.
Note: for now I only have the top wall working. The other three will be done when I can figure out how to bounce off the top wall first.
Can you help me see what's the problem? And if this kind of operation requires the use of the vector2 class, can you explain it to me or give me a place to learn it?
The issue are the multiple nested loops. You have an application loop, so use it.
Continuously move the ball in the loop:
box.y -= box.vel_y
box.x += box.vel_x
Define a rectangular region for the ball by a pygame.Rect object:
bounds = window.get_rect() # full screen
or
bounds = pygame.Rect(450, 200, 300, 200) # rectangular region
Change the direction of movement when the ball hits the bounds:
if box.x - box.radius < bounds.left or box.x + box.radius > bounds.right:
box.vel_x *= -1
if box.y - box.radius < bounds.top or box.y + box.radius > bounds.bottom:
box.vel_y *= -1
See the example:
box = Circle(600,300,10)
run = True
start = False
clock = pygame.time.Clock()
while run:
clock.tick(120)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
start = True
bounds = pygame.Rect(450, 200, 300, 200)
if start:
box.y -= box.vel_y
box.x += box.vel_x
if box.x - box.radius < bounds.left or box.x + box.radius > bounds.right:
box.vel_x *= -1
if box.y - box.radius < bounds.top or box.y + box.radius > bounds.bottom:
box.vel_y *= -1
window.fill((0,0,0))
pygame.draw.rect(window, (255, 0, 0), bounds, 1)
pygame.draw.circle(window, (44,176,55), (box.x, box.y), box.radius)
pygame.display.update()
Related
I am working on a little project to get to know Pygame and I was working with the following tutorial to introduce myself:
https://www.101computing.net/pong-tutorial-using-pygame-getting-started/
After following that tutorial and making tweaks of my own (mainly stylistic, nothing functional), every time I run the program the ball just goes back and forth on the same y coordinate and won't go up and down. It seems like everything else works but the variation in the vertical movement of the ball.
I can provide my code if needed as well, but it looks similar to the tutorial above.
edit: here's the code
import pygame
#need random integers for velocity changes
import random
Black = (0,0,0)
#create ball object for the game, wil be a sprite object
class Ball(pygame.sprite.Sprite):
#define the package function and also call the pygame sprite constructor using super()
def __init__(self, color, width, height):
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(Black)
self.image.set_colorkey(Black)
#draw the ball
pygame.draw.rect(self.image, color, [0, 0, width, height])
#set velocity
self.velocity = [random.randint(4,8), random.randint(-8,8)]
#get rectangle object from image package
self.rect = self.image.get_rect()
def update(self):
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
#reverse velocity path of ball hits paddle
def bounce(self):
self.velocity[0] = -self.velocity[0]
self.velocity[1] = random.randint(-8,8)
-----Main File-----
import pygame
#import paddle sprites
from paddle import Paddle
#import ball
from ball import Ball
import time
pygame.init()
#set local colors: Black for background, white for text, blue and red for teams
Black = (0,0,0)
White = (255,255,255)
Red = (255,0,0)
Blue = (0,0,255)
#create paddles using paddle class and add them to a list of sprites
paddleLeft = Paddle(Red, 10, 100)
paddleLeft.rect.x = 20
paddleLeft.rect.y = 200
paddleRight = Paddle(Blue, 10, 100)
paddleRight.rect.x = 870
paddleRight.rect.y = 200
ball = Ball(White, 10, 10)
ball.rect.x = 445
ball.rect.y = 195
allSprites = pygame.sprite.Group()
allSprites.add(paddleLeft)
allSprites.add(paddleRight)
allSprites.add(ball)
#set game window
size = (900,500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Multiplayer Pong")
#to the functionality, we will have a while loop that will listen to user inputs, adding logic to the game (score, boundaries, etc.), and refreshing the program
#global "running" funtion that will control the while loop, simple bool
running = True
#need a clock for refreshing the screen (included in pygame package)
clock = pygame.time.Clock()
#scores for each side
scoreLeft = 0
scoreRight = 0
#start loop
while running:
#--listen for inputs
for event in pygame.event.get():
if event.type == pygame.QUIT: #if quit button is pressed, leave
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
running = False
#keyboard inputs
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddleLeft.mUp(5)
if key[pygame.K_s]:
paddleLeft.mDown(5)
if key[pygame.K_UP]:
paddleRight.mUp(5)
if key[pygame.K_DOWN]:
paddleRight.mDown(5)
#--logic
allSprites.update()
#--drawing here (paddles, screen, scores, boundaries, etc
screen.fill(Black)
pygame.draw.line(screen, White, [448, 0], [448, 500], 4)
allSprites.draw(screen)
#check for wall bounce
#algorithms for bounce look like
#Hits right or left wall? reverse X-bound velocity
#Hits top or bottom wall? reverse Y-bound velocity
if ball.rect.x >= 890:
scoreLeft += 1
ball.rect.x = 445
ball.rect.y = 195
time.sleep(2)
ball.velocity[0] = -ball.velocity[0]
if ball.rect.x <= 0:
scoreRight += 1
ball.rect.x = 445
ball.rect.y = 195
time.sleep(2)
ball.velocity[0] = -ball.velocity[0]
#reverse ball angle
if ball.rect.y >= 490:
ball.velocity[1] = -ball.velocity[1]
if ball.rect.y >= 0:
ball.velocity[1] = -ball.velocity[1]
#check for paddle hit
if pygame.sprite.collide_mask(ball, paddleLeft) or pygame.sprite.collide_mask(ball, paddleRight):
ball.bounce()
#display scores
font = pygame.font.SysFont("impact.ttf", 50)
text = font.render(str(scoreLeft), 1, Red)
screen.blit(text, (420,10))
text = font.render(str(scoreRight), 1, Blue)
screen.blit(text, (460,10))
#--update screen with drawings
pygame.display.flip()
#--60 fps limit
clock.tick(60)
#stop program once main loop is exited
pygame.quit()
After some debugging I realized that the y values was constantly hopping from some value up then down, the velocity seemed to work but it was constantly changing signs
The problem is on line 103 the:
if ball.rect.y >= 0:
you must of missed typed it as the y value will always be greater then 0, I fixed it by switching it to
if ball.rect.y <= 0:
and it worked.
I recently started making Atari Breakout in Pygame and I encountered a weird bug. Whenever the ball touches the left side of the paddle, it bounces off normally but when it's on the right, it flies through the paddle. Please help, because I don't know how to fix it.
This is my code:
import pygame, random, math
pygame.init()
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption('Atari Breakout')
player = pygame.image.load('player copy.png')
ball = pygame.image.load('poland.png')
ballx, bally = 400, 300
balldx, balldy = 2,2
def isCollision(x1,y1,x2,y2):
distance = math.sqrt(math.pow(x1 - x2, 2) + math.pow(y1 - y2, 2))
if distance <= 32:
return True
else:
return False
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pos = pygame.mouse.get_pos()
if isCollision(ballx, bally, pos[0], 525):
balldy *= -1
if bally >= 0:
balldy *= -1
if bally <= 570:
balldy *= -1
if ballx <= 0:
balldx *= -1
if ballx >= 770:
balldx *= -1
ballx += balldx
bally += balldy
screen.blit(player, (pos[0], 525))
screen.blit(ball, (ballx,bally))
pygame.display.update()
Actually isCollision computes the Euclidean distance between the top left of the rectangle which surrounds the ball and the top left of the paddle.
The shape of the player (paddle) is a rectangle with a very long and a very short side. Thus the collision algorithm doesn't work at all. I recommend to use pygame.Rect objects and colliderect, to detect a collision between the ball and the player. e.g.:
def isCollision(x1,y1,x2,y2):
ballRect = ball.get_rect(topleft = (x1, y1))
playerRect = player.get_rect(topleft = (x2, y2))
return ballRect.colliderect(playerRect)
while running:
# [...]
pos = pygame.mouse.get_pos()
if isCollision(ballx, bally, pos[0], 525):
balldy *= -1
This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
I'm creating a game in pygame, but the collision isn't working between the player (a rect) and a wall (an image).
here's v190131a/__init__.py,
import os
import sys
import pygame
import time
import screeninfo
screendata = screeninfo.get_monitors()
screendata = screendata[0]
class Player(object):
def __init__(self):
self.rect = pygame.Rect(32, 32, 16, 16)
# self.offset = (screen.get_size()[0]-32, screen.get_size()[1]-32)
self.offset = (1, 1)
def move(self, dx, dy):
# Move each axis separately. Note that this checks for collisions both times.
if dx != 0:
self.move_single_axis(dx, 0)
if dy != 0:
self.move_single_axis(0, dy)
def move_single_axis(self, dx, dy):
# Move the rect
self.rect.x += dx
self.rect.y += dy
for wall in walls:
if self.rect.colliderect(wall.rect):
print(wall.rect)
if dx > 0: # Moving right; Hit the left side of the wall
self.rect.right = wall.obj.left
if dx < 0: # Moving left; Hit the right side of the wall
self.rect.left = wall.obj.right
if dy > 0: # Moving down; Hit the top side of the wall
self.rect.bottom = wall.obj.top
if dy < 0: # Moving up; Hit the bottom side of the wall
self.rect.top = wall.obj.bottom
for border in borders:
if self.rect.colliderect(border):
if dx > 0: # Moving right; Hit the left side of the wall
self.rect.right = border.left
if dx < 0: # Moving left; Hit the right side of the wall
self.rect.left = border.right
if dy > 0: # Moving down; Hit the top side of the wall
self.rect.bottom = border.top
if dy < 0: # Moving up; Hit the bottom side of the wall
self.rect.top = border.bottom
class Wall(object):
def __init__(self, pos):
walls.append(self)
self.obj = assets["whitebrick"]
self.rect = self.obj.get_rect()
self.pos = pos
borders = [pygame.Rect(0, 0, screendata.width, 16),
pygame.Rect(0, 16, 16, screendata.height),
pygame.Rect(0, screendata.height-64, screendata.width, 16),
pygame.Rect(screendata.width-16, 0, 16, screendata.height)
]
walls = []
screen = None
clock = None
player = None
assets = None
def assetgrab():
return {
"whitebrick": pygame.image.load("v190131a/assets/img/whitebrick.png").convert_alpha()
}
def init():
global screen, clock, player, assets
os.environ["SDL_VIDEO_CENTERED"] = "1"
pygame.init()
# Set up the display
pygame.display.set_caption("Get to the red square!")
screen = pygame.display.set_mode((0, 0), pygame.RESIZABLE)
clock = pygame.time.Clock()
player = Player() # Create the player
assets = assetgrab()
Wall((32, 256))
def event(evnt):
if evnt.type == pygame.QUIT:
sys.exit()
if evnt.type == pygame.KEYDOWN and evnt.key == pygame.K_ESCAPE:
sys.exit()
def mainloop():
global borders
# Move the player if an arrow key is pressed
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
player.move(-5, 0)
if key[pygame.K_RIGHT]:
player.move(5, 0)
if key[pygame.K_UP]:
player.move(0, -5)
if key[pygame.K_DOWN]:
player.move(0, 5)
screen.get_size()
borders = [pygame.Rect(0, 0, screen.get_size()[0], 16),
pygame.Rect(0, 16, 16, screen.get_size()[1]),
pygame.Rect(0, screen.get_size()[1]-64, screen.get_size()[0], 16),
pygame.Rect(screen.get_size()[0]-16, 0, 16, screen.get_size()[1])
]
player.move(0, 5)
# Draw the scene
screen.fill((0, 0, 0))
pygame.draw.rect(screen, (255, 200, 0), player.rect)
for wall in walls:
screen.blit(wall.obj, wall.pos)
[pygame.draw.rect(screen, (0, 0, 0), x) for x in borders]
pygame.display.flip()
def end():
time.sleep(0.0166666667)
pass
Which then gets ran by core.py:
import pygame
import v190131a as core
core.init()
while True:
for event in pygame.event.get():
core.event(event)
core.mainloop()
core.end()
The player is supposed to land on the wall and stop, but instead, it passes right through. Is there something I'm missing; do I need to change the player to an image, is it an obvious logic error?
Help would be appreciated, thanks.
I am creating a physics-based game with Pygame in which the player controls a ball. As you control the ball, it accelerates in the specified direction (holding the left arrow adds x pixels per frame to its movement speed). Since the ball is... well... a ball, and Pygame doesn't support ball collision detection, I created a new class with its own collision method. The method has two parts: if the ball runs into the corner of a rectangle, or if it runs into the side of the rectangle. The problem concerns the circle-to-side collision.
The ball is based on a rect object, and therefore has those pesky corners. I cannot use the simple colliderect method, otherwise the situation above would detect a collision where there should be none, and it would overlap the first part of my collision detection method. Instead, I opted to use collidepoint between the rectangle and the midpoints on each side of the ball's rectangle.
Finally, the heart of the issue. I mentioned earlier that the ball accelerates. When the ball accelerates to the point that (even though it appears to be standing still) it moves far enough into the rectangle for another midpoint on the circle to detect a "collision." This problem likely stems from the fact that (for a collision on the left side of the ball) my code sets the ball's left equal to the rectangle's right, so that when the ball accelerates enough to be inside the rectangle, it gets moved to another face of the rectangle.
Thank you so much for bearing with me, any and all suggestions are welcome. I would either be looking for a fix to my specific problem, or a cleaner way to handle the collision detection. My full code is below:
import pygame, sys, math
global Color
Color = {}
Color['white'] = (255,255,255)
Color['black'] = ( 0, 0, 0)
Color['red'] = (255, 0, 0)
Color['green'] = ( 0,255, 0)
Color['blue'] = ( 0, 0,255)
global WINDOWWIDTH, WINDOWHEIGHT
WINDOWWIDTH, WINDOWHEIGHT = 500, 500
class Ball():
def __init__(self, x, y, r):
self.rect = pygame.Rect(x, y, r, r)
self.radius = r/2
self.speed = [0, 0]
self.b_fact = 1
self.move = {'left':False, 'right':False, 'up':False, 'down':False}
self.new_dir = {'left':False, 'right':False, 'up':False, 'down':False}
def move_self(self):
if self.move['left']:
self.speed[0] -= 2
if self.move['up']:
self.speed[1] -= 2
if self.move['right']:
self.speed[0] += 2
if self.move['down']:
self.speed[1] += 2
if self.speed[0] < 0:
self.speed[0] += 1
if self.speed[1] < 0:
self.speed[1] += 1
if self.speed[0] > 0:
self.speed[0] -= 1
if self.speed[1] > 0:
self.speed[1] -= 1
self.rect.left += self.speed[0]
self.rect.top += self.speed[1]
def bounce(self, rectList):
for rect in rectList:
self.collide_rect(rect)
if self.rect.left <= 0:
self.rect.left = 0
self.new_dir['right'] = True
if self.rect.right >= WINDOWWIDTH:
self.rect.right = WINDOWWIDTH
self.new_dir['left'] = True
if self.rect.top <= 0:
self.rect.top = 0
self.new_dir['down'] = True
if self.rect.bottom >= WINDOWHEIGHT:
self.rect.bottom = WINDOWHEIGHT
self.new_dir['up'] = True
for key in self.new_dir:
if self.new_dir[key] and key=='left':
self.speed[0] *= (-1)*self.b_fact
if self.new_dir[key] and key=='right':
self.speed[0] *= (-1)*self.b_fact
if self.new_dir[key] and key=='up':
self.speed[1] *= (-1)*self.b_fact
if self.new_dir[key] and key=='down':
self.speed[1] *= (-1)*self.b_fact
self.new_dir[key] = False
def collide_rect(self, rect):
x1, y1, r = self.rect.centerx, self.rect.centery, self.radius
foundSide = 0
foundCorner = 0
side_list = ['left', 'right', 'bottom', 'top']
corner_list = ['topleft', 'topright', 'bottomleft', 'bottomright']
collision_list = []
for side in side_list:
if rect.collidepoint(eval('self.rect.mid'+side)):
collision_list.append(side)
for corner in corner_list:
x2, y2 = eval('rect.'+corner)[0], eval('rect.'+corner)[1]
dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
if dist < r:
if corner.find('left') > -1:
corner = corner.replace('left','right')
else:
corner = corner.replace('right','left')
if corner.find('top') > -1:
corner = corner.replace('top','bottom')
else:
corner = corner.replace('bottom','top')
collision_list.append(corner)
for direction in collision_list:
if direction.find('left') > -1:
self.rect.left = rect.right
self.new_dir['left'] = True
if direction.find('top') > -1:
self.rect.top = rect.bottom
self.new_dir['top'] = True
if direction.find('right') > -1:
self.rect.right = rect.left
self.new_dir['right'] = True
if direction.find('bottom') > -1:
self.rect.bottom = rect.top
self.new_dir['bottom'] = True
class BallGame():
def __init__(self):
pygame.display.set_caption("Ball is life")
pygame.init()
self.ball = Ball(0, 0, 30)
self.allRects = []
rect = pygame.Rect(60,60,50,50)
self.allRects.append(rect)
self.mainClock = pygame.time.Clock()
self.screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
self.basicFont = pygame.font.SysFont(None, 50)
def drawScreen(self):
self.screen.fill(Color['green'])
pygame.draw.ellipse(self.screen, Color['white'], self.ball.rect)
for rect in self.allRects:
pygame.draw.rect(self.screen, Color['black'], rect)
def mainloop(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
for i in range(2):
k = (pygame.KEYUP, pygame.KEYDOWN)
if event.type == k[i]:
if event.key == pygame.K_LEFT:
self.ball.move['left'] = i
elif event.key == pygame.K_UP:
self.ball.move['up'] = i
elif event.key == pygame.K_RIGHT:
self.ball.move['right'] = i
elif event.key == pygame.K_DOWN:
self.ball.move['down'] = i
self.ball.move_self()
self.ball.bounce(self.allRects)
self.drawScreen()
pygame.display.update()
self.mainClock.tick(20)
Game = BallGame()
while True:
Game.mainloop()
Another way to think about the collision is to consider an enlarged version of the black rectangle. This would be a rounded rectangle with corner radius r. The collision between the ball and black rectangle is equivalent to the collision between the center of the ball and the rounded rectangle. This can help make the analysis of the situation easier.
When it bounces a more accurate way of determining the new position is to consider the line from the previous position to the current position. You can calculate where this line crosses the boundary and where a prefect reflection should be.
I am reading this book for Python called "More Python Programming for the Absolute Beginner" and in chapter 4, you create this bomb catching game. I am trying to modify it so you shoot at the bomb or enemy.
I want to be able to draw the bullets using
pygame.draw.circle()
and so it shoots when you click on the right mouse button, then it hits the enemy and it adds on your score.
By the way - I already know how to add the score on I just need help with shooting the shape :)
if you want to have a look at the original game source file, go here -
http://www.delmarlearning.com/companions/content/1435459806/relatedfiles/index.asp?isbn=1435459806
and it's in chapter 4, "BombCatcher"
original source code-
# Bomb Catcher Game
# Chapter 4
import sys, random, time, pygame
from pygame.locals import *
def print_text(font, x, y, text, color=(255,255,255)):
imgText = font.render(text, True, color)
screen.blit(imgText, (x,y))
#main program begins
pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("Bomb Catching Game")
font1 = pygame.font.Font(None, 24)
pygame.mouse.set_visible(False)
white = 255,255,255
red = 220, 50, 50
yellow = 230,230,50
black = 0,0,0
lives = 3
score = 0
clock_start = 0
game_over = True
mouse_x = mouse_y = 0
pos_x = 300
pos_y = 460
bomb_x = random.randint(0,500)
bomb_y = -50
vel_y = 0.7
#repeating loop
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
elif event.type == MOUSEMOTION:
mouse_x,mouse_y = event.pos
move_x,move_y = event.rel
elif event.type == MOUSEBUTTONUP:
if game_over:
game_over = False
lives = 3
score = 0
keys = pygame.key.get_pressed()
if keys[K_ESCAPE]:
sys.exit()
screen.fill((0,0,100))
if game_over:
print_text(font1, 100, 200, "<CLICK TO PLAY>")
else:
#move the bomb
bomb_y += vel_y
#has the player missed the bomb?
if bomb_y > 500:
bomb_x = random.randint(0, 500)
bomb_y = -50
lives -= 1
if lives == 0:
game_over = True
#see if player has caught the bomb
elif bomb_y > pos_y:
if bomb_x > pos_x and bomb_x < pos_x + 120:
score += 10
bomb_x = random.randint(0, 500)
bomb_y = -50
#draw the bomb
pygame.draw.circle(screen, black, (bomb_x-4,int(bomb_y)-4), 30, 0)
pygame.draw.circle(screen, yellow, (bomb_x,int(bomb_y)), 30, 0)
#set basket position
pos_x = mouse_x
if pos_x < 0:
pos_x = 0
elif pos_x > 500:
pos_x = 500
#draw basket
pygame.draw.rect(screen, black, (pos_x-4,pos_y-4,120,40), 0)
pygame.draw.rect(screen, red, (pos_x,pos_y,120,40), 0)
#print # of lives
print_text(font1, 0, 0, "LIVES: " + str(lives))
#print score
print_text(font1, 500, 0, "SCORE: " + str(score))
pygame.display.update()
To check if a button was pressed, you should check for an event.type : MOUSEBUTTONDOWN,and then check for the RMB.
In order to shoot, you need some sort of a list, so that there will be many bullets possible.
You can create a simple Bullet class, that will have a draw and move functions.
An example:
class Bullet:
def __init__(self,position):
self.x,self.y = position
def move(self):
self.position += 5
def draw(self,screen):
pygame.draw.circle(screen, black, x, y, 30, 0)
This covers the drawing, and movement of your bullets. Apart from this, you should check if bullets do not go off screen, and if they do, remove them from the list.
Collision can be done in many ways. Pygame has a built in method called collide_rect, which checks if 2 rectangles are overlapping. But since you have 2 circles, the method is a bit different.
Since you have 2 circles, you have a distance between them. It's given by this equation:
D = sqrt((xa-xb)^2+(ya-yb)^2))
If the distance is smaller than R1 + R2, then the circles are overlapping. You can then proceed to remove the bullet as well as the bomb.
We can simplify this to:
(R1+R2)^2 > (xa-xb)^2+(ya-yb)^2)