So in Pygame, I am trying to create this bat/ball game where the ball comes from the top of the screen (like a meteor) at various speeds, and the bat is near the bottom of the screen that can be moved left/right. Depending on the key pressed (direction the ball goes) and if there is a hit (i.e collision), the ball goes in a certain direction. For example, if you press the "d" key then the ball goes to the right side (provided there was a hit/collision).
Now everything seems to be working fine, however, what I actually want is the player timing the key press WHEN the ball is near the bat. At the moment, I can do that, but also if I keep holding the "d" key from much earlier, the ball still hits the bat. This is definitely not what I want, as it defeats the purpose of timing and having different speeds for the ball. I understand why this is happening as pygame.key.get_pressed() doesn't seem to differentiate between one key press and hold, and considers them one event. So, essentially, I would like to only let the collision happen if the key was pressed as the ball passed the bat and not while it was held from the very start. Here is the Ball class which contains the main code.
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = meteor_img
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width * .85 / 2)
#pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = WIDTH /2 + 10
self.rect.y = HEIGHT - 770
self.speedy = random.randint(7, 14)
self.speedx = 0.3
self.j = 0
def update(self):
if self.rect.y < HEIGHT - 450 and self.j!= 1:
Ball.old_ball(self)
self.rect.x -= self.speedx
self.rect.y += self.speedy
#print (self.rect.x, self.rect.y)
elif self.j !=1:
Ball.change_ball(self)
self.rect.x += self.speedx
self.rect.y += self.speedy
#print (self.rect.x, self.rect.y)
else:
Ball.old_ball(self)
self.rect.x += self.speedx
self.rect.y += self.speedy
#print (self.rect.y)
shot_played = pygame.key.get_pressed()
hits = pygame.sprite.spritecollide(player, mobs, False, pygame.sprite.collide_circle)
#print (hits)
if hits and shot_played[pygame.K_e]:
#print ("Perfect Timing")
self.speedx = random.uniform(1, 5)
self.speedy = -random.uniform(2, 4)
self.j = 1
elif hits and shot_played[pygame.K_d]:
#print ("Perfect Timing")
self.speedx = random.uniform(6, 10)
self.speedy = -random.uniform(-2, 2)
self.j = 1
elif hits and shot_played[pygame.K_a]: #Leg Side
#print ("Perfect Timing")
self.speedx = -random.uniform(6, 10)
self.speedy = -random.uniform(-2, 2)
self.j = 1
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20 or self.rect.y < 10:
self.rect.x = WIDTH /2+10
self.rect.y = HEIGHT - 770
self.speedy = random.randint(7, 14)
self.speedx = 0.3
self.j = 0
time.sleep(1)
#self.speedy = random.randrange(1, 8)
def change_ball(self):
self.image = ball_pitched_img
self.image.set_colorkey(WHITE)
def old_ball(self):
self.image = meteor_img
self.image.set_colorkey(WHITE)
You could just use an event loop instead of the state checking. When you press a key, pygame adds a pygame.KEYDOWN event to the queue once and a pygame.KEYUP event when the key is released. Calling pygame.event.get() empties the queue and returns a list of events over which you can iterate with a for loop to handle one event after the other.
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
done = False
while not done:
# for each event in the event queue.
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
print('d pressed')
# Check if the bat collides with the ball here.
screen.fill((30, 30, 30))
pygame.display.flip()
clock.tick(60)
Related
I am trying to make an if statement in PyGame to have sound affect playing when the player hits the edge of the screen, but I'm apperently making a mistake in my if statement; in another word, I check the condition in a wrong way becasue I don't want my soud affect to continually play when the user is at the edge of the screen, I want the sound to play once when the player is at the edge. I also don't my player to silde off the screen.
I have made a vatiable that handles the playing command in a variable called 'bump_sound':
bump_sound = pygame.mixer.Sound("bump.wav")
And this is what my if statement look like:
# These if statements check to make sure the player won't slide off the screen.
# They also check if the player hits the edge; if so, play the bump sound.
if self.rect.x >= 650:
self.rect.x = 650
bump_sound.play()
if self.rect.x >= 650:
self.rect.x = 650
if self.rect.x < 0:
self.rect.x = 0
bump_sound.play()
if self.rect.y > 325:
self.rect.y = 325
bump_sound.play()
if self.rect.y < 0:
self.rect.y = 0
bump_sound.play()
Thanksfully, the player won't slide off the screen; however, the sound keeps playing.
You have to use > instead of >=:
if self.rect.x > 650:
self.rect.x = 650
bump_sound.play()
Another way is to use Boolean variables. One that indicates if the player hits the edge and one that indicates if the player hit the edge in the previous frame. The sound is played only if the player touched the edge but did not hit it in the previous frame:
def __init__(self):
# [...]
self.previous_hit = False
self.hit = False
def your_function(self):
self.previous_hit = self.hit
if self.rect.x >= 650:
self.rect.x = 650
self.hit = True
if self.rect.x <= 0:
self.rect.x = 0
self.hit = True
if self.rect.y >= 325:
self.rect.y = 325
self.hit = True
if self.rect.y <= 0:
self.rect.y = 0
self.hit = True
if self.hit and not self.previous_hit:
bump_sound.play()
After finally beeing able to make multiple enemies in the game I confronted myself with the most annoying bug ever. I have multiple enemies, a space ship and I can even shoot bullets, but right after I added the enemies to the game and followed the exact same steps as show in this video, the background is gone for some reason, what made the speed of the player character, of the enemies and the bullet went like crazy. Plus, the sprites are duplicating themselves and wont go away, and the only think that I can think is "What the hell am I doing wrong??" because I feel like I can't even follow the steps and copy the code from a video (btw I'm not receiving any error messages). Anyways, here's the full game code.
import pygame
import random
import math
# Initiate pygame
pygame.init()
# Display the game window
screen = pygame.display.set_mode((800, 600))
# Title and Icon
pygame.display.set_caption('Space Invaders')
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)
# Background
background = pygame.image.load('background.png')
# Player
playerSprite = pygame.image.load('player.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemies
enemySprite = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemySprite.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyX_change.append(4)
enemyY_change.append(40)
# Bullet
bulletSprite = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletY_change = 10
# When bullet_state = 'ready', you can't see the bullet on the screen
# When bullet_state = 'fire', the bullet is currently moving
bullet_state = 'ready'
score = 0
def player(x, y):
screen.blit(playerSprite, (x, y))
def enemy(x, y, i):
screen.blit(enemySprite[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = 'fire'
screen.blit(bulletSprite, (x + 16, y + 10))
def isCollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# If a key is pressed, check if it's the right or left arrow key
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if bullet_state == 'ready':
bulletX = playerX
fire_bullet(playerX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# Player movement
playerX += playerX_change
# Prevents the player from going off the border
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemies movement
for i in range(num_of_enemies):
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 4
enemyY[i] += enemyX_change[i]
elif enemyX[i] >= 736:
enemyX_change[i] = -4
enemyY[i] += enemyY_change[i]
# Collision
collision = isCollision(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
bulletY = 480
bullet_state = 'ready'
score += 1
print(score)
enemyX[i] = random.randint(0, 736)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
# Bullet movement
if bulletY <= 0:
bulletY = 480
bullet_state = 'ready'
if bullet_state == 'fire':
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
pygame.display.update()
the background is gone for some reason
Of course, because the background is never blit to screen.
the sprites are duplicating themselves and wont go away,
That's because you don't draw the background.
blit the background in the main application loop, before the objects of the scene are drawn:
while running:
# [...]
screen.blit(background, (0, 0))
# Enemies movement
for i in range(num_of_enemies):
# [...]
the speed of the player character, of the enemies and the bullet went like crazy.
Use pygame.time.Clock() to control the frames per second.
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
# [...]
Another (less sophisticated) possibility, which is probably use in the tutorial is to use pygame.time.delay():
running = True
while running:
pygame.time.delay(10)
# [...]
I am making a game in pygame 1.9.2.
It's a faily simple game in which a ship moves between five columns of bad guys who attack by moving slowly downward. I am attempting to make it so that the ship moves left and right with the left and right arrow keys. Here is my code:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location-=1
if location==-1:
location=0
if keys[K_RIGHT]:
location+=1
if location==5:
location=4
It works too well. The ship moves too fast. It is near impossible to have it move only one location, left or right. How can i make it so the ship only moves once every time the key is pressed?
You can get the events from pygame and then watch out for the KEYDOWN event, instead of looking at the keys returned by get_pressed()(which gives you keys that are currently pressed down, whereas the KEYDOWN event shows you which keys were pressed down on that frame).
What's happening with your code right now is that if your game is rendering at 30fps, and you hold down the left arrow key for half a second, you're updating the location 15 times.
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
location -= 1
if event.key == pygame.K_RIGHT:
location += 1
To support continuous movement while a key is being held down, you would have to establish some sort of limitation, either based on a forced maximum frame rate of the game loop or by a counter which only allows you to move every so many ticks of the loop.
move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if move_ticker == 0:
move_ticker = 10
location -= 1
if location == -1:
location = 0
if keys[K_RIGHT]:
if move_ticker == 0:
move_ticker = 10
location+=1
if location == 5:
location = 4
Then somewhere during the game loop you would do something like this:
if move_ticker > 0:
move_ticker -= 1
This would only let you move once every 10 frames (so if you move, the ticker gets set to 10, and after 10 frames it will allow you to move again)
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 1, otherwise 0. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
This code can be simplified by subtracting "left" from "right" and "up" from "down":
while True:
keys = pygame.key.get_pressed()
x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
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 movement:
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x -= speed
if event.key == pygame.K_RIGHT:
x += speed
if event.key == pygame.K_UP:
y -= speed
if event.key == pygame.K_DOWN:
y += speed
See also Key and Keyboard event
Minimal example of continuous movement: replit.com/#Rabbid76/PyGame-ContinuousMovement
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
keys = pygame.key.get_pressed()
rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
rect.centerx = rect.centerx % window.get_width()
rect.centery = rect.centery % window.get_height()
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), rect)
pygame.display.flip()
pygame.quit()
exit()
Minimal example for a single action: replit.com/#Rabbid76/PyGame-ShootBullet
import pygame
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))
bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
bullet_list.insert(0, tank_rect.midright)
for i, bullet_pos in enumerate(bullet_list):
bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
del bullet_list[i:]
break
window.fill((224, 192, 160))
window.blit(tank_surf, tank_rect)
for bullet_pos in bullet_list:
window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
pygame.display.flip()
pygame.quit()
exit()
import pygame
pygame.init()
pygame.display.set_mode()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); #sys.exit() if sys is imported
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_0:
print("Hey, you pressed the key, '0'!")
if event.key == pygame.K_1:
print("Doing whatever")
In note that K_0 and K_1 aren't the only keys, to see all of them, see pygame documentation, otherwise, hit tab after typing in
pygame.
(note the . after pygame) into an idle program. Note that the K must be capital. Also note that if you don't give pygame a display size (pass no args), then it will auto-use the size of the computer screen/monitor. Happy coding!
I think you can use:
pygame.time.delay(delayTime)
in which delayTime is in milliseconds.
Put it before events.
Try this:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if count == 10:
location-=1
count=0
else:
count +=1
if location==-1:
location=0
if keys[K_RIGHT]:
if count == 10:
location+=1
count=0
else:
count +=1
if location==5:
location=4
This will mean you only move 1/10 of the time. If it still moves to fast you could try increasing the value you set "count" too.
The reason behind this is that the pygame window operates at 60 fps (frames per second) and when you press the key for just like 1 sec it updates 60 frames as per the loop of the event block.
clock = pygame.time.Clock()
flag = true
while flag :
clock.tick(60)
Note that if you have animation in your project then the number of images will define the number of values in tick(). Let's say you have a character and it requires 20 sets images for walking and jumping then you have to make tick(20) to move the character the right way.
Just fyi, if you're trying to ensure the ship doesn't go off of the screen with
location-=1
if location==-1:
location=0
you can probably better use
location -= 1
location = max(0, location)
This way if it skips -1 your program doesn't break
make something like this, but based on time delay. i call my function first time immediately and then lunch timer, and while button is pressed i call it every button_press_delta seconds
from time import time
before main loop:
button_press_delta = 0.2
right_button_pressed = 0
while not done:
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
if not right_button_pressed:
call_my_function()
right_button_pressed = 1
right_button_pressed_time_start = time()
if right_button_pressed:
right_button_pressed_time = (
time() - right_button_pressed_time_start)
if right_button_pressed_time > button_press_delta:
call_my_function()
right_button_pressed_time_start = time()
else:
right_button_pressed = 0
You should use clock.tick(10) as stated in the docs.
all of the answers above are too complexicated i would just change the variables by 0.1 instead of 1
this makes the ship 10 times slower
if that is still too fast change the variables by 0.01
this makes the ship 100 times slower
try this
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location -= 0.1 #or 0.01
if location==-1:
location=0
if keys[K_RIGHT]:
location += 0.1 #or 0.01
if location==5:
location=4
To slow down your game, use pygame.clock.tick(10)
I am making a game in pygame 1.9.2.
It's a faily simple game in which a ship moves between five columns of bad guys who attack by moving slowly downward. I am attempting to make it so that the ship moves left and right with the left and right arrow keys. Here is my code:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location-=1
if location==-1:
location=0
if keys[K_RIGHT]:
location+=1
if location==5:
location=4
It works too well. The ship moves too fast. It is near impossible to have it move only one location, left or right. How can i make it so the ship only moves once every time the key is pressed?
You can get the events from pygame and then watch out for the KEYDOWN event, instead of looking at the keys returned by get_pressed()(which gives you keys that are currently pressed down, whereas the KEYDOWN event shows you which keys were pressed down on that frame).
What's happening with your code right now is that if your game is rendering at 30fps, and you hold down the left arrow key for half a second, you're updating the location 15 times.
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
location -= 1
if event.key == pygame.K_RIGHT:
location += 1
To support continuous movement while a key is being held down, you would have to establish some sort of limitation, either based on a forced maximum frame rate of the game loop or by a counter which only allows you to move every so many ticks of the loop.
move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if move_ticker == 0:
move_ticker = 10
location -= 1
if location == -1:
location = 0
if keys[K_RIGHT]:
if move_ticker == 0:
move_ticker = 10
location+=1
if location == 5:
location = 4
Then somewhere during the game loop you would do something like this:
if move_ticker > 0:
move_ticker -= 1
This would only let you move once every 10 frames (so if you move, the ticker gets set to 10, and after 10 frames it will allow you to move again)
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 1, otherwise 0. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
This code can be simplified by subtracting "left" from "right" and "up" from "down":
while True:
keys = pygame.key.get_pressed()
x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
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 movement:
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x -= speed
if event.key == pygame.K_RIGHT:
x += speed
if event.key == pygame.K_UP:
y -= speed
if event.key == pygame.K_DOWN:
y += speed
See also Key and Keyboard event
Minimal example of continuous movement: replit.com/#Rabbid76/PyGame-ContinuousMovement
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
keys = pygame.key.get_pressed()
rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
rect.centerx = rect.centerx % window.get_width()
rect.centery = rect.centery % window.get_height()
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), rect)
pygame.display.flip()
pygame.quit()
exit()
Minimal example for a single action: replit.com/#Rabbid76/PyGame-ShootBullet
import pygame
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))
bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
bullet_list.insert(0, tank_rect.midright)
for i, bullet_pos in enumerate(bullet_list):
bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
del bullet_list[i:]
break
window.fill((224, 192, 160))
window.blit(tank_surf, tank_rect)
for bullet_pos in bullet_list:
window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
pygame.display.flip()
pygame.quit()
exit()
import pygame
pygame.init()
pygame.display.set_mode()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); #sys.exit() if sys is imported
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_0:
print("Hey, you pressed the key, '0'!")
if event.key == pygame.K_1:
print("Doing whatever")
In note that K_0 and K_1 aren't the only keys, to see all of them, see pygame documentation, otherwise, hit tab after typing in
pygame.
(note the . after pygame) into an idle program. Note that the K must be capital. Also note that if you don't give pygame a display size (pass no args), then it will auto-use the size of the computer screen/monitor. Happy coding!
I think you can use:
pygame.time.delay(delayTime)
in which delayTime is in milliseconds.
Put it before events.
Try this:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if count == 10:
location-=1
count=0
else:
count +=1
if location==-1:
location=0
if keys[K_RIGHT]:
if count == 10:
location+=1
count=0
else:
count +=1
if location==5:
location=4
This will mean you only move 1/10 of the time. If it still moves to fast you could try increasing the value you set "count" too.
The reason behind this is that the pygame window operates at 60 fps (frames per second) and when you press the key for just like 1 sec it updates 60 frames as per the loop of the event block.
clock = pygame.time.Clock()
flag = true
while flag :
clock.tick(60)
Note that if you have animation in your project then the number of images will define the number of values in tick(). Let's say you have a character and it requires 20 sets images for walking and jumping then you have to make tick(20) to move the character the right way.
Just fyi, if you're trying to ensure the ship doesn't go off of the screen with
location-=1
if location==-1:
location=0
you can probably better use
location -= 1
location = max(0, location)
This way if it skips -1 your program doesn't break
make something like this, but based on time delay. i call my function first time immediately and then lunch timer, and while button is pressed i call it every button_press_delta seconds
from time import time
before main loop:
button_press_delta = 0.2
right_button_pressed = 0
while not done:
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
if not right_button_pressed:
call_my_function()
right_button_pressed = 1
right_button_pressed_time_start = time()
if right_button_pressed:
right_button_pressed_time = (
time() - right_button_pressed_time_start)
if right_button_pressed_time > button_press_delta:
call_my_function()
right_button_pressed_time_start = time()
else:
right_button_pressed = 0
You should use clock.tick(10) as stated in the docs.
all of the answers above are too complexicated i would just change the variables by 0.1 instead of 1
this makes the ship 10 times slower
if that is still too fast change the variables by 0.01
this makes the ship 100 times slower
try this
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location -= 0.1 #or 0.01
if location==-1:
location=0
if keys[K_RIGHT]:
location += 0.1 #or 0.01
if location==5:
location=4
To slow down your game, use pygame.clock.tick(10)
Hi i'm making a fighting game to get some practice with pygame but I have run into a problem with crouching/ducking. When I press the down button it goes back to its original location then ducks. If you need more info to help i will provide.
import pygame
import random
display_height = 600
display_width = 1000
dis_screen = pygame.display.set_mode((display_width, display_height))
FPS = 30
clock = pygame.time.Clock()
img = pygame.image.load('foo.png')
crouchimg = pygame.image.load('crouchimg.png')
# Simple player object
class Player(object):
def __init__(self, x, y, image):
self.x = x
self.y = y
self.image = image
# Method to draw object
def draw(self):
dis_screen.blit(self.image, (self.x, self.y))
# Method to move object
def move(self, speedx, speedy):
self.x += speedx
self.y += speedy
class MainRun(object):
def __init__(self, displayw, displayh):
self.dw = displayw
self.dh = displayh
self.Main()
def Main(self):
# Put all variables up here
stopped = False
x_move = 0
y_move = 0
p1_y_loc = 200
p1_x_loc = 200
x = pygame.Rect().x
greg = Player(p1_x_loc, p1_y_loc, img)
# Main Loop
while not stopped:
print(x)
dis_screen.fill((255, 255, 255)) # Tuple for filling display... Current is white
# Event Tasking
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
y_move = 0
x_move = 5
elif event.key == pygame.K_LEFT:
y_move = 0
x_move = -5
elif event.key == pygame.K_UP:
y_move = -5
x_move = 0
elif event.key == pygame.K_DOWN:
p1_y_loc = 300
p1_x_loc = 0
greg = Player(p1_x_loc, p1_y_loc, crouchimg)
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
p1_y_loc = 200
greg = Player(p1_x_loc, p1_y_loc, img)
if event.key == pygame.K_UP:
y_move = 0
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
x_move = 0
greg.move(x_move, y_move)
greg.draw()
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
run = MainRun(display_width, display_height)
run.Main()
That's because when you're pressing the down key you're creating a new player at the x-position p1_x_loc (which you've set to 0) and y-position p1_y_loc (which you've set to 300). So when the player crouches it also moves it to (0, 300) no matter the position the player currently is.
A way to solve this would be to just change the player's image, and not create a completely new player. You can do it this way, player.image = crouchimg instead of greg = Player(p1_x_loc, p1_y_loc, crouchimg). And when the player gets up you just change the image again: player.image = img
And if you have to change the players' y-position when crouching you could do it the same way: player.y = 200 and player.y = 300.