Game Development (June 2013)

Well it doesn’t really feel like there’s been huge leaps & bounds in anything to see over the last month but the basis of some pretty important pieces have been put into place website link.

Please note that the video is also zoomed out to what it will be, this is purely to show how the tiles are working.

The first noticeable change will be the buildings but they’re merely placeholders for something better which is why they look pretty flakey. They’re currently created based on individual tiles which won’t really work as a whole as they’re going to need to know which building type they’re part of and which tile of that building. There’s also the issue where buildings at the edge of a city section have a wall through the middle.

The next thing to notice would be the enemies are back, even if they are very basic in their current state. At present there’s a set limit of five which will randomly spawn on the level load and respawn when they’re knocked off the map. They move very linearly, as in a randomly picked direction and they’ll travel in that direction non-stop unless you get close enough for them to follow you. They can also be targeted and attacked by the player, though this is a very primitive process as it currently stands.

What’s Next?
Like I mentioned earlier, the buildings really could do with a lot of work but at this point I’m thinking that the basics of different building types would be good to get in place. Another important item on the todo list is obstacles and let the player walk through walls =)

A new perspective

After spending an excessive amount of free time trying to get 3D picking to work without any success I decided to go back and revisit the original plan.

When I first started out planning this game I was originally torn between two very different directions. Firstly there was a more old-school type RPG style using point & click on an isometric field. The other was more of an action RPG where the player would be in direct control of their character. Originally I was leaning towards the isometric as I thought it would work better on touch screen devices and there were certain aspects of gameplay could be integrated. For example, I wanted ammunition to be relatively scarce and for the player to weigh up using valuable ammo from a safe distance or going in for a melee attack. I think this idea works better in a classic RPG style due to weapon familiarity could then be added to provide better accuracy and damage.

Although I preferred isometric and thought it would work better, I chose to go with a top down approach purely out of laziness which was probably a bad step. I knew that if I used a top down setup then it would allow me to adopt a GTA style of sprites where only one direction would be needed and rotated. The isometric view would however need a different graphic for each direction.

During working on the isometric tiles I revisited the AS3 graphics API which I’ve not really looked at much for the last few years and there are a few neat feature which have been added in. One which I’m now using is the ability to use texture triangulation on the 2D canvas in the same way you would in the 3D stage. This means that I can reuse my road texture which could create all road tiles from just one square image.

You may be wondering what’s going on with the tiles, the lime green & white set is the old tiles which was loading in each city block as it was in the 3D version. The dark green tiles is using a new technique which consists on only 100 tiles which dynamically update their positions and tile types based on the player’s position. Doing it in this manner should be more memory friendly as there will be less creating / removing and fewer tiles overall.

Random City Generator Code

I’ve been meaning to release the code for my random city generator for a little while now but just hadn’t got round to it…. UNTIL NOW!

Now I’m not saying this is the best or most efficient method for doing this, this is just the method I’ve created. Below is an interactive version of the generator, click on it to create a new city.

[swf:https://defenestrate.me/wp-content/uploads/2013/04/City.swf 201 201]

As you can see, far from perfect but it does the job. There’s still the issue of two lanes of road running next to each other but this is something I can live with

City.as

package
{

	import city.Tile;

	import flash.display.Sprite;

	public class City extends Sprite
	{
		// Array of all the tiles
		private var _tiles:Array = new Array();
		// Visual display of the map
		private var _map:Sprite = new Sprite;

		// Width of the map to create
		private var _width:int = 50;
		// Height of the map
		private var _height:int = 50;

		// minimum length of a building
		private var _buildingMin:int = 5;
		// maximum length of a building
		private var _buildingMax:int = 10;

		// Exit points, can be predefined or randomly generated
		private var _exitPoints:Object = {
			//'north':new Array(10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190),
			'north':new Array(),
			'south':new Array(),
			'east':new Array(),
			'west':new Array()
		};

		private const SIDE_NORTH:int = 1;
		private const SIDE_SOUTH:int = 2;
		private const SIDE_EAST:int = 3;
		private const SIDE_WEST:int = 4;

		// The current side we're building up
		private var _activeSide:int;

		// The level away from the boundary
		private var _activeLevel:int = 0;

		// Array containing the buildings details
		private var _buildings:Array = new Array();

		public function City()
		{
			// Let's start from the top
			_activeSide = this.SIDE_NORTH

			addChild(_map);
			this.createMap();
			this.checkExits();
			this.process();

			// Just for cosmetics, move away from the window
			_map.x = 20;
			_map.y = 20;
		}

		private function createMap():void
		{
			// Creates a map of empty tiles based on the width / height
			for (var i:int = 0; i < this._height; i++) {
				this._tiles.push(new Array());
				for (var j:int = 0; j < this._width; j++) {
					var tile:Tile = new Tile();
					_map.addChild(tile);
					tile.x = j*4;
					tile.y = i*4;
					this._tiles&#91;i&#93;.push(tile);
				}
			}
		}

		// Checks to see if exits exist and randomly generates any missing
		private function checkExits():void
		{
			// Randomly generate the exits if they weren't predefined
			if (!this._exitPoints&#91;'north'&#93;) {
				this._exitPoints&#91;'north'&#93; = this.generateExits(this._width);
			}
			if (!this._exitPoints&#91;'south'&#93;) {
				this._exitPoints&#91;'south'&#93; = this.generateExits(this._width);
			}
			if (!this._exitPoints&#91;'east'&#93;) {
				this._exitPoints&#91;'east'&#93; = this.generateExits(this._height);
			}
			if (!this._exitPoints&#91;'west'&#93;) {
				this._exitPoints&#91;'west'&#93; = this.generateExits(this._height);
			}

			// Draw the exits on the map
			var i:int;
			for(i=0;i<this._exitPoints&#91;'north'&#93;.length;i++) {
				this._tiles&#91;0&#93;&#91;this._exitPoints&#91;'north'&#93;&#91;i&#93;&#93;.type = Tile.TYPE_ROAD;
			}
			for(i=0;i<this._exitPoints&#91;'south'&#93;.length;i++) {
				this._tiles&#91;this._height-1&#93;&#91;this._exitPoints&#91;'south'&#93;&#91;i&#93;&#93;.type = Tile.TYPE_ROAD;
			}
			for(i=0;i<this._exitPoints&#91;'east'&#93;.length;i++) {
				this._tiles&#91;this._exitPoints&#91;'east'&#93;&#91;i&#93;&#93;&#91;this._width-1&#93;.type = Tile.TYPE_ROAD;
			}
			for(i=0;i<this._exitPoints&#91;'west'&#93;.length;i++) {
				this._tiles&#91;this._exitPoints&#91;'west'&#93;&#91;i&#93;&#93;&#91;0&#93;.type = Tile.TYPE_ROAD;
			}

		}

		// Function to randomly generate the exits
		private function generateExits(length:int):Array
		{
			var arrReturn:Array = new Array();
			var tmpLoc:int = 0;
			while (tmpLoc < length) {
				tmpLoc += Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));
				if (tmpLoc < length-3) { 					arrReturn.push(tmpLoc); 				} 			} 			return arrReturn; 		} 		 		 		 		// Function to rotate around the boundary on an inwards spiral 		private function process():void 		{ 			var count:int = 4; 			while (count > 0) {
				// Scan the row and create buildings if needed
				this.scanSide();

				// Switch the active side once we reach the edge
				switch (this._activeSide) {
					case SIDE_NORTH:
						this._activeSide = SIDE_EAST;
						break;
					case SIDE_EAST:
						this._activeSide = SIDE_SOUTH;
						break;
					case SIDE_SOUTH:
						this._activeSide = SIDE_WEST;
						break;
					case SIDE_WEST:
						this._activeSide = SIDE_NORTH;
						break;
				}
				count--;

				// If we've covered all four sides, let's move in a level
				if (
					count == 0 &&
					this._activeLevel < (this._height/2)-2 &&
					this._activeLevel < (this._width/2)-2
				) {
					this._activeLevel++;
					count = 4;
				}

			}
		}

		// Finds empty tiles & populates with a building
		private function scanSide():void
		{
			var xLoc:int;
			var yLoc:int;
			switch (this._activeSide) {
				case SIDE_NORTH:
					for (xLoc=0;xLoc<this._width;xLoc++) {
						if (this._tiles&#91;this._activeLevel&#93;&#91;xLoc&#93;.type == Tile.TYPE_EMPTY ) {
							this.createBuilding(xLoc,this._activeLevel);
						}
					}
					break;

				case SIDE_EAST:
					for (yLoc=0;yLoc<this._height;yLoc++) { 						if (this._tiles&#91;yLoc&#93;&#91;this._width-1-this._activeLevel&#93;.type == Tile.TYPE_EMPTY ) { 							this.createBuilding(this._width-1-this._activeLevel,yLoc); 						} 					} 					break; 				 				case SIDE_SOUTH: 					for (xLoc=this._width-1;xLoc>=0;xLoc--) {
						if (this._tiles[this._height-1-this._activeLevel][xLoc].type == Tile.TYPE_EMPTY ) {
							this.createBuilding(xLoc,this._height-1-this._activeLevel);
						}
					}
					break;

				case SIDE_WEST:
					for (yLoc=(this._height-1);yLoc>=0;yLoc--) {
						if (this._tiles[yLoc][this._activeLevel].type == Tile.TYPE_EMPTY ) {
							this.createBuilding(this._activeLevel,yLoc);
						}
					}
					break;

			}
		}

		// This tile is empty, let's create a building
		private function createBuilding(xLoc:int,yLoc:int):void
		{
			var xPos:int = xLoc;
			var yPos:int = yLoc;

			// Let's check the first dimention

			while (this.isTileEmpty(xPos,yPos)) {
				if (this._activeSide == SIDE_NORTH) {
					xPos++;
				}else if (this._activeSide == SIDE_SOUTH) {
					xPos--;
				}else if (this._activeSide == SIDE_EAST) {
					yPos++;
				}else if (this._activeSide == SIDE_WEST) {
					yPos--;
				}
			}

			if (
				this._activeSide == SIDE_NORTH &&
				(xPos - xLoc) > 10
			) {
				xPos = xLoc + Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));

			}else if (
				this._activeSide == SIDE_SOUTH &&
				(xLoc - xPos) > 10
			) {
				xPos = xLoc - Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));

			}else if (
				this._activeSide == SIDE_EAST &&
				(yPos - yLoc) > 10
			) {
				yPos = yLoc + Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));

			}else if (
				this._activeSide == SIDE_WEST &&
				(yLoc - yPos) > 10

			) {
				yPos = yLoc - Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));
			}

			var tmpDimention:int;
			var direction:String;
			var length:int;

			if (xLoc != xPos) {
				tmpDimention = xPos;
				if(xLoc < xPos){
					direction = 'right';
					length = xPos-xLoc;
				}else{
					direction = 'left';
					length = xLoc-xPos;
				}
			}else{
				tmpDimention = yPos;
				if(yLoc < yPos){ 					direction = 'down'; 					length = yPos-yLoc; 				}else{ 					direction = 'up'; 					length = yLoc-yPos; 				} 			} 			 			xPos = xLoc; 			yPos = yLoc; 			 			 			// Let's check the second dimention 			 			while (this.isLineEmpty(xPos, yPos, direction, length)) { 				if (this._activeSide == SIDE_NORTH) { 					yPos++; 				}else if (this._activeSide == SIDE_SOUTH) { 					yPos--; 				}else if (this._activeSide == SIDE_EAST) { 					xPos--; 				}else if (this._activeSide == SIDE_WEST) { 					xPos++; 				} 			} 			 			if ( 				this._activeSide == SIDE_NORTH && 				(yPos - yLoc) > 10
			) {
				yPos = yLoc + Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));

			}else if (
				this._activeSide == SIDE_SOUTH &&
				(yLoc - yPos) > 10
			) {
				yPos = yLoc - Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));

			}else if (
				this._activeSide == SIDE_EAST &&
				(xLoc - xPos) > 10
			) {
				xPos = xLoc - Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));

			}else if (
				this._activeSide == SIDE_WEST &&
				(xPos - xLoc) > 10

			) {
				xPos = xLoc + Math.floor( Math.random()*this._buildingMin+(this._buildingMax-this._buildingMin));
			}

			if (xLoc != xPos) {
				yPos = tmpDimention;
			}else{
				xPos = tmpDimention;
			}

			var left:int,right:int,top:int,bottom:int;

			// let's get the dimentions
			// Left / Right
			if (xPos > xLoc) {
				left = xLoc;
				right = xPos-1;
			}else{
				left = xPos+1;
				right = xLoc;
			}

			// Top / Bottom
			if (yPos > yLoc) {
				top = yLoc;
				bottom = yPos-1;
			}else{
				top = yPos+1;
				bottom = yLoc;
			}

			// check to see if all tiles within this area are empty
			var allEmpty:Boolean = true;
			for(var $y:int=top;$y<=bottom;$y++){
				for(var $x:int=left;$x<=right;$x++){
					if (!this.isTileEmpty($x,$y)) {
						allEmpty = false;
					}
				}
			}

			// if all the tiles aren't empty, let's quit out
			if (!allEmpty) {
				return void;
			}

			//var building:Object = {'top':top,'right':right,'bottom':bottom,'left':left};
			this._buildings.push({'top':top,'right':right,'bottom':bottom,'left':left});

			// Let's change to building
			for($y=top;$y<=bottom;$y++){
				for($x=left;$x<=right;$x++){ 					this._tiles&#91;$y&#93;&#91;$x&#93;.type = Tile.TYPE_BUILDING; 					 					// make the roads 					//LEFT 					if ($x==left && (this._tiles&#91;$y&#93;&#91;$x-1&#93;) != undefined) { 						this._tiles&#91;$y&#93;&#91;$x-1&#93;.type = Tile.TYPE_ROAD; 					} 					//RIGHT 					if ($x==right && (this._tiles&#91;$y&#93;&#91;$x+1&#93;) != undefined) { 						this._tiles&#91;$y&#93;&#91;$x+1&#93;.type = Tile.TYPE_ROAD; 					} 					//TOP 					if ($y==top && (this._tiles&#91;$y-1&#93;) != undefined) { 						this._tiles&#91;$y-1&#93;&#91;$x&#93;.type = Tile.TYPE_ROAD; 					} 					//BOTTOM 					if ($y==bottom && (this._tiles&#91;$y+1&#93;) != undefined) { 						this._tiles&#91;$y+1&#93;&#91;$x&#93;.type = Tile.TYPE_ROAD; 					} 					//TOP LEFT 					if ( 						$x==left && (this._tiles&#91;$y&#93;&#91;$x-1&#93;) != undefined && 						$y==top && (this._tiles&#91;$y-1&#93;)!= undefined 					) { 						this._tiles&#91;$y-1&#93;&#91;$x-1&#93;.type = Tile.TYPE_ROAD; 					} 					//TOP RIGHT 					if ( 						$x==right && (this._tiles&#91;$y&#93;&#91;$x+1&#93;) != undefined && 						$y==top && (this._tiles&#91;$y-1&#93;) != undefined 					) { 						this._tiles&#91;$y-1&#93;&#91;$x+1&#93;.type = Tile.TYPE_ROAD; 					} 					//BOTTOM LEFT 					if ( 						$x==left && (this._tiles&#91;$y&#93;&#91;$x-1&#93;) != undefined && 						$y==bottom && (this._tiles&#91;$y+1&#93;) != undefined 					) { 						this._tiles&#91;$y+1&#93;&#91;$x-1&#93;.type = Tile.TYPE_ROAD; 					} 					//BOTTOM RIGHT 					if ( 						$x==right && (this._tiles&#91;$y&#93;&#91;$x+1&#93;) != undefined && 						$y==bottom && (this._tiles&#91;$y+1&#93;) != undefined 					) { 						this._tiles&#91;$y+1&#93;&#91;$x+1&#93;.type = Tile.TYPE_ROAD; 					} 				} 			} 		} 		 		private function isTileEmpty(xLoc:int,yLoc:int):Boolean 		{ 			if ( 				(this._tiles&#91;yLoc&#93;) != undefined && 				(this._tiles&#91;yLoc&#93;&#91;xLoc&#93;) != undefined && 				this._tiles&#91;yLoc&#93;&#91;xLoc&#93;.type == Tile.TYPE_EMPTY 			) { 				return true; 			} 			return false; 		} 		 		private function isLineEmpty(xLoc:int,yLoc:int,direction:String,length:int):Boolean 		{ 			var xPos:int = xLoc; 			var yPos:int = yLoc; 			 			while (length > 0) {
				if(!this.isTileEmpty(xPos,yPos)){
					return false;
				}
				switch (direction) {
					case 'left':
						xPos--;
						break;
					case 'right':
						xPos++;
						break;
					case 'up':
						yPos--;
						break;
					case 'down':
						yPos++;
						break;
				}
				length--;
			}
			return true;

		}

		public function get buildings():Array
		{
			return _buildings;
		}
	}
}

Tile.as

The Tile class is simply a graphical element to show different colours for the different types of square, white being buildings & black being roads

package city
{
	import flash.display.Sprite;
	public class Tile extends Sprite
	{

		public static const TYPE_EMPTY:int = 0;
		public static const TYPE_BUILDING:int = 1;
		public static const TYPE_ROAD:int = 2;

		private var _type:int;

		public function Tile() {
			// constructor code
			_type = TYPE_EMPTY;
			colour = 0xffffff;
		}

		public function set colour(val:uint):void
		{
			graphics.clear();
			graphics.lineStyle(1,0x000000);
			graphics.beginFill(val);
			graphics.drawRect(0,0,4,4);
			graphics.endFill();
		}

		public function get type():int
		{
			return this._type;
		}

		public function set type(value:int):void
		{
			this._type = value;
			if (value==TYPE_EMPTY) {
				colour = 0xffffff;
			}else if (value==TYPE_BUILDING) {
				colour = 0xefefef;
			}else if (value==TYPE_ROAD) {
				colour = 0x333333;
			}else {
				colour = 0x000000;
			}
		}

	}

}

Dynamic Roads & Picking

It’s been a slow couple of weeks on the game development front which has mainly been down to trying to get ‘picking’ to work. I was thinking about the game play style and think that I’d prefer it to be more strategic than action and decided to change it to a point & click style game. This would also be a better choice as its mainly been aimed for mobile devices.

The main issue with this decision is that because I’m using a 3D environment now, I need to use a process called picking. Picking is the process when you click on a position of the screen and it calculates which object in the 3D environment has been clicked. This is all new to me and left me feeling quite out of my depth. I did manage to find an example of picking but it didn’t play nicely with my current workings when trying to add the methods to my code. After a full week of free time hours try to getting this working, I admitted defeat which doesn’t happen too often. The decision was made to take a look into a premade 3D engine so I started looking at Away3D.

Away3D

Looking at the examples on the Away3D shows that picking is alive & kicking and having a quick go at creating a testbed seems like a quick & easy solution to creating a 3D environment. My first issue was that there’s not really a great number of tutorials and the genreal help seems to be lacking, that is unless you want to pay for their support or purchase a book. At this revelation, the tenacious side of me kicked in again and I’ve decided to take another look at getting my own version working but in the mean time, take a break & make progress in other areas.

Dynamic Roads

While looking into the picking, I came to the realisation that the different sections of roads being used could be generated from just one tile. Being that the 3D models use triangulation, I could create a tile which would contain two different elements which could be manipulated to the correct road layout.

road

When applying the texture to the mesh, I have control over which part of the texture gets applied to which corner of the triangle. Therefore, with the image above I can create a straight section of road with the left triangle of the image twice or a crossroad using the right triangle in the same method. This in theory means that less textures are required and should help improve performance. The short video below shows this method in action.

It’s not the greatest looking piece of work but it’s functional and can be updated later on.

What’s Next?

There are a few pieces which are next on the list, I still need to get the picking working but I’ve pushed this to the back-burner for now so I can make some progress on other sections.

I really need to optimise the transition from one city area to another, currently there’s a lag when creating the new area which I really want to reduce or remove.

The other two sections are the pieces I really want to get my teeth into, that’s the enemies with basic reactions. The other is to make each city block more unique, I want there to be different building types and searchable items (crashed cars, bodies, containers, etc)

Seamless city generation progress

I’ve made the decision to change the loading of levels in the game. Originally the plan was to load each piece of the city at a time when you exited and entered a new area. In more recent games, gamers are more accustom for levels loading in the background making it a seamless experience, therefore, this is what I’ve attempted to go for.

To show how I’ve implemented this, I’ve zoomed right out to give  you an idea of the process being performed.

As you can see there’s still a little left to do, the buildings at the edge of each section is still full length which will lead to long buildings so I just need to half the width of these. There’s also a slight lag while each block is being generated. All in all, it’s not too far off what I was hoping to achieve, just needs a few tweaks.

Game Development (April 2013)

Once again, it’s been a while since I’ve posted anything but enthusiasm dwindled a bit a few months ago. A few changes have been made since the last update but nothing substantial. They pretty much cover what I was wanting to get done in the next stint but it hasn’t progressed much further than that. The main reason of the lack of progress is that I tried running the game on an Android Nexus and by the version of AIR available doesn’t support the 3D stage which is a bit of a major blow for trying to create a 3D game for AIR to be used on Android devices =P

Zombies!

I’ve added in basic randomised zombie sprites which are currently spawning on each road tile. At this point in time, it was mainly to get a sprite on stage with a randomly picked texture. They’re also shootable but hit-testing is a little hit & miss and needs tweaking. The next step for them is to be randomly spawning based on the player’s location and being destroyed once too far from the player. They also need to move (as zombies do), randomly at first but react to the player by noise and viewing angle.

Besides the zombies, I’ve also added in a slight camera chase so the camera movement is a little more fluid. I’ve tried to capture this in the video by starting & stopping but this may just end up being annoying. I’ve also added in a slight improvement on how the roads are being drawn on stage, now I’ve just got to replicate this on all the other models.

I’ve been trying again to get the 3D stage working on the Android but there’s been a security update which is causing problems so I can’t currently export onto the device. Hopefully I’ll crack it soon.

Update (2 minutes later)

Welllllll……. although I spent a couple of hours the other day fighting with AIR and Android and gave up in a sulk, I’ve just tried it again and it worked straight off the bat. Seriously, no changes to any configuration, literally plugged in the device & clicked debug.

Now this is working, I’m feeling a second wind coming on.

Game Development Update

Updates

It’s been a little while since my last update on the game dev process. I hadn’t really worked on it much over the last few months but had an inspirational burst over the last few days. I had hit a block with the 3D translations where models weren’t moving properly and it seemed to be moving some vertices in one direction while move the rest in another. This wasn’t ideal and it looked a bit like there was a rip in the fabric of the game’s universe.

After spending many hours trying to fix, I decided to cut the dead weight and completely rewrite how the 3D worked. There are still a few niggles which are annoying me but they’re purely with how the code’s currently working, they shouldn’t affect the final output so I’ve pushed them a bit lower down the priority list.

Now although the underlying code is all sparkly new, the output looks pretty much the same as the last video so I’m afraid there’s nothing new to actually see in this video. Hopefully I’ll have something more exciting in the next update.

What’s next

There are still a few pieces to be done on the 3D side of things, cleaning up & optimising but with the rewrite out of the way it lets me start coding some game functionality plavix tablet.

As you can see from the video I’ve already started by adding in a placeholder sprite for the main player. Next I need to add in some basic enemies, bullets and hit testing on everything. Another important addition is to add in touch interface controls. I had wanted to make this more like a classic point click style RPG but there doesn’t seem to be an easy method of capturing touch events on the 3D stage. I’m therefore changing it to be more of an action RPG style.

Wireframing Apps

In the run up to starting development of mobile apps I thought it to be a good idea to start planning ahead. My usual method is that I get an idea in my head & I run with it which I guess is a common programmers method.

My initial thought was to design some mockups on the iPad, I’ve recently replaced my iPad and have started using it again. Upon scouring the App Store I found a couple of wireframing app which caught my eye. The first was iMockup which is aimed at both app and web design which I thought was ideal, especially at the reasonable £5 price tag. The second app I saw was AppCooker and it looked a lot more polished but the price tag reflected this at £10, this however seems the be a beta price and apparently this will raise three fold once released. I did mull over both apps, iMockup was cheaper and would let me mock up for the web but AppCooker looked like it was made to do one task and that it could probably to it really well. In the end I splurged and bought AppCooker, shortly after I found out the iMockup price had been slashed to half so I bought that too.

Interface

Both apps have very well laid out interfaces for the main design view, each with pull-out drawer style elements which can be closed to give additional workspace. AppCooker has one at the top with grouping, arranging and transitioning options and iMockup has one on each side, the left with the pages and components on the right. Both apps have a small toolbar at the top with a few options and AppCooker has an additional bar at the bottom with preferences. The bottom bar on AppCooker is static so iMockups has the ability to have a slightly larger workspace but it really is negligible.

With the app pages, iMockup only really has three different pages, the projects page, the main design view and a preview mode. AppCooker has all these pages but with a few extras thrown in. First off in iMockup you select the different pages by just opening out the left drawer and clicking on the page you want, nice, quick and simple. AppCooker has an additional section for viewing a projects pages which is really quite useful.

20121127-211948.jpg
Not only can you drag the pages around to organise them how you like, it also shows the relationships between the pages.

AppCooker is not only just a wireframing app, they’ve also crammed in a few extra pages like an icon editor and a potential profit calculator.

Components

Both applications have a great set of components each. The AppCooker components are generally much more cosmetically appealing as they really do look like authentic iOS components. The components in iMockups are quite barebones in comparison and are more true to a classic wireframe style. iMockups has three sections which are web, iPhone / iPad and ‘markup’, markup is pretty much miscellaneous items like shapes, arrows and links. AppCooker has widgets, wireframe, misc, shapes and images. Wireframe components are pretty much identical to the main widgets but are lacking the colour and glossy feel of the main components. They say its so you can ignore the colour and concentrate on the design, essentially making it like iMockups.

20121124-102315.jpg

You can use images within each app, AppCooker has an additional menu which gives you direct access to your images on your iPad. iMockups however has an image component which you need to add to the page and then go into the images preferences to select the desired image.

The components are customisable in both apps but this is handled very differently in each. In iMockups you select the component onscreen and select the info option. The customisable sections for the text of each component is purely text based, mainly comma separated. The following example shows the configuration for the footer iOS navigation.

20121127-232949.jpg

The customisation options for AppCooker are much more advanced. Continuing of the example of the main app navigation, not only can you select the text but you can also select the icon from an inbuilt selection and enable a link to another page.

20121127-234434.jpg

In iMockups you also have the option to select a link but not for individual navigation items, either you have to select a link for the whole navigation component or add a link component for each navigation option, align it up to the correct position and set the link.

Preview

The links brings us nicely to the previews as setting a link will allow us to navigate between the pages in the preview mode. The preview modes are exactly what you’d expect them to be, a demonstration mode to see the prototype in action. The preview in iMockups is simple & straight forward to use, you can swipe left and right to quickly skip through the pages, alternatively if you have links set on a component you can tap the component to go to the target page. The AppCooker preview works on the component links to navigate through to the other pages, it doesn’t have an option to slide between the pages. It does however have a really nice additional feature in the form of a separate app called AppTaster which is completely free. AppCooker allows you to save out a preview file which you can then email to your client, the client can install the AppTaster app on their device and preview the prototype remotely.

.

Conclusion

The outcome of using both apps is that it’s quite clear a case of getting what you pay for. AppCooker does have a lot more features and is far more polished than iMockups but when the discount ends it will be six times more expensive.

At this point in time AppCooker is currently twice the price of iMockup but what you get in terms of quality can be seen throughout the app. I’m glad I got it but the question remains, would I purchase it when it reaches the full price? I’d say it’d be doubtful but it really does depend on what these ‘top secret’ future changes are going to be and if they’re as spectacular as they’re making out, in my opinion it’d have to be pretty spectacular to be worthy for a £30 price tag.

I feel that although they are both wireframing apps, they both ultimately serve very different purposes. I think the iMockup is mainly intended as a barebones tool to create quite simple layouts very quickly. If you have an idea for a design it allows you to churn out a few pages effortlessly.

AppCooker however comes across as nearly the next stage of the process. I could quite happily spend a few hours tweaking a design, customising the components to look nearly like the real thing. I’d say that with the additional feature of AppTaster where you can send a copy of the prototype and for it to be previewed remotely is an excellent idea. It really does allow you to get a real feel for the app without touching a line of code and is ideal for remote clients to get their say before any real development takes place.

Mobile projects

It’s been a little while since I’ve written anything about development and that’s down to yet another project. I seem to have quite a short attention span when it comes to my own projects so I seem to bounce between old & new things I’m working on.

One thing I’ve been wanting to do for a little while is take a look into mobile app development. I was on the verge of venturing out to teach myself iOS & android development until I learnt that Flash Builder can now export to both platforms. This means that I get to be somewhat lazy, I only have to build one application to work on multiple devices and I get to use ActionScript 3 which I’m already proficient in. There were plans for this before but I the last I heard Apple had pretty much put a stop to it. Luckily now they seem to have made a U- turn.

I’ve been looking through the available components and although some key pieces are there, that’s about it…. it feels very barebones. I guess this does allow you to be more creative in having to build the components you need but that’s half the fun (from a programmers point of view at least). Hopefully once I’ve gotten something worth publishing on the matter I can divulge further.

Ipad mini

The insurance money from the burglary came in the other day and being that my iPad was stolen it was decision time.

The first decision was to even replace it at all, over the last coupe of months I’d not been using my old iPad as much since I had just bought myself a new MacBook to work on. If I was to replace it, did I want to upgrade to the latest model with retina? Alternatively I could abandon iPad altogether and buy myself an android tablet.

I was very tempted to buy a Google Nexus but the main reason I decided to stick Apple was due to the fact that I had already bought into it. If I was to buy an android tablet, I’d have to rebuy all the apps I had already paid for which wasn’t overly appealing.

In the end I decided to go with the brand spanking new iPad mini and actually went to the store on the day of release to pick one up. I’ve gotta say, I’m pretty impressed with it and already prefer it over my old tablet. There’s no really much difference between the old and the new, the key difference is the size. Although the standard iPad isn’t exactly gigantic, I did on occasion find it cumbersome for my usage.

The next improvement is purely a side effect of the smaller size and that’s the image does look sharper, not as sharp as the retina display but sharper than my old iPad.

The final key difference has to be the new ‘lightning’ power adaptor, purely as you can now plug the cable in either way.

In all honesty there’s not too much more you can say than that, the rest of the specs are exactly the same as the iPad2 so is there even any regurgitating what’s already been said? All in all, I’m really happy with the iPad mini.