Wednesday, June 24, 2009
After a good while of non-techy pimpings I decided to go the x++ route and describe the process of diving into a new game ...

(CE is again on hold due to some gameplay issues I found during testplays - oh well)

There is no name to the game yet, but I can say as much as it will feature random dynamic level creation (as used in Diablo 1 for example), sci-fi themed, using RPG elements and use Unity (though the levels created will look quite different to Diablo, but the idea is the same).
I want to have random levels because that would add to the replay value of the game. I want a single game to last between 15 and 45 minutes. You should be able to start playing and kill the end-boss in that time. After that you should be able just play again, but with different set of maps ...

But to get things rolling a lot quicker I wanted to rapid prototype my ideas using flash/AS3 and then port it to c#.
The reason for this is quite simple: output. In order to "see" what the level will look like without having to worry about how to display them (ie. place 3d walls, create the assets). With using flash i can just grab the data from the generator classes and use the drawing api to quickly throw out a few lines to show the generated data.

Let's dive straight in.

Part 1 - part 1: To cell or to tile ... and is there anything we need before that?

Before I started I thought that it would be nice to move between maps (in case you thought you forgot something), to do so there needs to be a way to store the maps ... I thought of 2 methods:
a) store all visited maps
b) make them reproduceable

I prefer the later one.

So instead of using some built in random number generator I decided to use my "own" that takes a seed and the produces the same set of random numbers when using that seed - perfect.
I found some old AS1 source of some older rnd gen that I could have ported but a quick search showed that there are some more powerfull ones. After bit of research I decided to go with the Mersenne Twister algorithm. As I was too lazy to see if there was an AS3 port, I wrote my own implementation, though you could use any rnd method you want.

The next one was a bit tricky: cell based or tile based?
Tiles are easy to use and to handle, but they are limited to a single spot and mostly do only have a single "state", ie. you can walk on them or not. This might be ok in most cases but for what I have in mind they are too limited.

A cell in my case is a tile with 4 walls (north, east, south and west), if all 4 walls are set, the cell is "closed" ie. a solid rock in a clasical dungeon. The cell also stors a single integer value (so based on it's useage I could store an index in it.
Here is the code for the cell:

package com.gamingyourway.Dungeon {
    
    /**
     * Cell datatype
     * @version 2009 06 24
     * @author nGFX
     */

    public class Cell {
        
        public static const WALL:int = 0;
        public static const OPEN:int = 1;
                
        private var _aWall:Array;    // array of values ... 0=empty ...
        private var _iValue:int;    // stores a single value, ie. room num
        private var _bVisited:Boolean;    // has cell been visited
        private var _bCorridor:Boolean;    // is cell a corridor
        
        
        public function get aWall ():Array { return this._aWall; }
        public function set aWall (value:Array):void { this._aWall = value; }
        
        public function get iValue ():int { return this._iValue; }
        public function set iValue (value:int):void { this._iValue = value; }
        
        public function get bVisited ():Boolean { return this._bVisited; }
        public function set bVisited (value:Boolean):void { this._bVisited = value; }
        
        public function get bCorridor ():Boolean { return this._bCorridor; }
        public function set bCorridor (value:Boolean):void { this._bCorridor = value; }
        
        public function get wallCount ():int {
            
            var i:uint;
            var iCount:int = 0;
            
            for (i = 0; i < this._aWall.length; i++) {
                if (this._aWall[i] == 0) iCount++;
            }
            
            return iCount;
            
        }
        
        public function get isDeadEnd ():Boolean { return (this.wallCount == 3); }
        public function get isUnused ():Boolean { return (this.wallCount == 4); }
        
        /**
         * Creates a new empty (ie. all walls set) cells
         * @param    iValue    used to stor a single bit of info, ie. room num
         */

        public function Cell (iValue:int = 0) {
        
            this._aWall = [0, 0, 0, 0];
            this._iValue = iValue;
            this._bVisited = false;
            this._bCorridor = false;
            
        }
        
        /**
         * sets a single wall
         * @param    iDir    Direction of the wall
         * @param    iWall    value of the wall, 0 is a solid wall, any other value makes it "open"
         */

        public function setWall (iDir:int, iWall:int = 0):void {
            
            this._aWall[iDir] = iWall;
            
        }
        
        /**
         * return the value if the wall in iDIr
         * @param    iDir    direction of the wall to get
         * @return    value of the wall
         */

        public function getWall (iDir:int):uint {
            
            return this._aWall[iDir];
            
        }
        
        /**
         * shortcut for testing if there is a closed wall in iDir
         * @param    iDir    direction to test
         * @return    true if there is a wall
         */

        public function hasWall (iDir:int):Boolean {
            
            return (this._aWall[iDir] == 0);
            
        }
        
        /**
         * if the cell is a dead end, return the direction of the opening
         * @return    the direction of the opening
         */

        public function getDeadEndDir ():int {
            
            var iReturn:int = -1; // not a dead end
            
            if (isDeadEnd) {
                
                if (this._aWall[Dir.NORTH] != 0) iReturn = Dir.NORTH;
                if (this._aWall[Dir.EAST] != 0) iReturn = Dir.EAST;
                if (this._aWall[Dir.SOUTH] != 0) iReturn = Dir.SOUTH;
                if (this._aWall[Dir.WEST] != 0) iReturn = Dir.WEST;
                
            }
            
            return iReturn;
            
        }
        
        /**
         * returns a string representation of the cell
         * @return    a string for the falls of this cell
         */

        public function toString ():String {
            
            var i:uint;
            var strReturn:String = "";
            
            for (i = 0; i < this._aWall.length; i++) {
                strReturn += this._aWall[i].toString();
            }
            
            return strReturn;
            
        }
        
        
    }
    
}


Part 1 - part 2 - Storage and creation

To store the maps generated I wrote a simple Mapa datatype, it'll store a 2d array of cells along with some very basic methods to deal with the data.
The map type also stores width and height in an rectangle, to have an easy way to check if a point lies within the boundaries of the map.
Aditional methods so far:

hasCellInDir (pPos:Point, iDir:uint):Boolean
getNextPos (pPos:Point, iDir:uint):Point
getSurroundingCells (pPos:Point, bUsed:Boolean = false):Array


To create a map (let's call it dungeon for the sake of easiness) I didn't include the methods need to create a dungeon in the map class, instead I wrote a DungeonGenerator class, that returns a filled map class. This way I can mess around with the creation process without messing with the map class.

Part 1 - part 3 - Let's start with a simple maze ...

The most simple representation of a dungeon I can think of is a maze. Mazes are incredibly easy to create and they work oh so well with cells.

The walkthrough to create a maze:
1. create a map of "solid" cells
2. pick a random solid cell as starting point
3. get surrounding solid cells and pick a random one
4. knock the walls between these cells, store the "old" cell in a stack for later use
5. use the cell picked in 3 as new starting point and start over
6. if the current cell has no solid neighbours, pop one from the stack
7. repeat until there are no more solid cells


Easy, eh?

package com.gamingyourway.Dungeon {
    import de.drygoods.Random.MersenneTwister;
    import flash.geom.Point;
    
    /**
     * Dungeon generator
     * @version 2009 06 24
     * @author nGFX
     */
    public class DungeonGenerator {
        
        private var _Dungeon:Dungeon;
        private var _rnd:MersenneTwister;
        
        public function DungeonGenerator(iWidth:int, iHeight:int) {
            
            this._Dungeon = new Dungeon(iWidth, iHeight);
            
            this._rnd = MersenneTwister.getInstance();
            
        }
        
        public function createMaze (iDirChange:int = 100):Dungeon {
            
            var aCellStack:Array = new Array();
            var aCellNeighbors:Array;
            
            var iTotalCells:int = this._Dungeon.iWidth * this._Dungeon.iHeight;
            var iCellCount:int = 1;
            var iRndCell:int;
            var iRndDir:int;
            
            var pCurrentCell:Point = new Point(this._rnd.Range(0, this._Dungeon.iWidth -1), this._rnd.Range(0, this._Dungeon.iHeight -1));
            var pPopCell:Point;
            
            while (iCellCount < iTotalCells) {
                
                // get neighbor cells ...
                aCellNeighbors = this._Dungeon.getSurroundingCells(pCurrentCell);
                
                // set the cell
                if (aCellNeighbors.length != 0) {
                    
                    iRndCell = this._rnd.Range(0, (aCellNeighbors.length - 1));
                    iRndDir = Dir.getDirFromPoint(pCurrentCell, aCellNeighbors[iRndCell]);
                    
                    // remove walls
                    this._Dungeon.cell(pCurrentCell).setWall (iRndDir, 1);
                    this._Dungeon.cell(aCellNeighbors[iRndCell]).setWall(Dir.getOppositeDir(iRndDir), 1);
                    
                    // store for later use ...
                    aCellStack.push(new Point(pCurrentCell.x, pCurrentCell.y));
                    pCurrentCell = new Point(aCellNeighbors[iRndCell].x, aCellNeighbors[iRndCell].y);
                    
                    iCellCount++;
                } else {
                    pPopCell = aCellStack.pop();
                    pCurrentCell = new Point(pPopCell.x, pPopCell.y);
                }
                
            } // while
            
            
            return this._Dungeon;
            
        }
        
    }
    
}


The code of the dungeon generator ... for now only with the maze creation in it.
Note that the variable iDirChange is currently not used, but I'll go over it in the 2nd part of this article.

I think that is enough for today, you can see the result (and from the upcoming articles, too) Random Dynamic Level Creation Test page (or here).

See you next time when I add some direction modifications and take care of dead ends ...

nGFX


Wednesday, June 24, 2009 3:02:34 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [7]  |  Trackback
 Thursday, June 18, 2009
They've been spoken about for a while, even been available in various forms already, but now a couple of big hitters are entering the market.

In the blue corner, GamerSafe, FGL's pretty all encompassing attempt to cover off not just M-Ts but other nice things too.

In the red corner, Mochi and their coins.

Both have their advantages, and both seem to be well thought out and planned ( Although there's not a wealth of info about either yet, early days and all that ).
Is this going to be a VHS vs BetaMax thing, or can the market cope with both ?

This is just a "Look, new things" post. We're really not in a position to review either, or get dragged into a debate about the rights and wrongs of M-T's, and the effect that could have on the market ( Either good or bad ).

We have been discussing them recently and they do have a huge amount of possibilities, but we think they're going to need to be more than a "Buy a new hat for your avatar" style buy throughs, so with what we'd like to do would take time and money, and no one yet knows if there's a market for that ( Or if there is, which system is going to be the BluRay and which the HD-DVD ) ?

Squize.

Thursday, June 18, 2009 4:31:52 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [14]  |  Trackback
 Wednesday, June 17, 2009
Perhaps 'cause it's late, and I'm tired, and I'm coming down from quite a hellish crunch ( All the games got there in time, and the client is pleased. Just thought I should share the good news along with the moans and gripes ), but something is bugging me.

Mike Chambers, well known Flash community facing guy at Adobe, has posted "What new game APIs do you want in the Flash Player ?".

Fantastic!

Why do I feel the need to be churlish about this, I mean it's great news, isn't it ? A chance to air our views to someone whose in a position to push forward ideas to the roadmap.

"I have been learning some game development lately, and building my first game... I think game development and deployment are some of the real strengths of the Flash player, but ones which we haven’t specifically focused on in a while... While working on my game, there were a couple of things I needed to do where additional player APIs could have made the development easier... So, what APIs would you like to see that would make game development easier."

( That's the gist of the post, but please take a minute to read it all ).

Personally, I'd like to see all the things that so many game developers have been asking for since Flash 5. Mike mentions how handy it would be to have a built in pixel perfect hitTest. Surely everyone one reading this right now has been thinking that for years ? Has no one ever requested that feature ?

Why have all the feature requests fallen on deaf ears before ? Flash has been geared towards RIA's for years, with a recent glance at 3D as Away3D et al have helped fill in a short fall with the player, along with the huge ( And really successful ) push to own web video.

But games have been left out in the cold. They're treated like they're almost a happy side effect of the Flash player, that it's not really a real use of Flash ( Noticed that very few of the really high profile Flash developers make games ? Some of them touch on game related mechanics, and do it really well, but actual complete games are very few and far between. I'm sure if they did they would be vocal about the shortfalls in the API and help to have forced a change sooner. Sound got a kick up the arse using a similar approach ).
And yet, GameJacket had a stat that 28% of internet traffic was Flash games ( I can't provide a link for obvious reasons ). The Flash Forwards have a game category. Until a couple of years ago BAFTA did too ( That's now being merged with console games, and in all fairness I can't see Desktop Tower Defence giving Call of Duty a run for it's money ). Millions of people play Flash games, and talk about them, every day
There is a knowledge and interest of Flash gaming, with huge budgets for them, outside of the "Suck and Fuck Street Racing"s.

So why has it taken until now for it to be recognised by Adobe ? Would it really have taken so much effort to not package yet another fucking scroll bar component and give us a hi-score table component just once ? I know there's an excellent one from Mochi, but we're talking first party support here.

Yes to some extent I am being churlish. In effect I'm bitching about Adobe looking to make all our jobs that little bit better, it's just that does it really only take one employee at Adobe to notice the shortfall for things to happen ?

( And yes before you ask I am a bit of a hypocrite as I've never filled in a feature list request for Flash. Maybe all of us who haven't have just got ourselves to blame that we're going to have to wait 'til F11 before getting the sugar ).

Squize.

Wednesday, June 17, 2009 12:21:54 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [12]  |  Trackback
 Monday, June 15, 2009
Nothing really new so here's at least something to look at ...

After a good deal of non game related stuff (some WBTs, a lot of non game flash stuff) I finally found the time (and motivation) to continue on Calisto Eclipse my current private joy project, although I must admit that the joy part has left me untill just recently.

There was some oh so boring serverside stuff to do, plus some database layout and it's still not done at all, because I really wanted to have a working game at some point.
Finally the action mode gameplay is working 100%, I just need to fill in the 150+ levels in order to provide at least some sort of progress (just fiddling with times and percentages for a certain tile type, so no real magic behind this).

Story mode needs yet to be "coded", although it just uses things I've done already for the action mode (with some minor variations, so I can create things like "build x structures with size y."

Today was paint the medal day so I thought it might also be a good thing to give you a quick glance at them:
ce_medals.jpg

There are 12 of them all nicely linked to myw (the other thing that dragged me down a good deal).

I guess that's me for now again, but I think it'll be nice to add an ingame screenie too, so here it is:
ce_ingame_action_00.jpg
(scaled down)

Lets just hope I get that done before I die ...

nGFX

 | 
Monday, June 15, 2009 4:10:14 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, June 14, 2009
We've become a bit lazy here just linking to other peoples stuff and pimping iPhone games. It's partly because we're in the usual state of NDA-ness that means we can't talk about a lot of things ( Such as the great, but very crunch heavy, project we're doing for National Geographic right now ) and partly 'cause all our friends are doing great things which deseve a pimp.

So this is going to be the last one for a while, but it's a great one to go out on. Our friends over at urbaniacs have released their first iPhone game. Want to hear more ? Yeah you sure do.

This is a port of Wedgie Toss 2 ( You can play it on their site right now ), where apparently 14 million wedgie's have been snapped out.

colbert2.png


Look at Stephen Colbert there, oh Stephen how your faux right wing views make me giggle. But I'm going to pick an angle and twang your pants on this fun and yet surprisingly cheap iPhone game ( £0.59, which I guess is $0.99 to the 65% of our readers. See how I tie all our posts together ? When it's done it's all going to make sense, a novel in the form of a blog, with a twist at the end which will blow you away ) which is available here.
Also look where I left a tiny part of the edge of the logo at the top left on that cropped image which I'm too lazy to sort out, but is really bugging me already. How can I take my mind off that, short of playing the game itself ? Another grab should do it,

colbert.png

Look at him go! That's a grace you don't see very often, although you could see it any time if you buy the game, for a tiny $0.99 right here.

Two great games in a week or so, it's never been a better time to buy an iPhone. Well, not right now 'cause the new ones coming out, and let's face it you'll be pissed if you just get the current one.

And on that note, I think I've strained my pimp muscle, so you young 'uns go play whilst I get back to work.

Squize.

Sunday, June 14, 2009 1:18:53 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, June 12, 2009
More a case of doing-anything-rather-than-work-on-the-current-project I thought I'd have a quick glance at our stats, see where we are in the grand scheme of things ( Our Alexa rank has had a little bump recently, we're back to a more healthy #324,797 ).

In terms of countries visiting us, our friends from across the pond are number #1,

United States,
hits: 150,381
sexy visitors: 25,793
percentage out of everyone coming here ( And weeping ):  65.56%

The following places were a bit of a surprise though,

2     Republic of Korea     10,606    3,795     9.65%
3     France                   10,864    3,735     9.49%    
4     China                     10,313    1,987     5.05%    
5     Russian Federation   4,518      1,691     4.30%

I didn't realise there was such a passion for Flash combined with reading a blog which doesn't ever actually say anything at all, in some of those countries. It may be a little egotistical ( Me ? ) but I thought Germany and the UK would rank higher.

So if your are visiting here from one of those top 5 countries, it'd be nice if you could say hi in the comments. Actually, it'd be better if you taught us a swear word in your respective language, be fair, you must have picked up quite a few English ones here.

Squize.

Friday, June 12, 2009 7:55:17 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [7]  |  Trackback
 Thursday, June 11, 2009
Rare we do two posts in one day, but this is breaking news and will affect quite a few people who visit us here.

GameJacket closes. Real pity, not just 'cause we've lost a couple of quid, but we were really early adopters of the system and there were a lot of good people involved in it.

We've not long since received an email officially announcing that GJ ceased trading yesterday, and that they'll pass on more info soon.

Even if you never put a game on their system, it's quite a blow for Flash dev in general, as it's another outlet gone.

On a slightly self-centric note, it means our games using the system are screwed. We'll try and rip the GJ code out and reload them as soon as we can.

Squize.

Thursday, June 11, 2009 2:57:34 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [2]  |  Trackback
It's finally occurred to me that there must be some blogs out there that are silly enough to link to us, but because we're so wrapped up in ourselves, we're not aware of them.

If you do link to us ( Albeit out of pity ) and we've not linked back, do us a favour and let us know via the comments so we can redress the balance and keep the whole internet ticking over the way it's meant to be.

Cheers,

Squize.

Thursday, June 11, 2009 11:09:58 AM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [8]  |  Trackback
 Tuesday, June 09, 2009
Yet another post where we just talk about someone else's work rather than our own. It's just so much easier.

This time it's our mate Mark, and his first steps into the world of iphone and all the gold that goes with that. It's a port of his hit game Particle Pong.





Now to be honest, he doesn't really need the money. He pays someone to burn the cash that he can't fit in the bank vault, but if you have an iphone and want a great game, then he's all but giving it away ( Guilt I think ).

Interested ? Yeah I knew it, I could tell by the way you were reading this. K, it's as simple as putting your mouse pointer on this link and clicking it. It's really that simple to have a pong game with an orgy of particles running on your swanky iphone.

Squize.

Tuesday, June 09, 2009 9:15:55 PM (W. Europe Daylight Time, UTC+02:00)  #    Disclaimer  |  Comments [2]  |  Trackback