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.]
Related
I'm making a pygame game where a person can purchase bombs from a shop. The player can also drop as many bombs as he buys. I need a way to make each bomb disappear after 3 seconds of it being dropped. In the following code I am just able to drop the bombs however I have tried various methods and failed.
import pygame
import random
pygame.font.init()
width = 900
height = 600
screen = pygame.display.set_mode([width, height])
walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'),
pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
char = pygame.image.load('standing.png')
bomb_pic = pygame.transform.scale(pygame.image.load('bomb.png'), (20,20))
bomb_explosion = pygame.transform.scale(pygame.image.load('explosion1.png'), (40,40))
# char_rect = char.get_rect()
enemy_Left = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'),
pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'),
pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png')]
x = 50
y = 50
width = 40
height = 60
vel = 5
isJump = False
jumpCount = 10
left = False
right = False
down = False
up = False
walkCount = 0
enemy_vel = 2
enemy_list = []
shop = pygame.transform.scale(pygame.image.load("shop.png"), (60, 60))
clock = pygame.time.Clock()
FPS = 60
font = pygame.font.Font('freesansbold.ttf', 32)
items_font = pygame.font.Font('freesansbold.ttf', 16)
bombs =[]
bag = {'bomb': 0}
print(bag["bomb"])
class Button():
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def draw(self, win, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.SysFont('comicsans', 20)
text = font.render(self.text, 1, (0, 0, 0))
win.blit(text, (
self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))
def shop_run():
shop_bomb = Button((0, 200, 0), 820, 150, 60, 20, text="Bomb_b")
bright_green = (0, 255, 0)
green = (0, 200, 0)
shop_bomb.draw(screen)
def redrawGameWindow():
global walkCount
global font
global bag
global items_font
global enemy_list
screen.fill([166, 166, 166])
for five_enemies in range(6):
random_enemy_location_y = random.randrange(100, 400)
random_enemy_location_x = random.randrange(800, 840)
enemy_list.append([random_enemy_location_x, random_enemy_location_y])
for enemies in range(6):
screen.blit(enemy_Left[enemies], enemy_list[enemies])
enemy_list[enemies][0] -= 0.3
pygame.draw.rect(screen, (0, 0, 0), (800, 0, 100, 600))
if x + char.get_width() < 60 and y + char.get_height() < 60:
shop_run()
screen.blit(shop, (0, 0))
screen.blit(font.render("Menu", True, (255,255,255)),(805, 10))
screen.blit(items_font.render("Bombs: "+ str(bag["bomb"]), True, (255, 255, 255)), (805, 550))
# screen.blit(bomb_explosion, (450, 300))
if walkCount + 1 >= 27:
walkCount = 0
if left:
screen.blit(walkLeft[walkCount // 3], (x, y))
walkCount += 1
elif right:
screen.blit(walkRight[walkCount // 3], (x, y))
walkCount += 1
elif down:
screen.blit(char, (x, y))
walkcount = 0
elif up:
screen.blit(char, (x, y))
walkcount = 0
else:
screen.blit(char, (x, y))
walkCount = 0
for pos in bombs:
screen.blit(bomb_pic, pos)
pygame.display.update()
def main():
run = True
# shopper()
pygame.display.set_caption("bomb-mania")
global x
global y
global width
global height
global vel
global isJump
global jumpCount
global left
global right
global down
global up
global walkCount
global bomb_pic
global font
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if x + char.get_width() < 60 and y + char.get_height() < 60:
buy = pygame.key.get_pressed()
if buy[pygame.K_b]:
bag["bomb"] += 1
print(bag["bomb"])
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and bag["bomb"] >= 1:
bombs.append(((x + (char.get_width()/2)),( y + (char.get_height() - 20))))
bag["bomb"] -= 1
redrawGameWindow()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel - 15:
x -= vel
left = True
right = False
down = False
up = False
elif keys[pygame.K_RIGHT] and x < 800 - vel - width:
x += vel
left = False
right = True
down = False
up = False
elif keys[pygame.K_DOWN] and y < 600 - height:
y += vel
left = False
right = False
down = True
up = False
elif keys[pygame.K_UP] and y > vel - 15:
y -= vel
left = False
right = False
down = False
up = True
else:
left = False
right = False
down = False
up = False
walkCount = 0
clock.tick(FPS)
pygame.display.flip()
main()
Use pygame.time.get_ticks() to get the current time in milliseconds. Compute the time when the bomb has to disappear.
Store the time to the list bombs. The list bombs has to contain a tuple of position and time.
If the time is elapsed, then remove the bomb from the list:
def redrawGameWindow():
current_time = pygame.time.get_ticks()
# [...]
for i in reversed(range(len(bombs))):
pos, end_time = bombs[i]
if current_time > end_time
bombs.pop(i)
else:
screen.blit(bomb_pic, pos)
def main():
# [...]
while run:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# [...]
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and bag["bomb"] >= 1:
pos = x + char.get_width()/2, y + char.get_height() - 20
end_time = current_time + 3000 # 3000 milliseconds = 3 seconds
bombs.append((pos, end_time))
bag["bomb"] -= 1
redrawGameWindow()
I am working on creating a donkey kong like game in which I will have Mario try to reach the top platform. To do this, I need Mario to have the ability to jump and fall with gravity.
I have been working on implementing gravity, but when I tried something that I thought would work, the gravity element worked, but the player avatar began to glitch erratically. I believe this is because he is moving up and down several times per second. Any help as to how resolve this issue, and get my gravity mechanism functioning would be greatly appreciated.
Here is my code so far:
from pygame.locals import *
import itertools
global moves
pygame.init()
screen_height = 800
screen_width = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Donkey Kong')
FPS = 30
player = pygame.image.load('mario.bmp') #facing right
player_rect = player.get_rect()
player_rect.center = (80, 700)
move_rate = 3
move_left = False
move_right = False
move_up = False
move_down = False
touch_ladder = True
ladder_move_up = False
ladder_move_down = False
gravity = 4
gravity_check = True
jump = False
jump_moves = 0
platform = pygame.image.load('platform.bmp')
platforms = []
platform_x = [60,120,180,240,300,360,420,480]
platform_y = [120,240,360,480,600,720]
ladders = []
ladder_x = [300, 480, 240, 300, 180, 420, 240, 120, 60, 420, 300, 480]
ladder_y = []
class Platform():
def __init__(self, y, x, x_index, y_index):
self.platform = platform
self.rect = self.platform.get_rect()
self.x_index = x_index
self.y_index = y_index
if (self.y_index % 2) != 0 :
self.rect.y = y + (2 * self.x_index)
else:
self.rect.y = y - (2 * self.x_index)
self.rect.x = x
def draw_platform(self):
if (self.rect.y % 240) != 0:
screen.blit(self.platform, (self.rect.x, self.rect.y )) #up
else:
screen.blit(self.platform, (self.rect.x, self.rect.y)) #down
class Ladder():
def __init__(self, y, x, y_index, x_index):
self.y_index = y_index
self.x_index = x_index
if (y % 240) != 0:
self.height = abs(((platform_y[self.y_index - 1] + (2 *(2 * self.x_index)))) - y)
self.rect = pygame.Rect(x, y - self.height, 20, self.height)
self.rect.y -= (2 * self.x_index)
else:
self.height = abs(((platform_y[self.y_index - 1] - (2 * (2 * self.x_index)))) - y)
self.rect = pygame.Rect(x, y - self.height, 20, self.height)
self.rect.y += (2 * self.x_index)
self.rungs = 0
def draw_ladder(self):
#pygame.draw.rect(screen, (255,0,0), self.rect)
pygame.draw.rect(screen, (255, 255, 255), (self.rect.x, self.rect.y , 4, self.height))
pygame.draw.rect(screen, (255, 255, 255), (self.rect.x + 16, self.rect.y, 4, self.height))
def draw_rungs(self):
pygame.draw.line(screen, (255, 255, 255), (self.rect.x, self.rect.y+self.rungs),(self.rect.x + 19, self.rect.y+self.rungs), 4)
self.rungs += 14
y_multiplied = platform_y.copy()
y_multiplied.extend(platform_y)
y_multiplied.sort()
print(y_multiplied)
print(ladder_x)
for y in platform_y:
if platform_y.index(y) < 6:
for x in platform_x:
platforms.append(Platform(y, x, platform_x.index(x), platform_y.index(y)))
for y, x in zip(y_multiplied, ladder_x):
ladders.append(Ladder(y, x, platform_y.index(y), platform_x.index(x)))
while True:
gravity_check = True
screen.fill((105, 105, 255))
screen.blit(player, player_rect)
for p in platforms:
p.draw_platform()
if player_rect.colliderect(p.rect):
player_rect.bottom = p.rect.top
gravity_check = False
for l in ladders:
if player_rect.colliderect(l.rect):
touch_ladder = True
gravity_check = False
if gravity_check == True:
player_rect.y += gravity
for l in ladders:
if l.y_index > 0:
l.draw_ladder()
for i in range(l.height // 14):
l.draw_rungs()
l.rungs = 0
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.quit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
player = pygame.transform.flip(player, True, False)
move_left = True
if event.key == K_RIGHT:
move_right = True
player = pygame.image.load('mario.bmp')
if event.key == K_UP:
jump = True
if event.key == K_DOWN:
player_rect.y += move_rate
if event.type == KEYUP:
if event.key == K_LEFT:
move_left = False
if event.key == K_RIGHT:
move_right = False
if move_left == True:
player_rect.x -= move_rate
if move_right == True:
player_rect.x += move_rate
if ladder_move_up == True:
player_rect.y -= move_rate
if jump == True:
gravity_check = True
if jump_moves <= 60:
player_rect.y -= 10
jump_moves += 10
else:
jump_moves = 0
jump = False
pygame.display.update()
pygame.time.Clock().tick(FPS)```
This line causes problems:
if gravity_check == True:
player_rect.y += gravity
If you put print():
if gravity_check == True:
print(player_rect.y)
player_rect.y += gravity
print(player_rect.y)
You'll see that player_rect.y constantly changes between 56 and 60 (for my random image) at the start. So you need to prevent change of the player_rect.y on more than one place simultaneously to avoid this behaviour. Also as I mentioned in the comment try to avoid loading images inside of the loop because it will consume much resources.
EDIT:
for p in platforms:
p.draw_platform()
if player_rect.colliderect(p.rect):
player_rect.bottom = p.rect.top + gravity
gravity_check = False
player_rect.bottom = p.rect.top + gravity adding gravity value will solve the problem. And this is the line of code that was causing changes to player_rect.y as well as one mentioned in the original post. Hope this solves your problem.
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()
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)