1
\$\begingroup\$

So I made a new game in pygame and after hours of debugging, I got to a stage where all of my objects get blitted onto the screen. Well, that's great but now I want movement for a particular object. I achieved that task easily enough, but I was wondering is there a way to make movement continuous while a key is pressed. For example, while the down key is pressed down, the character will smoothly glide 5 steps down instead of jerking repeatedly. This won't be good in a runner game where the player chooses when to start running and when to stop. I thought that this would work:

if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                heroY += 10

but unfortunately, this is the same as removing the second line and fixing the code indentation. I am very new to pygame and am making test projects to practice. Thanks in advance.

Full Code :

'''
Imports
'''
import pygame_textinput
import pygame
import sys
import random
import os
os.chdir(os.path.dirname(os.path.abspath(__file__)))

'''
Basic Stuff for Pygame
'''
pygame.init()
display_surface = pygame.display.set_mode((800, 640))
pygame.display.set_caption("AMOGUS")
gameIcon = pygame.image.load('icon_of_the_game.png')
pygame.display.set_icon(gameIcon)

'''
Variables
'''


player_changeable_name = pygame_textinput.TextInputVisualizer()
clock = pygame.time.Clock()
white = (255, 255, 255)  

'''
Game State Variable
'''
menu = "menu"
game = "game"
ending_ani = "ending_ani"

'''
Functions
'''
def menu():
    print("In Proggress")

def game():
    print("In Proggress")

def ending_ani():
    print("In Proggress")

'''
Images
'''
special_character = random.randint(1, 5)
if special_character == 1:
    imposter = pygame.image.load('sus1.png')
    sussie1 = pygame.image.load('sus2.png')
    sussie2 = pygame.image.load('sus3.png')
    sussie3 = pygame.image.load('sus4.png')
    sussie4 = pygame.image.load('sus5.png')
elif special_character == 2:
    imposter = pygame.image.load('sus2.png')
    sussie1 = pygame.image.load('sus1.png')
    sussie2 = pygame.image.load('sus3.png')
    sussie3 = pygame.image.load('sus4.png')
    sussie4 = pygame.image.load('sus5.png')    
elif special_character == 3:
    imposter = pygame.image.load('sus3.png')
    sussie1 = pygame.image.load('sus1.png')
    sussie2 = pygame.image.load('sus2.png')
    sussie3 = pygame.image.load('sus4.png')
    sussie4 = pygame.image.load('sus5.png')
elif special_character == 4:
    imposter = pygame.image.load('sus4.png')
    sussie1 = pygame.image.load('sus1.png')
    sussie2 = pygame.image.load('sus2.png')
    sussie3 = pygame.image.load('sus3.png')
    sussie4 = pygame.image.load('sus5.png')
else:
    imposter = pygame.image.load('sus5.png')
    sussie1 = pygame.image.load('sus1.png')
    sussie2 = pygame.image.load('sus2.png')
    sussie3 = pygame.image.load('sus3.png')
    sussie4 = pygame.image.load('sus4.png')
hero = pygame.image.load('hero.png')


'''
Hero
'''
heroX = 100
heroY = 100

'''
Imposter
'''
ImpX = 0
ImpY = 0

'''
Sussies
'''
Sussie1X = 0
Sussie1Y = 0
Sussie2X = 500
Sussie2Y = 500
Sussie3X = 250
Sussie3Y = 250
Sussie4X = 100
Sussie4Y = 500


'''
Main Script
'''
game_state = menu
while game_state == menu:
    

    display_surface.fill(white)
    display_surface.blit(imposter, (ImpX, ImpY))
    display_surface.blit(hero, (heroX,heroY))
    display_surface.blit(sussie1, (Sussie1X,Sussie1Y))
    display_surface.blit(sussie2, (Sussie2X,Sussie2Y))
    display_surface.blit(sussie3, (Sussie3X,Sussie3Y))
    display_surface.blit(sussie4, (Sussie4X,Sussie4Y))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                heroY += 10

        if event.type == pygame.KEYUP:
            pass
    pygame.display.update()
   

```
\$\endgroup\$
6
  • \$\begingroup\$ Right now you're only reacting when a new key down signal comes from the OS (ie. when the key is first pressed, and then at an OS-configurable key repeat rate after that). Presumably you considered storing a variable that says "the down key is currently held" and then using that variable to apply movement every frame in your main update loop? \$\endgroup\$
    – DMGregory
    Jan 3 at 15:16
  • \$\begingroup\$ @DMGregory I understood your first line, but what do you mean by "Presumably you considered storing a variable that says "the down key is currently held" and then using that variable to apply movement every frame in your main update loop?" ? all I want is the y-axis of hero to change continuously while the down / up key is held down and it should become stationary when released. \$\endgroup\$ Jan 3 at 16:00
  • \$\begingroup\$ When you get a key press event you store downButtonPressed = true and when you get a key released event you store downButtonPressed = false and then in your game's main update loop you check the value of downButtonPressed to decide whether to move the character down one frame's worth. Where did you run into trouble with this? \$\endgroup\$
    – DMGregory
    Jan 3 at 16:24
  • \$\begingroup\$ so using variables and if and elif statements isn't hard. I never ran into trouble. I was just wondering. But how am I supposed to implement the use of variables in my code? I did the most sensible thing to do and it still does not work. I first did an event checker and if the down key is pressed while being held, Down_Key_Pressed = True. Then did the same with the key being released event, but this time it sets it to True. Then used if to move the hero. Unfortunately, no improvement. Could you edit the main loop and share it with me? \$\endgroup\$ Jan 4 at 3:26
  • \$\begingroup\$ Sounds like you should edit your question to show what you tried. \$\endgroup\$
    – DMGregory
    Jan 4 at 3:41

2 Answers 2

1
\$\begingroup\$

Your problem is nothing related to Pygame. It's about Python.

pygame.event.get() is a function that reports CURRENT EVENTS received from the user.

It means when you press a key, an event is sent to this function, which type is pygame.KEYDOWN. And when you release that key, another event is being sent: pygame.KEYUP.

Note that when you are holding a specific key, no event is being sent to pygame.event.get().

So, basically, all you need to do is track held-down keys using pygame.KEYDOWN and pygame.KEYUP.

Method 1: creating a medium list

With this method, whenever a key is pressed, you append it to a list. Whenever you release that key, you remove it from the list. Then, all you need to do is check that list in your game loop.

Use this if you want to track down many held keys.

heldKeys=[]

def getEvents():
    global heldKeys
    for i in pg.event.get():
        if i.event==pygame.KEYDOWN:#Track down key presses here

            if i.key==pygame.K_DOWN:
                heldKeys.append('Down')
            
        elif i.event==pygame.KEYUP:#Track down key releases here

            if i.key==pygame.K_DOWN:
                heldKeys.remove('Down')

def checkHeldKeys():#use this in you'r game loop to move you'r character
    global heroY;
    for i in heldKeys:
        if 'Down' in heldKeys:
            heroY+=10;

Method 2: creating a medium boolean variable

In here, all You need is a boolean:

  • Whenever the pygame.KEYDOWN signal is sent, set this boolean to True.
  • whenever the pygame.KEYUP signal is sent, set this boolean to False.

Use this method only if you need to check 1 or 2 held keys.

isMoving=False

def getEvents():
    global heldKeys
    for i in pg.event.get():
        if i.event==pygame.KEYDOWN:#Track down key presses here

            if i.key==pygame.K_DOWN:
                isMoving=True
            
        elif i.event==pygame.KEYUP:#Track down key releases here

            if i.key==pygame.K_DOWN:
                isMoving=False

def checkIsMoving():#use this in you'r game loop to move you'r character
    global heroY;
    
    if isMoving==True:
        heroY+=10
```
\$\endgroup\$
7
  • \$\begingroup\$ Hey @YoloWex . I am just a new programmer (i stopped using python, learning java now). But thanks for the answer. I found a way too. It required less code, and it worked perfectly. So I used True and False to find a solution. All I did was check if the down key was held. If held, Set a variable for the down key to True. If not held/released, set down to False. Then I added if move_down: and added the movement speed. Anyway thanks for the answer, I am sure it will help out a lot of people! \$\endgroup\$ Jan 11 at 10:49
  • \$\begingroup\$ Hey @Command_Blocks, I personally think learning python/pygame is a much better choice to improve you'r programming skills. as it only requires pure code in python to conclude you'r project. but in java ( especially in android studio ) You tend to include/import a thousand of packages which you don't you know nothing about what they're actually doing.(happened for me) . If you want to be a Pro game developer You need experience to make games from scratch . And pygame is a very good option for that. \$\endgroup\$
    – YoloWex
    Jan 11 at 12:56
  • \$\begingroup\$ *questions his choices * Well... if you have done java before and it is very clear you are extremely talented in programming, surely you will know more than me... while other people programming journey starts when they pick up a language, become good at it and then go to the other, mine is entirely different. First HTML for 1.3 yrs. Then python for 2 days. Then c++ for 1 day. then renpy for some months. Then python, again. Then pygame, renpy then java then python then now, java. So I think I will take your word for it and stick to python for a while. \$\endgroup\$ Jan 11 at 13:21
  • \$\begingroup\$ you were right. I just saw some "beginner code" in a book and I'm lost for words. So I have a question, for how long are you doing python now? \$\endgroup\$ Jan 11 at 13:24
  • \$\begingroup\$ It's about 2 years I'm learning python, but I'm moving on to C family because it is more efficient and faster in game developing .@Command_Blocks \$\endgroup\$
    – YoloWex
    Jan 11 at 15:32
1
\$\begingroup\$

Answering for movement in all 4 directions.

  1. Create some variables for movements. For example: moveLeft and moveRight and set them to false (this should be out of the game loop).

  2. Add this to after the for event in pygame.event.get(): loop.

        if event.type == pygame.KEYDOWN:
            # Change the keyboard variables.
            if event.key == K_LEFT or event.key == K_a:
                moveRight = False
                moveLeft = True
            if event.key == K_RIGHT or event.key == K_d:
                moveLeft = False
                moveRight = True
            if event.key == K_UP or event.key == K_w:
                moveDown = False
                moveUp = True
            if event.key == K_DOWN or event.key == K_s:
                moveUp = False
                moveDown = True
        if event.type == pygame.KEYUP:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
            if event.key == K_LEFT or event.key == K_a:
                moveLeft = False
            if event.key == K_RIGHT or event.key == K_d:
                moveRight = False
            if event.key == K_UP or event.key == K_w:
                moveUp = False
            if event.key == K_DOWN or event.key == K_s:
                moveDown = False
        else:
            pass

  1. Now the image I want to move is in the hero variable. Before the game loop, I would add heroX = "X coordinate of hero" and heroY = "Y coordinate of hero. and put these in the screen.blit() of the hero image.

  2. Now finally add this section to the main loop before pygame.Display.update():

if moveDown and heroY < WINDOWHEIGHT:
    heroY += MOVESPEED
if moveUp and heroY > 10:
    heroY -= MOVESPEED
if moveLeft and heroX > 10:
    heroX -= MOVESPEED
if moveRight and heroX < WINDOWWIDTH:
    heroX += MOVESPEED

P.S: WINDOWHEIGHT and WINDOWWIDTH are my display's height and width and MOVESPEED is an integer of movement speed.

Hope this easy fix helped!

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .