Skip to content

Isometric Collisions and Hitboxes

Ethan Roderick edited this page Oct 19, 2021 · 3 revisions

Details

Sprint 3

As the game transitioned from orthogonal to isometric view, various components of the orthogonal system had to be altered. This page documents the changes made concerning entity hitboxes and collision boxes.

At the beginning of sprint 3, collision and boundary boxes were based on the orthogonal grid, rather than isometric. The first step to temporarily resolve this, was rotation of the rectangular boxes; however, this implementation had misaligned overlap (as the pieces were placed on an isometric grid).

The next iteration involved using the mathematical tangent function and the isometric angles to calculate vector points for an isometric grid. This was misaligned by just a few pixels around corners. Additionally, this method also caused the placement of the collision boxes to be wrong, relative to the containing hitbox.

To fix this issue, the coordinate system used for the isometric shape's corners was made relative to a provided position, allowing for the boxes to be centred.

Finally, as the game engine emulates an isometric view using a 1:2 ratio, this ratio was used to calculate near perfect isometric vector positions.

Sprint 4

After the changes to the hitboxes were implemented, they were applied to entities that did not fit neatly into a square tile space. As such, the hitboxes for these objects did not work as intended, as shown below. In the image, we can see the bed entities have collision boxes that are very squashed parallelograms due to their textures takins the space of two tiles, rather than one. Additionally, the desk entities have collision components that far exceed the size of the entity, due to scaling issues.

Furthermore, after consideration into the applications of collision boxes and their expected usage, it was realised that the method of basing box size on the entity size would not be the best approach, and going forward the two should be disconnected. This is because only part of an entity requires collisions with the player, with other regions of the texture allowing overlap to give the illusion of depth.

For example, take a Grandfather clock entity. This object would have a large texture and overall entity size, however, as the object takes up most of its space in the z direction, the player should be able to stand "behind" said grandfather clock. In this case, the collisions we require should simply correspond to the area of the grandfather clock that contacts with the floor, providing the illusion of depth and three dimensions. To demonstrate, the following image outlines an example entity shape with green highlighting the intended collision box area.

To accomplish this, the component shape creator was changed to take the intended size of the collision area, in terms of tile units for both axes of the shape. With this new implementation rectangles of any size can be implemented in an isometric fashion. For example, the following screenshot shows the player with a collision box measuring two tile units by half a tile unit (This collision box was set to serve as an example).

Implementation

Current

The implementation for any isometric rectangle is as follows:

        Vector2 south = isoVector2(position.x, position.y);
        Vector2 east = isoVector2(position.x + right, position.y + right);
        Vector2 north = isoVector2(position.x + right - left, position.y + right + left);
        Vector2 west = isoVector2(position.x - left, position.y + left);

Where left and right are the sides of the box in tile units, and position is the offset calculated by any supplied offset values and the bottom-middle alignment.

Older Implementations

Entity Scaling Method

This was the implementation of best fitting isometric boxes uses a 1:2 ratio. That is, for every 1 unit of height in the texture, there are 2 units of width (this defines the points of the parallelogram). As such, the isometric boxes can be represented by the following four vectors:

      Vector2 west = new Vector2(position.x - (size.x / 2), (height / 2));
      Vector2 north = new Vector2(position.x, height);
      Vector2 east = new Vector2(position.x + (size.x / 2), (height / 2));
      Vector2 south = new Vector2(position.x, 0);

Where height is defined as float height = 0.5f * size.y; to maintain the 1:2 ratio, and position is the position to offset the vectors for centring.

Tangential Method

The implementation prior to the 1:2 solution utilised the Math.tan function to create an isometric border with 60 and 30 degree side angles. This implementation was similar to the above solution:

      double isoAngle = Math.toRadians(30);
      float height = (float) Math.tan(isoAngle) * size.y;

      Vector2 west = new Vector2(position.x - (size.x / 2), (height / 2));
      Vector2 north = new Vector2(position.x, height);
      Vector2 east = new Vector2(position.x + (size.x / 2), (height / 2));
      Vector2 south = new Vector2(position.x, 0);
Clone this wiki locally