Specifically, I was interested not in the actual movement of crowds of people, and I wasn't interested in their behavior as individual entities, but how their behavior as a crowd can be modeled. I was most intrigued thinking of the spread of information through a crowd. We've all seen a knot of people looking at something, and gone over to see what they're all staring at. There's also the behavior of protesters, mobs, or rioters - behavior that starts with a few individuals but has the potential to sweep up others in a wave of emotion and carry them along as part of the growing throng. I was also struck by something I've seen described as "soccer fight" behavior, where an interesting event causes some farther-away people to press close, while those nearby want nothing more than to get away from the violence, creating an interesting crush of opposing desires.*
A basic existing model for the behavior of large numbers of entities in a simulation is Craig Reynolds's "Boids" flocking behavior. It produces pretty impressive results for things like flocks of birds or schools of fish - they will generally stay together, change directions in moments, but stay a small distance away from each other. We can easily imagine modified versions of that behavior looking like a crowd of people, albeit one that doesn't swoop around as gracefully. But there was something that interested me more than just the movement of the boids: one of the techniques it uses to create the flocking behavior is that neighboring boids will tend to align their velocities, attempting to match the speed and heading of other boids in the flock.
If instead of velocity, we imagine emotional state as a vector, won't this model an interesting flow of information and feeling in a crowd? Curious people headed towards something interesting would cause others around them to be curious about the attraction and join the crowd, frightened people fleeing something might cause others to flee as well, without ever seeing the danger, and a raging mob shouting slogans would tend to pull others into its passion.
So I decided to prototype this in a really basic Flash app, using the excellent Flixel for the first time. I've done a fair amount of ActionScript coding when I was BioShock 2's GUI programmer, and Flixel's tools make it easy to whip up a simple game-like object in a few hours. Still, I was rusty and this was my first Flixel app, so I was learning a bit as I went. It was tons of fun, though, and I definitely recommend it for quick-and-dirty prototyping.
In the prototype, I used a simple one-dimensional vector representing a Fear/Curiosity spectrum. A more nuanced approach would be possible, but I wanted to keep things simple and also couldn't think of anything that would add anything as a second axis. A two-dimensional scenario might have a happiness axis and a passion axis, though, where fear and curiosity are the negative and positive happiness points at max passion, or something. There are lots of options.
Here's the code for the function that spreads emotion through the crowd:
public function EmotionalAlign(OtherEntities:Array):JVector { var NeighborDist:Number = 24; var sum:JVector = new JVector(0, 0); var count:Number; var i:Number; var loc:JVector = new JVector(x, y); for (i = 0; i < OtherEntities.length;i++) { var OtherLoc:JVector = new JVector(OtherEntities[i].x, OtherEntities[i].y); var Distance:Number = JVector.Distance(loc, OtherLoc); if (Distance > 0 && Distance < NeighborDist /*&& JVector.Distance(Emotion, OtherEntities[i].Emotion) < 1.0*/) { sum.Add(OtherEntities[i].Emotion); count++; } } if (count > 0) { sum.Div(count); } if (sum.Mag() > 0) { sum.Normalize(); sum.Sub(Emotion); sum.Mult(MaxEmotionalChange); } return sum; }
It's pretty simple - we sum up the emotional vectors of nearby Boids, take the difference of that with our current emotional "heading", and impose a max "emotional acceleration" on it so that it changes gradually. This is then applied over time as an acceleration to the emotional direction of the boid. As you can see, we use the physical distance of nearby boids as the determining factor of whether to add them to the calculation or not. I also experimented with requiring boids to be within a certain "emotional distance" of each other, but it caused the simulation to be less interesting, so I left it in commented out.
No comments:
Post a Comment