Player Movement Troubles

228 views Asked by At

I have tried to make my character move in one direction at a time, and it has worked...kind of. The upward and downward motion of the character is wrong -- it requires the user to hold the W / S / / for the player to move in the up / down direction.

I have no clue why this is occurring, since the left and right motion of the character works fine - that is, the character moves with the user input pressing a button ONCE (A / D / / ). Note that this is Python 2.7.

Code:

 # Import modules

import sys, pygame, os, random, Tkinter, ttk, math
from pygame import *
from random import *
from Tkinter import *
from ttk import *
from math import *

class Application(Frame):

    # Game Menu Setup

    def __init__(self, master):
        Frame.__init__(self,master)
        self.grid()
        self.create_buttons()

    def Collision(self):
        pass 

    def create_buttons(self):

        self.button = Button(self)
        self.button["text"] = "Play Game"
        self.button["command"] = self.Game
        self.button.grid(row=0, column=1)

        self.button1 = Button(self)
        self.button1["text"] = "Help / Instructions"
        self.button1["command"] = self.Instructions
        self.button1.grid(row=0, column=2)

        self.button2 = Button(self)
        self.button2["text"] = "Quit"
        self.button2["command"] = self.Quit
        self.button2.grid(row=0, column=3)

    # Main Class

    def Game(self):

        # Initialise Pygame + Clock

        pygame.init()
        mainClock = pygame.time.Clock()
        pygame.mouse.set_visible(False)

        # Image Setup

        Cursor = pygame.image.load("Cursor.png")
        Food = pygame.image.load("Food.png")
        Background = pygame.image.load("Wallpaper.jpg")

        # Food Setup

        FoodImage = pygame.Surface((20, 20))

        # Music Setup

        pygame.mixer.music.load("Helix Nebula.mp3")

        # Window Setup

        WINDOWHEIGHT = 600 #set standard values
        WINDOWWIDTH = 800
        windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
        pygame.display.set_caption('The Basilisk')

        # Player Drawing

        player = pygame.Rect(50, 50, 50, 50)

        # Movement Variables

        moveLEFT = False
        moveRIGHT = False
        moveUP = False
        moveDOWN = False

        MOVESPEED = 7

        # Score Setup

##        Score = 0
##        print score

        # Game Loop & Events

        while True:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()

                # Change the keyboard variables

                elif event.type == KEYDOWN:                
                    if event.key == K_LEFT or event.key == ord('a'):
                        moveLEFT = True
                        moveRIGHT = False
                        moveUP = False
                        moveDOWN = False
                        movex = 0.5
                        movey = 0
                    if event.key == K_RIGHT or event.key == ord('d'):
                        moveRIGHT = True
                        moveLEFT = False
                        moveUP = False
                        moveDOWN = False
                        movex = -0.5
                        movey = 0
                    if event.key == K_UP or event.key == ord('w'):
                        moveUP = True
                        moveLEFT = False
                        moveRIGHT = False
                        moveDOWN = False
                        movey = 0.5
                        movex = 0
                    if event.key == K_DOWN or event.key == ord('s'):
                        moveDOWN = True
                        moveLEFT = False
                        moveRIGHT = False
                        moveUP = False
                        movey = -0.5
                        movex = 0
                    if event.key == ord('o'):
                        pygame.mixer.music.pause()
                    if event.key == ord('r'):
                        pygame.mixer.music.play()
                    if event.key == ord('p'): 
                        pygame.mixer.music.unpause()
                elif event.type == KEYUP:
                    if event.key == K_ESCAPE:
                        pygame.quit()
                        sys.exit()                        
                    elif event.key == K_LEFT or event.key == ord('a'):
                        moveLEFT = True
                        moveRIGHT = False
                        moveUP = False
                        moveDOWN = False
                    elif event.key == K_RIGHT or event.key == ord('d'):
                        moveRIGHT = True
                        moveLEFT = False
                        moveUP = False
                        moveDOWN = False
                    elif event.key == K_UP or event.key == ord ('w'):
                        moveUP = True
                        moveLEFT = False
                        moveUP = False
                        moveDOWN = False
                    elif event.key == K_DOWN or event.key == ord('s'):
                        moveDOWN = True
                        moveLEFT = False
                        moveUP = False
                        moveDOWN = False

            # Loading Image(s) Setup

            windowSurface.blit(Background, (0,0))
            windowSurface.blit(Food, (15, 15))

            # Player Movement Setup

            if moveDOWN and player.bottom < WINDOWHEIGHT:
                player.top += MOVESPEED
            if moveUP and player.top > 0:
                player.top-= MOVESPEED
            if moveLEFT and player.left > 0:
                player.left -= MOVESPEED
            if moveRIGHT and player.right < WINDOWWIDTH:
                player.right += MOVESPEED

            # Mouse Setup

            mousex, mousey = pygame.mouse.get_pos()
            mousex -= Cursor.get_width()/2
            mousey -= Cursor.get_height()/2

            # Final Update + Character Loading

            pygame.draw.rect(windowSurface, pygame.Color('green'), player)
            windowSurface.blit(Cursor, (mousex, mousey))
            pygame.display.update()
            mainClock.tick(60)

    # Quit Screen

    def Quit(self):

        os._exit(0)

    # Instructions Screen

    def Instructions(self):

        root.title("Instructions")
        root.geometry("260x200")

        app = Frame(root)
        app.grid()

        label_1 = Label(app, text = "The Point of the game is to eat")
        label_2 = Label(app, text = "as many chicks as possible using")
        label_3 = Label(app, text = "the 'Basilisk'. The character controls")
        label_4 = Label(app, text = "the Basilisk using the WASD / arrow keys.")
        label_5 = Label(app, text = "Press the 'Escape' key to exit.")
        label_6 = Label(app, text = "Press the 'o' key to pause the music,")
        label_7 = Label(app, text = "'p' key to unpause the music, and")
        label_8 = Label(app, text = "'r' to restart / play the music.")

        label_1.grid()
        label_2.grid()
        label_3.grid()
        label_4.grid()
        label_5.grid()
        label_6.grid()
        label_7.grid()
        label_8.grid()

# Final Settings for Menu

root = Tk()
root.title("Navigation")
root.geometry("260x25")
app = Application(root)
root.mainloop()

What would happen with the code above is that the player would click the button 'Play Game', the game window would open, and the player would control a green square and move it left, right, up and down.

When the player moves left and right, they only need to press A or D or or ONCE for the square to move left / right. The case for the top and down direction is not the same. The character moves as long the user provides input, that is, the keys W or S or or needs to be held for the square to move in said directions. How can I fix this?

2

There are 2 answers

1
xor On BEST ANSWER

It seems that your event.type==KEYUP: condition is buggy:
you are setting false the up and down movements after setting them true...
Check this code:
see comments in the last two if-else statements

elif event.type == KEYUP:
    if event.key == K_ESCAPE:
        pygame.quit()
        sys.exit()                        
    elif event.key == K_LEFT or event.key == ord('a'):
        moveLEFT = True
        moveRIGHT = False
        moveUP = False
        moveDOWN = False
    elif event.key == K_RIGHT or event.key == ord('d'):
        moveRIGHT = True
        moveLEFT = False
        moveUP = False
        moveDOWN = False
    elif event.key == K_UP or event.key == ord ('w'):
        moveUP = True
        moveLEFT = False
        moveUP = False   ##This line is faulty moveRIGHT=FALSE should be used instead
        moveDOWN = False
    elif event.key == K_DOWN or event.key == ord('s'):
        moveDOWN = True
        moveLEFT = False
        moveUP = False
        moveDOWN = False   ##This line is faulty moveRIGHT=FALSE should be used instead


As a Suggestion:
You can use print statements in the parts of codes where you think the bug can be.
And then track the printed records to see where things are working well and where they are not.
This will give you a fair idea about the bug.
Its part of White Box Testing

0
kazagistar On

It looks like you copied code for continuous movement and tried to adapt it. If you want to just move instantly upon pressing the button, have your KEYDOWN events change the player's position directly.

If you want to animate the movement though, things get more complex: you will have to have 2 states: moving and standing. When standing, you listen for KEYDOWN events, and then trigger a move in the desired direction if there is one. If moving, you ignore KEYDOWN events (or store them for later if you want to get really advanced) and switch again to standing once you arrive at the target square.

Additionally, if you want to support both modes of transit (press key OR hold key) you will have to add additional logic... maybe check pygame.key.get_pressed() to see if you should transition from moving to standing, or just keep moving another square.