Displaying images for only a specific period of time in pygame - python

So I just came to know about pygame and thought it would be cool to use it to make a simple space invaders game.So in my code https://pastebin.com/eksFCbYr I want the image "bullet.png" to be displayed on the screen only during the duration of the spacebar being pressed.But it doesnt seem to work.
I first thought that it may be because the image is being drawn below another image.So I changed the positions of the images concerned such that they dont overlap.But that seems to have had no effect,indicating that is not the problem.
Could someone identify what mistake i have made in my code.Also please tell me if there are any better ways to do this.
Thanks`
m = 2
bull = pygame.image.load("bullet.png")
t=True
while t:
screen.fill((50, 50, 50))
for event in pygame.event.get():
if event.type == pygame.QUIT:
t = False
#keydown statement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
n = 1
if event.key == pygame.K_LEFT:
p = -1
if event.key == pygame.K_SPACE:
m = 0
#keyup statement
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or pygame.K_LEFT:
n = 0
p = 0
if event.key == pygame.K_SPACE:
m = 1
if m == 0:
screen.blit(bull, (ab, 100))
background()
player1(ab, bc)
ab += n+p
if ab <= 0:
ab = 0
if ab >= 468:
ab = 468
pygame.display.update()
{This is my first ever post and also i am a complete newbie to python(and even programming for that matter).So please forgive me if my question is not formatted in the right way.}

The reason the bullet is not showing up on screen is because of the keyup statement. Because as it says in your code, the moment the Space key is unpressed, the value 'm' is back to 1 again (m = 1) and the if statement wont be executed. Then if what I said is the problem, I suggest you define a shoot function that blits the bullet on screen and moves it too. It's also better to use the following code instead using keyup or keydown statements:
keys = pygame.key.get_pressed()
if keys[pygame.K_Space]:
player.shoot()
This might help with the problem. shoot() is the function I mentioned but you can use some other method that you're comfortable with.

Related

How to return a function state in the event.get() function of pygame?

I am currently working on a small project where I create a 2d game using pygame. But I am currently stuck with my collisions which are not working as I wished they do. I have a first function returning True or False when the character is in a boundary,
leaved = False
moving = False
player_collision = False
def Extracted_Data(x,y,x_speed,y_speed):
global player_collision
player_collision=False
Player_Hitbox = pygame.draw.rect(gameDisplay,'black',((screen_width-png_width/4)/2 - x_speed,(screen_height-png_height/8)/2 - y_speed , tile_size , 3/4*tile_size),width=1)
for row_index,row in enumerate(data):
for col_index,val in enumerate(row):
if val == 1025:
Boundary = pygame.draw.rect(gameDisplay,'red',(x + col_index * tile_size, y + row_index * tile_size , tile_size , tile_size),width=1)
if pygame.Rect.colliderect(Player_Hitbox,Boundary):
player_collision=True
return player_collision
Which I think is working properly as it prints 'Colliding' when it should. I then tried to detect if player_collision is True or False in my event.get() loop which is the part not doing the right thing.
while not leaved:
print(player_collision)
gameDisplay.fill('white')
Background(x,y)
Extracted_Data(x,y,x_speed,y_speed)
Player(Img_Position)
Foreground(x,y)
Text()
for event in pygame.event.get():
if event.type == pygame.QUIT:
leaved = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
Img_Position = Img_Positions.get("left")
player_collision = Extracted_Data(x,y,player_speed,0)
if player_collision == True:
print("left")
moving = False
x_speed = 0
else:
moving = True
x_speed = player_speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_q or event.key == pygame.K_d:
moving = False
x_speed = 0
elif event.key == pygame.K_z or event.key == pygame.K_s:
moving = False
y_speed = 0
x += x_speed
y += y_speed
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
Even if the collision is detected, the player can still move in the boundary. It will only be stuck if the key is released in the boundary. I think the problems come from the recovery of the player_collision state but I don't know how to fix this. I do not get any error message.
Thank you in advance for any answer !
You should add a line global player_collision just after the line starting with def.
By default, every function has their own scope. This means that all variables defined and changed in this function are not defined or changed outside the function. When the function ends, all changes and defined variables are removed.
This can be changed using the global keyword. Declaring a variable global means that all its changes remain when the function ends, and thus can be used outside the function.
For more information, see an explanation about scopes.

pygame moving left and right issue

I have started making something on pygame but I have encountered an issue when moving left or right. if I quickly change from pressing the right arrow key to pressing the left one and also let go of the right one the block just stops moving. this is my code
bg = "sky.jpg"
ms = "ms.png"
import pygame, sys
from pygame.locals import *
x,y = 0,0
movex,movey=0,0
pygame.init()
screen=pygame.display.set_mode((664,385),0,32)
background=pygame.image.load(bg).convert()
mouse_c=pygame.image.load(ms).convert_alpha()
m = 0
pygame.event.pump()
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type==KEYDOWN:
if event.key==K_LEFT:
movex =-0.5
m = m + 1
if event.key==K_RIGHT:
movex=+0.5
m = m + 1
elif event.type == KEYUP:
if event.key==K_LEFT and not event.key==K_RIGHT:
movex = 0
if event.key==K_RIGHT and not event.key==K_LEFT:
movex =0
x+=movex
y=200
screen.blit(background, (0,0))
screen.blit(mouse_c,(x,y))
pygame.display.update()
is there a way I can change this so if the right arrow key is pressed and the left arrow key is released that it will go right instead of stopping?
P.S
I am still learning pygame and am very new to the module. I'm sorry if this seems like a stupid question but i couldn't find any answers to it.
Your problem is that when you test the KEYDOWN events with
if event.key==K_LEFT and not event.key==K_RIGHT:
you always get True, because when event.key==K_LEFT is True,
it also always is not event.key==K_RIGHT (because the key of the event is K_LEFT after all).
My approach to this kind of problem is to separate
the intent from the action. So, for the key
events, I would simply keep track of what action
is supposed to happen, like this:
moveLeft = False
moveRight = False
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_LEFT: moveLeft = True
if event.key == K_RIGHT: moveRight = True
elif event.type == KEYUP:
if event.key == K_LEFT: moveLeft = False
if event.key == K_RIGHT: moveRight = False
Then, in the "main" part of the loop, you can
take action based on the input, such as:
while True:
for event in pygame.event.get():
...
if moveLeft : x -= 0.5
if moveRight : x += 0.5
the problem is that you have overlapping key features; If you hold down first right and then left xmove is first set to 1 and then changes to -1. But then you release one of the keys and it resets xmove to 0 even though you are still holding the other key. What you want to do is create booleans for each key. Here is an example:
demo.py:
import pygame
window = pygame.display.set_mode((800, 600))
rightPressed = False
leftPressed = False
white = 255, 255, 255
black = 0, 0, 0
x = 250
xmove = 0
while True:
window.fill(white)
pygame.draw.rect(window, black, (x, 300, 100, 100))
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
rightPressed = True
if event.key == pygame.K_LEFT:
leftPressed = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
rightPressed = False
if event.key == pygame.K_LEFT:
leftPressed = False
xmove = 0
if rightPressed:
xmove = 1
if leftPressed:
xmove = -1
x += xmove
pygame.display.flip()
One way could be to create a queue that keeps track of the button that was pressed last. If we press the right arrow key we'll put the velocity first in the list, and if we then press the left arrow key we put the new velocity first in the list. So the button that was pressed last will always be first in the list. Then we just remove the button from the list when we release it.
import pygame
pygame.init()
screen = pygame.display.set_mode((720, 480))
clock = pygame.time.Clock()
FPS = 30
rect = pygame.Rect((350, 220), (32, 32)) # Often used to track the position of an object in pygame.
image = pygame.Surface((32, 32)) # Images are Surfaces, so here I create an 'image' from scratch since I don't have your image.
image.fill(pygame.Color('white')) # I fill the image with a white color.
velocity = [0, 0] # This is the current velocity.
speed = 200 # This is the speed the player will move in (pixels per second).
dx = [] # This will be our queue. It'll keep track of the horizontal movement.
while True:
dt = clock.tick(FPS) / 1000.0 # This will give me the time in seconds between each loop.
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise SystemExit
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
dx.insert(0, -speed)
elif event.key == pygame.K_RIGHT:
dx.insert(0, speed)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
dx.remove(-speed)
elif event.key == pygame.K_RIGHT:
dx.remove(speed)
if dx: # If there are elements in the list.
rect.x += dx[0] * dt
screen.fill((0, 0, 0))
screen.blit(image, rect)
pygame.display.update()
# print dx # Uncomment to see what's happening.
You should of course put everything in neat functions and maybe create a Player class.
I know my answer is pretty late but im new to Pygame to and for beginner like me doing code like some previous answer is easy to understand but i have a solution to.I didn`t use the keydown line code, instead i just put the moving event code nested in the main game while loop, im bad at english so i give you guy an example code.
enter code here
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT or event.type == pygame.K_ESCAPE:
run = False
win.blit(bg, (0, 0))
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
x -= 5
if pressed[pygame.K_RIGHT]:
x += 5
if pressed[pygame.K_UP]:
y -= 5
if pressed[pygame.K_DOWN]:
y += 5
win.blit(image,(x,y))
pygame.display.update()
pygame.quit()
This will make the image move rapidly without repeating pushing the key, at long the code just in the main while loop with out inside any other loop.

My python character only moves 1 pixel at a time

I am making a small little Parkour Minigame where the character jumps from platform to platform, but I can't seem to get the character to move properly. I made another game and it worked correctly, but this one doesn't. When I hold down the left/right arrow key it only moves 1 pixel at a time. Here are the V
Parkour_MoveLeft=Parkour_MoveRight=Parkour_Jump='no'
Parkour_Speed=1
Parkour_X=0
Parkour_Y=0
Parkour_Rows=0
Parkour_Col=0
Now here is my code for the part of the game I am having trouble with :
if location=='Parkour':
Window.fill(Black)
WindowW = 700
WindowH = 700
Window=pygame.display.set_mode((WindowW, WindowH),0, 32)
pygame.draw.rect(Window, Blue, Parkour_Character)
num=0
for point in Parkour_Grids:
mat=Parkour_Lvl_1[num]
num+=1
if mat=='a':
point['collide']='no'
if mat=='p':
pygame.draw.rect(Window, Green, point['rect'])
point['collide']='yes'
for point in Parkour_Grids:
if point['collide']=='yes':
if Parkour_Character.colliderect(point['left']):
Parkour_MoveRight='no'
if Parkour_Character.colliderect(point['right']):
Parkour_MoveLeft='no'
if Parkour_Character.colliderect(point['bottom']):
Parkour_MoveUp='no'
if Parkour_Character.colliderect(point['top']):
Parkour_MoveDown='no'
Parkour Movement
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RIGHT:
Parkour_MoveRight='yes'
if event.key == K_LEFT:
Parkour_MoveLeft='yes'
if event.type == KEYUP:
if event.key == K_RIGHT:
Parkour_MoveRight='no'
if event.key == K_LEFT:
Parkour_MoveLeft='no'
if Parkour_MoveLeft=='yes':
Parkour_Character.right-=Parkour_Speed
if Parkour_MoveRight=='yes':
Parkour_Character.right+=Parkour_Speed
Level Map
Parkour_Lvl_1=['a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','p','p','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','p','p','p','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a']
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Parkour_Grids.append({'rect':pygame.Rect(Parkour_X, Parkour_Y, 80, 30),'right':1,'left':1,'top':1,'bottom':1,'type':'air','collide':'yes'})
Parkour_X+=80
Parkour_Col+=1
if Parkour_Col==40:
Parkour_Col=0
Parkour_X=0
Parkour_Y+=70
Parkour_Rows+=1
if Parkour_Rows==10:
break
for point in Parkour_Grids:
point['right']=pygame.Rect(point['rect'].left+70,point['rect'].top , 6, 70)
point['left']=pygame.Rect(point['rect'].right-76,point['rect'].top , 6, 70)
point['top']=pygame.Rect(point['rect'].left+6,point['rect'].top-15 , 58, 6)
point['bottom']=pygame.Rect(point['rect'].left+6,point['rect'].bottom+6 , 58,6)
Anyone have any help on what I can do? It's the exact same code at another game I made (with different variables), but this one doesn't seem to work.
You need to raise Parkour_Speed. It is set to one, and because it does not look like you have ever multiplied it or implemented a movement twice, that is exactly how many pixels it will move. Upping this number will make it move more pixels at one time. However, while it isn't explicitly clear if this is your issue, it is also possible that it is not moving continuously when you press the button. If the event finder is not being run constantly, this will definitely happen, however because checking events is implemented at the same time, this is probably not the case (with more code it would be easier to know). Another thing that you must repeatedly implement to continuously move your sprite across the screen is where you sync Parkour_X and Y with the screen. I do not see where you do this in the code, but I think it should be easiest to use the move_ip function to solve your problems. Provided that the screen is being updated, this modification to your code should solve your issues:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RIGHT:
Parkour_MoveRight='yes'
if event.key == K_LEFT:
Parkour_MoveLeft='yes'
if event.type == KEYUP:
if event.key == K_RIGHT:
Parkour_MoveRight='no'
if event.key == K_LEFT:
Parkour_MoveLeft='no'
if Parkour_MoveLeft=='yes':
Parkour_Character.move_ip(-Parkour_Speed,0)
if Parkour_MoveRight=='yes':
Parkour_Character.move_ip(Parkour_Speed,0)
If this also does not solve your problem, everything else seems fine, so it may be useful to include even more code. I know you have a lot of code up already, but simple features in graphical programs such as this one tend to be very interconnected.

Character only maintains movement while mouse is moving on screen?

My while loops only maintains the movement for the sprite while the cursor is moving inside of the screen. I've tried reorganizing some of the screen.blits and display.update() and display.flip(). I can't seem to figure out why the character stops after a change in one pixel instead of continuing like it I intended.
background_image = 'Terrain_Grass_First.png'
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.display.set_caption('Hans')
screen_width = 600
screen_height = 400
screen = pygame.display.set_mode((screen_width, screen_height),0,32)
pygame.mouse.set_visible(False)
sprite = pygame.image.load('Hans_front_still.png').convert_alpha()
x,y = (0,0)
movex, movey = (0,0)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_w:
y = -1
elif event.key == K_a:
x = -1
elif event.key == K_s:
y = +1
elif event.key == K_d:
x = +1
elif event.type == KEYUP:
if event.key == K_w:
y = 0
elif event.key == K_a:
x = 0
elif event.key == K_s:
y = 0
elif event.key == K_d:
x = 0
movex += x
movey += y
screen.fill((0,0,0))
screen.blit(sprite,(movex,movey))
pygame.display.flip()
Your loop blocks on pygame.event.get.
You don't schedule any events of your own.
So, you do nothing until the OS has an event (mouse move, redraw, etc.) to give you.
And, even if you fixed that, you're calling movex += x once per event. So, when the OS is throwing a lot of events at you, your sprite will go zipping madly across the screen, but when the events are coming more slowly, it will crawl along. That's almost never what you want.
An easy fix for both problems is to just schedule your own events. For example, with pygame.time.set_timer(), you can make sure you get an event every, say, 250 milliseconds, and you can only move the sprite on those events. For example:
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event, 250)
while True:
for event in pygame.event.get():
# ...
elif event.type == timer_event:
movex += x
movey += y
Another alternative is to design your game with a fixed framerate.
A trivial example looks like this:
FRAME_TIME = 50 # 50ms = 20fps
next_frame_time = pygame.time.get_ticks() + FRAMES
while True:
while True:
event = pygame.event.poll()
if event.type == pygame.NOEVENT:
break
elif # ...
pygame.display.flip()
now = pygame.time.get_ticks()
if now < next_frame_time:
pygame.time.wait(next_frame_time - now)
next_frame_time += FRAMES
Now you can just move every 5th frame.
A realistic example has to deal with missed frames, too many events in the queue, choose between wait and delay appropriately, etc.
But I'd go with the event-driven version with a timer instead of a fixed-framerate version in most cases, especially if you're already going down that line.
The only problem is your Indentation!
The fifth and sixth lines from the bottom have wrong indentation, and you need to delete them.
These two lines:
movex += x
movey += y
should be:
movex += x
movey += y
And it works

Pygame: key.get_pressed() does not coincide with the event queue

I'm attempting to work out simple controls for an application using pygame in Python. I have got the basics working, but I'm hitting a weird wall: I am using the arrow keys to control my character. If I hold down one arrow key, then hold down another arrow key (to move diagonally), the character moves as expected. However, if I release the second key that I pressed (while still holding down the first key), the character stops moving, even though I am still holding down that first key. Here is my simple movement code:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if pygame.key.get_pressed()[K_LEFT]:
player.pos = (player.pos[0] - 2, player.pos[1])
if pygame.key.get_pressed()[K_RIGHT]:
player.pos = (player.pos[0] + 2, player.pos[1])
if pygame.key.get_pressed()[K_UP]:
player.pos = (player.pos[0], player.pos[1] - 2)
if pygame.key.get_pressed()[K_DOWN]:
player.pos = (player.pos[0], player.pos[1] + 2)
Now, I was naturally very confused by this. So I tried to print some lines to debug. In the top of the main control loop, I wrote:
print (pygame.key.get_pressed()[K_DOWN], pygame.key.get_pressed()[K_RIGHT])
print pygame.event.get()
...to output a tuple displaying the state of the down and right arrow keys, and then display the pygame event queue. My results baffled me even more. If I move the character diagonally down and right, pressing the down key first and then the right key, then release the right key to make it move simply downward, the character stops moving as before... but this is printed to the shell:
(1, 0)
[]
That is, when I release the right arrow key and still hold down the down arrow key, pygame.key.get_pressed() understands that the down arrow key is still being held down, but there is nothing in the event queue.
Also, earlier in the code (before the control loop) I am invoking
pygame.key.set_repeat(1, 2)
to make the character continue to move while the key is held down.
Any help will be appreciated! Thanks :)
For things like movement, you should not check for events (like KEYDOWN or KEYUP), but check every iteration of your mainloop if your movement keys are pressed (using get_pressed).
In your code, you check the pressed keys only if there's also a KEYDOWN event.
There are also some other things to consider:
You should seperate the key-mapping and the speed of your player, so it will be easier later on to change either of this.
You should determine a movement vector and normalize it first, since otherwise, if your vertical and horizontal movement speed is 10, your diagonal movement speed would be ~14.
Working example:
import pygame
pygame.init()
screen = pygame.display.set_mode((200, 200))
run = True
pos = pygame.Vector2(100, 100)
clock = pygame.time.Clock()
# speed of your player
speed = 2
# key bindings
move_map = {pygame.K_LEFT: pygame.Vector2(-1, 0),
pygame.K_RIGHT: pygame.Vector2(1, 0),
pygame.K_UP: pygame.Vector2(0, -1),
pygame.K_DOWN: pygame.Vector2(0, 1)}
while run:
for e in pygame.event.get():
if e.type == pygame.QUIT: run = False
screen.fill((30, 30, 30))
# draw player, but convert position to integers first
pygame.draw.circle(screen, pygame.Color('dodgerblue'), [int(x) for x in pos], 10)
pygame.display.flip()
# determine movement vector
pressed = pygame.key.get_pressed()
move_vector = pygame.Vector2(0, 0)
for m in (move_map[key] for key in move_map if pressed[key]):
move_vector += m
# normalize movement vector if necessary
if move_vector.length() > 0:
move_vector.normalize_ip()
# apply speed to movement vector
move_vector *= speed
# update position of player
pos += move_vector
clock.tick(60)
just use the events return data, instead of trying to poll, you're already checking if its a keydown event TYPE, now just interrogate the KEY index, like so:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_LEFT:
player.pos = (player.pos[0] - 2, player.pos[1])
rest of code.....
also consider using a separate data structure to store the state of your controls, then just use the events to update that data structure. That will help make the controls a bit more flexible as you wont be relying on the event queue to cause your character to move, which in my experience causes problems like: not being able to push more than two buttons at a time, and odd delay or timing issues with character movements. so something like:
keystates={'up':False, 'down':False, 'left':False, 'right':False}
running=True
#start main pygame event processing loop here
while running:
for event in pygame.event.get():
if event.type == QUIT:
running=False
#check for key down events
if event.type == KEYDOWN:
if event.key == K_UP:
keystates['up']=True
if event.key == K_DOWN:
keystates['down']=True
if event.key == K_LEFT:
keystates['left']=True
if event.key == K_RIGHT:
keystates['right']=True
#check for key up events
if event.type == KEYUP:
if event.key == K_UP:
keystates['up']=False
if event.key == K_DOWN:
keystates['down']=False
if event.key == K_LEFT:
keystates['left']=False
if event.key == K_RIGHT:
keystates['right']=False
#do something about the key states here, now that the event queue has been processed
if keystates['up']:
character.moveUp() #or whatever your call for these are...
if keystates['down']:
character.moveDown()
if keystates['left']:
character.moveLeft()
if keystates['right']:
character.moveRight()
#gracefully exit pygame here
pygame.quit()
You are using event-based input , but in this case you want polling-based input. Then you don't mess with key-repeats.
import pygame
from pygame.locals import *
done = False
player.pos = Rect(0,0,10,10)
while not done:
for event in pygame.event.get():
# any other key event input
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESC:
done = True
elif event.key == K_F1:
print "hi world mode"
# get key current state
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
player.pos.left -= 10
if keys[K_RIGHT]:
player.pos.left += 10
if keys[K_UP]:
player.pos.top -= 10
if keys[K_DOWN]:
player.pos.left += 10
if keys[K_SPACE]:
print 'firing repeated gun'
My guess is that set repeat doesn't work the way that you think it will. Basically, after your second key goes up, the repeat doesn't happen. This would seem to make sense to me: open up a text editor and hold down the "A" key. "A"s will spill out across the screen. Then, press the "J" key with the "A" key still held down. The "A"s stop. That is a typical key repeat system.
I'm not sure using this "set_repeat" method is going to work out in the end anyway. Basically, any key that the player presses will now "repeat", even if they click "fire" or "jump".
As an alternative, try saving the state when the user presses or releases. Don't use the set_repeat, but do something like the following:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if pygame.key.get_pressed()[K_LEFT]:
player.moving_left = True
if pygame.key.get_pressed()[K_RIGHT]:
player.moving_right = True
if pygame.key.get_pressed()[K_UP]:
player.moving_up = True
if pygame.key.get_pressed()[K_DOWN]:
player.moving_down = True
elif event.type == KEYUP:
if pygame.key.get_pressed()[K_LEFT]:
player.moving_left = False
if pygame.key.get_pressed()[K_RIGHT]:
player.moving_right = False
if pygame.key.get_pressed()[K_UP]:
player.moving_up = False
if pygame.key.get_pressed()[K_DOWN]:
player.moving_down = False
# Somewhere else in your game loop...
if player.moving_left:
player.pos[0] -= 2
if player.moving_right:
player.pos[0] += 2
if player.moving_up:
player.pos[1] -= 2
if player.moving_right:
player.pos[1] += 2

Categories