Precise Entity Selection - UQdeco2800/2022-studio-3 GitHub Wiki

Introduction

As the game has become more developed and closer to completion, it has become necessary for increasingly large and complicated sprite designs - especially in the city buildings. Whilst this is great from a visual perspective, it has posed a severe gameplay impediment, as the legacy implementation of building selection is no longer sufficient to deal with a large number of overlapping textures.

Issue

Previously, selection worked one of two ways:

  1. Buildings specifically could be selected by their hitbox
  2. Every other entity would be selected by their texture's bounding box

This was deemed an issue, as building hitboxes only surrounded the base, leaving large areas of the structure unclickable, and other entities could easily overlap by their texture box (as shown below - figure indicating the overlapping texture bounds of each building in the city).

These overlapping boxes were causing multiple buildings, and even units to be selected concurrently, when the user only intended to select one.

Solution - SelectionCollider

The solution to the aforementioned issues was to create a new component - SelectionCollider.java - which, when attached to an entity that contains a SelectableComponent and a TextureRenderComponent, can provide a separate hitbox that bounds the entity's texture and allows for a precise selection. The rationale, motivation and implementation was similar in theory to the existing method to create hitboxes for buildings: a set of pixel vertices were established around each building texture, to form a polygon that would allow selection when clicked.

The SelectionCollider interfaces with the pre-existing SelectableComponent, to check if an input click from a user occurs within the collider's polygon, meaning, once attached, the SelectionCollider will instantly provide precise selection to any pre-existing selectable entity. This choice was conscious to accommodate for other studio members who wish to add it.

How to add a SelectionCollider to an Entity

Firstly, it should be noted that a SelectionCollider should ONLY be added to an Entity with a TextureRenderComponent and a SelectableComponent. Doing so without these may cause unpredicted behaviour.

Secondly, an array of floats must be declared, containing pairs of floats corresponding to (x,y) pixel coordinates on the image. These form the vertices of a polygon that will be used for selection.

After adding a SelectionCollider to an entity, and after scaling it using TextureScaler.setPreciseScale() OR entity.scaleWidth(), you must then call SelectionCollider.setPoints() to pass the array of floats to the collider.

An example implementation is given as follows - with many more available for observation in BuildingFactory.java

        Entity townHall = createBaseBuilding();
        float[] selectionPoints = new float[] {
                2f, 608f,
                505f, 855f,
                962f, 507f,
                941f, 154f,
                506f, 108f,
                179f, 346f
        };
        townHall.addComponent(new TextureRenderComponent("images/level 1 town hall.png"))
                .addComponent(new SelectableComponent())
                .addComponent(new SelectionCollider());
        //Scale entity BEFORE calling setPoints()
        townHall.getComponent(TextureScaler.class).setPreciseScale(TH_SCALE, true);
        //Set selection hitbox
        townHall.getComponent(SelectionCollider.class).setPoints(selectionPoints);

Testing

As this solution is largely intangible, both experimental and unit testing were employed to verify the integrity of SelectionCollider

Unit testing

Unit tests were constructed which test the following

  1. Given a set point that should lie within the hitbox of the collider, when this point is tested against the collider in game, does it recognise that the point is in the selected hitbox?
  2. Given a set point that should lie outside of the collider hitbox, when this point is tested against the collider in game, does it recognise that the point is out of the selected hitbox?

These two tests in tandem work to verify that the hitbox can correctly detect when an entity is selected

Experimental testing

The results of the implementation can also be tested visually in game by using the debug mode, which draws all hitboxes over objects. Although this hitbox is a sensor (i.e. will not impede unit movement) it is still drawn by the debug mode, so it is very easy to see whether a selection hitbox is performing correctly

  • Debug mode e.g Building Selection Hitboxes in debug mode

Although the above image is very cluttered, it is clear that hitboxes extend around the texture of buildings

  • Verifying through clicks

Finally, the hitbox was tested against its hitbox in debug mode, by clicking vacant tiles around the hitbox to ensure the building wasn't selected, then the points inside the hitbox were clicked to verify that it did indeed select