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
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

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/

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/

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

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

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/

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

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
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
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

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.

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
- Get up to $100,000 for your next Flash game with Mochi GAME Developer Fund
- Create a dynamic content animated footer ad for your site in just 9 jQuery lines – 17 lines version
- Sell sitelocked version of your Flash games and even .fla sources to Free Online Games
- Protect your work from ActionScript code theft with SWF Protector
- Create a dynamic content animated footer ad for your site in just 9 jQuery lines
- Understanding Box2D’s one-way platforms, aka CLOUDS
- Triqui MochiAds Arcade plugin for WordPress upgraded to 1.2
- Box2D Flash game creation tutorial – part 2
- 11 Flash isometric engines you can use in your games
- Monetize your Flash games with GamesChart
- Create a Lightbox effect only with CSS - no javascript needed
- Flash game creation tutorial - part 1
- Create a Flash Racing Game Tutorial
- Flash game creation tutorial - part 2
- Make a Flash game like Flash Element Tower Defense - Part 2
- Flash game creation tutorial - part 3
- Make a Flash game like Flash Element Tower Defense - Part 1
- Create a flash draw game like Line Rider or others - part 1
- Triqui MochiAds Arcade plugin for WordPress official page
- Create a flash artillery game - step 1
- Flash game creation tutorial – part 5.2 (4.88/5)
- Create a flash artillery game – step 1 (4.79/5)
- Create a Flash Racing Game Tutorial (4.76/5)
- Create a flash artillery game – step 2 (4.74/5)
- Create a survival horror game in Flash tutorial – part 1 (4.73/5)
- Creation of a Flash arcade site using WordPress – step 2 (4.73/5)
- Flash game creation tutorial – part 2 (4.71/5)
- Flash game creation tutorial – part 1 (4.70/5)
- Create a flash draw game like Line Rider or others – part 1 (4.69/5)
- Creation of a platform game with Flash – step 2 (4.68/5)








