GLBasic forum

Main forum => GLBasic - en => Topic started by: Leon on 2016-Aug-12

Title: Problem with tile based movement
Post by: Leon on 2016-Aug-12
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
Title: Re: Problem with tile based movement
Post by: dreamerman on 2016-Aug-12
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).
Title: Re: Problem with tile based movement
Post by: Ian Price on 2016-Aug-12
Make sure that you can only press a key once a character has stopped moving, whether it's a change of direction or not.
Title: Re: Problem with tile based movement
Post by: Slydog on 2016-Aug-12
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%
...
Title: Re: Problem with tile based movement
Post by: Leon on 2016-Aug-12
Thanks :)
I'll give it a try (and implement your tips)!