I have a TiledMap map with some object layers like "wall", "door", "spike"...
Each layer has only rectangles, at their specific positions.
What is the best way I could check if a specific cell of the tile layer contains an object from a specific object layer?
To do something like if Cell of the tile layer at (x,y) contains an object from a object layer "wall", say "can't move there".
I just started using libGDX and Tiles, and the current way of detecting something like this that I can think of would be to create all those rectangles and check if they overlap with the player rectangle each time a player moves to the next cell.
But that would be checking every single object, and I need to just check the one cell the player is currently in.
One way you could reduce computation (this only works if the walls/doors/etc. are all static and don't move or change shape) is by keeping a 2D array of booleans (basically your TiledMap) with true meaning that tile is blocked and vice versa.
In pseudocode:
// Initially all grid cells are un-blocked
boolean[][] gridBlockedByWall = new boolean[MAP_HEIGHT][MAP_WIDTH]; //Replace with your grid size
// Loop over each wall and set array (change depending on your implementation)
for (Rectangle wall: walls) {
// Here we run over every wall and column covered by this rectangle and set it as blocked
for (int row = wall.y; row < wall.y + wall.height; row++) {
for (int col = wall.x; col < wall.x + wall.width; col++) {
gridBlockedByWall[row][col] = true;
}
}
}
Now to test if position (x, y) is blocked by a wall simply do gridBlockedByWall[y][x] which will run in constant time.
Related
I have a GUI Maze game that I am creating and I am having trouble implementing walls that prevent the player from moving. The walls are rectangles but the player is a circle so I had to create a collision detection method between a rectangle and a circle. The problem I am having is that my collidesWith() method is in the player class and it takes a single wall as a parameter and returns a string that tells you which side of the wall is the player intersecting with. This means I can only check if the player is colliding with one wall at a time. Here is the code for the collidesWith() method. x and y are the x and y coordinates of the player since this method is in the player class:
I should mention that the code above doesn't exactly work how I wanted it to since it only works when the player is coming from the sides. If the player is coming from the top or bottom, the player just goes through the wall.
The reason I need this method to return a string to tell me where the player is coming from is so that I can explicitly restrict the movement of the player when the up, down, left, right keys are pressed. This is in another class where all the GUI components are. Here is the code for that. I have created a wall object on top so that it can be passed as a parameter here when checking for intersection:
In my view, it is better to avoid to iterate through the whole array of wallsArraylist. If I understood correctly, it is necessary to explore neighbour cells, if yes, then you can explore neighbours in a two-dimensional array using this approach:
(pseudo-code)
row_limit = count(array);
if(row_limit > 0){
column_limit = count(array[0]);
for(x = max(0, i-1); x <= min(i+1, row_limit); x++){
for(y = max(0, j-1); y <= min(j+1, column_limit); y++){
if(x != i || y != j){
print array[x][y];
}
}
}
}
In addition, try to avoid magic strings. Replace "comingFromRight" and etc to constant string:
public static final String COMING_FROM_RIGHT = "comingFromRight";
I am trying to write something that will take a X and Y coordinate and a value that represents the available movement points the selected actor has. It should then output a list of the reachable locations so that I can highlight those tiles when the actor is choosing where to move.
I managed to use a function from my pathfinding library (https://github.com/xaguzman/pathfinding) that gives me the neighbouring tiles of a tile as a List of grid cells. It can also check my Tile-map and see if the tile is walkable.
What I can't really get my head around is how I would be able to set this up so that it would run as many times as the movement points.
List<GridCell> neighbours;
NavigationTiledMapLayer navLayer;
public void getMovementPossibilities(int tileX, int tileY) {
GridCell cell1;
GridCell cell2;
cell1 = navLayer.getCell(tileX, tileY);
GridFinderOptions opt = new GridFinderOptions();
opt.allowDiagonal = true;
opt.dontCrossCorners = false;
neighbours = navLayer.getNeighbors(cell1, opt);
for (int i = 0; i < neighbours.size(); i++) {
int nX = neighbours.get(i).getX();
int nY = neighbours.get(i).getY();
cell2 = navLayer.getCell(nX, nY);
neighbours.addAll(navLayer.getNeighbors(cell2, opt));
}
}
Sounds like a case for recursion. I can't see how you're keeping track of movement points but your current method finds all tiles 1 distance away. Inside this method, you need to recall the same method, but with each of those neighbours as your new start point and with the movement points reduced by 1.
This in turn generates all the second neighbours, and then the method will be called recursively and so on...
You will want a check at the top of the method so that if the distance points left are 0, it just immediately adds the current tile to neighbours and then returns (to stop the recursive chain going on forever).
I'm trying to implement Collision detection using Rectangles for my game but can't seem to get it to work.
Bullets are updated when pressing space every frame so they move across the screen. Apparently so I've been told on here, the collisionbox moves with it as well. I'm getting this by using sprite.getBoundingBox() which sets a datafield Rectangle to this value for each instance.
I have two Arraylists, one holding instances of Monsters and one holding instances of Bullets. They all have collisionRectangles associated with them.
I'm calling the checkCollisions() method from my main render loop every frame as long as there's something in the bullets or monsters arraylist.
/*this handles collisions between bullets and enemies*/
public static void checkCollisions(){
for (int i = 0; i < Main.currentBullets.size(); i++){
for (int k = 0; k < Main.currentMonsters.size(); k++){
if (Intersector.overlaps(Main.currentBullets.get(i).collisionBoxBullet,
Main.currentMonsters.get(k).collisionBoxMonster)){
System.out.println("Boom headshot");
}
}
}
Shouldn't this do Boom Headshot every time it overlaps? Instead it always seems to keep evaluating to true.
Why does it keep evaluating to true and writing boom headshot?
What I didn't do is set the position of the rectangle of the sprite which was at 0.0. I also then didn't move the collision box properly with collisionBox.setPosition().
It initially checking to see if sprite at 0/0 is colliding with collision box at 0.0 which is always true, hence always saying it's overlapping.
I'm fairly new to Java and I'm having a problem with arrays in a game I am creating, which is similar to Bejeweled.
In this game, I have one class called Tile, which represents one colored tile on the board, along with its column and row (integers)on the board. I have another class for the board, called Board, that manages these tiles in a 2D array of integers, organized by column and row.
My problem occurs I swap two tiles on the screen. When this happens, their columns and rows are swapped, but the array that they are saved in does not recognize this change. On the screen, everything looks fine. The two tiles will switch positions.
For instance, if I have two adjacent tiles that I want to switch, at (column0, row0) and (column1, row0). In my array of tiles, these are tiles array[0][0] and array[1][0]. When I switch them, the first tile is now at the second tile's old position, and the second tile is now at the first tile's old position. However, the first tile is still recognized as array[0][0], even though it should now be array[1][0].
The significance of this is that my program will not recognize three consecutive tiles with the same color, and therefore it will not clear them from the board.
Is there anything I can do to fix this?
If you have any suggestions at all, that would be great. Thank you.
Not sure what exactly is wrong from your description. The code should look similar to this:
class Tile {
int col;
int row;
void setPos(int newCol, int newRow) {
col = newCol;
row = newRow;
}
class Board {
Tile[][] array;
void swap(int col0, int row0, int col1, int row1) {
// Get hold of the tile objects to swap
Tile tile0 = array[col0][row0];
Tile tile1 = array[col1][row1];
// Swap the positions stored in the tile objects
tile0.setPos(col1, row1);
tile1.setPos(col0, row0);
// Swap the tile objects in the array
array[col0][row0] = tile1;
array[col1][row1] = tile0;
}
}
Background:
I have two 2d arrays. Each index within each 2d array represents a tile which is drawn on a square canvas suitable for 8 x 8 tiles.
The first 2d array represents the ground tiles and is looped and drawn on the canvas using the following code:
//Draw the map from the land 2d array
map = new Canvas(mainFrame, 20, 260, 281, 281);
for(int i=0; i < world.length; i++){
for(int j=0; j < world[i].length; j++){
for(int x=0; x < 280; x=x+35){
for(int y=0; y < 280; y=y+35){
Point p = new Point(x,y);
map.add(new RectangleObject(p,35,35,Colour.green));
}
}
}
}
This creates a grid of green tiles 8 x 8 across as intended.
The second 2d array represents the position on the ground. This 2d array has everyone of its indexes as null apart from one which is comprised of a Person class.
Problem
I am unsure of how I can draw the position on the grid. I was thinking of a similar loop, so it draws over the previous 2d array another set of 64 tiles. Only this time they are all transparent but the one tile which isn't null. In other words, the tile where Person is located.
I wanted to use a search throughout the loop using a comparative if statement along the lines of
if(!(world[] == null)){
map.add(new RectangleObject(p,35,35,Colour.red));}
However my knowledge is limited and I am confused on how to implement it.
Do not use a second Array at all. Simply create a RectangleObject named, for example, currentPosition or activeTile or personPosition.
You, however, do not really need to store the Point in the RectangleObject. Either use a 2D RectangleObject array for that (so that you can use the indexes to access them) and exclude the Point information in the RectangleObject,
or
create a List of RectangleObjects and add the Point information - but do not increment by 35, but rather by 1. When you're drawing the tiles, you can still (by knowing the index) figure out where to put the tile (e.g. indexX*tileWidth, indexY*tileHeight).
(It's not quite clear from what you've written what world and map are used for. Please explain so I can give a better answer)