#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2015
    Posts
    5
    Rep Power
    0

    moving objects in only one direction at a time


    Hi,

    I am using python 3.4.3 on windows 7 64bit.

    I'm using John M. Zelle graphics module.

    Graphics module:
    Graphics Module Reference

    I am trying to create user movable blocks that can only move in one direction at a time. The arrow keys are used to move left or right.

    Currently while moving left, pressing the right arrow key will change the blocks direction and vice versa. I'm trying to get the block to continue moving in only one direction determined by the arrow keys, i.e. pressing right should not move the blocks right if they already moving left.

    How can I fix my code to do this?

    I expected adding True/False variables (moveLEFT, moveRIGHT) would allow me to disable one key press while another is in action, unfortunately has not worked.

    --> blockgame.py

    Code:
    import graphics
    import game_functions
    import time
    
    def handleKeys(event):
        global direction
        global moveLEFT
        global moveRIGHT
        print('Key pressed', event.keysym, event.keycode)
    
        if event.keysym == 'Left':
            direction = 'Left'
            moveLEFT = True
            moveRIGHT = False
        elif event.keysym == 'Right':
            direction = 'Right'
            moveLEFT = False
            moveRIGHT = True
    
        elif event.keysym == 'q':
            win.close()
    
    def game():
        global direction
        global square
        global moveLEFT
        global moveRIGHT
    
        block = game_functions.GameBlock(WIN_WIDTH//2,
                                         WIN_HEIGHT//2, BLOCK_SIZE,
                                         BLOCK_SIZE, 'Red', None, None, 0)
        block.draw(win)
        square.append(block)
        block = game_functions.GameBlock(WIN_WIDTH//2,
                                         WIN_HEIGHT//2, BLOCK_SIZE,
                                         BLOCK_SIZE, 'Red', None, None, 0)
        block.draw(win)
        square.append(block)
        speed = 0.1
        playing = True
        while playing:
    
            # Move squares
            for k in range(len(square)-1, 0, -1):
                moveX = square[k-1].getCentreX() - square[k].getCentreX()
                moveY = square[k-1].getCentreY() - square[k].getCentreY()
                square[k].move(moveX, moveY)
    
            # Update pos
            if moveLEFT == True and moveRIGHT == False:
                square[0].move(-20, 0)
            if moveRIGHT and moveLEFT == False:
                square[0].move(20, 0)
    
            time.sleep(speed)
    moveLEFT = False
    moveRIGHT = False
    
    WIN_WIDTH = 500
    WIN_HEIGHT = 500
    BLOCK_SIZE = 20
    direction = ""
    square = []
    win = graphics.GraphWin("Snake", WIN_WIDTH, WIN_HEIGHT)
    win.setBackground("white")
    win.bind_all('<Key>', handleKeys)
    game()
    win.mainloop()
    win.getMouse()
    win.close()
    --> game_functions.py

    Code:
    import graphics
    
    class GameBlock():
        def __init__(self, dx, dy, width, height, colour, imageName, blockType, points):
            self.centreX = dx
            self.centreY = dy
            self.width  = width
            self.height = height
            self.colour = colour
            self.imageName = imageName
            self.blockType = blockType
            self.points = points
            self.scrollSpeed = 10
            self.block = graphics.Rectangle(graphics.Point(self.centreX-self.width//2, self.centreY-self.height//2),
                                            graphics.Point(self.centreX+self.width//2, self.centreY+self.height//2))
            self.block.setFill(colour)
            if not(imageName == None):
              self.image = graphics.Image(graphics.Point(dx,dy), imageName)
            else:
              self.image = None
    
        def getCentreX(self):
            return self.centreX
    
        def getCentreY(self):
            return self.centreY
    
        def move(self, dx, dy):
            self.centreX = self.centreX + dx
            self.centreY = self.centreY + dy
            self.block.move(dx,dy)
            if not(self.image == None):
                self.image.move(dx,dy)
    
        def draw(self, canvas):
            if self.image == None:
                self.block.draw(canvas)
            else:
                self.image.draw(canvas)
    __________________________
    I will greatly appreciate any help!
  2. #2
  3. Contributing User
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Aug 2011
    Posts
    5,971
    Rep Power
    510
    You might include another global variable that indicates whether to permit motion changing events.
    Code:
    def handleKeys(event):
        global direction
        global moveLEFT
        global moveRIGHT
        global keysEnabled
        print('Key pressed', event.keysym, event.keycode)
    
        if event.keysym == 'q':
            win.close()
    
        if keysEnabled:
            if event.keysym == 'Left':
                direction = 'Left'
                moveLEFT = True
                moveRIGHT = False
            elif event.keysym == 'Right':
                direction = 'Right'
                moveLEFT = False
                moveRIGHT = True
    
            keysEnabled = False
    I'd wrap these functions and global variables into a class were it my program. The program is still short so I can't see that it matters much, except that you've got this `playing' variable which never changes state to False. Pressing `q' does not terminate the program. I tried a few code variations to stop the program and did not solve the problem. Had to use ^C, or suspend process followed by kill.
    As I recall you're the first person to use graphics module who also included a reference to it. Thank you!
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2015
    Posts
    5
    Rep Power
    0
    Thanks for the reply! This code is a shortened down version of a snake game I'm creating, that's why playing is never false (it is somewhere in the full version).
    I just pulled this part of the program so there is less clutter and so I can work on making the movement only go in one direction.

    I tried adding keysEnabled as a global to permit motion changing events as the code you posted shows. However the blocks still move left or right per arrow click.

    Although if I move "keysEnabled = False" under the first event key ('Left') the 'Right' key is disabled after pressing the left arrow key.
    This is what I'd like it to do, only problem is that the right arrow key does not work even if the block isn't moving left.

    From the blocks starting position if I press the right arrow key I want to to go of the right side of the screen even if I press the left arrow key,
    same for when I press the left arrow key from the blocks starting position. If that makes sense :/

    Code:
    def handleKeys(event):
        global direction
        global moveLEFT
        global moveRIGHT
        global keysEnabled
    
        print('Key pressed', event.keysym, event.keycode)
    
        keysEnabled = True
        if keysEnabled:
            if event.keysym == 'Left':
                direction = 'Left'
                keysEnabled = False
                
        elif event.keysym == 'Right':
            direction = 'Right'
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2015
    Posts
    5
    Rep Power
    0
    I'm not sure if I have to change anything where the code to move the squares is:

    Code:
            # Update pos
            if moveLEFT == True and moveRIGHT == False:
                square[0].move(-20, 0)
            if moveRIGHT and moveLEFT == False:
                square[0].move(20, 0)
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    May 2009
    Posts
    667
    Rep Power
    40
    Every left arrow press enables the left and disables the right, but then a right arrow press will do the opposite until there is another left arrow press. You could also initialize "direction" as "" and then test direction for not equal "Right".
    Code:
        if keysEnabled:
            ## assumes moveLEFT is initially set to True, i.e
            ## initially can move either left or right
            ## moveLEFT will be False if a right arrow was pressed
            if event.keysym == 'Left' and moveLEFT:
                direction = 'Left'
                ##moveLEFT = True   done at startup
                moveRIGHT = False
    Last edited by dwblas; June 11th, 2015 at 05:35 PM.

IMN logo majestic logo threadwatch logo seochat tools logo