Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Bug with collision detection with Tiled(LWJGL & Slick2D)  (Read 628 times)
0 Members and 1 Guest are viewing this topic.
Offline Zarkopafilis

Senior Newbie





« Posted 2013-12-26 10:32:47 »

Information:
The tiled map and player : http://prntscr.com/2c445u . I tried to make some kind of pixel-precise movement
It is weird because I can achieve stuff like this sometimes : http://prntscr.com/2c44px

I can not figure out how to prevent these bugs..(It needs to works with more maps too...)I believe that the whole issue is caused by the way I calculate tileX and tileY (player's positions @ grid. Is there a better way?)

This thing(in pic) only happens when I try to move left or right and I am in the middle of 2 tiles. Is there any way to prevent that?

(I am not a noob with java. Its just the fact that I am now taking my first steps in game-dev.)
Here is the full code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
//packet
//imports
public class LevelOne extends BasicGameState{

public int state;
boolean esc;
Input input;

private TiledMap map;

private float x,y,vel;


public LevelOne(int state){
    this.state = state;
}

@Override
public void init(GameContainer arg0, StateBasedGame arg1)
        throws SlickException {
      esc = false;
      map = new TiledMap("res/map/map.tmx");

      x = 2 * 32;
      y = 1 * 32;
      vel = .1f;
}

@Override
public void render(GameContainer arg0, StateBasedGame arg1, Graphics g)
        throws SlickException {
        map.render(0, 0);

        g.fillRect(x, y, 32, 32);

}

@Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
        throws SlickException {
    input = gc.getInput();
    if(esc){
        Mouse.setGrabbed(false);

    }else{
        Mouse.setGrabbed(true);
    }
        if(input.isKeyPressed(Input.KEY_ESCAPE)){
            esc = true;
        }  
    if(esc){
        Mouse.setGrabbed(false);
            if(input.isKeyPressed(Input.KEY_R)){
                esc = false;
            }else if(input.isKeyPressed(Keyboard.KEY_Q)){
                System.exit(0);
            }else if(input.isKeyPressed(Keyboard.KEY_M)){
                esc = false;
                sbg.enterState(0);
                Mouse.setGrabbed(false);
            }
        }

    int objLayer = map.getLayerIndex("Objects");

    int tileX = (int)(x + 1)/ 32;
    int tileY = (int)(y + 1)/ 32;

    System.out.println(tileX +"   "+ tileY);

    //TODO -- FIX COLLISIONS

    if(input.isKeyDown(Input.KEY_RIGHT)){
        if(map.getTileId(tileX+1, tileY, objLayer) == 0){
            x+= vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_LEFT)){

        tileX++;

        if(map.getTileId(tileX-1, tileY, objLayer) == 0){
            x-= vel * delta;
        }

        tileX--;

    }

    if(input.isKeyDown(Input.KEY_UP)){

        tileY++;

        if(map.getTileId(tileX, tileY-1, objLayer) == 0){
            y-= vel * delta;
        }

        tileY--;

    }

    if(input.isKeyDown(Input.KEY_DOWN)){
        if(map.getTileId(tileX, tileY+1, objLayer) == 0){
            y += vel * delta;
        }
    }

        }

@Override
public int getID() {
    return state;
}
}

Thanks in advance
Offline Axeman

Senior Duke


Medals: 7



« Reply #1 - Posted 2013-12-26 19:44:28 »

This doesn´t look right. There are no bounding box checks, you´re just checking if the neighbouring tiles are empty and if they are the player is allowed to move. I would suggest storing all unwalkable tiles in an array and check all tiles around you. If there are any unwalkable tiles you do a bounding box check and if there is a collision/intersection you deal with the respons.

A lot have been written about AABB ("axis aligned bounding box") in the forum so do a search for that and I´m guessing that Slick has it´s own "rectangle intersect" function that is good to go. And there was a similar question some time ago when I wrote this answer: http://www.java-gaming.org/topics/aabb-collision-detection-fails-when-moving-to-the-left/31443/msg/292675/view.html#msg292675
Offline trollwarrior1
« Reply #2 - Posted 2013-12-26 20:21:33 »

Take a look at this

http://www.java-gaming.org/topics/2d-collision-detection/31488/view.html
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Zarkopafilis

Senior Newbie





« Reply #3 - Posted 2013-12-26 20:38:30 »

I think I have got it now , thanks! Anyways , Axis Aligned Bounding Box. Have seen that term. Translating to my language doesnt help...
Offline Axeman

Senior Duke


Medals: 7



« Reply #4 - Posted 2013-12-26 21:00:18 »

"Axis aligned bounding box" is fancy talk for "rectangle", basically. Smiley It´s the rectangle you use to check collision/intersections against objects.

"Axis aligned" means its sides are parallel with the x and y axis, or in other words it´s not rotated. Like this: http://documentation.flatredball.com/frb/docs/images/a/a2/AxisAligned.png. "Bounding box" is, well, a rectangle. Smiley Most people just call it AABB and it´s a good word to remember since it´s used a lot.
Offline Zarkopafilis

Senior Newbie





« Reply #5 - Posted 2013-12-27 21:34:29 »

This doesn´t look right. There are no bounding box checks, you´re just checking if the neighbouring tiles are empty and if they are the player is allowed to move. I would suggest storing all unwalkable tiles in an array and check all tiles around you. If there are any unwalkable tiles you do a bounding box check and if there is a collision/intersection you deal with the respons.


After a rethink , I do not get this one. Indeed slick has it's own Box(Bounding) and intersects/contains methods , but , what am I supposed to check?
What I think I need to check:
Check the three nearby tiles (left/right/up/down depending at the direction the player wants to move) and then determine if he is allowed to move onto that direction by checking if
A)All 3 tiles are not blocked
B)the center tile is not blocked and the player does /does not intersect with the 2 others
C)The center tile is blocked

Is this the proper way to do this?
Offline Zarkopafilis

Senior Newbie





« Reply #6 - Posted 2013-12-29 15:41:26 »

This doesn´t look right. There are no bounding box checks, you´re just checking if the neighbouring tiles are empty and if they are the player is allowed to move. I would suggest storing all unwalkable tiles in an array and check all tiles around you. If there are any unwalkable tiles you do a bounding box check and if there is a collision/intersection you deal with the respons.

A lot have been written about AABB ("axis aligned bounding box") in the forum so do a search for that and I´m guessing that Slick has it´s own "rectangle intersect" function that is good to go. And there was a similar question some time ago when I wrote this answer: http://www.java-gaming.org/topics/aabb-collision-detection-fails-when-moving-to-the-left/31443/msg/292675/view.html#msg292675


Second attempt:

 I still face a few issues with the tiles.(http://prntscr.com/2evl5c) e.g. -> http://prntscr.com/2evl92 , http://prntscr.com/2evlg6 , http://prntscr.com/2evll1


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
public int[][] obj; //store each tile's id of the object layer here

private TiledMap map;

private float x,y,vel, TILE_SIZE;//x position , y position ,velocity, tile size in pixels

private Sound jump;//nevermind

public boolean cLeft,cRight,cUp,cDown;//c(anMove)Left/Right/Down etc

public LevelOne(int state){
    this.state = state;//constructor to pass the
}

@Override
public void init(GameContainer arg0, StateBasedGame arg1)
        throws SlickException {
      TILE_SIZE = 32;//initialization
      esc = false;
      map = new TiledMap("res/map/map.tmx");
      cUp = false;
      cDown = false;
      cLeft = false;
      cRight = false;
      x = 2 * TILE_SIZE;//see the map
      y = 1 * TILE_SIZE;
      vel = .1f;
      objLayer = map.getLayerIndex("Objects");//get the layer
      jump = new Sound("res/sound/jump.wav");

      obj = new int[10][10];//initialize the 2d array to store the blocked tiles

      for(int col = 0; col < 10;col++){
          for(int row = 0;row < 10;row++){
              obj[col][row] = map.getTileId(col, row, objLayer);
          }
      }
}

@Override
public void render(GameContainer arg0, StateBasedGame arg1, Graphics g)
        throws SlickException {
        map.render(0, 0);//render only the map and a white rectangle (player)

        g.fillRect(x, y, TILE_SIZE, TILE_SIZE);

}

@Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
        throws SlickException {
    input = gc.getInput();//get input
    if(esc){//somehting about the menu , ignore it!
        Mouse.setGrabbed(false);

    }else{
        Mouse.setGrabbed(true);
    }
        if(input.isKeyPressed(Input.KEY_ESCAPE)){
            esc = true;
        }  
    if(esc){
        Mouse.setGrabbed(false);
            if(input.isKeyPressed(Input.KEY_R)){
                esc = false;
            }else if(input.isKeyPressed(Keyboard.KEY_Q)){
                System.exit(0);
            }else if(input.isKeyPressed(Keyboard.KEY_M)){
                esc = false;
                sbg.enterState(0);
                Mouse.setGrabbed(false);
            }
        }


    //calculate collisions
    AABB();



    //TODO -- FIX COLLISIONS , thats what we need to do :/

    if(input.isKeyDown(Input.KEY_RIGHT)){//arrow keys, check if player can move and decide, see AABB() method!
        if(cRight){
            x += vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_LEFT)){
        if(cLeft){
            x -= vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_UP)){
        if(cUp){
            y -= vel * delta;
        }
    }

    if(input.isKeyDown(Input.KEY_DOWN)){
        if(cDown){
            y += vel * delta;
        }
    }

        }

@Override
public int getID() {//get the id of the class
    return state;
}

private void AABB(){

    cLeft = false;//re-initialize
    cRight = false;
    cUp = false;
    cDown = false;

    tileX = (int) Math.round(Math.ceil(x / TILE_SIZE));//get the tile of the player
    tileY = (int) Math.round(Math.ceil(y / TILE_SIZE));

    int diffX = (int) Math.round(Math.ceil(x % TILE_SIZE));//get the remainder , sorry for the name
    int diffY = (int) Math.round(Math.ceil(y % TILE_SIZE));

    int HALF_TILE_SIZE = 32 / 2;//get half the tile size

    //Start handling collisions

    if(diffX == HALF_TILE_SIZE){//if the player is actually on a number that can be divided by 32 without remainder , do a simple up/down check
        if(obj[tileX][tileY - 1] == 0){
            cUp = true;
        }  
        if(obj[tileX][tileY + 1] == 0){
            cDown = true;
        }
    }else{
        if(diffX > HALF_TILE_SIZE){//if it is not , check the other nearby squares.Here because diffX > HALF_TILE_SIZE , I get the one near these tiles. its obj[numberoftilex][numberoftiley] to get the tile's id. it returns 0 if it is empty.
            if(obj[tileX][tileY - 1] == 0 && obj[tileX + 1][tileY - 1] == 0){
                cUp = true;
            }
            if(obj[tileX][tileY + 1] == 0 && obj[tileX + 1][tileY + 1] == 0){
                cDown = true;
            }
        }else if(diffX < HALF_TILE_SIZE){
            if(obj[tileX][tileY - 1] == 0 && obj[tileX - 1][tileY - 1] == 0){
                cUp = true;
            }
            if(obj[tileX][tileY + 1] == 0 && obj[tileX - 1][tileY + 1] == 0){
                cDown = true;
            }
        }
    }
    //same things done with X are done with Y
    if(diffY == HALF_TILE_SIZE){
        if(obj[tileX - 1][tileY] == 0){
            cLeft = true;
        }

        if(obj[tileX + 1][tileY] == 0){
            cRight = true;
        }
    }else{
        if(diffY > HALF_TILE_SIZE){
            if(obj[tileX - 1][tileY] == 0 && obj[tileX - 1][tileY - 1] == 0){
                cLeft = true;
            }
            if(obj[tileX + 1][tileY] == 0 && obj[tileX + 1][tileY - 1] == 0){
                cRight = true;
            }
        }else if(diffY < HALF_TILE_SIZE){
            if(obj[tileX - 1][tileY] == 0 && obj[tileX - 1][tileY + 1] == 0){
                cLeft = true;
            }
            if(obj[tileX + 1][tileY] == 0 && obj[tileX + 1][tileY + 1] == 0){
                cRight = true;
            }
        }


    }

}
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (46 views)
2014-10-17 03:59:02

Norakomi (37 views)
2014-10-16 15:22:06

Norakomi (29 views)
2014-10-16 15:20:20

lcass (32 views)
2014-10-15 16:18:58

TehJavaDev (62 views)
2014-10-14 00:39:48

TehJavaDev (62 views)
2014-10-14 00:35:47

TehJavaDev (52 views)
2014-10-14 00:32:37

BurntPizza (70 views)
2014-10-11 23:24:42

BurntPizza (40 views)
2014-10-11 23:10:45

BurntPizza (82 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!