Thursday, October 15, 2009
I've done this effect to death, used it again in the upcoming DAC ( Whose launch has been delayed due to having to add achievements, luckily someone else is doing that ) so I figured it's time to put it out to pasture and share it around.

'cause we've not been posting as often here, I thought I'd treat everyone to some nice grabs to break up the code slightly.

Basically we want to create a simple gradient rectangle movieclip, like so

swatch_grab.png

And we end up with something looking like this,

gradient_grab.png

A simple rectangle that's slightly bigger than your stage, that fades out to one side. It needs to be bigger than your stage 'cause we want all the gradient part with the alpha blending to be off-screen when we first apply it as a mask.

Next up, the boring old code bit.

package Classes {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.Stage;
    
    import gs.TweenLite;
    
    public class Transition {

//---------------------------------------------------------------------------------------
// Assets
//---------------------------------------------------------------------------------------
        [Embed("../_assets/assets.swf",symbol="transitionMaskMC")]
        private var transitionMaskMC:Class;

//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private var playField:Sprite;

        private var grabBitmapData:BitmapData;
        private var grabBitmap:Bitmap;

        private var transitionMask:Sprite;
            
//------------------------------------------------
// System
//------------------------------------------------
        private var main:Main;
        private var mainMovie:DisplayObject;
        private var stage:Stage;

        private var callBack:Function;
        
//---------------------------------------------------------------------------------------
//Constructor
//---------------------------------------------------------------------------------------
        public function Transition(){
            main=Main.getInstance();
            mainMovie=main.getMainMovie();
            stage=main.getStage();

            grabBitmapData=new BitmapData(640,480,false,0);
            grabBitmap=new Bitmap(grabBitmapData);
            grabBitmap.cacheAsBitmap=true;
            
            transitionMask=new transitionMaskMC();
            transitionMask.cacheAsBitmap=true;
        }
        
//---------------------------------------------------------------------------------------
// Public
//---------------------------------------------------------------------------------------
        public function toString():String {
            return "Transition";
        }        

//---------------------------------------------------------------------------------------
        public function grabScreen(callBackArg:Function):void{
            callBack=callBackArg;

            if(playField==null){
                playField=main.getInitObj().getPlayField().transition;
            }

            grabBitmapData.draw(stage);
            transitionMask.x=-160;
            grabBitmap.mask=transitionMask;
            playField.addChild(grabBitmap);
            playField.addChild(transitionMask);

            callBackArg();

            TweenLite.to(transitionMask, 1.5, {x:640, delay:0.2,onComplete:houseKeeping});

        }

//---------------------------------------------------------------------------------------
        public function houseKeeping():void{
            playField.removeChild(transitionMask);
            playField.removeChild(grabBitmap);
        }

//---------------------------------------------------------------------------------------
    }
}

There's really no way to make code look interesting in a blog is there ?

            grabBitmapData=new BitmapData(640,480,false,0);
            grabBitmap=new Bitmap(grabBitmapData);
            grabBitmap.cacheAsBitmap=true;
            
            transitionMask=new transitionMaskMC();
            transitionMask.cacheAsBitmap=true;

Here in our constructor we're just creating a bitmap which we're going to use when we take a snap shot of the whole screen, and create our transisitonMask ( ie, the gradient mc we've just made ) instance.
The key thing is to turn cacheAsBitmap=true on both, otherwise the gradient mask won't work, it'll just be a boring old normal gradient free mask.

            grabBitmapData.draw(stage);
            transitionMask.x=-160;
            grabBitmap.mask=transitionMask;
            playField.addChild(grabBitmap);
            playField.addChild(transitionMask);

            callBackArg();

            TweenLite.to(transitionMask, 1.5, {x:640, delay:0.2,onComplete:houseKeeping});

This is the guts of what we're doing. Firstly use the always sexy draw() to grab the whole screen, then position the mask so our alpha blended bit is off screen. We want the whole snap shot bitmap to be masked normally at first.
We then simply add both the bitmap and mask to the screen. You'll notice the playField reference there. What I do, as I'm a layer loving kinda guy, is create a simple class that creates all the holders for all the things in a game at the depths I want. It's like codey version of using layers that way. So for your transition "layer", that should be on top of everything else ( You could also add it directly to the stage, same thing, I'm just paranoid that I'll need a layer above the transition for some reason ).
We've got the bitmap, the mask, the bitmap is now masked so all we need to do is cheat, and use the very lovely TweenLite. That just slides our mask all the way across the screen, in effect removing our mask, but with the nice alpha blending on the edge it makes it appear soft. Kinda like in Star Wars.

Notice the callback and the slight delay in the tween in there ? What we do is call the transition method, and then jump back to our main code where we're setting up the screen "beneath" the transition, so it wipes away to reveal our next screen.

[Update: Destroy all Cars is now ( Finally ) live, so you can see it action and see if you want to go to the effort of using it yourself ]

Squize.

Thursday, October 15, 2009 11:57:14 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, October 07, 2009
Played with Pixel Bender yet ? For Ionic ( My TD game which is taking an age to finish ) I wanted to use a similar effect to the transition in cronusX, the rgb split / tv interference thing. In the transition it didn't matter how long it took, but to use it in-game with God knows how many sprites along with collisions running it's got to be a lot lot quicker. Yeah you know where this is going.

ionic_rgbGrab.jpg

After firing up the Pixel Bender toolkit and swearing and looking through docs and examples for an hour or so, I kinda got it, so I thought I'd share what little I know. Just to warn you, this is going to be code heavy and no example to even look at, dry reading ahead. Maybe open up some porn in another tab and just flick between the two when your eyes start glazing over.

<languageVersion : 1.0;>

kernel RGBDistortion
< namespace : "RGB Distort";
vendor : "www.gamingyourway.com";
version : 1;
description : "Pixel Bender version of RGB distort";
>
{
  input image3 src;
  output pixel3 dst;

  parameter float rOffset
<
   minValue:float(-50.0);
   maxValue:float(50.0);
   defaultValue:float(0.0);
>;

  parameter float gOffset
<
   minValue:float(-50.0);
   maxValue:float(50.0);
   defaultValue:float(0.0);
>;

  parameter float bOffset
<
   minValue:float(-50.0);
   maxValue:float(50.0);
   defaultValue:float(0.0);
>;
  void

  evaluatePixel()
  {
    float2 outCoords=outCoord();

    float2 redPos=outCoords;
    redPos[0]+=rOffset;
    float3 inputColorR = sample(src,redPos);
    dst.r = inputColorR.r;

    float2 greenPos=outCoords;
    greenPos[0]+=gOffset;
    float3 inputColorG = sample(src,greenPos);
    dst.g = inputColorG.g;

    float2 bluePos=outCoords;
    bluePos[0]+=bOffset;
    float3 inputColorB = sample(src,bluePos);
    dst.b = inputColorB.b;
  }
}

I'll try and break it down quickly in my usual lazy not really explaining things style. At the start is simple metadata, nothing you can't figure out there.

   input image3 src;
   output pixel3 dst;


A bit more interesting. input is the image you're going to send to the kernal, image3 being the datatype ( Because we don't want to worry about the alpha channel the datatype is image3 ( RGB ), if you want alpha it would be image4 ( ARGB )), the output is the bitmap we're going to plot the result to, which is a pixel3 datatype ( Which is the same as image3 ).

  parameter float rOffset
<
   minValue:float(-50.0);
   maxValue:float(50.0);
   defaultValue:float(0.0);
>;

This how you set up an argument to pass to the kernal. It's a float and refers to the red channel offset when we jiggle things about. The min/max and default values are more for the toolkit itself. When you run it it'll give you a slider to play with, and those are the values for the slider ( It'll make sense when you copy the code into the toolkit. Also you can drop a description in there as more metadata, but this is for Flash so we don't really need it ).

   evaluatePixel()

This is our main loop. Everything in this method is run on each and every pixel in the image.

    float2 outCoords=outCoord();

The outCoord() method returns this pixels x/y as two floating point numbers, in the form of an array ( Kinda ). We just store that in a var out of habit and speed.

    float2 redPos=outCoords;
    redPos[0]+=rOffset;
    float3 inputColorR = sample(src,redPos);
    dst.r = inputColorR.r;

redPos is our x,y position. We then add the new x position to redPos.x ( redPos[0] ), with the new x position being our parameter from above.
inputColorR is quite a chunky little line. sample grabs the pixel data at ( inputSource, position ), in effect we're setting the float3 ( RGB ) variable inputColorR = sourceImage[x+our offset][y]
After doing that, we make this pixel in the r(ed channel ) in our destination this colour. Basically we're doing this:

var rgb=sourceBitmap.getPixel(x+offset,y);
destBitmap.setPixel(x,y,rgb);

( But just on the red channel ).

The rest of the kernal is just more of the same, just for the other two channels.

After that pick the Export Filter for Flash Player option and we're ready to get back to normal coding.

package Classes {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.MovieClip;
    import flash.display.Shader;
    import flash.display.ShaderJob;
    import flash.display.ShaderParameter;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.events.ShaderEvent;
    import flash.filters.ShaderFilter;
    
    public class Transition {
        
//---------------------------------------------------------------------------------------
// Assets
//---------------------------------------------------------------------------------------
        [Embed(source="_shaders/distortion.pbj", mimeType="application/octet-stream")]
        private var shader_distortPBJ:Class;

        [Embed("/_assets/assets.swf",symbol="staticMC")]
        private var staticMC:Class;

//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private var playField:Sprite;

        private var shaderBitmapData:BitmapData;
        private var grabBitmapData:BitmapData;
        private var grabBitmap:Bitmap;

        private var shader_distort:Shader;
        private var shaderFilter_distort:ShaderFilter;
        
        private var distortCnt:int;
        private var rSin:Number;

        private var staticEffect:Sprite;
        private var staticAnim:MovieClip;
                
//------------------------------------------------
// System
//------------------------------------------------
        private var main:Main;
        private var mainMovie:DisplayObject;
        private var stage:Stage;

//---------------------------------------------------------------------------------------
//Constructor
//---------------------------------------------------------------------------------------
        public function Transition(){
            main=Main.getInstance();
            mainMovie=main.getMainMovie();
            stage=main.getStage();

//Let's make our bitmaps where we're going to plot our data too
            shaderBitmapData=new BitmapData(700,380,false,0);
            
            grabBitmapData=new BitmapData(700,380,true,0);
            grabBitmap=new Bitmap(grabBitmapData);
            grabBitmap.alpha=0.4;
//Create our shader, sexy
            shader_distort=new Shader(new shader_distortPBJ());
            shader_distort.data.src.input=shaderBitmapData;

            staticEffect=new staticMC();
            staticAnim=staticEffect["anim"];
            staticAnim.gotoAndStop(1);
        }

//---------------------------------------------------------------------------------------
// Public
//---------------------------------------------------------------------------------------
        public function toString():String {
            return "Transition";
        }        

//---------------------------------------------------------------------------------------
        public function init():void{
            playField=main.getInitObj().getPlayfield().transitionPlayField;
            rSin=0;
        }
        
//---------------------------------------------------------------------------------------
        public function distortInit():void{
            if(grabBitmap.parent!=null){
                return;    
            }

            distortCnt=0;
            shaderBitmapData.draw(stage);
            playField.addChild(grabBitmap);

            staticEffect.height=int(Math.random()*100)+10;
            staticEffect.y=int(Math.random()*300)+50;
            staticAnim.gotoAndPlay(1);
            playField.addChild(staticEffect);
            
            startJob();
        }

//---------------------------------------------------------------------------------------
// Private
//---------------------------------------------------------------------------------------
        private function startJob():void{
            rSin++;
            rSin++;
            ShaderParameter(shader_distort.data.rOffset).value=[Math.sin(rSin)*12];
            ShaderParameter(shader_distort.data.gOffset).value=[Math.cos(rSin)*12];
            ShaderParameter(shader_distort.data.bOffset).value=[Math.sin(-rSin)*12];
            
            var job:ShaderJob = new ShaderJob(shader_distort,grabBitmapData);
            job.addEventListener(ShaderEvent.COMPLETE,shaderCompleted);
            job.start();
        }
        
//---------------------------------------------------------------------------------------
        private function shaderCompleted(e:ShaderEvent):void{
            if(++distortCnt==6){
                staticAnim.gotoAndStop(1);
                playField.removeChild(staticEffect);
                playField.removeChild(grabBitmap);
                return;
            }

            staticEffect.height=int(Math.random()*100)+10;
            staticEffect.y=int(Math.random()*300)+50;

            startJob();
        }

//---------------------------------------------------------------------------------------
    }
}

Sigh, that's a ton of boring code to look at, let's just pick out the fun stuff ( Equating as3 to fun, fuck me that's tragic ).

        [Embed(source="_shaders/distortion.pbj", mimeType="application/octet-stream")]
        private var shader_distortPBJ:Class;

That's how to embed the kernal.

//Let's make our bitmaps where we're going to plot our data too
            shaderBitmapData=new BitmapData(700,380,false,0);
            
            grabBitmapData=new BitmapData(700,380,true,0);
            grabBitmap=new Bitmap(grabBitmapData);
            grabBitmap.alpha=0.4;

What we're going to do is grab the screen when we want to run the effect, but we just want it faint ( alpha=0.4 ). shaderBitmapData is our source, with grabBitmapData being our dest. You can use the same bitmap for both, but Flash has to create a temp working copy, so it's slower.

//Create our shader, sexy
            shader_distort=new Shader(new shader_distortPBJ());
            shader_distort.data.src.input=shaderBitmapData;

Finally we're creating our actual shader, with the second line defining our source bitmap, which can do here as it won't change.

The distortInit() just grabs the screen, resets any vars we need and sends up the static effect ( Which has nothing to do with the pixel bender stuff, so we're going to ignore that ). Once that's all done we call the startJob() method which does the magic.

        private function startJob():void{
            rSin++;
            rSin++;
            ShaderParameter(shader_distort.data.rOffset).value=[Math.sin(rSin)*12];
            ShaderParameter(shader_distort.data.gOffset).value=[Math.cos(rSin)*12];
            ShaderParameter(shader_distort.data.bOffset).value=[Math.sin(-rSin)*12];
            
            var job:ShaderJob = new ShaderJob(shader_distort,grabBitmapData);
            job.addEventListener(ShaderEvent.COMPLETE,shaderCompleted);
            job.start();
        }

K, so we're using sin and cos to create our r,g and b position offsets, nothing new there. The ShaderParameter is how we change our parameter values in the kernal. You can hit the values directly, and they will be modified, but it doesn't actually do anything. I lost over an hour to that before finding out about ShaderParameter. Hopefully those lines should make sense.

Next up, we create a ShaderJob. We're doing this as opposed to the adding it as a filter approach, as this is the async magic that we've gone to all this effort for ( Runs on it's own thread etc. etc. Let's face it, that's the only thing we all know about PB ). The ShaderJob just wants to know which kernal we're using, and the destination bitmap.
Finally we just add a listener to that, and call the start() method, and it'll go and do it's thing and won't affect our other code. There's no waiting around here.

        private function shaderCompleted(e:ShaderEvent):void{
            if(++distortCnt==6){
                staticAnim.gotoAndStop(1);
                playField.removeChild(staticEffect);
                playField.removeChild(grabBitmap);
                return;
            }

            staticEffect.height=int(Math.random()*100)+10;
            staticEffect.y=int(Math.random()*300)+50;

            startJob();
        }

We're just been recursive bad boys here. Have we run the effect 6 times ? Yes so we're done, clear everything up, nope, so call the startJob() method again.

Hardly an indepth technical breakdown, but hopefully it's a starting point. This was a fair few hours of swearing for me, but I'm old so new things take longer to make sense, so it shouldn't take you more than a couple of hours to get PB doing cool things.

Squize.

Wednesday, October 07, 2009 9:29:09 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Wednesday, July 22, 2009
Nice descriptive title for a change, mainly 'cause I've spent ages hunting around for a solution myself, so if you're coming here for just this very reason, I understand your pain.

We had issues with mochibot on Invaders Must Die, but by then I'd passed it over to Mousebreaker so they had to deal with it in-house. It's the first time I've hit it face on so to speak.

To set the scene and get you in the mood, I've just finished the viral version of cronusX and wanted to try the version control that mochi offer, as that was one of the best things about gameJacket, plus I've added a twitter option to the game which I know is going to bite me on the arse with people bitching it's spyware etc. etc. so I wanted the option to rip that out if it was becoming too much of a ball ache.
I've also included mochi-bot tracking so Candystand can see how it's doing out in the wild, so I've dropped that in too.

Everything worked first time ( That's where it differs from gameJacket and it's constant security check failures ), gave it a quick test, all good. Ah, not all good, the transition craps out to a black screen.

Testing it locally ( Turns out I've not installed the browsers debug version of FP10 on the pc, how good am I ? ) it spat out an error,

Error # 2121: Sandbox Security Violation: BitmapData.draw

etc.

Joy.

Lots of googling ( To no real avail, hence this post ), seeing the only advice on the mochi forums that I could find was someone copying out some text from the Flash help ( Cheers for that, solves everything ) it turns out that the mochi-bot can't be on your root display object, as you get all the security violations when trying to use draw(); that you would if you tried loading in say an image and using draw(); on that ( It's a cross domain thing. To be honest life is too short to go into it, I could just copy from the as3 docs, but... ).

Basically, long story cut shorter, if you do something like:

MochiBot.track(this,"yourMagicNumber");

In your preloader ( Assuming that "this" is your main preloader class than extends MovieClip ) then you can't use draw(); in your main code.

To get around this, give it a movieclip instead, eg.

mochiBotHolder=new MovieClip();
stage.addChild(mochiBotHolder);
mochiBotHolder.addEventListener(Event.ADDED_TO_STAGE,triggerMochiBotTracking);

private function triggerMochiBotTracking(e:Event):void{
    mochiBotHolder.removeEventListener(Event.ADDED_TO_STAGE,triggerMochiBotTracking);
    Security.allowDomain("http://core.mochibot.com/my/core.swf");
    MochiBot.track(mochiBotHolder,"yourMagicNumber");
}

Now I'm not sure if you need the allowDomain(), but it works with it, and that's good enough for me after losing a good hour and a half to this little gem of a problem.
Because the mochibot code needs to hit loaderInfo.loaderURL via the clip you pass it, you have to add your holder mc to the stage, and then wait until it's actually there before calling MochiBot.track, otherwise you're in the land of null properties.

Now I'm not sure if you can kill that holder mc of after calling the track() method, it's like the allowDomain(), it works as it is, and I'm happy with that.

This has proved to be a fairly techy / geeky post, quite rare from me.

Squize.

Tuesday, July 21, 2009 11:00:58 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [6]  |  Trackback
 Wednesday, July 01, 2009
I've found myself defending oop recently, and at the same time bemoaning the lack of good oop tutorials with regards game development.

Rather than promising to write a full blown tutorial, as to be honest there's no way I'll stick to it, after around 3 parts at most I'll be bored stupid, I thought I'd try and explain the structure behind an existing game which we've already posted the source to. So it may be an idea to open this link in it's own tab.

Ready ? Ok, let's go.

opCFlow.png


Look at that, made with a free package so you get the watermark, nothing's too cheap for you dear reader.

This at heart is how I've structured all my games since starting with as2. It only varies in that there are sometimes more classes in there, the actual hierarchy never changes.

Ok lots of code here is never that great to read, but there's no way around it, sorry,

package {
    import Classes.Init;
    
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;

    [SWF(width="600", height="400", frameRate="35", backgroundColor="#000000")]

    public class Main extends Sprite{

//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private static var instance:Main;
        private static var __parent:DisplayObject;
        private static var stage:Stage;
        private static var init:Init;
        
//---------------------------------------------------------------------------------------
// Static ( Singleton )
//---------------------------------------------------------------------------------------
        public function Main(){
            if(instance){
                throw new Error( "Singleton and can only be accessed through Singleton.getInstance()" );
            } else {
                instance=this;
            }        

            instance=this;
//When we are running from our preloader, comment this out
            waiting();
        }

//---------------------------------------------------------------------------------------
// Public
//---------------------------------------------------------------------------------------
        public override function toString():String {
            return "Main";
        }        

//---------------------------------------------------------------------------------------
        public function waiting():void{
            addEventListener(Event.ADDED_TO_STAGE,mainAddedToStage);
        }

//---------------------------------------------------------------------------------------
// Getters
//---------------------------------------------------------------------------------------
        public static function getInstance():Main {
            return instance;
        }

//----------------------------------------------------------------------
        public function getMainMovie():DisplayObject{
            return __parent;    
        }

//----------------------------------------------------------------------
        public function getStage():Stage{
            return stage;    
        }

//----------------------------------------------------------------------
        public function getInit():Init{
            return init;    
        }

//---------------------------------------------------------------------------------------
// Private
//---------------------------------------------------------------------------------------
        private function mainAddedToStage(e:Event):void{
            stage=this.stage;
            stage.showDefaultContextMenu=false;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality=StageQuality.LOW;
            stage.stageFocusRect=false;

            __parent=this.root;
            
            init=new Init();
        }


//---------------------------------------------------------------------------------------
    }
}

Hopefully this should be fairly straight forward ( I did actually grab it from somewhere else when looking for an as3 version which matched what I was doing in as2, so sorry original author, I can't tell anymore what's yours and what's mine ). We're basically waiting around until this instance is added to the stage ( If you try and read some properties before it's technically been created then you're going to get errors. ) and then running the mainAddedToStage method. Importantly we have some getter methods set up here, as we need them ( More later ). This is our document class, and as such it has a "direct" link with the swf ( For want of a better term ). From now on throughout every other class, any reference to stage or Main is obtained from this class.
The very last line you'll see we create a new instance of the Init class ( init=new Init(); ), so let's check that class out.

package Classes {
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.Stage;

    public class Init {
//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private var gameController:GameController;
        private var attract:Attract;
        private var soundHandler:SoundHandler;
        
//------------------------------------------------
// System
//------------------------------------------------
        private var main:Main;
        private var mainMovie:DisplayObject;
        private var stage:Stage;
        
//---------------------------------------------------------------------------------------
//Constructor
//---------------------------------------------------------------------------------------
        public function Init(){
            main=Main.getInstance();
            mainMovie=main.getMainMovie();
            stage=main.getStage();

            soundHandler=new SoundHandler();
           
            gameController=new GameController();
            attract=new Attract();
        }

//---------------------------------------------------------------------------------------
// Public
//---------------------------------------------------------------------------------------
        public function toString():String {
            return "Init";
        }        

//---------------------------------------------------------------------------------------
// Getters
//---------------------------------------------------------------------------------------
        public function getAttract():Attract{
            return attract;
        }

//---------------------------------------------------------------------------------------
        public function getGameController():GameController{
            return gameController;
        }

//---------------------------------------------------------------------------------------
        public function getSoundHandler():SoundHandler{
            return soundHandler;
        }

//---------------------------------------------------------------------------------------
    }
}

This again is a bit of a nothingy class. In theory it could be shoved into the Main class with no real harm, the reason I don't is pure lazyness. I like being able to copy the Main class to every new project without having to think about it, i.e aside from the [swf] tag I never have to alter it. It just feels cleaner having that first class do very little.

If you look at our Init class you'll see we just create instances of each class we need ( Refer to our cheapo diagram to help clarify ), and set up some getter methods again ( Just to clarify, a method is exactly the same as a Function, it's just that if you use a function in oop it's called a method instead. I don't know why either ), so other classes can get a reference to these instance's if they need to.

How do I decide which classes sit on which row of the hierarchy ? Main is our document class, so he's at the top and doesn't really do much. Init is Main's love child, and doesn't do much either, he's just creating the actual game classes.
The next row is more interesting. Attract is our front-end. It deals with the title screen, the game over screen, hi-score entry if the game supports it, instructions etc. Basically everything that happens before starting the game and after the game has finished.
Let's jump over to SoundHandler. This is just what it says. It's here because it's used by both Attract and GameController, as both need to have sounds. GameController is a simple class like Init, it handles the creation of all the child classes needed for the game ( Check the diagram ).

Let me try and rationalise why Attract, GameController, SoundHandler are all on the same row, in effect why they're equal to each other. We've already established that Attract and GameController need to be aware of the SoundHandler class as both need sounds. In the grand scheme of things, the Attract class doesn't really need to know about GameController ( Remember Attract is everything but the actual game ) and conversely the GameController really doesn't give a crap about Attract. If one of these classes is working, then the other isn't doing anything, so it makes sense to me that they're on the same row.
Does that mean they never need to chat to each other ? No, but it's at very key points. For example, when the player presses the "Play Game" button in Attract, we kill off all the Attract mode things and then call startGame() method in GameController.

Now we come to something cool. Quite a few times I've seen people moving over to oop, and it's all going well, until they need a reference to a different class. How the hell do we get the reference we need ? No one wants to pass a reference to a class via a constructor, as that's just messy and nasty and really easy to screw up, and it's not like we can be old school and use _root.myMethod(); when we're oop gods.

Notice all my constructors are the same, eg,

//------------------------------------------------
// System
//------------------------------------------------
        private var main:Main;
        private var mainMovie:DisplayObject;
        private var stage:Stage;
        
//---------------------------------------------------------------------------------------
//Constructor
//---------------------------------------------------------------------------------------
        public function GameController(){
            main=Main.getInstance();
            mainMovie=main.getMainMovie();
            stage=main.getStage();
        }

We get a reference to our document class, Main and store it in our local var main. We also store away a reference to our mainMovie ( To be honest I don't think I've used that ref. in as3 yet, it's just a throw back to my as2 code, but I'm a creature of habit so it'll stay there 'til as4 ) and the Stage.

So this is the GameController class, and it's game over, so we want to call the Attract class as he deals with that. This is how we get our reference:

main.getInit().getAttract().gameOver();

Check back with our Main class code up there, see getInit() in the getters section ? It returns a reference to our Init instance. Then look at the Init getters, getAttract() gives us our instance of Attract, and from there we're just calling the method gameOver in the Attract class.
Don't worry if this doesn't make sense straight away, it's quite a bit to get your head around in one go. Basically so long as we have a reference to Main in any class, we can get a reference to any other class no matter how far away from the callee class we are. References aren't a pain in the arse anymore, they're as simple as this.

You may be thinking, how the hell am I going to remember all those getOurInstanceName() method calls. Auto-completion. Flex does all this for you so it's never an issue ( And I'm sure Flash Develop does the same ). I don't know about the Flash IDE, I really don't hold much faith in it doing it, so now may be the time to install Flash Develop and have a play with that.

See we've got the basics of oop hierarchy covered, and I've not had to slip into terms like singleton and composition. Feel free to google both terms, see what they actually mean, and hopefully when you read the flowery descriptions you'll realise that you already get them as we've covered them here.

As always feel free to fire over questions or point out glaring errors in what I've done. Like I said all my games pretty much follow this pattern, which makes sharing code between projects a lot easier plus I'm not having to think about how classes are inter-connected. I'm not suggesting you just blindly copy what I've done, but perhaps plan out your next game using some simple flowchart boxes so you can see where classes should be connected and where it'll be a waste of time to do so.

Squize.

Wednesday, July 01, 2009 1:27:56 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [12]  |  Trackback
 Tuesday, May 05, 2009
Just a quick one in case you ever get a,

error 1152: a conflict exists with inherited definition

I'd used the instance name "name" on a dynamic text field on the stage, and the Flex compiler just didn't like any of it, to the point of giving me 14 errors for my trouble.

Simple lamer mistake I know, but if you're here after pulling your hair out with that error it may save you some pain.

Hmmm bit of a geeky post, sorry, we'll get back to our usual brand of swearing and talking crap next post.

Squize.


Tuesday, May 05, 2009 6:42:12 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, April 30, 2009
As I already mentioned, the Unity docs are not quite what I would call helpfull. I think they cover a lot and most of it will solve your problem, finding the right info in them is what really is the hard part.

Take the GUI scripting guide for instance "Reference Manual > GUI Scripting Guide", this covers everything you need to know to build a GUI. My mission currently is to create a simple form for the game I talked about earlier.
For the salutation I needed a drop down list, so I had to do it on my own, because that's the one usefull control I missed.


unity_igts_00.png
After a few hours I came up with this (scaled down a bit)

The form is dynamic (you can turn of the salutation for instance) and already has a working validation, but it's dead ugly. So the next task was to skin that up ("Reference Manual > GUI Scripting Guide > Customization").

Yet again the manual does a good job to tell you what you can do, but fucking lacks some basic examples on how to deal with the textures to skin up buttons for instance. That's where I got a bit pissy (although I must admit that I hate searching in boards or wikis when the solution should be in the manuals).

So the key to skinning the buttons (and the rest of the UI elements is the GUISkin file or for single use the GUIStyle. I knew that there has been a psd file with "templates" of the default textures used, but alas I still havent been able to find it again, though I know I saw it while playing with Unity for the first day (and I was like wtf?).

unity_igts_01.png
After skinning for a few minutes

I found the most valuable (and yet again MISSED info) in the scripting guide (after just testing it with a basic psd file) ...
So I looked at the default values of a new Skin and saw this:

unity_igts_02.png And I wondered why (and how) it'll become this: unity_igts_03.png.

What the manual is missing badly is the info that you can set a "fixed" border for a texture in a skin that isn't stretched:
var border : RectOffset
Description

The borders of all background images.

This corresponds to the border settings for GUITextures. It only affects the rendering of the background image and has no effect on positioning.

Why do I need to find that out by testing? (I guess no one reads through the scripting guide until he needs a specific info, I for sure do not)

By default the border values are set to:
left: 6, right: 6, top: 6, bottom: 4 ...

After knowing this it was oh so easy to just do this: unity_igts_04.png to get to the buttons used above.

Oh well.

I hope that saves some ugly searching for you,
nGFX

 | 
Thursday, April 30, 2009 5:36:07 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [3]  |  Trackback
 Tuesday, April 21, 2009
Hi folks,

most regular readers will have noticed that we've jumped onto the Unity wagon after it finally came out for the windows world and so I think it's time to write down a few of my thoughts ...

What it is:
an easy to use development platform for 3d games (although easy, well, I'll cover that later)

What it is not:
Simply put: easy.
And it is not flash.

So?
The best part of it is, that you can do a decent 3d based game with it quite quickly, that is if you know how to code unity (I might have twittered once or twice that the docs are not one of the strong points) and (what's more important if you or someone in your team) can do low poly 3d.

So?
I really can't stress enough that it is NOT flash, not at all, when you get started with Unity all is nice and straight forward, but once you hit the point where you really would like to do a quick tween for the main menu, or use a fancy drop shadow on your font ... you'll probably start cursing and wish you could use a timeline and some keyframes.

One of the really big letdowns for me was to discover that a quick, easy and nice UI is not going to happen fast in Unity. You can get away with it if you don't need dynamic text to appear, but I need to do a lot of stuff with that, because nearly all of our games are prepared to be played in at least two languages.

How does all that relate to the title?
When I first got in touch with flash (6 I think) AS was really nothing more than a scripting language, coding for the best part was ... shit and most of us messed with onEnterFrames per movielclip. Then AS2 hit the light of the day and with AS3 it came very close to real coding ...
But when I entered the Unity world it seems like the old distributed scripts came back to haunt me. You've got the choice of using a set of different languages: javascript like, c#, boo and some others.

JS on the one hand is easy to use, ridiculously lose typed and commonly used. I really don't like lose typed coding, so for me it was c# ...
Anyway something that commes very close the the old MC based onEnterFrame is Update ... so a script that would move the object 1 "unit" (since we have no pixel) to the left would be:

function Update () {
    transform.position.x++;
}

(or something very close to that, I said I use c#, oh and I'm sure I saw some other methods to do the same)

Save that as a ".js" text file, add that to a cube on stage and viola (there you have the back to script part covered).

I hope you won't be doing that for a complex game, but ... thinking back ... I knew people who did that with flash  ** shudder **.

As I already mentioned, I hate lose typed coding and as I used c# for some years now for coding anyway it was a logical choice (that and the fact that I could continue using Visual Studio).

Oh and did I stress that there is NO timeline?

Everything you want to have animated either needs to be coded (ie for dynamic text) or already be animated in a 3d app ...

Oops, I think I need to get back to work ...

nGFX

ps: just to have something to look at a screenie of the menu (the start of a camera move) of my "test" game to see how I get along with Unity, if everything works well, I might be able to invite for a private beta test on Friday (give me a shout if you want to) ...

pots_menu_de_00.jpg
(the text for the menu was a big lesson in cheating, it uses GUI.Button, btw)

Tuesday, April 21, 2009 7:38:04 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [6]  |  Trackback
 Monday, March 23, 2009
Hi all.

Back on coding CE again (at least for a few hours today) after spending a good deal of time coding and designing the backend for MYW, writing a tiny versatile CMS and doing some 3d for X.

So today I'm  going to ask myself why the hell I have done a few things in CE the way I did them (I bet you are a lot wiser now).

Let's raise the question if it is worth to add the extra amount of work needed to draw a hard line between the game's "engine" and the game's UI - for your average flash game.

You may have noticed that neither Squize nor me tend to make out lives overly easy when it comes to games, for some odd reason we both tend to try to give out very best for each and every game (even if it is a pain in the back) - well call that stupid.

Give me a good reason to split game and game (play) UI ...
The best reason I can come up with is: reusability, and it is also the least used one.

In most cases I can come up with there seems to be no reason to really split things, because the game is a one-of-a-kind thing. Even for games that share a good deal of similarites (like Wintertales and LogiMotion), a whole lot of things need to be rewritten in order to reuse the engine.

That leaves the reusability inside a single game. !?

WTH?

Inside a single game? Yep!

A good deal of our games either uses an ingame editor (although not usable by the player)  or uses an external editor to generate the level data. Mostly, but not always they share the same visuals. For instance the editor for Logimotion uses smaller tiles than the game itself (so have room for the tools and don't have to scroll the map). That is a good reason to split things between the UI and the "engine".
Another good reason is when you have a stupid designer and you just code - you know those guys tend to be smart and change the size of the assets as often as you should change your underwear.

So why question that and not do it all the time?

Well, it takes a good deal more planing to really split things up. in an ideal world, the "game" knows nothing about the UI, but it still has to control it (ie. update the score, display infos). In my case this is done using callbacks.
A good example might be a game we did (but still isn't playable online): CC

cc_game_00.jpg
(CC game, using 40x40 tiles)

cc_editor_00.jpg
(CC editor, using 32x32 tiles)

As you're meant to be able to play the game inside the editor (without leaving it), the engine had to cope with different tile sizes and environments.

So whenever the game needs to comunicate with its surroundings I provide a callback method, if I would have made it "the right" way, I should have used an interface for that, but ... hell you can overdo it too.

To make it easier and not having an endless number of callback methds I used only a few and gave them params (which are stored in the game's class as constants: like:

public static const UPDATEUI_INFO:uint = 0;
public static const UPDATEUI_BTNPLAY:uint = 1;
public static const UPDATEUI_ITEM:uint = 2;
public static const UPDATEUI_WIN:uint = 3;

Whenever you finish a level, the game would just call the callback provided for UI updates and pass the parameter needed.

And is it really worth the extra work?
Not always.

I like to spend that extra piece of work for games that require and editor or might have parts in it that seem to be a good start for reusing it in a second game. Sometimes you notice halfway through the project that you need to change something to make the game work again (ie. different tile size, or different UI), sometimes (like I did for CE) you notice that the game will be a one of and you cause yourself a good deal of fuzz for "nice code" only.

Well, lets get back coding CE.

nGFX


Monday, March 23, 2009 11:18:59 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, February 18, 2009
The 4K comp is gathering pace which is great ( Actually finished my game last night / this morning. I had some ideas the other night on how to improve it and it was quite nasty going from being "well" under the limit at around 4070 bytes and then going over with the new code. I was on 4099 bytes for quite a while last night until I cracked it. 4093 bytes and done, which is cool. I was going to be a clever sod and round that up to 4096 exactly, then realised that someone will do something in 2.5k that'll crap on my game and I'll just look silly for having used the max available and making something which isn't as good )

Rich over at photonStorm has posted some great tips for those of you giving the comp a bash in as3.

I opted for F8 / as2, although it's written like as1 with datatyping ( No Delegate or classes here ). Publishing as F7 would have saved a few bytes, but I wanted some of the filter effects.
I'm not sure what I can pass on that may be some use, but here goes ( Remember it applies to F8 / as2, the rules could be totally different for say F5 / as1, the size report is your friend with this comp ).

Chaining vars is actually longer, eg

score=level=d=cnt=0;

is a bit bigger than

score=0;
level=0;
d=0;
cnt=0;

Loops seem shorter this way,

while(--i)

Although to be honest I didn't try for loops ( I always use while, just habit )

It's common knowledge that pre-as3 var names have an effect on  size and speed in terms of their length ( i is "better" then myTempLoopCounterVar ) but linkage names have an impact too, so "bb" is smaller than "baddieBullet". Common sense I know, but if you're not used to thinking it terms of making code as tight as possible it's easy to miss ( It was for me anyway ).

More general things I did was to re-use values as much as I could, for example when the player dies I have to move it out of the way so the collision checks don't get triggered again, so I set player._x=2000; because I use a setInterval afterwards to wait for the gameOver ( id=setInterval(gameOver,player._x); )

Another thing, which is so dirty, was to drop an enterFrame on to everything. Originally I did the usual looping through an array calling the objects mainloop, but by adding the code to the sprite itself you remove all the loop overhead and make each sprite self sufficient.

It's weird tearing up the rule book for this comp, it's like going back to as1 and doing all those nasty things we used to do just to get things working.
If you've not done anything yet I can really recommend giving it a bash. The deadline is ages away yet, it should only take you a couple of hours for a couple of evenings and it's really good fun, it gets you back in touch with coding again rather than just dropping huge bitmaps into your fla and using a tweening package.

Squize.

Wednesday, February 18, 2009 10:41:28 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Wednesday, December 03, 2008
December already, it really does fly.

I was chatting with our mate Jeff @ 8bitRocket the other week about function pointers / state machines and I thought it may be useful to quickly write something up about it here, as so much of my code relies on them and they do make life easier.

private var mainFunc:Function;

That's pretty much it.

I'm guessing all your routines have some sort of mainloop. Either you're old school and that's running on an enterFrame on each mc you're moving about or it's a public method in an object which you loop through and call every frame.

Let's take a space invaders mainloop as an example ( Psuedo-code ahead )

function mainloop():void{
  if(thisInvaderIsDeadFlag==true){
    return;
  }
  if(areWeDyingFlag==true){
    if(sprite.currentframe==endOfExplosionsFrame){
      thisInvaderIsDeadFlag=true;
    }
    return;
  }

  moveInvader();
  testForShootingAtPlayer();
  testForBeingHitByPlayersBullet();
}


That should hopefully be straight forward enough. In real life we wouldn't want to be testing for thisInvaderIsDeadFlag every time, we'd just remove this invader from our array of active ones, but this is just an example.

Now check this out,

mainFunc=mainloop_normal;

function mainloop():void{
    mainFunc();
}

function mainloop_normal():void{
    moveInvader();
    testForShootingAtPlayer();
    testForBeingHitByPlayersBullet();
}

Here we've set up our function pointer to point to mainloop_normal, and then we just call that one method in our mainloop() method. Cool so far ?

Now we're not checking to see if the invader is dead, or if it's exploding. That's good, because by default the vast majority of the time neither of those are going to be true, so it's a waste to check ( It's like waking up every morning and seeing if it's your birthday ).

At the moment it's more of a function pointer than a state machine as such, so next up is why doing it this way is so sexy...

function testForBeingHitByPlayersBullet():void{
    if(playerBullet.hitTest(thisInvaderSprite)){
       thisInvaderSprite.gotoAndPlay("firstExplodingFrame");
       mainFunc=mainloop_waitingToDie;
    }
}

Here's our testForBeingHitByPlayerBullet method from the main loop. Imagine that's just doing a hitTest, the invader to the player bullet. Bang, it's a collision, but instead of having to set our areWeDyingFlag from the original example, we just change the state machine.

function mainloop_waitingToDie():void{
  if(sprite.currentframe==endOfExplosionsFrame){
//Kill this invader totally, ie remove the mc
      mainFunc=null;
  }
}

In effect, no extra checks are needed every frame, we're only running what we need. We've got the advantage of a slight performance boost, but far more useful than that is the flexibility this gives us.

Say for example you want your invader to teleport in now, at the start instead of:

mainFunc=mainloop_normal;

we can now alter it to,

mainFunc=mainloop_waitingForInvaderToTeleportIn;

And run the code there waiting for your cool teleport effect to finish, and then just alter the mainFunc to carry on with our flow.

Running your code this way means you can chop and change states without having to have lots of extra conditionals in your code ( If the player is teleporting in, but that teleport tween isn't at frame 10 yet, then don't test for collisions with the player bullet etc. etc. ).

Any questions just hit that comment button,

Squize.

Wednesday, December 03, 2008 9:16:54 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [8]  |  Trackback
 Thursday, November 06, 2008
Quite a descriptive title for this post for a change.
651_jellyVectors.jpg

In this section of 651 we're running two effects, a bog standard RGB plasma effect and then a "Jelly vector" effect.

To create a plasma you're going to have to suck up to Math.sin, he's your daddy for this.

Firstly we pre-calc a colour table, eg.

        public function ColourTable(){
            colourTable=new Array();
            var cnt:Number=-1;
            var col:Number;
            var r:int;
            var g:int;
            var b:int;
            var offset:Number=3.1415;

//To avoid /4 for each pixel every frame, we just make the colour table 4 times as big
            while(++cnt!=256*4){
                r = 128 + 128 * Math.sin(offset * cnt / 32);
                g = 128 + 128 * Math.sin(offset * cnt / 64);
                b = 128 + 128 * Math.sin(offset * cnt / 128);
                col=(r << 16)+(g << 8)+b;
                colourTable.push(col);
                colourTable.push(col);
                colourTable.push(col);
                colourTable.push(col);
            }
        }

Here we're just creating what is in effect a gradient, so we have an array which smoothly goes from one colour to the last one. When it comes to the look-up when we're plotting we'd need to divide the value by 4, so to avoid this we make the colour table 4 times larger than is really needed ( Often it's a balance between memory usage vs speed. An easy way to think of it is with loops. If your game didn't have any loops and you just copy / pasted the same thing over and over it would run quicker, but take a lot more memory, and be pretty insane ).

Right the colour table is done, next up we create instances of our Pixel class,

            activePixelsStorage=new Array();
            var pixelObj:Pixels;
            var j:int=-1;
            var k:int;
            while(++j!=120){
                k=-1;
                while(++k!=120){
                    pixelObj=new Pixels(new Point(j,k),colourTable);
                    activePixelsStorage.push(pixelObj);
                }
            }    

It's just like doing a tile based engine, each instance of our Pixel class is passed an x/y position so our plasma is 120 pixels wide by 120 high. That's pretty tiny so we double the scale of the sprite in which we're plotting and add a blur filter just to smooth it out. It's a lot less expensive than plotting a 240x240 plasma.

On to the actual Pixel class:

    public class Pixels{
//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private var xPos:int;
        private var yPos:int;

        private var cX:Number;
        private var cY:Number;
        
        private var jointDist:Number;
        
        private var offset:int;

        private var cT:Array;
        
//---------------------------------------------------------------------------------------
//Constructor
//---------------------------------------------------------------------------------------
        public function Pixels(pos:Point,colourTableArg:Array):void{
            cX=xPos=pos.x;
            cY=yPos=pos.y;
            var xDist:int=120-cX;            //Distance from the bottom
            var yDist:int=120-cY;

            cT=colourTableArg;
            
            var distance:Number=Math.round((Math.sqrt((xDist*xDist)+(yDist*yDist))/2));
            var distX:Number=256 * Math.sin(distance/8);
            var distY:Number=256 * Math.cos(distance/8);

            jointDist=distX+distY;
       }
        
//---------------------------------------------------------------------------------------
//Public
//---------------------------------------------------------------------------------------
        public function toString():String {
            return "Pixels";
        }        

//---------------------------------------------------------------------------------------
        public function pixelmainloop(x:Number,y:Number,plotbm:BitmapData):void{
            offset = (Math.cos((xPos+x)*0.0525) + Math.sin((yPos+y)*0.0255))*256 + jointDist;

            if(offset<0){
                offset=(offset ^ -1) + 1;
            }
            
            plotbm.setPixel(xPos,yPos,cT[offset]);
        }
    }

I'm not going to go into too much detail with this, as it'll take ages to be honest. The most interesting part is the pixelmainloop, where we pass in the x/y ( As well as the bitmapData we're plotting too, more on that soon ), and from those coords we create an offset into the colour table. To create the smooth curves that makes a plasma look so sexy we use some lovely sin and cos ( That's the bit I'm skipping explaining in any real detail. It takes quite a bit of tweaking to get something looking how you like and different values really give different results, for example:

            offset = (Math.cos((xPos+x)*0.0525) + Math.sin((yPos+y)*0.0255))*64 + jointDist;
            offset=offset>>3;

That's what's used in the credits plasma / kaleidoscope effect, which uses exactly the same colour table values but looks totally different ).

All that's left for the plasma part is the mainloop that we run on the enterFrame.

            sinOffset++;
            var radian:Number = sinOffset/60;
            paletteShiftX = 128-Math.sin(radian)*255;
            paletteShiftY = 128-Math.cos(radian)*255;

            plotbm.lock();

            var pixelObj:Pixels;
            for each(pixelObj in activePixelsStorage){
                pixelObj.pixelmainloop(paletteShiftX,paletteShiftY,plotbm);
            }

            plotbm.unlock();

            if(plotbm==bm1){
                plotbm=bm2;
            } else {
                plotbm=bm1;
            }

            bmData1.bitmapData=plotbm;

Nothing too tricky here. We just increase the position ( Offset ) into the colour table every frame, and then use for...each ( Much quicker ) to loop through all our Pixel instances calling the pixelmainloop and passing the args.
The part that may be of interest is the plotbm var. To increase speed slightly we double buffer the plasma bitmap, so when one bitmapData is being displayed we're plotting to the other one which is no longer being shown.
To try and explain that a little better, we have two bitmapData objects, bm1 and bm2. bmData1 is our bitmap ( I find the difference between the two confusing as hell in as3. It makes total sense, it just doesn't seem to stay in my brain very well ) which is attached to the our holder sprite for the plasma ( The one we doubled in size and added a blur to as mentioned earlier ).
So lets say we have something like this:
holderSprite.bmData1.bm1;
And that's what you see on screen. If you can see bm1 that means we're plotting to bm2, and visa versa.

This is why we pass the currently hidden bitmapData to each instance of the Pixel class every frame rather than just passing one value in during it's construction.

That's plasmas for you. I've only really given the core concept as hopefully a spring board for your own experiments.

The Jelly cube is going to be much more straight forward, because someone else wrote the clever bit. After x amount of time we run a really quick white up over the whole stage, and that's where we remove the plasma all together and replace it with a papervision cube.

Ultra simple, we just rotate him and scale him. The twister code came from the excellent zupko who kindly open sourced it. Now we've got a twisty cube, what about the texture ?

This is another big fat cheat. At best you can get a plasma running the size we have at around 40fps, so there's no way we could do it realtime and run the cube. One idea I had early on was to use draw() on every frame of the plasma and store those away, then update the texture every frame on the cube using those stored away bitmaps.
I didn't go this route as I was concerned about the amount of memory it would use and I was concerned that using draw() may have had a negative performance hit when actually running the plasma ( I'm possibly paranoid about that and it would more than likely be fine, but it felt like quite a bit of data to be copying every frame when you want everything running as quickly as possible ).

The solution ? flv baby. Unless it's youTube the flv format seems to be badly over looked when it can be used for all types of tricks ( I did quite a bit of video work in games at preloaded long before flv came out so I've learnt what the advantages of using video are early on ).
I just ran the plasma for a little while grabbing the frames, cropped them up, created a copy running backwards and then joined the two together, so runs as A > B > A.
All that was left then was to created a flv texture for each side of the cube, and papervision along with Flash did everything for me.

The only thing left to cover off is the black outline on the cube. Again ultra simple, it's just a glow filter. Set it to black, turn up the strength, turn down the blurring and you've got a sexy outline.

Phew. I think this is going to be last in-depth-ish tut on the 651 effects. Not only does it takes ages, but I think the rest of the effects not touched on so far can be summarised in one post.

Squize.


Thursday, November 06, 2008 5:24:29 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, November 04, 2008
So what's wrong with this code:

if (this._iDrawLayer & ChipsGame.VIEW_LAYER_A == ChipsGame.VIEW_LAYER_A) {
// draw contents of layer A ...
}

nothing, really. Nonetheless it's not working in CS3 (yet again, prove me wrong).

Basically it's just the unoptimized check if a certain bit is set or not. Let's do some traces:

trace ("with ():", ((this._iDrawLayer & ChipsGame.VIEW_LAYER_A) == ChipsGame.VIEW_LAYER_A))
trace ("without ():", (this._iDrawLayer & ChipsGame.VIEW_LAYER_A == ChipsGame.VIEW_LAYER_A))
trace ("values :", this._iDrawLayer & ChipsGame.VIEW_LAYER_A , ChipsGame.VIEW_LAYER_A)

The result is this:

with (): true
without (): 1
values: 1 1

Interesting, isn't it?
It seems like the compiler chains the & and the == for some reason that escapes me...

So if you get something undesiered with bitwise operators ... use ( and ) around it.

nGFX

Tuesday, November 04, 2008 3:33:54 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [3]  |  Trackback
 Wednesday, October 29, 2008
Back again!

After a good deal of time I finally have something to post about - or let's face it moan about.

As the headling slightly might suggest I'm dealing with sound today.
I think that sound handling in AS3 is a nightmare compared to the ease of it in AS1/2 and I'm not the only one asking WTF?

So in order to play your sound you have to instanciate it, if it's exported CS3 kindly creates a class for you so you can easily use it ... (loading it from an external source is another story)

This is what the CS3 help gives us for embeded sounds ("working with embeded sounds"):

var drum:DrumSound = new DrumSound();
var channel:SoundChannel = drum.play();

My first question was: what do I need the SoundChannel for if I just want to play the sound?

Well, the rocket scientists at Adobe thought that it would be a good idea to add a play() command to the Sound, but not a stop(), so in order to stop our sound playing we *need* the SoundChannel - so we better store it for later use.

Anyway, to make my life easier I converted my SoundUtil class from AS2, basically it deals with the sounds so I don't have to think about it, it has a few usefull commands like playSFX (plays a sound effect, once), playMusic (which allows fading), crossfade ...
I usually used attached sounds (or from an external swf, but the SoundUtil dealt with it ...)
So in order to play music for the menu I'd just do:

SoundUtil.getInstance().playMusic("musicName", 2); // 2 would do a 2 sec. fade in

The AS3 version should work the same, although it uses static functions which then call the singleton's method.

Oh wait. We need to have a class to start the embeded sound ...

To get over that I wrote the add method, which basically takes the name of the sound (or the classname) and then does it's magic.

        public function add (strSound:String, bIsMusic:Boolean):void {
            
            var refClass:Class = getDefinitionByName(strSound) as Class;
            var sndTmp:Sound = new refClass();
                        
            var iTmp:int = this._aSound.length;
            
            this._aSound.push(sndTmp);
            this._objSound[strSound] = { id:iTmp, bIsMusic: bIsMusic };
            
            if (bIsMusic) {
                this._objSound[strSound].spDummy = new Sprite();
            }
            
        }

Ha! that was easy ...

As you see the sounds name gets stored in an object (I just use it as dictionairy), I store an Object with some more values along with the name. And you surely might ask WHY on earth I did create a Sprite for music files ...
Well I'm a lamer, I use the Sprite to attach an onEnterFrameTo it for things like fading :)

Fast forward ...

k. Let's say we play some music, and only wont it to play 2 times, after that the sound should be removed from memory. Luckily we have the onSoundComplete Event, it should return (CS3 help): "The Sound object on which a sound has finished playing."

For me it reads like it returns the Sound that is playing. FAIL!

It does however return a SoundChannel, which of course HAS no information (prove me wrong) about the Sound it belongs to ...
So how can I unload/cleanup a Sound when an onSoundComplete occurs, if I don't know which Sound is playing (and don't want to write a seperate Listner for each sound)?

Oh lucky me...

Thank fuck I store a lot of things in my information object (not only what is shown in the add method), for instance I store the SoundChannel I got from Sound's play() command and I store if a Sound is playing ...

After a few hours of using our favorite search engine I came up with something so stupid it might even be brilliant ...

private function onSoundComplete (e:Event):void {
            
      var strKey:String;
            
      for (strKey in this._objSound) {
           if (this._objSound[strKey].bIsMusic) {
               if (this._objSound[strKey].chChannel == e.target) {
                   this._objSound[strKey].chChannel.removeEventListener(Event.SOUND_COMPLETE, this.onSoundComplete);
                   this._objSound[strKey].bIsPlaying = false;
                   // do some cleanup
               }
           }
       }
            
}

Basically I loop over all music "files" that are playing and *compare* their SoundChannel with the one returned by the Event.
That's so insanely stupid! But it works. Sweet.

Maybe it helps some of you ...

nGFX

Wednesday, October 29, 2008 5:46:21 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Thursday, October 23, 2008
Here's another really old trick we used in 651.

651_bobs.jpg

Way back in Amigaland software sprites ( ie, sprites which were plotted by the blitter as opposed to being hardware based, like a mouse pointer ) were called "Bobs" ( Blitter OBjects ). As with everything you could only ever run a certain amount before you started running out of cpu time, so when the first infinite bob effects started appearing in demos every one passed a little bit of involuntary wee.

//------------------------------------------------
// Bob properties
//------------------------------------------------
        private var ball:Sprite;
        
        private var bm1:BitmapData;
        private var bm2:BitmapData;
        private var bm3:BitmapData;
        private var bmData1:Bitmap;
        private var bmData2:Bitmap;
        private var bmData3:Bitmap;

        private var currentBitmapNumber:int;

Just set up 3 bitmaps, and then...

//Set up the sprites
            container=new Sprite();
            stage.addChild(container);
            
            playField=new Sprite();
            container.addChild(playField);

Create a holder sprite + add it to the stage, and then a further sprite within that. Also add your bob to the playField ( Not the container or the stage )

Next up, our mainloop,

//---------------------------------------------------------------------------------------
        private function mainloop(e:Event):void{
            moveBob();
            copyBitmap();
}

moveBob() is however you want to move the bob around the screen, use your nice sin based movement that you've got tucked away. All it's doing is just moving one bob ( ball:Sprite in this case ) around the screen.

The funky bit is the copyBitmap() method,

//---------------------------------------------------------------------------------------
        private function copyBitmap():void{
            container.addChild(this["bmData"+currentBitmapNumber]);
            this["bm"+currentBitmapNumber].draw(playField);

            if(++currentBitmapNumber==4){
                currentBitmapNumber=1;
            }
        }

It just simply loops through all our bitmaps, copying what's in our playField ( ie the ball ) to the next bitmap. Just written down like this it's a bit tricky to grasp, think of it like an old flick book. You move the bob, you take a copy of the whole screen and store that in a bitmap and then display that, you then move the bob again, and take another grab of it and so on. We use 3 bitmaps because the image will be slightly different on all of them, creating the sense of movement ( Otherwise it wouldn't animate and would just look like a trail behind the bob ).

I can recommend giving it a quick play, it'll take 5 mins to set yourself up with a working example and once it's running infront of you it'll click into place how it actually does work.

Squize.

Thursday, October 23, 2008 2:22:11 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Tuesday, October 21, 2008
Now 651 is history I thought it may be of interest to go through how some of the parts work.

Let's start with the boring bit for today, the actual structure. To make testing it easier, and to be able to swap and change the order to make sure it felt right, I used a pretty simple yet modular approach,

//------------------------------------------------
// Demo classes
//------------------------------------------------
        private var logo:Logo;
        private var credits:Credits;
        private var twister:Twister;
        private var vectorBalls:VectorBalls;
        private var pimp:Pimp;
        private var showReel:ShowReel;
        private var water:Water;
        private var fin:Fin;
        
        private var sequenceOrder:Array=new Array("logo","twister","vectorBalls","pimp","credits","showReel","water","fin");
        private var sequenceOffset:int;


The sequenceOrder array kinda speaks for itself. The other part of the code is just as straight forward:

//---------------------------------------------------------------------------------------
        public function sequence():void{
            switch (sequenceOrder[sequenceOffset]){
                case "logo":
                    logo=new Logo();
                    break;    
                case "twister":
                    twister=new Twister();
                    break;    
                case "credits":
                    credits=new Credits();
                    break;    
                case "vectorBalls":
                    vectorBalls=new VectorBalls();
                    break;    
                case "pimp":
                    pimp=new Pimp();
                    break;    
                case "showReel":
                    showReel=new ShowReel();
                    break;    
                case "water":
                    water=new Water();
                    break;    
                case "fin":
                    fin=new Fin();
                    break;    
            }
        }

//---------------------------------------------------------------------------------------
        public function finished():void{
            if(++sequenceOffset==sequenceOrder.length){
//Finished            
            } else {
                sequence();
            }
        }


Each segment is totally independent, ie it has it's own init and housekeeping routines, there's no co-dependency at all. To start the demo the sequenceOffset var is set to 0 and then the sequence() method is called.
When a segment has finished, it calls it's houseKeeping() method to dispose of all the bitmaps and removes all the sprites from the stage, and then calls the finished() method ( Hence it being public ).

That's all there is to the underlying structure which runs the demo, it really doesn't get any more straight forward.

Squize.

Tuesday, October 21, 2008 8:37:29 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, October 02, 2008
Air. The future of RIA. Unless you try and actually use it.

I've been wanting to write a swf encryptor for ages and last night I finally cracked ( As I'm working on something that I really don't want decompiling for various reasons ).
It was a toss up between Zinc and Air, but I opted for AIR 'cause in theory it is the future and therefore should have better support than Zinc.

So after all the hype surrounding Air I should just be able to google around, find out how to drag and drop, save a file and some other basics. I develop in Flex rather than cs3 'cause it's a million times better, but any search for Flex and Air just brings up examples using MXML. That's not great.

Eventually I found a hacky way to create an Air project in actionscript in Flex ( It's so convoluted it's untrue. You create a Flex project as opposed to an AS one as usual, tick the Air box, but on the part where you set the document class you alter the mxml extension to .as and it works ).
Getting there. Published the main class and up popped... nothing. More searching and I found out how to set it up ( A big thanks to Toby for blogging about it, without his words I'd have given up all together ).

Cool, got a window in place now. Close it, try publishing it again, and... nothing. Lot's more searching ( And swearing ) and I found out what the problem was, and the cure. If you don't exit your app correctly ( ie call an exit() after adding a listener to the close button ) then it doesn't actually exit correctly ( I found this out myself after a lot of messing about ).
When you publish an air app it runs something called adl.exe ( Adobe Debugging something. I've had enough air googling for a life time so can't face looking it up ) which runs the swf wrapped in the air api.
If you don't call exit() then when you close the app adl.exe keeps running. Ok, that's not the end of the world. What actually is though, is that you can only run one instance of adl.exe. If it's running after you've closed your app incorrectly, then you can't run any more air apps.
The beautiful thing is, it doesn't tell you. Flex doesn't tell you either. It's like they've ganged up to keep us in the dark.

Until I figured out the whole exit() thing, I was working with task manager open closing it down every time. The only solutions I found online were, yep, work with task manager open and...

Ok it kinda makes sense, and if you've got to call exit() then you've got to call it, but c'mon, this is the future of RIA and I've got task manger open to kill it ?
It all feels very beta-ish, from the hacky way to even create an Air project in Flex to that.

Once I got past these hurdles, I must admit it wasn't that bad. The lack of docs ( I only found this after I'd gone through a lot of pain ) has made it a less pleasant exercise than it should have been ( Oh joy, another mxml example for something I want to do with code ).

One weird thing which I'm putting down to me is that when I drag and drop a swf into my sexy little app it runs the app twice. I don't mean it opens another window, it just runs through all the code twice ( In alcon I was getting,
"wtf ?"
"wtf ?"
which was a bit of a give away ). A little kludgy check cleared that up.

At present we've got a simple little app which you can drag a swf onto, it then encrypts that with blowfish via the very nice Crypto library and you can then save that back out.

Next up ( And what I've been swearing at for the past hour or so ) is the decryption routines. Well, the code is being embedded and decrypted, it's just figuring out how to then make that byteArray run as a swf rather than just sitting there annoying me.

Squize.

Thursday, October 02, 2008 9:20:04 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [7]  |  Trackback
 Sunday, September 07, 2008

I've been silent the last couple of weeks, too silent I reckon, but ... yet again I've been oompha-loompha'ing for various projects.

One of this projects really raised the bar in several ways (I think I'll do a rundown afterward - deadline is tomorrow, really, no way of extending it, even for a few minutes).

So for now let us assume we're dealing with a purely hypothetic project (as this is not about what all went wrong during the assignment).

This fantasy project should contain this:
- a menu, 3 languages, able to load in various games
- multi language support for the games (which have been done by someone else)

As I'm used to work with Flash's strings panel it was a logical choice to use, basically you can set it to "auto" mode and all assigned Textfields will be replaced at runtime with the associated one, you can also set a new language while running and everything is fine.

Or so I thought.

The menu worked fine, but then I got the first game ... oh, now we Imagine the first game ...
Some files ...
- one 150MB fla, called "library" - LIBRARY? yes.
- one 90MB called "game" ...
- a few more files (levels), each around 90MB

OK, library mustn't mean something bad.

Or so I thought.

Library in this case means something bad. BAD. BAD. BAD.
It meant: shared library (for those of you lucky enough to have not heard about it yet ... read about here.)
Oh when you're back from reading about it, you surely think "oh, that is nice"

WAIT! Don't ever even think about thinking "oh, that is nice" when it comes to shared libraries. They are EVIL!
It's the foot and mouth disease of Flash's features.

(imagine using one)
You'll first notice that you lose control about preloading - shared libs work like things exported to the first frame BUT without being able to detect their size.

Fast forward now ...

So you have the menu using Flash's strings panel, working, now it's time to load in the first game ...
I chose to use the good old and trusty loadMovie method instead of the MovieclipLoader class. So it was just a simple load and detect the size, start when done.

OR SO I THOUGHT.

Well, I knew from other project that when loading an swf that uses Locale, the newly loaded swf (using Locale, too) replaces the language data from the holder swf. This is OK and it makes sense if you think about the fact that a static class is assigned to _global in AS2. So the game used the same language files the menu does ... easy.

The dirty details ...

The game loads in a couple of external mp3 files, so I had to take care of that, too - easy enough, so no problem there too..
This is what we see:
- loading starts, use getBytesLoaded / getBytesTotal to see when it's done ...
- tracing shows 140k of swf to load, fair enough.
- after loading that, nothing happened. For 900k nothing happened - Flash was loading in the shared lib.
- then I was able to watch the mp3 files loading and afterward start the game - finally.

The problem is that the user might think that the game isn't loading at all when the shared lib is loaded - THERE IS NO WAY OF WATCHING IT LOADING!!!!!!
First I thought I could trick my way out of it by loading the shared lib FIRST and then hope the cache would kick in when the game is later loaded - nice try buddy. No, it doesn't work (at least not very well).

I ended up by using a faked (and then real) file list to load the game, basically it shows that there are 2 files to load.
First the swf is loaded, then while waiting for it to load the shared lib, I fake a progress and later I add the mp3 files to that list also to watch them loading, too.

Now that this is off the list ...

Yehaa the game is loaded and ready to to be played ...
- level one works ...
- the "level done" screen pops up AND ... it is definitely NOT in the language I've been using in the menu. WTF?

In fact the game was now all in German, whereas I selected English for the menu.

WHY? What happened. I had no idea.

A lengthy search using your fav. search engine did not give us anything.

OK, so we're on our own again (hey, after all this is Flash).

Let the tracing begin ...

First thing I checked was the language set using Locale.getDefault():
- startup: "de" (because of my desktop language)
- set it to "en"
- (checking, yes now everything is "en")
- load game: still "en"
- play game: still "en"
- show level done: still ... "en"

BUT IT FUCKING SHOWS ALL FUCKING STRINGS IN FUCKING GERMAN!

More fast forward ...

A few hours later I have lost a good deal of hair, brain and energy and of course all the trouble is caused by ...  right . the shared library.
It seems like it overwrites the language data with it's own values but doesn't report it to Locale (so you can see it).

And they lived happily ever after ...

I ended up, oh, we "would" (we still imagine the project you know) with loading the game, loading all external files and THEN reload the language file.

nGFX

ps: next time I tell you about the joys of using art based levels that consist of over 900 vector based drawings, movieclips and components ... which take almost 10 minutes to copy and move ... joy.

Sunday, September 07, 2008 2:25:04 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Thursday, August 28, 2008
Collisions, they're always a part of my games that I'm never happy with. Not so much the actual this sprite has hit that sprite part ( The narrowphase of the check ), but the broadphase, ie deciding which checks are needed and which we can just ignore.

Different genres require different ways to test for collisions. For a long time now I've been using grid based checks ( As far back as this old beauty ) in arena based shoot'em ups. Simple enough, you split the screen up into overlapping sectors, and store each baddie in the sector it's occupying.
So let's say we've split the screen up into quarters, you check each baddie's position, and store it in one of the four arrays you've set aside for each sector. Then you can run through your bullets and see which sector they're in, so in theory you're only testing the baddies which are nearest to the bullet ( There's no point testing a bullet against a baddie which is on the other side of the screen ) which in an ideal world will reduce the checks by 75%. Not bad.

The problem I've always had with this is that it feels costly to maintain. I've always just cleared the sector arrays at the start of the baddie movement routines, I've never been clever enough to come up with a way to maintain it "properly". Therefore I could have baddies that have only moved a pixel or two since the last frame, there's no way they're going to have changed sectors, but I've had to treat them afresh.
That can't be good, but like I've said, I've never been able to come up with a clever way of negating that, so I've always just done it that big dumb way.

Recently quadtrees ( Check here for a great example, and an overview by the always excellent 8bitrocket can be found here ) and octtrees are very in vogue with Flash developers, so being a bandwagon jumper I thought I'd have a bit of that.

Again, I couldn't think of really good way to maintain the structure every frame, and it felt like you'd need a lot of objects to make it worthwhile ( Or just use it as a generic collision system for every game, but I'm not a fan of that. Collisions are a weird beast where very rarely does one hat fit all ).

One aspect that all the collision methods I mentioned above have, is shown below,

dbB1.png

I'm going to generalise a bit here, but let's say we've drilled down into the correct sector / node / whatever. Our bullet is travelling along that path ( Pick which ever direction you feel more comfortable with, in my head it's going up and right ). Chances are it's never going to hit that baddie ( I know the baddie could in theory move enough to come into collision with it, but we're generalising for a second ).
So we've gone to quite a bit of effort to narrow down our collision checks, and then we're still running a check per bullet every frame when most of the time it's not going to hit ( Think of your accuracy rating at any game that checks such things. 75% is pretty good in a game. That means that 25% of all the bullets are going to miss, yet we're having to test 100% of the bullets a 100% of the time ).

This all felt a bit sucky in my head. A lot of cpu time spent on something that wouldn't happen.

Let's talks about "Distance Based Broadphase". I made that up, it's more than likely already been around for years with a different name and I've just happened across a similar idea, but it explains what it is pretty well.

I've approached it in a different way than how I normally set up the whole bullets / baddies stuff. Using DBB every baddie has an array of all the player bullets ( Well a linked list for speed ), and every time the player shoots that new bullet is shoved into that array.
During the baddies main loop it runs through all the bullets it has in it's array and checks it's distance to it ( The narrowphase checks are just your bog standard circle to circle collisions ). If it's distance has increased, then the bullet is moving away from the baddie, and it won't hit it.

dbB2.png

So looking at that diagram above, lets say the bullet is flying up to the top left. The broadphase will keep checking as the distance from the bullet to the baddie is decreasing every frame, ie it's getting closer. It's possible that it could hit it, so it's worth checking.
Once the bullet goes past the sweet spot, it's moving away from the baddie. It'll never ever hit it, so we just remove it from the array and the baddie won't check for it again.

Whilst there's a possability of a collision it's worth checking, so it's not so costly ( If you're shooting at baddies from a distance then it's going to incur a cost until the bullet goes past the sweet spot, ie 'til the bullet gets to a point where it's not going to hit the baddie. The greater the distance the more the tests as it will take a while to actually get to the sweet spot ).
Going back to the first diagram, the bullet ( If moving to the top right ) is moving away from the baddie right from the start, so it's thrown away.
In effect we're checking the general direction until we get to the point of a hit, or a miss.

Now I've done some generalisation here. In real life your baddie will be flying around throwing some great shapes. For that, you just increase the size of the sweet spot to take it into account. If you have a fixed speed for a baddie you could work out exactly the sweet spot's size ( That is you'd work out if the baddie moving at it's max speed in a straight line to the bullets path how big the area to check would be ), or if you're lazy like me you just increase the size of the sweet spot by subtracting some pixels from the distance and testing it til it stops breaking.

Hopefully I've made some sense, it's proved to be quite a fair bit to explain. As always please feel free to post a comment if you have any questions or if I've got anything wrong. I'm sure I'll be editing this soon enough to clear things up.

Squize.

Thursday, August 28, 2008 2:44:27 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [7]  |  Trackback
 Wednesday, August 27, 2008
In the recent theme of speed testing I thought I'd better double check my atan2 results, and comparing the below method to the built in one I got the following:

runAtan2():  2161
runAtan2Quicker():  1159

( For more about how I test this stuff, please check this recent post )

Phew, something actually working quickly as it's meant to.

The following method is based on code by Jim Shima, http://dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm

private static var coeff_1:Number = Math.PI / 4;
private static var coeff_2:Number;
private static var r:Number;
private static var angle:Number;
private static var absY:Number;

//--------------------------------------------------------------------------
public static function atan2(y:Number,x:Number):Number{
    coeff_2 = 3 * coeff_1;
    absY=y;
    if (absY < 0) absY = -absY;                    //Math.abs
    if(x>=0){
        r= (x - absY) / (x + absY);
        angle = coeff_1 - coeff_1 * r;
    } else {
        r = (x + absY) / (absY - x);
        angle = coeff_2 - coeff_1 * r;
    }
    return y < 0 ? -angle : angle;
}

I've used static properties / method 'cause it's part of my MathX class ( So if you're going to set up a similar way, create a class called MathX and then the usage would be,

var value:Number=MathX.atan2(y,x);

Exactly the same as the built in method ).

Squize.

Wednesday, August 27, 2008 5:05:00 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Saturday, August 23, 2008
I'm becoming a bit of a speed testing slut with as3, and seeing how this function is used in so many games, I thought I'd have a play and see which actually is the quickest way to do this.

Point.distance() seems to have everything going for it, but does it ?

import flash.utils.getTimer;
import flash.geom.Point;

var time:Number;

var point1:Point=new Point(100,100);
var point2:Point=new Point(200,200);

var dist:Number;
var dx:Number;
var dy:Number;

function runPythagorean():void{
    time = getTimer();
    for (var i:int = 0; i < 10000000; i++) {
         dx = point2.x-point1.x;
         dy = point2.y-point1.y;
         dist = Math.sqrt(dx*dx + dy*dy);
    }
    trace("runPythagorean(): ", (getTimer()-time));
}

function runDistance():void{
    time = getTimer();
    for (var i:int = 0; i < 10000000; i++) {
         dist = Point.distance(point1,point2);
    }
    trace("runDistance(): ", (getTimer()-time));
}

runPythagorean();
runDistance();

Slap that into Flash, and be surprised at the huge difference between the two ( For those of you who prefer just to look rather than get involved, on my machine I got the following:

runPythagorean():  1452
runDistance():  10485

Not really neck and neck ).

So the distance method is a none starter ( What the hell does Flash do behind the scenes ? It's only returning a Number, it shouldn't need to be doing anything other that the code in the runPythagorean() method ).

Don't know if I've posted about it here before either, but avoid Rectangle.intersects() for the same reasons too.

Whilst I was testing I thought I'd do the old shortcut of:

var sq:Function=Math.sqrt;
dist = sq(dx*dx + dy*dy);

Again, another surprise,

runPythagorean():  1464
runPythagoreanWithShortCut():  2824

Finally, I finished off with some "quicker" versions of sqrt, ie

//---------------------------------------------------------------------------------------
function sqrt(w:Number):Number{
// Fast Math sqrt function from
// http://osflash.org/as3_speed_optimizations#as3_speed_tests
    var thresh    : Number = 0.002;
    var b:Number = w * 0.25
    var a:Number;
    var c:Number;
    
    if (w == 0) return 0;
    
    do {
        c = w / b;
        b = (b + c) * 0.5;
        a = b - c;
        if (a < 0) a = -a;
    }
    while (a > thresh);
    
    return b;
}
        
//---------------------------------------------------------------------------------------
function fsqrt(w:Number):Number{
// SUPA fast but not very accurate sqrt
// Fast Math sqrt function from
// http://osflash.org/as3_speed_optimizations#as3_speed_tests
    var thresh    : Number = 2;            //1
    var b:Number = w * 0.25
    var a:Number;
    var c:Number;
    
    do {
        c = w / b;
        b = (b + c) * 0.5;
        a = b - c;
        if (a < 0) a = -a;
    }
    while (a > thresh);
    
    return b;
}


I've got both of these in my MathX class, which is a collection of quicker alternatives to the built in methods and various other little math based utils.
This test made me think I was going a bit mental,

runPythagorean():  1452
runQuickSqrt():  3514
runQuickFSqrt():  3237

Now I've not done these tests over and over and averaged them out, 'cause to be honest the results really aren't close enough to warrant it. Please feel free to try these out yourselves and post the results back here. Maybe those last two methods should be inlined rather than wrapped in functions, but I've really not got the inclination to try it out.

Squize.

Saturday, August 23, 2008 9:54:47 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Thursday, July 10, 2008
I've been pulling my hair out for about an hour with this beauty, and after finding the solution I thought I should share here, if for no other reason that I know I'll get it again and lose another hour ( I'm 36, my memory is shot ).

When trying to make a new bitmap instance of a bitmap in the library, along the lines of:

        [Embed("/_assets/assets.swf",symbol="bouncerBitmap")]
        private var bouncerBitmap:Class;

        var bm:Bitmap=new bouncerBitmap();

I was getting invalid data when running the swf, basically it was failing big time.

Had a bit of a google and found this. For some beautiful unknown reason, sometimes when you import a png to the library and set the compression to jpg ( Although in this case I actually hadn't, Flash just took it upon itself to make it a jpg for me ) it screws up.

Joy.

Anyway all fixed now, and I've even got this as a reminder for next time.

Squize.

Wednesday, July 09, 2008 10:48:45 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, June 29, 2008
Preloading with Flex for actionscript projects still seems to be really under-documented. Personally I've found it to be a bit of a joke that you've got to search half a dozen sites to find out how it's done, I mean it's preloading, it's what Flash does.

So I thought I'd add "my" approach here. It's what I'm using and seems to work well, it's been cobbled together by reading through the half a dozen websites, so I'm not claiming it's all my code or my idea, it's other peoples code who are clever than me shoved together.

Let's start at the begining,

package {
    import flash.display.DisplayObject;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.MovieClip;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.utils.getDefinitionByName;

    [SWF(width="400", height="600", frameRate="40", backgroundColor="#FFFFFF")]

    public class Preloader extends MovieClip{
//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private var logoClass:Class;
        private var logoClassInstance:Object;
        
//---------------------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------------------
        public function Preloader() {
            stop();
            stage.showDefaultContextMenu=false;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.quality=StageQuality.LOW;

            addEventListener(Event.ENTER_FRAME,mainloop);
        }

//---------------------------------------------------------------------------------------
// Private
//---------------------------------------------------------------------------------------
        private function mainloop(e:Event):void{
            if(framesLoaded >= 2){
                nextFrame();
                triggerLogo();
                removeEventListener(Event.ENTER_FRAME,mainloop);
                addEventListener(Event.ENTER_FRAME,mainloop2);
            }            
        }

//---------------------------------------------------------------------------------------
        private function mainloop2(e:Event):void{
            if(framesLoaded == totalFrames){
//It's all loaded, has the logo finished ?
                if(logoClassInstance.animCompletedFlag==true){
                    removeEventListener(Event.ENTER_FRAME,mainloop2);
                    nextFrame();
                    triggerGame();
                }
            }            
        }

//---------------------------------------------------------------------------------------
private function triggerLogo():void{
            logoClass = getDefinitionByName("PreloaderLogo") as Class;
    if(logoClass) {
        logoClassInstance = new logoClass();
        addChild(logoClassInstance as DisplayObject);
    }
}

//---------------------------------------------------------------------------------------
private function triggerGame():void{
            var main:Class = getDefinitionByName("Main") as Class;
    if(main) {
        var app:Object = new main();
        addChild(app as DisplayObject);
             app.waiting();                        //Call the singleton to kick it all off
                logoClassInstance.dispose();
    }
}

//---------------------------------------------------------------------------------------
    }
}

Just to run through this nice and quickly, the preloader extends the MovieClip class as we're using 3 frames for the game ( The actual preloader class, the PreloaderLogo class and the Main one ( Which is the game itself )).
In the constructor we just do all the stage stuff that we want to do ( Hide that menu ), and then run an eventListener ( Mainloop ) which checks to see how much of the overall game has loaded. If frame 2 has loaded it means how logo is loaded, so we can fire that off ( See the trigger logo method, and below is the PreloaderLogo class )

package {  
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.events.Event;
    
    public class PreloaderLogo extends Sprite {
//---------------------------------------------------------------------------------------
// Assets
//---------------------------------------------------------------------------------------
        [Embed("/_assets/assets.swf",symbol="gywLogoMC")]
        private var gywLogoMC:Class;

//---------------------------------------------------------------------------------------
// Properties
//---------------------------------------------------------------------------------------
        private var gywLogo:MovieClip;
        public var animCompletedFlag:Boolean=false;
        
//---------------------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------------------
        public function PreloaderLogo(){
            gywLogo=new gywLogoMC();
            waiting();
        }

//---------------------------------------------------------------------------------------
        public function waiting():void{
            addEventListener(Event.ADDED_TO_STAGE,logoAddedToStage);
        }

//---------------------------------------------------------------------------------------
        public function dispose():void{
            stage.removeChild(gywLogo);
        }

//---------------------------------------------------------------------------------------
// Private
//---------------------------------------------------------------------------------------
        private function logoAddedToStage(e:Event):void{
            stage.addChild(gywLogo);
            gywLogo.gotoAndPlay(1);
            gywLogo.addEventListener(Event.ENTER_FRAME,waitingToEnd);
        }

//---------------------------------------------------------------------------------------
        private function waitingToEnd(e:Event):void{
            if(gywLogo.currentFrame==gywLogo.totalFrames){
                gywLogo.gotoAndStop(gywLogo.totalFrames);
                gywLogo.removeEventListener(Event.ENTER_FRAME,waitingToEnd);
                animCompletedFlag=true;
            }
        }


//---------------------------------------------------------------------------------------
    }
}

All that's happening there is the class embeds our logo and plays the animation. The waiting() method checks to see if this class has been added to the display list, if we don't wait then you open up a world of pain where the class can't find the stage.
The waitingToEnd method is as simple as it gets, once the animation has finished it just sets the animCompletedFlag to true.

Going back to the preloader class, after the PreloaderLogo class has been triggered we're running mainLoop2. That's just a check to see if the whole game ( ie all 3 frames ) has loaded. If it has when then check for the animCompletedFlag to be true. If it isn't it means the preloader logo is still running, if it is true, then we're done. The game has loaded and our sexy intro anim is done. From there we do exactly what we did before and trigger our Main class ( The game itself ).

The last part of this is the setting in Flex itself. Right click your project and select properties. From there go to the "ActionScript Compiler" options and pass the following arguments to the compiler
flex.png
(click image to enlarge)

And finally after jumping through an insane amount of hoops you should have a working preloader. The logo class can be whatever you want, and there can be more than 3 frames, if for example you want a loader bar to be displayed quickly and then bring in your logos.

*Update - I've posted the source to Operation Cortex, which includes the preloader code which should make life easier*

Squize.

Sunday, June 29, 2008 3:30:55 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, March 29, 2008
Another rant post (but once I get back on game coding I'll do some more coding oriented posts. Promised.).

The reason I din't post about the current game of mine is that it's more or less on hold while I slave for another project (which is I'm sorry to say 100% not game related :|).

So why is that another rant post?

I bought a new box, a new shiny f$%&ing fast one (and to slow it down a bit I also installed Vista Ultimate on it :) ) (no need to point out that there are other OSes, because I *like* it).

Sometime last year I bought a copy of Nero Burning Rom, the once best cd/dvd burning app. You may have noticed "once".
The version I got was 7.5.7 and except for the darn amount of useless shit that came with it, I was quite happy with it on XP.

Because I like the ease of Nero Express I just wanted to install this (and the Nero app of course) but who the f$%& needs "recode", "showtime" a wave editor(!) ?
Anyway, I decided to install it on my new box and it turned out to become quite a nightmare ...

Once Nero was installed everytime I opened a folder that contained a video file I was greeted with as "rundll32 crash". Sweet.
First and (why not) choice to blame was MS for their OS, but after a quick google I found out that the problem is Nero. To be precise, one of the things I didn't chose to install, the shit codecs that came with it (there's no option to *not* install them).

But how do you remove a codec under Vista?

Quick google again, here we are: InstalledCodec v1.00
"InstalledCodec is a small utility displays the list of all Codec drivers and DirectShow filters currently installed on your system. For each component the following information is displayed: Display Name, Type, Disabled Status, Installed/Modified Time, Description, Company Name, Filename, and more...
It allows you to easily disable or enable any Codec/DirectShow component or export the list into text/xml/html file."

A few clicks later I disabled all codecs that started with "Nero" and viola. no rundll32 crashes.

So far I noticed no problems.

nGFX
Saturday, March 29, 2008 8:51:35 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, November 16, 2007

I was just tinkering and wondered what would be quicker, using clone() on a Rectangle or just copying each property by hand.

Totally blown away by the difference,


import flash.utils.getTimer;
import flash.geom.Rectangle;

var time:Number = getTimer();

function runClone():void{    
    var rect:Rectangle=new Rectangle(0,0,100,100);
    var destRect:Rectangle=rect.clone();
    time = getTimer();
    for (var i:int = 0; i < 10000000; i++) {
        destRect=rect.clone();
    }
    trace("runClone: ", (getTimer()-time));
}

function runCopy():void{    
    var rect:Rectangle=new Rectangle(0,0,100,100);
    var destRect:Rectangle=rect.clone();
    time = getTimer();
    for (var i:int = 0; i < 10000000; i++) {
        destRect.x=rect.x;
        destRect.y=rect.y;
        destRect.width=rect.width;
        destRect.height=rect.height;
    }
    trace("runCopy: ", (getTimer()-time));
}

runClone();
runCopy();

And here's my results ( Please feel free to post your own, or to point out anything dumb I may have done to affect the outcome )

runClone:  11567
runCopy:  65

Squize.



Friday, November 16, 2007 1:32:43 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Tuesday, October 30, 2007
In a recent comment posted here I was asked about the slopes in the current platformer, and I promised I'd go over it, so here it is ( Albiet slightly rushed and with no nice diagrams, deadlines and all that ).

In a tile based engine it's fairly simple to work out where the position of the sprite is in relation to the tile he's standing on. So as you move over a tile you're updating the x position which is obvious enough.
Also usually with map data you have an attribute value / byte for each tile, again if you've worked with tiles you're with me so far.

To simulate a slope easily you have an array of y positions for the sprite. In my case I have 8 values for every sloping tile, as the player moves at 4 pixels per frame, and the tiles are 32px wide, so it's 32/4 = 8 possible positions for every tile on the horizontal.

Let's say our slope looks like this ( In array form )

[0,2,4,6,8,12,14,16];

If we're at position 0 on the x of the tile, ie the left hand side, we read the first value in the slope array, in this case 0, and we decrease the sprites._y by that amount ( Decrease 'cause we're moving him up ), so the next step will make the sprite 2 pixels higher up the screen than he was last move and so on.

Above I mentioned using attributes, this is how I get an offset into the array of slopes ( They're just stored as a 2 dimensional array ). If you didn't use an attribute in the map data, just used the tile number, then you'd need to have an array for every single tile ( Where the vast majority would be flat ), which is a hell of a lot of work for no reason, and a waste of resources.

So again we're stepping on our tile, and it's attribute is 1. We know to look into the slope array at attribute-1 ( Arrays start at 0 ), which gives us our first saved slope value, and from there we can get the correct y position for each step of the way.

Simple as you like, hardly any real cpu overhead, and so far with what I've been working on it seems to cope with any angle I've thrown at it. If you wanted to add more realistic movement ( So the sprite stuggles up a hill, sprints down it ) you could store another array with the players max moving speed for each position and add that to the overal speed.

Squize.

Tuesday, October 30, 2007 6:23:32 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, May 07, 2007
As promised way to long ago (here), I finally manged to get the brush example done.
Not the best way, not the best code, but an example nonetheless.

(just press the left mousebutton and move the mouse ...)

And the zipped fla (F8): drawexample.zip (6,11 KB)

And for those hwo don't want to d/load the fla ... just the code. You just need this two images set for export in the first frame:
(Brush, with alpha)
(color / pattern)

import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;

var bmpColor:BitmapData = BitmapData.loadBitmap("color_00.png");                // the color to paint with
var bmpWall:BitmapData = new BitmapData(480, 200, false, 0xc0c0c0);                // a bmp to paint in

var bMouseDown:Boolean = false;
var iPaint:Number = 0;    // "color on brush"

this.onEnterFrame = function ():Void {
    
    var bmpAlpha:BitmapData = BitmapData.loadBitmap("brush_shape_and_alpha.png");     // the "brush"
    
    var iPosX:Number = this._xmouse - (bmpAlpha.width * 0.5);
    var iPosY:Number = this._ymouse - (bmpAlpha.height * 0.5);

    if (bMouseDown) {
        
        // modify alpha ...
        bmpAlpha.colorTransform(bmpAlpha.rectangle, new ColorTransform(1, 1, 1, 1, 0, 0, 0, iPaint));
            
        bmpWall.copyPixels(bmpColor, bmpAlpha.rectangle, new Point(iPosX, iPosY), bmpAlpha, new Point(0,0), true);
        this.attachBitmap(bmpWall, 0); // show ... (not the best way, imho ...)
        
        // Disolve paint ...
        iPaint -= 5;
        if (iPaint <= -250) {
            iPaint = 0; // just resti t
        }
    }
}

this.onMouseDown = function ():Void {
    bMouseDown = true;
}

this.onMouseUp = function ():Void {
    bMouseDown = false;
}




nGFX
Monday, May 07, 2007 10:26:39 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Sunday, January 14, 2007
Hi folks,

I know that there are by far more people out there not iis/asp.net, and not all of this tiny rest are having to deal with the server (2003 and iis 6.0 that is).

Anyway, I was just setting up a flash application that uses flash video. So do a bit of surrounding html, upload the app and the .flv vids and ... done.

Oh bugger, it would have been so good if it would have worked.

The first thing I thought it has something to do with my code, but on my local iis it worked like a charm.
The best thing was, the file gave me a 404 when I tried to access it via the URL I used in the player ...

A good deal of time later i finally found this: How to set up .flv files on iis 6.0.


Here's the solution (copied from the above link, though)
  1. On the Windows 2003 server, open the Internet Information Services Manager.
  2. Expand the Local Computer Server.
  3. Right-click the local computer server and select Properties.
  4. Select the MIME Types tab.
  5. Click New and enter the following information:
    • Associated Extension box: .FLV
    • MIME Type box:flv-application/octet-stream
  6. Click OK.
  7. Restart the World Wide Web Publishing service.


nGFX

Sunday, January 14, 2007 3:57:00 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |  Trackback