Intel sponsors gamedev.net search:   
Tesseract's Game Development JournalBy Tesseract      

How I Work
Preferred Language
Actionscript 3
Development Environment
Notepad++ for coding
Flex 3 SDK for compiling
Graphics
The GIMP, among others

See my personal weblog

Completed (and published) Flash Game Projects:
Games
TriGavoid
Tutorials
Creating Textures with Perlin Noise
Simple Trigonometry and Curves Tutorial



Wednesday, July 25, 2007
Gyruss clone created in Flash and AS3

Now they blow up real pretty when they get hit.

My free time the past few days has been taken up with the crime map. I fell about a month behind in updates, and all kinds of crazy shit went on in that time. Well, crazy for Grand Rapids.

Comments: 2 - Leave a Comment

Link



Wednesday, July 18, 2007
Actionscript 3 Gyruss clone with aggressive (and mortal) enemies

Added simple collision detection, varying enemy strength (1 - 5 "hit points") and enemies dying when they reach 0 health. I have the beginnings of the player being hit, but I did something funny earlier in the development cycle and now the visible ship is actually about 20 pixels farther out from where the code expects it to be. Probably something with the way I embedded it in the first place.

I think I am going to put a "Formation" class between the game class and the enemy class. The formation will take care of all of the enemy behaviors and keep them all playing nice. This will simplify the code for the main game class and allow me to do things like create bosses which are actually aggregates of several enemies of different size and shape. I think this is essentially how other arcade games (cf. Raiden X, 1941, etc) handle bosses which gradually lose pieces as they are worn down.

So next up: formations, player death, explosion animations, and perhaps the beginnings of a game UI.

Comments: 1 - Leave a Comment

Link



Tuesday, July 17, 2007
Actionscript 3 Gyruss clone with aggressive enemies

I have the democratic response coming in from the enemies now. There is no collision detection in place yet, but that shouldn't take long to implement. Right now I have all the pieces in place to finish creating a simple game. Total time today: 45 minutes.

I like the effect of the shots crossing paths. The blur layer is taking the colors and mixing them in what could be, with enough action, a really psychedelic pattern. I guess I will have to see what the processor can handle.

I should point out that the game plays much faster in the standalone Flash projector, or when embedded in an executable. When the game is a little more polished I will have a download available for anyone who is interested.

Comments: 0 - Leave a Comment

Link



Monday, July 16, 2007
Attack of the iPods of DOOM

After a beautiful weekend in northern Michigan (Blissfest, Harbor Springs, Petoskey) with the girlfriend, I am back in the saddle coding into the wee hours of the morning.

Clicking the screenshot will take you to the latest prototype. I just ported the Enemy class from AS2 to AS3 (total time: 1 hour), and have things working pretty well. Next step: collision detection with the player shots. After that: The enemies shoot back.

Here is the Enemy class, thus far:

package{
	import flash.display.*;
	public class Enemy extends Sprite {
		private var game:Gyruss;
		private var index:Number;
		private var radius:Number = 0;
		private var minRadius:Number = 10;
		private var maxRadius:Number = 160;
		private var centerX:Number;
		private var centerY:Number;
		private var angle:Number;
		private var direction:Number;					//	clockwise or counterclockwise
		private var approachDirection:Number = 1;		//	approaching or receding
		private var APPROACH_SPEED:Number = .3;			//	approach speed
		private var SPEED:Number = Math.PI*2/300;		//	rotation speed
		private var THETA:Number = Math.PI * 2;
		private var RAD_DEG:Number = Math.PI/180;
		
		public var health:Number = 100;
		
		public var isDead:Boolean = false;
		
		public function Enemy($game:Gyruss) {
			game = $game;
			centerX = game.centerX;
			centerY = game.centerY;
			
			x = centerX;
			y = centerY;
			
			setRandomDirection();
			graphics.beginFill(0xcccccc,100);
			graphics.drawRoundRect(-25,-10,50,20,5,5);
			graphics.endFill();
			
			graphics.beginFill(0xff0000,100);
			graphics.drawCircle(0,0,7);
			graphics.endFill();
			
			graphics.beginFill(0x000000,100);
			graphics.drawCircle(0,0,3);
			graphics.endFill();
			
		}
		
		public function setDirection($d:Number):void {
			direction = $d;
		}
		public function setRandomDirection():void {
			direction = (Math.round(Math.random())*2)-1;
			direction = 1;
		}
		
		public function move():void {
			THETA += (SPEED * direction);
			x = centerX + (radius * Math.cos(THETA));
			y = centerY + (radius * Math.sin(THETA));
			rotation = Math.atan2(y-centerY,x-centerX)/RAD_DEG;
			scaleX = scaleY = radius/maxRadius;
			if((radius < maxRadius && approachDirection==1) || (radius > minRadius && approachDirection == -1)) {
				radius += (APPROACH_SPEED*approachDirection);
			} else {
				approachDirection *= -1;
			}
		}
		
		public function takeDamage($d:Number):void {
			health -= $d;
			if(health <= 0) explode();
		}
		public function explode():void {
			isDead = true;
		}
	}
}


Comments: 0 - Leave a Comment

Link



Friday, July 13, 2007


I wanted to put a little time into learning how the Keyboard commands work in AS3, so I used that as an excuse to update the Gyruss clone (Flash 9 plugin required).

Here is the main class:

package{
	import flash.display.*;
	import flash.events.*;
	import flash.ui.Keyboard;
	import flash.geom.*;
	import flash.filters.BlurFilter;
	[SWF(backgroundColor="0x000000",width="540",height="540",frameRate="50")]
	public class KeyCodes extends Sprite {
		/*					*/
		/*	EMBEDDED ASSETS	*/
		/*					*/
		
		[Embed(source="ship_1.gif")]
		private var Ship:Class;
		private var ship:Bitmap;
		
		public var shots:Array;
		private var ball:Sprite;
		private var flame:Sprite;
		private var _bitmap:BitmapData;
		private var _buffer:BitmapData;
		private var _buffer_clear:BitmapData;	//	used to "clear" the bitmapdata
		private var _blur_layer:BitmapData;
		private var _image:Bitmap;
		private var _blurFilter:BlurFilter;
		
		private var SPEED:Number = Math.PI*2/100;	//	number of steps around a circle
		private var THETA:Number = Math.PI*.5;
		private var RAD_DEG:Number = 180/Math.PI;
		public var radius:Number;
		private var flameRadius:Number;
		public var centerX:Number;
		public var centerY:Number;
		private var angle:Number;
		
		private var isLeft:Boolean = false;
		private var isRight:Boolean = false;
		private var isFiring:Boolean = false;
		private var xDirection:Number = 0;
		public function KeyCodes() {
			_blurFilter = new BlurFilter();
			shots = [];
			addEventListener(Event.ENTER_FRAME,init);
		}
		private function init(e:Event):void {
			if(!stage) return;
			removeEventListener(Event.ENTER_FRAME,init);
			ball = new Sprite();
			ship = new Ship();
			ship.x = -(ship.width/2);
			ship.y = -(ship.height/2);
			ship.rotation = 90;
			ball.addChild(ship);
			
			flame = new Sprite();
			flame.graphics.beginFill(0x990000,100);
			flame.graphics.drawCircle(4,-10,4);
			flame.graphics.endFill();
			flame.graphics.beginFill(0x990000,100);
			flame.graphics.drawCircle(4,10,4);
			flame.graphics.endFill();
			
			centerX = stage.stageWidth/2;
			centerY = stage.stageHeight/2;
			radius = stage.stageWidth*.3;
			flameRadius = radius + (ship.height*1.5);
			ball.x = centerX + radius*Math.cos(THETA);
			ball.y = centerY + radius*Math.sin(THETA);
			flame.x = centerX + flameRadius*Math.cos(THETA);
			flame.y = centerY + flameRadius*Math.sin(THETA);
			_bitmap = new BitmapData(stage.stageWidth,stage.stageHeight,true,0xff000000);
			_buffer = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00000000);
			_buffer_clear = new BitmapData(stage.stageWidth,stage.stageHeight,true,0xff000000);
			_blur_layer = new BitmapData(stage.stageWidth,stage.stageHeight,true,0xff000000);
			_image = new Bitmap(_bitmap);
			addChild(_image);
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN,setDirection);
			stage.addEventListener(KeyboardEvent.KEY_UP,unsetDirection);
			addEventListener(Event.ENTER_FRAME,moveMe);
		}
		public function moveMe(e:Event):void {
			if(isLeft==true) {
				xDirection = -1;
			} else if (isRight==true) {
				xDirection = 1;
			} else {
				xDirection = 0;
			}
			THETA += SPEED * xDirection;
			ball.x = centerX + radius*Math.cos(THETA);
			ball.y = centerY + radius*Math.sin(THETA);
			flame.x = centerX + flameRadius*Math.cos(THETA);
			flame.y = centerY + flameRadius*Math.sin(THETA);
			var r:Number = Math.atan2(centerY - ball.y , centerX - ball.x)*RAD_DEG;
			ball.rotation = r;
			flame.rotation = r;
		//	_buffer.draw(_buffer_clear);
			_blur_layer.draw(flame,flame.transform.matrix);
			for(var i:Number = 0;i<shots.length;i++) {
				if(shots[i].isDead==false) {
					shots[i].move();
					_blur_layer.draw(shots[i],shots[i].transform.matrix);
				} else {
					delete shots[i];
					shots[i] = null;
					shots.splice(i,1);
				}
			}
			_blur_layer.applyFilter(_blur_layer,_blur_layer.rect,new Point(),_blurFilter);
			_buffer.draw(_blur_layer);
			_buffer.draw(ball,ball.transform.matrix);
			_bitmap.draw(_buffer);
		}
		
		public function setDirection(e:KeyboardEvent):void {
			switch(e.keyCode) {
				case Keyboard.LEFT :
					isLeft=true;
					break;
				case Keyboard.RIGHT :
					isRight=true;
					break;
				case Keyboard.SPACE : 
					addShot();
				default:
					break;
			}
		}
		public function unsetDirection(e:KeyboardEvent):void {
			switch(e.keyCode) {
				case Keyboard.LEFT :
					isLeft = false;
					break;
				case Keyboard.RIGHT :
					isRight = false;
					break;
				case Keyboard.SPACE : 
					isFiring = false;
				default:
					break;
			}
		}
		
		public function addShot():void {
			if(isFiring==true) return;
			isFiring = true;
			var s:Shot = new Shot(this,centerX + (radius+50)*Math.cos(THETA),centerY + (radius+50)*Math.sin(THETA));
			shots.push(s);
		}
	}
}



Once again, things are simpler than I am used to, so I find myself making things overly complicated, then having to go back and clean up my code.

I kind of like having lots of little projects to work on in the process of learning a new(ish) language. It keeps me from being distracted by the big picture of a big game, and it forces me to keep my code abstract enough that I can apply it in a number of situations.

Comments: 0 - Leave a Comment

Link



Tuesday, July 10, 2007
This idea came from several sources. First, from Lord Demon, a posthumous novel by Roger Zelazny and Jane Lindskold. Lord Demon is the story of a Chinese demon in modern California and his adventures therein. His specialty is creating bottles and other ceramics for other spirits to live in or use for various purposes. Not Zelazny's best story, but it has some interesting ideas. The bottles fascinated me because each was its own world, complete with landscape, ley lines, mythical creatures, and, from the inside, many exits.

As a side note, it occurs to me that many, if not most, of Zelazny's novels center around characters that create new worlds - Lord Demon, the Amber Chronicles, Eye of Cat, Donnerjack, et al.

Anyway, I like the idea of being able to have several different worlds, each with its own rules, and be able to logically (more or less) fit these widely varying worlds into a single over-arching storyline.

The second source for this idea was the novel 0X, by Piers Anthony, wherein the protagonists must travel between worlds in a particular order in order to find their way home.

The third was the concept of recursion, which I studied while learning to program.

The game story would go something like this: You are a genie/sprite critter who lives in a bottle. One day while outside your bottle you are attacked by a group of Bad Guys, and in the process of fleeing, while entering your bottle, something goes wrong and you pull the bottle inside of itself. The bottle fragments and you find yourself in a hall-of-mirrors analog, with bottles scattered all over your world. Each one is a variation on the one you live in, and each contains each of the others. You must travel through them in the right order, braving the new worlds in each one, in order to find your way back out.

Oh: And the bad guy was caught in the same accident. Now there are variations of the enemies throughout the worlds, and each was transformed along with the interior of the bottles.

Good luck to you.

There are so many wonderful ways a game like this could be presented, in gameplay style, graphically, thematically...every facet could be changed to suit the needs of the overall game.

This system would also allow for expanding the game, post-launch. The way the bottle fragments could be modified, the number of bottles could be changed, and new worlds could be added at whim.

A world like this would also lend itself admirably to a MMO game. Each player starts off in a small, plain bottle, and based on where the bottle is, and what is in the bottle, many adventures could be had.

But I need to keep myself reigned in so I don't start building something so far beyond by current capabilities that I spend all of my development time learning to program instead of programming. I will burn that bridge as I am crossing it.

Comments: 0 - Leave a Comment

Link



Monday, July 9, 2007
A new book just came in: Essential Actionscript 3.0. Looking through it, I can see I have a lot to learn, both in the new Actionscript and in programming in general. I am not used to being so strictly directed in what should and shouldn't be done, but I can see that it will speed things up for me dramatically. Having my options on how to do something cut back means I can't spend as much time hemming and hawing about whether this should be a local or global variable.

I have the beginnings of an idea for a game which will use the engine (?) I am building. I will post details when they become more clear. It is entirely possible that the specifics will change when 4e6 begins.

Next steps for the parallax sprite engine:
-reacting to key presses
-scrolling ground
-terrain created from an XML file
-move all variables to an external config file

One thing at a time, I suppose.

Comments: 0 - Leave a Comment

Link



Monday, July 2, 2007
Parallax Sprite with transparency and perspective distortion

I had a little free time so I threw this together. The image is a .gif, randomly rotated and repeated a random number of times from 0 to 50. As the layers build, they are enlarged very slightly to provide the illusion of perspective distortion.

Right now between the rotation and the distance offsets there is a lot of moire happening along the edges of the "buildings", but judicious use of blocks of color, and perhaps restriction rotation to 45-degree increments will solve the problem. I also had to add a single transparent pixel all the way around the image when I created it, in order to keep a hair-line from "wrapping" to the opposite side of the image. After all, I am using a fill to create the image, rather than duplicating the image directly. I feel this gives me a lot more control over how it is displayed, and allows for flood-filling large shapes with textures in order to make e.g. a long wall out of a single small brick texture and a lot of large, dynamically created sprite graphics.

Now that I am beginning to load images in a runtime, I have to correct for a security issue when accessing "the network" locally. Flash doesn't want to let the user do that, so when I compile the movie I need to use the "-use-network=false" flag in the mxmlc.exe compiler.

A little more each day. I don't have large chunks of time to spend learning these things, so I need to make the most of, say, half an hour before work, and an hour at night during the week. Such is the life of the obsessive hobbyist.

Comments: 0 - Leave a Comment

Link


parallax sprite bitmap test

Thanks to some tips from Pingnak over at the Kirupa forums, I have my .pngs loading in with alpha transparency intact.

I am still not sure why this was happening, but something about embedding the .png in the flash movie at compile time and then immediately using it to flood-fill the graphics layers caused the alpha channel to be ignored. Even when I embedded the .png, then copied the bitmapdata to a new bitmap, then used the new bitmap to fill the sprite, the alpha channel was ignored. I thought it might be the .png itself (which I had created in The Gimp), but when I looked at the png in any other setting everything was as it should be.

So I switched over to loading it at run-time (which is how it will ultimately be handled anyway), and everything seems to be working!

Now that I have this issue resolved, I am going to play around with graphics for different types of objects, and how to make sure the edges "fill" the offset areas so they look like full depth instead of layers.

Comments: 0 - Leave a Comment

Link


All times are ET (US)

 
S
M
T
W
T
F
S
1
3
4
5
6
7
8
11
12
14
15
19
20
21
22
23
24
26
27
28
29
30
31

OPTIONS
Track this Journal

 RSS 

ARCHIVES
November, 2009
March, 2009
January, 2009
November, 2008
October, 2008
September, 2008
August, 2008
July, 2008
February, 2008
December, 2007
November, 2007
October, 2007
September, 2007
July, 2007
June, 2007
March, 2007
February, 2007
January, 2007
December, 2006
August, 2006
July, 2006
June, 2006