LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: ChaoticCactus on June 28, 2013, 16:37:37

Title: Platformer Collision Detection
Post by: ChaoticCactus on June 28, 2013, 16:37:37
Hello everybody!

So after some experimentation with a simple platformer I've added some features like when you jump on an enemy the player jumps up and a coin goes flying.  ... Ok, that might not be the best explanation, so imagine that its like jumping on a goomba in mario except that a coin falls out of it.  I've got that coin to fall on the ground, mostly because the ground is just flat so I can use code like this:
if(y <= 32) {
           speedX = 0;
           speedY = 0;
           y = 32;
       }


But I know that code like that won't work forever.  The problem is that if the player runs over the coin, nothing happens.  I tried this:
if(Math.abs(x - Game.player.getX()) > 4 || Math.abs(y - Game.player.getY()) > 4) {
           System.out.println("Colliding with the coin!");
       }


But once I touch the coin it just keeps on saying "Colliding with the coin" in the console.  What can I use for a better collision system and how can I get the player to "pick up" the coin?

Thanks!

EDIT: By pick up I mean run it over so that it disappears and then update the score to reflect how many coins you've picked up.
Title: Re: Platformer Collision Detection
Post by: quew8 on June 29, 2013, 10:11:34
Firstly, you should be using an && rather than || in your conditional since it has to be closer than 4 units in the x and y axes.

If you're looking for better collision detection, then I would say this works fine axis aligned bounding boxes (AABB). There is a very simple one for circles (which I presume your coin is). Find the distance from the centre of the first circle to the centre of the second via Pythagoras. If it is less than the sum of the two radii of the circles, then they are colliding. An obvious optimization of this is to test the square of the radii against the square of the distance (gets rid of square route). You can also mix and match this with an polygon by finding the nearest vertex (or even better the nearest point on an edge).

If you ever want to move beyond AABBs and circles (which are often more than enough anyway) then you can look into SAT (separation axis theorem) or the GJK algorithm.

As for "picking up the coin," it depends on the structure of your code. Presumably you have a list of objects to draw somewhere and a score variable. All you have to do is remove the coin from the list (yes very likely you will need some kind of id system) and increment the score by the score of a coin.
Title: Re: Platformer Collision Detection
Post by: ChaoticCactus on June 29, 2013, 15:52:30
Thanks Quew8, I substituted && for || but it doesn't work.  With || the enemy only "dies" when the player jumps on top of them.  But with && the enemy "dies" whenever the player hits the right spot on the Y axis.

At the moment I just went for a simple as possible and I only have 4 classes:

Game, Player, Coin, and Enemy.

So there's no inheritance, but I do draw the coins through an arrayList.  I've tried just adding: Game.coinList.remove();  But I odn't know what parameter to put in the remove() call, as it takes either an integer or an object (I've tried remove(new Con(x, y)) but that didn't work). 

So if you could explain that to me that would be fantastic!

Thanks again!
Title: Re: Platformer Collision Detection
Post by: broumbroum on June 29, 2013, 17:43:46
if you use List's to store your coins, or anyother objects, you always have to check the equals() consistency. Lists check for equality to hold Object's. So it's a basic Java problem, each of your instances of the class Coin must return true for equals() if the "other" Coin is in X,Y.

Unlike HashMap that may rather be used for caches, the List doesn't check the hashCode() value. However, the Java equality contract is to ensure that hashCode() values are always consistent with the equals() function : that is if the hashCode is equal to another object's hashCode, then equals() must return true for these two objects (they might not be the same instances, but are acknowledged as equal). Then any of your coins could return as hashCode() the value : new String("X, Y").hashCode(), for instance.

class Coin {
int x, y;
Coin(int x,int y) {init..}

@Override
public void equals(Object o) {
   return o != null ? o.hashCode() == hashCode();
}

@Override
public int hashCode() {
return ("coin x, y").hashCode();
}
}
Title: Re: Platformer Collision Detection
Post by: ChaoticCactus on June 30, 2013, 03:23:41
Ok, to be honest I didn't really understand much of that... =\  I've never used hashcodes and such before.  Is there just a way that I can call remove() ?
Title: Re: Platformer Collision Detection
Post by: broumbroum on June 30, 2013, 08:34:44
I'm sorry this is a bit off topic ..

You need collision detection, but the first thing is to ensure that your List is correctly sorted (this really is Java basics).
Here is a link to Java Tutorials about using Collections and thus List with the Comparable interfaces. Because it's about ordering your classes (the Coin).
http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html


Then you have to implement the methods I posted above . :)