I'm trying to determine whether two rectangles border each other. If they share an edge or part of an edge, then I want to include them, if they only share a vertice then I don't.
I've tried using android android.graphics.Rect, I was hoping that the intersect method would return true giving me a rectangle, with 0 width but the points of the intersecting edge. I'm using andEngine and also tried the collideswith method of org.andengine.entity.primitive.Rectangle however that returns true, even if the rectangle only share one corner vertice.
Is there a nice way of doing this? The only other way I can think of is to try and create a collection of all the edges then see if they're equal or are in someway partly equal.
Here's an image to demonstrate what I want. If I click on rect 1 then I want to return rects 2,3 and 4, but not 5.
"Map":
It sounds like you need a new class to do this. I would take the coordinates of each corner of the rectangles. Then, when you are selecting a rectangle, you can get those adjacent to it by finding them one side at a time. Starting with the top for an example, you check which other rectangles have corners at the same height. From that list, you check to see which ones exist on at least one point between the two top corners. So, if top left is 0,3 and top right is 4,3 then you would look for the list of corners at y=3. From that list you find all corners where 0<=x<=4 and anything that fits will be adjacent. You then do the same thing for each additional side. It should be an easy class to make, but I am not going to write any code as I do not know anything about how you stored your data or how you would reference this in your code. If you need help with that, write a comment.
Write a function to find which rectangles share edges with rectangles within all considered rectangles.
Then, map these rectangles which share edges to one another. An Adjacency List is just a way of representing a graph in code.
Sometimes code is easier to understand, so here's code. I have not tested this, but it should get you most the way there.
Also, I'm not sure what you're end goal is here but here's a question I answered that deals with rectangular compression.
List<Rectangle> allRectangles;
public boolean shareAnEdge(Rectangle r1, Rectangle r2){
int y1 = r1.y + r1.height;
int y2 = r2.y+r2.height;
int x1 = r1.x+r1.width;
int x2 = r2.x+r2.width;
boolean topShared = (y1 == r2.y && r2.x == r1.x);
boolean bottomShared = (y2 == r2.y && r2.x==r1.x);
boolean rightShared = (x1 == r2.x && r2.y==r1.y);
boolean leftShared = (x2 == r1.x && r2.y==r1.y);
if (topShared || bottomShared || rightShared || leftShared) {
return true;
}
return false;
}
public List<Rectangle> findSharedEdgesFor(Rectangle input){
List<Rectangle> output = new List<Rectangle>();
for(Rectangle r : allRectangles){
if(r!=input && shareAnEdge(r, input)){
output.add(r);
}
}
}
public AdjacencyList createGraph(List<Rectangle> rectangles){
AdjacencyList graph = new AdjacencyList();
for(Rectangle r : rectangles){
List<Rectangle> sharedEdges = findSharedEdgesFor(r);
for(Rectangle shared : sharedEdges){
graph.createEdgeBetween(r, shared);
}
}
}
Related
I'm working on finding maximum overlap rectangle.
I've tried using following lines of code but it returns with that rectangle is overlaping to other or not
public boolean isOverlapping(Rect r1, Rect r2) {
if (r1.top < r2.top || r1.left > r2.left) {
return false;
}
if (r1.width() < r2.width() || r1.height() > r2.height()) {
return false;
}
return true;
}
I expect output that rectangle 3 is most overlaping to given rectangle. Not list or number of rectangles that overlaping to given rectangle.
A bit of pseudo code to get you going:
for each rect in Rectangle list
overlap = compuateOverlap(rect, givenRect)
In other words: it is relatively easy to actually compute the overlap area for two rectangles. Just do that, and compare the results, and isolate the maximum.
In case you need more guidance how to compute that overlap, see this answer for some inspiration.
Or here, there you find even the exact formula to use to compute the overlap area of two rectangles!
im trying to draw rectangles of different sizes on a grid for a uni assignment. so what i want to do is drawing and colouring them in blue. but i want to check first if at a given position a rectangle exists. is there a method in the library for this or do i have to develop that method. In the latter case where should i start?
thanks!
Let's say you have an LTRB (left/top/right/bottom) representation for a rectangle. You can check if a point (x,y) is inside the rectangle like so:
boolean pointInRect(int x, int y, int l, int t, int r, int b)
{
return x >= l && x <= r &&
y >= t && y <= b;
}
Note that if you use java.awt.Rectangle, there is a contains method that already does this, though I'm not sure if that would be considered "cheating" or not in the context of a school assignment.
So given a position, you can iterate through a list of rectangles you have (the same ones you draw to the screen) and see which one contains the point/position.
If you want to do this in faster than linear time, you can use, say, a quad-tree or partition your rectangles into a fixed NxM grid. In the latter case, you can just check the rectangles that belong to the same grid cell the mouse cursor is over. That might be overkill for this assignment though.
Edit
After some back-and-forth, I think more helpful to your situation is a test to see if a rectangle overlaps with another.
// Returns true if two solid rectangles intersect.
bool rectIntersect(int l1, int t1, int r1, int b1,
int l2, int t2, int r2, int b2)
{
return l1 <= r2 && r1 >= l2 &&
t1 <= b2 && b1 >= t2;
}
Using this function, whenever you want to add a new rectangle, you can loop through the existing rectangles you have and see if any one of them intersect the new one you're trying to add. This isn't the most efficient approach, but it should give you the desired behavior.
I'm making a game similar to mario and I've got this map generated by arrays and images. But my problem is that I don't know how to make a hitbox system for all the tiles. I've tried to have a position based collision system based on your position on the map
like this
if(xpos > 10*mapX && xpos < 14 * mapX){
ypos -= 1;
}
But I don't want to that for every wall or hole.
So is there a way to check in front, below and above the character to see if there is a hitbox there and if there is you cant move that direction or fall?
Thank you
If it's a simple 2D game, I'd suggest dividing the map into square tiles. You could store the map in the memory as a two dimensional array and during each frame check tiles adjacent to the player. Of course he can occupy as much as 4 tiles during movement, but it makes you check only up to 12 positions, which can be easily done.
Further collision checking can be done easily using image position and dimension.
Remember that there is no need to check if a static object (environment) is colliding with something, you just need to check objects that have made a move since last frame, i.e. the player and sprites.
EDIT:
Let's say you've got the following section of map (variable map):
...
.pe
ooo
where
. = nothing
p = player
o = floor
e = enemy
you also have the pair (x, y) representing tile indices (not exact position) of the player. In this case you have to do something like this:
if ("o".equals(map[y + 1, x + 1]))
//floor is under
if ("e".equals(map[y, x + 1]))
//enemy is on the right
if ("o".equals(map[y - 1, x]))
//floor is above us
If any of these conditions are met, you have to check image positions and handle collisions.
Note: clicked submit way after the last post was made...
As Mateusz says a 2D array is best for this type of game:
e.g. using chars:
0123456789012
0 ==
1 * ===
2===== =======
So in this case tileMap[8][1] == '*'. You'd probably be best using an enumeration instead of chars though e.g. Tile.SPRING for a Sonic style spring board.
If your map was made up of regular sized tiles you could say:
int xInFrontOfPlayer = playerX + PLAYER_WIDTH;
int xBehindPlayer = playerX - PLAYER_WIDTH;
Tile tileInFrontOfPlayer = getTileAtWorldCoord(xInFrontOfPlayer, playerY);
Tile tileBehindPlayer = getTileAtWorldCoord(xBehindPlayer, playerY);
...
public Tile getTileAtWorldCoord(int worldX, worldY) {
return tileMap[worldX / TILE_WIDTH][worldY / TILE_HEIGHT];
}
Where TILE_WIDTH and TILE_HEIGHT are the dimensions of your tiles in pixels. Then use similar math for yAbovePlayer and yBelowPlayer.
You might then have some logic in your game loop:
if user is pressing the "go right" key:
if the tile to the right is Tile.SPACE:
move player right
else if the tile to the right is Tile.WALL:
don't do anything
if the tile below is Tile.SPACE:
fall
I'm making a game where i need to give my objects collision, but i have many fast small objects and normal collision algorithms (Intersection of shapes and such) do not work, because the position+speed iteration advances the walls and there's never actually an Intersection.
So i've started constructing my own (Maybe it already exists but i didnt see it anywhere) collision algorithm based on saving the last position the object was.
Please see the following image:
The idea is demonstrated in frame 1 and 2 of the image. Basicly by checking if there's a wall between the left side of the last rectangle and the right side of the new rectangle, i never skip zones while i check collision, and there's no risk of skipping a wall (so i thought).
This is the code of the algorithm:
private void bounce(GameElement b, Terrain t)
{
Rectangle tR = t.getRectangle();
int tRleft = tR.x;
int tRright = tR.x+tR.width;
int tRup = tR.y;
int tRdown = tR.y+tR.height;
Rectangle bRnow = b.getRectangle();
int bRnowLeft = bRnow.x;
int bRnowRight = bRnow.x+bRnow.width;
int bRnowUp = bRnow.y;
int bRnowDown = bRnow.y+bRnow.height;
Rectangle bRlast = b.getRectangleLast();
int bRlastLeft = bRlast.x;
int bRlastRight = bRlast.x+bRlast.width;
int bRlastUp = bRlast.y;
int bRlastDown = bRlast.y+bRlast.height;
boolean leftRight = false, rightLeft=false, upDown=false, downUp=false;
boolean betweenX = false, betweenY = false;
if(bRnow.x>bRlast.x)leftRight=true;
if(bRnow.x<bRlast.x)rightLeft=true;
if(bRnow.y>bRlast.y)upDown=true;
if(bRnow.y<bRlast.y)downUp=true;
if(bRlastRight>tRleft && bRlastLeft<tRright) betweenX = true;
if(bRlastDown>tRup && bRlastUp<tRdown) betweenY=true;
if(leftRight)
if((tRleft>bRnowLeft || tRleft>bRlastLeft) && tRleft<bRnowRight && betweenY)
{
b.setX(tR.x-bRnow.width - 1);
}
if(rightLeft)
if((tRright<bRnowRight || tRright<bRlastRight) && tRright>bRnowLeft && betweenY)
{
b.setX(tR.x+tR.width + 1);
}
if(upDown)
if((tRup>bRnowUp || tRup>bRlastUp) && tRup<bRnowDown && betweenX)
{
b.setY(tR.y-bRnow.height - 1);
}
if(downUp)
if((tRdown<bRnowDown || tRdown<bRlastDown) && tRdown>bRnowUp && betweenX)
{
b.setY(tR.y+tR.height + 1);
}
}
Its called bounce because its not really organized atm, i still have to think how to structure the algorithm so it becomes more generalized and pratical (Would appreciate help on that too)
This way of doing collision has one bug at the moment which is seen in image 3 (sorry for drawing circles, they are supposed to be squares) because FAST objects still pass diagonals :/ On the other hand, direct hits on walls are pretty neat.
How could i improve, optimize and organize this algorithm? Or is there any better algorithm and im just thinking too much for nothing? I appreciate your help.
Axis aligned bounding box trees are usually well suited to detecting object collisions. Here is a tutorial with some code - its examples are for 3D collision detection, but the data structure can be easily adapted to 2D collision detection.
The program should detect circles and colour them in red. The symmetry method was suggested where I assume each pixel is a center of a circle and check the four points r (radius) distance from it. If they are the same, draw a circle. However in the code bellow I get way to many unnecessary circles
static boolean isCenterOfCircle(int row, int col, int r, BufferedImage image) {
//getPixels gets the color of the current pixel.
if(getPixel(row,col,image) == getPixel(row+r,col,image)
|| getPixel(row,col,image) == getPixel(row-r,col,image)
|| getPixel(row,col,image) == getPixel(row,col+r,image)
|| getPixel(row,col,image) == getPixel(row,col-r,image)){
return true;
}else{
return false;
}
}
This can be done using the Hough transform for circles.
See algorithm for detecting a circle in an image
You should check more than 4 points to detect the circle. What about 16 or more. Maybe depending on the radius. For bigger radius you should check more points.
Or search the web for circle detecting algorithms. There are other approaches than checking a few pixels.