Problem with tile based movement

Previous topic - Next topic

Leon

Hello, I have a problem with the following code, which is supposed to make my character move tile per tile (for example the character can't walk 1 or 2 pixels but always predefined distances).
However, it sometimes happens that the player doesn't stop walking for some time even if I don't press any buttons.

Code (glbasic) Select

GLOBAL startXorY2 = FALSE
GLOBAL Dir = 1

TYPE character
x
y
w
h
moving


FUNCTION init:
self.x = 200
self.y = 200
self.w = 50
self.h = 50
self.moving = FALSE
ENDFUNCTION

FUNCTION draw:
DRAWRECT self.x, self.y, self.w, self.h, RGB(100,200,50)
ENDFUNCTION

FUNCTION move: speed, distance, direction, startXorY
IF startXorY2=FALSE
startXorY2=startXorY
ENDIF


IF direction = 0
IF startXorY2-distance< self.x-speed
DEC self.x, speed
self.moving = TRUE
ELSE
startXorY2 = FALSE
direction = ""
self.moving = FALSE
ENDIF
ENDIF
IF direction = 1
IF startXorY2+distance>self.x+speed
INC self.x, speed
self.moving = TRUE
ELSE
startXorY2 = FALSE
direction = ""
self.moving = FALSE
ENDIF
ENDIF

IF direction = 2
IF startXorY2+distance> self.y+speed
INC self.y, speed
self.moving = TRUE
ELSE
startXorY2 = FALSE
direction = ""
self.moving = FALSE
ENDIF
ENDIF

IF direction = 3
IF startXorY2-distance< self.y-speed
DEC self.y, speed
self.moving = TRUE
ELSE
startXorY2 = FALSE
direction = ""
self.moving = FALSE
ENDIF
ENDIF
ENDFUNCTION
ENDTYPE


GLOBAL player AS character
player.init()


LOOP:
checkForPressedKey()
player.draw()

IF Dir = 0 OR Dir = 1
player.move(2, 32, Dir, player.x)
ELSE
player.move(2, 32, Dir, player.y)
ENDIF

IF KEY(57)=1
END
ENDIF
PRINT Dir,20,20

  SHOWSCREEN
GOTO LOOP

FUNCTION checkForPressedKey:
IF KEY(203)=1
Dir = 0
ELSEIF KEY(205)=1
Dir = 1
ELSEIF KEY(208)=1
Dir = 2

ELSEIF KEY(200)=1
Dir = 3
ELSE
  IF player.moving = FALSE
Dir = -1
   ENDIF
ENDIF
ENDFUNCTION


spacefractal: Just added code tag for easier reading

dreamerman

Get rid of 'startXorY2', or in other words don't use it in such way.
Code (glbasic) Select
GLOBAL startXorY2 = FALSE
GLOBAL Dir = 1

TYPE character
   x%
   y%
   w%
   h%
   moving%
   start_x%
   start_y%
   
   
   FUNCTION init:
      self.x = 200
      self.y = 200
      self.w = 50
      self.h = 50
      self.moving = FALSE
   ENDFUNCTION
   
   FUNCTION draw:
      DRAWRECT self.x, self.y, self.w, self.h, RGB(100,200,50)
   ENDFUNCTION

   FUNCTION move: speed, distance, direction, startXorY
      IF self.moving=FALSE
         self.start_x = self.x
         self.start_y = self.y
      ENDIF
     
     
      IF direction = 0
         IF self.start_x-distance< self.x-speed
            DEC self.x, speed
            self.moving = TRUE
         ELSE
            //startXorY2 = FALSE
            direction = ""
            self.moving = FALSE
         ENDIF
      ENDIF
      IF direction = 1
         IF self.start_x+distance>self.x+speed
            INC self.x, speed
self.moving = TRUE
         ELSE
            //startXorY2 = FALSE
            direction = ""
            self.moving = FALSE
         ENDIF
      ENDIF
     
      IF direction = 2
         IF self.start_y+distance> self.y+speed
            INC self.y, speed
self.moving = TRUE
         ELSE
            //startXorY2 = FALSE
            direction = ""
            self.moving = FALSE
         ENDIF
      ENDIF
     
      IF direction = 3
         IF self.start_y-distance< self.y-speed
            DEC self.y, speed
            self.moving = TRUE
         ELSE
            startXorY2 = FALSE
            direction = ""
            self.moving = FALSE
         ENDIF
      ENDIF
   ENDFUNCTION
ENDTYPE


GLOBAL player AS character
player.init()


LOOP:
   checkForPressedKey()
   player.draw()
   
   IF Dir = 0 OR Dir = 1
      player.move(2, 64, Dir, player.x)
   ELSEIF (Dir = 2 OR Dir = 3)
      player.move(2, 64, Dir, player.y)
   ENDIF
   
   IF KEY(57)=1
      END
   ENDIF
   PRINT Dir,20,20
   
  SHOWSCREEN
GOTO LOOP

FUNCTION checkForPressedKey:
   IF KEY(203)=1
      Dir = 0
   ELSEIF KEY(205)=1
      Dir = 1
   ELSEIF KEY(208)=1
      Dir = 2
   ELSEIF KEY(200)=1
      Dir = 3
   ELSE
     IF player.moving = FALSE
      Dir = -1
      ENDIF
   ENDIF
ENDFUNCTION

But this way is still faulty, as you can interrupt moving in one direction and start moving in another, either use moving/drawing really based on tiles, or set moving direction in character type, that could be changed only in player isn't moving (new move only after last is done).
Check my source code editor for GLBasic - link Update: 20.04.2020

Ian Price

Make sure that you can only press a key once a character has stopped moving, whether it's a change of direction or not.
I came. I saw. I played.

Slydog

Also, try using integers when they are called for.
Not sure if floating point inaccuracies will be a problem if you don't, but it's good practgice so you know what variables are meant to be floats and which integers. 
A float value of 2.0 may actually be 1.999999999, so equal comparisons will fail.

The '%' characters specifies an integers, like dreamerman did:
Code (glbasic) Select
TYPE character
   x%
   y%
...
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Leon

Thanks :)
I'll give it a try (and implement your tips)!