Create an Eskiv Flash game tutorial

Do you know a Flash game called Eskiv? No?

Never mind, it’s not the best game around there, but there is a thread called Eskiv Clone? in the forum asking help in making a game like that one.

First, play it a minute

Then, take this prototype, starting from an old tutorial called Flash game creation tutorial – part 1.

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
_root.attachMovie("score","score",1);
_root.attachMovie("hero", "hero", 2, {_x:250, _y:200});
_root.attachMovie("target", "target", 3, {_x:Math.random()*400+25, _y:Math.random()*300+25});
power = 3;
enemy_power = 5;
points = 0;
hero.onEnterFrame = function() {
	if (Key.isDown(Key.LEFT)) {
		this._x -= power;
	}
	if (Key.isDown(Key.RIGHT)) {
		this._x += power;
	}
	if (Key.isDown(Key.UP)) {
		this._y -= power;
	}
	if (Key.isDown(Key.DOWN)) {
		this._y += power;
	}
};
target.onEnterFrame = function() {
	dist_x = this._x-hero._x;
	dist_y = this._y-hero._y;
	distance = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
	if (distance<(hero._width+this._width)/2) {
		points++;
		score.scoretxt.text = points;
		this._x = Math.random()*400+25;
		this._y = Math.random()*300+25;
		foe = _root.attachMovie("enemy", "enemy", _root.getNextHighestDepth(), {_x:Math.random()*400+25, _y:Math.random()*300+25});
		foe.dir = Math.floor(Math.random()*4);
		foe.onEnterFrame = function() {
			switch (this.dir) {
			case 0 :
				this._x += enemy_power;
				if (this._x>500-this._width/2) {
					this.dir = 1;
				}
				break;
			case 1 :
				this._x -= enemy_power;
				if (this._x<0+this._width/2) {
					this.dir = 0;
				}
				break;
			case 2 :
				this._y += enemy_power;
				if (this._y>400-this._width/2) {
					this.dir = 3;
				}
				break;
			case 3 :
				this._y -= enemy_power;
				if (this._y<0+this._width/2) {
					this.dir = 2;
				}
				break;
			}
			dist_x = this._x-hero._x;
			dist_y = this._y-hero._y;
			distance = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
			if (distance<(hero._width+this._width)/2) {
				points--;
				score.scoretxt.text = points;
				this.removeMovieClip();
			}
		};
	}
};

And this is the result

Move the purple ball with arrow keys and take the red one. Avoid blue ones and score as much as you can.

This version has better collision detection than the original one

Download and play with it

Marketing Flash games: email template

When you make a Flash game, unless it hits top portals frontpages (like NewGrounds) and spreads virally, you have to submit it to thousands portals in order to give it some decent exposure.

At the moment the best resource about Flash game marketing is Marketing Flash Games: The Other Half of the Battle, but if you’re not into marketing, you will also need a mail template.

I was (heavily) inspired by the creator of Kullors and this is an email template that should work the first time (you’ll understand later why)

[greeting]
Hi

[brief ice breaker]
My Latest game (gamename) has just (been released/completed a 7 day exclusive license/etc) and I am now able to distribute the game freely. As such I would be most grateful if you were to consider it for inclusion on your website/Game Portal.

[brief game description]
(gamename) is (about 20 words to describe it)

[links to play and download]
You can play it at (link) and you can download a zip file containing the swf a txt description and game icons of various sizes in gif format at (link).

[encourage feed back]
If you have any questions or comments I would more than happy to hear from you.

[thank ]
Many thanks for your time and consideration

[close]
Kind regards
(your name)

Now just two or three (well… three!) considerations:

1) The link to the game to play should be the one of an important portal only if the game has good rating/reviews… you don’t want the portal owner going to play your game at Kongregate just to read players don’t like it

2) This, as said, is the template for the first email you will send to the portal. Once they reply, if they do, save the contact of the person who replied and try to establish a contact more… let’s say “human” than a “developer to portal owner” one.

This will help you when you will need to release future games. Remember that good marketers don’t have millions of contacts. They have some good contacts. When I need some information about MochiAds, I don’t look for an invisible “contact us” button… I write to Ada. When I want to show my new game to AddictingGames, I write to Justin… and so on. Make your own priceless contact list and your life will be easier

3) When you managed to have a good contact list, remember they are not your classmates. Don’t bother them with “I have a new girlfriend!” and don’t submit them bad games just because you think they will publish anything you produce since they are friends of yours

Follow those rules and your games marketing will reach a new level.

Finding adjacent cells in an hex map – part 2

In the Finding adjacent cells in an hex map post I showed you how to find adjacent cells in horizontal hex maps.

Now it’s time to find adjacent cells in vertical hex maps.

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
hexagon_width = 44;
hexagon_height = 38;
grid_x_size = 10;
grid_y_size = 12;
sector_width = hexagon_width/4*3;
sector_height = hexagon_height;
gradient = (hexagon_width/4)/(hexagon_height/2);
for (x=0; x<grid_x_size; x++) {
	for (y=0; y<grid_y_size; y++) {
		hexagon_x_position = hexagon_width*y/4*3;
		hexagon_y_position = hexagon_height*x+(y%2)*hexagon_height/2;
		hexagon_number = y+x*grid_y_size;
		hexagon_movieclip = attachMovie("hhexagon", "hhexagon_"+hexagon_number, hexagon_number, {_x:hexagon_x_position, _y:hexagon_y_position});
		hexagon_movieclip.gotoAndStop(1);
		hexagon_movieclip.txt.text = hexagon_number;
	}
}
onEnterFrame = function () {
	_root["hhexagon_"+hexagon_hover].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+1)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-1)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+11)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+12)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+13)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-11)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-12)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-13)].gotoAndStop(1);
	sector_x = Math.floor(_xmouse/sector_width);
	sector_y = Math.floor(_ymouse/sector_height);
	delta_sector_x = _xmouse%sector_width;
	delta_sector_y = _ymouse%sector_height;
	switch (sector_x%2) {
		case 1 :
			if (delta_sector_y>=hexagon_height/2) {
				if (delta_sector_x>(hexagon_width/2-delta_sector_y*gradient)) {
					real_x = sector_x;
					real_y = sector_y;
				}
				else {
					real_x = sector_x-1;
					real_y = sector_y;
				}
			}
			else {
				if (delta_sector_x<delta_sector_y*gradient) {
					real_x = sector_x-1;
					real_y = sector_y;
				}
				else {
					real_x = sector_x;
					real_y = sector_y-1;
				}
			}
			break;
		case 0 :
			real_x = sector_x;
			real_y = sector_y;
			if (delta_sector_x<((hexagon_width/4)-delta_sector_y*gradient)) {
				real_x = sector_x-1;
				real_y = sector_y-1;
			}
			if (delta_sector_x<((-hexagon_width/4)+delta_sector_y*gradient)) {
				real_x = sector_x-1;
				real_y = sector_y;
			}
			break;
	}
	if ((real_x>=0) and (real_x<grid_y_size) and (real_y>=0) and (real_y<grid_x_size)) {
		hexagon_hover = real_x+real_y*grid_y_size;
		_root["hhexagon_"+hexagon_hover].gotoAndStop(2);
		if(hexagon_hover%grid_y_size!=grid_y_size-1){
			_root["hhexagon_"+(hexagon_hover+1)].gotoAndStop(3);
		}
		if(hexagon_hover%grid_y_size!=0){
			_root["hhexagon_"+(hexagon_hover-1)].gotoAndStop(3);
		}
		if (hexagon_hover%2 == 0) {
			_root["hhexagon_"+(hexagon_hover-11)].gotoAndStop(3);
			if(hexagon_hover%grid_y_size!=0){
				_root["hhexagon_"+(hexagon_hover-13)].gotoAndStop(3);
			}
			_root["hhexagon_"+(hexagon_hover+12)].gotoAndStop(3);
			_root["hhexagon_"+(hexagon_hover-12)].gotoAndStop(3);
		}
		else {
			if(hexagon_hover%grid_y_size!=grid_y_size-1){
				_root["hhexagon_"+(hexagon_hover+13)].gotoAndStop(3);
			}
			_root["hhexagon_"+(hexagon_hover+11)].gotoAndStop(3);
			_root["hhexagon_"+(hexagon_hover+12)].gotoAndStop(3);
			_root["hhexagon_"+(hexagon_hover-12)].gotoAndStop(3);		
		}
	}
};

Here it is:

This is the last uncommented step, during next one we will discuss about the method used to determine adjacent cells.

Download and enjoy!!

Play Flash games on Triqui.com

What I introduced in the Ramblings about Flash game portals post went live today

Triqui

I am talking about a game portal called Triqui, where you will find all MochiAds games. Well, not exactly “all”, but every game listed in their feeds.

Why did I made the millionth Flash games portal? Because I want to play a bit with this new toy, because I want to make an experiment about sponsoring games (why do portals sponsor a game?) and something more.

The entire design sucks a bit, but the entire project has only 63 (yes! sixtythree!!) php lines

I will add some new features soon (game rankings, comments, reviews…), then I’ll release the source code, so anyone can have its portal.

It’s completely automated: every day it reads from MochiAds feed, adds new games in a MySql database and it’s ready for a brand new feature Mochi guys will release in the next future.

Of course the goal is monetizing the portal… any idea?

Flash physics engines galore

Are you looking for a Flash physics engine?

Well, now you only have to choose the one you prefer.

Let’s see how many engines we have (listed in alphabetical order):

APE: www.cove.org/ape/index.htm

APE

Free AS3 open source 2D physics engine for use in Flash and Flex, released under the MIT License.
Its last update (0.45 alpha) is dated June 2007. Anyway, it’s the one with the most active community at Google Groups.

You can also find two tutorials on my blog here and here

Box2DFlashAS3: box2dflash.sourceforge.net/

Box2DFlashAS3

Open source port of Erin Catto’s powerful c++ physics library Box2D, it’s the most updated engine at the moment with its latest 2.0.0 version.

The Flash engine does not have a good documentation but you can start studying original Box2D manual

I wrote a tutorial on this engine here

Fisix Engine: www.fisixengine.com/

Fisix

Currently at 0.5 (alpha) version, provides an interesting documentation and some of the most complete demos.

It’s not freeware, though.

FOAM: blog.generalrelativity.org/?p=17

FOAM

According to the author, it’s in fact not a physics engine but an interface for simulating physics.

Its version is Alpha 0.1

In the zipped source you will find the API documentation and the source code is very well commented.

It seems interesting, too bad the demos are poor

glaze: yaa-blog.blogspot.com/search/label/Glaze

glaze

It’s interesting to know the author wrote this engine to make the remake of an old game called Exile

motor: lab.polygonal.de/2007/12/31/motor-physics-released/

motor

Another porting of Erin Catto’s Box2D

The author is currently working on motor2, just after a couple of months he released the first version, so the projects seems well supported

PopShapes: lab.andre-michelle.com/physics-engine

PopShapes

More an experiment than an engine, from its source you can learn how to make your own physics engine

Which one will you use?

Finding adjacent cells in an hex map

This tutorial continues Hex maps creation and rollover.

Now I will show you how find adjacent cells. Again, at the moment it’s only code, and it only works for horizontal hex maps

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
hexagon_width = 38;
hexagon_height = 44;
grid_x_size = 12;
grid_y_size = 10;
sector_width = hexagon_width;
sector_height = hexagon_height/4*3;
gradient = (hexagon_height/4)/(hexagon_width/2);
for (x=0; x<grid_x_size; x++) {
	for (y=0; y<grid_y_size; y++) {
		hexagon_x_position = hexagon_width*x+(y%2)*hexagon_width/2;
		hexagon_y_position = hexagon_height*y/4*3;
		hexagon_number = x+y*grid_x_size;
		hexagon_movieclip = attachMovie("hhexagon", "hhexagon_"+hexagon_number, hexagon_number, {_x:hexagon_x_position, _y:hexagon_y_position});
		hexagon_movieclip.gotoAndStop(1);
		hexagon_movieclip.txt.text = hexagon_number;
	}
}
onEnterFrame = function () {
	_root["hhexagon_"+hexagon_hover].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+1)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-1)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+11)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+12)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover+13)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-11)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-12)].gotoAndStop(1);
	_root["hhexagon_"+(hexagon_hover-13)].gotoAndStop(1);
	sector_x = Math.floor(_xmouse/sector_width);
	sector_y = Math.floor(_ymouse/sector_height);
	delta_sector_x = _xmouse%sector_width;
	delta_sector_y = _ymouse%sector_height;
	switch (sector_y%2) {
	case 1 :
		if (delta_sector_x>=hexagon_width/2) {
			if (delta_sector_y<(hexagon_height/2-delta_sector_x*gradient)) {
				real_x = sector_x;
				real_y = sector_y-1;
			} else {
				real_x = sector_x;
				real_y = sector_y;
			}
		} else {
			if (delta_sector_y<delta_sector_x*gradient) {
				real_x = sector_x;
				real_y = sector_y-1;
			} else {
				real_x = sector_x-1;
				real_y = sector_y;
			}
		}
		break;
	case 0 :
		real_x = sector_x;
		real_y = sector_y;
		if (delta_sector_y<((hexagon_height/4)-delta_sector_x*gradient)) {
			real_x = sector_x-1;
			real_y = sector_y-1;
		}
		if (delta_sector_y<((-hexagon_height/4)+delta_sector_x*gradient)) {
			real_x = sector_x;
			real_y = sector_y-1;
		}
		break;
	}
	if ((real_x>=0) and (real_x<grid_x_size) and (real_y>=0) and (real_y<grid_y_size)) {
		hexagon_hover = real_x+real_y*grid_x_size;
		_root["hhexagon_"+hexagon_hover].gotoAndStop(2);
		if (hexagon_hover%grid_x_size != grid_x_size-1) {
			_root["hhexagon_"+(hexagon_hover+1)].gotoAndStop(3);
		}
		if (hexagon_hover%grid_x_size != 0) {
			_root["hhexagon_"+(hexagon_hover-1)].gotoAndStop(3);
		}
		if (Math.floor(hexagon_hover/grid_x_size)%2 == 0) {
			if (hexagon_hover%grid_x_size != 0) {
				_root["hhexagon_"+(hexagon_hover+11)].gotoAndStop(3);
				_root["hhexagon_"+(hexagon_hover-13)].gotoAndStop(3);
			}
			_root["hhexagon_"+(hexagon_hover+12)].gotoAndStop(3);
			_root["hhexagon_"+(hexagon_hover-12)].gotoAndStop(3);
		} else {
			if (hexagon_hover%grid_x_size != grid_x_size-1) {
				_root["hhexagon_"+(hexagon_hover+13)].gotoAndStop(3);
				_root["hhexagon_"+(hexagon_hover-11)].gotoAndStop(3);
			}
			_root["hhexagon_"+(hexagon_hover+12)].gotoAndStop(3);
			_root["hhexagon_"+(hexagon_hover-12)].gotoAndStop(3);
		}
	}
};

and this is the result:

While I am optimizing the code and writing the routines for the vertical hex maps, James Prankard sent me the AS3 version of the code published in the Hex maps creation and rollover tutorial

Here it is:

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
// Container so you can easily getChildAt
var hexagon_container:MovieClip = new MovieClip();
addChild(hexagon_container);
// Declare variables
var hexagon_width:int = 38;
var hexagon_height:int = 44;
var hexagon_number = 0;
var grid_x_size:int = 12;
var grid_y_size:int = 10;
var sector_width:Number = hexagon_width;
var sector_height:Number = hexagon_height/4*3;
var gradient:Number = (hexagon_height/4)/(hexagon_width/2)
var hexagon_hover:Number = 0;
// Changed the y and x for loop to add the hexagons in the correct way for getChildAt
for (var y_pos:int =0; y_pos<grid_y_size; y_pos++) {
	for (var x_pos:int =0; x_pos<grid_x_size; x_pos++) {
		var hexagon_x_position:Number = hexagon_width*x_pos+(y_pos%2)*hexagon_width/2;
		var hexagon_y_position:Number = hexagon_height*y_pos/4*3;
		hexagon_number = x_pos+y_pos*grid_x_size;
		var hexagon:hhexagon = new hhexagon();
		hexagon_container.addChild(hexagon);
		hexagon.x = hexagon_x_position;
		hexagon.y = hexagon_y_position;
		hexagon.txt.text = hexagon_number;
		hexagon.gotoAndStop(1);
	}
}
 
addEventListener("enterFrame", enterFramer)
 
function enterFramer(event:Event):void {
	// Get replaces the lastFrame's tile with a blank one
	MovieClip(hexagon_container.getChildAt(hexagon_hover)).gotoAndStop(1);
	// Declare vars (enterFrame)
	var sector_x:Number = Math.floor(mouseX/sector_width);
	var sector_y:Number = Math.floor(mouseY/sector_height);
	var delta_sector_x:Number = mouseX%sector_width;
	var delta_sector_y:Number = mouseY%sector_height;
	var real_x:Number;
	var real_y:Number;
	switch(sector_y%2){
		case 1:
			if(delta_sector_x>=hexagon_width/2){
				if(delta_sector_y<(hexagon_height/2-delta_sector_x*gradient)){
					real_x = sector_x;
					real_y = sector_y-1;
				}
				else{
					real_x = sector_x;
					real_y = sector_y;
				}
			}
			else{
				if(delta_sector_y<delta_sector_x*gradient){
					real_x = sector_x;
					real_y = sector_y-1;
				}
				else{
					real_x = sector_x-1;
					real_y = sector_y;
				}
			}
			break;
		case 0:
			real_x = sector_x;
			real_y = sector_y;
			if(delta_sector_y<((hexagon_height/4)-delta_sector_x*gradient)){
				real_x = sector_x-1;
				real_y = sector_y-1;
			}
			if(delta_sector_y<((-hexagon_height/4)+delta_sector_x*gradient)){
				real_x = sector_x;
				real_y = sector_y-1;
			}
			break;
	}
	if((real_x>=0)&&(real_x<grid_x_size)&&(real_y>=0)&&(real_y<grid_y_size)){
		hexagon_hover = real_x+real_y*grid_x_size;
		// Re-adds new hovering tile with red
		MovieClip(hexagon_container.getChildAt(hexagon_hover)).gotoAndStop(2);
	}
};

Download the source codes and experiment

Creation of a sortable list with Ajax tutorial

One interesting Web 2.0 effect is the sortable list, and we are going to make one in less than five minutes thanks to Prototype and script.aculo.us libraries.

Prototype is a JavaScript Framework that aims to ease development of dynamic web applications and can be downloaded here, while script.aculo.us (scriptaculous from now on) provides you with easy-to-use, cross-browser user interface JavaScript libraries to make your web sites and web applications fly and can be downloaded here.

This tutorial is based on zen of shen’s pseudocode found at script.aculo.us Ajax Sortable Lists Tutorial.

This tutorial will show real code and a step by step guide through MySql, php and Ajax coding in order to create your sortable list.

Of course your hosting plan must allow you to use php and MySql, so refer to your hosting provider if you don’t know if your web space supports those features.

MYSQL

First we need to work on the database to create the table that will store our list. I made the simplest table ever, because it’s just an example, but you can add as many columns as you want, in order to fit the table to your needs.

My table only has three fields: the primary key id, the name of the list element color and the core column, the one where you will save the order of the elements, called, in a lack of creativity, color_order. Read more

Hex maps creation and rollover

This is just a quick, uncommented snippet of code I made starting from Coordinates in Hexagon-Based Tile Maps tutorial I found at GameDev.net.

The article does not cover all hex maps, just horizontal ones. Read Understanding hexagonal tiles to know something more about hex maps.

Also, the pseudo code shown in the article has some errors, but I finally managed to have a working, full math hex maps creation and rollover.

No line comments at the moment as said, because I still have to optimize the code and write the routine to generate vertical hex maps, meanwhile take a look at it:

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
hexagon_width = 38;
hexagon_height = 44;
grid_x_size = 12;
grid_y_size = 10;
sector_width = hexagon_width;
sector_height = hexagon_height/4*3;
gradient = (hexagon_height/4)/(hexagon_width/2)
for (x=0; x<grid_x_size; x++) {
	for (y=0; y<grid_y_size; y++) {
		hexagon_x_position = hexagon_width*x+(y%2)*hexagon_width/2;
		hexagon_y_position = hexagon_height*y/4*3;
		hexagon_number = x+y*grid_x_size;
		hexagon_movieclip = attachMovie("hhexagon", "hhexagon_"+hexagon_number, hexagon_number, {_x:hexagon_x_position, _y:hexagon_y_position});
		hexagon_movieclip.gotoAndStop(1);
		hexagon_movieclip.txt.text = hexagon_number;
	}
}
onEnterFrame = function() {
	_root["hhexagon_"+hexagon_hover].gotoAndStop(1);
	sector_x = Math.floor(_xmouse/sector_width);
	sector_y = Math.floor(_ymouse/sector_height);
	delta_sector_x = _xmouse%sector_width;
	delta_sector_y = _ymouse%sector_height;
	switch(sector_y%2){
		case 1:
			if(delta_sector_x>=hexagon_width/2){
				if(delta_sector_y<(hexagon_height/2-delta_sector_x*gradient)){
					real_x = sector_x;
					real_y = sector_y-1;
				}
				else{
					real_x = sector_x;
					real_y = sector_y;
				}
			}
			else{
				if(delta_sector_y<delta_sector_x*gradient){
					real_x = sector_x;
					real_y = sector_y-1;
				}
				else{
					real_x = sector_x-1;
					real_y = sector_y;
				}
			}
			break;
		case 0:
			real_x = sector_x;
			real_y = sector_y;
			if(delta_sector_y<((hexagon_height/4)-delta_sector_x*gradient)){
				real_x = sector_x-1;
				real_y = sector_y-1;
			}
			if(delta_sector_y<((-hexagon_height/4)+delta_sector_x*gradient)){
				real_x = sector_x;
				real_y = sector_y-1;
			}
			break;
	}
	if((real_x>=0)and(real_x<grid_x_size)and(real_y>=0)and(real_y<grid_y_size)){
		hexagon_hover = real_x+real_y*grid_x_size;
		_root["hhexagon_"+hexagon_hover].gotoAndStop(2);
	}
};

And see how does it work

Download the source code.

From zero to Bombuzal – step 5

This 5th step is kinldy produced by Frederik J, who decided to upgrade the game with some new features

Recently I was looking in some old posts on your site, and saw the bombuzal step 4.

It hasn’t been finished, and because I think it wasn’t a hard task i took it!

Here it is, finished – now you can drop and pickup bombs, and you can also explode them if space is down for more than two seconds.

This comes before my main upgrade that will allow to play a complete level, and it has comments in the code for your understanding

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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
//create an invisible movie clip across the entire stage using API
_root.createEmptyMovieClip("base", 1);
with (base) {
	lineStyle(2, 0x0000000, 0);
	beginFill(0x00000000, 0);
	lineTo(Stage.width, 0);
	lineTo(Stage.width, Stage.height);
	lineTo(0, Stage.height);
	lineTo(0, 0);
}
//whether to pan or not
level_pan = false;
//tile size
tile_size = 50;
// pan variables
pan_dist = 50;
pan_speed = 5;
// tiles array generation
tiles = [[0, 1, 0, 0], [1, 1, 2, 1], [1, 2, 1, 2], [0, 0, 1, 0]];
// bombs array generation
bombs = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]];
// main sprite
// xpos: bombuzal x position
// ypos: y position
// moving: bombuzal is moving or not
// facing: the side bombuzal is facing on
bombuzal_obj = {xpos:0, ypos:1, moving:false, facing:"right"};
//space down variable for checking if space is down for more
//than two seconds
space_down = false;
//time variable for checking how long space has been down
space_time = 0;
// bombuzal walk speed, in pixels/frame
walk_speed = 5;
// time passed since bombuzal last move
does_not_move = 0;
// creating the level movieclip
_root.createEmptyMovieClip("level", _root.getNextHighestDepth());
// placing tiles
for (x=0; x<tiles.length; x++) {
	for (y=0; y<tiles[x].length; y++) {
		// notice as it's not [x][y] but [y][x]
		if (tiles[y][x]) {
			placed = level.attachMovie("tile", "tile_"+(x*tiles.length+y), level.getNextHighestDepth(), {_x:x*tile_size, _y:y*tile_size});
			placed.gotoAndStop(tiles[y][x]);
		}
	}
}
// placing bombs
//MODIFIED 
//CHANGED:
/*for (x=0; x<bombs.length; x++) {
for (y=0; y<bombs[x].length; y++) {
if (bombs[y][x]) {
level.attachMovie("bomb", "bomb"+level.getNextHighestDepth(), level.getNextHighestDepth(), {_x:x*tile_size, _y:y*tile_size});
}
}
}*/
//TO:
for (x=0; x<bombs.length; x++) {
	for (y=0; y<bombs[x].length; y++) {
		if (bombs[y][x]) {
			level.attachMovie("bomb", "bomb"+x+"_"+y, level.getNextHighestDepth(), {_x:x*tile_size, _y:y*tile_size});
		}
	}
}
// placing bombuzal
level.attachMovie("bombuzal", "bombuzal", level.getNextHighestDepth(), {_x:bombuzal_obj.xpos*tile_size, _y:bombuzal_obj.ypos*tile_size});
level.bombuzal.onEnterFrame = function() {
	// if bombuzal is not alread moving...
	if (!bombuzal_obj.moving) {
		// incrementing counter
		does_not_move++;
		// if 150 frames has passed and bombuzal did not move..
		if (does_not_move == 150) {
			bombuzal_obj.moving = true;
			// choosing a random direction
			moving_direction = Math.floor(Math.random()*4)+1;
			switch (moving_direction) {
			case 1 :
				bombuzal_obj.facing = "left";
				break;
			case 2 :
				bombuzal_obj.facing = "right";
				break;
			case 3 :
				bombuzal_obj.facing = "up";
				break;
			case 4 :
				bombuzal_obj.facing = "down";
				break;
			}
		}
		// moving left       
		if (Key.isDown(Key.LEFT)) {
			bombuzal_obj.moving = true;
			bombuzal_obj.facing = "left";
		}
		// moving right                     
		if (Key.isDown(Key.RIGHT)) {
			bombuzal_obj.moving = true;
			bombuzal_obj.facing = "right";
		}
		// moving down                     
		if (Key.isDown(Key.DOWN)) {
			bombuzal_obj.moving = true;
			bombuzal_obj.facing = "down";
		}
		// moving up                     
		if (Key.isDown(Key.UP)) {
			bombuzal_obj.moving = true;
			bombuzal_obj.facing = "up";
		}
		// else, if it's moving...         
	} else {
		does_not_move = 0;
		switch (bombuzal_obj.facing) {
			// moving left
		case "left" :
			dx = -1;
			dy = 0;
			this._x -= walk_speed;
			break;
			// moving right
		case "right" :
			dx = 1;
			dy = 0;
			this._x += walk_speed;
			break;
			// moving up
		case "up" :
			dx = 0;
			dy = -1;
			this._y -= walk_speed;
			break;
			// moving down
		case "down" :
			dx = 0;
			dy = 1;
			this._y += walk_speed;
			break;
		}
		// if bombuzal walked for an entire tile...
		if ((this._x%tile_size == 0) and (this._y%tile_size == 0)) {
			// stop moving bombuzal
			bombuzal_obj.moving = false;
			// checking if bombuzal just walked a disappearing tile
			if (tiles[bombuzal_obj.ypos][bombuzal_obj.xpos] == 2) {
				// remove tile
				tiles[bombuzal_obj.ypos][bombuzal_obj.xpos] = 0;
				level["tile_"+(bombuzal_obj.xpos*tiles.length+bombuzal_obj.ypos)].removeMovieClip();
			}
			// increase bombuzal x and y position according to its direction  
			bombuzal_obj.xpos += dx;
			bombuzal_obj.ypos += dy;
			update_bombuzal_position();
		}
	}
	if (Key.isDown(Key.SPACE) && !bombuzal_obj.moving && !space_down) {
		//call handle bombs
		handle_bombs();
		//set spacedown to true
		space_down = true;
	}
	if (space_down && !Key.isDown(Key.SPACE)) {
		//set space down to false
		space_down = false;
		//set space time to 0
		space_time = 0;
	}
	//if space is down 
	if (space_down) {
		//increase it by one
		space_time++;
		//if its bigger than 60 (ie. 2 seconds)
		if (space_time>=60) {
			//then explode bombs
			explode_bombs();
		}
	}
};
// centering level
level._x = (Stage.width-tiles.length*tile_size)/2;
level._y = (Stage.height-tiles[0].length*tile_size)/2;
level.onEnterFrame = function() {
	//if mouse is on stage
	if (level_pan) {
		//stopping level leaving screen
		//too high
		if (level._y<=0) {
			level._y = 0;
		}
		//too low                                      
		if (level._y>=Stage.height-level._height) {
			level._y = Stage.height-level._height;
		}
		//too far to the left                                      
		if (level._x<=0) {
			level._x = 0;
		}
		//too far to the right                                      
		if (level._x>=Stage.width-level._width) {
			level._x = Stage.width-level._width;
		}
		// panning level                                      
		// pan right
		if (_root._xmouse<pan_dist) {
			level._x += pan_speed;
		}
		// pan left                                      
		if (_root._xmouse>Stage.width-pan_dist) {
			level._x -= pan_speed;
		}
		// pan down                                      
		if (_root._ymouse<pan_dist) {
			level._y += pan_speed;
		}
		// pan up                                      
		if (_root._ymouse>Stage.height-pan_dist) {
			level._y -= pan_speed;
		}
	}
};
//when mouse is on stage pan
base.onRollOver = function() {
	level_pan = true;
};
//when mouse leaves stage stop panning
base.onRollOut = function() {
	level_pan = false;
};
//function that handles bombs
function handle_bombs() {
	//if theres a bomb on the tile
	if (bombs[bombuzal_obj.ypos][bombuzal_obj.xpos] == 1) {
		//pickup bomb
		//remove the bomb
		_root.level["bomb"+bombuzal_obj.xpos+"_"+bombuzal_obj.ypos].removeMovieClip();
		//set the bomb array[y][x] to 0
		bombs[bombuzal_obj.ypos][bombuzal_obj.xpos] = 0;
	} else {
		//place bomb
		placed = _root.level.attachMovie("bomb", "bomb"+bombuzal_obj.xpos+"_"+bombuzal_obj.ypos, _root.level.getNextHighestDepth());
		placed._x = bombuzal_obj.xpos*tile_size;
		placed._y = bombuzal_obj.ypos*tile_size;
		//add to bomb array
		bombs[bombuzal_obj.ypos][bombuzal_obj.xpos] = 1;
	}
}
function explode_bombs() {
	//loop through bomb array
	for (x=0; x<bombs.length; x++) {
		for (y=0; y<bombs[x].length; y++) {
			if (bombs[y][x]) {
				//remove the bomb
				_root.level["bomb"+x+"_"+y].removeMovieClip();
				//set space_time to 0
				space_time = 0;
				/*
				Place here for what to do when a bomb explodes, ie.
				check if tile under is class - if then remove it.
				- Just and example....
				*/
			}
		}
	}
}
// update bombuzal position
function update_bombuzal_position() {
	// if bombuzal falls off the stage...
	if ((tiles[bombuzal_obj.ypos][bombuzal_obj.xpos] == undefined) or (tiles[bombuzal_obj.ypos][bombuzal_obj.xpos]<1)) {
		// reset bombuzal to its starting position
		bombuzal_obj.xpos = 0;
		bombuzal_obj.ypos = 1;
		level.bombuzal._x = bombuzal_obj.xpos*tile_size;
		level.bombuzal._y = bombuzal_obj.ypos*tile_size;
		update_bombuzal_position();
	}
}

And here it is:

Download the source and say thanks to Frederik

Understanding hexagonal tiles

You should already know Tile Maps: they are often used for the level design in two-dimensional games.

The most used (and simplest) tiling system has squares. Tileball is an example of a game made with this method.

Even if there are a lot of games using this tiling system, it’s easy to find its limit. All movements are restricted to four directions: up, down, left, right.

Some more complex games require a more complex tiling system.

That’s why I am introducing you the hexagon based tile system (hex maps from now on)

Wkipedia explains us the advantage of a hex map over a square grid map is that the distance between the center of each hex cell and the center of all six adjacent hex cells remains constant. Compare this to a square grid map where the distance from the center of each square cell (of side length x) to the center of its four diagonal adjacent cells is longer than the distance to the center of its four cardinal adjacent cells (x√2 instead of x).

It’s nothing new, because you may find hex maps in Gettysburg, a board game released in 1958 (yes: half a century ago), as you can see in the photo showing the 125th Anniversary Edition of the game

Gettysburg

Back to computer games, you can play The Battle for Wesnoth, a free turn based strategy game designed in June 2003 by David White using hex maps

Wesnoth

Now that we know hex maps are important, let’s see what is an hexagon: in geometry, a hexagon is a polygon with six edges and six vertices. When the six sides of an hexagon have the same length, we are talking about a regular hexagon.

Regular hexagon properties

Hexagon

As you can see, if all sides have the same lenght, we can say the total length of the hexagon is:

Total length = Side + 2*(Side*sin(30°)) = Side + 2*0.5 = 2*Side

And the total height is:

Total height = 2*(Side*cos(60°))

Now, it’s important to know we can tile hexagons in two ways: I don’t think someone already gave a name to the ways you can tile hexagons, so I will call H-hex map a map made tiling hexagons horizontally and V-hex map a map made tiling hexagons vertically, just like in the picture.

Hexagon tiling

Obviously, each map has its own way to manage tiles.

And that’s all… obviously I am about to code everything in Actionscript, meanwhile if you have some code to share, show the world you are awesome

Next Page →

flash games company