I'm currently working on a project, which basically is creating the pokemon game with pygame. To do so, I adapted an online code that consisted on game states (https://python-forum.io/Thread-PyGame-Creating-a-state-machine) I created a game state where the user will move the sprite with wads keys, the problem is that, although it does detect the key pressed and moves the sprite, it doesn't detect when the key is being held and moves only 5 pixels the sprite(id does not continue to move, it gets stuck). I tried moving the sprite movement code into the control class but I had the same problem, I think that it could be because the loop in which it's located interrupts the movement. I'd really appreciate the help here. Here´s the Control Class code:
From player import *
import pygame as pg
bg = pygame.image.load("imgs/bg_prueba.jpg")
class Control:
def __init__(self):
self.done = False
self.fps = 60
self.screen = pg.display.set_mode(bg.get_rect().size)
self.screen_rect = self.screen.get_rect()
self.clock = pg.time.Clock()
""" CREATE TRAINER """
motor = Motor()
self.trainer = player(40, 40, motor.pokedex(), self.screen)
def setup_states(self, state_dict, start_state):
self.state_dict = state_dict
self.state_name = start_state
self.state = self.state_dict[self.state_name]
def flip_state(self):
self.state.done = False
previous, self.state_name = self.state_name, self.state.next
self.state.cleanup()
self.state = self.state_dict[self.state_name]
self.state.startup()
self.state.previous = previous
def update(self, dt):
if self.state.quit:
self.done = True
elif self.state.done:
self.flip_state()
self.state.update(self.screen, dt)
def event_loop(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
self.state.get_event(event)
def main_game_loop(self):
while not self.done:
delta_time = self.clock.tick(self.fps) / 1000.0
self.event_loop()
self.update(delta_time)
pg.display.update()
And this is the Game State code:
from States import *
from Gym import *
from Control import *
gyms = [Gym(pygame.image.load("imgs/gym1.png"), 150,5)]
bg = pygame.image.load("imgs/bg_prueba.jpg")
class Map(States):
def __init__(self):
States.__init__(self)
self.next = 'menu'
def cleanup(self):
print('cleaning up Game state stuff')
def startup(self):
print('starting Game state stuff')
def get_event(self, event):
clock.tick(20)
if event.type == pg.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
self.trainer.x -= self.trainer.v
self.trainer.right = False
self.trainer.left = True
self.trainer.down = False
self.trainer.up = False
if event.key == pygame.K_RIGHT or event.key == ord('d'):
self.trainer.x += self.trainer.v
self.trainer.right = True
self.trainer.left = False
self.trainer.down = False
self.trainer.up = False
if event.key == pygame.K_UP or event.key == ord('w'):
self.trainer.y -= self.trainer.v
self.trainer.right = False
self.trainer.left = False
self.trainer.down = False
self.trainer.up = True
if event.key == pygame.K_DOWN or event.key == ord('s'):
self.trainer.y += self.trainer.v
self.trainer.right = False
self.trainer.left = False
self.trainer.down = True
self.trainer.up = False
def update(self, screen, dt):
global walkCount
screen.blit(bg, (0, 0))
self.trainer.draw()
gyms[0].draw(screen)
pygame.display.update()
And the Trainer code for any possible doubts
from Motor import *
walkDown = [pygame.image.load("imgs/run_down1.png"), pygame.image.load("imgs/run_down2.png")]
walkUp = [pygame.image.load("imgs/run_up1.png"), pygame.image.load("imgs/run_up2.png")]
walkLeft = [pygame.image.load("imgs/run_left1.png"), pygame.image.load("imgs/run_left2.png")]
walkRight = [pygame.image.load("imgs/run_right1.png"), pygame.image.load("imgs/run_right2.png")]
stand = pygame.image.load("imgs/stand.png")
clock = pygame.time.Clock()
class player():
def __init__(self, x, y, pokedex, screen):
self.x = x
self.y = y
self.pokedex = pokedex
self.right = False
self.left = False
self.up = False
self.down = False
self.v = 5
self.width, self.height = stand.get_size()
self.rect = (self.x, self.y, self.width, self.height)
self.x2 = x + self.width
self.y2 = y + self.height
self.screen = screen
def draw(self):
self.screen.blit(stand, (self.x, self.y))
if self.left:
self.screen.blit(walkLeft[0], (self.x, self.y))
self.screen.blit(walkLeft[1], (self.x, self.y))
elif self.right:
self.screen.blit(walkRight[0], (self.x, self.y))
self.screen.blit(walkRight[1], (self.x, self.y))
elif self.up:
self.screen.blit(walkUp[0], (self.x, self.y))
self.screen.blit(walkUp[1], (self.x, self.y))
elif self.down:
self.screen.blit(walkDown[0], (self.x, self.y))
self.screen.blit(walkDown[1], (self.x, self.y))
else:
self.screen.blit(stand, (self.x, self.y))
self.rect = (self.x, self.y, self.width, self.height)
pygame.draw.rect(self.screen, (255, 0, 0), self.rect, 2)
KEYDOWN
and KEYUP
event occur only once when a key is pressed. I recommend to gent the current sates of the keys by pygame.key.get_pressed()
, to achieve a continuously smooth movement. e.g:
class Control:
# [...]
def event_loop(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
self.state.get_event(event)
self.state.get_keys()
class Control:
# [...]
def get_event(self, event):
clock.tick(20)
def get_keys(self):
keys = pg.key.get_pressed()
if keys[pg.K_LEFT] or keys[pg.K_a]:
self.trainer.x -= self.trainer.v
elif keys[pg.K_RIGHT] or keys[pg.K_d]:
self.trainer.x += self.trainer.v
elif keys[pg.K_UP] or keys[pg.K_w]:
self.trainer.y -= self.trainer.v
elif keys[pg.K_DOWN] or keys[pg.K_s]:
self.trainer.y += self.trainer.v