Gaming Your Way

May contain nuts.

Air today, gone...

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.

How to really *#$&! things up in a flash game project

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.

Distance Based Broadphase

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.

Faster atan2

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.

Pythagorean Theorem, how quick are you ?

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.

Quick AS3 bug / fix - invalid data

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.

as3 preloader in Flex

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.

Nero did not only burn Rome - he busted Vista as well ...

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

Little as3 speed test

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.

 

 

Slopes in a tile based game. The dirty way.

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.