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
 Thursday, October 30, 2008
Another quick break down of an effect in 651.

651_vectorBallGrab2.jpg

On paper this is quite impressive, 500 3D objects with depth of field running over a skybox. In real life, it's not exactly rocket science.

Although we used Papervision in 651, we didn't for the effect itself ( Just for the skybox, which uses the background from Orbs as it's texture ).

We start by creating the 3D objects and giving them random x,y,z coords ( For the very best introduction to 3D movement in Flash check these excellent tuts on Kirupa, everything you need for an effect like this is there ).

Right, we're spinning some objects around in 3D space, what about the depth sorting ?
This is just between us right ? It's not going any further ?
Ok then. We just don't bother. It's a very old trick ( I remember doing it back on the Amiga ). If the vector bobs are translucent enough, it's pretty hard to tell if they're not being z-sorted correctly. Looking at that grab above quickly I can't see anything too wrong in terms of sorting, and even if there was, the bobs would all have moved in the demo before you really notice it.
By dropping the sorting we've got more cpu power for more objects, and the more the merrier.

Next up, depth of field. Such a buzzy thing in Flash atm. We all know it's only a blur filter, but depth of field sounds so much cooler. To avoid an extra hit we pre-calculate each blur frame, we're not blurring in real time. Or even using the blur filter itself as it's all done in PaintShop Pro ( And each frame is imported into Flash ).
Each bob is a movieclip ( Which feels very old school already ) and when we're calculating the scale ( Based on it's z property, ie how close or far away from the camera it is ) we can also gotoAndStop() to the correct level of bluriness.

So to recap, the 3D code can be found in some great tuts, there's no z sorting, the depth of field is gotoAndStop and the skybox was done in about 10 lines of code. Drop a nice image over the top of some scanlines and it's all done.

It may seem like I'm talking the effect down quite a bit. I'm not really, it looks sweet, I just don't like people acting like their code is l33t and they're so clever for doing it. Smoke and mirrors is as good a technique as clever code, and there's not always a need to mystify everything.

Squize.

Thursday, October 30, 2008 12:42:37 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |  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
 Monday, October 20, 2008
Monday, October 20, 2008 1:08:54 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [9]  |  Trackback
 Wednesday, October 08, 2008
What do the following things have in comon?

test.swf (5,87 KB)

goAway.swf (8,07 KB)

test.png

goAway.jpg


After my funny little episode with the hacked version of Law of the West I started wondering how to prevent that little pricks that can use an URL changer or decompiler to mess around with my stuff. Above you see what might be a solution. It will not stop someone who really, really wants to see your code from seeing it in the end but it will make it reasonably hard.

So how can you prevent that someone just grabs a decompiler, changes things and publish it back?

Maybe if there is no game inside the swf, at least not directly visible.

This is a screenshot of the library of the goAway.swf. Nice, eh?

Right now goAway is a neat little console app (so you can batch it), that takes an swf, optional a textfile full of vars (so you can check them later from the game itself) and spits out a png.

This can be included in another swf (to be released) and is unpacked after loading - and viola you have your swf again, though it'll be like a loaded swf, so you loose your "root".

There is a lot more security related portential behind this:
- load the png from a server instead of including it.
- use a key to decrypt the png
- create the png on the fly on the server each time with a new key
- store multiple swfs/files in a single png to pack a multi file game into a single distributable swf without a lot of trouble
- and and and

The above swf is just a proof of concept and there is still alot to do on the goAway app in oder to make it useable (maybe a frontend, new features (like dynamic png dimensions, splitting into multiple png files for more security, different ways of reading writing the data into the png (byte order)) not to mention an AS3 class to easily handle the goAway png.

After all I'm quite pleased with the idea, as it makes it quite hard for script kids to mess around with a published flash file with the available tools. Making hacking a game just that little bit harder that is needed to seperate the users from the coders.

And of course SiCo will be used to obfuscate the goAway code ...

Ha!

nGFX

Wednesday, October 08, 2008 11:14:04 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [5]  |  Trackback
 Monday, September 15, 2008
I had an idea last week on how to code a voxel landscape, so a couple of nights after work later, here's my little...

Trip to Mars

( No preloader, but it's only just under 400k )

Just to caveat it, it's not the quickest routine ever and may chug if you've got a slower machine, this is more looks rather than speed.

I'm really pleased with how it turned out. It uses a real image of Mars for it's height map, so it's a lot more rocky than the usual perlin noise generated maps.

That's about it really. I was going to save it up for a demo I have in mind, but I've got no time for it for the foreseeable future, and if I do re-use it as part of a bigger production I've got some ideas to improve it anyway.

Squize.

Monday, September 15, 2008 11:59:27 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [9]  |  Trackback
 Tuesday, September 09, 2008
I needed a bit of a break from all things gamey this evening, so I looked back over my old plasma source.

By stripping the maths down to the bare minimum and using a for...each loop along with other bits and bobs ( Double buffering the screen helped too ) I managed to increase the fps from the 31/32 mark to 42/43.
Pretty sweet.

I thought I could either post it like that, smug in the knowledge that I've speeded up a pretty intensive routine by ( In real terms ) quite a lot, or do something slightly different.

I opted for a bit of a play, and was really surprised ( And pleased ) to see you can attach the same bitmap to multiple sprites and it still updates. From there it was a no brainer what to do with it. In real terms this is plotting less pixels than the plasma effect ( That was 150x150 doubled ), this is a 120x120, but it's a much bigger effect in terms of screen size.

Kaleidoscope

Squize.


Tuesday, September 09, 2008 8:22:17 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Saturday, January 26, 2008
So I had a long night yesterday, finishing off some unloved project that I've been delaying for some time now and as some sort of personal reward for being so brave I played a bit with my "play media on the wii" idea...

I had written the service for getting drives, dirs and files a few days ago (don't try this on real a webserver :) ), so I *just* had to do some flash frontend ...

Oh well, I should have known better ....

To give you a basic idea of what I was thinking of, here's a (sized) image:

wiicenter_00.jpg
(icons are just temporary)

I thought that fiddling with scrollbars would be a no-go on the Wii, so I came up with the idea of a dragable "canvas".
So you can click on a drive, which opens the folder list for it, clicking on a folder... you get the point.

Now here starts the tricky part ...
Once I had the drive list done, I noticed that it lists floppy disks and CD/DVD drives, too. I either had to give the drive type when getting the list from the service or don't show them (in both cases this means to mess with the service's code - that for quick and easy).
The next thing I noticed that the service currently doesn't care if a directory is hidden or not (and if it is hidden, I might need to know in my flash file).

Well, it doesn't end there (of course not), because I might need to know some more about the files inside a folder (size is obvious) - oh and what is if there are some more files/folders (say you have a folder with 1000 images or mp3s) ...

That clearly killed my idea of a quick solution, I'll have to heavily modify the service (although I had to do that anyway) and there are some quite important things to consider for the swf (I may have to drop the drag idea).

We will see.

nGFX


Saturday, January 26, 2008 12:35:59 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, January 22, 2008
It's so long ago I've posted something that it's untrue. It may be because there was nothing much to say during that time, that is projects not really game related or so absurdly NDA protected that even to mention the general direction would be ... well expensive.

You surely remember my last (!) post where I have a bit of a rant about the media capabilities of the Wii (still no games on it for me, though). Right now this neat piece of hardware sits beneath the TV left of it's bigger and way more often used brother the xbox 360. All I do with it (you remember: playing Wii Sports after a lot of coding) is using it as TV based web browser.

Webbrowser ... well that brought the idea.

(OK, that and the fact that we had some friends here and wanted to look at some photos from the last party. One of them (a "no gamer") asked if there would be some music to play along and I had to admit that it's not working anymore (due to the glorious photo chanel update))

So inspired be the fact that I got the 360 playing my mp3/fotos/movies from my pc in no time, I started to set up a small test environment webpage on my local IIS to see if I could use the browser to browse my pc's hdd. And of course it works.

So I wrapped the output with some XML and viola I had a flash 7 swf that I could use to browse the directories on my pc. Well done.

The only drawback atm is the fact that there has to be a webserver running ... I guess you can't convince most people to install an IIS on their PC to get some media on the Wii. After a few minutes of thinking it came to me that I could write my own - or better integrate cassini (an open source micro webserver) - to host the services for the Wii ...

Well, let's see where that leads to ...

nGFX

[edit] just found this while hunting for informations about the Wii browser flashplayer ...
http://my.opera.com/[..]flash-7-and-not-8-or-9

Tuesday, January 22, 2008 10:16:10 AM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Wednesday, October 03, 2007
But I found a sweet article about making a textured tunnel, and before I knew it this bad boy was up and running...

Tunnel.swf (16.1 KB)

( No displacement maps, just pure pixel plotting. as3, I'm loving you )

I've really got an urge to do a full blown demo. I know I've got far too much on, but it's gnawing away at me.

Squize.
Wednesday, October 03, 2007 2:00:37 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, August 18, 2007
So after Squize was boring us with that grid, I thought it's time to give AS3 a go (finally).

While diving into the "new" AS version I also tried a new editor, I use(d) se|py for AS2, but felt the need to try something new editor wise, too.

I had a look at SharpStyle Neutron, a coding plugin for Visual Studio 2005 (imho one of the best coding environments), but as it's AS2 only (the current beta is able to handle AS3 it seems) so while it's great for AS2 it didn't help me on my current task ...

Another Editor I wanted to give a go was FlashDevelop. I instantly fell in love with the current 3.0.0 beta build. It feels like Visual Studio, it's fast and has some niffty, helpfull features.

So I did what I always do in a new language, I coded a 3d formular plotter, the idea reaches back to the good old c64 days, though, it took a whole night to render a way smaler version.

Anyway this is what I came up with during my first 2 hours of AS3:
plotter.swf (1,31 KB)

It's not that impressive, but it's fast (just used an onEnterFrame to show the plotting).

<olli/>
Saturday, August 18, 2007 2:15:47 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, August 13, 2007
Well I carried on working on the GWars effect last night, and discovered quite a few things.

The example from yesterday used a raster line plotter, but I tried it with the Flash drawing API ( Which uses Flash's vector plotter ) and it crapped all over it in terms of speed. I was surprised but I guess it's 'cause the dAPI works on a "hardware" level.

Next up was to look at Geometry Wars itself, where I realised that the grid was made up of a load of dots rather than lines. Back to the code, I used the dashTo prototype ( An example of that can be seen here ) and got a nasty drop in speed. No shock there really. Then it dawned on me that the raster line drawer could be kinda handy here, after all it's just a loop and some setPixels, if we're skipping pixels to make a dotted line then it'll reduce the length of the loop.

Sweet, ran a lot quicker.

Next up was a bit of a lucky one. I had a bitmap which I copied the grid to every couple of frames and ran a ColorMatrixFilter on it to fade it down ( By reducing the alpha every frame ), and where I was putting a surround on the screen and positioning things I screwed up the alignment of this bitmap, so I could see the lines slightly offset. It didn't take long to align it so it was offset by half a grid position on the x/y, hey presto, twice as many lines and for no more hit than it was running at anyway.

Time to drop a player sprite in there ( My very first as3 one, I imagine there will be more ). I really liked the control system in neon2, where holding ctrl down stopped the player ship so you could just rotate and shoot, and as3 just gave it to me for free.
When using a MouseEvent.MOUSE_DOWN event listener, the event which is called has an arg passed to it. This arg has all types of interesting goodies in it, one of which is a boolean ctrlKey flag. So adding the keyboard control I wanted took about 3 lines, and from a cpu point of view it's a freebie ( Ok, at the hardware level Flash is scanning the key, but it does anyway on a MOUSE_DOWN event so it's not like I'm polling the keys seperately ).

Want to see it ? Yeah you do.

GWars_v2.swf (37.69 KB)

Squize.
Monday, August 13, 2007 11:28:02 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, August 12, 2007
Inspired by this thread at FK games I decided a nice little break from mansion would be in order and started playing with a geometry wars style grid.

It's still not a 100% right, and I think to get much more speed out of it I'm going to have to really rethink it, but it does look pretty cool.

A lot of the actual clever stuff which is beyond me was taken for a example at the always astounding liquid journey site. I also used bytearray.org's raster based line plotter, which I tweaked slightly to try and get a few more ms out of it ( Code for the tweak is here )
public static function quickLine(bmp:BitmapData,x0:int,y0:int,x1:int,y1:int,c:Number):void{
    var i:int;
    var xinc:int;
    var yinc:int;
    var cumul:int;
    var x:int = x0;
    var y:int = y0;
    var dx:int= x1 - x0;
    var dy:int= y1 - y0;
    xinc = ( dx > 0 ) ? 1 : -1;
    yinc = ( dy > 0 ) ? 1 : -1;
    dx = (dx ^ (dx >> 31)) - (dx >> 31);            //Math.abs
    dy = (dy ^ (dy >> 31)) - (dy >> 31);
    bmp.setPixel32(x,y,c);

//Test for a straight vertical line
    if(dx==0){
          for ( i = 1 ; i <= dy ; i++ ){
            y += yinc;
            bmp.setPixel32(x,y,c);
        }
        return;
    }
    if(dy==0){
          for ( i = 1 ; i <= dx ; i++ ){
              x += xinc ;
            bmp.setPixel32(x,y,c);
        }
        return;
    }
   
    if ( dx > dy ){
        cumul = dx >> 1;
          for ( i = 1 ; i <= dx ; i++ ){
            x += xinc;
            cumul += dy;
            if (cumul >= dx){
                  cumul -= dx;
                  y += yinc;
            }
            bmp.setPixel32(x,y,c);
        }
    }else{
        cumul = dy >> 1;
          for ( i = 1 ; i <= dy ; i++ ){
            y += yinc;
            cumul += dx;
            if ( cumul >= dy ){
                  cumul -= dy;
                  x += xinc ;
            }
            bmp.setPixel32(x,y,c);
        }
    }
}
And that's about it really. I'm hoping to play with this some more next time I get chance and hopefully make a homage to a certain popular shoot'em up.

GWars.swf (7 KB)

Squize.
Sunday, August 12, 2007 2:16:01 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Sunday, June 24, 2007
This is it, the last demo effect I'm going to be doing in as3. There are of course more I'd like to do ( Using a plasma as a texture would be a neat one that springs to mind ) but I guess I should be more productive in an actual game kind of way with my free time, rather than pointless eye candy.

Anyway, enjoy yet another cube variation.

DotVectors.swf (32.28 KB)

Squize.
Sunday, June 24, 2007 6:03:31 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Thursday, June 21, 2007
I know I owe a couple of posts about the GOL games, but I've kinda fallen behind.

To get out of trouble, here look at this

Polygons.swf (147 KB)

Phew, that should buy me some time until I can pull my finger out and take some nice grabs.

Squize.
Thursday, June 21, 2007 3:57:19 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, June 11, 2007
Still trying to get my head around as3, it's a saucy little minx alright.

Anyway, he's yet another old school demo effect, and another one I never managed to get working on the Amiga at the time ( Flash just seems to be an outlet for my past failures as a coder ).

Plasma.swf (5.47 KB)

Guess a bit of texture mapping should be next to keep with this theme.

( For a lot more demo style eye-candy check the experiments cat., and to see them all shoved together and wrapped up with plenty of love, check out 651 )

Squize.
Monday, June 11, 2007 2:47:12 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [3]  |  Trackback
 Monday, May 28, 2007
I've had a bit of down time since Friday, so I thought I should finally look into AS3.

I've heard lot's of comments from fellow game devs. That it's a steep learning curve. Being kinda cock sure I thought "It can't be that bad".

Oh silly silly me.

I remember hating AS2 when I crossed over to that late last year, and loving it now, so I know that AS3 is just going to be the same. That nasty month or two of "If I could do this in AS2 it'd have been done 3 hours ago", and that feeling of going from being pretty good at something to absolute lamer. Never nice.

Anyway the fruits of my labour are below. It's just a re-working of my infinite bobs effect I did a little time ago ( In as1. In an hour ). At least I've managed to convert my fps counter ( Although ensuring it stays on top of all the other mcs / sprites / displayObjects / whatever the hell they're called now, is still a bit beyond me ).
No preloader, as that seems to be a can of worms, but it's less than 13k so it's not an issue with this. Also it's not really a clever clever AS3 speed test, the whole point of the original code was to show you can still do funky things in as1 ( It was a slight backlash against what seemed like everyone at that time acting like as3 was the second coming ).

InfiniteBobs.swf (12.18 KB)

Squize.
Sunday, May 27, 2007 11:13:47 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [1]  |  Trackback