How to generate friendly URLs with .htaccess – part 2

Once you read part 1, you should know how to have a friendly url to play a game in your Flash game portal.

In the previous example, I showed you how to transform this link:

http://www.triqui.com/play.php?id=1713

into this one:

http://www.triqui.com/id/1713/

playing with .htaccess file

This is called “friendly” url, and now I’ll show you how to improve it. Starting from…

Your database game table

There are thousands of ways you can store your games data into your database, but all should follow a rule that in the table that stores your games information you have a column where you saved the game name.

No matter if you called the table “games” or “entries” or “bananas” and you called the column “game_name” or “title” or “apples”… you should have a table with all games with a column for the game name. Read more

How to generate friendly URLs with .htaccess

Ok, now you have your own game portal. Let’s call it triqui.com.

You want to share a link with your friends, or want search engine to index it properly.

If I want you to play Jamag, I have to give you this link
http://www.triqui.com/play.php?id=1713.
Now, I would like you to tell me how can you understand I am talking about Jamag from this link http://www.triqui.com/play.php?id=1713.
You can’t.

Now let’s understand why I have to write that play.php?id=xxxx to play a game.

All information about the games is stored in a database, and every game has an unique id assigned by the script.

Jamag’s id is 1713, so when I pass this value, the php script knows where to retrieve information about the game.

If you want to play Jamag on Kongregate, this is the link:
http://www.kongregate.com/games/triqui/jamag.

Seems like Kongregate has a directory to store my games (triqui) and a subdirectory for every game I made. Read more

Managing multiple balls collisions with Flash: AS3 version

Some days ago Sunil Changrani sent me a the script to manage multiple balls collisions with Flash, in AS2.

Now, it’s time for Andrew Cook to give us the AS3 version.

Hi Emanuele,

I’ve been coming to your blog for over a year now. I am doing a new game with Ball vs. Ball collision and turn to your tutorials for help. I am programming my game in AS3, so I reprogrammed the tutorial in AS3. I thought you might want to check it out. There are three files. The main .fla, a document class, and a Ball class.

Thank you for starting your great blog that helps developers like me all the time. I really appreciate the way you give back to the development community. Keep it up!

This is the script to solve collisions: Read more

Flash flood fill implementation

Do you know what is the flood fill algorithm?

From Wikipedia: Flood fill, also called seed fill, is an algorithm that determines the area connected to a given node in a multi-dimensional array. It is used in the "bucket" fill tool of paint programs to determine which parts of a bitmap to fill with color, and in puzzle games such as Minesweeper, Puyo Puyo, Lumines, and Magical Drop for determining which pieces are cleared.

So now you know there is an algorithm to manage some issues in "click somewhere and..." games.

Let's make it!

My version of the algorithm looks for all light grey tiles (two-dimensional array elements) which are connected to the starting light grey tile (the one we click) by a path of same tiles, and changes them to pink.

It's a ricorsive algorithm acting this way: if the clicked tile is grey, then turn it into pink, then act as we clicked the tile at the top of the clicked tile, the one at the bottom, the one at the left and the one and the right. This is called 4-directions flood fill, because we extend the flooding to four directions (up, down, left, right).

You can also perform a 8-directions flood fill, extending the flooding to the original four directions plus the four diagonals

Look at this actionscript:

ACTIONSCRIPT:
  1. fill_map = new Array();
  2. fill_map[0] = [1, 1, 1, 1, 1, 1, 1, 1, 1];
  3. fill_map[1] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  4. fill_map[2] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  5. fill_map[3] = [1, 0, 0, 1, 0, 0, 0, 0, 1];
  6. fill_map[4] = [1, 1, 1, 0, 0, 0, 1, 1, 1];
  7. fill_map[5] = [1, 0, 0, 0, 0, 1, 0, 0, 1];
  8. fill_map[6] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  9. fill_map[7] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  10. fill_map[8] = [1, 1, 1, 1, 1, 1, 1, 1, 1];
  11. for (y=0; y<9; y++) {
  12.     for (x=0; x<9; x++) {
  13.         tile = _root.attachMovie("tile", "tile_"+(y+x*9), _root.getNextHighestDepth(), {_x:y*50, _y:x*50});
  14.         tile.gotoAndStop(1+fill_map[x][y]);
  15.     }
  16. }
  17. _root.attachMovie("cursor", "cursor", _root.getNextHighestDepth());
  18. cursor.onEnterFrame = function() {
  19.     this._x = 50*Math.floor(_root._xmouse/50);
  20.     this._y = 50*Math.floor(_root._ymouse/50);
  21. };
  22. _root.onMouseDown = function() {
  23.     pos_x = Math.floor(_root._xmouse/50);
  24.     pos_y = Math.floor(_root._ymouse/50);
  25.     flood_fill(pos_x, pos_y);
  26. };
  27. function flood_fill(x, y) {
  28.     pos = x+y*9;
  29.     if (fill_map[y][x] == 0) {
  30.         fill_map[y][x] = 2;
  31.         _root["tile_"+(x+y*9)].gotoAndStop(3);
  32.         flood_fill(x+1,y);
  33.         flood_fill(x-1,y);
  34.         flood_fill(x,y+1);
  35.         flood_fill(x,y-1);
  36.     }
  37. }

The 4-directions flood function goes from line 27 to line 37 and allows me to paint grey areas this way:

As you can see, you can paint only one "room" at time because the diagonal "walls" does not allow the four direction flood to paint everywhere.

Look at the 8-directions flood:

ACTIONSCRIPT:
  1. fill_map = new Array();
  2. fill_map[0] = [1, 1, 1, 1, 1, 1, 1, 1, 1];
  3. fill_map[1] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  4. fill_map[2] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  5. fill_map[3] = [1, 0, 0, 1, 0, 0, 0, 0, 1];
  6. fill_map[4] = [1, 1, 1, 0, 0, 0, 1, 1, 1];
  7. fill_map[5] = [1, 0, 0, 0, 0, 1, 0, 0, 1];
  8. fill_map[6] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  9. fill_map[7] = [1, 0, 0, 0, 1, 0, 0, 0, 1];
  10. fill_map[8] = [1, 1, 1, 1, 1, 1, 1, 1, 1];
  11. for (y=0; y<9; y++) {
  12.     for (x=0; x<9; x++) {
  13.         tile = _root.attachMovie("tile", "tile_"+(y+x*9), _root.getNextHighestDepth(), {_x:y*50, _y:x*50});
  14.         tile.gotoAndStop(1+fill_map[x][y]);
  15.     }
  16. }
  17. _root.attachMovie("cursor", "cursor", _root.getNextHighestDepth());
  18. cursor.onEnterFrame = function() {
  19.     this._x = 50*Math.floor(_root._xmouse/50);
  20.     this._y = 50*Math.floor(_root._ymouse/50);
  21. };
  22. _root.onMouseDown = function() {
  23.     pos_x = Math.floor(_root._xmouse/50);
  24.     pos_y = Math.floor(_root._ymouse/50);
  25.     flood_fill(pos_x, pos_y);
  26. };
  27. function flood_fill(x, y) {
  28.     pos = x+y*9;
  29.     if (fill_map[y][x] == 0) {
  30.         fill_map[y][x] = 2;
  31.         _root["tile_"+(x+y*9)].gotoAndStop(3);
  32.         flood_fill(x+1,y);
  33.         flood_fill(x+1,y+1);
  34.         flood_fill(x+1,y-1);
  35.         flood_fill(x-1,y);
  36.         flood_fill(x-1,y+1);
  37.         flood_fill(x-1,y-1);
  38.         flood_fill(x,y+1);
  39.         flood_fill(x,y-1);
  40.     }
  41. }

Now you can paint everywhere

What's better? The one that fits your needs, of course?

What kind of game can we make out of that? I don't know (lie! lie!), it's up to you

Download the source code and start flooding

How to use a Flash game tutorial to make your own game

When I stated writing tutorials, I did not expect I would have to write a tutorial about... using a tutorial.

If you look at the most recent games published, you'll find a lot of games are useless clones of some of my tutorials or some of Tony Pa's ones.

I said "useless" because a tutorial is not meant to be a complete game... so if you just add your name and the game name to a tutorial, be sure that it will be a game that sucks, no matter how good is the tutorial.

In order to use a tutorial to make your own game, you need to follow some rules.

Let's see them

Because it would be too easy to use a tutorial of mine to create a game, I'll use Tony Pa's tile based tutorials.

The first one is "Creating Tiles" and that's where I am going to start.

1) Resize the movie

The first thing you have to do is resizing the movie to your needs. Remember that tutorials are often embedded in blogs or websites, so their sizes depend on pages layout. Your game will be played on gaming portals that will display it on popups (like NG) or on liquid pages that will fit to your game. Read more

Flash sending, manipulating and receiving data with sendAndLoad

This is a very importat thing to know when you are about to design Flash forms, or any application that needs to manage data such as an highscore table.

This is a standalone tutorial, but the basics explained will be useful in the Creation of a Flash highscores API course.

The only method we need to know is sendAndLoad

Let's dive into an example: I created an input text area called input_text, a button called send_button and a dynamic text called result_text.

Now, look at the code:

ACTIONSCRIPT:
  1. var php_process:LoadVars = new LoadVars();
  2. send_button.onRelease = function() {
  3.     var post_variable:LoadVars = new LoadVars();
  4.     post_variable.string = input_text.text;
  5.     post_variable.sendAndLoad("http://www.emanueleferonato.com/downloads/sendtest.php",php_process,"POST");
  6. };
  7. php_process.onLoad = function(success:Boolean) {
  8.     if (success) {
  9.         result_text.text = php_process.result;
  10.     }
  11.     else {
  12.         result_text.text = "Error connecting to server.";
  13.     }
  14. };

Line 1: Declaring a variable called php_process as LoadVars

The LoadVars class is useful for transferring variables between a Flash application and a server (who said "like an highscore"?)

Line 2: Beginning of the function to be executed when the send_button button has been pressed

Line 3: Declaring another LoadVars variable called post_variable

Line 4: Setting the string attribute of the post_variable as the content of the input_text dynamic text area

Line 5: Using sendAndLoad to pass post_variable to a script on the server at the address http://www.emanueleferonato.com/downloads/sendtest.php using the POST method and saving the result in the php_process variable

Line 7: Beginning of the function to be executed when the php_process has been loaded (when the server replied). Notice the success boolean flag

Lines 8-10: If success is true (I communicated with the server), then display in the result_test dynamic text area the result variable of php_process. We'll see how to get the result variable when we'll examine the php script

Lines 11-13: Dispaying an error if I wasn't able to communicate with the server

Now, let's see the php script in the
http://www.emanueleferonato.com/downloads/sendtest.php page

PHP:
  1. <?php
  2.  
  3. if($_POST[string]){
  4.     $upper = strtoupper($_POST[string]);
  5.     echo "result=You just wrote $upper";
  6. }
  7. else{
  8.     echo "result=You did not write anything";  
  9. }
  10.  
  11. ?>

Line 3: If the string variable passed with POST method contains something...

Line 4: Convert the string to uppercase, just to do something...

Line 5: writing the content of the result variable as the uppercased value of the initial string

Lines 7-9: if the string variable passed with POST does not contain anything, then writing the content of the result variable as a message saying you did not write anything.

And that's it... play with it and give me feedback

Write something in the upper text area and press "send"

Integrate your Flash game on Facebook

You all should know Facebook. I think it would be interesting to integrate your Flash game into a Facebook application.

There are more options than you can imagine, but at the moment I'll just embed a game, nothing more. Just remember there will be a lot more.

Obviously, first you have to have a Facebook account and be logged in

Then you have to install the Developer application.

From this page http://developers.facebook.com/get_started.php click on "Add Facebook Developer Application" and you will be able to start creating your own applications.

Once you clicked on that link, you will find a "Developer" item in the left nav button. This is your application control panel, where you can manage your applications.

Click on "Set up New Application"

You will be redirected to a quite unclear page with a lot of fields to fill... don't worry, you will be out of this step in less than 2 minutes. Read more

Managing multiple balls collisions with Flash

The first post of the new year (you should know the new year starts on May, 27th) is made by Sunil Changrani and it's about managing multiple balls collisions with Flash.

I already published a tutorial about Managing ball vs ball collision with Flash but this time we'll manage any number of balls.

Sunil was just making a Flash game and he ended up getting stuck when he needed a lot of circles to collide with each other.

With some help from Tony Pa, Voidskipper and Kazama_bee, ended up making some nice perfect collisions.

In the movie there are two symbols, one empty movieclip called blip and a movieclip called circle (which has the ball)

So here it is the commented code:

ACTIONSCRIPT:
  1. stop();
  2. t = 0;
  3. dx = 0;
  4. //Creating variables
  5. _root.attachMovie("blip","blip",_root.getNextHighestDepth(),{_x:1500, _y:200});
  6. _root.createEmptyMovieClip("container_movie",_root.getNextHighestDepth());
  7. //attaching the movieclips
  8. blip.onEnterFrame = function() {
  9.     //this is the function that executes every frame
  10.     if (Math.random()*1000<100 and t<50) {
  11.         //This condition adds another circle after a certain random interval till total circles are 50
  12.  
  13.         circle = container_movie.attachMovie("circle", "circle"+t, container_movie.getNextHighestDepth(), {_width:a, _height:b, _x:(20+Math.random()*300), _y:(20+Math.random()*300), _rotation:Math.random()*300});
  14.         t++;
  15.         circle.xspeed = Math.random()*9;
  16.         circle.yspeed = Math.random()*9;
  17.         //Creating the circle with random x and y speeds.
  18.         circle.onEnterFrame = function() {
  19.             this._x -= this.xspeed;
  20.             this._y -= this.yspeed;
  21.             //Motion of the circles
  22.             if (this._x<10) {
  23.                 this._x = 10;
  24.                 this.xspeed = -this.xspeed;
  25.             }
  26.             if (this._x>490) {
  27.                 this._x = 490;
  28.                 this.xspeed = -this.xspeed;
  29.             }
  30.             if (this._y<10) {
  31.                 this._y = 10;
  32.                 this.yspeed = -this.yspeed;
  33.             }
  34.             if (this._y>390) {
  35.                 this._y = 390;
  36.                 this.yspeed = -this.yspeed;
  37.             }
  38.             //Making sure the circle won't go out of the boundaries.
  39.         };
  40.     }
  41.     //From here I start checking for collisions of the circles
  42.     for (i=0; i<t; i++) {
  43.         a = _root.container_movie["circle"+i];
  44.         for (j=i+1; j<t; j++) {
  45.             b = _root.container_movie["circle"+j];
  46.             var dx = b._x-a._x;
  47.             var dy = b._y-a._y;
  48.             var dist = Math.sqrt(dx*dx+dy*dy);
  49.             //Checking the distances between two circles.
  50.             if (dist<20) {
  51.                 _root.solveBalls(a,b);
  52.                 //The circles I've taken are of radius 10, so if distance <20 then they collide, so I call a function.
  53.             }
  54.             else {
  55.             }
  56.         }
  57.     }
  58. };
  59. //This function is provided by kazama_bee at mochi forums. I'll try my best to explain it
  60. function solveBalls(ballA, ballB) {
  61.     var x1 = ballA._x;
  62.     var y1 = ballA._y;
  63.     var dx = ballB._x-x1;
  64.     var dy = ballB._y-y1;
  65.     var dist = Math.sqrt(dx*dx+dy*dy);
  66.     radius = 10;
  67.     //it calculates the distance, i could have passed it to the function but it works this way
  68.     normalX = dx/dist;
  69.     normalY = dy/dist;
  70.     midpointX = (x1+ballB._x)/2;
  71.     midpointY = (y1+ballB._y)/2;
  72.     //Now this calculates the normal and mid points..
  73.     ballA._x = midpointX-normalX*radius;
  74.     ballA._y = midpointY-normalY*radius;
  75.     ballB._x = midpointX+normalX*radius;
  76.     ballB._y = midpointY+normalY*radius;
  77.     //shifts the two circle two a different location so they don't hit each other
  78.     dVector = (ballA.xspeed-ballB.xspeed)*normalX+(ballA.yspeed-ballB.yspeed)*normalY;
  79.     dvx = dVector*normalX;
  80.     dvy = dVector*normalY;
  81.     //This calculates the new speeds for the circles
  82.     ballA.xspeed -= dvx;
  83.     ballA.yspeed -= dvy;
  84.     ballB.xspeed += dvx;
  85.     ballB.yspeed += dvy;
  86.     //assigns the new values
  87. }

And this is the result: look at the balls... how interesting!

Now tell me for how long will we see games based on this engine... I have one idea... download the source code and thank all developers.

Create a font browser with Flash AS3

When I am looking for an interesting font for my web design, the first site I look at is dafont.com.

What I like of this site is the capability to preview the font I am going to use with a sample text.

We are going to build something like a font viewer with AS3, previewing the fonts currently installed in our computer.

This script is based on a tip found on Cristalab. I suggest to read this site if you can read spanish.

In order to do this (learning spanish? No! The font browser) we need three object on the stage: an input text area instanced as sampletext, where we will write the text to be displayed in the selected font, a List User Interface component instanced as font_list, that we will populate with all fonts, and a dynamic text instanced as displayer to show the result.

Then, in the first frame of the movie timeline, this is the actionscript:

ACTIONSCRIPT:
  1. var fonts:Array = Font.enumerateFonts(true).sortOn("fontName");
  2. var fonts_array:Array = new Array();
  3. for (var i:int = 0; i <fonts.length; i++) {
  4.     fonts_array.push(new String(fonts[i].fontName));
  5. }
  6. font_list.dataProvider = new DataProvider(fonts_array);
  7. font_list.addEventListener(Event.CHANGE, change_font);
  8. sampletext.addEventListener(Event.CHANGE,change_text);
  9. function change_font(event:Event):void {
  10.     var font:TextFormat = new TextFormat();
  11.     font.font = new String(font_list.selectedItem.data);
  12.     displayer.setTextFormat(font);
  13. }
  14. function change_text(event:Event) {
  15.     displayer.text = sampletext.text;
  16. }

Line 1: Creation of an array called fonts with all currently available embedded fonts, sorted by font name.

Line 2: Declaring a new array called fonts_array

Line 3: Loop scanning all fonts array. Notice that with AS3 in the for conditions you must declare the index variable, and this code

for (i = 0; i < fonts.length; i++) {}

that worked fine in AS2, does not work anymore with AS3

Line 4: Pushing the ith fontName property of the fonts array into the fonts_array array. What a mess!

I am just passing in the array created at line 2 only the fontName property of the font contained in the fonts array created at line 1.

I need to do this because a font has three properties: fontName, fontStyle and fontType, and I need only the first one.

Line 6: Populating the list with the content of the fonts_array array. Now we have a list with all font names

Line 7: Adding a listener to the list that will call the change_font function when I select a list element

Line 8: Adding a listener to input text that will call the change_text function when I change the text in the input text area

Line 9: Beginning of the function to be executed when I select an item from the list

Line 10: Declaration of a new TextFormat class called font. The TextFormat class is used to stylize both static and dynamic text fields.

Line 11: Assigning to the font TexFormat font the value of the selected item in the list. In this way I am defining the font of the font TextFormat

Line 12: Applying the text format to the displayer text area

Line 14: Beginning of the function to be executed when I change the text in the input text area

Line 15: Changing the text in the displayer text area according to the text actually in the input text area

And that's it...

Download the source code and enhance it.

Creation of a Flash highscores API – Step 2

Now that you know how to communicate between two Flash movies thanks to the Creation of a Flash highscores API tutorial, it's time to introduce the next step that will make you save your highest score on your computer.

It's not an hard prototype once you read Create an Eskiv Flash game tutorial (in order to have a real game) and Managing savegames with Flash shared objects (to store data on your computer)

This is the game:

ACTIONSCRIPT:
  1. var send_score:LocalConnection = new LocalConnection();
  2. _root.attachMovie("score", "score", 1);
  3. _root.attachMovie("hero", "hero", 2, {_x:250, _y:200});
  4. _root.attachMovie("target", "target", 3, {_x:Math.random()*400+25, _y:Math.random()*300+25});
  5. enemy_power = 3;
  6. points = 0;
  7. max_score = 0;
  8. hero.onEnterFrame = function() {
  9.     this._x = _root._xmouse;
  10.     this._y = _root._ymouse;
  11. };
  12. target.dir = Math.random()*2*Math.PI;
  13. target.xspeed = enemy_power*Math.cos(foe.dir);
  14. target.yspeed = enemy_power*Math.sin(foe.dir);
  15. target.onEnterFrame = function() {
  16.     dist_x = this._x-hero._x;
  17.     dist_y = this._y-hero._y;
  18.     distance = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
  19.     if (distance<(hero._width+this._width)/2) {
  20.         points++;
  21.         if (points>max_score) {
  22.             max_score = points;
  23.             send_score.send("hall_of_fame", "compare_scores", points);
  24.         }
  25.         score.scoretxt.text = points;
  26.         this._x = Math.random()*400+25;
  27.         this._y = Math.random()*300+25;
  28.         foe = _root.attachMovie("enemy", "enemy", _root.getNextHighestDepth(), {_x:Math.random()*400+25, _y:Math.random()*300+25});
  29.         foe.dir = Math.random()*2*Math.PI;
  30.         foe.xspeed = enemy_power*Math.cos(foe.dir);
  31.         foe.yspeed = enemy_power*Math.sin(foe.dir);
  32.         foe.onEnterFrame = function() {
  33.             this._x += this.xspeed;
  34.             this._y += this.yspeed;
  35.             if ((this._x&lt;0) or (this._x>500)) {
  36.                 this.xspeed *= -1;
  37.             }
  38.             if ((this._y&lt;0) or (this._y>400)) {
  39.                 this.yspeed *= -1;
  40.             }
  41.             dist_x = this._x-hero._x;
  42.             dist_y = this._y-hero._y;
  43.             distance = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
  44.             if (distance<(hero._width+this._width)/2) {
  45.                 points--;
  46.                 score.scoretxt.text = points;
  47.                 this.removeMovieClip();
  48.             }
  49.         };
  50.     }
  51. };

The game game developer only needs to add line 1 and line 23 to his game

and this is the highscore table Read more

Next Page →

Posts