In this post I will give an overview of how I arrived at the current movement system for Seabird and some of the challenges that I faced. I will show the problems with my initial idea of using a vector grid, and how my use of cubic splines largely replaced that. Then I will discuss the reasons for going back to a vector-based approach, and the flexibility that it has given me for scene layout.

This video shows what the character and wind movement presently looks like:

(Note: This scene is made of placeholder art. The player is marked by a circle.)

Requirements for a Movement System
Most of the gameplay in Seabird involves trying to avoid becoming separated from other birds in scenes made up of wind currents. If the player loses sight of a bird, they may need to find another bird that is willing to help them.

The only gameplay requirement for the wind currents is that they present some challenge to the player for staying with other birds. Two approaches I used for this are:
- Once a bird enters a wind current it is difficult to leave the current.
- Wind currents can move in the scene.

Vector Field
The first approach to tackling this problem I tried was to represent the entire scene as a vector field, or vector grid. For every point in the scene, there was a force vector for the wind force at that point. This worked well, except that I did not have a good way to set up the forces at each point without doing it manually. I experimented with different functions to set up the scene, but I could not find an approach to this that was satisfying.

An approach I could have tried would have been to use to the level editor to “paint” the vector grid. One problem I would have needed to work around if I chose to do this would be how I would make currents that are animated.

Direct Movement on Spline
Then I started looking into using parametric paths for the wind currents. Instead of a vector field for the entire scene, I set up the scene using multiple spline paths. I found that splines were a good fit for the problem I was trying to solve. Splines are much nicer to work with, and provided a more straight forward way to both manually and procedurally set up the wind currents in the scene. They are also easy to animate and move around in the scene.

Instead of using vectors, I tried to write the movement code using only spline mathematics. With a spline, it is easy to move a point along the path at a constant speed. This speed can be adjusted by whether the player’s input vector (direction of joy-stick, or arrow keys) is facing more upstream or downstream on the path, as well as the curvature of that segment on the path. The player is also able to get off the path by facing the input vector orthogonality to the spline slope.

Diverging Paths and Problems with Direct Movement
The major problem I ran into with this technique was that it became difficult to handle the case in which multiple wind currents might be affecting the player.

For instance, how should I handle the case in which a wind current forks into two currents, or in which a smaller current branches off of the first? In these cases, two or more wind paths need to be influencing the player. Moving between them smoothly was difficult. I worked out a solution, but I was not satisfied with it so I moved on to another approach.

Vector Spline Movement
I decided to go back to the vector field approach but instead determine the vector forces by the spline paths in the scene. The idea is this: when updating each of the characters, find a number of points nearby and determine a wind vector for each point based on the spline paths in the scene. Get an average of these points, and let that be the wind force applied to the character each frame.

To make it difficult for the birds to leave the wind current, I set wind vectors near the edge of the path to point strongly inward. Branching of wind paths was now a trivial problem. For a given point I add up the vectors of the wind for each wind path.

Each solution seems obvious to me now that I have seen it working. At the time it was difficult to know what would work and what would not. If some unseen challenges come up, I may need to again rethink this system, but for now it seems like a mostly viable solution to ship in the game.