Merge pull request #414 from ryleykimmel/enhancement/orientation-duplicate

Remove duplicate GameObject rotated checks
This commit is contained in:
Major
2019-03-29 22:38:42 +00:00
committed by GitHub
4 changed files with 64 additions and 37 deletions
@@ -63,21 +63,4 @@ fun Mob.walkTo(target: Position, positionPredicate: ((Position) -> Boolean)? = n
/**
* Returns the bounding size of the specified [Entity], in [x-size, y-size] format.
*/
private fun bounds(target: Entity): Pair<Int, Int> {
return when (target) {
is GameObject -> {
val orientation = Direction.WNES[target.orientation]
val rotated = (orientation == Direction.WEST || orientation == Direction.EAST)
val definition = target.definition
val width = if (rotated) definition.length else definition.width
val height = if (rotated) definition.width else definition.length
Pair(width, height)
}
is Npc -> Pair(target.definition.size, target.definition.size)
is Player -> Pair(1, 1)
else -> error("Invalid entity type")
}
}
private fun bounds(target: Entity): Pair<Int, Int> = Pair(target.width, target.length)
@@ -195,23 +195,16 @@ public final class CollisionUpdate {
}
int x = position.getX(), y = position.getY(), height = position.getHeight();
int width = definition.getWidth(), length = definition.getLength();
boolean impenetrable = definition.isImpenetrable();
int orientation = object.getOrientation();
// north / south for walls, north east / south west for corners
if (orientation == 1 || orientation == 3) {
width = definition.getLength();
length = definition.getWidth();
}
if (type == FLOOR_DECORATION.getValue()) {
if (definition.isInteractive() && definition.isSolid()) {
tile(new Position(x, y, height), impenetrable, Direction.NESW);
}
} else if (type >= DIAGONAL_WALL.getValue() && type < FLOOR_DECORATION.getValue()) {
for (int dx = 0; dx < width; dx++) {
for (int dy = 0; dy < length; dy++) {
for (int dx = 0; dx < object.getWidth(); dx++) {
for (int dy = 0; dy < object.getLength(); dy++) {
tile(new Position(x + dx, y + dy, height), impenetrable, Direction.NESW);
}
}
@@ -13,6 +13,9 @@ import org.apollo.game.model.entity.Player;
import com.google.common.base.MoreObjects;
import static org.apollo.game.model.entity.obj.ObjectType.RECTANGULAR_CORNER;
import static org.apollo.game.model.entity.obj.ObjectType.TRIANGULAR_CORNER;
/**
* Represents an object in the game world.
*
@@ -86,21 +89,32 @@ public abstract class GameObject extends Entity implements GroupableEntity {
return packed >> 2 & 0x3F;
}
@Override
public int getLength() {
Direction direction = Direction.WNES[getOrientation()];
return direction == Direction.WEST || direction == Direction.EAST ?
getDefinition().getWidth() : getDefinition().getLength();
return isRotated() ? getDefinition().getWidth() : getDefinition().getLength();
}
@Override
public int getWidth() {
Direction direction = Direction.WNES[getOrientation()];
return isRotated() ? getDefinition().getLength() : getDefinition().getWidth();
}
return direction == Direction.WEST || direction == Direction.EAST ?
getDefinition().getLength() : getDefinition().getWidth();
/**
* Returns whether or not this GameObject's orientation is rotated {@link Direction#WEST} or {@link Direction#EAST}.
*
* @return {@code true} iff this GameObject's orientation is rotated.
*/
public boolean isRotated() {
int orientation = getOrientation();
int type = getType();
Direction direction = Direction.WNES[orientation];
if (type == TRIANGULAR_CORNER.getValue() || type == RECTANGULAR_CORNER.getValue()) {
direction = Direction.WNES_DIAGONAL[orientation];
}
return direction == Direction.NORTH || direction == Direction.SOUTH
|| direction == Direction.NORTH_WEST || direction == Direction.SOUTH_EAST;
}
@Override
@@ -85,9 +85,10 @@ public final class CollisionManagerTests {
assertUntraversable(collisionManager, back, Direction.SOUTH_EAST);
}
/**
* Tests that a corner wall is untraversable from the sides that it blocks. Corners are much like walls, with
* the only difference being their orientation. Instead of {@link Direction#WNES}, they have diagonal directions.
* Tests that a corner triangular wall is untraversable from the sides that it blocks. Corners are much like walls,
* with the only difference being their orientation. Instead of {@link Direction#WNES}, they have diagonal directions.
* With a corner wall at (0, 1) facing to the north-east we end up with a grid looking like this:
* <p>
* <pre>
@@ -121,6 +122,42 @@ public final class CollisionManagerTests {
assertUntraversable(collisionManager, back, Direction.SOUTH_WEST);
}
/**
* Tests that a corner rectangle wall is untraversable from the sides that it blocks. Corners are much like walls,
* with the only difference being their orientation. Instead of {@link Direction#WNES}, they have diagonal directions.
* With a corner wall at (0, 1) facing to the north-east we end up with a grid looking like this:
* <p>
* <pre>
* (0,2) |---------|---------|
* | | |
* | | |
* | |xxx |
* (0,1) |---------|---------|
* | xxx| |
* | | |
* | | |
* (0,0) |---------|---------|
* (1,0) (2,0) (3,0)
* </pre>
* <p>
* Where you can walk north and east through the tile the corner occupies, as well as south and west through the
* adjacent tile, but not north-east or south-west.
*/
@Test
public void rectangleWall() {
Position front = new Position(0, 1, 0);
Position back = front.step(1, Direction.NORTH_EAST);
CollisionManager collisionManager = createCollisionManager(
createMapObject(WALL, front, ObjectType.RECTANGULAR_CORNER, Direction.NORTH_EAST)
);
assertTraversable(collisionManager, front, Direction.NORTH, Direction.EAST);
assertUntraversable(collisionManager, front, Direction.NORTH_EAST);
assertTraversable(collisionManager, back, Direction.SOUTH, Direction.WEST);
assertUntraversable(collisionManager, back, Direction.SOUTH_WEST);
}
/**
* Tests that the tiles occupied by a 2x2 square object are not traversable. When an interactable object is added
* to a collision update, all tiles spanning its with and length from its origin position will be marked as completely