I am currently making a game where you run around as a bear, collect fish, and get points. However, when the bear runs into the fish, it does not pick it up as the bear has run into the fish.
I have tried having the function running in some of the loops where the fish has been made and even making it a function but it does not seem to work.
global screen, grasspic, bearImg, fishpic, screen_width, screen_height, score_number, bearRect
import random
import pygame
import sys
import time
import math
pygame.init()
screen_width = 640
screen_height = 480
sw2 = screen_width/2
sh2 = screen_height/2
bearImg = pygame.image.load('bear.png')
bearImg = pygame.transform.scale(bearImg, (150,150))
green = (24, 255, 0)
bearImg_width = 150
def text_objects(text, font):
textSurface = font.render(text, True, (0,0,0))
return textSurface, textSurface.get_rect()
def message_display(text):
clocktxt = pygame.font.Font('freesans.ttf', 20)
TextSurf, TextRect = text_objects(text, clocktxt)
TextRect.center = (55, 15)
screen.blit(TextSurf, TextRect)
pygame.display.update()
white = (255, 255, 255)
black = (0,0,0)
#NOTE: DOWNLOAD FISH, BEAR, AND GRASS PICTURES|| IT WILL NOT WORK WITHOUT IT
grasspic = []
for i in range(1, 5):
grasspic.append(pygame.image.load('grass%s.png' % i))
fishpic = []
for i in range(1, 3):
fishpic.append(pygame.image.load('fish%s.png' % i))
fishpic[0] = pygame.transform.scale(fishpic[0], (50,50))
fishpic[1] = pygame.transform.scale(fishpic[1], (50,50))
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption('Hungry Boi')
clock = pygame.time.Clock()
camerax = 0
cameray = 0
def getRandomOffCameraPos(camerax, cameray, objWidth, objHeight):
cameraRect = pygame.Rect(camerax, cameray, screen_width, screen_height)
while True:
x = random.randint(camerax - screen_width, camerax + (2*screen_width))
y = random.randint(cameray - screen_height, cameray + (2*screen_height))
objRect = pygame.Rect(x, y, objWidth, objHeight)
if not objRect.colliderect(cameraRect):
return x, y
def makeNewGrass(camerax, cameray):
gr = {}
gr['grassImage'] = random.randint(0, len(grasspic) - 1)
gr['width'] = 80
gr['height'] = 80
gr['x'], gr['y'] = getRandomOffCameraPos(camerax, cameray, gr['width'], gr['height'])
gr['rect'] = pygame.Rect((gr['x'], gr['y'], gr['width'], gr['height']))
return gr
def makeNewFish(camerax, cameray):
fi = {}
fi['fishImage'] = random.randint(0, len(fishpic) - 1)
fi['width'] = 150
fi['height'] = 150
fi['x'], fi['y'] = getRandomOffCameraPos(camerax, cameray, fi['width'], fi['height'])
fi['rect'] = pygame.Rect((fi['x'], fi['y'], fi['width'], fi['height']))
return fi
def bear(x,y):
screen.blit(bearImg,(x,y))
allgrass = []
def makegrass():
for i in range(15):
allgrass.append(makeNewGrass(camerax, cameray))
allgrass[i]['x'] = random.randint(0, screen_width)
allgrass[i]['y'] = random.randint(0, screen_height)
makegrass()
allfish = []
def makefish():
for i in range(2):
allfish.append(makeNewFish(camerax, cameray))
allfish[i]['x'] = random.randint(0, screen_width)
allfish[i]['y'] = random.randint(0, screen_height)
makefish()
def game_loop():
x = (screen_width * 0.4)
y = (screen_height * 0.4)
STARTINGX = (screen_width * 0.4)
STARTINGY = (screen_height * 0.4)
x_change = 0
y_change = 0
vel = 5
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change -= vel
STARTINGX -= vel
elif event.key == pygame.K_RIGHT:
x_change += vel
STARTINGX += vel
elif event.key == pygame.K_UP:
y_change -= vel
STARTINGY -= vel
elif event.key == pygame.K_DOWN:
y_change += vel
STARTINGY += vel
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
#print (event) #see events, basically a console, makes a mess
x += x_change
y += y_change
screen.fill(green)
bearRect = pygame.Rect((STARTINGX, STARTINGY, STARTINGX+150, STARTINGY+150))
for grass in allgrass:
gRect = pygame.Rect((grass['x'] - camerax,
grass['y'] - cameray,
grass['width'],
grass['height']))
screen.blit(grasspic[grass['grassImage']], gRect)
for fish in allfish:
fRect = pygame.Rect((fish['x'] - camerax,
fish['y'] - cameray,
fish['width'],
fish['height']))
screen.blit(fishpic[fish['fishImage']], fRect)
bear(x,y)
score_count()
if bearRect.colliderect(fRect):
makefish()
makegrass()
pygame.display.update()
clock.tick(30) #fps//may not be safe to run really fast
def score_count():
score_number = 0
message_display("Score is: " + str(score_number))
game_loop()
pygame.quit()
quit
Instead of getting a collision and have both the grass and fish images randomize on the screen again, the code will ignore the entire collision. Is there a way to fix it and have it know where the bear and the fish is correctly?
Thank you
Now it works correctly but I made so many changes that it is hard to describe it.
Code did't remove fishes and did't change score so it was hard to say if it checked collision. Now it removes fish (and add new in new place) and change score.
Code keeps position and size in Rect and use only one Rect for every item. I old code Bear had two rect - one to check collision and one to blit it.
In some functions I change names to show that they are very similar and it could be one function.
Every object has image and rect. When you read documentation for pygame.sprite.Sprite then you see that it also uses image and rect.
import random
import pygame
import sys
import time
import math
# --- constants --- (UPPER_CASE_NAMES)
GREEN = (24, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0,0,0)
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
SW2 = SCREEN_WIDTH/2
SH2 = SCREEN_HEIGHT/2
# --- functions ---
def text_objects(text, font):
surface = font.render(text, True, BLACK)
return surface, surface.get_rect()
def message_display(text):
surface, rect = text_objects(text, CLOCKTXT)
rect.center = (55, 15)
screen.blit(surface, rect)
#pygame.display.update() # use update() olny in one place
def getRandomOffCameraPos(camerax, cameray, objWidth, objHeight):
camera_rect = pygame.Rect(camerax, cameray, SCREEN_WIDTH, SCREEN_HEIGHT)
x1 = camerax - SCREEN_WIDTH
x2 = camerax + (2*SCREEN_WIDTH)
y1 = cameray - SCREEN_HEIGHT
y2 = cameray + (2*SCREEN_HEIGHT)
while True:
x = random.randint(x1, x2)
y = random.randint(y1, y2)
obj_rect = pygame.Rect(x, y, objWidth, objHeight)
if not obj_rect.colliderect(camera_rect):
return x, y
def makeNewGrass(camerax, cameray):
w, h = 80, 80
x, y = getRandomOffCameraPos(camerax, cameray, w, h)
images = grasspic
item = {
'image': random.choice(images),
'rect': pygame.Rect(x, y, w, h),
}
return item
def makeNewFish(camerax, cameray):
w, h = 50, 50
x, y = getRandomOffCameraPos(camerax, cameray, w, h)
images = fishpic
item = {
'image': random.choice(images),
'rect': pygame.Rect(x, y, w, h),
}
return item
def makegrass(number=15):
for i in range(number):
item = makeNewGrass(camerax, cameray)
item['rect'].x = random.randint(0, SCREEN_WIDTH-item['rect'].width)
item['rect'].y = random.randint(0, SCREEN_HEIGHT-item['rect'].height)
allgrass.append(item)
def makefish(number=2):
for i in range(number):
item = makeNewFish(camerax, cameray)
item['rect'].x = random.randint(0, SCREEN_WIDTH-item['rect'].width)
item['rect'].y = random.randint(0, SCREEN_HEIGHT-item['rect'].height)
allfish.append(item)
def score_draw(score):
message_display("Score is: " + str(score))
#--- main ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Hungry Boi')
CLOCKTXT = pygame.font.Font('freesans.ttf', 20)
# ---
bear_img = pygame.image.load('bear.png').convert()
bear_img = pygame.transform.scale(bear_img, (150, 150)).convert()
bear_rect = bear_img.get_rect()
bear_rect.x = SCREEN_WIDTH * 0.4
bear_rect.y = SCREEN_HEIGHT * 0.4
bear_vel = 5
grasspic = []
for i in range(1, 5):
image = pygame.image.load('grass%s.png' % i).convert()
grasspic.append(image)
fishpic = []
for i in range(1, 3):
image = pygame.image.load('fish%s.png' % i).convert()
image = pygame.transform.scale(image, (50, 50)).convert()
fishpic.append(image)
# ---
allgrass = []
makegrass()
allfish = []
makefish()
x_change = 0
y_change = 0
camerax = 0
cameray = 0
score = 0
# --- mainloop ---
gameExit = False
clock = pygame.time.Clock()
while not gameExit:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change -= bear_vel
elif event.key == pygame.K_RIGHT:
x_change += bear_vel
elif event.key == pygame.K_UP:
y_change -= bear_vel
elif event.key == pygame.K_DOWN:
y_change += bear_vel
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change += bear_vel
elif event.key == pygame.K_RIGHT:
x_change -= bear_vel
elif event.key == pygame.K_UP:
y_change += bear_vel
elif event.key == pygame.K_DOWN:
y_change -= bear_vel
# --- updates ---
bear_rect.x += x_change
bear_rect.y += y_change
keep_fish = []
for fish in allfish:
if not bear_rect.colliderect(fish['rect']):
keep_fish.append(fish)
else:
makefish(1)
#makegrass()
score += 1
allfish = keep_fish
# --- draws ---
screen.fill(GREEN)
for grass in allgrass:
screen.blit(grass['image'], grass['rect'].move(camerax, cameray))
for fish in allfish:
screen.blit(fish['image'], fish['rect'].move(camerax, cameray))
screen.blit(bear_img, bear_rect.move(camerax, cameray))
score_draw(score)
pygame.display.update()
# --- FPS ---
clock.tick(30) #fps//may not be safe to run really fast
# --- end ---
pygame.quit()
Related
I've been set a challenge to make a game using pygame ( I am making snake so it should be easy... but I've never used pygame) so using a more efficient language isn't an option.So my question is that I updating the snake grid is too slow and I'm not experienced enough in pygame to fix this, can anyone who is help.Also as a note if I only fill the grid it doesn't clear behind the Snake.
Using python 3.8
import pygame
import time
import random
pygame.init()
display_width = 800
display_height = 600
display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Snake")
pureblue = (0,0,255)
purered = (255,0,0)
puregreen = (0,255,0)
white = (255,255,255)
black = (1,1,1)
grey = (50,50,50)
darkgrey = (25,25,25)
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 30
font_style = pygame.font.SysFont(None, 50)
def drawGrid():
blockSize = 10
for x in range(display_width):
for y in range(display_height):
rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
pygame.draw.rect(display, darkgrey, rect, 1)
def message(msg, colour):
text = font_style.render(msg, True, colour)
display.blit(text, [display_width/2, display_height/2])
def SnakeGameLoop():
game_over = False
X = display_width/2
Y = display_height/2
X_change = 0
Y_change = 0
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
X_change = -10
Y_change = 0
elif event.key == pygame.K_RIGHT:
X_change = 10
Y_change = 0
elif event.key == pygame.K_UP:
X_change = 0
Y_change = -10
elif event.key == pygame.K_DOWN:
X_change = 0
Y_change = 10
if X >= display_width or X < 0 or Y >= display_height or Y < 0:
game_over = True
X += X_change
Y += Y_change
display.fill(grey)
drawGrid()
pygame.draw.rect(display,puregreen,[X,Y,10,10])
pygame.display.update()
clock.tick(15)
message("You lost", purered)
pygame.display.update()
time.sleep(2)
pygame.quit()
quit()
SnakeGameLoop()
To improve the game's performance, draw the grid on a pygame.Surface object with the size of the screen, before the application loop:
def drawGrid(surf):
surf.fill(grey)
blockSize = 10
for x in range(display_width):
for y in range(display_height):
rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
pygame.draw.rect(surf, darkgrey, rect, 1)
grid_surf = pygame.Surface(display.get_size())
drawGrid(grid_surf)
blit the surface once per frame on the display instead of drawing the grid once per frame, in the application loop:
def SnakeGameLoop():
# [...]
while not game_over:
# [...]
display.blit(grid_surf, (0, 0))
pygame.draw.rect(display,puregreen,[X,Y,10,10])
pygame.display.update()
I am trying to get an enemy, called fudd_img, to follow the player who is playing as bear_img. fudd_img should be slower than the player themselves.
I have tried using the lines:
if bear_rect_x > fudd_rect_x:
fudd_rect_x = fudd_rect_x + max(2, bear_rectx - fudd_rect_x)
elif bear_rect_x < fudd_rect_x:
fudd_rect_x = fudd_rect_x - max(2, fudd_rect_x - bear_rect_x)
but instead, fudd_img will act exactly as bear_img instead of finding a path to the bear_img. Whenever I try to translate this to y, it doesn't work and fudd_img will not move along the y axis.
import random
import pygame
import sys
import time
import math
# --- constants --- (UPPER_CASE_NAMES)
GREEN = (24, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0,0,0)
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
SW2 = SCREEN_WIDTH/2
SH2 = SCREEN_HEIGHT/2
#---
camerax = 0
cameray = 0
# --- functions ---
def text_objects(text, font):
surface = font.render(text, True, BLACK)
return surface, surface.get_rect()
def message_display(text):
surface, rect = text_objects(text, CLOCKTXT)
rect.center = (58, 15)
screen.blit(surface, rect)
#pygame.display.update() # use update() only in one place
#generate random pos for fish and grass
def getRandomOffCameraPos(camerax, cameray, objWidth, objHeight):
camera_rect = pygame.Rect(camerax, cameray, SCREEN_WIDTH, SCREEN_HEIGHT)
x1 = camerax - SCREEN_WIDTH
x2 = camerax + (2*SCREEN_WIDTH)
y1 = cameray - SCREEN_HEIGHT
y2 = cameray + (2*SCREEN_HEIGHT)
while True:
x = random.randint(x1, x2)
y = random.randint(y1, y2)
obj_rect = pygame.Rect(x, y, objWidth, objHeight)
if not obj_rect.colliderect(camera_rect):
return x, y
def makeNewGrass(camerax, cameray):
w, h = 80, 80
x, y = getRandomOffCameraPos(camerax, cameray, w, h)
images = grasspic
item = {
'image': random.choice(images),
'rect': pygame.Rect(x, y, w, h),
}
return item
def makeNewFish(camerax, cameray):
w, h = 50, 50
x, y = getRandomOffCameraPos(camerax, cameray, w, h)
images = fishpic
item = {
'image': random.choice(images),
'rect': pygame.Rect(x, y, w, h),
}
return item
def makegrass(number=15):
for i in range(number):
item = makeNewGrass(camerax, cameray)
item['rect'].x = random.randint(0, SCREEN_WIDTH-item['rect'].width)
item['rect'].y = random.randint(0, SCREEN_HEIGHT-item['rect'].height)
allgrass.append(item)
def makefish(number=2):
for i in range(number):
item = makeNewFish(camerax, cameray)
item['rect'].x = random.randint(0, SCREEN_WIDTH-item['rect'].width)
item['rect'].y = random.randint(0, SCREEN_HEIGHT-item['rect'].height)
allfish.append(item)
def score_draw(score):
message_display("Score is: " + str(score))
#--- main ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Hungry Boi')
CLOCKTXT = pygame.font.Font('freesans.ttf', 20)
# ---
bear_img = pygame.image.load('bear.png')
bear_img = pygame.transform.scale(bear_img, (150, 150))
bear_rect = bear_img.get_rect()
bear_rect.x = SCREEN_WIDTH * 0.4
bear_rect.y = SCREEN_HEIGHT * 0.4
bear_vel = 5
fudd_img = pygame.image.load('fudd.png')
fudd_img = pygame.transform.scale(fudd_img, (150,150))
fudd_rect = fudd_img.get_rect()
fudd_rect.x = SCREEN_WIDTH * 0.4
fudd_rect.y = SCREEN_HEIGHT * 0.4
fudd_vel = 2
grasspic = []
for i in range(1, 5):
image = pygame.image.load('grass%s.png' % i)
grasspic.append(image)
fishpic = []
for i in range(1, 3):
image = pygame.image.load('fish%s.png' % i)
image = pygame.transform.scale(image, (50, 50))
fishpic.append(image)
# ---
allgrass = []
makegrass()
allfish = []
makefish()
x_change = 0
y_change = 0
score = 0
time = 60
# --- mainloop ---
gameExit = False
clock = pygame.time.Clock()
while not gameExit:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change -= bear_vel
elif event.key == pygame.K_RIGHT:
x_change += bear_vel
elif event.key == pygame.K_UP:
y_change -= bear_vel
elif event.key == pygame.K_DOWN:
y_change += bear_vel
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change += bear_vel
elif event.key == pygame.K_RIGHT:
x_change -= bear_vel
elif event.key == pygame.K_UP:
y_change += bear_vel
elif event.key == pygame.K_DOWN:
y_change -= bear_vel
# --- updates ---
bear_rect.x += x_change
bear_rect.y += y_change
keep_fish = []
for fish in allfish:
if not bear_rect.colliderect(fish['rect']):
keep_fish.append(fish)
else:
makefish(1)
#makegrass()
score += 1
allfish = keep_fish
# --- time down ---
for i in range(60):
time -= 1
# --- draws ---
screen.fill(GREEN)
for grass in allgrass:
screen.blit(grass['image'], grass['rect'].move(camerax, cameray))
for fish in allfish:
screen.blit(fish['image'], fish['rect'].move(camerax, cameray))
screen.blit(bear_img, bear_rect.move(camerax, cameray))
screen.blit(fudd_img, fudd_rect.move(camerax, cameray))
score_draw(score)
pygame.display.update()
# --- FPS ---
clock.tick(30) #fps//may not be safe to run really fast
# --- end ---
pygame.quit()
How do I get fudd_img to follow the player, bear_img but not layer on top of the player and spawn on the top left corner of the game? I am hoping that later, this will make it easier for a collision system to work.
Thank you
If it has to follow in a straight line without any obstacles then you can use pygame.math.Vector2D to make all calculations. It has all needed functions to make it simpler and it uses float values so move can be smoother.
First I convert positions from pygame.Rect to pygame.math.Vector2D
player_vector = pygame.math.Vector2(player_rect.center)
enemy_vector = pygame.math.Vector2(enemy_rect.center)
next I calculate difference between both objects (it still gives vector)
diff = player_vector - enemy_vector
If I add it to enemy's position then it gets player's position - enemy would get player in one step but I need shorter vector with the same direction to move enemy slower - to move it in more steps.
If I normalize vector then I get vector with the same direction but shorter. It's length is 1.
move = diff.normalize()
Now I can add it to enemy's position to make small step in player's direction.
enemy_vector += move
And now I can use new position to convert back to position in pygame.Rect
enemy_rect.center = enemy_vector
and draw on screen
pygame.draw.rect(screen, GREEN, player_rect)
pygame.draw.rect(screen, RED, enemy_rect)
If I want to faster move then I can multiplicate normalized vector
move = diff.normalize() * 2
player_vector = pygame.math.Vector2(player_rect.center)
enemy_vector = pygame.math.Vector2(enemy_rect.center)
diff = player_vector - enemy_vector
move = diff.normalize() * 2
enemy_vector += move
enemy_rect.center = enemy_vector
pygame.draw.rect(screen, GREEN, player_rect)
pygame.draw.rect(screen, RED, enemy_rect)
To make move smoother I will keep enemy's position in Vector (as float values) and convert to pygame.Rect only to draw it.
Full working example. Player is in center, enemy starts in random position and move to player. It displays also line between objects. You can move player using arrows.
import pygame
import random
# --- constants --- (UPPER_CASE_NAMES)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 600
SCREEN_WIDTH_HALF = SCREEN_WIDTH//2
SCREEN_HEIGHT_HALF = SCREEN_HEIGHT//2
#--- main ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
player_rect = pygame.Rect(0, 0, 16, 16)
player_rect.center = (SCREEN_WIDTH_HALF, SCREEN_HEIGHT_HALF)
player_speed = 2
enemy_rect = pygame.Rect(0, 0, 16, 16)
enemy_rect.centerx = random.randint(0, SCREEN_WIDTH)
enemy_rect.centery = random.randint(0, SCREEN_HEIGHT)
enemy_speed = 2
enemy_vector = pygame.math.Vector2(enemy_rect.center)
#old_rect = enemy_rect.copy()
clock = pygame.time.Clock()
run = True
while run:
clock.tick(15) # 120 FPS
#pygame.time.delay(5)
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# --- changes ---
keys = pygame.key.get_pressed()
# move player
if player_rect.top > 0 and keys[pygame.K_UP]:
player_rect.y -= player_speed
if player_rect.bottom < SCREEN_HEIGHT and keys[pygame.K_DOWN]:
player_rect.y += player_speed
if player_rect.left > 0 and keys[pygame.K_LEFT]:
player_rect.x -= player_speed
if player_rect.right < SCREEN_WIDTH and keys[pygame.K_RIGHT]:
player_rect.x += player_speed
# enemy follow player
player_vector = pygame.math.Vector2(player_rect.center)
diff = player_vector - enemy_vector
if diff.length() > 0.1:
move = diff.normalize() * enemy_speed
enemy_vector += move
enemy_rect.center = enemy_vector
# -- draws ---
screen.fill(BLACK)
pygame.draw.line(screen, WHITE, player_rect.center, enemy_rect.center)
pygame.draw.rect(screen, GREEN, player_rect)
pygame.draw.rect(screen, RED, enemy_rect)
#pygame.draw.rect(screen, WHITE, old_rect)
pygame.display.flip()
# --- end ---
pygame.quit()
my quit button is working in my pygame but only partly. it works once i have just run the game, but after i have been killed in game and the game_loop is reset, the quit button just resets the game loop when i press it and doesn't close the window. it's like it has changed it's function to the same as the function of when the player get's killed if that makes sense.
i am just going to show you my whole games code to make it easier. (btw my game is being changed currently so some things might be in the wrong place and stuff just don't worry about it).
import pygame
import time
import random
pygame.init()
pygame.font.init()
dis_width = 500
dis_height = 500
game_exit = False
hit = False
FPS = 150
record = 0
game_display = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('RACRZ')
clock = pygame.time.Clock()
#COLOURS
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0 ,0)
green = (0, 255, 0)
blue = (0, 0, 255)
sky_blue = (0, 136, 239)
#VEHICLE
bg = pygame.image.load('c:\\users\\riley\\pictures\\Saved Pictures\\spaceImg_bg.png')
carImg = pygame.image.load('c:\\users\\riley\\pictures\\Saved Pictures\\space invader1.png')
car_width = 32
car_height = 33
vel = 3
#projectile
enemyImg = pygame.image.load('c:\\users\\riley\\pictures\\saved pictures\\projectile1.png')
explosionImg = pygame.image.load('c:\\users\\riley\\pictures\\saved pictures\\explosion 1.png')
def car(x, y):
game_display.blit(carImg, (x, y))
def enemy(enemyx, enemyy):
game_display.blit(enemyImg, (enemyx, enemyy))
def enemy2(enemyx, enemyy):
game_display.blit(enemyImg, (enemyx, enemyy))
def enemy3(enemyx, enemyy):
game_display.blit(enemyImg, (enemyx, enemyy))
def enemy4(enemyx, enemyy):
game_display.blit(enemyImg, (enemyx, enemyy))
def enemy5(enemyx, enemyy):
game_display.blit(enemyImg, (enemyx, enemyy))
def enemy6(enemyx, enemyy):
game_display.blit(enemyImg, (enemyx, enemyy))
def explode(x, y):
game_display.blit(explosionImg, (x, y))
#TEXT
def textobjects(text, font):
textsurface = font.render(text, True, green)
return textsurface, textsurface.get_rect()
#RESTART MESSAGE
def message_display(text, colour, locationX, locationY):
largeText = pygame.font.Font('freesansbold.ttf', 50)
text = largeText.render('HIT', True, (colour))
game_display.blit(text, (locationX, locationY))
pygame.display.update()
time.sleep(2)
game_loop()
def collision(ex, ey, ew, eh, x, y, w, h):
if x > ex and x < ex + ew or x + w > ex and x + w < ex + ew:
if y > ey and y < ey + eh or y + h > ey and y + h < ey + eh:
print ('HIT')
hit = True
game_loop()
def score(rounds):
font = pygame.font.SysFont(None, 35)
text = font.render(f'ROUND {rounds}', True, green)
game_display.blit(text, (0,0))
#GAME LOOP
def game_loop():
#beggining car location
x = dis_width * 0.45
y = dis_height * 0.8
#movement variables
x_change = 0
y_change = 0
loop_count = 0
enemy_startx = random.uniform(0, dis_width)
enemy_starty = -1000
enemy2_startx = -1000
enemy2_starty = random.uniform(0, dis_height)
enemy3_startx = random.uniform(0, dis_width)
enemy3_starty = -24
enemy4_startx = random.uniform(0, dis_width)
enemy4_starty = 500
#goes from top side diagonaly to bottom left
enemy5_startx = random.uniform(0, dis_width)
enemy5_starty = -24
#goes from bottom side diagonaly to top right
enemy6_startx = random.uniform(0, dis_width)
enemy6_starty = 500
enemy_speed = 3
enemy_width = 24
enemy_height = 24
#game has not been quit
game_exit = False
#while the game is running this will happen
while not game_exit:
#quit button
for event in pygame.event.get():
#assingning keys to movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change -= vel
elif event.key == pygame.K_RIGHT:
x_change += vel
elif event.key == pygame.K_DOWN:
y_change += vel
elif event.key == pygame.K_UP:
y_change -= vel
elif event.type == pygame.K_ESCAPE:
print ('escape')
game_exit = True
if event.type == pygame.QUIT:
game_exit = True
#stops vehicle from moving after key press
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
#moves vehicle
y += y_change
x += x_change
#display colour
game_display.blit(bg, (0,0))
#spawns objects
if loop_count >= 10:
enemy3_startx += enemy_speed
enemy3_starty += enemy_speed
enemy3(enemy3_startx, enemy3_starty)
if loop_count >= 15:
enemy4_startx -= enemy_speed
enemy4_starty -= enemy_speed
enemy4(enemy4_startx, enemy4_starty)
if loop_count >= 20:
enemy5_startx -= enemy_speed
enemy5_starty += enemy_speed
enemy5(enemy5_startx, enemy5_starty)
if loop_count >= 25:
enemy6_startx += enemy_speed
enemy6_starty -= enemy_speed
enemy6(enemy6_startx, enemy6_starty)
car(x,y)
enemy(enemy_startx, enemy_starty)
enemy2(enemy2_startx, enemy2_starty)
score(loop_count)
enemy2_startx += enemy_speed
enemy_starty += enemy_speed
if hit == True:
game_loop = 0
#MAKES DISPLAY BOUNDARIES
#car boundaries
if x > dis_width - car_width:
x = 0
elif x < 0:
x = dis_width - car_width
elif y > dis_height - car_height:
y = 0
elif y < 0:
y = dis_height - car_height
#boundaries for enemy1
if enemy_starty > dis_height:
enemy_starty = 0 - enemy_height
enemy_startx = random.uniform(0, dis_width - enemy_width)
#loop_count will count the number of times enemy1 passes through the screen
loop_count = loop_count + 1
print(loop_count)
# ex, ey, ew, eh, x, y, w, h
collision(enemy_startx, enemy_starty, enemy_width, enemy_height, x, y, car_width, car_height)
collision(enemy2_startx, enemy2_starty, enemy_width, enemy_height, x, y, car_width, car_height)
collision(enemy3_startx, enemy3_starty, enemy_width, enemy_height, x, y, car_width, car_height)
collision(enemy4_startx, enemy4_starty, enemy_width, enemy_height, x, y, car_width, car_height)
collision(enemy5_startx, enemy5_starty, enemy_width, enemy_height, x, y, car_width, car_height)
collision(enemy6_startx, enemy6_starty, enemy_width, enemy_height, x, y, car_width, car_height)
#boundaries for enemy2
if enemy2_startx > dis_width:
enemy2_startx = 0 - enemy_width
enemy2_starty = random.uniform(0, dis_height - enemy_height)
#enemy3 boundaries
if enemy3_startx > dis_width:
enemy3_startx = random.uniform(0, dis_width)
enemy3_starty = -24
#enemy4 boundaries
if enemy4_startx < 0 - enemy_width:
enemy4_startx = random.uniform(0, dis_width)
enemy4_starty = 500
#enemy5 boundaries
if enemy5_startx < 0 - enemy_width:
enemy5_startx = random.uniform(0, dis_width)
enemy5_starty = -24
#enemy6 boundaries
if enemy6_startx > dis_width:
enemy6_startx = random.uniform(0, dis_width)
enemy6_starty = 500
#record checker/ set
global record
roundnum = loop_count
if roundnum > record:
record = roundnum
#updates screen after movements
pygame.display.update()
#FPS
clock.tick(FPS)
#loops through code
if game_exit == True:
pygame.quit()
game_loop()
print (f'your record is {record}')
it would mean allot you could find the error in my code.
if you find any other issues please let me know thanks.
The bit of code here is quite wrong. Try this in a while True: loop:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
[The pygame.display.update bit is in a different place so delete it where it was and copy and past this in isntead.]
I am making a game in which the player has to use a bowl to catch falling items. I have some images of items in a list and an image of a bowl that is used to catch the items. The items keep on falling and reset to the top of the screen if they reach the boundary (bottom edge). I got this logic done which allows the items to fall but I do not know how to detect when there is a collision between the bowl and item.
My code:
import math
import pygame
import random
pygame.init()
display_width = 800
display_height = 600
game_display = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
pygame.display.set_caption("Catch the Ball")
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 255, 0)
player_img = pygame.image.load("Images/soup.png")
thing_imgs = [pygame.image.load('Images/muffin.png'), pygame.image.load('Images/dessert.png'),
pygame.image.load('Images/cheese.png'), pygame.image.load('Images/fruit.png')]
def player(x, y):
game_display.blit(player_img, (x, y))
def things(x, y, img):
game_display.blit(img, (x, y))
def game_loop():
running = True
x = display_width * 0.45
y = display_height * 0.8
x_change = 0
player_width = 64
player_height = 64
things_cor = [[random.randint(0, display_width), 32]]
things_added = [random.choice(thing_imgs)]
thing_height = 32
thing_width = 32
y_change = 5
caught = 0
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
game_display.fill(white)
player(x, y)
x += x_change
for i in range(len(things_cor)):
thing_x, thing_y = things_cor[i]
things(thing_x, thing_y, things_added[i])
for i in range(len(things_cor)):
things_cor[i][1] += y_change
if things_cor[i][1] > display_height:
things_cor[i][1] = random.randint(-2000, -1000)
things_cor[i][0] = random.randint(0, display_width)
things_added[i] = random.choice(thing_imgs)
things_added.append(random.choice(thing_imgs))
if len(things_added) < 6:
things_cor.append(
[random.randint(0, display_width), -10])
if x < 0:
x = 0
elif x > display_width - player_width:
x = display_width - player_width
clock.tick(60)
pygame.display.update()
game_loop()
Use pygame.Rect objects and colliderect() to detect the collision between the bounding rectangles of 2 objects or 2 images:
rect1 = pygame.Rect(x1, y1, w1, h1)
rect2 = pygame.Rect(x2, y2, w2, h2)
if rect1.colliderect(rect2):
# [...]
If you have to images (pygame.Surface objects), the bounding rectangle of can be get by get_rect(), where the location of the Surface has to be set by an keyword argument, since the returned rectangle always starts at (0, 0):
(see Why is my collision test not working and why is the position of the rectangle of the image always wrong (0, 0)?)
def game_loop():
# [...]
while running:
# [...]
player_rect = player_img.get_rect(topleft = (x, y))
for i in range(len(things_cor)):
thing_rect = things_added[i].get_rect(topleft = things_cor[i])
if player_rect.colliderect(thing_rect):
print("hit")
player(x, y)
x += x_change
for i in range(len(things_cor)):
thing_x, thing_y = things_cor[i]
things(thing_x, thing_y, things_added[i])
Use pygame.time.get_ticks() to delay the start of the game for a certain time. pygame.time.get_ticks() return the number of milliseconds since pygame.init() was called. For instance:
def game_loop():
# [...]
while running:
passed_time = pygame.time.get_ticks() # passed time in milliseconds
start_time = 100 * 1000 # start time in milliseconds (100 seconds)
# [...]
# move player
if passed_time >= start_time:
x += x_change
if x < 0:
x = 0
elif x > display_width - player_width:
x = display_width - player_width
# move things
if passed_time >= start_time:
for i in range(len(things_cor)):
things_cor[i][1] += y_change
if things_cor[i][1] > display_height:
things_cor[i][1] = random.randint(-2000, -1000)
things_cor[i][0] = random.randint(0, display_width)
things_added[i] = random.choice(thing_imgs)
things_added.append(random.choice(thing_imgs))
if len(things_added) < 6:
things_cor.append(
[random.randint(0, display_width), -10])
# draw scene and update dispaly
game_display.fill(white)
player(x, y)
for i in range(len(things_cor)):
thing_x, thing_y = things_cor[i]
things(thing_x, thing_y, things_added[i])
pygame.display.update()
clock.tick(60)
I am making a game in which the player has to use a bowl to catch falling items. I have some images of items in a list and an image of a bowl that is used to catch the items. The items keep on falling and reset to the top of the screen if they reach the boundary (bottom edge). I got this logic done which allows the items to fall but I do not know how to detect when there is a collision between the bowl and item.
My code:
import math
import pygame
import random
pygame.init()
display_width = 800
display_height = 600
game_display = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
pygame.display.set_caption("Catch the Ball")
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 255, 0)
player_img = pygame.image.load("Images/soup.png")
thing_imgs = [pygame.image.load('Images/muffin.png'), pygame.image.load('Images/dessert.png'),
pygame.image.load('Images/cheese.png'), pygame.image.load('Images/fruit.png')]
def player(x, y):
game_display.blit(player_img, (x, y))
def things(x, y, img):
game_display.blit(img, (x, y))
def game_loop():
running = True
x = display_width * 0.45
y = display_height * 0.8
x_change = 0
player_width = 64
player_height = 64
things_cor = [[random.randint(0, display_width), 32]]
things_added = [random.choice(thing_imgs)]
thing_height = 32
thing_width = 32
y_change = 5
caught = 0
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
game_display.fill(white)
player(x, y)
x += x_change
for i in range(len(things_cor)):
thing_x, thing_y = things_cor[i]
things(thing_x, thing_y, things_added[i])
for i in range(len(things_cor)):
things_cor[i][1] += y_change
if things_cor[i][1] > display_height:
things_cor[i][1] = random.randint(-2000, -1000)
things_cor[i][0] = random.randint(0, display_width)
things_added[i] = random.choice(thing_imgs)
things_added.append(random.choice(thing_imgs))
if len(things_added) < 6:
things_cor.append(
[random.randint(0, display_width), -10])
if x < 0:
x = 0
elif x > display_width - player_width:
x = display_width - player_width
clock.tick(60)
pygame.display.update()
game_loop()
Use pygame.Rect objects and colliderect() to detect the collision between the bounding rectangles of 2 objects or 2 images:
rect1 = pygame.Rect(x1, y1, w1, h1)
rect2 = pygame.Rect(x2, y2, w2, h2)
if rect1.colliderect(rect2):
# [...]
If you have to images (pygame.Surface objects), the bounding rectangle of can be get by get_rect(), where the location of the Surface has to be set by an keyword argument, since the returned rectangle always starts at (0, 0):
(see Why is my collision test not working and why is the position of the rectangle of the image always wrong (0, 0)?)
def game_loop():
# [...]
while running:
# [...]
player_rect = player_img.get_rect(topleft = (x, y))
for i in range(len(things_cor)):
thing_rect = things_added[i].get_rect(topleft = things_cor[i])
if player_rect.colliderect(thing_rect):
print("hit")
player(x, y)
x += x_change
for i in range(len(things_cor)):
thing_x, thing_y = things_cor[i]
things(thing_x, thing_y, things_added[i])
Use pygame.time.get_ticks() to delay the start of the game for a certain time. pygame.time.get_ticks() return the number of milliseconds since pygame.init() was called. For instance:
def game_loop():
# [...]
while running:
passed_time = pygame.time.get_ticks() # passed time in milliseconds
start_time = 100 * 1000 # start time in milliseconds (100 seconds)
# [...]
# move player
if passed_time >= start_time:
x += x_change
if x < 0:
x = 0
elif x > display_width - player_width:
x = display_width - player_width
# move things
if passed_time >= start_time:
for i in range(len(things_cor)):
things_cor[i][1] += y_change
if things_cor[i][1] > display_height:
things_cor[i][1] = random.randint(-2000, -1000)
things_cor[i][0] = random.randint(0, display_width)
things_added[i] = random.choice(thing_imgs)
things_added.append(random.choice(thing_imgs))
if len(things_added) < 6:
things_cor.append(
[random.randint(0, display_width), -10])
# draw scene and update dispaly
game_display.fill(white)
player(x, y)
for i in range(len(things_cor)):
thing_x, thing_y = things_cor[i]
things(thing_x, thing_y, things_added[i])
pygame.display.update()
clock.tick(60)