How to handle collision after detecting it - java

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());
}

Related

How can I determine which side collision has occured from (Java)

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
}

how to check two rectangles are touching from left or top or right

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.

How to stop a ball from bouncing after the position hasnt changed much libgx java

I am writing a physics engine and when the ball hits a surface it bounces up at half the velocity it came down at(velocity.y = -velocity). However when the ball is almost at rest it switches velocities constantly and starts falling through the platform incredibly slow but still will eventually fall through if I let it run long enough, and this is not acceptable. I tried writing some code to stop it but it checks way too fast here is the update method that attempts to check it.
public void update() {
velocity.y += Globals.GRAVITY.y;
if(canFall)
position.y += velocity.y;
position.x += velocity.x;
oldPosition.y = position.y;
oldPosition.x = position.x;
elapsedTime += 1 * Gdx.graphics.getDeltaTime();
if(elapsedTime >= 5){
if(oldPosition.y - 5 <= position.y && oldPosition.y + 5 >= position.y){
elapsedTime = 0;
canFall = false;
}else{
canFall = true;
elapsedTime = 0;
}
}
}
The collision handler knows when it hits the top of the ball which is the only solution I need for this. How do I check when the ball is at rest.
This code attempts to check if the ball hasn't moved in a couple seconds, if it hasn't it sets canFall to false. I need a generic check that will see if the ball should be at a stop. The velocity of the ball when it is falling through the platform you can see from the picture below. The picture shows the ball "at rest" after ten seconds so as you can see the ball is slowly but surely falling through. Every three seconds with this "rest" velocity the y position goes down 1, the velocity changes from positive to negative so the velocity you see in the picture isn't constantly negative. Ignore the elapsed time variable Any help is greatly appreciated!
Why let time have anything to do with it? I'm not saying it coudln't, but should it? So maybe lose the if(elapsedTime ... ) conditional.
Isn't this what you want? If the magnitiude of the vertical difference between the last two positions is negligible (set tolerance accordingly; maybe it's 5), stop bouncing:
if(Math.abs(position.y - oldPosition.y) < tolerance)
{
canBounce = false;
...
}
else
{
canBounce = true;
...
}
or, if nothing else needs to change at the ... above:
canBounce = Math.abs(position.y - oldPosition.y) > tolerance;
Also, don't you need { and } somewhere in the segment below? Maybe not, if ball is bouncing vertically, but it looks like x can change, too, which might make the code above need adjusting. But the way code below is indented makes me think there's supposed to be more to do than just changing position.y:
if(canFall)
position.y += velocity.y;
position.x += velocity.x;
oldPosition.y = position.y;
oldPosition.x = position.x;
Finally, you're addding velocity to position. That seems questionable. Multiply velocity times time? Or is time = 1 always? (Doubt it.)
The problem may be external to this method. Something needs to keep ball's y from becoming less than the y of the top of the dark blue box. This code can't do that without knowing y of top of dark blue box (unless you apply physics formulas?). Maybe include this value in parameter list as topOfDarkBlueBox?
Then add code such as:
if(position.y < topOfDarkBlueBox.y) position.y = topOfDarkBlueBox.y
I'd rather see physics at work, but you might say, "Who'd notice?"
EDIT
You wrote, "The collision handler knows when it hits the top of the ball," but I assume you meant "when the ball hits the top of the dark blue box". Maybe call the collision handler instead of passing new parameter topOfDarkBlueBox?

Proper Collision

So basically im trying to figure out how to make a proper collision between two Rectangles.
Detecting isn't the problem, but the rectangles begin to clip. I wanted to reset the position, but how do I do that.
I'm trying to use dx and dy to reset, but it won't reset to the right coordinates.
http://i.stack.imgur.com/IU6sK.png (Sorry I can't use images yet)
System.out.println(this.y + this.h + " " + e.getY());
if(this.y + this.h >= e.getY())
{
if(this.dy > 0)
{
this.y -= delta * this.dy + 0.1;
this.dy = 0;
}
else
{
this.y += delta * this.dy;
this.dy = 0;
this.inAir = false;
}
}
This code is just an example to show how I am trying it for the top. (this = the white Rectangle and e = the orange one) I used my class Entity, which extends Rectangle.
I'm checking intersection before I call this. This is a function in the "white" Entity and the intersection is checked in the update function of the main loop.
If I use this, there is like 1px between the rectangles.
Any ideas?
Thanks for any help :)
http://docs.oracle.com/javase/6/docs/api/java/awt/Rectangle.html
Use the Rectangle class.
Here, some code
http://pastebin.com/raw.php?i=TzkST3Hm
The best way to do rectangular collision is to use the Rectangle class to detect collision using the .intersects(Rectangle) method, and then calculate a new variable called displacementX and displacementY.
displacementX = Math.abs(entitiy1.getX() - entity2.getX());
displacementY = Math.abs(entitiy1.getY() - entity2.getY());
So what we have currently is the amount of pixels entity1 is intruding on entity2 (or vice versa due to the absolute value). Then, run some comparisons and move entity1 (or entity2) by the value of the lesser displacement, which should yield perfect-looking collision.
This is at least how I do it. The correct method for rectangular collision is to:
1) Determine if they collide
2) Correct it
3) Render
Simply preventing movement after detecting collision will look horrible (especially on low frame rates).
Hope I helped!
~Izman

Moving objects getting stuck in a corner

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.

Categories