• Migrating to Starling 1: Get it to Compile

    Starlings by onkel_wart

    Welcome to the first of Colin Northway’s “I’m Too Busy Writing Games to Write Technical Blog Posts So I’ll Just Write a Shoddy Technical Blog Post Really Quickly Instead”.

    This Shoddy blog post is the first of two on migrating an existing project to Starling and Falsh’s Stage3d. You can find part 2 here.

    Well Flash is now all jiggy with the graphics card and even though you started your project a year ago you’re definitely going to want to get all jiggy too. Putting graphics on the graphics card is way faster and you get all those extra CPU cycles to do cool things like physics. Plus you can play with neat things like Pixel Shaders which I’ll talk about in a future post.

    This is all based on my experience converting Incredipede and is really just intended to provide a vague roadmap through the experience. This first post will merely be about getting your project swapped over and compiling. The next one will be about making your Stage3d code suck less.

    First thing’s first: go download Starling. Starling is a 2d Stage3d framework being written by Daniel Sperl. It wraps the flexible but verbose Stage3d stuff into a Display-List-like interface. It’s open source, Daniel is constantly working on it, the community is growing and helpful, and it’s quite good so it’s prolly the way to go for 2d Flash games from now on. Also, it closely replicates the way Flash did things before Stage3d existed so it’s going to make it much easier to convert your existing project.

    To get you going, you’ll need to grab the newest versions of the Flex SDK, either the AIR SDK or playerglobal.swc, and the Starling SDK, point your project at them and add “-swf-version=13” to your compiler options. Read the first part of the quite good Starling Introduction by Thibault Imbert, and come back when you call starling.start();

    Now that you have Starling all up and running it’s time to do some mass search and replaces. This would be a really really good time to back up your code. It’s pretty hard to undo the changes we’re going to make so please back it up in case you get half way through and decide I’m an idiot who led you astray.

    Now to work: time to grab the Flash display list, yank out the spine, and then stuff Starling down in the hole left behind.

    Search and replace the following:

    “import flash.display.DisplayObject;” with “import starling.display.DisplayObject;”

    “import flash.display.Sprite;” with “import starling.display.Sprite;”

    “import flash.display.MovieClip;” with “import starling.display.MovieClip;”

    Now everything is going to be broken and you’re going to get a lot of Compile Time errors, mostly where you add graphics to the game. Less’ fix ’em!

    An Error has Occured

    There are three ways you might be getting graphics into your game at the moment. You might be embedding images, you might be embedding MovieClips and you might be using the flash 2d graphics drawing API. Incredipede uses all 3 so I’ve got a system in place to deal with all of them. Let’s deal with embedding images and MovieClips first.

    Most of your compile time errors are going to be where you .addChild(new Graphic()); because starling’s Sprite.addChild method takes a starling.display.DisplayObject not a flash.display.DisplayObject.

    It’s just going to take a little grunt work to make these errors go away. We’re going to do it in a very easy, very bad way and then after you have everything running we’ll go back and make everything suck less (in the next post).

    First let’s make up a very simple, static, texture manager class:

    public class TextureManager
    {
        public static function imageFromSprite(sprite:DisplayObject):Image
        {
            var rect:Rectangle = sprite.getBounds(sprite);
    
            var image:Image = new Image(textureFromSprite(sprite));
            image.x = rect.x;
            image.y = rect.y;
    
            return image;
        }
    
        public static function textureFromSprite(sprite:DisplayObject):Texture
        {
            var rect:Rectangle = sprite.getBounds(sprite);
    
            if ( rect.width > 2048 ) {
                rect.width = 2048;
                trace("Bitmap too big, shrinking");
            }
            if ( rect.height > 2048 ) {
                rect.height = 2048;
                trace("Bitmap too big, shrinking");
            }
    
            //red box means invalid texture
            if ( rect.width <= 2 || rect.height <= 2 ) {
                var tempSprite:flash.display.Sprite = new flash.display.Sprite();
                tempSprite.graphics.beginFill(0xFF0000);
                tempSprite.graphics.drawRect(0, 0, 50, 50);
                sprite = tempSprite;
                rect = sprite.getBounds(sprite);
            }
    
            var bmd:BitmapData = new BitmapData(
                rect.width, rect.height, true, 0x0000000000);
            var matrix:Matrix = new Matrix();
            matrix.translate( -rect.x, -rect.y);
    
            // draw the shape on the bitmap
            bmd.draw(sprite, matrix);
    
            var texture:Texture = Texture.fromBitmapData(bitmapData);
    
            return texture;
        }
    }

    This takes whatever DisplayObject you just passed in, converts it to a bitmap and then uploads it to the graphics card. Now you can go replace all of your:

    addChild(new Graphic())

    with this call:

    addChild(TextureManager.imageFromSprite(new Graphic()));

    That should work for Sprites and MovieClips (alhtough they wont animate) and .PNGs and anything you might embed.

    So that will have killed a lot of errors but there are still a lot left. Among them are all those graphics.beginFill calls which now make no sense.

    To make those errors go away just draw to an intermediate sprite and pass that to imageFromSprite() like this:

    var sp:Sprite = new Sprite();
    sp.graphics.stuff
    sp.graphics.etc...
    addChild(TextureManager.imageFromSprite(sp));

    WARNING: you are now leaking horribly into texture memory. Read part 2 if you are interested in how I stopped this.

    Now all your graphics problems should be gone. You’re close to having things at least running. Well, if all those Event errors weren’t staring at you pretty menacingly you’d be close.

    Starling replaces the Flash event model with its own. I’m not totally in love with this decision but whatever, we can work with it. More search and replace!

    replace “import flash.events.Event;” with “import starling.events.Event;”

    Now all your event classes extend Starling.event.Event so you have to go remove all the clone() methods from them. That’s one upside to Starlings events. One of the down sides is that all your MouseEvents just stopped working.

    That sucks pretty hard right? Well, if you step into this back alley I have some candy you might like. Just don’t tell anyone you got this from me…

    Starling handles mouse events in a totally different way than Flash. Which is too bad because Incredipede was written to use Flash’s mouse events and changing the way everything works is going to kind of suck. But if we put this method in a Utils class:

    public static function addMouseListener(mouseEvent:String,
        target:starling.display.DisplayObject, callback:Function):void
    {
        target.addEventListener( TouchEvent.TOUCH, function( event:TouchEvent ):void {
            var touch:Touch = event.getTouch(target.stage);
            var newEvent:MouseEvent;
            if ( mouseEvent == MouseEvent.MOUSE_DOWN
                && touch.phase == TouchPhase.BEGAN ) {
                newEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, false);
            }else if ( mouseEvent == MouseEvent.MOUSE_MOVE
                && touch.phase == TouchPhase.MOVED ) {
                newEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, false);
            }else if ( (mouseEvent == MouseEvent.MOUSE_UP
                || mouseEvent == MouseEvent.CLICK)
                && touch.phase == TouchPhase.ENDED ) {
                newEvent = new MouseEvent(MouseEvent.MOUSE_UP, false);
            }
            if ( newEvent != null ) {
                callback(newEvent);
            }
        });
    }

    Then we can replace

    button.addEventListener(MouseEvent.MOUSE_DOWN, loadMain);

    with

    Utils.addMouseListener(MouseEvent.MOUSE_DOWN, button, loadMain);

    Of course this is pretty limited. You can’t get the mouse position from the event or anything (although you could make position work) but it’s a quick and dirty way to make your code compile.

    In fact at this point your game should be running! On the graphics card! Really fast! Or actually, you might be uploading a lot of textures to the graphics card every frame depending on how your game works so it might instead be Really slow! Which we’ll fix next time.

    I welcome other suggestions if you’ve found better ways to do some of this stuff. Stay tuned for my next post when I discuss “how to make your Stage3d code suck less”. See you then!

    starlings on wires by Hopefoote
  • Incredipede Christmas

    My folks got me these great Incredipede themed pins from Illuminati Glassworks on Gabriola Island. Gabriola is a small island off of the coast of British Columbia. Sarah and I are spending Christmas in B.C. on Vancouver Island where I grew up. Gabriola is known for supporting a lot of interesting artists.

    We’ll see what happens to them… I only have like 10 so I guess I’ll give them to friends? Or mabey I’ll do some kind of contest…?

  • Philippines & Hong Kong


    Kiss
    Originally uploaded by apes_abroad.

    After Tokyo we spent two months in the Philippines with our friends Ron and Arlie, and my god did we have a blast. We stayed in a seaside mansion where we had delicious Filipino food prepared for us nightly, and were visited by friends from across the indieverse and beyond. We took a lot of pictures, and it seems most of them fit into the categories: sailing, snorkeling… and bugs.

    Oh and some photos of me shooting an AK-47 and hiking up to a native Mangyan village with our friend Peter. The expats were super friendly and welcoming, centered around the local yacht club where we had dinner on Friday nights and took a few sailing lessons. The older brits and their young Filipino wives seemed a little colonial at times, but some like Peter were active in the community and helping to promote touristic alternatives to seedy Sabang and boring White Beach.

    After the Philippines the two of us spent two weeks in Hong Kong. Unfortunately Colin came down with a mysterious illness and was out of commission for much of it. We stayed in Mong Kok on the Chinese side which has the highest population density in the world, as well as many wonderful markets and whole streets dedicated to aquariums, flowers, and songbirds. Our room was a cozy little breadbasket, bright and quiet and just big enough for a bed and the two of us to stand. We met some eccentric housemates and wrote an iPad game for Colin’s mum, which teaches Japanese Katakana using a crossword and photos from our time in Tokyo. We showed it around at an indie game meetup in Hong Kong and people were impressed, so we may release it on the app store eventually.

    Christmas with family on Vancouver Island was great as always. It hasn’t snowed yet but there’s still time before we head down to San Francisco. We’ll be there until March or April but haven’t decided where to go after that. Europe? Eastern Canada? We’ll see…

  • Rebuild: iPad 1 + 2 sales figures

    Rebuild for iPad reached the US top ten in Simulation & Strategy.
    After all sorts of whining about Flash’s poor performance on the iPad 1, I manned up and made it happen.

    The iPad 1 version of Rebuild has less snantzy animations, the map doesn’t scroll quite as smoothly, and admittedly it does run out of ram sometimes and crash. But these issues don’t seem to have lowered the game’s ranking or sales. I’ve gotten more complaints about Air incorrectly listing 15 languages than about performance.

    I’ve been tracking the figures on AppFigures.com and was excited to see Rebuild’s #1 app ranking in Anguilla. Well… just kidding, but it was in the top 100 games in the US and UK for awhile. Considering it was never featured by Apple, Rebuild did pretty well, and made $15k in the first month.

    Rebuild for iPad now has Game Center Achievements & Highscores
    Rebuild for iPad now has Game Center Achievements & Highscores.
    It’s evident that Rebuild’s success on the iPad came from it’s previous success as a Flash game. The sales peaks came on days when Rebuild was reviewed on sites like TouchArcade, as well as AppTudes, AppSmile, iPaddisti, 148Apps.

    Releasing iPad 2 then iPad 1 separately may have been better too, because the update triggered a second round of press.


    Rebuild sales peaked during reviews and updates
    Rebuild sales peaked during reviews and updates.
    Likely it will earn another $15k from now on, possibly more if I put out an iPhone version or a content update and do some creative sales to get more press. But of course I’d rather be working on new things.

    Like the Katakana crossword game Colin and I wrote for his mum for Xmas. Or the movie keywords parlor game I’ve been meaning to write for years. Or Word Up Dog (perhaps soon to be rewritten in Stage 3D).

    Or, you know, Rebuild 3.

  • Word Up Dog: Game Center with AS3

    Word Up Dog Leaderboard
    This bizness be fresh. Take you from some disconnected punk to BAM! – competin' with all yo homeboys, earnin' achievements and shit.
    In my last post I lamented not having access native iOS features such Game Center and single sign-on Twitter. Well, Milkman Games has come to the rescue with their Game Center Native Extension for Adobe AIR. Took me less than an hour to pop it in to my FlashDevelop project, connect all the events and go. All in AS3, no Mac or Xcode required. Post scores, view achievements, all that good stuff with minimal effort. They also have an Android AdMob extension and more on the way – valuable tools for running AIR on mobile devices.

    I’ve got Word Up Dog now running with Game Center on iPads and iPhone 4+, but I need to test it on the iPhone 3GS and iPod Touch 3+. So this is a call for testers – please sign up to join my Test Flight team if you’ve got any iOS device, and I may recruit you to help me test Word Up Dog, Rebuild, or some future game.

    Word Up Dog Sand Level
    Sandworms, vines, thievin rabbits. Dawg this hood gonna get isself a makeover.
    For anyone who played the old flash version of Word Up Dog, there’s going to be some changes. I’m spicing up the levels with some new terrain and new powerups. I know, it’s no Rebuild, but after writing about zombies for four months I need some cute animals talking in urban slang stereotypes.

    Word Up Dog was always meant to be an iOS game, so here we go!