StructureComponents - UQdeco2800/2022-studio-1 GitHub Wiki

Introduction

To create the specialised behaviour demonstrated in the specialised structure entities, several components were created to give the desired behaviour. These components are critical to the studio as a whole, as they allow for integration with other game systems, i.e.:

  • The ResourceCostComponent allows the integration of structures with the game's economy, allowing players to regain resources for selling their structures (and in doing so, not be unjustly punished for mistakes such as placing structures incorrectly)
  • The TrapComponent allows the creation of Trap objects, and creates more variety in buildable structures, creating a better gameplay experience
  • The RangeAttackComponent allows structures to damage enemies at range, which enables the basic gameplay loop of tower-defence games

Component

These components and their associated effects are described below.

ResourceCostComponent

The ResourceCostComponent was created to assign unique costs to each buildable structure. Buildings require different amounts of gold, stone and wood to be purchased from the shop, and the ResourceCostComponent provides the implementation of this, as well as various methods to return the associated costs of each structure.

TrapComponent

The TrapComponent was largely based off of the TouchAttackComponent (which provides functionality to damage entities that collide with the owner of the component), with the main difference being that that upon damaging enemies, the Trap is removed from the game world.

RangeAttackComponent

The RangeAttackComponent provides functionality for the owner to damage enemies that come within the provided range. It continuously damages an enemy (designated as the target), until the enemy either dies or exits the structures range.

Progress / Challenges

Whilst the development of the first two components was uneventful, the development of the RangeAttackComponent faced some major setbacks. Initial development of this component focused on utilising the systems and knowledge available at the start of Sprint 2. The component is shown by the code snippet below:

    /*
     * Function which provides the means to damage enemies which are within a certain range. 
     * For use on structures only. 
    */
    @Override
    public void update() {
        System.out.println("Running RAT");
        if (targetAcquired) {
            System.out.println("target acquired true");
            if (getDistanceToTarget(this.target) <= this.range) {
                while (getDistanceToTarget(entity) <= this.range) {
                    attackTarget();
                }
            } else {
                //Toggle targetAcquired, and set acquired target to null
                toggleTargetAcquired();
                this.target = null;
            }
        } else {
            for (Entity entity : ServiceLocator.getEntityService().getEntities()) {   
                System.out.println("Searching for target");

                HitboxComponent hitboxComponent = entity.getComponent(HitboxComponent.class);
                if (hitboxComponent != null) {    
                    if (hitboxComponent.getLayer() == PhysicsLayer.NPC) {  //Check entity is an NPC
                        System.out.println("Got target");
                        if (getDistanceToTarget(entity) <= this.range) { //Check range to target
                            toggleTargetAcquired();
                            this.target = entity; //Set target
                            while (getDistanceToTarget(entity) <= this.range) {
                                attackTarget();
                            }
                        }
                     }

                }
            }
        }
    }

The focus of this implementation was to iterate through all entities in the game (as the enemies teams had provided no means of obtaining only enemy entities), and iteratively check whether they were in range. If an enemy was found to be in range, it would be continually damaged until it had either exited the given range, or had died.

Whilst logically this naive approach made sense, upon doing testing in-game it was found that tower1 would either inconsistently damage enemies, or not damage them at all. The team decided this was mainly the result of the inconsistent use of grid-based systems across different teams, and as a result decided to overhaul these systems and provide an improved system.

Whilst the team was able to overhaul the grid system and implement a fully functional system that allows the detection of other obstructions in the buildable areas (allowing detection of whether the user cannot build in certain areas), the time taken to design and implement such a system for studio-wide use meant that the RangeAttackComponent could not be completed to a satisfactory level in the given time for Sprint 2.

Future Expansion

Whilst the ResourceCostComponent and the TrapComponent do not particularly need to be expanded (given that all functionality required is present), the RangeAttackComponent could be expanded in the future to be more fully functional and more intelligent.

To implement these improvements upon the RangeAttackComponent further research amongst users would need to be conducted to look at what users would expect from structures in a tower defence game. Initial conversations with users indicated the following: Users would expect that:

  • Towers engage lower-health enemies as priority targets
  • Towers engage enemies which are closer in proximity to the tower first
  • Towers are capable of intelligently switching targets (i.e. if the tower is targeting an enemy with full-health, and a low-health enemy enters its range it will prioritise the low-health enemy)