Kinessia, game school project

Hey,

I’m happy to share with you my game school project made at the french Gobelins school, in Annecy.
It is now online : http://kinessia.aymericlamboley.fr/.

I worked with a graphic designer, Tiffany Francony, which made an amazing job !

For the exam we had high honours and the best rating !!

It is made with the Citrus Engine. The original version used a smartphone as a controller for the game, and all the HUD was displayed on this. I used a Java server to make the synchronization.

This is a simple web version, I can’t pay a Java server. The concept is more raw than the original one, there was a video at the beginning to explain the story, and our approach was on the website. But, that was all in french, so I cut off.

All the source code is available on GitHub.

A short video :

I hope you will enjoy the prototype 🙂

Greedy algorithm

According to Wikipedia, a greedy algorithm is any algorithm that follows the problem solving heuristic of making the locally optimal choice at each stage with the hope of finding the global optimum. In general, greedy algorithms are used for optimization problems.

An example of a Greedy algorithm is a charging machine. Assume that it give you your change with € currency, you will have coin of : 200, 100, 50, 20, 10, 5, 2, 1. Your change will be really easy to calculate with a greedy algorithm :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var moneySystem:Array = [200, 100, 50, 20, 10, 5, 2, 1];
var giveBack:uint = 263;
var solution:Array = [];
 
trace(greedyMethod(moneySystem, giveBack, solution));
 
function greedyMethod($moneySystem:Array, $giveBack:uint, $solution:Array):Array {
 
	if ($giveBack == 0) {
		return $solution;
	}
 
	while ($giveBack >= $moneySystem[0]) {
		$giveBack -= $moneySystem[0];
		$solution.push($moneySystem[0]);
	}
 
	$moneySystem.shift();
 
	return greedyMethod($moneySystem, $giveBack, $solution);
}

For 263, the algorithm will output : 200,50,10,2,1. It is the best solution. Thanks to the € currency, greedy algorithm will always give the best results.
However if we have an other money with only 4, 3, 1 coins and the change is 6 the greedy algorithm outputs 4, 1, 1 instead of 3, 3. That’s a fail !

Another typical example is the knapsack problem : given a set of items, each with a weight and a value, determine the number of each item to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible.
According that our values are sorted in decreasing order we have :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var objects:Array = [["A", 12, 10], ["B", 10, 7], ["C", 8, 5], ["D", 7, 4], 
		 ["E", 7, 4],  ["F", 6, 4], ["G", 5, 2], ["H", 4, 2],
		 ["I", 4, 1], ["J", 3, 2], ["K", 3, 2], ["L", 3, 1],
		 ["M", 2, 2], ["N", 1, 1]];
var totalWeight:uint = 25;
 
trace(knapSack(totalWeight, objects));
 
function knapSack($totalWeight:uint, $objects:Array):Array {
 
	var currentWeight:uint = 0;
	var subSet:Array = [];
 
	for (var counter:uint;counter< $objects.length; ++counter) {
 
		if (currentWeight + $objects[counter][2] <= $totalWeight) {
			currentWeight += $objects[counter][2];
			subSet.push($objects[counter]);
		}
	}
 
    return subSet;
}

The output is [A,12,10],[B,10,7],[C,8,5],[G,5,2],[I,4,1]. It’s ok, but we aren’t sure that it is the best result. The problem with a greedy algorith : it will always try to select the first parameter even if it is not the better.
For instance, our max weight is 40, our objects are [“A”, 30, 39], [“B”, 12, 10], [“C”, 12, 10], [“D”, 12, 10], [“E”, 12, 10],[“F”, 4, 1]. The greedy algorithm choose A and F for a value of 34 whereas B, C, D, E is obviously the best value : 48. That’s an other example where it fails.

So to conclude greedy algorithms depends of datas if they are balanced or not. More data are balanced, more it will be powerful. For a perfect result, you can use dynamic programming method. It is more complex and requires more resources. So it’s up to us to find the best solution for our problem.

Synch a phone with a website using the Union Platform

For my school game project, I use an iPhone to move my hero thanks to the accelerometer. It can move to left/right, jump… and manage informations in a menu. To make the synchronization, I use the Union Platform.

There are several ways to realize a synchronization between a smartphone and a website using servers like : Flash Media Server, SmartFox Server, BlazeDS… I didn’t really try FMS because I use a mac and it can not runs on it. At first I wanted to put my game online using SmartFox, so I needed a Java server… but it’s really expensive ! However there was an alternative with the Google App Engine. We can have a free access to Java and Python server hosting by Google ! It seemed to be great, but SmartFox can’t be deploy on it whereas BlazeDS and GraniteDS can ! These 2 servers use the flex technology… it was a big problem to deal with because I use an old iPhone 2G. Even if today you can easily export flash with as3 for iPhone with Flash IDE or the new Flash Builder 4.5, exporting flex for iPhone is not easy : indeed, we need to use some Ant Tasks… and if your .ipa is well exported, it will not run on iPhone 2G. In fact with the new Air 2.6 you can’t export to old iPhone.

So these months have been really frustrating, until a friend informed me of the release of a new server : the Union Platform. It has been released by Colin Moock who wrote Essential ActionScript 3.0 book.

Continue reading Synch a phone with a website using the Union Platform

Create objects and Art in the Citrus Engine

Update : if you want a version with a SWC for targeting iOS, please refers to this post.

Hey ! I started to make my school game project this week. I advance quickly, it should be fine for the end of june !

For this third tutorial on the Citrus Engine, I explain better how you can use the Flash IDE as Level Editor, and I show two classes that I’ve created for my game. Here is what you will have.

Continue reading Create objects and Art in the Citrus Engine

Create a breakout game with the Citrus Engine

Today this is a new tutorial on the great Citrus Engine framework. Before starting my school project, I wanted to try using box2D inside the Citrus Engine, so I will show you how create a breakout game !

Click here to play the game, don’t forget to click in the swf to enable keyboard.

Continue reading Create a breakout game with the Citrus Engine

Webcam picture cutout

In many websites, for a most immersive surf you take a shot of your face. Often, it is simply a red square. You move your head in, and you take the picture; it is really easy to do. However if you want to take only the head with a circle for exemple it’s a bit more difficult.

This is a script to do that (on the website, the swf is opened with a lightbox and the picture is saved) :

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
114
115
116
package {
 
	import com.adobe.images.PNGEncoder;
 
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.external.ExternalInterface;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.utils.ByteArray;
 
        /**
	 * @author Aymeric
	 */
 
	public class CaptureTete extends Sprite {
 
		public var button:Sprite;
 
		private var _cam:Camera;
		private var _video:Video;
 
		private var _bitmapData:BitmapData;
		private var _bitmap:Bitmap;
 
		private var _conteneur:Sprite;
		private var _drawPanel:Sprite;
 
		public function CaptureTete() {
 
			_cam = Camera.getCamera();
			_video = new Video(320, 240);
 
			_bitmapData = new BitmapData(_video.width, _video.height);
			_bitmap = new Bitmap(_bitmapData);
 
			_video.attachCamera(_cam);
			_video.x = _bitmap.x = 20;
			_video.y = _bitmap.y = 40;
 
			addChild(_video);
 
			_conteneur = new Sprite();
			addChild(_conteneur);
 
			_drawPanel = new Sprite();
			_drawPanel.graphics.clear();
			_drawPanel.graphics.lineStyle(2, 0xeea41e);
			_drawPanel.graphics.beginFill(0xDEFACE, 0);
			_drawPanel.graphics.drawCircle(80, 80, 80);
			_drawPanel.graphics.endFill();
			_conteneur.addChild(_drawPanel);
			_drawPanel.x = 100;
			_drawPanel.y = 100;
 
			button.buttonMode = true;
			button.addEventListener(MouseEvent.CLICK, _captureImage);
		}
 
		private function _captureImage(e:MouseEvent):void {
 
                        button.removeEventListener(MouseEvent.CLICK, _captureImage);
 
			_bitmapData.draw(_video);
			_conteneur.addChild(_bitmap);
 
			_conteneur.setChildIndex(_drawPanel, _conteneur.numChildren - 1);
 
			_cam = null;
			removeChild(_video);
			_video = null;
 
			_bitmap.mask = _drawPanel;
 
			_bitmapData = new BitmapData(320, 240,true,0x000000);
			_bitmapData.draw(_conteneur);
 
			var bitmap:Bitmap = new Bitmap(_bitmapData);
			_conteneur.addChild(bitmap);
 
			var bmd:BitmapData = new BitmapData(160, 160);
			var rect:Rectangle = new Rectangle(100, 100, 160, 160);
			bmd.copyPixels(_bitmapData, rect, new Point(0, 0));
 
			var pngStream:ByteArray = PNGEncoder.encode(bmd);
 
			var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
 
			var savePNG:URLRequest = new URLRequest("save.php");
			savePNG.requestHeaders.push(header);
			savePNG.method = URLRequestMethod.POST;
			savePNG.data = pngStream;
 
			var urlLoader:URLLoader = new URLLoader();
			urlLoader.load(savePNG);
 
			urlLoader.addEventListener(Event.COMPLETE, _loaded);
		}
 
		private function _loaded(evt:Event):void {
 
			evt.target.removeEventListener(Event.COMPLETE, _loaded);
			ExternalInterface.call("closeLightbox");
		}
	}
 
}

You can found the external library made by Mike Chambers : as3corelib.

The Php script to save it :

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
 
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
 
	$png = $GLOBALS["HTTP_RAW_POST_DATA"];
	$img = $_GET["img"];
	$filename = "images/img_". mktime(). ".png";
	file_put_contents($filename, $png);
} else {
	echo "Encoded PNG information not received.";
}
 
?>

To go further, we can draw our own circle or an other shape. Using a Php Session for the filename is cool too !
Exemple (don’t worry, I do not save ! 😉 )

Beat the bot

At the Gobelins school, we made a game in less than 5 days. The concept was to create a musical and memory game : a sequencer. We worked in pairs : a developper and a graphic designer, he did a great job !

To developp the game I used the Gaia Framework and made MVC design pattern ! Gaia saves me some precious time : preloader, external loading, swfadress, transition between pages ; and MVC helps cleaning my code.

The game : Beat the bot !

Recently I’m trying to syncrhonize an iPhone with a website using BlazeDS on Google App Engine. I just need to find how can I export a flex project into an ipa… Hope it will be soon ok !

Flash Circle Preloader

A beautiful preloader is important for a flash website. Indeed, if you need to load much data, your preloader will be visible all during this time. And if it is not interssant, visitors may leave your website.

Here are some examples of interesting preloader : http://www.prettyloaded.com.

Most often, preloader are made by graphic designer on 100 frames without using any code.
Developpers integrate them, and use gotoAndStop on an enterFrame to display the loading progression.

This is my circle preloader.
To make this, I used 2 masks moving like the circle. Of course it could be done with code, but it would be a headlock with cosinus and sinus !
You can find the source here.

Playing with Blend Mode

Recently, I tried some BlendMode in AS3. Thanks to them we can reproduce some cool effects of Photshop.
This is a simple script to do that. I thought it’s a nice effect !

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
package {
 
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
 
	[SWF(backgroundColor="#000000", frameRate="31", width="600", height="500")]
 
	/**
	 * @author Aymeric
	 */
 
	public class MouseFollower extends Sprite {
 
		private var _container:Sprite;
 
		private var _bData:BitmapData;
		private var _img:Bitmap;
		private var _circle:Shape;
 
		public function MouseFollower() {
 
			_container = new Sprite();
                        _container.visible = false;
			this.addChild(_container);
 
			_bData = new BitmapData(600, 500, true, 0x00FF00);
 
			_img = new Bitmap(_bData);
 
			_circle = new Shape();
 
			this.addChild(_img);
 
			_container.addChild(_circle);
 
			this.addEventListener(Event.ENTER_FRAME, _ef);
		}
 
		private function _ef(evt:Event):void {
 
			_circle.graphics.clear();
			_circle.graphics.beginFill(Math.random()*0xFFFFFF);
			_circle.graphics.drawCircle(0, 0, 10);
			_circle.graphics.endFill();
 
			var diffx:int =	mouseX - _circle.x;
			var diffy:int = mouseY - _circle.y;
 
			_circle.x +=diffx * 0.05;
			_circle.y +=diffy * 0.05;
 
			_bData.draw(_container, null, null, BlendMode.ADD);
			_bData.applyFilter(_bData, _bData.rect, new Point(), new BlurFilter(5, 5, 2));
		}
	}
}

This two lines are important if you want to keep an eye on your CPU usage :
_circle.graphics.clear();
_circle.graphics.endFill();
BlendMode are more than ever CPU’s eater !