People have submitted almost 40,000 silly faces to The Silly Face Society. Today, we are delighted to showcase one of our favourite players: Dinosaur Soup.
Dinosaur joined the esteemed society in April of 2013 and has risen to the rank of Toucan Sam with 1185 monocles earned to date. She is a welcome face to new players, and has even alerted us to a few application bugs.
Hailing from the great state of New Jersey, Dinosaur Soup is a stay-at-home mom of an awesome two year old girl. Naturally, she uses this an excuse make silly faces to her phone in public. Her friends don’t even give her a second glance when she’s making the Barf or the Flamboyant Metalhead.
She also enjoys more traditional games like Skyrim and branches out into RPGs and survival-horror. But with the Silly Face Society, it was love at first app-open. Her advice to new players? “Don’t be afraid to be the silliest you can be!”.
Dinosaur has challenged members with over 500 faces! We’ve prepared a short video celebrating her rise to silly stardom:
Can you out-silly Dinosaur Soup? Challenge her and others with the Silly Face Society on your iPhone, iPad or iPod!
The Silly Face Society is a casual iPhone game that uses a surprisingly large number of visual effects. Below, I’ll demo a few of the particle systems (using iOS 5′s built in libraries) and provide some sample code to implement them.
Most particle system tutorials focus on effects such as fire and smoke that are appropriate for sprite-based games. Although there are a number of great tutorials for UIKit particle systems, they are a bit top heavy. I’d like to spend a bit of time doing a “case study” on the less aggressive particle systems we implemented for our casual game. Here is a visual into the effects that I will be showing off:
Anatomy of the System
In UIKit, particle systems consist of two parts:
One or more CAEmitterCells. The emitter cells can be thought of as prototypes for individual particles (e.g., a single puff in a cloud of smoke). When emitting a particle, UIKit looks at the emitter cell and create a randomized particle based on the definition. The prototype includes properties that control the image, colour, direction, movement, scale and lifetime of particles.
One or more CAEmitterLayers but usually just one. The emitter layer mostly controls the shape (e.g., a point, a rectangle or a circle) and the position of the emission (e.g. inside the rectangle, or on the edge). The layer has global multipliers that can be applied to CAEmitterCells within the system. These give you an easy way to blanket changes over all particles – a contrived example would be changing the x velocity of rain to simulate wind.
The basics are simple but the parameters can be quite subtle. CAEmitterLayer has over 30 different parameters to customize the behaviour of particles. Below, I’ll spell out some of the particular issues that caused me grief.
What makes the particle system into a system is randomness. CAEmitterCell’s properties generally have two parameters – a mean and a “cone”: e.g., velocity and velocityRange. By default, the “cone” is 0, meaning that all particles will have identical velocity. By changing the cone, each emitted particle will randomly be perturbed to have a velocity value falling within the cone. This is subtly mentioned in the Apple CAEmitterLayer documentation:
Each layer has its own random number generator state. Emitter cell properties that are defined as a mean and a range, such as a cell’s speed, the value of the properties are uniformly distributed in the interval [M - R/2, M + R/2].
Even colour has a cone: I’ll use this below to make psychedelic smoke. Groovy.
Direction of Emission
CAEmitterCells have a velocity property that means the speed in the direction of emission. The actual direction of emission is specified using the emissionLongitude property. Apple describes this as
The emission longitude is the orientation of the emission angle in the xy-plane. it is also often referred to as the azimuth.
. Every time I see this it makes me want to scream. Here is an example I made to clear things up:
Super quick code for this is available in this gist.
Code Setup / Structure
Setting up your code base is explained in much more detail here. Here are my cliff notes:
Add the “QuartzCore” kit to your project
Create a new view, but set the root layer class to CAEmitterLayer
In the init, set up the CAEmitterLayer and one or more CAEmitterCells
Add the cell to the layer by setting emitterLayer.emitterCells = [NSArray arrayWithObject:cell]
The advantage of this is structure is that it is reasonably modular and can be inserted above / below any particular view. It can also act as a particle system liaison: for example, the stopEmitting code in the above will halt the emission of new particles immediately. Generally I add this view, wait a few seconds to stop it and then wait a few more seconds to remove the view.
Here is the scoop on the effects in the video:
We use coloured smoke as a transition between different text options within the same screen. The effect is made by layering a large number of randomly coloured smoke particles within a rectangular box. We configure them to turn white over time, creating a nice white-out effect.
First, we create the rectangular frame for particle emission:
We account for the short lifeTime by having a relatively large (for the particle size) birthRate. The lifetimeRange makes our smoke particles disappear non-uniformly, adding a bit of variety. In terms of speed, we wanted to have are smoke particles shoot up and then “sink” over the course of their life. This is accomplished by balancing an upwards initial velocity with a downwards yAcceleration:
The secret sauce. Colour. This is mostly a fun trial and error game. I set a slightly white-biased base colour, and configure random variations of red / blue / green around it. All colours have a positive speed, so they will drift towards white in time. Finally, I set a negative alphaSpeed so they get more transparent over their life. Here we go
Psychedelic. You can see the complete code here in the gist. For the particle image, see SmokeParticle.png. Feel free to use it in your own app.
Confetti is used in our reveal animation – it is a visual indicator that you guessed people’s silly faces correctly. The emitter itself comes as a line of particles that “drop” into the screen via gravity. As such, the shape is a bit different than smoke:
As in the apple documentation, the y-coordinate of the position is ignored for lines, and the x is the center of the line. For confetti colours, we will set it up to have a wide range with a slight bias towards white:
The birth rate was determined experimentally – it felt about right. Acute observers would notice that the above code, gives a range of [0.2,1] for each of the colours for confetti. Naturally, we will emit the confetti straight down. While we do this we add yAcceleration so that it looks like gravity is having an effect. The exact numbers were all trial and error:
One final issue: a “wall” of confetti looks a bit strange. The birth rate of confetti should slow down over time, as if there is a finite amount of confetti dropping. I hacked together a couple of quick functions that we use for linear decay over aninterval:
Done! To actually use this code, you’ll probably want the gist. For the particle image, see Confetti.png. Feel free to use it in your own app.
Okay. The Chicken is an easter egg and an homage to Arg! The Pirates Strike Back. I’m not sure we really need to give a detailed description of how to create it. I’ll give a quick description and then let the gist handle the rest.
The Chicken is a point particle that gets emitted at a funny angle and spins while it falls. The only thing that is slightly unique about it is that we fade it in from nothing. The simplest way of doing this is to make the initial alpha colour as 0, and set a large alpha speed (10 = 0.1s fade in):
Happy particling! If I ever have time, I’d love to put together a little Cocoa app for fiddling with the parameters of particle systems. For now, I’m occupied with the Silly Face Society. Sign up and learn when we launch.