I want to prevent diagonal movement in Pygame - python

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

name 'event' is not defined not sure why im getting this

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.

How to move a picture this pygame program?

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)

Smoother Keypressed event for paddle object in pong

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.

How do I move an object in one direction with a single keypress until the direction is changed?

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) ---
# ...

Sprite image not displaying in pygame window

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)

Categories

Resources