Python Forum
Movement after KEYUP, only after pause func - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Game Development (https://python-forum.io/forum-11.html)
+--- Thread: Movement after KEYUP, only after pause func (/thread-12373.html)



Movement after KEYUP, only after pause func - esteel - Aug-21-2018

I've been trying to figure it out for hours. Someone help please? The problem is if I hit the pause key while holding a movement key, the character will continue moving in that direction after its unpaused. The only way to stop it is to hold key for the opposite direction and pause simultaneously, or close.

import pygame
import os
os.environ['SDL_VIDEO_CENTERED'] = '1'
import sys
from pygame.locals import *
pygame.display.set_mode((800, 600))


class Player(pygame.sprite.Sprite):

	def __init__(self):
		global direction
		pygame.sprite.Sprite.__init__(self)
		self.movex = 0
		self.movey = 0
		self.frame = 0
		self.images = []
		img_right = pygame.image.load('assets/charactermodels/hero_right_small.png').convert_alpha()
		img_left = pygame.image.load('assets/charactermodels/hero_left_small.png').convert_alpha()
		img_down = pygame.image.load('assets/charactermodels/hero_front_small.png').convert_alpha()
		img_up = pygame.image.load('assets/charactermodels/hero_back_small.png').convert_alpha()
		self.images.append(img_right)
		self.images.append(img_left)
		self.images.append(img_down)
		self.images.append(img_up)
		self.image = self.images[2]
		self.rect  = self.image.get_rect()
		
	def action(self):
			if self.rect.x >= 280 and self.rect.x <= 320 and self.rect.y >= 440:
				textures["S"] = OH
		
	def control(self, x, y):
		self.movex += x
		self.movey += y
	
	def update(self):
		self.rect.x = self.rect.x + self.movex
		self.rect.y = self.rect.y + self.movey
		if direction == 'right':
			self.image = self.images[0]
		elif direction == 'left':
			self.image = self.images[1]
		elif direction == 'down':
			self.image = self.images[2]
		elif direction == 'up':
			self.image = self.images[3]
		else:
			self.image = self.images[0]
		if self.rect.y <= -55:
			self.rect.y = -55
		if self.rect.x >= 657:
			self.rect.x = 657
		if self.rect.y >= 447:
			self.rect.y = 447
		if self.rect.x <= -25:
			self.rect.x = -25
			
		
		if self.rect.x > 398 and self.rect.x < 435 and self.rect.y > 15 and self.rect.y < 44:
			textures["B1"] = Y
			
def Pause():
	#create menu
	pygame.display.set_caption('***GAME PAUSED***')
	background = pygame.display.set_mode((x*tilesize, y*tilesize))
	
	#Loop Setup
	pause = True
	while pause:
		for event in pygame.event.get():
			if event.type == pygame.KEYDOWN:
				if event.type == pygame.QUIT:
					pygame.quit(); sys.exit()
			
				if event.key == ord('p') or event.key == ord('P'):
					pause = False
					
				if event.key == ord('q'):
					pygame.quit()
					sys.exit()

	pygame.display.set_caption('Mysterious Mr. MAN')





blk = (0, 0 , 0)
direction = 'down'

OH = pygame.image.load('assets/levels/black.png').convert()
B = pygame.image.load('assets/levels/wall_bottom.png').convert()
O = pygame.image.load('assets/itemsobjects/PressMeButton.png').convert()
Y = pygame.image.load('assets/itemsobjects/successButton.png').convert()

textures = {
0:pygame.image.load('assets/levels/floor1.png').convert(),
1:pygame.image.load('assets/levels/wall_left.png').convert(),
2:pygame.image.load('assets/levels/corner_TL.png').convert(),
3:pygame.image.load('assets/levels/corner_TR.png').convert(),
4:pygame.image.load('assets/levels/corner_BL.png').convert(),
5:pygame.image.load('assets/levels/corner_BR.png').convert(),
6:pygame.image.load('assets/levels/wall_top.png').convert(),
7:pygame.image.load('assets/levels/wall_right.png').convert(),
8:B,
9:pygame.image.load('assets/levels/floor2.png').convert(),
10:blk,
"B1":O,
"S":B
}

map = [
[2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, "B1", 0, 0, 0, 0, 0, 9, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 7],
[1, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7],
[4, 8, 8, 8, 8, 8, 8, 8, 8, "S", 8, 8, 8, 8, 8, 8, 8, 8, 8, 5]
]

tilesize = 40
x = 20
y = 15
fps = 24
ani = 4
worldx = x * tilesize
worldy = y * tilesize
player = Player()   # spawn player
player.rect.x = 300   # go to x
player.rect.y = 200  # go to y
player_list = pygame.sprite.Group()
player_list.add(player)
steps = 2 #how many pixels to move
player_coord = (player.rect.x, player.rect.y)

pygame.init()
pygame.display.set_caption('Mysterious Mr. MAN')
background = pygame.display.set_mode((x*tilesize, y*tilesize))
background.fill(blk)

main = True

while main:
	for event in pygame.event.get():
		print(event)
		if event.type == pygame.QUIT:
			pygame.quit(); sys.exit()
			main = False
			
		if event.type == pygame.KEYDOWN:
				
			if event.key == pygame.K_SPACE:
				player.action()
				
			if event.key == pygame.K_LEFT or event.key == ord('a'):
				print('Start: ', player_coord)
				player.control(-steps,0)
				direction = 'left'
				
			if event.key == pygame.K_RIGHT or event.key == ord('d'):
				print('Start: ', player_coord)
				player.control(steps,0)
				direction = 'right'
				
			if event.key == pygame.K_UP or event.key == ord('w'):
				print('Start: ', player_coord)
				player.control(0, -steps)
				direction = 'up'
				
			if event.key == pygame.K_DOWN or event.key == ord('s'):
				print('Start: ', player_coord)
				player.control(0, steps)
				direction = 'down'

			if event.key == ord('p') or event.key == ord('P'):
				player.control(0, 0)
				Pause()

		if event.type == pygame.KEYUP:			
			if event.key == pygame.K_LEFT or event.key == ord('a'):
				print('EndPos: ', player_coord)
				print()
				print()
				player.control(steps,0)
			if event.key == pygame.K_RIGHT or event.key == ord('d'):
				print('EndPos: ', player_coord)
				print()
				print()
				player.control(-steps,0)
			if event.key == pygame.K_UP or event.key == ord('w'):
				print('EndPos: ', player_coord)
				print()
				print()
				player.control(0, steps)
			if event.key == pygame.K_DOWN or event.key == ord('s'):
				print('EndPos: ', player_coord)
				player.control(0, -steps)
				print()
				print()
			
				
			
			if event.key == ord('q'):
				pygame.quit()
				sys.exit()
				main = False
				
		
	for row in range(y):
		for column in range(x):
			background.blit(textures[map[row][column]], (column*tilesize, row*tilesize))
			
	player_coord = (player.rect.x, player.rect.y)
	player.update() #update sprite
	player_list.draw(background) # draw player
	pygame.display.flip()
	pygame.display.update()
	steps = 2
	
	continue



RE: Movement after KEYUP, only after pause func - metulburr - Aug-21-2018

see this for why not to use multiple while loops (issue #8)
https://python-forum.io/Thread-PyGame-warnings-of-sentdex-pygame-tutorials

and how to properly have game states
https://python-forum.io/Thread-PyGame-Creating-a-state-machine


RE: Movement after KEYUP, only after pause func - Windspar - Aug-22-2018

This is because you store movement in player class. So when key is let go in pause loop.
There is nothing telling it what to do. So it just thrown away.

Example key press
import pygame
pygame.init()

class Screen:
    @classmethod
    def create(cls, caption, size):
        pygame.display.set_caption(caption)
        cls.surface = pygame.display.set_mode(size)
        cls.clock = pygame.time.Clock()
        cls.running = False
        cls.keys = []

    @classmethod
    def add_display_key(cls, surface):
        rect = surface.get_rect()
        rect.center = cls.surface.get_rect().center
        cls.keys = cls.keys[-4:] + [(surface, rect)]

def loop_event_one():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            Screen.running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_p:
                Screen.loop = loop_event_two
            t = 'loop one keydown: {0}, {1}, {2}'.format(event.unicode, event.key, event.mod)
            s = Screen.font.render(t, 1, (0,100,0))
            Screen.add_display_key(s)

        elif event.type == pygame.KEYUP:
            t = 'loop one keyup: {0}, {1}'.format(event.key, event.mod)
            s = Screen.font.render(t, 1, (0,100,0))
            Screen.add_display_key(s)

def loop_event_two():
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_p:
                Screen.loop = loop_event_one
            t = 'loop two keydown: {0}, {1}, {2}'.format(event.unicode, event.key, event.mod)
            s = Screen.font.render(t, 1, (0,100,0))
            Screen.add_display_key(s)

        elif event.type == pygame.KEYUP:
            t = 'loop two keyup: {0}, {1}'.format(event.key, event.mod)
            s = Screen.font.render(t, 1, (0,100,0))
            Screen.add_display_key(s)


def main():
    Screen.create("Key Press Example", (800,600))
    Screen.loop = loop_event_one
    Screen.font = pygame.font.Font(None, 64)

    Screen.running = True
    while Screen.running:
        Screen.loop()

        Screen.surface.fill((0,0,0))
        for enum, item in enumerate(Screen.keys):
            surface, rect = item
            rect.y = enum * 100 + 70
            Screen.surface.blit(surface, rect)

        pygame.display.update()
        Screen.clock.tick(10)

main()
Key states will work better here.
import pygame
pygame.init()

class Screen:
    @classmethod
    def create(cls, caption, size):
        pygame.display.set_caption(caption)
        cls.surface = pygame.display.set_mode(size)
        cls.clock = pygame.time.Clock()
        cls.running = False

def main():
    Screen.create("Key Press Example", (800,600))
    font = pygame.font.Font(None, 64)
    x = 0
    y = 0

    Screen.running = True
    while Screen.running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Screen.running = False

        x = 0
        y = 0
        key_states = pygame.key.get_pressed()
        if key_states[pygame.K_LEFT]:
            x -= 1
        if key_states[pygame.K_RIGHT]:
            x += 1
        if key_states[pygame.K_DOWN]:
            y += 1
        if key_states[pygame.K_UP]:
            y -= 1

        surface = font.render('{0}, {1}'.format(x, y), 1, (0,100,0))
        rect = surface.get_rect()
        rect.center = Screen.surface.get_rect().center
        Screen.surface.fill((0,0,0))
        Screen.surface.blit(surface, rect)
        pygame.display.update()
        Screen.clock.tick(10)

main()
Don't know why you are using ord.
pygame.K_letter will work for lower an upper case
KeyDown event has unicode, key, and mod.
mod well tell if which crtl, shift, and alt is press. left or right.

pygame don't use both update and flip in the same loop.
if your screen is changing every loop. Then you use flip.

While loop does not need continue.