what i am trying to achieve
I am attempting to get the enemy to do a set of movements with a picture swap that are timed and in a ordered sequence that repeats.
the timing is not doing milliseconds?
what is happening
After a long time the enemy does first movement then long pause images some times swap sometimes not.
I am not getting any exceptions or errors when I run it.
Also when I add the userevent into the game loop above the keydown events I break the player movement.
Github to images and full code
Below is the most successful of the things I tried so far
I created the desired numbered USEREVENT in ordered sequence
# Create a bunch of AI events
ai_uppercut_event = pygame.USEREVENT + 1
ai_l_punch_event = pygame.USEREVENT + 2
ai_r_punch_event = pygame.USEREVENT + 3
ai_r_dodge_event = pygame.USEREVENT + 4
ai_l_dodge_event = pygame.USEREVENT + 5
Gave the enemy ai character a start position
enemy_x = 235
enemy_y = 145
gave the enemy ai a movement amount
aimovex = 40
aimovey = 40
defined the images to swap out for the different moves
# Define ai images for different moves
enemy_default = pygame.image.load("enemy_default.png")
ai_uppercut_image = pygame.image.load("enemy_uppercut.png")
ai_l_punch_image = pygame.image.load("enemy_left.png")
ai_r_punch_image = pygame.image.load("enemy_right.png")
ai_r_dodge_image = pygame.image.load("enemy_dodge_right.png")
ai_l_dodge_image = pygame.image.load("enemy_dodge_left.png")
set up the clock and tick and timer for events
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
start_time = pygame.time.get_ticks()
# set timer for the ai movement events
pygame.time.set_timer(ai_uppercut_event, MOVE_UPPERCUT)
pygame.time.set_timer(ai_l_punch_event, MOVE_PUNCH_LEFT)
pygame.time.set_timer(ai_r_punch_event, MOVE_PUNCH_RIGHT)
pygame.time.set_timer(ai_r_dodge_event, MOVE_DODGE_RIGHT)
pygame.time.set_timer(ai_l_dodge_event, MOVE_DODGE_LEFT)
in the main event loop
# -------- Main Program Loop -----------
paused = False
running = True
while running:
# --- Main Event Loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for event in pygame.event.get():
if event.type == ai_uppercut_event:
aimovex =+ 80
activeEnemyImage = ai_uppercut_image
elif event.type == ai_l_punch_event:
aimovex =+ 80
activeEnemyImagee = ai_l_punch_image
elif event.type == ai_r_punch_event:
aimovex =- 80
activeEnemyImage = ai_r_punch_image
elif event.type == ai_r_dodge_event:
aimovey =+ 80
activeEnemyImage = ai_r_dodge_image
elif event.type == ai_l_dodge_event:
aimovey =- 80
activeEnemyImage = ai_l_dodge_image
enemy_x += aimovex
enemy_y += aimovey
#elif event.type == reloaded_event:
# when the reload timer runs out, reset it
#reloaded = True
#pygame.time.set_timer(reloaded_event, 0)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
if event.key == pygame.K_SPACE:
paused = not paused
# --- Event Processing ---
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
movex =- 40
activeCharacterImage = player_left
elif event.key == pygame.K_RIGHT:
movex =+ 40
activeCharacterImage = player_right
I suspect your issue has to do with your doubled event polling loops:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for event in pygame.event.get():
if event.type == ai_uppercut_event:
# ...
Because there are two loops, you'll often have your events lost to the first loop which only checks if they're QUIT events and ignores all other kinds of events.
To fix this, combine the two loops and use an elif for the first non-QUIT event check:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == ai_uppercut_event:
# ...
Related
I ran into a bug with my timer. When I pause my game I noticed that my timer doesn't pause a long with the game. Example: if I pause the game when the timer is at 26 seconds remaining, and unpause the game about ten seconds later, the timer will say 16 seconds left instead of counting down from 26 like I want it to. If I pause the game for 30 seconds the timer still runs down to 0 instead of the timer pausing along with the game. How can I fix this?
code where my game runs:
#game runs here
run = True
paused = False
while run:
for event in pygame.event.get():
if event.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'GAME OVER!'
if event.type == pygame.QUIT:
run = False
#pause game
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = not paused
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
if paused:
continue
#draw street
screen.blit(bg, [0, 0])
#draw timer
screen.blit(timer_font.render(text, True, (0,0,0)), (800, 10))
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
player.collision(debris_group)
player.stats()
#update all sprites
all_sprites.update()
all_sprites.draw(screen)
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
The timer event can be stopped by passing 0 to the time argument of pygame.time.set_timer.
Stop and restart the timer event when you toggle the pause state:
run = True
paused = False
while run:
for event in pygame.event.get():
if event.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'GAME OVER!'
if event.type == pygame.QUIT:
run = False
#pause game
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = not paused
if pause:
pygame.time.set_timer(pygame.USEREVENT, 0) # stop timer
else:
pygame.time.set_timer(pygame.USEREVENT, 1000) # 1 second interval
# [...]
This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
How can I make a sprite move when key is held down
(6 answers)
Closed 1 year ago.
I am a newbie to pygame so when I type the below code in, it shows that there is no such thing as a 'type' attribute for the event object. Can you please tell me what's the error.
# Importing libraries and other stuff
import pygame
from pygame.locals import *
# defining the funtion for drawing the block
def draw_block():
surface.fill((232,127,7))
surface.blit(block,(block_x,block_y))
pygame.display.flip()
if __name__ == "__main__":
pygame.init()
surface = pygame.display.set_mode((500,500))
surface.fill((232,127,7))
block = pygame.image.load("block_better_3.jpg").convert()
block_x = 100
block_y = 100
surface.blit(block,(block_x,block_y))
pygame.display.flip()
# Making the window run until user input
running = True
while running:
for event in pygame.event.get():
if event.type == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
elif event.key == K_UP:
block_y -= 10
elif event.key == K_DOWN:
block_y += 10
elif event.key == K_LEFT:
block_x -= 10
elif event.key == K_RIGHT:
block_x +=10
If you want to know when a key is pressed, you need to verify that the event type (event.type) is KEYDOWN and the key attribute of the event object (event.key) is the specific key (K_ESCAPE, K_UP, ...):
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_UP:
block_y -= 10
elif event.key == K_DOWN:
block_y += 10
elif event.key == K_LEFT:
block_x -= 10
elif event.key == K_RIGHT:
block_x += 10
See also pygame.event module and pygame.key module.
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.
If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
keys = pygame.key.get_pressed()
if keys[K_UP]:
block_y -= 1
if keys[K_DOWN]:
block_y += 1
if keys[K_LEFT]:
block_x -= 1
if keys[K_RIGHT]:
block_x += 1
Further more you need to redraw the scene in every frame:
# Importing libraries and other stuff
import pygame
from pygame.locals import *
# defining the funtion for drawing the block
def draw_block():
surface.fill((232, 127, 7))
surface.blit(block,(block_x, block_y))
pygame.display.flip()
if __name__ == "__main__":
pygame.init()
surface = pygame.display.set_mode((500,500))
clock = pygame.time.Clock()
block = pygame.image.load("block_better_3.jpg").convert()
block_x = 100
block_y = 100
# application loop
running = True
while running:
# limit the frames per second
clock.tick(100)
# handle the events
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
# update the game states and positions of objects
keys = pygame.key.get_pressed()
block_x += (keys[K_RIGHT] - keys[K_LEFT]) * 2
block_y += (keys[K_DOWN] - keys[K_UP]) * 2
# clear the display; draw the scene; update the display
draw_block()
pygame.quit()
The typical PyGame application loop has to:
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
I want to close the game after was pressed the esc button. how can I do? And where should I place it?
I also found some problems that I can't solve, so if you solve them for me I would be happy
This is the code:
#Import Libraries
import pygame
import random
#PyGame Initialization
pygame.init()
#Images Variables
background = pygame.image.load('images/sfondo.png')
bird = pygame.image.load('images/uccello.png')
base = pygame.image.load('images/base.png')
gameover = pygame.image.load('images/gameover.png')
tube1 = pygame.image.load('images/tubo.png')
tube2 = pygame.transform.flip(tube1, False, True)
#Display Create
display = pygame.display.set_mode((288,512))
FPS = 60
#Define Functions
def draw_object():
display.blit(background, (0,0))
display.blit(bird, (birdx, birdy))
def display_update():
pygame.display.update()
pygame.time.Clock().tick(FPS)
def animations():
global birdx, birdy, bird_vely
birdx, birdy = 60, 150
bird_vely = 0
#Move Control
animations()
while True:
bird_vely += 1
birdy += bird_vely
for event in pygame.event.get():
if ( event.type == pygame.KEYDOWN
and event.key == pygame.K_UP):
bird_vely = -10
if event.type == pygame.QUIT:
pygame.quit()
draw_object()
display_update()
Well you do so by implementing below code snippet in your code:
running = True
while running:
# other code
event = pygame.event.wait ()
if event.type == pygame.QUIT:
running = False # Be interpreter friendly
pygame.quit()
Make sure that you call pygame.quit() before you exit your main function
You can also reference this thread
Pygame escape key to exit
You must terminate the application loop when the QUIT event occurs. You have implmented the QUIT event, but you don't terminate the loop. Add a variabel run = True and set run = False when the event occurs.
To terminate the game when ESC is pressed you have to implement the KEYDOWN event. Set run = False when the KEDOWN event occurs and event.key == pgame.K_ESC:
run = True
while run:
bird_vely += 1
birdy += bird_vely
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pgame.K_ESC:
run = False
elif event.key == pygame.K_UP:
bird_vely = -10
draw_object()
display_update()
pygame.quit()
exit()
In my game the player can shoot different coloured bullets using the WASD keys. The player can shoot bullets as fast as they can press the keys right now, which means you can mash the WASD keys and shoot a stream of bullets. I've tried creating a USEREVENT to make a cooldown for when the player can shoot, but I'm not entirely sure if I'm doing this right because the player doesn't shoot at all when I run the game.
#cooldown userevent
shot_cool = pygame.USEREVENT + 2
pygame.time.set_timer(shot_cool, 10)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False #breaks out of the while loop
if event.type == pygame.KEYDOWN and event.type == shot_cool:
if event.key == pygame.K_w:
pygame.time.set_timer(shot_cool, 10)
player.shoot('red')
elif event.key == pygame.K_a:
pygame.time.set_timer(shot_cool, 10)
player.shoot('green')
elif event.key == pygame.K_s:
pygame.time.set_timer(shot_cool, 10)
player.shoot('white')
elif event.key == pygame.K_d:
pygame.time.set_timer(shot_cool, 10)
player.shoot('blue')
Is there any way I can make it so the player has a short cooldown until he can fire another bullet?
As I said in my comment, you fixed your problem perfectly. But since I already had it in my editor I decided I'd share a little more. Since all the keys function the same way, you can handle them in the same function block, using a dictionary. It could end up looking like this:
#cooldown userevent
EVT_SHOT_COOLDOWN = pygame.USEREVENT + 2
# shot cool down time
COOLDOWN_TIME_MS = 100
SHOT_KEYS = {
pygame.K_w:'red',
pygame.K_a:'green',
pygame.K_s:'white',
pygame.K_d:'blue',
}
running = True
shot_delay = False
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False #breaks out of the while loop
elif event_type == shot_cool:
shot_delay = False
elif event.type == pygame.KEYDOWN:
# handle shooting keys
if (event.key in SHOT_KEYS and not shot_delay):
pygame.time.set_timer(shot_cool, COOLDOWN_TIME_MS)
shot_delay = True
player.shoot(SHOT_KEYS[event.key])
# handle other keys (if any)
Thanks to the comment from RufusVS, what you said has worked perfectly. This is the working code:
shoot_cooldown = pygame.USEREVENT +2
pygame.time.set_timer(shoot_cooldown, 100)
shot_delay = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == shoot_cooldown:
shot_delay = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w and shot_delay == False:
pygame.time.set_timer(shoot_cooldown, 100)
shot_delay = True
player.shoot('red')
elif event.key == pygame.K_a and shot_delay == False:
pygame.time.set_timer(shoot_cooldown, 100)
shot_delay = True
player.shoot('green')
elif event.key == pygame.K_s and shot_delay == False:
pygame.time.set_timer(shoot_cooldown, 100)
shot_delay = True
player.shoot('white')
elif event.key == pygame.K_d and shot_delay == False:
pygame.time.set_timer(shoot_cooldown, 100)
shot_delay = True
player.shoot('blue')
I am working on a game called HypoPixel using ray casting, and I found yet another bug. I can not get the game to open, it just crashes, and when I use it in IDE it does not give an error.
I just used the simple
elif event.type == pygame.MOUSEBUTTONDOWN:
procedure, but it keeps crashing ever since I added this
pygame.init()
Screen = "None"
Sobj = "None"
Width = 800
Height = 600
Time = 0
MouseX, MouseY = pygame.mouse.get_pos()
Frame = pygame.display.set_mode((Width,Height))
pygame.display.set_caption("HypoPixel")
FPS = pygame.time.Clock()
def button(DisplayText,ButtonPosition,Function):
pass
def mapX(MapXPos):
pass
def mapY(MapYPos):
pass
def mapZ(MapZPos):
pass
def ReDisplayItem():
if Sobj == "None":
Raycast('Assets/Textures/Extra/ItemBox.png',0,0,160,160)
elif Sobj == "Loom":
Raycast('Assets/Textures/Extra/IBO.png',0,0,160,160)
Raycast('Assets/Textures/Blocks/loom_side.png',10,10,140,140)
def Raycast(TTR, RayXPos, RayYPos, RaySizeX, RaySizeY):
RaycastThis = pygame.image.load(TTR)
RaycastThis = pygame.transform.scale(RaycastThis,(RaySizeX,RaySizeY))
Frame.blit(RaycastThis, (RayXPos, RayYPos))
Loop = True
Raycast('Assets/Textures/Screens/Skybox/Earth.png',0,0,800,600)
Raycast('Assets/Textures/Extra/ItemBox.png',0,0,160,160)
while Loop == True:
Time = Time + 1
while Sobj == "None":
RCT = 'Assets/Textures/Blocks/air.png'
while Sobj == "Loom":
RCT = 'Assets/Textures/Blocks/loom_side.png'
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
Raycast(RCT,MouseX,MouseY,160,160)
elif event.type == pygame.KEYDOWN:
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
exit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_0:
Raycast('Assets/Textures/Extra/ItemBox.png',0,0,160,160)
Sobj = "None"
elif event.type == pygame.KEYDOWN and event.key == pygame.K_1:
Raycast('Assets/Textures/Blocks/loom_side.png',10,10,140,140)
Sobj = "Loom"
if Time >= 2400 and Time < 4800:
Raycast('Assets/Textures/Screens/Skybox/EarthNight.png',0,0,800,600)
ReDisplayItem()
elif Time >= 4800:
Time = 0
Raycast('Assets/Textures/Screens/Skybox/Earth.png',0,0,800,600)
ReDisplayItem()
pygame.display.update()
FPS.tick(60)
I expected the application to open like normal and with the new added ability of painting blocks for a Alpha Test of my game, but it crashed, with no sign of an error.
NeverMind, I realized that I had to use
if
and
elif
instead of while loops, sorry for the clutter Stack OverFlow Community. :(