How do I add collision between player projectile and enemies?

I’m making a 2d tile based game, and I have implemented collision between the player and wall tiles.
I did this by placing each tile in an array, and then giving the player’s position an index in the array

However, this type of collision only works between one moving and one stationary tile.
I’m now trying to implement enemies and projectiles, which means my current collision won’t work because they should be able to collide when travelling between tiles.

How can I create collision between moving players, moving projectiles, and moving enemies?
They’re all 20x20 sprites

I’ve tried following most of the rectangle collision guides, but I can’t seem to figure out how to apply it to my game because there will be multiple enemies and projectiles which are changing in position every frame

Hi @Marfmamow,

At each frame, for every object that can collide you need to check if it collides with any of all other objects (except itself).

This depends on what you want:

  • Do projectiles collide with other projectiles? Same for enemies?
  • Do projectiles kill enemies?
  • Do you have multiple players?
  • Is your player hitbox the whole tile or the size of the sprite?

Also you might want to use Java’s object oriented features, specially abstract classes. Abstract classes define a “template” for classes that you need to implement later.

For example you might have a Collidable abstract class that is defined like so:

abstract class Collidable {
  int x, y, w, h;

  Collidable(int x, int y, int w, int h) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
  }

  boolean isCollidingWith(Collidable other) {
    // Rectangle / Rectangle collision
    return x + w > other.x 
      && y + h > other.y 
      && x < other.x + other.w
      && y < other.y + other.h;
  }
}

class Player extends Collidable {
  Player(int x, int y, int w, int h) {
    super(x, y, w, h);
  }
}

class Enemy extends Collidable {
  Enemy(int x, int y, int w, int h) {
    super(x, y, w, h);
  }
}

Each collidable object has coordinates and size (assuming they are all rectangular shaped) and has a default implementation of rectangle collision. Then you can define a Player and Enemy class extending the collidable class so that they get the collision behavior without re-implementing it.

You can then test for collision with every object that is Collidable (thanks to polymorphism):

Player player = new Player(0, 0, 50, 50);
Enemy enemy = new Enemy(30, 30, 20, 20);

println(player.isCollidingWith(enemy));

// => true

Bonus: here is an example on how you can implement collision for objects with different shapes

Linked to your previous post:

3 Likes

Thanks! I want the player to be able to collide with the enemies and the enemies projectile. The player and enemy projectiles should also be able to collide

The player projectiles are stored in an array list. The enemies are also stored in an arraylist, and their projectiles will be in their own array list as well.

Would I have to loop through each of these array lists every draw() and check for collision?

1 Like

Yes it’s probably the most straight forward solution. The logic can be extracted into its own system as stated here:

1 Like

I’m currently working on changing my wall collision to this type of collision.
I’ve managed to get the player to recognise that its collided with the wall, but how do I make it stop when it touches the wall? Right now the player still goes into the wall, but knows its collided with a wall.

I’m controlling the player using arrow keys

If it’s a tile based game, you can try to move temporarily the player then if it collides with something you don’t move it.

Or you before you move you can check if the corresponding tile (up, down, left, right) has a wall and if yes you don’t move.

2 Likes

Maybe something like this: if (!collided()) move();

1 Like

Good comments already

Or set a marker like hasCollided=true;

And then evaluate it so that it cannot move when it’s true

1 Like

I’ve managed to get two moving objects to detect whether they’ve touched or not, but currently it only works when the center of the sprites touch.

I tried adding the sprite width and height into the collision check, but it still doesn’t work.
This is what I have:

boolean collidingWith(Collidable other){
        return x + w + movementSpeed> other.x &&
               x - movementSpeed< other.x + other.w &&
               y + h + movementSpeed> other.y &&
               y - movementSpeed < other.y + other.h;
    }

It also doesn’t work very consistently when both objects are moving

2 Likes

You can also use the dist() command

2 Likes

Hello!
An EXCELLENT tutorial here on the Happy Coding site:

:nerd_face:

4 Likes