My adventures with the Sparrow framework
I had been looking into 2D game development frameworks when one of my friends suggested the Sparrow framework. Having struggled with OpenGLES in the past, I was eager to find a higher-level framework that would allow me to produce some working concepts without writing mountains of code just to render a basic shape on the screen.
I found Sparrow extremely easy to learn and if you have prior 2D or 3D game development experience, it should be even easier to pick up. To get started, download the latest package from:
http://www.sparrow-framework.org/download/
This package comes with the Sparrow library, a demo project, and a scaffold project that can be used as a starting point for all of your Sparrow apps.
For more detail, you can always read the Getting Started guide at:
http://www.sparrow-framework.org/help/gettingstarted/
When you first try to compile, you may get some errors related to the Sparrow source path. To remedy this, go to Xcode preferences > Locations > Source Trees. Create a variable called SPARROW_SRC and point it to the absolute path of your /sparrow/src/ folder.
For example, mine is:
/Users/ken/Work/Sparrow-Framework/sparrow/src
Try testing out the scaffold project to see if it works. If you’re able to see a red square rendered on the screen, Sparrow is setup correctly. Pretty boring so far, right?
I wanted to take it a step further and had an idea in my mind. My first inspiration came from typing in “let it snow” in Google. Determined to produce something with a somewhat similar effect on the iPhone, I had to see what Sparrow was capable of. The concept was to show a glass window on a snowy night. As time passes, snow will accumulate on the window. You may then use your finger to swipe away the snow.
First I created a canvas of type SPRenderTexture to draw on.
SPRenderTexture *mTexCanvas;
SPImage *mImgCanvas;
mTexCanvas = [[SPRenderTexture alloc] initWithWidth:320 height:480];
[mTexCanvas clearWithColor:0xffffff alpha:0];
mImgCanvas = [SPImage imageWithTexture:mTexCanvas];
[self addChild:mImgCanvas];
Next, I needed snowflakes of type SPImage for a few different sizes.
SPImage *mImgSnowLarge;
SPImage *mImgSnowMed;
SPImage *mImgSnowSmall;
mImgSnowLarge = [SPImage imageWithContentsOfFile:@"snow_l.png"];
mImgSnowMed = [SPImage imageWithContentsOfFile:@"snow_m.png"];
mImgSnowSmall = [SPImage imageWithContentsOfFile:@"snow_s.png"];
We will also need to create an eraser brush to wipe away the snow.
SPImage *brush;
brush = [SPImage imageWithContentsOfFile:@"erase.png"];
I also created an SPImage for the background of the sky.
SPImage *mImgSky;
mImgSky = [SPImage imageWithContentsOfFile:@"night.png"];
[mImgSky retain];
[self addChild:mImgSky];
Since I wanted the snow to accumulate on the window glass over time, I also added a timer.
NSTimer *mTimer;
mTimer = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(ticked) userInfo:nil repeats:YES];
To keep track of the touch events when you drag the eraser brush over the snow, I added event listeners to check when erasing firt took place and when erasing finished.
[self addEventListener:@selector(update:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
[self addEventListener:@selector(touched:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
One thing that I had noticed was that Sparrow did not support erasing out of the box. After digging through some of the Sparrow extensions, I stumbled upon SPRenderTexture+Erase that might be able to do what I wanted.
After some experimentation, it did exactly what I needed it to do. This extension allowed me to erase a SPRenderTexture with an SPDisplayObject. In my case, my eraser brush was an SPImage. Erasing is simply one line of code whenever erasing took place.
[mTexCanvas eraseWithObject:brush];
My update and touched event handlers look like this.
- (void)update:(SPEnterFrameEvent*)event{
if(drawing){
// group the draw calls together for speed
[mTexCanvas bundleDrawCalls:^{
double incX = (newTouch.x - lastTouch.x)/numSteps;
double incY = (newTouch.y - lastTouch.y)/numSteps;
brush.x = lastTouch.x - (brush.width/2);
brush.y = lastTouch.y - (brush.height/2);
// loop through so that if our touches are far apart we still create a line
for (int i=0; i
-
(void)touched:(SPTouchEvent*)event{ SPTouch *touchStart = [[event touchesWithTarget:self andPhase:SPTouchPhaseBegan] anyObject]; SPPoint *touchPosition; if(touchStart){ touchPosition = [touchStart locationInSpace:self]; lastTouch = CGPointMake(touchPosition.x, touchPosition.y); newTouch = CGPointMake(touchPosition.x, touchPosition.y); }
SPTouch *touchMove = [[event touchesWithTarget:self andPhase:SPTouchPhaseMoved] anyObject]; if(touchMove){ touchPosition = [touchMove locationInSpace:self]; newTouch = CGPointMake(touchPosition.x, touchPosition.y); drawing = YES; }
SPTouch *touchEnd = [[event touchesWithTarget:self andPhase:SPTouchPhaseEnded] anyObject]; if(touchEnd){ touchPosition = [touchEnd locationInSpace:self]; lastTouch = CGPointMake(touchPosition.x, touchPosition.y); newTouch = CGPointMake(touchPosition.x, touchPosition.y); drawing = NO; } }
That's all there is to it. Once I build and run, I get something like this.
![sparrow_ss01](https://static.objectgraph.com/uploads/2011/12/sparrow_ss01-292x550.png "sparrow_ss01")
![sparrow_ss02](https://static.objectgraph.com/uploads/2011/12/sparrow_ss02-292x550.png "sparrow_ss02")
I've also posted a short 30 seconds video below.