Related
This question already has an answer here:
Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?
(1 answer)
Closed 5 months ago.
I'm trying to create a game in pygame where you are a rectangle trying to shoot a bullet towards another rectangle, when you click a mousebutton. I'm using this with the pygame.MOUSEBUTTONDOWN, as you can see here:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and ammunition > 0:
bullets.append(Bullet(*bullet_pos))
ammunition -= 1
**I'll include more code for reference later.
However, when I click the mouse button, it only shoots a bullet every few times I click. I checked multiple times, and there doesn't seem to be a pattern of when it does/doesn't shoot. It shoots about every 4-5 times, but that's just an estimate.
Full code, for reference:
import pygame
import math
import random
import time
pygame.init()
# Setting all variables to use later \/
width, height = 798, 552
white = pygame.Color('white')
black = pygame.Color('black')
green = pygame.Color('green')
blue = pygame.Color('blue')
red = pygame.Color('red')
grey = pygame.Color('gray')
yellow = pygame.Color('yellow')
orange = pygame.Color('orange')
azure = pygame.Color('azure')
size_x = 100
size_y = 50
pos_x = 100
pos_y = 275
size_x_2 = 100
size_y_2 = 50
pos_x_2 = random.randint(0, 798)
pos_y_2 = random.randint(0, 552)
pos_x_3 = random.randint(0, 798)
pos_y_3 = random.randint(0, 552)
window = pygame.display.set_mode((width, height))
bullet_pos_y = random.randint(0, 552)
bullet_pos_x = 798
ammunition = 5
enemy_health = 1000
player_health = 50
font = pygame.font.SysFont('Times New Roman', 32)
shooting_x = 0
shooting_y = 0
# Setting All Variables to use later /\
class Bullet:
def __init__(self, x, y):
self.pos = (x, y)
self.dir = (shooting_x - x, shooting_y - y)
length = math.hypot(*self.dir)
if length == 0.0:
self.dir = (0, -1)
else:
self.dir = (self.dir[0]/length, self.dir[1]/length)
angle = math.degrees(math.atan2(-self.dir[1], self.dir[0]))
self.bullet = pygame.Surface((27.5, 17.5)).convert_alpha()
self.bullet.fill((red))
self.bullet = pygame.transform.rotate(self.bullet, angle)
self.speed = 1
def update(self):
self.pos = (self.pos[0] + self.dir[0] * self.speed, self.pos[1] + self.dir[1] * self.speed)
def draw(self, surf):
bullet_rect = self.bullet.get_rect(center = self.pos)
surf.blit(self.bullet, bullet_rect)
bullets = []
keys = pygame.key.get_pressed()
# EVERYTHING BELOW THIS IS IN THE GAME LOOP, EVERYTHING ABOVE ISN'T
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(black)
# Drawing Everything
character = pygame.draw.rect(window, white, (pos_x, pos_y, size_x, size_y))
enemy = pygame.draw.rect(window, blue, (shooting_x, shooting_y, size_x, size_y))
coin = pygame.draw.circle(window, yellow, [pos_x_2, pos_y_2], 15)
# Setting Text
enemy_health_text = font.render(str(enemy_health), True, white, blue)
enemy_health_textRect = enemy_health_text.get_rect()
enemy_health_textRect.center = (enemy.center)
player_health_text = font.render(str(player_health), True, black, white)
player_health_textRect = enemy_health_text.get_rect()
player_health_textRect.center = (character.center[0] + 9, character.center[1])
ammunition_text = font.render("ammunition remaining: " + str(ammunition), True, azure, black)
ammunition_textRect = ammunition_text.get_rect()
ammunition_textRect.center = (205, 25)
bullet_pos = character.center
enemy_pos = enemy.center
# Shooting a bullet
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and ammunition > 0:
bullets.append(Bullet(*bullet_pos))
ammunition -= 1
# Enemy Dealing Damage to Player
if enemy.colliderect(character):
player_health -= 1
white = pygame.Color('red')
if not enemy.colliderect(character):
player_health -= 0
white = pygame.Color('white')
mouse_pos_x, mouse_pos_y = pygame.mouse.get_pos()
pos_x, pos_y = pygame.mouse.get_pos()
# If Character collides with coin
if character.colliderect(coin):
pos_x_2 = random.randint(0, 798)
pos_y_2 = random.randint(100, 552)
num = random.randint(0, 20)
if num == 17:
yellow = pygame.Color('purple')
ammunition += 5
if num != 17:
yellow = pygame.Color('yellow')
ammunition += 2
elif enemy.colliderect(coin):
pos_x_2 = random.randint(0, 798)
pos_y_2 = random.randint(100, 552)
enemy_health += 3
# Setting the Enemy Movement
if shooting_x < pos_x_2:
shooting_x += 0.1
if shooting_x > pos_x_2:
shooting_x -= 0.1
if shooting_y < pos_y_2:
shooting_y += 0.1
if shooting_y > pos_y_2:
shooting_y -= 0.1
# Updating/Drawing Bullets
for bullet in bullets:
bullet.update()
''' WORK ON THIS '''
if not window.get_rect().collidepoint(bullet.pos):
bullets.remove(bullet)
for bullet in bullets:
bullet.draw(window)
# Making sure the player doesn't leave boundaries
if pos_y >= 552:
pos_y = 552
if pos_y <= 0:
pos_y = 0
if pos_x <= 0:
pos_x = 0
if pos_x >= 700:
pos_x = 700
# Drawing all text on screen
window.blit(ammunition_text, ammunition_textRect)
window.blit(enemy_health_text, enemy_health_textRect)
window.blit(player_health_text, player_health_textRect)
pygame.display.update()
The function pygame.event.get() returns an object with all events that happens. It clears all events afterwards so nothing will be executed twice when an event occurs. So you shouldn't call it twice without checking all needed events both times. Some events might get ignored when you don't call pygame.event.get() often because it has a limit of 128 events.
As a solution you can save the events in a variable (Some events might be delayed):
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
run = False
...
for event in events:
if event.type == pygame.MOUSEBUTTONDOWN and ammunition > 0:
bullets.append(Bullet(*bullet_pos))
ammunition -= 1
Or you only have one event loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.MOUSEBUTTONDOWN and ammunition > 0:
bullets.append(Bullet(*bullet_pos))
ammunition -= 1
...
I'm fairly new to python and I'm trying to build a game with Pygame. I kept having issues with collisions not being recognized. Here's the code I tried
import pygame
pygame.init()
WIDTH, HEIGHT = (900, 500)
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Bong Pong')
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BORDER = pygame.Rect(WIDTH// 2 -5, 0, 10, HEIGHT)
VEL = 3
PLAYER_HEIGHT = 50
PLAYER_WIDTH = 15
BALL_HEIGHT = 15
BALL_WIDTH = 15
def draw_window(player_1, player_2, game_ball):
WIN.fill(WHITE)
pygame.draw.rect(WIN, BLACK, BORDER)
pygame.draw.rect(WIN, BLACK, player_1)
pygame.draw.rect(WIN, BLACK, player_2)
pygame.draw.rect(WIN, RED, game_ball)
pygame.display.update()
def player_1_movement(keys_pressed, player_1):
if keys_pressed[pygame.K_w] and player_1.y - VEL > 0:
player_1.y -= VEL
if keys_pressed [pygame.K_s] and player_1.y + PLAYER_HEIGHT + VEL < 500:
player_1.y += VEL
def player_2_movement(keys_pressed, player_2):
if keys_pressed[pygame.K_UP] and player_2.y - VEL > 0:
player_2.y -= VEL
if keys_pressed [pygame.K_DOWN] and player_2.y + PLAYER_HEIGHT + VEL < 500:
player_2.y += VEL
def player_collision(player_1, player_2, game_ball, ball_vel_x):
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel_x *= -1
def main():
clock = pygame.time.Clock()
run = True
player_1 = pygame.Rect(50, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
player_2 = pygame.Rect(850, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
game_ball = pygame.Rect(50 + PLAYER_WIDTH, HEIGHT//2 - BALL_HEIGHT// 2, BALL_WIDTH, BALL_HEIGHT)
ball_vel_y = 2
ball_vel_x = 2
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.QUIT()
keys_pressed = pygame.key.get_pressed()
player_1_movement(keys_pressed, player_1)
player_2_movement(keys_pressed, player_2)
draw_window(player_1, player_2, game_ball)
if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500:
ball_vel_y *= -1
game_ball.y -= ball_vel_y
player_collision(player_1, player_2, game_ball, ball_vel_x)
game_ball.x += ball_vel_x
main()
if __name__ == '__main__':
main()
I've also tried putting the
game_ball.x += ball_vel_x
in the player_collsion function but it doesn't reverse it properly.
I've already solved the issue by putting the entire player_collision function code inside the main function like so
def main():
clock = pygame.time.Clock()
run = True
player_1 = pygame.Rect(50, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
player_2 = pygame.Rect(850, HEIGHT//2 - PLAYER_HEIGHT// 2, PLAYER_WIDTH, PLAYER_HEIGHT)
game_ball = pygame.Rect(50 + PLAYER_WIDTH, HEIGHT//2 - BALL_HEIGHT// 2, BALL_WIDTH, BALL_HEIGHT)
ball_vel_y = 2
ball_vel_x = 2
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.QUIT()
keys_pressed = pygame.key.get_pressed()
player_1_movement(keys_pressed, player_1)
player_2_movement(keys_pressed, player_2)
draw_window(player_1, player_2, game_ball)
if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500:
ball_vel_y *= -1
game_ball.y -= ball_vel_y
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel_x *= -1
game_ball.x += ball_vel_x
main()
and this works exactly how I want it I just want to clear up my understanding of why this function wouldn't work properly if just called in the main function instead of putting it directly in.
Python has no concept of in-out parameters. The argument is passed by value. If you change ball_vel_x in the player_collision function, only the parameter changes, but the argument remains unchanged. You must return the new value of ball_vel_x from the function:
def player_collision(player_1, player_2, game_ball, ball_vel_x):
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel_x *= -1
return ball_vel_x
def main():
# [...]
while run:
# [...]
ball_vel_x = player_collision(player_1, player_2, game_ball, ball_vel_x)
# [...]
Another possibility is to store the velocity in an object (e.g. gyame.math.Vector2). A variable stores a reference to an object, so you can change the object's attributes in the function if the variable is an argument of the function call:
def player_collision(player_1, player_2, game_ball, ball_vel):
if game_ball.colliderect(player_1) or game_ball.colliderect(player_2):
ball_vel.x *= -1
def main():
# [...]
ball_vel = pygame.math.Vector2(2, 2)
while run:
# [...]
if game_ball.y - BALL_HEIGHT - VEL <= 0 or game_ball.y + BALL_HEIGHT + VEL >= 500:
ball_vel.y *= -1
game_ball.y -= ball_vel.y
player_collision(player_1, player_2, game_ball, ball_vel)
game_ball.x += ball_vel.x
# DONT CHANGE THIS
import pygame, os
pygame.init()
pygame.font.init()
WIDTH, HEIGHT = 450, 250
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Spar")
# VARIABLES
HEALTH_FONT = pygame.font.SysFont('comicsans', 20)
WINNER_FONT = pygame.font.SysFont('comicsans', 50)
WINCOUNT_FONT = pygame.font.SysFont('comicsans', 20)
SPACE = pygame.transform.scale(pygame.image.load(os.path.join("Assets", "space.png")), (WIDTH, HEIGHT))
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BORDER = pygame.Rect(WIDTH//2 - 5, 0, 5, HEIGHT)
FPS = 60
VEL = 3.5
SHIP_WIDTH, SHIP_HEIGHT, = 25, 20
BULLETS_VEL = 10
MAX_BULLETS = 1
YELLOW_HIT = pygame.USEREVENT + 1
RED_HIT = pygame.USEREVENT + 2
YELLOW_SPACESHIP_IMAGE = pygame.image.load(os.path.join('Assets', "spaceship_yellow.png"))
YELLOW_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(YELLOW_SPACESHIP_IMAGE, (SHIP_HEIGHT, SHIP_WIDTH)), 90)
RED_SPACESHIP_IMAGE = pygame.image.load(os.path.join('Assets', "spaceship_red.png"))
RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(RED_SPACESHIP_IMAGE, (SHIP_WIDTH, SHIP_HEIGHT)), 270)
# PLACE ANYTHING ON THE WINDOW HERE
# +y = down from top left
# +x = right from top left
def draw_window(red, yellow, red_bullets, yellow_bullets, red_health, yellow_health, red_win_count, yellow_win_count):
WIN.blit(SPACE, (0, 0))
pygame.draw.rect(WIN, BLACK, BORDER)
red_health_text = HEALTH_FONT.render("Health: " + str(red_health), 1, WHITE)
yellow_health_text = HEALTH_FONT.render("Health: " + str(yellow_health), 1, WHITE)
WIN.blit(red_health_text, (WIDTH - red_health_text.get_width() - 10, 10))
WIN.blit(yellow_health_text, (10, 10))
yellow_win_text = WINCOUNT_FONT.render('Wins: ' + str(yellow_win_count), 1, WHITE)
red_win_text = WINCOUNT_FONT.render('Wins: ' + str(red_win_count), 1, WHITE)
WIN.blit(red_win_text, (WIDTH - red_health_text.get_width() - 70, 10))
pygame.display.update()
WIN.blit(yellow_win_text, (70, 10))
pygame.display.update()
WIN.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
WIN.blit(RED_SPACESHIP, (red.x, red.y))
for bullet in red_bullets:
pygame.draw.rect(WIN, RED, bullet)
for bullet in yellow_bullets:
pygame.draw.rect(WIN, RED, bullet)
pygame.display.update()
# MOVEMENT
def yellow_movement(keys_pressed, yellow):
if keys_pressed[pygame.K_a] and yellow.x - VEL > 0: #left
yellow.x -= VEL
if keys_pressed[pygame.K_d] and yellow.x + VEL + yellow.width < BORDER.x: #right
yellow.x += VEL
if keys_pressed[pygame.K_w] and yellow.y - VEL > 0: #up
yellow.y -= VEL
if keys_pressed[pygame.K_s] and yellow.y + VEL + yellow.height < HEIGHT: #dowm
yellow.y += VEL
def red_movement(keys_pressed, red):
if keys_pressed[pygame.K_LEFT] and red.x - VEL > BORDER.x + BORDER.width: #left
red.x -= VEL
if keys_pressed[pygame.K_RIGHT] and red.x + VEL + red.width < WIDTH: #right
red.x += VEL
if keys_pressed[pygame.K_UP] and red.y - VEL > 0: #up
red.y -= VEL
if keys_pressed[pygame.K_DOWN] and red.y + VEL + red.height < HEIGHT: #dowm
red.y += VEL
def handle_bullets(yellow_bullets, red_bullets, yellow, red):
for bullet in yellow_bullets:
bullet.x += BULLETS_VEL
if red.colliderect(bullet):
pygame.event.post(pygame.event.Event(RED_HIT))
yellow_bullets.remove(bullet)
elif bullet.x > WIDTH:
yellow_bullets.remove(bullet)
for bullet in red_bullets:
bullet.x -= BULLETS_VEL
if yellow.colliderect(bullet):
pygame.event.post(pygame.event.Event(YELLOW_HIT))
red_bullets.remove(bullet)
elif bullet.x < 0:
red_bullets.remove(bullet)
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WIN.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT/2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(1000)
# MAIN LOOP
def main():
red = pygame.Rect(350, 150,SHIP_WIDTH, SHIP_HEIGHT)
yellow = pygame.Rect(50, 150, SHIP_WIDTH, SHIP_HEIGHT)
red_bullets = []
yellow_bullets = []
red_health = 1
yellow_health = 1
red_win_count = 0
yellow_win_count = 0
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
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 len(yellow_bullets) < MAX_BULLETS:
bullet = pygame.Rect(yellow.x + yellow.width, yellow.y + yellow.height//2 - 1, 15, 4)
yellow_bullets.append(bullet)
if event.key == pygame.K_LCTRL and len(red_bullets) < MAX_BULLETS:
bullet = pygame.Rect(red.x, red.y + red.height//2 - 1, 15, 4)
red_bullets.append(bullet)
if event.type == RED_HIT:
red_health -= 1
if event.type == YELLOW_HIT:
yellow_health -= 1
winner_text = ""
if red_health <= 0:
yellow_win_count += 1
pygame.display.update()
winner_text = "Yellow is cooler"
if yellow_health <= 0:
winner_text = "Red is cooler"
red_win_count += 1
pygame.display.update()
if winner_text != "":
draw_winner(winner_text)
main()
keys_pressed = pygame.key.get_pressed()
yellow_movement(keys_pressed, yellow)
red_movement(keys_pressed, red)
handle_bullets(yellow_bullets, red_bullets, yellow, red)
draw_window(red, yellow, red_bullets, yellow_bullets, red_health, yellow_health, red_win_count, yellow_win_count)
pygame.quit()
# this is to make sure its opening the right thing blah blaho
if __name__ == "__main__":
main()
I'm trying to display a win count through a variable but the variable isn't updating on the screen, why?
I took a look at the Github version of this game and determined that what you are wanting to do is add an enhancement that shows wins on the screen. The issue at the moment is that once a spaceship wins and the program again starts "main()", the win variables get reset to "0" before the screen is redisplayed.
red_health = 1
yellow_health = 1
red_win_count = 0
yellow_win_count = 0
As a quick tweak, instead of constantly restarting the game by calling "main" at the end of the "while" block, I revised the last "if" block to just do the resetting of the player health and then continue on with the while loop function.
if winner_text != "":
draw_winner(winner_text)
red_health = 4
yellow_health = 4
continue
#main()
That then allowed for viewing the win count on the screen.
You might want to check to see if any other variables need to be reset, but you can give that a try.
So I am doing a project where I have to make a game that gives the user three lives and each time the beamrect's rectangle collides with the player's, it subtracts a life and puts them in the original position. When lives == 0: there will be a death screen displayed. But for some reason, the death screen isn't being displayed even though I made sure that every time the player rect (being zonicrect) and the beamrect collided, it would subtract 1 from the life variable.
# Your header should go here, each comment should be initialed -DK
import pygame, sys
import os
# https://youtu.be/jO6qQDNa2UY
pygame.init()
FPS = 60
# Useful Variables
# Size
size = height, width = 900, 500
zonhw = zheight, zwidth = 70, 70
scale2 = height2, width2 = 600, 300
lscale = lheight, lwidth = 80, 80
beamsz = bheight, bwidth = 50,25
platz = pheight, pwidth = 10, 70
# RGB
white = (255, 255, 255)
black = (0,0,0)
blue = (0, 0, 128)
green = (0, 255, 0)
brown = (165,42,42)
# Speed
VEL = 5
beamspeed = 3
# Position
laserpos = posx, posy = 500,250
#other
i = 0
life = 3
score = 0
# graphics
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Zonic bootleg")
font = pygame.font.Font('freesansbold.ttf', 32)
zonic = pygame.image.load(os.path.join("image","zonic.gif"))
zonic = pygame.transform.scale(zonic, zonhw)
bg = pygame.image.load(os.path.join("image","sonic-back.jpg"))
bg = pygame.transform.scale(bg, size)
gg = pygame.image.load(os.path.join("image","gg.jpg"))
gg= pygame.transform.scale(gg, size)
lazerz = pygame.image.load(os.path.join("image","Lazerz.gif"))
lazerz = pygame.transform.scale(lazerz, lscale)
beam = pygame.image.load(os.path.join("image","laserbeam.jpg"))
beam = pygame.transform.scale(beam, beamsz)
lives = pygame.image.load(os.path.join("image","health.png"))
lives = pygame.transform.scale(lives,(40,40))
# zoncz = pygame.image.load(os.path.join("image","zoncz.png"))
# zoncz = pygame.transform.scale(zoncz, scale2)
#coalitions
def collider(life,beamrect,zonicrect,lazerect):
beamrect.x -= beamspeed
if zonicrect.colliderect(beamrect):
beamrect.x = lazerect.x+21
zonicrect.x = 0
if beamrect.x <-60:
#screen.blit(beam, (posx, posy))
beamrect.x += 550
def updating(score, beamrect):
if beamrect.x == 0:
score += 1
#Death
def death():
while life <= 0:
death = font.render("Death", True, white)
screen.fill(black)
screen.blit(death,(250, 250))
# zonic movement
def KWS(keyvar, zonicrect,flip):
if keyvar[pygame.K_RIGHT]: # right
zonicrect.x += VEL
flip = False
if zonicrect.x > 500:
zonicrect.x -= VEL
if keyvar[pygame.K_LEFT] and zonicrect.x + VEL > 0: # left
zonicrect.x -= VEL
flip = True
def flipx(flip,zonicrect):
if flip:
screen.blit(pygame.transform.flip(zonic,True,False),(zonicrect.x,zonicrect.y))
if flip == False:
screen.blit(pygame.transform.flip(zonic,False,False),(zonicrect.x,zonicrect.y))
# text = font.render('Lives: {0}'.format(life), True, green, blue)
def heart(beamrect,zonicrect,lazerect):
x = 1
i = -33
while life >= x:
x +=1
i+=32
screen.blit(lives, (2+i,0))
# draw
def drawingfunc(zonicrect,lazerect, beamrect,flip, zonczrect):
#screen.blit(death,(0,0))
screen.blit(bg, (0, 0))
heart(beamrect,zonicrect,lazerect)
flipx(flip,zonicrect)
#screen.blit(zonic,(zonicrect.x, zonicrect.y))
screen.blit(beam, (beamrect.x, beamrect.y+15))
screen.blit(lazerz, (lazerect.x+21,lazerect.y))
# score = font.render('Score: ')
# screen.blit(zonic, (zonczrect.x, zonczrect.y))
sore = font.render("Score: {0}".format(score), True, black, white)
screen.blit(sore, (30, 70))
pygame.draw.rect(screen, brown, pygame.Rect(200, 200, 100, 50))
pygame.display.update()
# mainloop and refresh rate
def main():
jump = False
jumpCount = 0
jumpMax = 15
flip = False
zonicrect = pygame.Rect(10, 250, zheight, zwidth)
lazerect = pygame.Rect(posx, posy, lheight, lwidth)
beamrect = pygame.Rect(posx, posy, bheight, bwidth)
zonczrect = pygame.Rect(50, 25, height2, width2)
# (30,0,32,32)
# livesrect = pygame.Rect(0,0,10,10)
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if not jump and event.key == pygame.K_SPACE:
jump = True
jumpCount = jumpMax
death()
collider(life,beamrect,zonicrect,lazerect)
keyspressed = pygame.key.get_pressed()
KWS(keyspressed, zonicrect,flip)
updating(score, beamrect)
drawingfunc(zonicrect,lazerect, beamrect,flip, zonczrect)
flipx(flip, zonicrect)
if jump:
zonicrect.y -= jumpCount
if jumpCount > -jumpMax:
jumpCount -= 1
else:
jump = False
pygame.quit()
# calling function NOTE: needs to always be at the end of file
if __name__ == "__main__":
main()
Solution
In your death function, you forgot to call pygame.display.update() at the bottom of your loop. That's why you cannot see the death screen even when life is less than or equal to zero. Also, you need to add an event loop in your death function, so that the window will keep responding to events while the loop is running.
So change this:
def death():
while life <= 0:
death = font.render("Death", True, white)
screen.fill(black)
screen.blit(death, (250, 250))
To this:
def death():
while life <= 0:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
death = font.render("Death", True, white)
screen.fill(black)
screen.blit(death, (250, 250))
pygame.display.update()
Full Modified Code
# Your header should go here, each comment should be initialed -DK
import pygame, sys
import os
# https://youtu.be/jO6qQDNa2UY
pygame.init()
FPS = 60
# Useful Variables
# Size
size = height, width = 900, 500
zonhw = zheight, zwidth = 70, 70
scale2 = height2, width2 = 600, 300
lscale = lheight, lwidth = 80, 80
beamsz = bheight, bwidth = 50, 25
platz = pheight, pwidth = 10, 70
# RGB
white = (255, 255, 255)
black = (0, 0, 0)
blue = (0, 0, 128)
green = (0, 255, 0)
brown = (165, 42, 42)
# Speed
VEL = 5
beamspeed = 3
# Position
laserpos = posx, posy = 500, 250
# other
i = 0
life = 3
score = 0
# graphics
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Zonic bootleg")
font = pygame.font.Font('freesansbold.ttf', 32)
zonic = pygame.image.load(os.path.join("image", "zonic.gif"))
zonic = pygame.transform.scale(zonic, zonhw)
bg = pygame.image.load(os.path.join("image", "sonic-back.jpg"))
bg = pygame.transform.scale(bg, size)
gg = pygame.image.load(os.path.join("image", "gg.jpg"))
gg = pygame.transform.scale(gg, size)
lazerz = pygame.image.load(os.path.join("image", "Lazerz.gif"))
lazerz = pygame.transform.scale(lazerz, lscale)
beam = pygame.image.load(os.path.join("image", "laserbeam.jpg"))
beam = pygame.transform.scale(beam, beamsz)
lives = pygame.image.load(os.path.join("image", "health.png"))
lives = pygame.transform.scale(lives, (40, 40))
# zoncz = pygame.image.load(os.path.join("image","zoncz.png"))
# zoncz = pygame.transform.scale(zoncz, scale2)
# coalitions
def collider(life, beamrect, zonicrect, lazerect):
beamrect.x -= beamspeed
if zonicrect.colliderect(beamrect):
beamrect.x = lazerect.x + 21
zonicrect.x = 0
if beamrect.x < -60:
# screen.blit(beam, (posx, posy))
beamrect.x += 550
def updating(score, beamrect):
if beamrect.x == 0:
score += 1
# Death
def death():
while life <= 0:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
death = font.render("Death", True, white)
screen.fill(black)
screen.blit(death, (250, 250))
pygame.display.update()
# zonic movement
def KWS(keyvar, zonicrect, flip):
if keyvar[pygame.K_RIGHT]: # right
zonicrect.x += VEL
flip = False
if zonicrect.x > 500:
zonicrect.x -= VEL
if keyvar[pygame.K_LEFT] and zonicrect.x + VEL > 0: # left
zonicrect.x -= VEL
flip = True
def flipx(flip, zonicrect):
if flip:
screen.blit(pygame.transform.flip(zonic, True, False), (zonicrect.x, zonicrect.y))
if flip == False:
screen.blit(pygame.transform.flip(zonic, False, False), (zonicrect.x, zonicrect.y))
# text = font.render('Lives: {0}'.format(life), True, green, blue)
def heart(beamrect, zonicrect, lazerect):
x = 1
i = -33
while life >= x:
x += 1
i += 32
screen.blit(lives, (2 + i, 0))
# draw
def drawingfunc(zonicrect, lazerect, beamrect, flip, zonczrect):
# screen.blit(death,(0,0))
screen.blit(bg, (0, 0))
heart(beamrect, zonicrect, lazerect)
flipx(flip, zonicrect)
# screen.blit(zonic,(zonicrect.x, zonicrect.y))
screen.blit(beam, (beamrect.x, beamrect.y + 15))
screen.blit(lazerz, (lazerect.x + 21, lazerect.y))
# score = font.render('Score: ')
# screen.blit(zonic, (zonczrect.x, zonczrect.y))
sore = font.render("Score: {0}".format(score), True, black, white)
screen.blit(sore, (30, 70))
pygame.draw.rect(screen, brown, pygame.Rect(200, 200, 100, 50))
pygame.display.update()
# mainloop and refresh rate
def main():
jump = False
jumpCount = 0
jumpMax = 15
flip = False
zonicrect = pygame.Rect(10, 250, zheight, zwidth)
lazerect = pygame.Rect(posx, posy, lheight, lwidth)
beamrect = pygame.Rect(posx, posy, bheight, bwidth)
zonczrect = pygame.Rect(50, 25, height2, width2)
# (30,0,32,32)
# livesrect = pygame.Rect(0,0,10,10)
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if not jump and event.key == pygame.K_SPACE:
jump = True
jumpCount = jumpMax
death()
collider(life, beamrect, zonicrect, lazerect)
keyspressed = pygame.key.get_pressed()
KWS(keyspressed, zonicrect, flip)
updating(score, beamrect)
drawingfunc(zonicrect, lazerect, beamrect, flip, zonczrect)
flipx(flip, zonicrect)
if jump:
zonicrect.y -= jumpCount
if jumpCount > -jumpMax:
jumpCount -= 1
else:
jump = False
pygame.quit()
sys.exit(0)
# calling function NOTE: needs to always be at the end of file
if __name__ == "__main__":
main()
im fairly new to coding and python, i was messing around with pygame and i was wondering if theres a way i could limit the amount of circles that spawn in this game im making? when i run the code, it just spawns in circles all over the place really fast. i tried doing the time.sleep thing, but all it does is slow down the entire game.
import pygame
import random
import time
pygame.init()
y = 0
x = 0
point = 0
is_blue = True
WHITE = (255, 255, 255)
clock = pygame.time.Clock()
screen = pygame.display.set_mode([500, 500])
def food():
pygame.draw.circle(screen, WHITE, (random.randint(1, 400), random.randint(1, 400)), 5)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
is_blue = not is_blue
pygame.display.set_caption("Collect the balls to win!")
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
y -= 3
if pressed[pygame.K_DOWN]:
y += 3
if pressed[pygame.K_LEFT]:
x -= 3
if pressed[pygame.K_RIGHT]:
x += 3
if x <= -1:
x = 0
if x >= 441:
x = 440
if y <= -1:
y = 0
if y >= 441:
y = 440
screen.fill((0, 0, 0))
if is_blue:
color = (0, 128, 255)
else:
color = (255, 100, 0)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 30, 30))
food()
pygame.display.flip()
clock.tick(144)
You have to use a list. Create a list for the food positions:
food_list = []
Fill the list in a loop:
while len(food_list) < 10:
food_list.append((random.randint(1, 400), random.randint(1, 400)))
Draw the foods in the list in a loop:
for food_pos in food_list:
pygame.draw.circle(screen, WHITE, food_pos, 5)
You can also spawn the food with an time interval. Use pygame.time.get_ticks() to measure the time. Define a time interval after which a new object should appear. Create an object when the point in time is reached and calculate the point in time for the next object:
food_list = []
time_interval = 1000 # 1000 milliseconds == 1 seconds
next_food_time = pygame.time.get_ticks()
done = False
while not done:
# [...]
current_time = pygame.time.get_ticks()
if current_time > next_food_time and len(food_list) < 10:
next_food_time += time_interval
food_list.append((random.randint(1, 400), random.randint(1, 400)))
See also Spawning multiple instances of the same object concurrently in python
Complete example:
import pygame
import random
import time
pygame.init()
y = 0
x = 0
point = 0
is_blue = True
WHITE = (255, 255, 255)
clock = pygame.time.Clock()
screen = pygame.display.set_mode([500, 500])
food_list = []
time_interval = 1000 # 1000 milliseconds == 1 seconds
next_food_time = pygame.time.get_ticks()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
is_blue = not is_blue
pygame.display.set_caption("Collect the balls to win!")
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
y -= 3
if pressed[pygame.K_DOWN]:
y += 3
if pressed[pygame.K_LEFT]:
x -= 3
if pressed[pygame.K_RIGHT]:
x += 3
if x <= -1:
x = 0
if x >= 441:
x = 440
if y <= -1:
y = 0
if y >= 441:
y = 440
current_time = pygame.time.get_ticks()
if current_time > next_food_time and len(food_list) < 10:
next_food_time += time_interval
food_list.append((random.randint(1, 400), random.randint(1, 400)))
screen.fill((0, 0, 0))
if is_blue:
color = (0, 128, 255)
else:
color = (255, 100, 0)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 30, 30))
for food_pos in food_list:
pygame.draw.circle(screen, WHITE, food_pos, 5)
pygame.display.flip()
clock.tick(144)