Kekouan

Wherein, we handle events

2024-10-30

Firing while moving Continuing to fire while moving

In my new level it quickly became apparent that there was an issue where I could not shoot and steer at the same time. I just needed to handle a mouseDragged event in addition to the mouseDown (fire), mouseUp (stop firing) and mouseMoved (aim).

Hey! I'm patrolling over here

Okay, got a new level, need some enemies. So I added my existing Marten enemy into the scene, and it immediately slams into the player at high speed. Which is fun, but only so much.

Initial enemy in new level

A note on being Goal Oriented

The way GameplayKit works is that you have agents, and you give them goals

As Apple describes it:

In many kinds of games, entities move in real time and with some degree of autonomy. For example, a game might allow the player to tap or click to move a character to a desired location, and the character will automatically walk around obstacles to reach that location. Enemy characters might move to attack, planning to intercept the player character ahead of its current position. Ally characters might fly in formation with the player character, maintaining their distance from the player character and a parallel direction of flight. In all of these cases, each entity’s movement might also be constrained to realistic limits, so that the game characters still move and change direction realistically.

https://developer.apple.com/library/archive/documentation/General/Conceptual/GameplayKit_Guide/Agent.html

Implementing Patrol Behaviour

The first thing I was able to do was to add a "wandering" behaviour.

Enemy wandering behavior Enemy continuing to wander

To actual get things to patrol, I had to combine the path following goal with a speed goal.

// Create path following goal
let pathGoal = GKGoal(toFollow: path, maxPredictionTime: 1.0, forward: true)

// Add speed maintenance goal
let speedGoal = GKGoal(toReachTargetSpeed: desiredSpeed)

// Combine goals with appropriate weights
agent.behavior = GKBehavior(goals: [
    pathGoal.withWeight(1.0),
    speedGoal.withWeight(0.5)
])

This resulted in enemies that could patrol a path:

Enemy following patrol path Enemy continuing along path Enemy completing patrol route

Path Visualization and Refinement

To help with path creation and debugging, I added visible markers along patrol routes:

Path visualization with cubes

This helped identify issues like path clipping through geometry, which could be fixed by adding additional waypoints around obstacles.

Final Results

The completed system allows enemies to smoothly patrol predefined paths while maintaining the ability to engage targets:

Blue Marten patrolling Blue Marten continuing patrol Blue Marten turning corner Blue Marten completing patrol

And if you add a camera to an endless patrolling enemy, you get a neat screensaver effect. This is after I redesigned the weapons on the marten so that instead of two "pods" with two barrels, it's two much larger single weapons. That they look like RCA connectors is merely a coincidence.

Screensaver-like patrol movement