Java collision detection and player movement: tips
- by Loris
I have read a short guide for game develompent (java, without external libraries). I'm facing with collision detection and player (and bullets) movements.
Now i put the code. Most of it is taken from the guide (should i link this guide?). I'm just trying to expand and complete it.
This is the class that take care of updates movements and firing mechanism (and collision detection):
public class ArenaController {
private Arena arena;
/** selected cell for movement */
private float targetX, targetY;
/** true if droid is moving */
private boolean moving = false;
/** true if droid is shooting to enemy */
private boolean shooting = false;
private DroidController droidController;
public ArenaController(Arena arena) {
this.arena = arena;
this.droidController = new DroidController(arena);
}
public void update(float delta) {
Droid droid = arena.getDroid();
//droid movements
if (moving) {
droidController.moveDroid(delta, targetX, targetY);
//check if arrived
if (droid.getX() == targetX && droid.getY() == targetY)
moving = false;
}
//firing mechanism
if(shooting) {
//stop shot if there aren't bullets
if(arena.getBullets().isEmpty()) {
shooting = false;
}
for(int i = 0; i < arena.getBullets().size(); i++) {
//current bullet
Bullet bullet = arena.getBullets().get(i);
System.out.println(bullet.getBounds());
//angle calculation
double angle = Math.atan2(bullet.getEnemyY() - bullet.getY(), bullet.getEnemyX() - bullet.getX());
//increments x and y
bullet.setX((float) (bullet.getX() + (Math.cos(angle) * bullet.getSpeed() * delta)));
bullet.setY((float) (bullet.getY() + (Math.sin(angle) * bullet.getSpeed() * delta)));
//collision with obstacles
for(int j = 0; j < arena.getObstacles().size(); j++) {
Obstacle obs = arena.getObstacles().get(j);
if(bullet.getBounds().intersects(obs.getBounds())) {
System.out.println("Collision detect!");
arena.removeBullet(bullet);
}
}
//collisions with enemies
for(int j = 0; j < arena.getEnemies().size(); j++) {
Enemy ene = arena.getEnemies().get(j);
if(bullet.getBounds().intersects(ene.getBounds())) {
System.out.println("Collision detect!");
arena.removeBullet(bullet);
}
}
}
}
}
public boolean onClick(int x, int y) {
//click on empty cell
if(arena.getGrid()[(int)(y / Arena.TILE)][(int)(x / Arena.TILE)] == null) {
//coordinates
targetX = x / Arena.TILE;
targetY = y / Arena.TILE;
//enables movement
moving = true;
return true;
}
//click on enemy: fire
if(arena.getGrid()[(int)(y / Arena.TILE)][(int)(x / Arena.TILE)] instanceof Enemy) {
//coordinates
float enemyX = x / Arena.TILE;
float enemyY = y / Arena.TILE;
//new bullet
Bullet bullet = new Bullet();
//start coordinates
bullet.setX(arena.getDroid().getX());
bullet.setY(arena.getDroid().getY());
//end coordinates (enemie)
bullet.setEnemyX(enemyX);
bullet.setEnemyY(enemyY);
//adds bullet to arena
arena.addBullet(bullet);
//enables shooting
shooting = true;
return true;
}
return false;
}
As you can see for collision detection i'm trying to use Rectangle object. Droid example:
import java.awt.geom.Rectangle2D;
public class Droid {
private float x;
private float y;
private float speed = 20f;
private float rotation = 0f;
private float damage = 2f;
public static final int DIAMETER = 32;
private Rectangle2D rectangle;
public Droid() {
rectangle = new Rectangle2D.Float(x, y, DIAMETER, DIAMETER);
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
//rectangle update
rectangle.setRect(x, y, DIAMETER, DIAMETER);
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
//rectangle update
rectangle.setRect(x, y, DIAMETER, DIAMETER);
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
public float getRotation() {
return rotation;
}
public void setRotation(float rotation) {
this.rotation = rotation;
}
public float getDamage() {
return damage;
}
public void setDamage(float damage) {
this.damage = damage;
}
public Rectangle2D getRectangle() {
return rectangle;
}
}
For now, if i start the application and i try to shot to an enemy, is immediately detected a collision and the bullet is removed!
Can you help me with this? If the bullet hit an enemy or an obstacle in his way, it must disappear.
Ps: i know that the movements of the bullets should be managed in another class. This code is temporary.
update
I realized what happens, but not why. With those for loops (which checks collisions) the movements of the bullets are instantaneous instead of gradual.
In addition to this, if i add the collision detection to the Droid, the method intersects returns true ALWAYS while the droid is moving!
public void moveDroid(float delta, float x, float y) {
Droid droid = arena.getDroid();
int bearing = 1;
if (droid.getX() > x) {
bearing = -1;
}
if (droid.getX() != x) {
droid.setX(droid.getX() + bearing * droid.getSpeed() * delta);
//obstacles collision detection
for(Obstacle obs : arena.getObstacles()) {
if(obs.getRectangle().intersects(droid.getRectangle())) {
System.out.println("Collision detected");
//ALWAYS HERE
}
}
//controlla se è arrivato
if ((droid.getX() < x && bearing == -1)
|| (droid.getX() > x && bearing == 1))
droid.setX(x);
}
bearing = 1;
if (droid.getY() > y) {
bearing = -1;
}
if (droid.getY() != y) {
droid.setY(droid.getY() + bearing * droid.getSpeed() * delta);
if ((droid.getY() < y && bearing == -1)
|| (droid.getY() > y && bearing == 1))
droid.setY(y);
}
}