I have two rectangles. In my code, I can check when a collision occurs with Rect.intersects() method but cannot determine which side it is from. I've tried these below and it works for X-Axis but not for Y-Axis.
if(R1.getTranslateX() + R1.getWidth() < R2.getTranslateX() + (R2.getWidth() / 2) ) {
//Collision from left side
}
if(R1.getTranslateX() > R2.getTranslateX() + (R2.getWidth() / 2) ) {
//Collision from right side
}
if(R1.getTranslateY() + R1.getHeight() < R2.getTranslateY() + (R2.getHeight() / 2)) {
//Collision from top side
}
if(R1.getTranslateY() > R2.getTranslateY() + (R2.getHeight() / 2)) {
//Collision from bottom side
}
The code doesn't get past the X-Axis to check the Y-Axis side... Any ideas?
Left/right and top/bottom are with respect to R1. It is not possible to know for sure in all cases from which direction a collision happened without knowing the directions the objects were moving. The following would be the best way, as I see it, to detect collision direction with the information at hand. Consider the rectangle R1. We will make an estimation on how much colliding rectangles will at most intersect before the collision is detected. We'll call this margin m. Let's detect collisions following this illustration. We see that the smaller the margin, the smaller the areas at the corners are in which we don't know the direction of the collision for sure. The problem with making the margin smaller is that if the rectangles intersect more than the margin allows, we don't detect the direction of the collision at all. See code below.
int m = [an estimate on how much the rectangles will intersect at most]; //margin
//x-direction
if(R1.getTranslateX() + m > R2.getTranslateX() + R2.getWidth()){
//Collision from left side
}else if(R1.getTranslateX() + R1.getWidth() - m < R2.getTranslateX()){
//Collision from right side
}
//y-direction
if(R1.getTranslateY() + m > R2.getTranslateY() + R2.getHeight()){
//Collision from top side
}else if(R1.getTranslateY() + R1.getHeight() - m < R2.getTranslateY()){
//Collision from bottom side
}
Related
I am using Java awt library.
I am making a simple game where I have a player and enemy as Rectangles. then I set them bounds so I can use the intersect function on them.
Now I want to check how the player and enemy touch. see attchemnt.
there are mostly 4 different way player can touch the enemy. see the attachemnt. now if player touch the enemy from top than I was go inside the 'if' statment. but if player touch the enemy from left or right than I want to go inseide 'else' statment. I wrote the code below but it doesnt work. for some reason it always goes in else statment.
I was thinking may be there is another function I can use?
if (player.getBounds().intersects(enemy.getBounds())) {
if (playerY + playerHeight <= enemy.getY()) {
//player touch enemy from top
} else {
//player touch enemy from left or right
}
}
Might be not the best solution but it work for what I want. Thanks
if (player.getBounds().intersects(enemy.getBounds())) {
if (y + height <= enemy.getY() + enemy.getHeight() / 2) {
//player touch enemy from top
} else {
//player touch enemy from left or right
}
}
You are checking first the rectangles to see whether they intersect. Intersection is not "touching". It's when they have a common rectangle that is not empty.
So, for example, the following two rectangles do not intersect:
Rectangle a = new Rectangle( 100,100,200,200);
Rectangle b = new Rectangle( 100,300,200,200);
But note that a.y (100) + a.height (200) is exactly b.y (300).
Of course, if a is above b, say, its y is 99, then a.y + a.height is less than b.y.
So in all cases where a.y + a.height <= b.y, the rectangles do not intersect.
Since you only go into that if if the rectangles do intersect, you'll always end up in the else.
If you want to check if they have a slight overlap from above, you can change your condition to playerY + playerHeight == enemy.getY() + 1, or even
int playerBottom = playerY + playerHeight;
if ( playerBottom > enemy.getY() && playerBottom <= enemy.getY() + DELTA ) {
....
}
where DELTA is a constant that represents how big an overlap you consider "touching".
If you want to see that they touch without overlapping, you can't use the intersects method.
I use libGDX library for my game. I user overlap method for detecting collision detection between two rectangles.
...
if (r1.overlaps(r2)) collisionTest();
...
I want to detect touching side on rectangle (top, bottom, left or right):
r1 overlap r2 on the left side
Can anyone give me code for this, but this need to be fast method.
Thanks
You can use the method intersectRectangles provided in the Intersector class to determine if two rectangles are overlapping, and if so, where they overlap. You could use this info to determine if they overlap with the left, right, top, and/or bottom.
Rectangle r1 = /*Initialize*/;
Rectangle r2 = /*Initialize*/;
Rectangle intersection = new Rectangle();
Intersector.intersectRectangles(r1, r2, intersection);
if(intersection.x > r1.x)
//Intersects with right side
if(intersection.y > r1.y)
//Intersects with top side
if(intersection.x + intersection.width < r1.x + r1.width)
//Intersects with left side
if(intersection.y + intersection.height < r1.y + r1.height)
//Intersects with bottom side
I've been stuck on a bug regarding collision in my 2D Mario-like game.
public void collision() {
if (Rect.intersects(Robot.rect2, r)){
robot.setSpeedY(0);
robot.setCenterY(tileY - 32);
robot.setJumped(false);
} else if (Rect.intersects(Robot.rect, r)){
robot.setSpeedY(0);
robot.setCenterY(tileY + 32);
}
updateRect();
if (Rect.intersects(Robot.rect3, r)){
robot.setCenterX(tileX + 32);
robot.setSpeedX(0);
} else if (Rect.intersects(Robot.rect4, r)){
robot.setCenterX(tileX - 32);
robot.setSpeedX(0);
}
}
Collision in my game is checked by comparing rectangles. My robot's rectangles: rect (bottom collision, so rectangle on bottom half of my robot sprite), rect2 (top collision), rect3 (left collision), and rect4 (right collision).
Every tile in my game is bounded by an instanced Rectangle r. When my robot's rectangle and the tile's rectangle intersect, I call collision(), which sets the position of my robots direction.
Here is my problem: If my robot is at a corner, where it is in bottom collision and right collision, and I move to the right, my robot moves INTO the right tile, and that triggers the bottom collision, and screws everything up.
Switching the postiions of the Bottom/Top & Right/Left collision doesn't help since then the same problem occurs, where the robot falls into the ground, triggering the Right/Left collision.
Essentially, I need a way to run all four at the same time.
Thanks
Yku are trying to build it one check at a time. Why not something like
if(!Rect.intersects(robot.rect1) && !Rect.intersects(robot.rect2) && !Rect.intersects(robot.rect3) && !Rect.intersects(robot.rect4)
{
//act normally
} else {
//collieion
}
What youre doing now is checking one side and base your result on that.
yes I also had a trouble with that, what you are missing is to call updateRect(); again after you made the collision detection on the X axis.
And I recommendto check the X axis first.
here is a nice Article about tile based Collision:
http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/
I've been trying for the past few days to put simple collision into my simple game. I've looked in lots of places all over the internet but I just haven't found anything to be helpful. I'm just using bounding boxes and all i want the player box to do is stop when it hits the block from any of the four sides (and not get stuck or bounce against the block). Doesn't sound so difficult but I've found it incredibly difficult. I really just wanna know the code that i need to put in the if statement's brackets, I've read and heard all the theory I can take. Please help if you can.
if(bb_collide(player,block)){ //detection works just fine,
//just not sure what to do afterwards
}
else{
player.setX((player.getX() + velx));
player.setY((player.getY() - vely));
player.set_coll(player.getX(),player.getY(),player.getWidth(),player.getHeight());
block.set_coll(block.getX(),block.getY(),block.getWidth(),block.getHeight());
}
I actually figured it out, I was just having a couple of bad days, sorry if I had like a bad attitude or something but i got it to do what i wanted it to. Heres what I did if anyone's interested because it works very well for one moving object (mover) bumping into another stationary object (sitter). It finds the distance between the sides that will collide and sets the velocity to that distance minus a few so it doesnt overlap. I had the bounding boxes rendering so i could see they overlapped. Thanks for your replies!
public void Fix_Vel(Player mover, Terrain sitter){
if(sitter.coll_box.contains(mover.getX() + mover.getHeight() + mover.getVelX(), mover.getY()) ||
sitter.coll_box.contains(mover.getX() + mover.getHeight() + mover.getVelX(), mover.getY() + mover.getHeight()) ){ //mover top right and bottom right coords right collision testing
mover.setVelX(sitter.getX() - (mover.getX() + mover.getWidth()) - 2);
}
if(sitter.coll_box.contains(mover.getX() + mover.getVelX(), mover.getY()) ||
sitter.coll_box.contains(mover.getX() + mover.getVelX(), mover.getY() + mover.getHeight()) ){ //mover top left + bottom left coords left collision testing
mover.setVelX((sitter.getX() + sitter.getWidth()) - mover.getX() + 2);
}
if(sitter.coll_box.contains(mover.getX(), mover.getY() + mover.getVelY()) ||
sitter.coll_box.contains(mover.getX() + mover.getWidth(), mover.getY() + mover.getVelY())){ //mover top left + top right coords top collision testing
mover.setVelY((sitter.getY() + sitter.getHeight()) - mover.getY() + 2);
}
if(sitter.coll_box.contains(mover.getX(), mover.getY() + mover.getHeight() + mover.getVelY()) || //mover bottom left and bottom right coords bottom collision testing
sitter.coll_box.contains(mover.getX() + mover.getWidth(), mover.getY() + mover.getHeight() + mover.getVelY())){
mover.setVelY(sitter.getY() - (mover.getY() + mover.getHeight()) - 2);
jumping = false;
if(mover.getVelY() < 0)
mover.setVelY(0);
}
}
You don't say how each box is controlled, so I'm not sure exactly what you want. If detection works, simply don't allow an object to move if it will cause a collision.
PS: I really just wanna know the code that i need to put in the if statement's brackets, I've read and heard all the theory I can take. To be honest, with that attitude, you're not going to get very far and you're always going to need people's help. Game programming requires a decent amount of mathematical intuition. Trigonometry, calculus and linear algebra are essential.
Maybe you want to do something like this?
if(bb_collide(player,block)){
velx = 0;
vely = 0;
}
else{
player.setX((player.getX() + velx));
player.setY((player.getY() - vely));
player.set_coll(player.getX(),player.getY(),player.getWidth(),player.getHeight());
block.set_coll(block.getX(),block.getY(),block.getWidth(),block.getHeight());
}
I am working on a program which simulates objects moving in a field. The field has a boundary of 1024x1024. The object cannot go below 0 in terms of x,y coordinate and it cannot go above 1024. I have a method for each object called "move()" which moves the object in its current direction at its current speed. If the object approaches the boundary, it then turns around with a new direction and same speed.
The problem I am having is that when one of my objects gets close to both the x and y bound (corner of the field), it gets stuck in the corner. It is almost as if it is trying to move away from the corner, but then it turns back. It must love that corner. I looked over my code and to me, my logic seems correct. I check to make sure the new direction is not negative or over 359. I check to make sure the new x,y coordinate with the new direction is within the bounds too. I even have a method to set a new direction.
I have tried re-implementing this method with different logic, but no luck. If anyone could possibly find a flaw in my programming or point out what may be causing it, then that would be much appreciated.
I have tried to debug and step through my program and I see that when it gets to the corner, it changes direction to turn around, moves about 3 spaces, then goes back to the corner. Must be a wonderful corner.
Code for move method is below:
public void move(){
localX = super.getX();
localY = super.getY();
float newX=0, newY=0;
float testX, testY;
boolean acceptX = false, acceptY = false;
testX = (float) (Math.cos(direction)*10) + localX;
testY = (float) (Math.sin(direction)*10) + localY;
int testDirection;
while(!acceptX){
if(testX >= 0 && testX <= bound){
newX = testX;
acceptX = true;
}//end if statement
else{
if(direction+180 > 359){
setDirection(direction-180);
testX = (float) (Math.cos(Math.toRadians(direction))*speed) + localX;
}
else{
setDirection(direction+180);
testX = (float) (Math.cos(Math.toRadians(direction))*speed) + localX;
}
}//end else
}//end while that checks for X value
while(!acceptY){
if(testY >= 0 && testY <= bound){
newY = testY;
acceptY = true;
}//end if statement
else{
if(direction+180 > 359){
setDirection(direction-180);
testY = (float) (Math.sin(Math.toRadians(direction))*speed) + localY;
}
else{
setDirection(direction+180);
testY = (float) (Math.sin(Math.toRadians(direction))*speed) + localY;
}
}//end else
}//end while that checks for Y value
super.setX(newX);
super.setY(newY);
}
and here is the code for setDirection
public void setDirection(int d) {
direction = d;
}
Say you have an object in the upper left corner, going up. Your first test turns it around so it goes down. Then comes your second check, which turns it around again to go up... again.
Your code could also use some more readability. The very first thing I noticed is that you're using the >359 checks to normalize the new direction to go in. Yet all cases include the movement code as well. I would do something like:
setDirection(direction + 180); //turn around
if (direction >= 360) direction -= 360; //normalize
testY = ...; //move
to move the movement code out of the direction checking if/else blocks. 360 is also a better magic number to use; 359 degrees means nothing. As has been suggested, you should ultimately use a vector library and thus throw away most of the math.
I'd really recommend storing your direction as a vector (x, y) instead of calculating that vector from a scalar; I think that would help you immensely with your code.
Issue: When your object hits an edge, you turn it 180 degrees. If it hits both edges, it'll spin in place, and the test coordinates will always be in the wrong spot.
When one of your objects hits an edge, it needs to bounce, not About Face! Angle of incidence == angle of refraction, or some such. In other words, if you're checking the x coordinate and it bounces, negate the x velocity, not both x & y.