1

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()


```

  • 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? – DMGregory Jan 03 '22 at 15:16
  • @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. – Command_Blocks Jan 03 '22 at 16:00
  • 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? – DMGregory Jan 03 '22 at 16:24
  • 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? – Command_Blocks Jan 04 '22 at 03:26
  • Sounds like you should edit your question to show what you tried. – DMGregory Jan 04 '22 at 03:41
  • @DMGregory I did not try anything, I was just "curious". Anyway, after watching many tutorials on pygme, I got it. All you needed to do was create some variables like "leftPressed" and by default set it to false. and in pygame.KEYDOWN: set it to True. Then in pygame.KEYUP set it to False. and then create a movement block for the object use if leftPressed and then use the desired movement. It is very smooth. I am also going to answer my own question for this as not many people ask this question. – Command_Blocks Jan 04 '22 at 12:28

2 Answers2

2

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

```

liggiorgio
  • 4,636
  • 6
  • 25
  • 37
YoloWex
  • 136
  • 4
  • 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! – Command_Blocks Jan 11 '22 at 10:49
  • 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. – YoloWex Jan 11 '22 at 12:56
  • 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. – Command_Blocks Jan 11 '22 at 13:21
  • 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? – Command_Blocks Jan 11 '22 at 13:24
  • 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 – YoloWex Jan 11 '22 at 15:32
  • Oh the c family... I tried c++ but the loops are very confusing. I managed to make a calculator tho. Anyway good luck – Command_Blocks Jan 12 '22 at 03:11
  • I don't think you will ever use this but this website has some great programming books, 100% free. I have been using it for a while now: https://z-lib.org

    P.S: It might crash frequently, but ignore these errors and try again.

    – Command_Blocks Jan 12 '22 at 03:32
1

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!

DMGregory
  • 134,153
  • 22
  • 242
  • 357