Game Programmer
GOAP
C++ goal oriented action planning. Enemies determining which goals to reach and having different actions based on determined factors on how to reach that goal.
Main attributes
-
-
​Created the brain of the AIs, goals and actions and how they're run​​
-
-
-
​Implemented the gameplay around this system. Movements, actions, animations...​​
-
-
-
​Created game object and component system, both for engine and game.
-
GOAP System
GOAP stands for goal oriented action planning, meaning AIs in game have several goals to achieve, and different actions to take them there. The actions can have different costs, effectiveness and determining factors to take them towards that goal, making some actions more worth taking than others.​


What I implemented was goals with conditions consisting of WorldStates. WorldStates began as an unordered_map with floats and strings, and was replaced with an array of floats with a specific enum size to increase performance by skipping hashing during runtime. I considered using booleans, but decided floats are more flexible in its use.
Actions consisted of cost, effectiveness, a behaviortype, preconditions and effects. And for debugging, a string as a name.


Preconditions determine whether the action can be taken according to current worldstate, and effects affects the current worldstate if the action goes through. I added a helper function for comparing cost with effectiveness (percentage).
I had a GOAP-Planner class to choose which goal to take during runtime, and to make a plan if no plan existed using current worldstate.

GOAP Implementation
Project started out as a simple boids project, so the enemies are called boidy, but when flocking behaviors got done I wished to add more. I created a behavior tree which I made work with more behaviors. But then I wanted more, so I expanded this to a GOAP test.
3 goals,
Befriend, Roam, and Attack.
5 actions,
Spiral (befriend), Eat (if food is available), Free Roam (flocking), Army and CircleAttack.
Friendshipmeter
The enemies have a friendshipmeter which is clamped between 0 and 10. They don't know if player is friend or foe, and depending on which events the player sends out, they either like player more, or dislike player more. 0 is lowest when they don't like player, and 10 is max when they like player the most. In the video, it's made clear through their color, red is 0, white is 5, and green is 10.


When friendshipmeter is lower the boidys will attack, army, or go into flocking behaviors, depending on how low it is. The higher the friendshipmeter is, the more likely it will spiral or roam. Eat is only triggered if there's food, and depending on healthiness, tastiness and friendshipmeter, will the boidies eat.
Spiral
Spiral uses a Lemniscate curve, together with a seperation direction (from closest Boidy), and blends between them using a blendfactor to determine their next direction. I considered a sinewave curve, but it felt to robotic.


Free Roam
Free roam is the boids movement, flocking behavior including seperation, cohesion, and alignment, weighing them towards each other.
Circle Attack
With the help of an EnemyManager the boidies gets a spot around player in a circle that they travel to, to then attack one at the time.


Army
After circle attack the EnemyManager helps give them a spot in an army grid that's constantly moving. One of the few times I had to adjust MovementComponent to stop using force and only set their new positions as they otherwise never reached their spot.
Eat
Player can give food to try and befriend the boidies. First boidies check how tasty that food is, and they have a HungerComponent that slowly ticks up. Even if the food is super tasty, they wont eat if they're feeling full.


If they want to eat the food, they also check friendshipmeter. If player is foe, they will only dislike player more. If not, after eating, there's a healthiness variable determining whether they like or dislike player after eating.
Game Object System
This project has been refactored a few times, and hopefully how it ended up looks good. I strived to make the game object system as similar to Unity as possible, gameobjects with components.

Components exist in both engine and game. Those in engine like TransformComponent could be reused for other games created in this engine. While components in game like FriendshipComponent is specifically for this project.
Other
Player
Player uses a StateMachine, can move, dash, pet, feed and smile. Both player and boidies subscribes to an eventhandler, and almost each player state sends a message which bodies listen and react to.


Some states are simpler, dash decreases friendshipmeter, smile increases friendshipmeter, and then feed and pet are more complex, which food and boidies figure out what to do.
Food
There are four types of food, orange, apple, banana and chocolate. I based tastiness on my own taste, and I HATE ORANGES, so their tastiness is low. They all use a statemachine, have a full state and a half state.


All food used to inherit from Food class until I refactored all logic into Food class. Orange is super healthy, banana and apple as well, while chocolate is super unhealthy, makes boidies angrier, and hungrier.
Object Pool
I used an object pool for the spawned food in the scene to be very careful with avoiding memory leaks.


The scene updates normal gameobjects during its runtime, and has a container with raw gameobject pointers which the object pool owns.
Performance
I've refactored to increase performance as well. First it was WorldStates hashing during runtime when updating current values.
Previous:

Current:


Then it was gameobject GetComponent, which looped through all components until it found it. But since this is used in runtime I added a container with known components, now it's looking for that key instead of looping though the entire container.
Even with over 200 gameobjects the FPS is still over 60!