Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (535)
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  
  Tiled Level Collision Help  (Read 805 times)
0 Members and 1 Guest are viewing this topic.
Offline _Scyth_

Junior Member





« Posted 2013-01-15 19:59:39 »

I have a tiled level, which is expressed as:
1  
2  
int[][] level1 = {{1,0,0,0,0,0,1,1},
                       {1,0,0,0,0,0,0,1};

etc

I then render the tiles with code from mattheus Smiley
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
 // Render the Level
    public void renderTiles(Graphics g) {
         // Iterate through all tiles:
        for (int y = 0; y < level1.length; y++) {
               for (int x = 0; x < level1[y].length; x++) {
               renderTile(x, y, level1[y][x], g);
            }
         }
      }
     public void renderTile(int x, int y, int tileID, Graphics g) {
           switch (tileID) {
           // don't forget the breaks! :)
          case 0: g.setColor(Color.BLACK); g.fillRect(x * 16, y * 16, 16, 16); break;
           case 1: g.setColor(Color.GREEN); g.fillRect(x * 16, y * 16, 16, 16); break;
           }
      }


My player info:
1  
int playerX = 16, playerY = 16;


how can I check collision between the player and the tiles which are 1?

I've tried, some different methods:
  • Surround wall tiles in a Rectangle each the player in a Rectangle and check for collision between them. But I needed to use an array of Rectangles, and I hit the problem: i had to define what [] is for the .intersects() method.
  • I tried checking if playerX and playerY were 'Beside' a wall so that it wouldn't allow them to move, again, I think I need to define what tile I'm comparing them to.

Anyone have any suggestions I can try?
Offline krasse
« Reply #1 - Posted 2013-01-15 20:15:10 »

If you assume that the player is a rectangle, it is pretty easy to check collisions within a grid. Just get the grid index from the (minX, minY) and (maxX, maxY) points for the player and iterate over those cells to check if they are occupied in your tile map.

Also, when the player moves you also want to perform several checks that the player doesn't move into an occupied cell in the next tick.
Also, if you allow diagonal movement, you would like to know if the player can move in one direction (either x or y) only to avoid that it just stops when diagonally moving into a wall.

Offline krasse
« Reply #2 - Posted 2013-01-15 20:17:57 »

You don't need to specify rectangles for each cell. You just need to know the total grid size, it's start position and the number of cells in each direction. Then you can calculate all the rectangles with some very simple math.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline _Scyth_

Junior Member





« Reply #3 - Posted 2013-01-15 20:29:46 »

First, what do you mean by minX minY and maxX and maxY of player? Would that be 0,0 and say 320,240.

any tips on how to do the Rectangles?

and what math? I'm completely confuzzled
Offline krasse
« Reply #4 - Posted 2013-01-15 21:52:40 »

Is the player a point or has it some width or height? If it is a point then you can just ignore the minX, minY etc and just use playerX and playerY instead.

Is the player supposed to move in steps of whole cells or can it move a fraction of a cell? If it can just move in whole grid cells you can just perform a simple array[playerY][playerX] (with bounds checking). If it can move within fractions of cells, the player can overlap several cells at the same time. You need to check what cells that the player overlaps and then you need to know the size of the cells.

Here is some code where I assume that the level starts at position (0, 0) and the player position is at center of the player rectangle.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
int startCellX = (int) Math.floor((playerX - playerWidth * 0.5) / cellWidth);
int startCellY = (int) Math.floor((playerY - playerHeight * 0.5) / cellHeight);
int endCellX = (int) Math.ceil((playerX + playerWidth * 0.5) / cellWidth);
int endCellY = (int) Math.ceil((playerY + playerHeight * 0.5) / cellHeight);

for (int i=startCellX; i<=endCellX; i++) {
  for (int j=startCellY; j<=endCellY; j++) {
    // Check if level1[j][i] is occupied here, if so, the player intersects something
 }
}


You also have to add some checks for not referencing something outside the array.

Offline _Scyth_

Junior Member





« Reply #5 - Posted 2013-01-15 22:12:52 »

It moves one cell which is 16*16, but I haven't really done a cell if you know what I mean, just the level1[][], ahhh! I'm so confused!

I can't get this to work! It's probably something extremely easy, I'm just missing it!

My character now jumps several spaces, regardless of where it is.
I'm using a simple Graphics package because that is what I'm restricted too.
I need to try and have it that the character can move if its on an '0' tile but it can't move onto a 1 tile.
i've tried trying to predict what the tiles around the character are, but I can't get that to work either Sad

sorrry, I've been trying to fix this for the last couple of days, and haven't had a clue.

is there anyway I could do
1  
int[][] playerPos;


and then use it to define the player position?
but how can i  use it for rendering the image according to the
1  
playerPos[y][x]
Offline Ultroman

JGO Knight


Medals: 24
Projects: 1


Snappin' at snizzes since '83


« Reply #6 - Posted 2013-01-16 00:13:47 »

It's a bit too hard-coded to just check if the tile is 0 or 1, if you want to have several types of tiles. If you only need 2 types of tiles (walls and not walls) then it is fine.

If you have more types of tiles, like grass, forest (makes player move slower or leaves could fly around the player), or water (stops the player unless his name is Jesus) or whatever, then I'd recommend a Tile-class, which has an int ID (which refers to the number used in the map[][]), and an int type to recognize which kind of tile it is, and lastly a boolean passable indicating if it can be traversed at all.

Using simple rectangles to check for collisions is fine, but I believe there's an easier method, which also makes it much easier to control what to do, depending on which side of the player is colliding with a tile. Not to mention the freedom for precision, in that you can put the points as close to the actual player-part of your image, if he doesn't fill out the entire image.

What I did for my game, was to check 8 points around the player (see image below), and react if one of these points are within a tile that cannot be traversed. If any of the 4 top/bottom points are within a tile, I move the player back to his previous Y-position (which I save in a variable every update). If any of the 4 left/right points are within a tile, I move the player back to his previous X-position (which I save in a variable every update).

It is important to do the X and Y separately, or your player will get stuck in weird ways, meaning you can't be walking left into a wall and still move upwards or downwards along it.



This is what I used in my very first game, and it works perfectly. (See for yourself.

Extremely simplified code to move the player. Use whatever you'd like:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
    public void movePlayer(){
       if(keys[KeyEvent.VK_UP]){
          player.setPlayerPositionY(player.getPlayerPositionY()-3);
       }
       if(keys[KeyEvent.VK_DOWN]){
          player.setPlayerPositionY(player.getPlayerPositionY()+3);
       }
       if(keys[KeyEvent.VK_LEFT]){
          player.setPlayerPositionX(player.getPlayerPositionX()-3);
       }
       if(keys[KeyEvent.VK_RIGHT]){
          player.setPlayerPositionX(player.getPlayerPositionX()+3);
       }
    }


When the player has been moved, we do the collision-checking.
Code to check all points for collisions and reacting to them (the offsets for the points are hardcoded after the size of my player image; the playerPosition is the dead center of the player image in my game):
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  
    public void checkCollisionsAroundPlayer(){
       int tileCoordX = player.getPlayerPositionX();
       int tileCoordY = player.getPlayerPositionY();
       Point upRight = new Point(), upLeft = new Point(), rightTop = new Point(), rightBot = new Point(), leftTop = new Point(), leftBot = new Point(), downRight = new Point(), downLeft = new Point();
       
       upRight.setLocation(tileCoordX+9,tileCoordY-13);
       upLeft.setLocation(tileCoordX-9,tileCoordY-13);
       rightTop.setLocation(tileCoordX+13,tileCoordY-9);
       rightBot.setLocation(tileCoordX+13,tileCoordY+9);
       leftTop.setLocation(tileCoordX-13,tileCoordY-9);
       leftBot.setLocation(tileCoordX-13,tileCoordY+9);
       downRight.setLocation(tileCoordX-9,tileCoordY+13);
       downLeft.setLocation(tileCoordX+9,tileCoordY+13);
       
       if(checkCollisionForPoint(upRight) || checkCollisionForPoint(upLeft)){
          player.setPlayerPositionY(player.getLastY());
       }
       if(checkCollisionForPoint(downRight) || checkCollisionForPoint(downLeft)){
          player.setPlayerPositionY(player.getLastY());
       }
       if(checkCollisionForPoint(leftTop) || checkCollisionForPoint(leftBot)){
          player.setPlayerPositionX(player.getLastX());
       }
       if(checkCollisionForPoint(rightTop) || checkCollisionForPoint(rightBot)){
          player.setPlayerPositionX(player.getLastX());
       }
    }



Code to check a single point for collisions. The tiles are referenced by their ID in the ground[][], which is looked up in my TileList, which is a list of all loaded Tile-objects. Each Tile-object knows if it is passable:
1  
2  
3  
4  
5  
6  
7  
8  
    public boolean checkTileCollisionsFromMapCoordinates(int tileCoordX, int tileCoordY){
       boolean collides = false;
       int tileX = getTilePosX(tileCoordX);
       int tileY = getTilePosY(tileCoordY);
       if(!tileList.getTileList().get(map.getGround()[tileY][tileX]).isPassable()) collides = true;
       
       return collides;
    }

- Jonas
Offline _Scyth_

Junior Member





« Reply #7 - Posted 2013-01-16 17:47:20 »

I understand the points so i'll try that Smiley thanks for the suggestions. If it helps, I'm not looking for a complex collision system just an extremely simple one, my map is all squares and the character will end up being a circle, so it doesn't need to be too complicated. Everything i try seems to fail but.
Offline Ultroman

JGO Knight


Medals: 24
Projects: 1


Snappin' at snizzes since '83


« Reply #8 - Posted 2013-01-16 20:10:30 »

I wrote this: "How to approach 2D side-scrolling platformer collisions easily"
Meant for a platformer, but many of the same points apply. It'll help you around some devious traps Smiley

- Jonas
Offline _Scyth_

Junior Member





« Reply #9 - Posted 2013-01-16 20:30:16 »

Thanks I'll read through that now Smiley

Thanks for the help everyone, I'll update you all if I get this working.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline _Scyth_

Junior Member





« Reply #10 - Posted 2013-01-16 21:34:17 »

I got it working!

I think some people said this already, and with that and by reading through Ultroman's code, I got a way of doing it formed in my head. Thanks Smiley

I simply let the player walk onto a "wall" then check to see if the player is on a "wall" by using
1  
2  
3  
4  
5  
if( level1[pY][pX] == 1 )
{
   pX = prevX;
   pY = prevY;
}


I knew something simple would have been what it takes to do it, thanks everyone for helping me out! This took much longer than I had anticipated Smiley
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.

E.R. Fleming (13 views)
2014-07-29 03:07:13

E.R. Fleming (4 views)
2014-07-29 03:06:25

pw (39 views)
2014-07-24 01:59:36

Riven (39 views)
2014-07-23 21:16:32

Riven (26 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21

Zero Volt (50 views)
2014-07-17 23:47:54

danieldean (42 views)
2014-07-17 23:41:23

MustardPeter (44 views)
2014-07-16 23:30:00
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!