Jun 8 2009

Phlocks is out!!!

Finally, I managed to release Phlocks - Physical blocks. It is a casual flash puzzle game using the Box2D physics engine. I started playing with the engine in the beginning of this year. End of January I came up with the first version of the game.

This weekend finally, I found some time to pick up that project again and finish it. Ok, try it out yourselves at the following little sub-page:

Phlocks icon

http://www.weltenkonstrukteur.de/games/phlocks/


Feb 15 2009

Simple countdown timer in ActionScript3.0

For a private site-project I did a very simple countdown timer in pure actionscript3.0. The timer extends a textfield and updates itself every seconds. Since it is very simple it should be easy to extend it in various ways. Right now it shows the remaining time in the following format:

DAYS:HOURS:MINUTES:SECONDS

countdown-timer-scr

The code itself is very basic - nothing really special. Only one thing really confused me. Have a look at line number 20. The second parameter of Date-constructor specifies the month. There is something special about it - months are enumerated from 0 to 11 whereas days for example are enumerated from 1 to 31. This is something I find very confusing and strange. So keep this in mind when you are using the Date object in actionscript.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package
{
	import flash.display.Sprite;
	import flash.events.DataEvent;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	/**
	 * Little countdown timer extending a normal textfield
	 *
	 * @author benny!weltenkonstrukteur.de
	 */
	public class Countdown extends Sprite
	{
		// CONFIG THIS VALUE TO THE DESTINATION DATE
                // FORMAT YYYY:MM:DD:HH::MM:SS::MSMS
                // MONTH STARTS WITH ZERO
		private static var DEST_DATE:Date = new Date(2009, 05, 15, 20, 42, 0, 0);
 
		// Member variables
		private var cntTxt:TextField = null;
		private	var cntTime:uint = 0;
		private var cntTimer:Timer = null;
 
		/**
		 * Constructor
		 */
		public function Countdown()
		{
			this.init();
			cntTimer.start();
		}
 
		/**
		 * Inits all stuff on startup
		 */
		private function init():void
		{
			// Setup the text format
			var tf:TextFormat = new TextFormat();
			tf.font = 'Courier New';
			tf.size = 24;
			tf.color = 0x33ff33;
			tf.bold = true;
 
			// Setup text field
			cntTxt = new TextField();;
			cntTxt.width = stage.stageWidth;
			cntTxt.defaultTextFormat = tf;
 
			// Setup timer
			cntTimer = new Timer(1000);
			cntTimer.addEventListener(TimerEvent.TIMER, onTimer);
 
			// Add text field to stage
			addChild(cntTxt);
		}
 
		/**
		 * Handler for timer event
		 * @param	e, TimerEvent
		 */
		private function onTimer(e:TimerEvent):void
		{
			// Calculate the remaining time
			var asec:int = Math.round((DEST_DATE.getTime() - new Date().getTime()) / 1000);
 
			trace(asec);
 
			// If countdown is passed
			if ( asec < 0 )
			{
				// Show zeros instead
				cntTxt.text = "000:00:00:00";
			}
 
			// Otherwise
			else
			{
				// Calculate time parts
				var secs:uint = asec % 60;
				var amin:uint = Math.round(asec / 60);
				var mins:uint = amin % 60;
				var ahr:uint  = Math.round(amin / 60);
				var hrs:uint  = ahr % 24;
				var days:uint = Math.round(ahr / 24);
				var strSecs:String, strMins:String, strHrs:String, strDays:String;
 
				// Format with inital 0
				( secs < 10 ) ? strSecs = "0" + secs.toString() : strSecs = secs.toString();
				( mins < 10 ) ? strMins = "0" + mins.toString() : strMins = mins.toString();
				( hrs < 10  ) ? strHrs  = "0" + hrs.toString()  : strHrs = hrs.toString();
				if ( days < 10 )
				{
					strDays = "00" + days.toString();
				}
				else if ( days > 10 && days < 100 )
				{
					strDays = "0" + days.toString();
				}
				else
				{
					strDays = days.toString();
				}
 
				// Update time
				cntTxt.text = strDays + ":" + strHrs + ":" + strMins + ":" +strSecs;
			}
		}
	}
}

Feb 1 2009

Beta version of a simple physics game

In the last two days I played around with Box2D. Box2D is an open source 2D physics engine for games. In addition there exists an actionscript port for the Flash platform. Studying various examples on the internet and the wonderful tutorials of Emanuele Feronato I came up with the following little game. It is still in beta phase and there are plenty of things which needs to be added and polished.

scr-tblocks

Note: Link to the game is deactivated. The final game is in progress. Beta is closed.

Anyway, maybe you want to have a try on it. The logic is very easy. The aim of the game is to drop as many blocks as possible on the green bar. Move your mouse to determine the x-position of the block to drop. Press left button to drop it. On the upper right you see the percentage of wind and the direction in which the wind is blowing. That wind effects the following blocks.

Here is a little list of things that are still to do:

  • Highscore system
  • Start screen
  • Polish score and wind system
  • Fixing bugs

Please let me know if you have any more ideas or if you find any bugs. By the way, my current highscore is 22 blocks ;-)


Dec 21 2008

Rotozoomer in Actionscript3.0

One oldschool demoscene effect I still love is the so called Rotozoomer. Rotozoomer by its name rotates and zooms an image in and out. The effect is really stunning and it is well known among oldschool amiga sceners. Reading the very good tutorial about Actionscript’s Transformation Matrix class by senocular.com inspired me to have a try to do a rotozoomer in pure ActionScript3.0.

If you cross-read to senocular’s tutorial and my source code you see how easy the pixel tranformation matrix work to come up with the effect.

The flash movie requires at least Flash Player9.0 - just press on the screenshot to run it. The fantastic “bunny” image was made by the artist called made.

Rotozoom Screenshot

Finally, here is the source code. I tried to comment it as best as I can. Have fun with it.

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.events.MouseEvent;
	import flash.net.*;
 
	/**
	  * Simple rotozoomer in actionscript3.0
	  *
	  * @author benny!weltenkonstrukteur.de
	  */
	public class RotoZoom2 extends Sprite
	{
		// Declaring class constants
		private const ZOOM_MAX:Number 		= 3;
		private const ZOOM_MIN:Number 		= -2.0;
		private const ZOOM_DELTA:Number 	= 0.015;
		private const ROTATE_DELTA:Number	= 0.05;
 
		/// Initialisate private class members
		private var angle:Number = 0, zoom:Number = ZOOM_MIN, isZoomIncreasing:Boolean = true;
		private var logo:Bitmap = null, logoBitmapData:BitmapData;
		private var sw:uint, sh:uint;
 
		// Declare embedded assets
		[Embed(source = "made-bunny.png")]
		private var LogoBitmap:Class;
 
		/**
		 * Constructor
		 */
		public function RotoZoom2()
		{
			init();
			addEventListener("enterFrame", loop);
		}
 
		/**
		 * Initialize needed sprites and bitmaps
		 */
		private function init():void
		{
			// Create logo bitmap and retrieving the bitmapData
			logo = new LogoBitmap();
			logoBitmapData = logo.bitmapData;
 
			// Setting canvas dimensions
			sw = stage.stageWidth;
			sh = stage.stageHeight;
		}
 
		/**
		 * Calcualte roto matrix and draws the scene
		 * @param	ev, onEnter event
		 */
		private function loop(ev:Event):void
		{
			// If we want to zoom in
			if ( isZoomIncreasing )
			{
				// Add increase value to zoom
				zoom = zoom + ZOOM_DELTA;
			}
			else
			{
				// Otherwise decrement value from zoom
				zoom = zoom - ZOOM_DELTA;
			}
 
			// Calculate new rotation angle
			angle = angle + ROTATE_DELTA;
 
			// If angle is greater than 360
			if ( angle > 360 )
			{
				// Reset it to zero
				angle = 0;
			}
 
			// If zoom is higher than maximum value
			if ( zoom > ZOOM_MAX )
			{
				// Change to zoom out
				isZoomIncreasing = false;
				zoom = ZOOM_MAX;
			}
			// If zoom is less than minimum value
			else if ( zoom < ZOOM_MIN )
			{
				// Change to zoom in
				isZoomIncreasing = true;
				zoom = ZOOM_MIN;
			}
 
			// Calculate matrix for rotation an zooming
			var rotoMatrix:Matrix = new Matrix(Math.cos(angle) * zoom, Math.sin(angle), -Math.sin(angle), Math.cos(angle) * zoom, 0, 0);
 
			// Fill scene with bitmap using the rotoMatrix
			graphics.clear();
			graphics.beginBitmapFill(logoBitmapData, rotoMatrix,true, true);
			graphics.drawRect(0, 0, sw, sh);
			graphics.endFill();
 
			// Set it free for gargabe collection
			rotoMatrix = null;
 
		}
	}
 
}