Update!
That works a treat! Thanks for the suggestion.
In case anyone else has this problem, I’ve posted my code below to handle player-vs-enemy collisions. It will push the player away from the enemy by a set amount (the variable for this in the code is called ‘pushStrength’). The beauty of this is that I don’t need to now do any per-enemy checks either, since the pushing back means you can’t really ever be ‘intersecting’ with an enemy, even if you’re standing still.
Here’s some notes about the code:
This is the code block from the collision detection algorithm that runs every tick. There is an arraylist that stores Mob class objects - just an abstractions of an enemy definition. The code cycles through each mob in the playfield, testing its bounding rectangle with the bounding rectangle points of the player object.
I’ve restricted this so that only one collision can be solved per tick, which should help clear up redundant calculations when colliding with more than one enemy at once (unlikely).
When a collision is detected (collision = true), I simply calculate the angle of the vector between the two objects - the player and the enemy - then use this as the ‘push’ vector to force the player away from the mob by a set amount (pushStrength).
It works great!
// check collisions with mobs
if (!collision)
{
for (Mob m : moblist)
{
if (!collision)
{
// test collision
Rectangle mobBox = new Rectangle();
mobBox.x = (int)(m.actualX + Mob.collBoxMargin);
mobBox.y = (int)(m.actualY + Mob.collBoxMargin);
mobBox.width = (int)(Level.TILE_SIZE - (Mob.collBoxMargin * 2));
mobBox.height = (int)(Level.TILE_SIZE - (Mob.collBoxMargin * 2));
if (pointInside(tl, mobBox)) { canGoTL = false; collideRefX = m.tileX; collideRefY = m.tileY; collision = true; }
if (pointInside(tr, mobBox)) { canGoTR = false; collideRefX = m.tileX; collideRefY = m.tileY; collision = true; }
if (pointInside(bl, mobBox)) { canGoBL = false; collideRefX = m.tileX; collideRefY = m.tileY; collision = true; }
if (pointInside(br, mobBox)) { canGoBR = false; collideRefX = m.tileX; collideRefY = m.tileY; collision = true; }
if (collision)
{
double mcx = mobBox.x + (Level.TILE_SIZE / 2);
double mcy = mobBox.y + (Level.TILE_SIZE / 2);
double ang = Math.atan2(cy - mcy, cx - mcx) * (180 / Math.PI);
speedX = 0;
speedY = 0;
dx = 0;
dy = 0;
double newPX = pushStrength * Math.cos(GameUtils.DegToRad(ang));
double newPY = pushStrength * Math.sin(GameUtils.DegToRad(ang));
x += newPX;
y += newPY;
actualX = level.scrollX + x;
actualY = level.scrollY + y;
}
}
}
}