It has been long been considered best practice to create a separate invisible controller which spawns the connected some animated sprite for each entity in the game such as players, npcs, enemies, etc. Often, the controller and animated sprite would have their origins both set to the "Center Bottom" of the images to keep things consistent.





Terms



Controller - An invisible sprite with logic, behaviors, and often the collision system.
AnimatedSprite - The sprite containing all animations for the entity which is pinned to the controller.
Animation - A single animation within the AnimatedSprite, such as "Walking", "Running", "Jumping", etc.

Is it possible to merge AnimatedSprite and Controller in a Singular Entity?



The following rules should be followed when creating a singular entity:

Fixed Dimensions

All dimensions within a single animation are identical, so all jump frames might be 32x52, all walk frames might be 32x50, etc. Everything must be consistent for purposes of bounding boxes, and origins.

Origin Point Consistency

For an entire Animated Sprite, all animations have the same origin point, for example, a platforming character's origin point would be center bottom.

Construct Family support

With family support, the first instance of SingularEntity for some given entity is always put in a new family. The SingularEntity does not have any member variables, all properties/behaviors *ALWAYS* exist on the Family itself. This means that it is easy to create new Entities with the same behavior as the original. For example, if you had three different types of enemy warriors in a game: SwordWarrior, ArmoredWarrior, HalberdWarrior. Each of these enemies has basically the same logic but differ in terms of their animations and art, the developer would create a WarriorFamily and add all three warriors to it. Any properties unique to the Warrior Class would be added to the WarriorFamily. Event code controlling movement and behavior would also need to be at the WarriorFamily level.

What are the advantages of using a SingularEntity?



Collision Simplification

No extra pinning is necessary since the controller and animation are the same thing. It is easy to draw and adjust collision boxes, since the boxes exist on each respective Animation within the SingularEntity. Verifying that collision boxes are aligned properly is trivial since they exist on the actual animations themselves. With separate controller and animated sprite, a complex set of animations, it can be tricky to line up collision boxes in the controller to match the animated sprite, since one might have to change frames/animations in the controller itself to change the collision box which can happen in a character with different styles of movement (example: ducking, crouching, etc).

Exception: When using a controller and AnimatedSprite, often the animated sprite is drawn, animated, and collision boxes are set up. The AnimatedSprite is then cloned and renamed to the Controller, ensuring the controller’s collision system is already identical. Then the animated sprite is erased from the controller. Often the controller sprite contains a translucent polygonal shape equivalent to the collision box.

Object Count

Having an invisible controller (for behavior/logic/collisions) + animated sprite (rendering) essentially doubles the object count. In most scenarios, the performance loss is negligible, however performance testing against thousands of objects has shown that this can result in frame-rate dropping.

What are the disadvantages of using a SingularEntity?



Swapping entire Animated Sprites at run-time

If you wanted to swap out an entire AnimatedSprite for another AnimatedSprite. For example, let's say the player's character morphed into a completely different character. Having a distinct controller would mean you could replace the old AnimatedSprite with a new AnimatedSprite while preserving all player's stats which live on the invisible Controller itself.

Scaling / Deformation

If the animated sprite needs to be rotated or deformed in a way that *should not* affect the collision box. This is especially true for a platform behavior object. For example, the object has an unusual collision box (such as a small central circle) that *should not* impact its movement behavior (ex: platform).





Hybrid Approach




Some developers choose to use a sort of hybrid approach with the following:
  • Invisible Controller - Contains movement behavior (platform), collision box used in conjunction with the platforming behavior, and any instance variables.
  • Animated Sprite - Visible pinned animated sprite that contains all animations (running, walking, ducking, etc). Each animation's collision polygon is used for purposes of hit detection.

One significant issue with this approach is that the object count is increased, and the number of collisions per game tick is also increased.