Skip to content

Joinable Component

Rowan Gray edited this page Aug 31, 2023 · 3 revisions

First see Components and Atlas Render Component

The JoinableComponent is a custom render component used to selectively change an entities texture and collision shape depending on its' neighboring entities.

It extends from AtlasRenderComponent to provide the selective texturing. This component requires the entity to also have a CollidorComponent to provide collision detection. For this component to work, all entities must be placed via the StructurePlacementService

Constructor

The constructor for JoinableComponent takes in a TextureAtlas containing the textures for each cardinality, a JoinLayer defining the layer to join on, and a JoinableComponentShapes object containing the different collision shapes for each cardinality. 

public JoinableComponent(TextureAtlas textures, JoinLayer layer, JoinableComponentShapes shapes)

JoinLayer

The JoinLayer enum is used by the JoinableComponent to check whether the entity is compatible with the neighbouring entity. Entities will only join if they have the same join layer.

Adding a new join layer

To add a join layer, simply insert a new entry into the JoinLayer enum.

public enum JoinLayer {
    WALLS,
    NEW_ENTRY_1,
    NEW_ENTRY_2,
    ...
}

JoinableComponent Shapes

The JoinableComponentShapes stores the collision shape for each cardinality. The class should only be created by reading in a vertices json file. An example file can be found here.

JSON file format

A JoinableComponentShapes JSON file should follow the following structure, where each cardinality contains a list of (x, y) pairs defining the vertices of the shape. The vertices for each cardinality are read in order and should create a walk around the edge of the shape.

{
    "vertices": {
        "cardinality_1": [
            {
                "x": 0.25,
                "y": 0
            },
            ...
        ],
        "cardinality2": [
            {
                "x": 0.25,
                "y": 0
            },
            ...
        ],
        ...
        "cardinality15": [
            {
                "x": 0.25,
                "y": 0
            },
            ...
        ]
    }
}

See cardinality ids for a list of cardinalities which must be defined.

Texture Atlas

A texture atlas is used to store the different variations of the entity's textures. A useful tool for creating these atlases can be found here. Here is an example of a texture atlas which is used for a JoinableComponent.

dirt_wall

See cardinality ids for a list of cardinalities which must be defined.

Cardinality Ids

Both the texture atlas and vertices JSON must have an entry for each of the following cardinalities.

  • no-connection
  • left
  • left-up
  • left-up-right
  • left-up-right-down
  • left-up-down
  • left-right
  • left-right-down
  • left-down
  • up
  • up-right
  • up-right-down
  • up-down
  • right
  • right-down
  • down

Each cardinality id defines the directions a connection is formed. For example, cardinality id left-down will be used if an entity is joined to another entity on the left and below while not being joined to any entities above or to the right. For instance, this would be the corresponding texture for the dirt wall.

left-down-wiki

Usage

Creating Entity

To being you must read in the vertices JSON file containing the collision shapes you would like to use.

JoinableComponentShapes shapes = FileLoader.readClass(JoinableComponentShapes.class, "vertices/walls.json");

Next you should obtain the TextureAtlas containing the textures you would like to use. The atlas can be loaded by the ResourceService as follows.

ServiceLocation.getResourceService().loadTextureAtlases(new String[]{"images/dirt_wall.atlas"});

Once loaded in by the ResourceService you can retrieve the TextureAlas as follows.

TextureAtlas textures = ServiceLocator.getResourceService().getAsset("images/dirt_wall.atlas", TextureAtlas.class);

You can then create and add a JoinableComponent to the entity. Please note that the entity must also contain a CollidorComponent. If the entity does not contain a CollidorComponent the JoinableComponent will not work.

entity.addComponent(new JoinableComponent(textures, JoinLayer.WALLS, shapes));

Finally, you can place the entity via the StructurePlacementService.

ServiceLocator.getStructurePlacementService().PlaceStructureAt(entity, new GridPoint2(10, 10), false, false);

Updating the Neighbours

The neighbours of the entity must be notified of a change in order for JoinableComponent to function correctly. This can be done by calling notifyNeighbours on the component. This can only be called once the entity has been placed via the StructurePlacementService.

public void notifyNeighbours(boolean isJoined)

An example of it being used is as follows.

// entity placed
entity.getComponent(JoinableComponent.class).notifyNeighbours(true);

// entity removed
entity.getComponent(JoinableComponent.class).notifyNeighbours(false);

Testing

Testing for the JoinableComponent was implemented using JUnit and Mockito. There is at least one test per public function. The tests aim to verify that the correct cardinality is selected and drawn to the screen when the component is created and updated.

Clone this wiki locally