Station Inventory and Visualisation - UQcsse3200/2024-studio-3 GitHub Wiki
Introduction
Stations use an InventoryComponent to hold items placed into the station, but their inventories are displayed differently to the player Inventory. Instead of using an InventoryDisplay component, which is a UI component, they use subclass of StationHoverComponent, which extends a RenderComponent. StationHoverComponent is an abstract class that provides functionality that displays items in a station's inventory as small icons hovering above the station itself, as shown in the image below.
A chopped is lettuce is displayed on the mixing bench (left), and a strawberry is displayed on the chopping board (right)
Each station type has a concrete display class that extends StationHoverComponent. For instance, chopping boards use a ChoppingBoardHoverComponent. While the inventory displaying functionality shown above is provided in the parent StationHoverComponent class, the concrete classes must implement specific key tooltips that display on the station when the player is able to interact with it.
Key tooltips are shown for the mixing bench the player can currently interact with, showing what buttons to press to take an item from the bench, rotate items, or combine them
Additionally, another crucial requirement for providing feedback to the player is to display the progress of chopped or cooked ingredients when they are placed on the chopping board or into a cooking station (i.e. oven, stove). To do this, a StationProgressDisplay component is used, which displays a small progress bar when an item placed on a station is being chopped/cooked, so the player can easily determine how close it is to completion.
A progress bar being shown for a lettuce ingredient while its being chopped. It is currently at just over 50%
These three display elements allow the full functionality of stations to be visualised, which is something that was lacking before as previously there were no visual indicators to determine what the stations were doing, apart from seeing that an item disappeared from the player's inventory when placing it into a station. These elements allow the storing and cook/chop functionality of the stations to be visualised, providing important information to the player, as well as making debugging easier during development. It also allows for available interactions and keybinds to be shown, improving the user experience as players won't have to memorise which keys to press for what actions. Further details on how these components work and how to use them are detailed below
StationHoverComponent
The StationHoverComponent is found in components/station. It is an abstract class that provides station inventory display functionality, as well as most of the core logic for implementing tooltips. There are tooltip icons for the following actions in the game:
- [E] Place item, Take item, Dispose (replaces place for bins), Submit (replaces place for submission stations), Cook (replaces place for cooking stations)
- [K] Rotate items (for stations holding more than 1 item at once)
- [J] Combine items into a meal
- [Q] Chop item
Since each station type has a different subset of applicable actions from this list, a concrete class has been created for each station type, extending StationHoverComponent. In each of these classes, the relevant tooltips are implemented for the station type.
This includes:
- BasketHoverComponent, for ingredient baskets
- BinHoverComponent, for bins
- ChoppingBoardHoverComponent, for chopping boards
- CookingHoverComponent, for cooking stations
- MixingBenchHoverComponent, for benches
- SubmitHoverComponent, for submission stations
For instance, a ChoppingBoardHoverComponent can be added to a chopping board using the following:
entity.addComponent(new ChoppingBoardHoverComponent());
With this, any items stored in the InventoryComponent of the chopping board will be displayed as icons above the entity. Chopping boards can support 3 action types: place, take and chop. Thus, if the player is able to place, take or chop an item on the chopping board, key tooltips will appear to notify of this:
The player can take the item on the chopping board into their inventory by pressing E, or chop the item currently placed on the chopping board by pressing Q
Extending the StationHoverComponent
If you wish to create a new concrete class extending from StationHoverComponent for a new station type, it is quite simple. Most of the logic for tooltips is already set up in the abstract StationHoverComponent class, you just need to specify which actions to show and when to show them. The abstract class already handles showing tooltips when the player is close enough to interact with the station.
The main requirement is to implement the abstract method, drawToolTips(SpriteBatch batch);
This method is called when the player is close enough to interact with the station. You can then call draw on the provided SpriteBatch parameter to draw the key tooltips when required. For instance, the following code is used to display the take key when the player's inventory is empty and the station's inventory has an item in it:
`public void drawToolTips(SpriteBatch batch) {
inventory = entity.getComponent(InventoryComponent.class);
if (!hasItem && inventory.getSize() > 0) {
// player can take item
batch.draw(takeKeyImage,
position.x,
position.y + KEY_Y_OFFSET,
KEY_WIDTH,
KEY_HEIGHT
);
}
}`
The hasItem member is a boolean that tracks whether the player is currently holding an item or not.
For some stations, we do not want to display the inventory of the station (i.e. for bins, baskets, submission stations). By default, the base StationHoverComponent does display the inventory of the station it is added to, but this can be disabled for specific stations by overriding the draw() method and only calling drawToolTips() in it:
@Override public void draw(SpriteBatch batch) { if (entity == null || position == null || scale == null) return; if (this.showKeys) { drawToolTips(batch); } }
showKeys tracks whether the player is close enough to interact with the station.
Multiple items
If there are multiple items stored in entity's inventory, the item icons will be stacked on top of each other, as shown below:
The mixing bench is holding 3 items, which are displayed stacking on top of each other, with the last item placed onto the station being on top
You may also notice the red border shown on the topmost item icon. This is displayed when there is more than 1 item displayed, highlighting the last item placed into the inventory. This is primarily used to indicate which item will be retrieved next when taking an item out of the station. Since station inventories use a stack-like structure, the next item to take out will be the last item put in (LIFO/FILO).
The mixing bench is currently the only station supporting this feature as it is the only station that can hold more than 1 item at a time. The mixing bench also has 'rotate' function which allows the player to press the 'k' key when near it to rotate the order of the items stored in its inventory (and thus changing the stack order). This will shift the order the items are displayed by the StationHoverComponent, rotating which item is at the top (i.e. is next to be taken out), allowing the player to take out any item in the mixing bench without having to take out any items placed after it first. This makes interacting with the mixing station quicker and smoother.
https://github.com/user-attachments/assets/72292580-0cf5-41aa-b786-a8cce1d022ff
Demo showing placing items into the mixing station and rotating them to change which item you want to take out next
StationProgressDisplay
The StationProgressDisplay is found in components/station. To use this component, add it to an entity that has a StationItemHandlerComponent (which is component used in station entities). Note that the entity MUST have a StationItemHandlerComponent, otherwise the StationProgressDisplay will not work. (disclaimer: the entity also requires a PhysicsComponent to determine the position of the entity).
To add a StationProgressDisplay, use the following:
entity.addComponent(new StationProgressDisplay());
This component displays a progress bar indicating the chop/cook percentage of the item held in the station. The progress bar will only display if there is an item currently placed in the station inventory, and if the item has a ChopIngredientComponent or a CookIngredientComponent. The display will update as the chop/cook percentage of the item increases, which can be seen in the demo below.
https://github.com/user-attachments/assets/4b1609af-03f6-46e1-a473-157a14a6e331
Demo showing progress bar advancing as ingredients on the chopping board are processed
As seen in the video, ingredients also save their chop/cook progress, so that if you take the ingredient out of the chopping board and place it back on to it, the progress bar will resume from the place it left off. Additionally, when the ingredient is fully processed (chop level reaches 100%), the progress bar disappears.
Burning ingredients
For stations that can accept cookable ingredients (currently just the stove), these ingredients have a cook level that exceeds 100%, indicating the item is burning. Once the ingredient reaches a certain cook level threshold above 100%, it becomes burnt. The behaviour of the progress display for such ingredients differs slightly from choppable ingredients. Once the cook level exceeds 100%, the progress bar will not disappear, and will stay at 100% as the cook level continues to increase. Only once the ingredient is burnt will the progress bar then disappear.
In a later sprint, a different visual indicator may be added to more clearly show to the player that an item is burning. Some ideas include making the bar turn red as its burning, and possibly making it blink, faster and faster as the item becomes closer and closer to becoming burnt.