I currently have a program that draws overlapping rectangles and was wondering if there is an easy way to determine which shape is on the top (most visible). This has me stumped as there is no z axis to use like in when dealing in 3D.
I have tried looping through the rectangles and using the .contains method but it returns all rectangles under a specific point and not the highest level one.
I have also searched around but perhaps I'm using the wrong keywords?
Normally when people do painting code they do something like:
List rectangles = ....
for (int i = 0; i < rectangles.size(); i++)
//paint the rectangle
So if you want to search for a Point to determine what Rectanle it is in then you should use:
for (int i = rectangles.size() - 1; i >= 0; i--)
{
if (rectangles.get(i).contains(yourPoint))
{
// do something
break;
}
}
Starting from the end will give you the last rectangle painted which means it is on top of all aother rectangles.
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'm trying to zoom the previously created shape. It works, but there are previous states of the shape, which are visible on the screen. I can't make it works that it shows only the last state of my shape. I do have a call repaint() in the end of the method which changes the size. Please tell me what code should I paste here, I give you the most appropriate one for me. I don't know if it's obvious or not, but I'm making this in JFrame.
Codes and image are below.
(a.other is the shape, valuesX and valuesY are arrays which contains where shape's points are located)
my class to draw it:
public class ZOtherShape extends Path2D.Float
a.other.moveTo(a.other.valuesX[0],a.other.valuesY[0]);
for (int index = 1; index < a.other.valuesX.length; index++)
a.other.lineTo(a.other.valuesX[index], a.other.valuesY[index]);
a.other.closePath();
g2d.fill(a.other);
g2d.setPaint(Color.BLACK);
a.other.moveTo(a.other.valuesX[0],a.other.valuesY[0]);
for (int index = 1; index < a.other.valuesX.length; index++)
a.other.lineTo(a.other.valuesX[index], a.other.valuesY[index]);
a.other.closePath();
g2d.draw(a.other);
Image
never posted a question before though plenty of lurking, thanks for all the advice you've already unwittingly supplied! Couldn't seem to find any previous answers to help with this. I'm a scientist who's only picked up programming on the fly so tend to be a bodger, hopefully the question makes sense.
How do I set up an java.awt.geom.Area object for a set of triangles (for which I have the coordinates of the corners)?
The problem I’m trying to solve is that I have a mesh of triangles over which I'm drawing a mesh of rectangles and I’m trying to find for each rectangle which triangle or triangles it lies within. The java.awt.geom.Area class has an intersect method which given sufficient looping would seem to solve it - my problem is constructing the areas.
I can create the square mesh as areas in the following (possibly inefficient) manner
Rectangle2D.Double[] squareMesh = new Rectangle2D.Double[totalCells];
int k = 0;
for(int i=0; i < cellsY; i++) {
for(int j=0; j < cellsX; j++) {
squareMesh[k]= new Rectangle2D.Double(cellsXCoords[j],cellsYCoords[i],resolution,resolution);
k++;
}
}
Area[] squareMeshAreas = new Area[totalCells];
for(int i=0; i < totalCells; i++) {
squareMeshAreas[i] = new Area(squareMesh[i]);
}
For the triangles I have the coordinates of the corners for each. The java.awt.Polygon looked hopeful but won't work as it only takes integer coordinates. What is the best way to set up Areas for these triangles?
If there are better ways of solving the problem without using Area class then suggestions are also welcome.
I am working on a platformer game that will use tile maps, which I don't know if is a good idea!
I've made a neat tile map editor with tools for setting a spawn point etc. but now that I want to be able to test play the game after editing map and for future use I need of course integrate physics which I've done with Box2D which comes with LibGDX!
I am creating a method to create a collision map from tile map which has data if tile is collideable or not!
So I came up with this great idea:
loop through the map and if we find a colliding tile loop through its neighbor tiles and see if they're colliding too, and do this til noncolliding tile is found when we set width and height for the colliding rectangle
after we got bunch of rectangle I sort them in order from biggest square to smallest so we get biggest pieces and I add the rectangles to final list and check against the final rect if any of them overlaps with current body so I don't have overlapping bodys
But you know, code tells more than 1000 words, right?
public void createBody() {
List<Rectangle> allRects = new ArrayList<Rectangle>();
for(int x = 0; x < info.getWidth(); x++) {
for(int y = 0; y < info.getHeight(); y++) {
if(tiles[x][y].getInfo().isColliding()) {
int width = 1;
int height = 1;
//loop through neighbors horizontally
for(int i = 0; i < info.getWidth() - x; i++) {
if(!tiles[x + i][y].getInfo().isColliding()) {
//if tile is not clipped, we set width to i which is current x offset
width = i;
break;
}
}
//only if width is bigger than zero can the rect have any tiels..
if(width > 0) {
boolean breakingBad = false;
//loop through neighbors horizontally
for(int j = 0; j < info.getHeight() - y; j++) {
//loop though neigbors vertizally
for(int i = 0; i < width; i++) {
//check if tile is not colliding
if(!tiles[x + i][y + j].getInfo().isColliding()) {
//and if so, we set height to j which is current y offset
height = j;
//breaking bad aka leaving both loops
breakingBad = true;
break;
}
}
if(breakingBad) {
break;
}
}
}
if(width * height > 0)
allRects.add(new Rectangle(x, y, width, height));
}
}
}
Collections.sort(allRects, new Comparator<Rectangle>() {
#Override
public int compare(Rectangle o1, Rectangle o2) {
Integer o1Square = o1.width * o1.height;
Integer o2Square = o2.width * o2.height;
return o2Square.compareTo(o1Square);
}
});
List<Rectangle> finalRects = new ArrayList<Rectangle>();
mainloop:
for(Rectangle rect: allRects) {
for(Rectangle finalRect: finalRects) {
if(finalRect.contains(rect)) {
continue mainloop;
}
}
finalRects.add(rect);
}
for(Rectangle rect: finalRects) {
PolygonShape polyShape = new PolygonShape();
polyShape.setAsBox((float)rect.getWidth() / 2, (float)rect.getHeight() / 2, Vector2.tmp.set((float)rect.getCenterX(), (float)rect.getCenterY()), 0f);
mapBody.createFixture(polyShape, 1);
polyShape.dispose();
}
}
however this sill seems pretty inefficient because for some reasons its still creating smaller fixtures than it could be possible, for example in upper right corner
also its creating single fixtures in the corners of the center rectangle and I can't figure out why!
Is the whole idea all inefficient, and should I use other method or manually create collision maps or what could be the best idea?
Originally each tile was its own fixture which caused weird bugs on their edges as expected
First off, a custom tile mapping tool is a great idea on the surface, but you're reinventing the wheel.
libGDX has built-in support for TMX maps.
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/maps/tiled/TmxMapLoader.html
Instead of using your homebrew editor, you can use a full featured editor such as this Tiled - http://www.mapeditor.org/
So once you have a better system in place for your maps, I would look at this from an object oriented perspective. Since you want to use box2d physics, each collidableTile HAS A body. So all you need to do is assign a physics body to each collidableTile, and set the size according to your standard tile size.
Don't forget that there is a difference between the box2d world and your game screen, where box2d is measured in metric units, and your screen is measured in pixels. So you need to do some math to set positions and size properly. If you want a set of tiles to share a body, you may want to pass in the body as a parameter when you construct each collidableTile, and then adjust the size of the body based on how many adjacent tiles you can find. More complex shapes for the physics body may be more complex.
You can also save resources by setting those tiles to 'sleep', where box2d does a reduced simulation on those bodies until it detects a collision. If you're only using box2d for collision detection on terrain, you may want to consider other options, like using shape libraries to detect intersections, and then setting the box2d physics on your player characters body to stop downward acceleration while there is contact, or something.
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)