I'm working on making a version of the game snake and I'm trying to prevent diagonal movement. Is there a way to prevent multiple KEYDOWN events
This is my helper function that detects KEYDOWN events.
def _keydown_events(self, event):
'''Responds to pressing keystrokes'''
if event.type == pg.KEYDOWN:
if event.key == pg.K_q:
pg.display.quit()
running = False
sys.exit()
elif event.key == pg.K_RIGHT:
self.snake.move_right = True
elif event.key == pg.K_LEFT:
self.snake.move_left = True
elif event.key == pg.K_UP:
self.snake.move_up = True
elif event.key == pg.K_DOWN:
self.snake.move_down = True
You have to ensure that just self.snake.move_right, self.snake.move_left, self.snake.move_up or self.snake.move_down is set, but never 2 or more states simultaneously. e.g:
def _keydown_events(self, event):
'''Responds to pressing keystrokes'''
if event.type == pg.KEYDOWN:
if event.key == pg.K_q:
pg.display.quit()
running = False
sys.exit()
elif if event.key in [pg.K_RIGHT, pg.K_LEFT, pg.K_UP, pg.K_DOWN]:
self.snake.move_right = False
self.snake.move_left = False
self.snake.move_up = False
self.snake.move_down = False
if event.key == pg.K_RIGHT:
self.snake.move_right = True
elif event.key == pg.K_LEFT:
self.snake.move_left = True
elif event.key == pg.K_UP:
self.snake.move_up = True
elif event.key == pg.K_DOWN:
self.snake.move_down = True
Anyway I recommend to remove the states self.snake.move_right, self.snake.move_left, self.snake.move_up or self.snake.move_down.
Use a single state which indicates the direction of the snake. Add a state move_dir and assign pygame.key.name(event.key). The value of move_dir becomes "right", "left", "up" respectively "down" for RIGHT, LEFT, UP or DOWN. e.g:
def _keydown_events(self, event):
'''Responds to pressing keystrokes'''
if event.type == pg.KEYDOWN:
if event.key == pg.K_q:
pg.display.quit()
running = False
sys.exit()
elif if event.key in [pg.K_RIGHT, pg.K_LEFT, pg.K_UP, pg.K_DOWN]:
# move_dir becomes "right", "left", "up" or "down"
self.snake.move_dir = pygame.key.name(event.key)
Of course you can state the move vector directly:
def _keydown_events(self, event):
'''Responds to pressing keystrokes'''
if event.type == pg.KEYDOWN:
if event.key == pg.K_q:
pg.display.quit()
running = False
sys.exit()
elif if event.key in [pg.K_RIGHT, pg.K_LEFT, pg.K_UP, pg.K_DOWN]:
move_dirs = {pg.K_RIGHT: (1, 0), pg.K_LEFT: (-1, 0),
pg.K_UP: (0, -1), pg.K_DOWN: (0, 1)}
self.snake.move_dir = move_dirs[event.key]
You may want to turn your movement direction variables into a single delta value instead:
if event.key == pg.K_RIGHT:
self.snake.move_dir = (+1, 0)
elif event.key == pg.K_LEFT:
self.snake.move_dir = (-1, 0)
elif event.key == pg.K_UP:
self.snake.move_dir = (0, -1)
elif event.key == pg.K_DOWN:
self.snake.move_dir = (0, +1)
and wherever you move your snake,
dx, dy = self.move_dir
x += dx
y += dy
Related
class GameState():
def init(self):
self.state = 'main_game'
def main_game(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN: # this is where the error comes from
mouse_state = 1
pygame.mouse.set_pos(mouse_x,mouse_y + 1)
else:
mouse_state = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
snake.yV = 0
snake.xV = -1
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
snake.yV = 0
snake.xV = 1
if event.key == pygame.K_UP or event.key == pygame.K_w:
snake.xV = 0
snake.yV = -1
if event.key == pygame.K_DOWN or event.key == pygame.K_s:
snake.xV = 0
snake.yV = 1
mouse_x = pygame.mouse.get_pos()[0]
mouse_y = pygame.mouse.get_pos()[1]
pygame.display.set_caption("Snake, FPS: " + str(clock.get_fps()))
screen.fill(GREY)
snake.update()
food.update()
utility.update()
bombs.update()
food.draw()
snake.draw()
utility.draw()
bombs.draw()
pygame.display.flip()
button = Button()
snake = Snake()
food = Food()
utility = Utility()
bombs = Bombs()
game_state = GameState()
while not done:
game_state.main_game()
clock.tick(50)
pygame.quit()
This is just the snippit of code i can send the rest if needed the thing i did previously i had it under a game loop but this time im making a class and object so i can make multiple levels in the game
The if event.type == pygame.MOUSEBUTTONDOWN: and if event.type == pygame.KEYDOWN: are both outside of the for loop that defines the "event" variable.
def main_game(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN: # this is where the error comes from
mouse_state = 1
pygame.mouse.set_pos(mouse_x,mouse_y + 1)
else:
mouse_state = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
snake.yV = 0
snake.xV = -1
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
snake.yV = 0
snake.xV = 1
if event.key == pygame.K_UP or event.key == pygame.K_w:
snake.xV = 0
snake.yV = -1
if event.key == pygame.K_DOWN or event.key == pygame.K_s:
snake.xV = 0
snake.yV = 1
mouse_x = pygame.mouse.get_pos()[0]
mouse_y = pygame.mouse.get_pos()[1]
pygame.display.set_caption("Snake, FPS: " + str(clock.get_fps()))
screen.fill(GREY)
snake.update()
food.update()
utility.update()
bombs.update()
food.draw()
snake.draw()
utility.draw()
bombs.draw()
pygame.display.flip()
button = Button()
snake = Snake()
food = Food()
utility = Utility()
bombs = Bombs()
game_state = GameState()
Your code have indentation problems. Which makes event.MOUSEBUTTONDOWN and other events outside the loop. You code should have looks like this.
I've got the code below, the image ain't moving. Please tell me what's wrong so I can fix it real quick. Also, try to keep the answers short and to the point.
I can hear the music and all, the escape button and the quit is working too, directional keys are not.
PlayerImage = pygame.image.load("ch.jpg")
Player = pygame.Rect(675, 350, 40, 4)
StretchPlayer = pygame.transform.scale(PlayerImage, (40, 40))
goLeft = False
goRight = False
goUp = False
goDown = False
Velocity = 3
EatSound = pygame.mixer.Sound("sound.wav")
pygame.mixer.music.load("X.mp3")
pygame.mixer.music.play(-1, 0.0)
musicPlaying = True
while True :
for event in pygame.event.get() :
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('A'):
goRight = False
goLeft = True
if event.key == pygame.K_RIGHT or event.key == ord('D'):
goRight = True
goLeft = False
if event.key == pygame.K_UP or event.key == ord('W'):
goUp = True
goDown = False
if event.key == pygame.K_DOWN or event.key == ord('S'):
goUp = False
goDown = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_LEFT or event.key == ord('A'):
goLeft = False
if event.key == pygame.K_RIGHT or event.key == ord('D'):
goRight = False
if event.key == pygame.K_UP or event.key == ord('W'):
goUp = False
if event.key == pygame.K_DOWN or event.key == ord('S'):
goDown = False
DisplayScreen.blit(StretchPlayer, Player)
pygame.display.update()
Just change the location of the rectangle Player dependent on goLeft, goRight, goUp and goDown, e.g. by .move:
dx = -1 if goLeft else 1 if goRight else 0
dy = -1 if goUp else 1 if goDown else 0
Player = Player.move(dx, dy)
DisplayScreen.blit(StretchPlayer, Player)
I'm trying to make my paddle movements smoother in my pong game. My player_paddle1 has smooth movements and will stop whenever I let go of the key. However, my other player_paddle2, which incorporates the same keypress algorithm has the other paddle, does not do so. It will keep on going even if I release the key.
if game_option == "Two Player":
if event.type == KEYDOWN:
if event.key == K_UP:
player_paddle1.direction = -1
elif event.key == K_DOWN:
player_paddle1.direction = 1
if event.key == K_w:
player_paddle2.direction = -1
elif event.key == K_s:
player_paddle2.direction = 1
if event.type == KEYUP:
if event.key == K_UP and player_paddle1.direction == -1:
player_paddle1.direction = 0
elif event.key == K_DOWN and player_paddle1.direction == 1:
player_paddle1.direction = 0
if event.key == K_UP and player_paddle2.direction == -1:
print("The key is now up!")
player_paddle2.direction = 0
elif event.key == K_UP and player_paddle2.direction == 1:
player_paddle2.direction = 0
Also, while the up and down keys are extremely responsive, the W and S keys are not too responsive, which means, a keypressed will not immedieatly result in paddle motion. How can I fix this?
You check K_UP for second player in KEYUP but it has to be K_w and K_s.
Besides you don't have to check player_paddle2.direction
if event.type == KEYUP:
if event.key == K_UP:
player_paddle1.direction = 0
elif event.key == K_DOWN:
player_paddle1.direction = 0
elif event.key == K_w: # <-- there was K_UP
print("The key is now up!")
player_paddle2.direction = 0
elif event.key == K_s: # <-- there was K_UP
player_paddle2.direction = 0
it can be shorter
elif event.type == KEYUP:
if event.key in (K_UP, K_DOWN)
player_paddle1.direction = 0
elif event.key in (K_w, K_s):
player_paddle2.direction = 0
BTW: you can use elif in some places.
When I start the program and press the first key the program freezes. Can anyone tell me why this doesn't work and give me a possible solution to my problem?
if event.key == pygame.K_UP:
key = False
while key == False:
schlange.move(0, -50)
if event.key == pygame.K_DOWN:
key = True
while key == True:
schlange.move(0, 50)
if event.key == pygame.K_LEFT:
key = False
while key == False:
schlange.move(-50, 0)
if event.key == pygame.K_RIGHT:
key = True
while key == True:
schlange.move(50, 0)
def move(self, x_change, y_change):
self.screen.fill(BLACK)
self.x_change = x_change
self.y_change = y_change
self.startx += x_change
self.starty += y_change
self.rectsize = (self.startx, self.starty)
pygame.draw.rect(self.screen, self.color, [self.startx, self.starty, self.width, self.height])
Thanks in advance!
The formatting in your code is off - but regardless - the code in each of the sections that look like:
key = False
while key == False:
schlange.move(0, -50)
Will never complete. That while loop will ALWAYS evaluate to True, because key == False is always true, and never changes. So the loop will never end.
it could be something like this
speed = (0, 0)
While True:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
speed = (0, -50)
elif event.key == pygame.K_DOWN:
speed = (0, 50)
if event.key == pygame.K_LEFT:
speed = (-50, 0)
if event.key == pygame.K_RIGHT:
speed = (50, 0)
# --- all updates (without draws) ---
schlange.move(speed[0], speed[1])
# --- all draws (without updates) ---
# ...
My sprite image is not displaying in the pygame window. It's probably something really simple, but I don't understand why it isn't showing. I'm fairly new to programming, so it's probably why I don't understand this. Is it something I've done wrong in the class itself? Here is my code:
import pygame, sys
from pygame.locals import *
windowwidth = 600
windowheight = 600
WALLWIDTH = 30
WALLHEIGHT = 30
PLAYERWIDTH = 20
PLAYERHEIGHT = 20
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
LIMEGREEN = (50, 205, 50)
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('Green circle png.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def changespeed(self, x, y):
self.change_x = x
self.change_y = y
def update_pos(self, x, y):
old_x_pos = self.rect.x
new_x_pos = old_x_pos + self.change_x
self.rect.x = new_x_pos
old_y_pos = self.rect.y
new_y_pos = old_y_pos + self.change_y
self.rect.x = new_y_pos
def main():
pygame.init()
thescreen = pygame.display.set_mode((windowwidth, windowheight))
pygame.display.set_caption('Maze Game')
thescreen.fill((BLACK))
mainclock = pygame.time.Clock()
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if (event.key == K_UP or event.key == K_w):
Player.changespeed = (-3, 0)
elif (event.key == K_DOWN or event.key == K_s):
Player.changespeed = (3, 0)
elif (event.key == K_LEFT or event.key == K_a):
Player.changespeed = (0, -3)
elif (event.key == K_RIGHT or event.key == K_d):
Player.changespeed = (0, 3)
if event.type == KEYUP:
if (event.key == K_UP or event.key == K_w):
Player.changespeed = (0, 0)
elif (event.key == K_DOWN or event.key == K_s):
Player.changespeed = (0, 0)
elif (event.key == K_LEFT or event.key == K_a):
Player.changespeed = (0, 0)
elif (event.key == K_RIGHT or event.key == K_d):
Player.changespeed = (0, 0)
mainclock.tick(60)
pygame.display.update()
pygame.quit()
if __name__ == '__main__':
main()
You need to draw the player on the screen. Call some code to draw it, (this is easiest to do in a render updates group but you could simply blit it as well). You probably also want to call the update function, but I won't include that in my example. Here is what you can do:
players = pygame.sprite.RenderUpdates()
players.add(Player(200,200))
def mainloop():
while running == True:
pygame.display.update(players.draw(thescreen))
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if (event.key == K_UP or event.key == K_w):
Player.changespeed = (-3, 0)
elif (event.key == K_DOWN or event.key == K_s):
Player.changespeed = (3, 0)
elif (event.key == K_LEFT or event.key == K_a):
Player.changespeed = (0, -3)
elif (event.key == K_RIGHT or event.key == K_d):
Player.changespeed = (0, 3)
if event.type == KEYUP:
if (event.key == K_UP or event.key == K_w):
Player.changespeed = (0, 0)
elif (event.key == K_DOWN or event.key == K_s):
Player.changespeed = (0, 0)
elif (event.key == K_LEFT or event.key == K_a):
Player.changespeed = (0, 0)
elif (event.key == K_RIGHT or event.key == K_d):
Player.changespeed = (0, 0)