Pages

Sunday, November 13, 2011

A Simple Arcade Game With Sparrow: Part 2


The Sparrow Framework on iOS: Part II
Last month I showed you how to start using the Sparrow Framework, and make a very basic game iOS game. This month we are going to expand that same game by adding in some of Sparrow’s more advanced features, primarily graphics. The source code of this demo has been updated and is available for download from Github; https://github.com/matt62king/SparrowDemo.
I think we could all agree that graphics are the most important part of a game;  wether us coder’s want to admit it or not. I am going to start this tutorial with a graphics update to the game. Last month the focus was using Sparrow, so the graphics were just simple OpenGL renderings. As luck has it, Sparrow has great solutions for handling images in your game. 
OpenGL creates images by rendering textures. Basically it draws a rectangle and lays the image onto it. The SPImage class takes care of this work for you.  
SPImage has several options for using images, the preferred method is by using a texture atlas, a.k.a sprite sheets. Texture atlas are a group of images combined together to make one large image. The idea is that you load the large image once and crop out sections of it to display the individual images you need. It is not as difficult as it sounds, and it will greatly increase the performance of the game.
Sparrow has built in methods that make using a texture atlas’s very simple. The first step is create an atlas. Code‘n’Web has free Mac App called Texture Packer, that will create texture atlases, and give a Sparrow compatible output. Texture Packer can be downloaded from here: http://www.texturepacker.com/. This app has great GUI, all you have to do is add the images you want, select Sparrow as the output format, and click Publish. 

The output will give and image file, and an xml file that is used for cropping the atlas. The xml file for Sparrow will look like this:
<?xml version="1.0" encoding="UTF-8"?>
<TextureAtlas imagePath="Textures.png">
    <!-- Created with TexturePacker -->
    <!--  -->
    <SubTexture name="Background" x="0" y="0" height="480" width="320"/>
    <SubTexture name="Invader" x="320" y="0" height="30" width="30"/>
    <SubTexture name="SpaceShip" x="350" y="0" height="30" width="30"/>
</TextureAtlas>
And the image file will look like this:

Now that we have a texture atlas we can start adding the images to the game. OpenGL can support a texture atlas that is 1024x1024, so for most iOS games you will not need more than one atlas. Remember the idea is that you load the atlas one time and then crop images from it. It is easiest to do this by creating a singleton instance of the SPTextureAtlas class. 
A singleton can be created by adding a category of the SPStage class. In the Game.h file define a category and some methods to set and use an instance of SPTextureAtlas. Add the following after the @end marker:
@interface SPStage (Game)
+ (void)setStageTextureAtlas:(SPTextureAtlas *)texture;
+ (SPTextureAtlas *)atlas;
+ (void)removeTextureAtlas;
@end
The implementation of this category is pretty simple. The +setStageTextureAtlas: method retains an instance, +atlas returns the instance, and +removeTextureAtlas releases the instance. Go to the Game.m file and add the following after the @end marker:
@implementation SPStage (Game)
SPTextureAtlas *mAtlas = nil;
+ (void)setStageTextureAtlas:(SPTextureAtlas *)texture {
    mAtlas = [texture retain];
}
+ (SPTextureAtlas *)atlas {
    return mAtlas;
}
+ (void)removeTextureAtlas {
    mAtlas = nil;
    [mAtlas release];
}
Now that the set-up is complete we are ready to start adding images to the game. We can start with the background image. This background image is a little to dark so we will need to lighten it up a bit. We will do this by putting a white background behind it and making the image semi transparent. In Game.m go to the top of the -initWithWidth:height: method and add a white square the covers the whole screen:
SPQuad *whiteQuad = [SPQuad quadWithWidth:320.0 height:480.0];        whiteQuad.x = 0.0;
whiteQuad.y = 0.0;
whiteQuad.color = 0xffffff;
        
[self addChild:whiteQuad];
Next we can create and store our texture atlas:
SPTextureAtlas *atlas = [[SPTextureAtlas alloc] initWithContentsOfFile:@"Textures.xml"];
[SPStage setStageTextureAtlas:atlas];
[atlas release];
SPTextureAtlas has several methods for creating textures. For this case we use the -initWithContentsOfFile: method. When using this method you need to pass the xml file that was generated from the Texture Packer app. It is important to make sure that the png file that holds your textures is given the same name, if it does not have the same name Sparrow will not be able to find it. 
After the instance is created it can be set with the +setStageTextureAtlas category method we made earlier.  Then the instance is stored in a singleton, so the one that we created can be released. Make sure you call [SPStage removeTextureAtlas]; in the  dealloc method to make sure there are no leaks. 
Next we can add an background image to the game using SPImage. For this case we will use the initWithTexture: method. This method needs an instance of SPTexture for a parameter. First create an instance of SPTexture from our texture atlas:
SPTexture *backgroundTexture = [[SPStage atlas] textureByName:@"Background"];
Calling -textureByName on our instance of SPTextureAtlas will clip the image of the texture atlas for us. You can find the name of the texture by looking at the xml file that was created by Texture Packer. Now we can use the initWithTexture: method of SPImage to create the image. Other than the creation, SPImage works just like any other display object. Add the following lines to make the image:
SPImage *background = [[SPImage alloc] initWithTexture:backgroundTexture];
background.x = 0.0;
background.y = 0.0;
background.height = 480.0;
background.width = 320.0;
background.alpha = 0.75;
[self addChild:background];
[background release];
If you build and run the project now, you will see the planets on the background and the two SPQuad from before. There is one little fix to make. If you double tap the ship to shoot a laser you will notice that you do not see anything happen. That is because we set the laser to be behind all the other objects. To fix this go to the -onShoot: in the Game.m file. Find [self addChild:laser atIndex:0]; and replace it with [self addChild:laser atIndex:2];. This will put the laser on top of the two background objects that we added. 
Use the same methods to create images for the ship and enemy sprites. Make sure you import Game.h into the Ship and Enemy classes so the SPStage category is usable. In the Ship.m’s init method replace the SPQuad creation, setting, and display with:
SPTexture *ship = [[SPStage atlas] textureByName:@"SpaceShip"]; 
         
SPImage *shipImage = [[SPImage alloc] initWithTexture:ship]; shipImage.x = -shipImage.width/2.0;
shipImage.y = -shipImage.height/2.0;
shipImage.height = 30.0;
shipImage.width = 30.0;
[self addChild:shipImage];
        
[shipImage release];
Do the same for the enemy in Enemy.m. Notice for the enemyImage instance, the color property is set. This is because the image used is semi transparent so setting the color property darkens it. 
SPTexture *enemyTexture = [[SPStage atlas] textureByName:@"Invader"];
        
SPImage *enemyImage = [[SPImage alloc] initWithTexture:enemyTexture];
enemyImage.color = 0x0000ff;
enemyImage.x = -enemyImage.width/2.0;
enemyImage.y = -enemyImage.height/2.0;
[self addChild:enemyImage];
        
[enemyImage release];
Remember in the last version we rotated the ship 45 degrees to make a diamond shape instead of a square. Now that the ship is an image we need to fix that. Go into the Game.m file, in the -initWithWidth:height: method find the ship.rotation = SP_D2R(45); and delete it. Build and run the game and you should see this:

  Now that we have a better looking game we can make it more interesting to play.
One thing we can do is add more enemies to give the game some challenge. To accomplish this we will have to make some modifications to the Game and Enemy classes. Starting in the Game.h file, add the following instance variables:
NSMutableSet *mEnemies;
float mTimePassed;
We will use a NSMutableSet to hold instances of our enemies, and the float will be used to count the time for new enemies to be added. There is a bit of fixes to make in the Game.m file. Starting from the top add a variable above the -initWithWidth:height: method, and remove the BOOL variable that is already there.
static float kEnemyDispatchTime = 1.5;
Inside the -initWithWidth:height: method insert the following lines at the top to initialize the NSMutableSet and set the mTimePassed to zero. Do not forget to release the mEnemies in the dealloc method.
mEnemies = [[NSMutableSet alloc] initWithCapacity:1];
mTimePassed = 0.0;
Next remove the creation and adding of the Enemy instance. Then go to the -advancedTime: method and remove everything after [self testCollisions];. Add the following to the advancedTime: method:
[mEnemies makeObjectsPerformSelector:@selector(advance)];
    
    if (mTimePassed < kEnemyDispatchTime) {
        mTimePassed += seconds;
    }
    else {
        mTimePassed = 0.0;
        
        Enemy *enemy = [[Enemy alloc] init];
        enemy.x = 150.0;
        enemy.y = 50.0;
        
        [mEnemies addObject:enemy];
        
        [self addChild:enemy];
        [enemy release];
    }
The first line in the block uses the NSSet instance method, makeObjectsPerformSelector: to move all of the enemy instances. Next, it checks to see if it is time to add another enemy. Notice that the comparison checks if the time passed is less than the dispatch time. We want an enemy to appear every 1.5 seconds but it  is unlikely that the time passed will equal exactly 1.5.  If enough time has not passed we add the amount that has. If enough time has passed, the time passed is reset to zero, and a new Enemy instance is created, added to the stage, and the NSMutableSet.
Since there are now several instances of the Enemy class on the game, each one needs to handle it’s own movement.  Start in the Enemy.h file and add an instance variable of: 
BOOL mIsMovingLeft;
Also define the following method:
  • (void)advance;
Move to the Enemy.m file and add mIsMovingLeft = NO; inside the -init method.   Next we need to implement the -advance method. This will be very similar to the way an enemy was moved before. The biggest difference is that when an enemy moves down the screen it moves by 40 px instead of 20 px. This is to keep the screen from being too crowded. Add the following method to Enemy.m.
- (void)advance {
    if (!mIsMovingLeft) {
        self.x = (self.x + 1);
        if (self.x == 300) {
            self.y = (self.y + 40);
            mIsMovingLeft = YES;
        }
    }
    else {
        self.x = (self.x - 1);
        if (self.x == 20) {
            self.y = (self.y + 40);
            mIsMovingLeft = NO;
        }
    }
}
If you build and run now you will see lot of enemies appear and move their way down the screen. The next issue is laser collisions are not going to be recognized. Just like each instance of an Enemy needs to handle its own movement, they each need to handle their own collisions as well. To do this, go to the Enemy.h file and import Laser.h. Then define the following method.
- (void)testCollisionWith:(Laser *)laser;
Move into the Enemy.m file for the implementation of this method. The implementation of this method is basically the same as it was when the collisions were handled by the Game.m file. Add the following to method to the Enemy.m file.
- (void)testCollisionWith:(Laser *)laser {
    SPRectangle *enemyRect = [self boundsInSpace:self.parent];
    SPRectangle *laserRect = [laser boundsInSpace:self.parent];
    
    if ([laserRect intersectsRectangle:enemyRect]) {
        [self.stage removeChild:laser];
        
        SPTween *tween = [SPTween tweenWithTarget:self time:0.5];
        [tween animateProperty:@"rotation" targetValue:(self.rotation + SP_D2R(360))];
        [tween animateProperty:@"width" targetValue:0.0];
        [tween animateProperty:@"height" targetValue:0.0];
        [self.stage.juggler addObject:tween];
        
        [self.stage performSelector:@selector(destroyedEnemy:) withObject:self afterDelay:tween.time];
    }
}
First SPRectangle objects are created for the enemy and laser instances. The rectangles represent where they are at in the enemy’s parent object. In this case the parent object is the stage. If the laser and an enemy are in the same space, the laser is removed and the enemy does a spin into its removal. Lastly, the stage is notified of the collision by performing a selector after a delay that is equal to the animation’s time.
The stage still needs to handle the collision. Start by defining the following method in Game.h: 
  • (void)destroyedEnemy:(Enemy *)enemy;
The implementation of this method is strait forward. All it needs to do is remove the  enemy from the stage and the mEnemys mutable set.
- (void)destroyedEnemy:(Enemy *)enemy {
    [self removeChild:enemy];
    [mEnemies removeObject:enemy];
}
At the end of this tutorial your game should look something like this:
This game has now gone from a wireframe prototype to a game with a graphical interface and some challenging play. All in all, utilizing this tutorial will take approximately  two to three hours of coding time. This of course depends on how familiar you are with Sparrow Framework.
All the images used in this demo were downloaded from Open Clip Art at http://www.openclipart.org/. This site is a great source for royalty free graphics, if you need quick images.  
The full source code of this and the previous demo is available on github at https://github.com/matt62king/SparrowDemo. I have tagged the sources to match the series, part I and part II.  Or download the master branch for the full source. 

Sunday, October 30, 2011

A Simple Arcade Game With Sparrow: Part 1


        The iOS game market has become one of the biggest game markets available today. The low cost of entry into the market helps make it a prime area for independent developers. The biggest challenge then becomes graphics programing. If you have little or no graphics programing knowledge and try to take on an OpenGL project, you will see what I mean. 
This is exactly how I discovered the Sparrow Framework. I had been doing iOS programing for a little over a year. I had published a few utility apps and was starting to carve out my place in the market. I wanted to get into the game market as well, so I dove into OpenGL. After a frustrating month of trial and error, forum searching, and googling, i thought there must be a better way. 
Then I found the Sparrow Framework. Sparrow is a Cocoa Touch wrapper for 2D OpenGL. Sparrow is open source project created by Daniel Sperl. Its is simple, fast, high quality, and has an amazing support group. Daniel himself is available to answer most questions.  
I was very impressed by Sparrow’s power and ease, and that is why I want to share it with all of you. The remainder of this article will describe how to input Sparrow
in your own projects. I will do this creating a simple arcade style game. Lets get started; the Sparrow Framework is available for download here: http://www.sparrow-framework.org/download/ or from GitHub here: https://github.com/PrimaryFeather/Sparrow-Framework
There are several different ways to incorporate Sparrow into into your project. This tutorial is going to use the scaffold project that is included with the download. After downloading the project you need to add it to your source trees in XCode. Open XCode, go to Preferences, and select the Sources Trees Tab. Click the add button. The Setting and Display Name needs to be SPARROW_SRC. The path needs to be the full path to Sparrow’s src folder, for example: /Users/Matt/Desktop/iPhone-Projects/Frameworks/sparrow/sparrow/src.

From here find the Sparrow scaffold project, and copy it. From the download the scaffold project can be found at samples->scaffold->src. Just copy the entire src folder and paste where you want your project. Then open the XCode project that is inside that folder. Rename the project going to the targets build settings, find the Product Name field and change the name. 
Build and run the project. If everything is set right you will see a black screen with  red square. 


In the scaffold project the Sparrow Framework is already set up for you. Look over the ApplicationDelegate h and m files to get an idea of how the start up works. When you are building a Sparrow project think of it like you are building a tree. The trunk of the tree is the SPStage object. The branches are subclass of the SPDisplayObject. Sparrow has several prebuilt subclasses to include sprites, images, buttons, text fields, and movies. All of these will branch out from trunk. 
The scaffold project already has the an SPStage subclass set up for you, it is the Game h and m file. Generally your game will only need one stage. For the demo we will add three more classes named Ship, Enemy, and Laser, they will all be SPSprite subclasses. For this game we just make our sprites simple squares. Sparrow has a SPQuad object that will render colored squares with OpenGL. This is most effect method to use if you don’t need detailed sprites. 
Add the following code to the Ship.m file: 
- (id)init {
    self = [super init];
    if (self) {
        SPQuad *quad = [SPQuad quadWithWidth:30.0 height:30.0];
        quad.color = 0xffffff;
        quad.x = -quad.width/2.0;
        quad.y = -quad.height/2.0;
        [self addChild:quad];
        
    }
    return self;
}
- (void)dealloc {
    [super dealloc];
}
This what Sparrow code will look like. We have a basic init method, where we make the square. I’ll go over this code line by line to give you the idea of what is happening. 
SPQuad *quad = [SPQuad quadWithWidth:30.0 height:30.0];
This is a basic factory method for creating a new instance of SPQuad. Just pass a width and height parameters for the size you want.
quad.color = 0xffffff;
This sets the color of the square. Sparrow uses the hexadecimal color reference. 0x000000 will give you white.
quad.x = -quad.width/2.0;
quad.y = -quad.height/2.0;
These two lines set x and y position of the quad relative to its parent. Setting the x and y to the width and height divided by two moves the origin to the center of the quad. This needs to be done for the proper rotating of the object.
[self addChild:quad];
This is the Sparrow equivalent of addSubview: You need to call this in order for the quad to be displayed.
All of Sparrow display objects are created in a similar way. Some of the specialty display objects have unique properties and methods. Check the Sparrow documentation for more information. For our game the Enemy and Laser will be set up in the same way as the Ship was.
Add the following code to Enemy.m:
- (id)init {
    self = [super init];
    if (self) {
        SPQuad *quad = [SPQuad quadWithWidth:30.0 height:30.0];
        quad.color = 0x0000ff;
        quad.x = -quad.width/2.0;
        quad.y = -quad.height/2.0;
        [self addChild:quad];
        
    }
    return self;
}
- (void)dealloc {
    [super dealloc];
}
Add the following code to Laser.m:
- (id)init {
    self = [super init];
    if (self) {
        SPQuad *quad = [SPQuad quadWithWidth:10.0 height:30.0];
        quad.color = 0xff0000;
        quad.x = -quad.width/2.0;
        quad.y = -quad.height/2.0;
        [self addChild:quad];
        
    }
    return self;
}
- (void)dealloc {
    [super dealloc];
}
Now that our sprites are created we can put the game together. Go into the the Game.m file and import the three sprites. Game.m will have an initWithWidth:height: method. Inside that method you will see all the code that created red square seen earlier. Delete this code out and replace it with:
- (id)initWithWidth:(float)width height:(float)height {
    if (self == [super initWithWidth:width height:height]) {
        Ship *ship = [[Ship alloc] init];
        ship.x = 150.0;
        ship.y = 400.0;
        ship.rotation = SP_D2R(45);
        ship.name = @"Ship";
        
        [self addChild:ship];
        [ship release];
        
        Enemy *enemy = [[Enemy alloc] init];
        enemy.x = 150.0;
        enemy.y = 50.0;
        enemy.name = @"Enemy";
        
        [self addChild:enemy];
        [enemy release];
    }
    return self;
}
This is just adding the sprites we created to the game’s stage. You will notice there are a couple of new properties set here. The name property gives us the ability to find the object later on by its name. Also we used the rotation property. OpenGL expects radian values to preform rotations. Sparrow comes with a handy macro to convert degrees to radian values. To rotate the ship 45 degrees we just have use the macro SP_D2R(45). Positive values rotate clockwise and negative values will rotate counterclockwise. If you build and run now you should see this:


Now this game needs some control. We want the enemy to move by itself and the ship to be moved by the user. Sparrow has a built in timer to step your game, so there is no need to create your own. Just add the follow method to the Game.m file:
- (void)advanceTime:(double)seconds {
    [super advanceTime:seconds];
    
}
The amount of times this method is called depends on what the stage’s frame rate is set at. Most games can run at 30 fps. If your game needs some faster speeds the  iOS devices can run at 60 fps. Make sure you call advanceTime: on the super object to keep the rest of the graphics framework running smooth. 
We want the enemy to move back and fourth across the screen and move down getting closer to the ship.  First we need to know which way the enemy is moving when it is going across the screen, to do this add an bool iVar named enemyIsMovingLeft. To move the enemy add the following code into the advanceTime: method. 
 Enemy *enemy = (Enemy *)[self childByName:@"Enemy"];
    
    if (!enemyIsMovingLeft) {
        enemy.x = (enemy.x + 1);
        if (enemy.x == 300) {
            enemy.y = (enemy.y + 20);
            enemyIsMovingLeft = YES;
        }
    }
    else {
        enemy.x = (enemy.x - 1);
        if (enemy.x == 20) {
            enemy.y = (enemy.y + 20);
            enemyIsMovingLeft = NO;
        }
    }
All of Sparrow display objects have an x and y property that can be changed at any time. If you need continuos movement, using logic such as the above in the advanceTime: method is a good way to manage it. The first line of this block is one of the most useful methods of Sparrow. The childByName: method can look up a display object by the name you assign to it. You should use this as often as possible, instead of retaining the object in an iVar.
The next thing we need to do is provide a way for the user to move the ship and shoot at the enemy. We will make the ship move by the user dragging it to the left or right and shoot a laser with by double tapping the ship. Sparrow has its own touch recognition built in. Define the method -(void)onTouch:(SPTouchEvent *)touch for the Ship class, and add the following line to the init method.
[self addEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
This adds the Ship object to Sparrow’s event dispatching. There are several events that Sparrow will dispatch itself, or you can create your own events. When you add an event listener you are responsible for removing it as well. Add the follow line to the dealloc method to remove the event listener.
[self removeEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
Now that the Ship can receive touches we just have to code them in. In Sparrow all the touches are handled by one method, in this case it is the onTouch: method we defined. In that method the touch phase (began, moved, or ended) will be defined.
The onTouch: method should look like this:
- (void)onTouch:(SPTouchEvent *)touch {
    SPTouch *begin = [[touch touchesWithTarget:self andPhase:SPTouchPhaseBegan] anyObject];
    SPTouch *moved = [[touch touchesWithTarget:self andPhase:SPTouchPhaseMoved] anyObject];
    
    if (begin) {
        if ([begin tapCount] == 2) {
            SPEvent *shoot = [SPEvent eventWithType:@"ShootEvent" bubbles:YES];
            [self dispatchEvent:shoot];
        }
    }
    
    if (moved) {
        if ([moved locationInSpace:self.parent].x > 30 && [moved locationInSpace:self.parent].x < 300) {
            self.x = [moved locationInSpace:self.parent].x;
        }
    }
}
There are a few things happening here. First we define the two touch phases we need by calling the touchesWithTarget:andPhase: methods. This method returns an NSSet of SPTouch objects. Next is the code for when a touch begins. First we check and see if there has been a double tap, this is done by calling tapCount on the begin instance of SPTouch. If there was a double tap a custom SPEvent is created and dispatched. 
When creating a Sparrow event you have the option to make it bubble. To visualize a bubbling event, think of the display tree discussed earlier.  When a bubbling event is dispatched will work its way from its own branch of the tree back to the trunk. Any branch along the way can preform process with the event and it will continue to move unit it reaches the trunk or it is stopped. 
The last thing we do is process when a touch is moved. We just want the ship to move to the left and right along the bottom of the screen.  Since the Ship object needs to move around on the stage, we need to the location of the touch in the stage. so we use the locationInSpace: method. This method gives the touche’s location inside of the given display object. In this case that object is the parent so we pass self.parent to the method. To move the Ship first make sure the touch is within a specific area so the ship cannot be moved of the screen. Next just set the ship’s x property to the x location of the touch. 
All of our touches are set, the next thing to do is handle the shoot event that we created. We will handle this event with the game’s stage. First thing is to go define a method -(void)onShoot:(SPEvent *)event in the Game class. All though the shoot event is a bubbling event, we still need to add an event listener in the Game.m initWithWidth:height: method. Do not forget to remove it.
[self addEventListener:@selector(onShoot:) atObject:self forType:@"ShootEvent"];
  The Laser needs to start at the ship and quickly go up the screen. We will use an instance of SPPoint to find out where the ship is at, and SPTween to move the laser up the screen. The SPTween class powers Sparrow’s animations. Animations should be used when moving the object with advanceTime: method is impractical. When it is done your onShoot: method will look like this:
- (void)onShoot:(SPEvent *)event {
    Ship *ship = (Ship *)[self childByName:@"Ship"];
    
    SPPoint *lPoint = [SPPoint pointWithX:ship.x y:(ship.y - 30.0)];
    
    Laser *laser = [[Laser alloc] init];
    laser.x = lPoint.x;
    laser.y = lPoint.y;
    laser.name = @"Laser";
    
    [self addChild:laser atIndex:0];
    
    SPTween *tween = [SPTween tweenWithTarget:laser time:0.25];
    [tween animateProperty:@"y" targetValue:-30.0];
    [self.juggler addObject:tween];
    
    [self performSelector:@selector(removeChild:) withObject:[self childByName:@"Laser"] afterDelay:tween.time];
    
    [laser release];
}
First we have to find the where the ship is on the screen. To do that we access the ship using the childByName: method. After that we create an instance of SPPoint using the ship’s x and y coordinates. I have went ahead and subtracted 30 from the ship’s y coordinate to make laser appear out the ship instead of on top of it. After that we create an instance of the Laser sprite and set the x and y properties using the point from above.  This time we use addChild:atIndex: method to add the laser. Passing 0 to this method will put the laser sprite behind all the other sprites on the screen. 
To move the laser, we use an instance of SPTween. The SPTween was created using the tweenWithTarget:time: factory method. The target is the display object that you want to animate and the time is how long the animation should take. To configure the animation we use animateProperty:targetValue: method. With Sparrow any display object property that is a number can be animated. Properties are passed by giving an NSString representation of the property. The targetValue it where you want the object to be when the animation is done. In order for the tween to work it has to be added to a juggler. Every instance of SPStage has its own juggler built in, so we just used it. SPTween dispatches several events to monitor its progress, however since all we need to do with the laser is remove it when the animation is done. It is easiest to do this using NSObjects performSelector:withObject:afterDelay: method, using the tween’s time for the delay.
  The last thing needed is some collision detection. Sparrow does have basic collision detection built in. If you need advanced collision detection I would recommend adding a physics engine to your game.  For this example it is easiest to handle the collisions in the stage. Define a testCollisions method and call it from the advanceTime: method. This way the game will test for collisions on every step. We only need to see the if the laser hits the enemy. The testCollisions method will look like this:
- (void)testCollisions {
    SPRectangle *enemy = [[self childByName:@"Enemy"] boundsInSpace:self];
    SPRectangle *laser = [[self childByName:@"Laser"] boundsInSpace:self];
    
    if (laser) {
        if ([laser intersectsRectangle:enemy]) {
            SPTween *tween = [SPTween tweenWithTarget:[self childByName:@"Enemy"] time:0.5];
            [tween animateProperty:@"rotation" targetValue:([self childByName:@"Enemy"].rotation + SP_D2R(360))];
            [self.juggler addObject:tween];
        }
    }
}
Basic collision detection is fairly simple with Sparrow. What happened here is we created a bounding box for the enemy and the laser using instances of SPRectangle. With SPRectangle we can find out where each object is using the boundsInSpace: method. In this case the space is our stage. After we know where the objects are we check to see if they are touching each other. SPRectangle instances can check if they are touching another instance with the intersectsRectangle: method. This method returns a bool value. If the laser and enemy are in the same space we just give the enemy a little animation to show that it was hit. 
There is no menus, points, and the graphics are not superb, but as you can see with the Sparrow Framework you can have functioning game play in less than hour. If you want to explore Sparrow more, visit their web site at www.sparrow-framework.org. The web site has lots of tutorials on the finer points of Sparrow, its own forum, full documentation, and recently added a wiki where you can find several extensions from other developers.
Note: This article was written for Sparrow v1.1, however Sparrow v1.2 was released while I was writing. Make sure you check the release notes for changes if you download v1.2.

Follow me on Twitter @matt62king
This projects is available at https://github.com/matt62king/SparrowDemo