2
\$\begingroup\$

I'm trying to make my character move around a tile map with collisions. Everything works fine except for one thing. I show you a picture with the problem:

https://i.sstatic.net/ZWI7x.jpg

That is, when I reach a tile above then I can not move anywhere. If you come from the left, I can not move either up or down. If you reach the bottom, I can move to the left but not right. And when you reach the right I can move in any direction.

Honestly I have no idea what may be failing. I think it has to do with if (...), because if I change the order, the addresses where I can move change :/

Here I leave some code:

boolean collision = false;

if(Keyboard.isKeyDown(Keyboard.KEY_UP)) {
    for(int i = 0; i < map.GetNumLayers(); i++) {
        if(UpTile(map, i) > 128) {
            collision = true;
        }
    }

    if(!collision) AddPos(0.0f, -vel);
}
if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
    for(int i = 0; i < map.GetNumLayers(); i++) {
        if(LeftTile(map, i) > 128) {
            collision = true;
        }
    }

    if(!collision) AddPos(-vel, 0.0f);
}
if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
    for(int i = 0; i < map.GetNumLayers(); i++) {
        if(DownTile(map, i) > 128) {
            collision = true;
        }
    }

    if(!collision) AddPos(0.0f, vel);
}
if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
    for(int i = 0; i < map.GetNumLayers(); i++) {
        if(RightTile(map, i) > 128) {
            collision = true;
        }
    }

    if(!collision) AddPos(vel, 0.0f);
}

public int UpTile(Map map, int layer) {
    return map.GetValue(layer, (int) (x/size), (int) (y/size));
}

public int LeftTile(Map map, int layer) {
    return map.GetValue(0, (int) (x/size), (int) (y/size));
}

public int DownTile(Map map, int layer) {
    return map.GetValue(layer, (int) (x/size), (int) (y/size + 1));
}

public int RightTile(Map map, int layer) {
    return map.GetValue(layer, (int) (x/size + 1), (int) (y/size));
}

public int GetValue(int layer, int x, int y) {
    return array[layer][y][x];
}

The map is an array with 3 componentes: [LAYER][Y][X]. So, in RightTile by example, with GetValue, I'm getting the value from the array in the position [layer][y/size][x/size + 1], x/size + 1 because I want to get the kind of tile that is to my right (same with the others). size = 64, that is the width and height of each tile.

Thanks >.<

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Did you try to use your debugger and just step through the code when that happens? \$\endgroup\$ Commented Jul 3, 2011 at 14:14

2 Answers 2

4
\$\begingroup\$

The upper right of the shown screens is misleading, you are only prevented from moving right in that situation if you try to move down at the same time. The reason that trying to move in another direction can block your movement is that you don't reset you variable collision to false between checks, thus as soon as one direction has set it to true it will it will block the following move directions.

Take a visual glance at what points you are actually checking, the upper left corner of your character twice, the upper right, and the lower left. Seems like a strange pattern, right?

To get things working as you'd want them in a simple fashion I suggest you use an 8 points method, 2 points for each direction, positioned at the corners of your character, moved out at least as far as the maximum moving speed.


Left: Current test. Right: Suggested test.

\$\endgroup\$
1
  • \$\begingroup\$ Yep, that another problem I had. I have fixed it doing what you say. I have changed all the *Tile method to check the 2 corners of each side. So, here is the full code: pastebin.com/8RZLvYZ1 Now it works fine and there isn't any kind of stuck :D Thank you very much! \$\endgroup\$
    – Kactung
    Commented Jul 3, 2011 at 18:01
2
\$\begingroup\$

I agree with Maik - debugging will help you here.

To do this you could walk to the top of the screen, then insert a breakpoint after:

if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {

And then press left and follow your code through to see if it does what you think it does. My best bet is that there is a problem indexing the map array; you should verify that the coordinates that are accessed are the correct coordinates.

I did notice some things that could potentially be the cause:

You said the map is an array with three components: [LAYER][Y][X] but then your calls to GetValue index in another order: LAYER, X, Y (although I guess your GetValue function probably does switch those around).

Also I'm not sure why you are doing (x/size) in UpTile/DownTile/RightTile/LeftTile - if x is smaller than 64 (and is an int) you'll get 0.

Also, I presume:

public int LeftTile(Map map, int layer) {
    return map.GetValue(0, (int) (x/size), (int) (y/size));
}

should be:

public int LeftTile(Map map, int layer) {
    return map.GetValue(layer, (int) (x/size), (int) (y/size));
}
\$\endgroup\$
6
  • \$\begingroup\$ +1 for debugging, programming without using a debugger is like riding a bike without wheels, you just dont get very far without \$\endgroup\$ Commented Jul 3, 2011 at 14:46
  • \$\begingroup\$ Thank you both. For parts: that of LeftTile is that I was doing test and I had forgotten to change the 0 to layer =P. I updated the question with the definition of GetValue, so there is no trouble. Another thing, I divide x/size to get the tile in which the character is located: for example, 23/64 = 0 (tile 0), 64/64 = 1 (tile 1), 80/64 = 1 (tile 1), 128/64 = 2 (tile 2), etc so I think it is correct. I've debugged and I get this i.imgur.com/s7g6D.png So it thinks the left and right tiles are collided :/ \$\endgroup\$
    – Kactung
    Commented Jul 3, 2011 at 15:33
  • \$\begingroup\$ @Puyover, that looks good, now also print the calculated indices and the x,y position \$\endgroup\$ Commented Jul 3, 2011 at 15:37
  • 1
    \$\begingroup\$ @Maik Semder, Oks, i.imgur.com/i8jsf.png By the way I solved the pj stucks upon reaching the tiles subtracting 1 pixel to the X in LeftTile and subtracting 1 pixel to the Y in UpTile. You can see in the picture that there are no problems go to the right or left. However, if I'm in that position by pressing the up arrow while the left or right are pressed, does not move, I have to release the up key to move. With the other directions happens same. I think it may be the keyboard buffer. I will do some tests to see. Thank you! \$\endgroup\$
    – Kactung
    Commented Jul 3, 2011 at 15:49
  • \$\begingroup\$ Well, I know where is the error of this last. When you enter ManageMovement method, it's checks if(...) one by one, so if you press up and then press right or left, only the first if(...) is checked so the other keys are missed. I think it will be solved by changing the implementation of reading the keyboard, so it's not a major problem. Thanks for the help! \$\endgroup\$
    – Kactung
    Commented Jul 3, 2011 at 15:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .