Reputation: 87
I'm trying to make a quick animation where if a key is held down the character will keep moving, however my code doesn't seem to be doing that. I press the key and moves once but doesn't move any further. Any help to fix this. Any other suggestions are appreciated and keep in mind this isn't near final product form.
import pygame
import os
import sys
from pygame.locals import *
pygame.init()
WIN = pygame.display.set_mode(display)
pygame.display.set_caption('The Game')
width = 500
height = 500
display = (width, height)
WHITE = (255, 255, 255)
left = [
pygame.image.load(os.path.join('assets', 'main', 'left_walk1.png')),
pygame.image.load(os.path.join('assets', 'main', 'left_walk2.png'))
]
right = [
pygame.image.load(os.path.join('assets', 'main', 'right_walk1.png')),
pygame.image.load(os.path.join('assets', 'main', 'right_walk2.png'))
]
up = [
pygame.image.load(os.path.join('assets', 'main', 'up_walk1.png')),
pygame.image.load(os.path.join('assets', 'main', 'up_walk2.png'))
]
down = [
pygame.image.load(os.path.join('assets', 'main', 'down_walk1.png')),
pygame.image.load(os.path.join('assets', 'main', 'down_walk2.png'))
]
standing_left = (os.path.join('assets', 'main', 'down_walk2.png'))
standing_right = (os.path.join('assets', 'main', 'down_walk2.png'))
standing_up = (os.path.join('assets', 'main', 'down_walk2.png'))
standing_down = (os.path.join('assets', 'main', 'down_walk2.png'))
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
self.health = 100
self.inv = []
self.left = False
self.right = False
self.up = False
self.down = False
self.walking_count = 0
self.facing = 'down'
def draw_player(self, win):
if self.walking_count == 3:
self.walking_count = 1
if self.left:
WIN.blit(left[self.walking_count // 2], (self.x, self.y))
elif self.right:
WIN.blit(right[self.walking_count // 2], (self.x, self.y))
player = Player(100, 100)
FPS = 40
fpsClock = pygame.time.Clock()
while True:
fpsClock.tick(FPS)
WIN.fill(WHITE)
player.draw_player(WIN)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_UP and player.y <= 0:
player.up = True
elif event.key == K_DOWN:
player.down = True
elif event.key == K_LEFT:
player.left = True
elif event.key == K_RIGHT:
player.right = True
elif event.type == KEYUP:
if event.key == K_UP:
player.up = False
if event.key == K_DOWN:
player.down = False
if event.key == K_LEFT:
player.left = False
if event.key == K_RIGHT:
player.right = False
if player.left:
player.x -= 5
player.walking_count += 1
if player.right:
player.x += 5
player.walking_count += 1
if player.up:
player.y -= 5
player.walking_count += 1
if player.down:
player.y += 5
player.walking_count += 1
pygame.display.update()
Upvotes: 2
Views: 58
Reputation: 211047
It is a matter of Indentation. You've to apply the movement in the application loop rather than the event loop:
while True:
fpsClock.tick(FPS)
WIN.fill(WHITE)
player.draw_player(WIN)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_UP and player.y <= 0:
player.up = True
elif event.key == K_DOWN:
player.down = True
elif event.key == K_LEFT:
player.left = True
elif event.key == K_RIGHT:
player.right = True
elif event.type == KEYUP:
if event.key == K_UP:
player.up = False
if event.key == K_DOWN:
player.down = False
if event.key == K_LEFT:
player.left = False
if event.key == K_RIGHT:
player.right = False
#<--| INDENTATION
if player.left:
player.x -= 5
if player.right:
player.x += 5
if player.up:
player.y -= 5
if player.down:
player.y += 5
pygame.display.update()
Alternatively you can use pygame.key.get_pressed()
rather than the KEYDOWN
and KEYUP
event:
while True:
fpsClock.tick(FPS)
WIN.fill(WHITE)
player.draw_player(WIN)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed()
player.left, player.right, player.up, player.down = False, False, False, False
if keys[K_LEFT]:
player.x -= 5
player.left = True
if keys[K_RIGHT]:
player.x += 5
player.right = True
if keys[K_UP]:
player.y -= 5
player.up = True
if keys[K_DOWN]:
player.y += 5
player.down = True
pygame.display.update()
To control the animation speed, add an attribute self.animation_frames = 10
. This attributes controls how many frames each image of the animation is shown. Compute the image index dependent on the attribute.
walking_count
has to be incremented in Player.draw_player
rather than the application loop.
To ensure that the correct "standing" image is displayed, you have to add an attribute self.standing
. Set the attribute dependent on the current direction in draw_player
. If the player is not moving, the display the current standing image:
class Player:
def __init__(self, x, y):
# [...]
self.animation_frames = 10
self.standing = standing_left
def draw_player(self, win):
# get image list
if self.left:
image_list = left
self.standing = standing_left
else self.right:
image_list = right
self.standing = standing_right
else:
image_list = [self.standing]
# increment walk count and get image list
image_index = self.walking_count // self.animation_frames
if image_index >= len(image_list):
image_index = 0
self.walking_count = 0
self.walking_count += 1
WIN.blit(image_list[image_index], (self.x, self.y))
Upvotes: 2