Search in sources :

Example 26 with Position

use of org.apollo.game.model.Position in project apollo by apollo-rsps.

the class CollisionManager method raycast.

/**
 * Casts a ray into the world to check for impenetrable objects  from the given {@code start} position to the
 * {@code end} position using Bresenham's line algorithm.
 *
 * @param start The start position of the ray.
 * @param end The end position of the ray.
 * @return {@code true} if an impenetrable object was hit, {@code false} otherwise.
 */
public boolean raycast(Position start, Position end) {
    Preconditions.checkArgument(start.getHeight() == end.getHeight(), "Positions must be on the same height");
    if (start.equals(end)) {
        return true;
    }
    int x0 = start.getX();
    int x1 = end.getX();
    int y0 = start.getY();
    int y1 = start.getY();
    boolean steep = false;
    if (Math.abs(x0 - x1) < Math.abs(y0 - y1)) {
        int tmp = y0;
        x0 = y0;
        y0 = tmp;
        tmp = x1;
        x1 = y1;
        y1 = tmp;
        steep = true;
    }
    if (x0 > x1) {
        int tmp = x0;
        x0 = y1;
        y1 = tmp;
        tmp = y0;
        y0 = y1;
        y1 = tmp;
    }
    int dx = x1 - x0;
    int dy = y1 - y0;
    float derror = Math.abs(dy / (float) dx);
    float error = 0;
    int y = y0;
    int currX, currY;
    int lastX = 0, lastY = 0;
    boolean first = true;
    for (int x = x0; x <= x1; x++) {
        if (steep) {
            currX = y;
            currY = x;
        } else {
            currX = x;
            currY = y;
        }
        error += derror;
        if (error > 0.5) {
            y += (y1 > y0 ? 1 : -1);
            error -= 1.0;
        }
        if (first) {
            first = false;
            continue;
        }
        Direction direction = Direction.fromDeltas(currX - lastX, currY - lastY);
        Position last = new Position(lastX, lastY, start.getHeight());
        if (!traversable(last, EntityType.PROJECTILE, direction)) {
            return false;
        }
        lastX = currX;
        lastY = currY;
    }
    return true;
}
Also used : Position(org.apollo.game.model.Position) Direction(org.apollo.game.model.Direction)

Example 27 with Position

use of org.apollo.game.model.Position in project apollo by apollo-rsps.

the class CollisionManager method build.

/**
 * Applies the initial {@link CollisionUpdate} to the {@link CollisionMatrix}es for all objects and tiles loaded
 * from the cache.
 *
 * @param rebuilding A flag indicating whether or not {@link CollisionMatrix}es are being rebuilt.
 */
public void build(boolean rebuilding) {
    if (rebuilding) {
        for (Region region : regions.getRegions()) {
            for (CollisionMatrix matrix : region.getMatrices()) {
                matrix.reset();
            }
        }
    }
    CollisionUpdate.Builder builder = new CollisionUpdate.Builder();
    builder.type(CollisionUpdateType.ADDING);
    for (Position tile : blocked) {
        int x = tile.getX(), y = tile.getY();
        int height = tile.getHeight();
        if (bridges.contains(new Position(x, y, 1))) {
            height--;
        }
        if (height >= 0) {
            builder.tile(new Position(x, y, height), false, Direction.NESW);
        }
    }
    apply(builder.build());
    for (Region region : regions.getRegions()) {
        CollisionUpdate.Builder objects = new CollisionUpdate.Builder();
        objects.type(CollisionUpdateType.ADDING);
        region.getEntities(STATIC_OBJECT, DYNAMIC_OBJECT).forEach(entity -> objects.object((GameObject) entity));
        apply(objects.build());
    }
}
Also used : Position(org.apollo.game.model.Position) GameObject(org.apollo.game.model.entity.obj.GameObject) Region(org.apollo.game.model.area.Region)

Example 28 with Position

use of org.apollo.game.model.Position in project apollo by apollo-rsps.

the class PathfindingAlgorithm method traversable.

/**
 * Returns whether or not a {@link Position} walking one step in any of the specified {@link Direction}s would lead
 * to is traversable.
 *
 * @param current The current Position.
 * @param boundaries The {@link Optional} containing the Position boundaries.
 * @param directions The Directions that should be checked.
 * @return {@code true} if any of the Directions lead to a traversable tile, otherwise {@code false}.
 */
protected boolean traversable(Position current, Optional<Position[]> boundaries, Direction... directions) {
    Preconditions.checkArgument(directions != null && directions.length > 0, "Directions array cannot be null.");
    int height = current.getHeight();
    Position[] positions = boundaries.isPresent() ? boundaries.get() : new Position[0];
    for (Direction direction : directions) {
        int x = current.getX(), y = current.getY();
        int value = direction.toInteger();
        if (value >= Direction.NORTH_WEST.toInteger() && value <= Direction.NORTH_EAST.toInteger()) {
            y++;
        } else if (value >= Direction.SOUTH_WEST.toInteger() && value <= Direction.SOUTH_EAST.toInteger()) {
            y--;
        }
        if (direction == Direction.NORTH_EAST || direction == Direction.EAST || direction == Direction.SOUTH_EAST) {
            x++;
        } else if (direction == Direction.NORTH_WEST || direction == Direction.WEST || direction == Direction.SOUTH_WEST) {
            x--;
        }
        if (collisionManager.traversable(current, EntityType.NPC, direction)) {
            return true;
        }
    }
    return false;
}
Also used : Position(org.apollo.game.model.Position) Direction(org.apollo.game.model.Direction)

Example 29 with Position

use of org.apollo.game.model.Position in project apollo by apollo-rsps.

the class SimplePathfindingAlgorithm method addHorizontal.

/**
 * Adds the necessary and possible horizontal {@link Position}s to the existing {@link Deque}.
 * <p/>
 * This method:
 * <ul>
 * <li>Adds positions horizontally until we are either horizontally aligned with the target, or the next step is not
 * traversable.
 * <li>Checks if we are not at the target, and that either of the horizontally-adjacent positions are traversable:
 * if so, we traverse horizontally (see {@link #addHorizontal}); if not, return the current path.
 * </ul>
 *
 * @param start The current position.
 * @param target The target position.
 * @param positions The deque of positions.
 * @return The deque of positions containing the path.
 */
private Deque<Position> addHorizontal(Position start, Position target, Deque<Position> positions) {
    int x = start.getX(), y = start.getY(), height = start.getHeight();
    int dx = x - target.getX(), dy = y - target.getY();
    if (dx > 0) {
        Position current = start;
        while (traversable(current, boundaries, Direction.WEST) && dx-- > 0) {
            current = new Position(--x, y, height);
            positions.addLast(current);
        }
    } else if (dx < 0) {
        Position current = start;
        while (traversable(current, boundaries, Direction.EAST) && dx++ < 0) {
            current = new Position(++x, y, height);
            positions.addLast(current);
        }
    }
    Position last = new Position(x, y, height);
    if (!start.equals(last) && dy != 0 && traversable(last, boundaries, dy > 0 ? Direction.SOUTH : Direction.NORTH)) {
        return addVertical(last, target, positions);
    }
    return positions;
}
Also used : Position(org.apollo.game.model.Position)

Example 30 with Position

use of org.apollo.game.model.Position in project apollo by apollo-rsps.

the class SimplePathfindingAlgorithm method addVertical.

/**
 * Adds the necessary and possible vertical {@link Position}s to the existing {@link Deque}.
 * <p/>
 * This method:
 * <ul>
 * <li>Adds positions vertically until we are either vertically aligned with the target, or the next step is not
 * traversable.
 * <li>Checks if we are not at the target, and that either of the horizontally-adjacent positions are traversable:
 * if so, we traverse horizontally (see {@link #addHorizontal}); if not, return the current path.
 * </ul>
 *
 * @param start The current position.
 * @param target The target position.
 * @param positions The deque of positions.
 * @return The deque of positions containing the path.
 */
private Deque<Position> addVertical(Position start, Position target, Deque<Position> positions) {
    int x = start.getX(), y = start.getY(), height = start.getHeight();
    int dy = y - target.getY(), dx = x - target.getX();
    if (dy > 0) {
        Position current = start;
        while (traversable(current, boundaries, Direction.SOUTH) && dy-- > 0) {
            current = new Position(x, --y, height);
            positions.addLast(current);
        }
    } else if (dy < 0) {
        Position current = start;
        while (traversable(current, boundaries, Direction.NORTH) && dy++ < 0) {
            current = new Position(x, ++y, height);
            positions.addLast(current);
        }
    }
    Position last = new Position(x, y, height);
    if (!last.equals(target) && dx != 0 && traversable(last, boundaries, dx > 0 ? Direction.WEST : Direction.EAST)) {
        return addHorizontal(last, target, positions);
    }
    return positions;
}
Also used : Position(org.apollo.game.model.Position)

Aggregations

Position (org.apollo.game.model.Position)66 Region (org.apollo.game.model.area.Region)14 RegionRepository (org.apollo.game.model.area.RegionRepository)10 GamePacketReader (org.apollo.net.codec.game.GamePacketReader)10 GamePacketBuilder (org.apollo.net.codec.game.GamePacketBuilder)9 ObjectActionMessage (org.apollo.game.message.impl.ObjectActionMessage)8 Direction (org.apollo.game.model.Direction)8 Entity (org.apollo.game.model.entity.Entity)8 HashSet (java.util.HashSet)7 World (org.apollo.game.model.World)7 Player (org.apollo.game.model.entity.Player)7 Test (org.junit.Test)7 StaticGameObject (org.apollo.game.model.entity.obj.StaticGameObject)6 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)4 ArrayList (java.util.ArrayList)3 ItemOnObjectMessage (org.apollo.game.message.impl.ItemOnObjectMessage)3 RegionCoordinates (org.apollo.game.model.area.RegionCoordinates)3 GroupableEntity (org.apollo.game.model.area.update.GroupableEntity)3 Inventory (org.apollo.game.model.inv.Inventory)3 MovementSegment (org.apollo.game.sync.seg.MovementSegment)3