A closer look at the Loom Game Engine, Part Five: Input and Sound

In the prior section we looked at getting graphics on screen.  In this section we will look at how to control your game and play sound.

 

Let’s jump right in with a touch example.

package

{

    import cocos2d.Cocos2DGame;

    import cocos2d.CCSprite;

    import cocos2d.Cocos2D;

 

    public class HelloWorld extends Cocos2DGame

    {

        public var sprites:Vector.<CCSprite>;

        public var cancelTouch:Boolean;

        override public function run():void

        {

            cancelTouch=false;

            sprites = new Vector.<CCSprite>();

            super.run();

            layer.onTouchBegan += onTouchBegan;

            layer.onTouchEnded += onTouchEnd;

        }

 

        public function onTouchBegan(id:int,x:Number,y:Number):void{

 

            for each(var s in sprites){

                if(s.hitTest_loomscript(x,y)){

                    System.Console.print(“Hit”);

                    layer.removeChild(s);

                    sprites.remove(s);

                    cancelTouch = true;

                }

            }

        }

 

        public function onTouchEnd(id:int, x:Number, y:Number):void

        {

            if(cancelTouch)

            {

 

                cancelTouch=false;

                return;

            }

 

            var sprite = CCSprite.createFromFile(“assets/robin.png”);

            

            sprite.x = x;

            sprite.y = y;

            sprite.scale = 0.5;

            layer.addChild(sprite);

            sprites.push(sprite);

        }

 

    }

}

 

When we run the application, as we touch the screen, one of the following occurs.  If the space is empty, a sprite is added.  If the location touched contains a sprite already, that sprite is removed.

 

Selection

 

Let’s take a quick look at what we did here.  We start off creating a Vector of CCSprites to hold our various sprite images.  The key part was in the Run() method was wiring up delegates for onTouchBegan and onTouchEnded, these methods will be called predictably enough when the screen is touched and when the screen is released.  When a touch occurs, we loop through the sprites in our vector and see if there is a sprite at that location already.  If there is we set cancelTouch to true to make sure the touch isn’t handled again on onTouchEnded.  We then remove the sprite from the layer, and the vector. In onTouchEnd, we simply create a sprite at that location, add it to the scene and our vector.

 

As you can see, handling touch is pretty simple.  Using a combination of onTouchBegan, Ended, Moved and Cancelled and tracking the id and location of the touches ( passed as parameters to the delegate ) you can handle dragging, dropping, pinch, zooming etc.  The Iso demo is the key place to look at for ideas how to implement advanced touch functionality.  One thing I did find annoying though was finding the parameters for the various delegate calls, no idea where to figure them out.  I figured out the onTouchBegan/Ended parameters by finding them in samples.  Another option is to dig into the C++ source code, which you can download as a separate archive.  Fortunately the class names on the C++ side of things mirror the Loom/Cocos2d side of things.  In this case, look up the CCLayer source code, located at /loom/engine/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp.  If you dig into the source code, you can puzzle out the parameters:

bool CCLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)

{

    if(_TouchBeganDelegate.getVM())

    {

        CCPoint localPoint = convertToNodeSpace(pTouch->getLocation());

 

        _TouchBeganDelegate.pushArgument(pTouch->getID());

        _TouchBeganDelegate.pushArgument(localPoint.x);

        _TouchBeganDelegate.pushArgument(localPoint.y);

        _TouchBeganDelegate.invoke();

        return true;

    }

}

 

I do wish there was an easier way to figure this stuff out, and it’s quite possible there is, but I didn’t find it.  It’s nice to know you can drop to the source code if needed though.

 

Alright, so thats touch, let’s take a look at using the accelerometer.  Let’s jump right in with code:

package

{

    import cocos2d.Cocos2DGame;

    import cocos2d.CCSprite;

    import cocos2d.Cocos2D;

 

    public class HelloWorld extends Cocos2DGame

    {

        override public function run():void

        {

            super.run();

            var sprite = CCSprite.createFromFile(“assets/robin.png”);

            

            sprite.x = Cocos2D.getDisplayWidth()/2;

            sprite.y = Cocos2D.getDisplayHeight()/2;

            layer.addChild(sprite);

 

            layer.onAccelerate += function(x:Number, y:Number, z:Number) {

                if(sprite.x > 0 && sprite.y > 0 &&

                    sprite.x < Cocos2D.getDisplayWidth() && sprite.y < Cocos2D.getDisplayHeight())

                {

                    System.Console.print(x);

                    sprite.x += x * 5;

                    sprite.y += y * 5;

                }

                else

                {

                    sprite.x = Cocos2D.getDisplayWidth()/2;

                    sprite.y = Cocos2D.getDisplayHeight()/2;

                }

            }

        }

    }

}

 

 

 As you can see it’s remarkably straight forward.  We draw a sprite centred to the screen, recycling the code we used a little while back.  The biggest difference is the onAccelerate delegate we assign to layer.  As you can see, this takes three values x,y and z.  These represent the amount of movement along each axis.  If you tilt your phone slightly up or down, Y will have a value like 0.01 or -0.0122332, depending on which direction.  The magnitude of the number ( between 0 and 1 I believe ) represents the speed of the motion.  So if you vigorously shake your phone, the numbers will be much higher then just tilting it.  If you run this code on your phone, the sprite will travel in whatever direction you tilt your phone until it gets to the screen edge, when it will go back to the centre.

 

So, thats touch and motion, now let’s take a quick look at audio.

 

package

{

    import cocos2d.Cocos2DGame;

    import CocosDenshion.SimpleAudioEngine;

    import cocos2d.Cocos2D;

 

    public class HelloWorld extends Cocos2DGame

    {

        override public function run():void

        {

            super.run();

            SimpleAudioEngine.sharedEngine().preloadEffect(“assets/gunshot.mp3”);

 

            SimpleAudioEngine.sharedEngine().playBackgroundMusic(“assets/song.mp3”);

 

            layer.onTouchEnded += function (){

                SimpleAudioEngine.sharedEngine().playEffect(“assets/gunshot.mp3”);

            };

 

            layer.onKeyBackClicked += function (){

                if(SimpleAudioEngine.sharedEngine().isBackgroundMusicPlaying())

                    SimpleAudioEngine.sharedEngine().pauseBackgroundMusic();

                else

                    SimpleAudioEngine.sharedEngine().resumeBackgroundMusic(); 

            };

        }

    }

}

 

When you run this, it will automatically start playing the background music song.mp3.  If you tap the screen, it will play the sound effect gunshot.mp3 as many times as you press the screen.  Finally we wire up a delegate to handle pressing the back button on your device ( no clue what this does on iOS ), that either pauses background music playback, or resumes it.  It’s the Cocos2d Denshion library that handles audio.  It handles formats other than mp3, but each time I tried to use a WAV file, it didn’t work.  I seem to recall Denshion being kinda picky about file formats, so I’m not shocked.

 

As you can see, input and audio are both fairly simple with Loom.

 

That concludes our look at the Loom Engine.  Of course, we only scratched the surface of what it can do, but I hope you got a good idea of what working with Loom is like.  

 

Jump forward to the conclusion.


Scroll to Top