- Basics of a game engine
- Basics of flocking algorithms
- Representing mixpanel data
- Point: A basic (x, y) pair
- Vector: An (x, y) pair with direction and magnitude
- Entity: An object within the game engine, has a position (Point) and heading (Vector)
- Magnitude: The length of the vector
- Normalize: Scaling of the magnitude of a Vector to 1 while maintaining the direction
- You can add a Vector to a Point to move it
- You can subtract a Point from a Point to create a Vector
- You can add Vectors with other Vectors, head to tail, and get a new Vector
- Render new entities
- Remove "dead" entities
- Update all entities, using time since last update or delta
- Repeat
Using delta enables smoother animations based on frame rate rather than a constant
- Practice
- Changing things up
- Experiment with new technologies
A good way to hone your skills Helpful to think about something different Try out new libraries / frameworks in a limited scope Let's be honest, sometimes it is just fun to screw around
- Individual-Based Model
- Boids & Steering Behaviors
- Burton's 1992 Batman Returns
Individual-Based Model "Global consequences of local interactions of members of a population" Craig Reynolds, in 1986 created the computer model for flocking Boids are our "entities", coind by Reynolds Real world implementation for bats and penguins in Batman Returns
The plane is a euclidean 2-torus, entities loop around edges Think: Pacman Currently no steering, just speed and heading
this.pos.scalePlusEquals(
this.speed * delta,
this.heading
);
Remember, delta is time since last frame update This occurs each loop of the game engine
- Alignment
- Cohesion
- Separation
// First, for all entities
alignmentVector.scalePlusEquals(
other.speed,
other.heading
);
// Then
alignmentVector.divideEquals(closeEntities);
alignmentVector.normalize();
Scale heading by speed Average resulting vector by number of entities
Blue line is normalized (and scaled for visibility) average heading This average changes slightly each loop Outliers to average cause this variation
// First, for all entities
cohesionVector.plusEquals(
other.pos
);
// Then
cohesionVector.divideEquals(closeEntities.length);
cohesionVector.minusEquals(entity.pos);
cohesionVector.normalize();
Add together all locations Divide by number of entities - center of mass Create vector from current position to center of mass
Green line is non-normalized heading towards center of mass
// First, for all entities
tempVector = other.pos.minus(this.pos);
separationVector.scalePlusEquals(
-1 / tempVector.magnitude(),
tempVector
);
// Then
separationVector.normalize();
Doing inverse for weighting results in small vector, no average
entity.heading.scalePlusEquals(alignmentWeight, alignmentVector);
entity.heading.scalePlusEquals(cohesionWeight, cohesionVector);
entity.heading.scalePlusEquals(separationWeight, separationVector);
entity.heading.normalize();
Normalizing individual vectors first puts them all on a level playing field Weighting then adjusts their overall impact on the starting, normalized heading
- Range / Neighborhood
- Groups
- Weight
- Distance from boid
- Field of view of boid (not implemented)
range: 150,
groupAlignmentWeight: 0.025,
groupCohesionWeight: 0.075,
groupSeparationWeight: 0.09
Notice higher separation than cohesion Boids will tend to avoid their "neighborhood" flock
range: 500,
groupAlignmentWeight: 0.025,
groupCohesionWeight: 0.08,
groupSeparationWeight: 0.08
Notice same cohesion and separation weight Boids will form more consistent flocks
range: 500,
alignmentWeight: -0.001,
cohesionWeight: 0,
separationWeight: 0.01,
groupAlignmentWeight: 0.0125,
groupCohesionWeight: 0.08,
groupSeparationWeight: 0.08
Negative alignment between different grouped entities causes overall group avoidance No cohesion means groups don't share a center of mass Small separation keeps groups from getting to close, despite avoidance Lower group alignment here just slows down alignment steering
speed: 0.2 * (1 + (this.group / 3)),
range: 500,
alignmentWeight: -0.00125,
cohesionWeight: 0.09,
separationWeight: 0.01,
groupAlignmentWeight: 0.0125,
groupCohesionWeight: 0.03,
groupSeparationWeight: 0.025
Speed is based on group ID, some groups slower than .2, some faaster
- Map pages / modules to regions
- Boids represent active users (x8)
- Active boids group with current region
- Speed increases with activity
- Inactive boids die out
- Orbiting entities to show historical data (small)
- Orbiting entities to show created assets (large)