Spite: Absolution is our Diablo 3 clone. It was created in 14 weeks half time using our own engine
Triggers and Events
Enemy flocking behaviour
Mini boss variant of the ranged enemy
Fire barrier in the boss room
I started off by implementing PhysX to our engine. I had not a lot of experience working with other SDK's before but merging it with the engine was suprisingly easy. Next up was to get some visual representation of the physics in action. Even though it wasnt necessary for this project I wanted to get some dynamic objects in. I linked the physX with our actors with the use of ENTT's entities and created a update loop for all physX objects.
With some static colliders created in a test scene I started spawning dynamic objects and noticed quickly there were problems with the rotation of the objects. Objects also had a tendency to bounce a lot.
Our engine only used Euler angles for rotation so I spent some time writing a utility class to convert between euler angles and quaternions aswell as converting between our engines vectors/transforms and PhysX's. This solved the problem of gimbal lock.
The bounciness was caused by objects not having any mass. As for the scale im still not sure why I have to scale every physX object by 50 but that seems to be the magic number. I think this might also be why a good mass for an object is around 0.001. An object with the mass of 1 will a lot of the time fall through the ground
All rigid bodies were hardcoded in at this point. It was time to create a proper factory that would simplify the process for the user. To add collisions to an object the user puts a collider and filter component on the entity before passing it to the factory. The factory creates the PhysX shape and Actor and adds it to the physics scene.
The player, enemies and attacks are all kinematic actors. I used the PhysX simulation callback to handle the combat. When 2 entities with rigid bodies and the correct filter combination collides all system that have a overridden function for collision will recieve the data and apply logic on the entities.
I used the physX trigger callback to detect the player entering a trigger. When this happens I use an observer pattern to send a message to the relevant event class which in turns run the event. Since most events interact with other systems a lot of the time an additional message is sent to other systems. For example the event to change level or save the players progress. For our next project the events will be created with a node system and simply be called upon by a script component placed on the trigger entity.
For the enemy behaviour I created 8 slots around the player. When enemies notice the player they will look for the closest slot that is not taken. Once all slots are taken any remaning enemies who have noticed the player will simply act busy by running in a random direction for a random set amount of time. If two enemies acting busy collide they were instructed to run opposite directions.
An issue with this was that with high amounts of enemies they would start ping ponging around the room and knocking enemies that were given a slot away from the player. To solve this enemies with a slot were giving a higher priority during collision so only the non prio enemy would move. This worked well but there was still one issue remaining.
If the player started running during combat high priority enemies would run straight through the player to reach their original slot. This was solved by checking collisions between high prio enemies and the player. If a collision occurs. The enemy will check the closest slot and the enemy reserving that slot. If our colliding enemy is closer they swap slots with the original enemy.
Visualisation of attack slots
Visualisation of attack slots