Customer Animation - UQcsse3200/2024-studio-3 GitHub Wiki
Introduction
The customer animation system is designed to be a versatile application of animating various animals the user will have to serve in their cooking spree. Each customer will be animated through a series of calls between personalised JSON files and factory creations to make a future-proof system which randomly generates a sequence of pre-selected animals for each day. These animations reflect simple idle animations at the moment, as the sprite sheets used are from INSERT LINK.
ATLAS Files and Sprites
Each animal/customer is equipped with a sprite sheet and an ATLAS file which references each frame of said sprite sheet in order to construct an 'animation'. These are registered in the JSON files within the 'texture' component. The following code represents a sample atlas file for a goat with its idle animation:
goat.png size: 64, 16 format: RGBA8888 filter: Nearest,Nearest repeat: none default rotate: false xy: 0, 0 size: 16, 16 orig: 16, 16 offset: 0, 0 index: 0 walk rotate: false xy: 16, 0 size: 16, 16 orig: 16, 16 offset: 0, 0 index: 1 walk rotate: false xy: 32, 0 size: 16, 16 orig: 16, 16 offset: 0, 0 index: 2 walk rotate: false xy: 48, 0 size: 16, 16 orig: 16, 16 offset: 0, 0 index: 3
Key Classes
NPCFactory
This class is responsible for creating the base customer (core functionality of the customer) and on top of that, its personal attributes, i.e. their name, animal type, food preferences. These will be dependent on whatever is within the JSON files that are called in the config section of the code seen below. This form of data management and retrieval is optimal as adding new customers for future patches will only require us to create a new JSON file and an extra condition within the config variable. NPCFactory also instantiates the animation of the sprite by referring to an animationrendercomponent to trigger its walking/idle animation.
public static Entity createCustomerPersonal(String name, Vector2 targetPosition, int Customer_id) {
Entity customer = createBaseCustomer(targetPosition, Customer_id);
CustomerPersonalityConfig config = switch (name) {
case "Hank" -> personalCustomerConfig.Hank;
case "Lewis" -> personalCustomerConfig.Lewis;
case "Silver" -> personalCustomerConfig.Silver;
case "John" -> personalCustomerConfig.John;
case "Moonki" -> personalCustomerConfig.Moonki;
default -> personalCustomerConfig.Default;
};
AnimationRenderComponent animator =
new AnimationRenderComponent(
ServiceLocator.getResourceService()
.getAsset(config.texture, TextureAtlas.class));
animator.addAnimation("walk", 0.3f, Animation.PlayMode.LOOP);
customer
.addComponent(animator)
.addComponent(new GhostAnimationController());
customer.getComponent(AnimationRenderComponent.class).scaleEntity();
return customer;
}
The following code snippet instantiates the core functionality of the customer, including its pathfollowtask, entity attributes and identification components. They will be built upon in functions such as createCustomerPersonal
public static Entity createBaseCustomer(Vector2 targetPosition, int Customer_id) {
AITaskComponent aiComponent =
new AITaskComponent()
.addTask(new PathFollowTask(targetPosition, Customer_id));
Entity npc =
new Entity()
.addComponent(new PhysicsComponent())
.addComponent(new PhysicsMovementComponent())
.addComponent(new ColliderComponent())
.addComponent(new HitboxComponent().setLayer(PhysicsLayer.NPC))
.addComponent(new TouchAttackComponent(PhysicsLayer.PLAYER, 1.5f))
.addComponent(aiComponent);
PhysicsUtils.setScaledCollider(npc, 0.9f, 0.4f);
npc.getComponent(PhysicsComponent.class).getBody().setUserData("Customer");
return npc;
}
GhostAnimationController
yeah ik the name is outdated GhostAnimationController adds a listener for another class to trigger the animation. It does this by referencing the "walk" animation cycle in the anima's atlas file, which is then triggered by NPCFactory on spawn.
public class GhostAnimationController extends Component {
AnimationRenderComponent animator;
@Override
public void create() {
super.create();
animator = this.entity.getComponent(AnimationRenderComponent.class);
entity.getEvents().addListener("wanderStart", this::animateWander);
}
void animateWander() {
animator.startAnimation("walk");
}
}
NPCConfigs
NPCConfigs instantiate a CustomerPersonalityConfig for each customer such that when they are read in createCustomerPersonal, they have their JSON files read in a certain manner. This allows the instantiation of a base and personal traits and, as mentioned before, is a future-proof way of implementing the customer data reading system. This applies to the animation of the customer.
public class NPCConfigs {
public CustomerPersonalityConfig Hank = new CustomerPersonalityConfig();
public CustomerPersonalityConfig Lewis = new CustomerPersonalityConfig();
public CustomerPersonalityConfig Silver = new CustomerPersonalityConfig();
public CustomerPersonalityConfig John = new CustomerPersonalityConfig();
public CustomerPersonalityConfig Moonki = new CustomerPersonalityConfig();
public BaseCustomerConfig Basic_Sheep = new BaseCustomerConfig();
public BaseCustomerConfig Basic_Chicken = new BaseCustomerConfig();
public CustomerPersonalityConfig Default = new CustomerPersonalityConfig();
public BaseCustomerConfig Basic_Default = new BaseCustomerConfig();
}
The following JSON code represents a single customer, Hank the Gorilla, and his attributes which will affect gameplay. The animation file is linked in the 'texture' component.
"Hank": {
"name": "Hank",
"type": "Gorilla",
"countDown": 20,
"patience": 100,
"preference": "bananaSplit",
"reputation": 100,
"texture": "images/animal_images/gorilla.atlas"
},