Qbasicnews.com

Full Version: RPG Tile Help!
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am having difficulty detecting collisions in my RPG engine. The problem is that all the objects are in integer tiles (for an array), and when I move my character, it sometimes walks into a wall because he isn't *technically* inside a wall until he is completely inside that tile yet. That only happens if you walk down or right because of that technicality. If you walk up or left and hit a wall, it works perfectly due to this same little problem. So I tried comprimising and taking 8 pixels off the location (my tiles and character images are 16x16) and then it works fine as long as you don't mind walking *halfway inside* a wall in any direction Wink

Does anyone know how to fix this problem? To give you a little better idea of the game, the X,Y positions are normal integers, however they are the actual location (not based on the tile position, but rather the pixel position). But then I calculate the tile position from those coordinates, and that's how I check if there is an object in that tile.
Just check differently when moving right or down. This is simple:

HORIZONTAL MOVEMENT:
1.- ¿Is x% MOD tilewidth%=0? If not, that means you are not in the limit of a tile (you are not tile-centered) so you can move without checking.
2.- If x% MOD tilewidth%=0 then you should check. If you are moving left, check map%(tilex%-1, tiley%) [if y% MOD tilewidth%<>0 then your sprite is halfway between two vertical liles and you should check map%(tilex%-1,tiley%+1) also]. ; if you are moving right, check map%(tilex%+1, tiley%) [same thing applies here]. If the tile is walkable, move.

Vertical movement is just the same thing.
nathan, I want your hot bod... Only problem is, I simply don't understand exactly what you are saying... I probably would understand it if I wasn't drunk from that pot, but since I amn't, yes. Please somebody explain what he said for someone drunk on pot to understand easier than eating cake would be for that same exact person. Holy moly!
what he is trying to say, is in your collision detection, make it one more space than you guy is at. EXSadlets make your wall tile 2)

Code:
if map(tilex + 1, tiley) = 2 then
tilex = tilex - 1
end if
if map(tilex - 1, tiley) = 2 then
tilex = tilex + 1
end if
if map(tilex, tiley+1) = 2 then
tiley = tiley - 1
end if
if map(tilex, tiley-1) = 2 then
tiley = tiley + 1
end if

this should help you out.
I'll try to explain it slower (and if you have pot, send it to me, man, I explain things better when I'm weeded):

You have two kinds of coordinates: pixel-perfect coordinates and tile coordinates. Let's say our tiles are 16x16.

In this situation, our character may be whether in a tile-perfect coordinate (for example at (0,0), or (16,16), or (32,64)...) or in a non-tile-perfect coordinate (such as (123,75)...).

Since our character will collide with tiles and it is the size of a tile (16x16, if it is bigger it doesn't care, you consider it the size of a tile. That's what I made on LALA or JILL: it makes your life easier), you only have to check for collisions when your player is in a tile-perfect coordinate. Otherwise, you can move freely, 'cause you know that your player won't collide in the next frame. So you check ONLY when you are in tile-perfect coordinates.

The logics before my mapping collision techniques is: Do I collide if I move? Yes:: don't move. No:: move. I handle the vertical movement first, then the horizontal movement. In a platformer, you usually have vx, and vy to keep track of vertical/horizontal velocities, but I'll try to picture something more simple.

Let's put an example: horizontal movement. Imagine that you have detemined to advance one pixel to the right (for several methods, maybe for a vx = 1 or having pressed RIGHT CURSOR in a linear-movement engine). Those are the checks you have to do in such case:

1.- p.x and p.y are the player's pixel coodinates. xx%=p.x\16 and yy%=p.y\16 are the player's tile coordinates.
2.- We are moving right, so we have to check in the first place wether our player is horizontally-centered on a tile, or, what is the same, (p.x MOD 16) = 0, or, making things faster, (p.x AND 15)=0.
3.- If (p.x AND 15)<>0 then just move: p.x = p.x +1. There is no problem, we won't collide with any tile.
4.- If (p.x AND 15)=0 then it is possible that we collide with a tile if we move right, so we have to perform more checks:
4.1.- Surely we should check the tile at right, but think on this: if the vertical coordinate is not tile-perfect, we can collide with two different tiles:

Code:
XX
PPXX
PPYY
  YY

So we have to check this also:

4.1.1. (p.y AND 15)=0 we are centered vertically:

Code:
PPXX
PPXX

so we just check if map%(yy%,xx%+1)=WALKABLE. If so, we move: p.x=p.x+1

4.1.2. (p.y AND 15)<>0, we are not centered vertically. That way we should check two map positions: if map%(yy%,xx%+1)=WALKABLE and map%(yy%+1,xx%+1)=WALKABLE. If so, we move: p.x=p.x+1

In this simple engine, the player jumps linearly (without gravity) during a number of steps. The player advances right of left at the tap of a key, no matter if it is falling or jumping. There is no horizontal acceleration. Tiles are 16x16. Empty (walkable tile) is 0. You can adapt this stuff as long as you get the logic behind tile collision detection.

This comes inside a SUB which holds the Screen%(MAXY,MAXX) and the p AS PlayerData with x, y and stuff like that.

Code:
' easy and dumb linear jump'n run tile collision engine

SUB MovePh (p AS PlayerData, Screen%())
   DEF SEG = 0
   ' Fall down?
   oldpx% = p.x
   xx% = p.x \ 16   ' Tile coordinates.
   yy% = p.y \ 16
   fall% = 0 ' flag
   IF NOT p.jmp AND yy% < 12 THEN  ' If not jumping, check if we fall
      IF (p.y AND 15) = 0 THEN
         IF (p.x AND 15) = 0 THEN
            IF Screen%(yy% + 1, xx%) = 0 THEN
               p.y = p.y + 1
               fall% = -1
            END IF
         ELSE
            IF Screen%(yy% + 1, xx%) = 0 AND Screen%(yy% + 1, xx% + 1) = 0 THEN
               p.y = p.y + 1
               fall% = -1
            END IF
         END IF
      ELSE
         p.y = p.y + 1
         fall% = -1
      END IF
   END IF
   ' Move
   yy% = p.y \ 16   ' p.y might have changed, so we recalc yy%
   IF (PEEK(1047) AND 4) THEN       ' Left = CONTROL key
      p.facing = 1
      p.ct = p.ct + 1
      IF (p.x AND 15) = 0 THEN
         IF xx% > 0 THEN
            IF (p.y AND 15) = 0 THEN
               IF Screen%(yy%, xx% - 1) = 0 THEN
                  p.x = p.x - 1
               END IF
            ELSE
               IF Screen%(yy%, xx% - 1) = 0 AND Screen%(yy% + 1, xx% - 1) = 0 THEN
                  p.x = p.x - 1
               END IF
            END IF
         ELSE
            IF p.x > 0 THEN p.x = p.x - 1
         END IF
      ELSE
         IF p.x > 0 THEN p.x = p.x - 1
      END IF
   END IF

   IF (PEEK(1047) AND 8) THEN       ' Right
      p.facing = 0
      p.ct = p.ct + 1
      IF (p.x AND 15) = 0 THEN
         IF xx% < 16 THEN
            IF (p.y AND 15) = 0 THEN
               IF Screen%(yy%, xx% + 1) = 0 THEN
                  p.x = p.x + 1
               END IF
            ELSE
               IF Screen%(yy%, xx% + 1) = 0 AND Screen%(yy% + 1, xx% + 1) = 0 THEN
                  p.x = p.x + 1
               END IF
            END IF
         ELSE
            IF p.x < 304 THEN p.x = p.x + 1
         END IF
      ELSE
         IF p.x < 304 THEN p.x = p.x + 1
      END IF
   END IF

   IF (PEEK(1047) AND 1) OR (PEEK(1047) AND 2) THEN  ' SHIFT=jump
      IF (p.y AND 15) = 0 THEN
         IF yy% < 12 THEN
            IF (p.x AND 15) = 0 THEN
               IF Screen%(yy% + 1, xx%) <> 0 THEN
                  p.jmp = -1
                  p.ctJmp = 0
               END IF
            ELSE
               IF Screen%(yy% + 1, xx%) <> 0 OR Screen%(yy% + 1, xx% + 1) <> 0 THEN
                  p.jmp = -1
                  p.ctJmp = 0
               END IF
            END IF
         ELSE
            p.jmp = -1
            p.ctJmp = 0
         END IF
      END IF
   END IF
  
   ' Calculate frame: (ignore this, just to calculate which sprite should I display)
   IF p.jmp OR fall% THEN
      IF p.facing = 0 THEN
         p.spr1 = "GH"
         p.spr2 = "KL"
      ELSE
         p.spr1 = "AB"
         p.spr2 = "EF"
      END IF
   ELSE
      IF p.ct >= 5 THEN p.ct = 0: p.frame = NOT p.frame: AdlibFX 0
      IF p.facing = 0 THEN
         p.spr1 = "GH"
         IF p.frame THEN p.spr2 = "IJ" ELSE p.spr2 = "KL"
      ELSE
         p.spr1 = "AB"
         IF p.frame THEN p.spr2 = "CD" ELSE p.spr2 = "EF"
      END IF
   END IF
  
   ' Jump
   IF p.jmp THEN
      xx% = p.x \ 16
      p.ctJmp = p.ctJmp + 1   ' jump counter
      IF p.ctJmp = 41 THEN p.jmp = 0
      IF (p.y AND 15) = 0 AND yy% > 0 THEN
         IF (p.x AND 15) = 0 THEN
            IF Screen%(yy% - 1, xx%) = 0 THEN
               p.y = p.y - 1
            END IF
         ELSE
            IF Screen%(yy% - 1, xx%) = 0 AND Screen%(yy% - 1, xx% + 1) = 0 THEN
                  p.y = p.y - 1
            END IF
         END IF
      ELSE
         IF p.y > 0 THEN p.y = p.y - 1
      END IF
   END IF
  
   DEF SEG
END SUB
Quote:what he is trying to say, is in your collision detection, make it one more space than you guy is at. EXSadlets make your wall tile 2)

Code:
if map(tilex + 1, tiley) = 2 then
tilex = tilex - 1
end if
if map(tilex - 1, tiley) = 2 then
tilex = tilex + 1
end if
if map(tilex, tiley+1) = 2 then
tiley = tiley - 1
end if
if map(tilex, tiley-1) = 2 then
tiley = tiley + 1
end if

this should help you out.

Thank you but what he's asking is so much more complicated. I did what you said and that is where I come across the problem.
Hey man, read my post! It took so long to write :lol:
Quote:Hey man, read my post! It took so long to write :lol:

I saved it to file so I can look at it when I get home, which is when I have all the time in the world...