Create a Flash game like Metro Siberia Underground - Part 5

Multipart tutorial: available parts 1, 2, 3, 4 ,5

This tutorial reached the 5th part, and it’s time to add some new feature… something that wasn’t included in the original game.

Always remember to add something to a game you are about to clone, or people will get bored very soon of your game.

In this tutorial we will make the ship fire. “Oh, well”, you may say, “thanks for the millionth tutorial about firing spaceships”.

Wait… do you remember Metro Siberia Underground is a one button game? And that the one an only button you can press in this game is already used to give thrust?

That’s where my gameplay idea comes and shines… your ship is always firing… and it’s up to you firing only at the rocks, avoiding to blow off fuel tanks.

Read parts 1 to 4 before continuing, then take this actionscript: Read more

Protect your ActionScript with Amayeta’s SWF Encrypt

Ok… you made it… you made the Flash game that will kick asses and you are sure nobody knows Actionscript like you. Nobody will clone your game because you know ActionScript better than the rest.

If you really know ActionScript, you should now that even if SWF files are compiled, they can be easily decompiled with a lot of softwares available on the net. Just Google for Flash Decompiler to see the most famous ones.

This means that once you published your file, everybody can do reverse engineering on your file and know how did you coded it.

And even if bigger projects are hard to understand, someone may decompile your game, change your logo with another one and submit it in all portals before you do it.

If you think people won’t waste their time decompiling your game, you are wrong. They will do it… maybe to hack your highscores, or maybe to put their name in the credits and show their friends what a cool game they made… for a reason or for another, they will do it.

That’s when Amayeta comes in our help with its SWF Encrypt. Available both for Windos and Mac OSX encrypts your Adobe Flash SWF files, protecting them from the most popular Flash Decompiler Tools on the market.

Sounds good… here I am for a test drive… Read more

How to show latest phpBB3 posts in your WordPress sidebar

As you may notice, at the top of the rightmost column of this blog I am showing the latest posts of the forum.

I did not find any widget fitting my needs so I had to solve the problem by myself. And I am going to tell you how.

At the moment it's not a widget, just a bunch of lines in a PHP Code Widget to do the trick. Should I receive good feedback, I will develop a fully customizable widget.

Anyway, following this tutorial will make you able to show your phpBB3 posts in your WP sidebar in a matter of minutes.

First, in your WP admin area go to Presentation -> Widgets to go into Sidebar Arrangement section.

You should find a screen like this one

WP admin area

... but it may be a bit different according to your theme. Anyway, what you need is a PHP Code Widget, so have to create one (look at the bottom arrow in the image) and drag/drop it in the sidebar.

Then you're ready to enter the code in your widget:

PHP:
  1. <?php
  2. $connection = mysql_connect(localhost,"your_login","your password") or die("Service temporairly unavailable");
  3. $db = mysql_select_db("your_db_name",$connection) or die("Service temporairly unavailable");
  4. $sql = "select * from phpbb_topics order by topic_last_post_time desc limit 0,10";
  5. $result = mysql_query($sql) or die("Service temporairly unavailable");
  6. for($x=1;$x<=10;$x++){
  7.     $row = mysql_fetch_array($result);
  8.     echo "<a href = \"http://www.yourforumdomain.com/viewtopic.php?f=$row[forum_id]&t=$row[topic_id]\" target = \"_blank\">$row[topic_title]</a><br>";
  9. }
  10. ?>

Line 1: Opening php tag. Normally it makes no difference between <? and >?php but my widget told me

PHP Code MUST be enclosed in tags!

Line 2: Connecting with the database where you are hosting your phpBB3. Change localhost with the address of your database, your_login with database login and your_password with your database password. In case something should fail (database is down, login or password are incorrect), I return a "Service temporairly unavaiable" and terminate the script.

Line 3: Selecting the database where you installed your phpBB3. Change your_db_name with the name of the database.

If you do not remember one (or more) data explained at lines 2-3, simply give a look to your config.php file in the folder where you installed phpBB3.

It's made in this way:

PHP:
  1. <?php
  2. // phpBB 3.0.x auto-generated configuration file
  3. // Do not change anything in this file!
  4. $dbms = 'mysql';
  5. $dbhost = '122.122.122.122';
  6. $dbport = '';
  7. $dbname = 'emanuele';
  8. $dbuser = 'triqui';
  9. $dbpasswd = 'banana';
  10.  
  11. $table_prefix = 'phpbb_';
  12. $acm_type = 'file';
  13. $load_extensions = '';
  14.  
  15. @define('PHPBB_INSTALLED', true);
  16. // @define('DEBUG', true);
  17. // @define('DEBUG_EXTRA', true);
  18. ?>

At line 5 you will find the database address (122.122.122.122), at line 7 db name (emanuele), at line 8 db username (triqui) and at line 9 the password (banana).

Also remember line 11 and write down somewhere the content of table_prefix variable (phpbb_)

I did not used any of those names, so don't even try to hack my forum... but let's go back to the script...

Line 4: This is the string representing the query that will create the table with the last 10 updated topcis. phpbb_topics is the name of the table than contains the topics. If you have another value in your table_prefix variable, then you will need to change phpp_topics with your_table_prefix_topics. So, as an example, if your table prefix is triqui, then your table name will be triqui_topics, while you won't have to change topic_last_post_time that represents the timestamp of the last post in the topic. In this way, you will get a table with the latest 10 topic ordered by last post time. If you want more (or less) than 10 topics, change the 10 in limit 0,10

Line 5: Processing the query, or returning in case of error the same fake message "Service temporairly unavaiable"

Line 6: Loop to be executed 10 times

Line 7: Fetching the row of the table in an array called row

Line 8: Displaying the link: notice that the link starts with http://www.yourforumdomain.com/, you will have to change this address with the path of your phpBB3 forum. For instance, if your forum is in the forum folder in the google domain, you will have to write http://www.google.com/forum/. You don't need to change anything else

That's all. Hope you will find it useful... maybe some day I will make a widget that will be easier to configure.

The forum is alive!

After some time from the post announcing the forum, I am proud to say the forum is now live.

Well... it's just a default-style phpBB page at the moment, but I am going to improve it day after day, to make it as successful as this blog.

This does not mean I am going to stop being active here... I will be active here, there, and somewhere else I can't tell you at the moment.

Of course you are free to post suggestion, comments, and so on.

Meanwhile, I will design the logo and the template. I am learning a lot about phpBB... maybe someday I will release a tutorial about it.

And now... the link... www.triquitips.com

Happy posting.

Understanding Flash Objects

I know people usually get scared when someone talks about Objects. Object always mean OOP and tt sounds very hard to understand, and all in all you can code everything you want without using objects.

That's true, but let me clarify some concepts:

1) Using basic Flash Objects is much easier than OOP
2) You can code everything without Objects, but with Objects your life will be easier
3) Basic Objects work both in AS2 and AS3
4) Never be afraid of new techniques (print this one)
5) I will use Objects in some future tuts so it's time to learn them

Usually Objects tutorials start with the classic phone book where you can store name, address, and so on.

You can find such examples elsewhere.

In our case, let's suppose we have a sphere (I told I will use Objects for a game in the near future...).
The sphere has a weight, a speed and a stamina.

You can declare it in the old way

ACTIONSCRIPT:
  1. sphere_weight = 100;
  2. sphere_speed = 100;
  3. sphere_stamina = 100;

or using Objects in this way

ACTIONSCRIPT:
  1. sphere = new Object();
  2. sphere.weight = 100;
  3. sphere.speed = 100;
  4. sphere.stamina = 100;

"hey", you may say, "you used four lines to do the same thing you did with 3 lines"

That's right, but let me show you something:

var sphere = {weight:100,speed:100,stamina:100}

in just one line... this should sound familiar to you since it's the same declaration to initialize movieclips attributes like

_root.attachMovie("obj","obj",1,{_x:100, _y:100});

Obviously Objects aren't intended to write more code in less lines, so I am going to jump to the point of this tutorial.

The most interesting thing about objects is you can create an array of objects. Let's suppose we have three spheres.

You can declare them with an array of objects in this way:

ACTIONSCRIPT:
  1. var spheres = new Array();
  2. spheres[1] = {weight:100, speed:100, stamina:100};
  3. spheres[2] = {weight:100, speed:100, stamina:100};
  4. spheres[3] = {weight:100, speed:100, stamina:100};

That's all you need to know at the moment... but during next tutorials I am going to use Objects a lot, and you will see how simple can be our life with Objects.

Create a Flash game like Metro Siberia Underground - Part 4

Multipart tutorial: available parts 1, 2, 3, 4 ,5

In this 4th part I'll cover the code written in 3rd part. You should read parts 1 and 2 too, because I will comment only the new code.

For a better understanding, I'll re-publish the code

ACTIONSCRIPT:
  1. import flash.filters.GlowFilter;
  2. var ship_filter:GlowFilter = new GlowFilter(0x00ff00, 0.8, 4, 4, 2, 3, false, false);
  3. var smoke_filter:GlowFilter = new GlowFilter(0xff0000, 0.8, 4, 4, 2, 3, false, false);
  4. var tunnel_filter:GlowFilter = new GlowFilter(0xffff00, 0.8, 4, 4, 2, 3, false, false);
  5. var fuel_filter:GlowFilter = new GlowFilter(0x00ffff, 0.8, 4, 4, 2, 3, false, false);
  6. var rock_filter:GlowFilter = new GlowFilter(0xffffff, 0.8, 4, 4, 2, 3, false, false);
  7. var score_filter:GlowFilter = new GlowFilter(0xff00ff, 0.8, 2, 4, 2, 3, false, false);
  8. gravity = 0.1;
  9. thrust = 0.25;
  10. yspeed = 0;
  11. xspeed = 5;
  12. distance = 0;
  13. smoke_interval = 10000;
  14. frames_passed = 0;
  15. tunnel_height = 150;
  16. fuel_freq = 10;
  17. gasoline = 500;
  18. rock_freq = 50;
  19. engines = false;
  20. _root.attachMovie("ship", "ship", _root.getNextHighestDepth(), {_x:150, _y:200});
  21. _root.createEmptyMovieClip("fuel_movie", _root.getNextHighestDepth());
  22. _root.createEmptyMovieClip("deadly_movie", _root.getNextHighestDepth());
  23. _root.attachMovie("score", "score", _root.getNextHighestDepth());
  24. ship.filters = new Array(ship_filter);
  25. score.filters = new Array(score_filter);
  26. ship.onEnterFrame = function() {
  27.     score.sc.text = "Distance: "+distance+" - "+"Fuel: "+gasoline;
  28.     if ((gasoline>0)and(engines)) {
  29.         yspeed -= thrust;
  30.         smoke_interval -= 0.25;
  31.         gasoline -= 1;
  32.     }
  33.     if (Math.random()*1000<fuel_freq) {
  34.         fuel = fuel_movie.attachMovie("fuel", "fuel"+fuel_movie.getNextHighestDepth(), fuel_movie.getNextHighestDepth(), {_x:510, _y:Math.random()*400+50});
  35.         fuel.filters = new Array(fuel_filter);
  36.         fuel.onEnterFrame = function() {
  37.             this._x -= (xspeed*1.2);
  38.             dist_x = ship._x+28*Math.cos(angle)-this._x;
  39.             dist_y = ship._y+28*Math.sin(angle)-this._y;
  40.             dist = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
  41.             if (dist<10) {
  42.                 gasoline += 100;
  43.                 this.removeMovieClip();
  44.             }
  45.             if (this._x<-10) {
  46.                 this.removeMovieClip();
  47.             }
  48.         };
  49.     }
  50.     if (Math.random()*1000<rock_freq) {
  51.         rock = deadly_movie.attachMovie("rock", "rock"+deadly_movie.getNextHighestDepth(), deadly_movie.getNextHighestDepth(), {_x:510, _y:Math.random()*400+50, _rotation:Math.random()*360});
  52.         rock.filters = new Array(rock_filter);
  53.         rock.onEnterFrame = function() {
  54.             this._x -= xspeed;
  55.             if (this._x<-10) {
  56.                 this.removeMovieClip();
  57.             }
  58.         };
  59.     }
  60.     yspeed += gravity;
  61.     this._y += yspeed;
  62.     angle = Math.atan2(yspeed, xspeed);
  63.     this._rotation = angle*180/Math.PI;
  64.     frames_passed++;
  65.     distance += xspeed;
  66.     if (frames_passed>=smoke_interval) {
  67.         sm = _root.attachMovie("smoke", "smoke"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:this._x-2, _y:this._y});
  68.         sm.filters = new Array(smoke_filter);
  69.         sm.onEnterFrame = function() {
  70.             this._x -= xspeed;
  71.             this._width += 0.2;
  72.             this._height += 0.2;
  73.             this._alpha -= 2;
  74.             if (this._alpha<=0) {
  75.                 this.removeMovieClip();
  76.             }
  77.         };
  78.         frames_passed = 0;
  79.     }
  80.     if ((this._y>400) or (this._y<0) or deadly_movie.hitTest(this._x+28*Math.cos(angle), this._y+28*Math.sin(angle), true) or deadly_movie.hitTest(this._x+8*Math.cos(angle+Math.PI/2), this._y+8*Math.sin(angle+Math.PI/2), true) or deadly_movie.hitTest(this._x+8*Math.cos(angle-Math.PI/2), this._y+8*Math.sin(angle-Math.PI/2), true)) {
  81.         yspeed = 0;
  82.         this._y = 200;
  83.         gasoline = 500;
  84.         distance = 0;
  85.         deadly_movie.removeMovieClip();
  86.         fuel_movie.removeMovieClip();
  87.         _root.createEmptyMovieClip("fuel_movie", _root.getNextHighestDepth());
  88.         _root.createEmptyMovieClip("deadly_movie", _root.getNextHighestDepth());
  89.     }
  90. };
  91. _root.onMouseDown = function() {
  92.     engines = true;
  93.     smoke_interval = 10;
  94. };
  95. _root.onMouseUp = function() {
  96.     engines = false;
  97.     smoke_interval = 100000;
  98. };

Lines 5-7: New filters used for the rock object (the white square), the fuel object (the blue circle) and the score written at the upper left corner. Since there isn't any tunnel in this example, you can remove line 4 if you want

Line 15: You can remove this line too if you want

Line 16: A variable that determines the fuel spawn frequency. Higher value means higher freq

Line 17: This is the amount of gasoline in your ship

Line 18: A variable that determines the rock spawn frequency... same thing as the fuel one seen at line 16

Line 21: Creating a new movieclip to host all fuel cans.

Line 22: New movieclip to host all rocks

Line 23: Attaching the score movieclip

Line 25: Applying the filter to score movieclip

Line 27: Showing distance traveled and remaining fuel

Line 28: As you can see in the if statement, now you must have gasoline in order to give thrust to your spaceship

Line 31: Obviously giving thrust will cost you some gasoline...

Line 33: Checking if it's time to spawn a can of gasoline

Line 34: if true, then attach a fuel movieclip in the game at a random position

Line 35: Applying the filter to fuel movieclip

Line 36: Function to be executed by the fuel tank at every frame

Line 37: Moving the fuel tank according to ship's speed. Notice that there is a 1.2 multiplier to make the fuel move faster than rocks

Lines 38-40: Calculating the distance from the head of the spaceship and the centre of the fuel tank using trigonometry. More information about trigonometry at Create a flash draw game like Line Rider or others - part 3. I want the gasoline to be collected only with the head of the ship, to give the game some kind of "realism"

Lines 41-44: If the distance is less than 10 (the radius of the gasoline tank), then add 100 units of gasoline and remove the fuel tank

Lines 45-47: If the fuel tank leaves the game to the left, then remove it

Line 50: Checking if it's time to spawn an asteroid (a rock)

Line 51: if true, then attach a rock movieclip in the game at a random position wiht a random rotation

Line 52: Applying the filter to rock movieclip

Line 53: Function to be executed by the rock at every frame

Lines 54-57: Moving the rock according to ship's speed. If the rock leaves the game to the left, then remove it

Lines 80-89: Checking if the ship hits the rocks or goes too high or too low... if true, resetting the game

That's all...

Multipart tutorial: available parts 1, 2, 3, 4 ,5

A new Flash game prototype

I played some times ago a game similar to the one I am making the prototype... I think it was a PopCap game, or a game by another casual game developer... anyway it's a game involving a balance and some spheres.

Just a quick, raw actionscript

ACTIONSCRIPT:
  1. field = new Array();
  2. for (x=0; x<10; x++) {
  3.     field[x] = new Array();
  4.     for (y=0; y<6; y++) {
  5.         field[x][y] = 0;
  6.     }
  7. }
  8. attach_sphere = true;
  9. _root.attachMovie("bar", "bar", _root.getNextHighestDepth(), {_x:250, _y:400});
  10. _root.attachMovie("triangle", "triangle", _root.getNextHighestDepth(), {_x:250, _y:400});
  11. _root.onEnterFrame = function() {
  12.     if (attach_sphere) {
  13.         attach_sphere = false;
  14.         sphere = bar.attachMovie("ball", "ball"+bar.getNextHighestDepth(), bar.getNextHighestDepth(), {_x:20,_y:-300});
  15.         sphere.moving = true;
  16.         sphere.onEnterFrame = function() {
  17.             if (this.moving) {
  18.                 pos_x = Math.floor(bar._xmouse/40)+5;
  19.                 if (pos_x<0) {
  20.                     pos_x = 0;
  21.                 }
  22.                 if (pos_x>9) {
  23.                     pos_x = 9;
  24.                 }
  25.                 this._x = pos_x*40-180;
  26.             }
  27.             if (this.falling) {
  28.                 this._y += 20;
  29.                 pos_y = Math.floor((this._y+20)/40);
  30.                 if ((pos_y == 0)or(field[pos_x][pos_y*(-1)-1]==1)) {
  31.                     this.falling = false;
  32.                     field[pos_x][pos_y*(-1)] = 1;
  33.                     attach_sphere = true;
  34.                 }
  35.             }
  36.         };
  37.     }
  38. };
  39. bar.onEnterFrame = function() {
  40.     dir = 0;
  41.     for (x=0; x<10; x++) {
  42.         for (y=0; y<6; y++) {
  43.             if (field[x][y]>0) {
  44.                 if (x<5) {
  45.                     dir -= (5-x);
  46.                 } else {
  47.                     dir += (x-4);
  48.                 }
  49.             }
  50.         }
  51.     }
  52.     dir *= 0.01;
  53.     this._rotation += dir;
  54. };
  55. _root.onMouseDown = function() {
  56.     if (sphere.moving) {
  57.         sphere.moving = false;
  58.         sphere.falling = true;
  59.     }
  60. };

and the result

Can you make a good game out of this? Download the source code

Some Flash preloading issues you’d better know

I never used a preloader in a game... all my games are quite light, and I used to preload movies only in some heavy website intros.
Heavy, as I said, but 100% timeline and 0% actionscript

Today, I was making a preloader for Glomb, because I am dealing with a sponsor (yes... maybe I am giving Glomb for an exclusive sponsorship) when I come into a problem.

The preloader started loading when the movie was at 99% loaded.

I don't think the sponsor would like his logo to be shown only at the 1% of the loading time, so I was wondering what was wrong with the preloader.

This was the code, in the 1st frame:

ACTIONSCRIPT:
  1. stop();
  2. onEnterFrame = function () {
  3.     already_loaded = _root.getBytesLoaded()/_root.getBytesTotal();
  4.     // show some fancy preloading graphics
  5.     if (already_loaded == 1) {
  6.         delete onEnterFrame;
  7.         play();
  8.     }
  9. };

It's a very common preloader, you may find it on a lot of tutorial sites and books.

But it did not work for me.

After a while, I solved the issue: most of the graphics and sounds in the game are not in the timeline... they are called dynamically by the actionscript with attachMovie or attachSound.

The problem is Flash compiler does not know when you are going to use those graphics and sounds, so it preloads all this stuff before the 1st frame. So when my preloader comes in action, the 99% of the movie (graphics and sounds) are loaded, then the remaining 1% (actionscript itself) is loaded showing the preloader.

This happens because you have this checkbox enabled

This checkbox determines the object must be loade before the 1st frame.

Never mind! Just uncheck it and everything will work fine!

This is not the solution... if you uncheck the checkbox, when the compiler scans the timeline and does not find the resource, it simply ignores it and your game will be compiled without graphics/sounds.

What can you do?

If your preloader is on frame 1, you should made your game start on frame 3, and put all your dynamically created objects at frame 2. This way, the movie will compile the objects because it finds them on frame 2, but the first thing to be loaded will be the preloader, and everything will work fine. Obviously, the Export in first frame mark has to be unchecked.

Create a Flash game like Metro Siberia Underground - Part 3

Multipart tutorial: available parts 1, 2, 3, 4 ,5

In the 3rd part I'll leave the tunnel for a future use and I will introduce some "asteroids", some "fuel tanks" and the distance traveled so far.

I suggest to read part 1 and 2 before reading this one

It's not a line-by-line commented tutorial, I am just sharing the source code at the moment, a full explication will come soon

* edit: full explication available

ACTIONSCRIPT:
  1. import flash.filters.GlowFilter;
  2. var ship_filter:GlowFilter = new GlowFilter(0x00ff00, 0.8, 4, 4, 2, 3, false, false);
  3. var smoke_filter:GlowFilter = new GlowFilter(0xff0000, 0.8, 4, 4, 2</