Playing with getPixel

Today I played a bit with getPixel function and I want to share with you some considerations about it.

First, you have to know getPixel(x,y) returns an integer that represents an RGB pixel value from a BitmapData object at a specific point (x, y).

Then, I wanted to know the percentage of a color in an image, maybe to manage level filling in a game like ColorFill (when using complex shapes to fill the level) or maybe to analyze the percentage of a color in a photo.

So I made this picture

and I linked it as bg.

Then I wrote this little actionscript

ACTIONSCRIPT:
  1. import flash.display.BitmapData;
  2. var bitmap_bg:BitmapData = BitmapData.loadBitmap("bg");
  3. _root.createEmptyMovieClip("background_image",_root.getNextHighestDepth());
  4. background_image.attachBitmap(bitmap_bg,_root.getNextHighestDepth());
  5. precision = 1;
  6. r = 0;
  7. g = 0;
  8. b = 0;
  9. other = 0;
  10. total = 0;
  11. for (x=0; x<500; x += precision) {
  12.     for (y=0; y<400; y += precision) {
  13.         switch (bitmap_bg.getPixel(x, y).toString(16)) {
  14.             case "ff" :
  15.                 b++;
  16.                 break;
  17.             case "ff00" :
  18.                 g++;
  19.                 break;
  20.             case "ff0000" :
  21.                 r++;
  22.                 break;
  23.             default :
  24.                 other++;
  25.         }
  26.         total++;
  27.     }
  28. }
  29. r = r/total*100;
  30. g = g/total*100;
  31. b = b/total*100;
  32. other = other/total*100;
  33. trace("Red: "+r+"%\nGreen:"+g+"%\nBlue: "+b+"%\nOhter: "+other+"%");

It's a very easy one:

Line 1: importing BitmapData library

Line 2: declaring a BitmapData variable called bitmap_bg containing the image linked as bg

Line 3: creating an empty movie clip where I will attach the bitmap image loaded at line 2

Line 4: attaching the bitmap, as said at line 3

Line 5: Setting a variable called precision. This is the core of the script. precision indicates the gap in pixels from the last examined pixel and the next pixel I am going to examine. The smaller precision value, the more accurate the percentage, the slower the script.

Lines 6-10: Initializing variables counting the amount of red, green and blue pixels found, and the total of pixels examined. I also count the pixels of other colors. Even if you only see a blue background, a red circle and a green heart, there are other colors due to antialiasing.

Lines 11-28: Scanning all pixels with the precision gap between one pixel and another, and incrementing the color variable according to the color found at line 13.

Lines 29-33: Formatting and showing the results

Look how results change when I play with precision

Precision: 1
Red: 8.91%
Green:7.9145%
Blue: 82.5735%
Ohter: 0.602%

Precision: 2
Red: 8.91%
Green:7.916%
Blue: 82.578%
Ohter: 0.596%

Precision: 5
Red: 8.9125%
Green:7.8625%
Blue: 82.55%
Ohter: 0.675%

Precision: 10
Red: 8.8%
Green:7.95%
Blue: 82.7%
Ohter: 0.55%

Precision: 20
Red: 8.8%
Green:8%
Blue: 82.6%
Ohter: 0.6%

As you can see, you don't need a low (and cpu expensive) precision value to obtain realistic results.

Download the source, maybe changing the image, and tell me what do you think about. Any idea for a game?

Win a TemplateMonster theme with TemplateMonster Lottery

If you are looking for a fresh and professional template for your personal site, Flash game portal or a site for a web design job, then you should take a look at TemplateMoster.

TemplateMonster

Now you have a chance to win one of these templates thanks to the TemplateMonster lottery.

Let's see what does it mean from the mouth (well, the keyboard) of Helen:

TemplateMonster.com is going to hold a lottery with give-away to any participant.

The lottery is going to be about the upcoming 4th of July.

And here are the details of TemplateMonster Lottery which reminds elections in its structure.

We'll expose two of TemplateMonster's website designs. In order to take part in the lottery one should vote for one design or the other.

The design which gets the most votes becomes the winner. Note the best design is chosen during two weeks period.

And here are the benefits for users to take part in our lottery:
- everyone who participates in our lottery gets the free Icon Set. All icons included into this free Icon Set also relate to patriotic and 4th of July topic;
- also everyone who participates in our lottery has a chance to get one of our special prizes.

The special prizes are:
- 1 Gift Certificate giving the opportunity to get any product from Template Monster database for free;
- two 80% discount coupons for purchasing any product from Template Monster database;
- three 50% discount coupons for purchasing any product from Template Monster database.

Note everyone who purchases any product from Template Monster during this promo will get the Icon Set that I've mentioned for free.

And now, the link: 4th July Lottery 2008.

That's it... and if you don't understand what's the point of giving away patriotic icons on July 4th, you should watch Independence Day movie.

Looking for your experience for a case history

I need some of your experiences in order to build a case history section in this blog and for an article do be published on a paper magazine... and maybe for something else.

If you think this blog changed your way of developing and monetizing Flash games, or just made you love Flash game developing, then please leave a comment with your first name, the first letter of your last name and the Country you are from (example: Emanuele F. - Italy)

And, of course, your experience.

Thank you very much.

Create a Flash game like ColorFill – part 1

If you play all successful Flash games (and you should, if you want to be a Flash game developer), surely you played ColorFill.

ColorFill

In this game, you have to fill 80% of the stage with colors while avoiding collisions with enemies.

Play the game a bit then follow this prototype

The main idea to create this game is based upon the "vertical state" of arrows. I designed the arrows as horizontal ones, but if the player presses SPACE, I rotate them by 90 degrees so the left one becomes the up one and the right one becomes the down one.

There's not any more difficulty in this first part, when I still don't fill the area once I successfully draw a line.

Some previous concepts from Create a flash draw game like Line Rider or others - part 2 are involved in order to determine collisions between the ball and the line. Read more

Step by step AS3 translation of Creation of a platform game with Flash – step 1.5

According to Bart de Boer, this is the step 1.5 of the Step by step AS3 translation of Creation of a platform game with Flash.

He fixed the jump issue and improved the collision engine.

As in the previous example, the file Script.as is the main class:

ACTIONSCRIPT:
  1. /*____________________________________________________
  2. |______________ register of functions _______________|
  3. |____________________________________________________|
  4.  
  5. - main()            only calling to update_hero() (every frame)
  6.  
  7. - create_hero()     creates hero as the var "Hero"
  8.  
  9. - update_hero()     check collision an move
  10.  
  11. - BuildMap()        load and create the level
  12.  
  13.  
  14. extern
  15.  
  16. Data.as
  17. - Setup()           create levels
  18.  
  19. collision_manager.as
  20. - Setup(size,map,hero)      setup the map
  21.  
  22. - Solve_all(forecastx,forecasty)        solves the collsions and checks for a jump
  23. */
  24.  
  25.  
  26. package{                                                //The begin of an .as file
  27.     import flash.display.MovieClip;                     //import some libraries
  28.     import flash.events.Event;
  29.     import flash.events.KeyboardEvent;
  30.  
  31.     public class Script extends MovieClip{              // start the script
  32.    
  33.     private const gravity:int = 1;
  34.     private const max_speed:int = 8;
  35.    
  36.     private const walkspeed:int = 4;
  37.     private const jumpspeed:int = 10;
  38.    
  39.     private var forecast_x:int;
  40.     private var forecast_y:int;
  41.    
  42.     private const start_x:int = 50;
  43.     private const start_y:int = 50;
  44.    
  45.     private var left:Boolean;
  46.     private var up:Boolean;
  47.     private var right:Boolean;
  48.     private var space:Boolean;
  49.        
  50.     private var level:Array = new Array();
  51.     private var tiles:Array = new Array();
  52.    
  53.     private var Map_data:Data = new Data;               // create a version of the Data.as
  54.     private var Hero_col:collision_manager = new collision_manager;
  55.    
  56.     private var Hero:hero = new hero;
  57.    
  58.         public function Script(){                       // the init (will only be runned once)
  59.             BuildMap();
  60.             create_hero();
  61.             addEventListener(Event.ENTER_FRAME, main);
  62.             stage.addEventListener(KeyboardEvent.KEY_DOWN, key_down);
  63.             stage.addEventListener(KeyboardEvent.KEY_UP, key_up);
  64.            
  65.             Hero_col.Setup(25,level,Hero);
  66.         }
  67.        
  68.         private function main(event:Event){
  69.             update_hero();
  70.         }
  71.        
  72.         private function key_down(event:KeyboardEvent){
  73.             if(event.keyCode == 37){
  74.                 left = true;
  75.             }
  76.             if(event.keyCode == 38){
  77.                 up = true;
  78.             }
  79.             if(event.keyCode == 39){
  80.                 right = true;
  81.             }
  82.         }
  83.        
  84.         private function key_up(event:KeyboardEvent){
  85.             if(event.keyCode == 37){
  86.                 left = false;
  87.             }
  88.             if(event.keyCode == 38){
  89.                 up = false;
  90.             }
  91.             if(event.keyCode == 39){
  92.                 right = false;
  93.             }
  94.         }
  95.                                
  96.            
  97.        
  98. /*
  99. ///    ///      /////////   ///////////     ///////////
  100. ///    ///      ///         ////    ///     ///     ///
  101. ///    ///      ///         ////    ///     ///     ///
  102. //////////      /////////   //////////      ///     ///
  103. //////////      /////////   ////    ///     ///     ///
  104. ///    ///      ///         ////    ///     ///     ///
  105. ///    ///      ///         ////    ///     ///     ///
  106. ///    ///      /////////   ////    ///     ///////////
  107. */
  108.         private function create_hero(){
  109.             addChild(Hero);
  110.             Hero.x = start_x;
  111.             Hero.y = start_y;
  112.             Hero.x_speed = 0;
  113.             Hero.y_speed = 0;
  114.         }
  115.        
  116.         private function update_hero(){
  117.             Hero.y_speed += gravity;
  118.             if(left){
  119.                 Hero.x_speed = -walkspeed;
  120.             }
  121.             if(right){
  122.                 Hero.x_speed = walkspeed;
  123.             }
  124.             if(up && Hero_col.can_jump){
  125.                 Hero.y_speed = -jumpspeed;
  126.             }
  127.            
  128.             if(Hero.y_speed> max_speed){
  129.                 Hero.y_speed = max_speed;
  130.             }
  131.            
  132.             forecast_y = Hero.y + Hero.y_speed;
  133.             forecast_x = Hero.x + Hero.x_speed;
  134.            
  135.             Hero_col.solve_all(forecast_x, forecast_y);
  136.            
  137.            
  138.             Hero.x_speed = 0;
  139.         }
  140.    
  141.    
  142. /*
  143. |||||||||||      |||||||||||      ||||||||||    ||||||||||
  144. ||||||||||||    ||||||||||||     ||||    ||||   ||||    |||
  145. ||||    ||||| |||||     ||||     ||||||||||||   ||||||||||
  146. ||||      |||||||       ||||     ||||    ||||   ||||
  147. ||||        |||         ||||    ||||      ||||  ||||
  148. ||||                    ||||    ||||      ||||  ||||
  149. */
  150.                
  151.         private function BuildMap(){
  152.             Map_data.Setup();                                               // setup data from extern file
  153.            
  154.             level = Map_data.level1;                                        // get data from extern file
  155.            
  156.             for(var t = 0; t <level.length; t++){
  157.                 for(var u = 0; u <level[t].length; u++){
  158.                     if(level[t][u] != 0){                                   //if the data is not null
  159.                         var new_tile:platform_tile = new platform_tile;     //than build a tile
  160.                        
  161.                         addChild(new_tile);                                 //put it on the screen
  162.                        
  163.                         new_tile.gotoAndStop(1);
  164.                         new_tile.x = u * 25;
  165.                         new_tile.y = t * 25;
  166.                        
  167.                         tiles.push(new_tile);                               //put it in an array
  168.                     }
  169.                 }
  170.             }
  171.         }
  172.     }
  173. }
  174.  
  175. // You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

The level is stored in the Data.as

ACTIONSCRIPT:
  1. package{
  2.    
  3.     public class Data{
  4.        
  5.     public var level1:Array = new Array();
  6.         public function Setup(){
  7.             level1 = [
  8.                       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  9.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  10.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  11.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  12.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  13.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1],
  14.                       [1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  15.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  16.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  17.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  18.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  19.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  20.                       [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  21.                       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
  22.                       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
  23.                      ]
  24.         }
  25.     }
  26. }
  27.  
  28. // You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

While the solve_all function contained in the collision_manager.as solves all collisions in the forecast position of the player

ACTIONSCRIPT:
  1. package{
  2.    
  3.     public class collision_manager{
  4.         private var Tile_size:int;          //containing the size of the tiles
  5.         private var level;                  //level data container
  6.         private var forecast_x:int;         //where the player will be at the end of the frame
  7.         private var forecast_y:int;         //"                                               "
  8.         public var can_jump:Boolean;        //same as in Emanuele's tutorial
  9.         private var hero;                   //to store the Hero object in
  10.        
  11.         public function Setup(size,map,heroj){      //my standard setup function(init)
  12.             Tile_size = size;                       //initializing al vars
  13.             level = map;
  14.             hero = heroj;
  15.         }
  16.        
  17.         public function get_corners(point_x,point_y){              
  18.         //get the position of the four corners of the hero
  19.            
  20.             hero.downy = Math.round((point_y + 10 - Tile_size/2) / Tile_size);
  21.             hero.upy = Math.round((point_y - 10 - Tile_size/2) / Tile_size);
  22.             hero.rightx = Math.round((point_x + 5 - Tile_size/2) / Tile_size)
  23.             hero.leftx = Math.round((point_x - 5 - Tile_size/2) / Tile_size);
  24.             /*
  25.             Looks in wich tiles these four point are.
  26.             *Attention* TILES and not pixel!
  27.            
  28.             Will be used to get the position of the corners
  29.             and to get the end position of the hero.
  30.             */
  31.            
  32.             hero.downleft = level[hero.downy][hero.leftx];
  33.             hero.downright = level[hero.downy][hero.rightx];
  34.             hero.upright = level[hero.upy][hero.rightx];
  35.             hero.upleft = level[hero.upy][hero.leftx];
  36.            
  37.            
  38.             /*
  39.             Gets the sort tile the position of the corners has.
  40.            
  41.             One means there can be collision, zero is air.         
  42.             */
  43.         }
  44.        
  45.         public function check_ground(){
  46.             hero.downy = Math.round((hero.y + 11 - Tile_size/2) / Tile_size);
  47.             hero.rightx = Math.round((hero.x + 5 - Tile_size/2) / Tile_size)
  48.             hero.leftx = Math.round((hero.x - 5 - Tile_size/2) / Tile_size);
  49.             // Makes three points in tile-coordinates
  50.            
  51.             hero.downleft = level[hero.downy][hero.leftx];
  52.             hero.downright = level[hero.downy][hero.rightx];
  53.             //Checks the sort
  54.            
  55.             if(hero.downleft == 1 || hero.downright ==1){       //if there is any collision by the hero's feet
  56.                 can_jump = true;                                //than can jump
  57.             }
  58.             else{
  59.                 can_jump = false;                               //else not
  60.             }
  61.         }
  62.        
  63.         public function solve_all(forecastx, forecasty){
  64.         /*
  65.         This function looks hard... an it is...
  66.         I've been working on it for loads of hours, and this is the result.
  67.        
  68.         This is the best collision-test I've ever made, for sqaures.
  69.        
  70.         It's still readable, because I made it simple.
  71.        
  72.         It's four times almost the same. It checks for collision between the spots,
  73.         the four spots if there only were x_speeds, the four spots if there only was y_speed,
  74.         the four spots if there were both y- and x_speed.  
  75.         That are 3*4 = 12 spots.
  76.        
  77.        
  78.         //////////////////////////////////
  79.         Why's:
  80.        
  81.         question:
  82.         Why did I used forecast_x and forecast_y and not just hero.x and hero.y?
  83.        
  84.         answer:
  85.         Changing the hero over the screen will cost loads of CPU because an hero
  86.         exist out of loads of pixels. The forecast's are just simple variables
  87.        
  88.         question:
  89.         Is such a huge function not requiring a lot of CPU?
  90.        
  91.         answer:
  92.         It doesn't uses any while- or for loops, Math. functions and the most important of
  93.         all: no hitTestPoint()/hitTestObject(). So it's a lot faster.
  94.        
  95.         question:
  96.         Is there a better or faster collision test?
  97.        
  98.         answer:
  99.         Probaly, yes.
  100.         //////////////////////////////////
  101.        
  102.         var-explanation:
  103.        
  104.         downC   ->  is collision under the spot
  105.         upC     ->  is collision above the spot
  106.         rightC  ->  is collision right from the spot
  107.         leftC   ->  You probaly wouldn't expect this, but this is collision left from the spot
  108.        
  109.                 */
  110.             forecast_x = forecastx;
  111.             forecast_y = forecasty;
  112.            
  113.             get_corners(forecast_x,forecast_y);
  114.            
  115.             if(hero.downleft == 1){
  116.                 get_corners(hero.x,forecast_y);
  117.                     if(hero.downleft == 1){                
  118.                         hero.downC = true;
  119.                     }
  120.                     else{
  121.                         hero.downC = false;
  122.                     }
  123.                 get_corners(forecast_x,hero.y);
  124.                     if(hero.downleft == 1){                
  125.                         hero.leftC = true;
  126.                     }
  127.                     else{
  128.                         hero.leftC = false;
  129.                     }
  130.                     if(hero.leftC && hero.downC){
  131.                         forecast_x = (hero.leftx+1) * 25 + 5;
  132.                         forecast_y = (hero.downy+1) * 25 - 11;
  133.                         hero.y_speed = 0;
  134.                     }
  135.                     else if(hero.leftC){
  136.                         forecast_x = (hero.leftx+1) * 25 + 5;
  137.                     }
  138.                     else if(hero.downC){
  139.                         forecast_y = (hero.downy+1) * 25 - 11;
  140.                         hero.y_speed = 0;
  141.                     }
  142.             }
  143.            
  144.             get_corners(forecast_x,forecast_y);
  145.            
  146.             if(hero.downright == 1){
  147.                 get_corners(hero.x,forecast_y);
  148.                     if(hero.downright == 1){                   
  149.                         hero.downC = true;
  150.                     }
  151.                     else{
  152.                         hero.downC = false;
  153.                     }
  154.                 get_corners(forecast_x,hero.y);
  155.                     if(hero.downright == 1){                   
  156.                         hero.rightC = true;
  157.                     }
  158.                     else{
  159.                         hero.rightC = false;
  160.                     }
  161.                     if(hero.rightC && hero.downC){
  162.                         forecast_x = hero.rightx * 25 - 6;
  163.                         forecast_y = (hero.downy+1) * 25 - 11;
  164.                         hero.y_speed = 0;
  165.                     }
  166.                     else if(hero.rightC){
  167.                         forecast_x = hero.rightx * 25 - 6;
  168.                     }
  169.                     else if(hero.downC){
  170.                         forecast_y = (hero.downy+1) * 25 - 11;
  171.                         hero.y_speed = 0;
  172.                     }
  173.             }
  174.            
  175.             get_corners(forecast_x,forecast_y);
  176.            
  177.             if(hero.upleft == 1){
  178.                 get_corners(hero.x,forecast_y);
  179.                     if(hero.upleft == 1){                  
  180.                         hero.upC = true;
  181.                     }
  182.                     else{
  183.                         hero.upC = false;
  184.                     }
  185.                 get_corners(forecast_x,hero.y);
  186.                     if(hero.upleft == 1){                  
  187.                         hero.leftC = true;
  188.                     }
  189.                     else{
  190.                         hero.leftC = false;
  191.                     }
  192.                     if(hero.leftC && hero.upC){
  193.                         forecast_x = (hero.leftx+1) * 25 + 5;
  194.                         forecast_y = (hero.upy) * 25 + 10;
  195.                         hero.y_speed = 0;
  196.                     }
  197.                     else if(hero.leftC){
  198.                         forecast_x = (hero.leftx+1) * 25 + 5;
  199.                     }
  200.                     else if(hero.upC){
  201.                         forecast_y = (hero.upy) * 25 + 10;
  202.                         hero.y_speed  = 0;
  203.                     }
  204.             }
  205.            
  206.             get_corners(forecast_x,forecast_y);
  207.            
  208.             if(hero.upright == 1){
  209.                 get_corners(hero.x,forecast_y);
  210.                     if(hero.upright == 1){                 
  211.                         hero.upC = true;
  212.                     }
  213.                     else{
  214.                         hero.upC = false;
  215.                     }
  216.                 get_corners(forecast_x,hero.y);
  217.                     if(hero.upright == 1){                 
  218.                         hero.leftC = true;
  219.                     }
  220.                     else{
  221.                         hero.leftC = false;
  222.                     }
  223.                     if(hero.leftC && hero.upC){
  224.                         forecast_x = hero.rightx * 25 - 6;
  225.                         forecast_y = (hero.upy) * 25 + 10;
  226.                         hero.y_speed = 0;
  227.                     }
  228.                     else if(hero.leftC){
  229.                         forecast_x = hero.rightx * 25 - 6;
  230.                     }
  231.                     else if(hero.upC){
  232.                         forecast_y = (hero.upy) * 25 + 10;
  233.                         hero.y_speed  = 0;
  234.                     }
  235.             }
  236.            
  237.             hero.x = forecast_x;        //place the hero
  238.             hero.y = forecast_y;
  239.            
  240.             check_ground()      //runs the function to check for ground
  241.         }
  242.     }
  243. }
  244.  
  245. // You may not post this on any other site than: http://www.emanueleferonato.com or http://www.frozenhaddock.com. You may not claim that you wrote this code. I'm not responsible for any nuclear activity that may be caused by this script.

Now we have a working AS3 platform engine

Thanks to Bart de Boer for providing the source code of this prototype. Download it and start making your own AS3 platform game.

Step by step AS3 translation of Flash game creation tutorial – part 2

This is the second part of Tim Edelaar's step by step AS3 translation of Flash game creation tutorial.

Now it's time to translate to AS3 the content of Flash game creation tutorial - part 2 which I suggest you to read before this one.

The style of the coding is the same of the previous part, with actionscript written directly in the timeline with the critical parts commented.

The bounds

ACTIONSCRIPT:
  1. //import some important flash libraries.
  2. import flash.events.KeyboardEvent;
  3. import flash.events.Event;
  4. import flash.display.MovieClip;
  5.  
  6. //initializes variables.
  7. var speed:Number = 0.08;
  8. var xspeed:Number = 0;
  9. var yspeed:Number = 0;
  10. var friction:Number = 0.98;
  11. var gravity:Number = 0.04;
  12. var thrust:Number = 0.8;
  13. var key_left:Boolean = false;
  14. var key_right:Boolean = false;
  15. var key_up:Boolean = false;
  16. var key_down:Boolean = false;
  17.  
  18. //Checks if the player presses a key.
  19. stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
  20. stage.addEventListener(KeyboardEvent.KEY_UP,KeyUp);
  21.  
  22. //Lets the function main play every frame.
  23. addEventListener(Event.ENTER_FRAME,Main);
  24.  
  25. //create the function main.
  26. function Main(event:Event){
  27.     CheckKeys();
  28.     MoveHero();
  29.     CheckCollision();
  30. }
  31.  
  32. //create the function KeyDown.
  33. function KeyDown(event:KeyboardEvent){
  34.     if(event.keyCode == 37){        //checks if left arrowkey is pressed.
  35.         key_left = true;
  36.     }
  37.     if(event.keyCode == 39){        //checks if right arrowkey is pressed.
  38.         key_right = true;
  39.     }
  40.     if(event.keyCode == 38){        //checks if up arrowkey is pressed.
  41.         key_up = true;
  42.     }
  43.     if(event.keyCode == 40){        //checks if down arrowkey is pressed.
  44.         key_down = true;
  45.     }
  46. }
  47.  
  48. function KeyUp(event:KeyboardEvent){
  49.     if(event.keyCode == 37){        //checks if left arrowkey is released.
  50.         key_left = false;
  51.     }
  52.     if(event.keyCode == 39){        //checks if right arrowkey is released.
  53.         key_right = false;
  54.     }
  55.     if(event.keyCode == 38){        //checks if up arrowkey is released.
  56.         key_up = false;
  57.     }
  58.     if(event.keyCode == 40){        //checks if down arrowkey is released.
  59.         key_down = false;
  60.     }
  61. }
  62.  
  63. function CheckKeys(){
  64.     if(key_left){
  65.         xspeed -= speed;
  66.     }
  67.     if(key_right){
  68.         xspeed += speed;
  69.     }
  70.     if(key_up){
  71.         yspeed -= speed*thrust;
  72.     }
  73.     if(key_down){
  74.         yspeed += speed*thrust;
  75.     }
  76. }
  77.  
  78. function MoveHero(){
  79.     hero.x += xspeed;
  80.     hero.y += yspeed;
  81.     xspeed *= friction;
  82.     yspeed += gravity;
  83.     yspeed *= friction;
  84.     hero.rotation += xspeed;
  85. }
  86.  
  87. function CheckCollision(){
  88.     //Checks if left border hits the wall.
  89.     if(wall.hitTestPoint(hero.x-(hero.width-5)/2,hero.y,true)){
  90.         hero.x = 275;
  91.         hero.y = 200;
  92.         xspeed = 0;
  93.         yspeed = 0;
  94.     }
  95.     //Checks if right border hits the wall.
  96.     if(wall.hitTestPoint(hero.x+(hero.width-5)/2,hero.y,true)){
  97.         hero.x = 275;
  98.         hero.y = 200;
  99.         xspeed = 0;
  100.         yspeed = 0;
  101.     }
  102.     //Checks if upper border hits the wall.
  103.     if(wall.hitTestPoint(hero.x,hero.y-(hero.height-5)/2,true)){
  104.         hero.x = 275;
  105.         hero.y = 200;
  106.         xspeed = 0;
  107.         yspeed = 0;
  108.     }
  109.     //Checks if lower border hits the wall.
  110.     if(wall.hitTestPoint(hero.x,hero.y+(hero.height-5)/2,true)){
  111.         hero.x = 275;
  112.         hero.y = 200;
  113.         xspeed = 0;
  114.         yspeed = 0;
  115.     }
  116. }

The coin - 1st attempt

ACTIONSCRIPT:
  1. //import some important flash libraries.
  2. import flash.events.KeyboardEvent;
  3. import flash.events.Event;
  4. import flash.display.MovieClip;
  5.  
  6. //initializes variables.
  7. var speed:Number = 0.08;
  8. var xspeed:Number = 0;
  9. var yspeed:Number = 0;
  10. var friction:Number = 0.98;
  11. var gravity:Number = 0.04;
  12. var thrust:Number = 0.8;
  13. var key_left:Boolean = false;
  14. var key_right:Boolean = false;
  15. var key_up:Boolean = false;
  16. var key_down:Boolean = false;
  17.  
  18. //Checks if the player presses a key.
  19. stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
  20. stage.addEventListener(KeyboardEvent.KEY_UP,KeyUp);
  21.  
  22. //Lets the function main play every frame.
  23. addEventListener(Event.ENTER_FRAME,Main);
  24.  
  25. //create the function main.
  26. function Main(event:Event){
  27.     CheckKeys();
  28.     MoveHero();
  29.     CheckCollision();
  30. }
  31.  
  32. //create the function KeyDown.
  33. function KeyDown(event:KeyboardEvent){
  34.     if(event.keyCode == 37){        //checks if left arrowkey is pressed.
  35.         key_left = true;
  36.     }
  37.     if(event.keyCode == 39){        //checks if right arrowkey is pressed.
  38.         key_right = true;
  39.     }
  40.     if(event.keyCode == 38){        //checks if up arrowkey is pressed.
  41.         key_up = true;
  42.     }
  43.     if(event.keyCode == 40){        //checks if down arrowkey is pressed.
  44.         key_down = true;
  45.     }
  46. }
  47.  
  48. function KeyUp(event:KeyboardEvent){
  49.     if(event.keyCode == 37){        //checks if left arrowkey is released.
  50.         key_left = false;
  51.     }
  52.     if(event.keyCode == 39){        //checks if right arrowkey is released.
  53.         key_right = false;
  54.     }
  55.     if(event.keyCode == 38){        //checks if up arrowkey is released.
  56.         key_up = false;
  57.     }
  58.     if(event.keyCode == 40){        //checks if down arrowkey is released.
  59.         key_down = false;
  60.     }
  61. }
  62.  
  63. function CheckKeys(){
  64.     if(key_left){
  65.         xspeed -= speed;
  66.     }
  67.     if(key_right){
  68.         xspeed += speed;
  69.     }
  70.     if(key_up){
  71.         yspeed -= speed*thrust;
  72.     }
  73.     if(key_down){
  74.         yspeed += speed*thrust;
  75.     }
  76. }
  77.  
  78. function MoveHero(){
  79.     hero.x += xspeed;
  80.     hero.y += yspeed;
  81.     xspeed *= friction;
  82.     yspeed += gravity;
  83.     yspeed *= friction;
  84.     hero.rotation += xspeed;
  85. }
  86.  
  87. function CheckCollision(){
  88.     //Checks if left border hits the wall.
  89.     if(wall.hitTestPoint(hero.x-(hero.width-5)/2,hero.y,true)){
  90.         hero.x = 275;
  91.         hero.y = 200;
  92.         xspeed = 0;
  93.         yspeed = 0;
  94.     }
  95.     //Checks if right border hits the wall.
  96.     if(wall.hitTestPoint(hero.x+(hero.width-5)/2,hero.y,true)){
  97.         hero.x = 275;
  98.         hero.y = 200;
  99.         xspeed = 0;
  100.         yspeed = 0;
  101.     }
  102.     //Checks if upper border hits the wall.
  103.     if(wall.hitTestPoint(hero.x,hero.y-(hero.height-5)/2,true)){
  104.         hero.x = 275;
  105.         hero.y = 200;
  106.         xspeed = 0;
  107.         yspeed = 0;
  108.     }
  109.     //Checks if lower border hits the wall.
  110.     if(wall.hitTestPoint(hero.x,hero.y+(hero.height-5)/2,true)){
  111.         hero.x = 275;
  112.         hero.y = 200;
  113.         xspeed = 0;
  114.         yspeed = 0;
  115.     }
  116.     //Now do the same for our coin.
  117.     if(coin.hitTestPoint(hero.x,hero.y,true)){
  118.         coin.x = Math.random()*510+20; //Changes the x of the coin to a random number between 20 and 530.
  119.         coin.y = Math.random()*360+20; //Changes the y of the coin to a random number between 20 and 380.
  120.     }
  121. }

The coin - 2nd attempt

ACTIONSCRIPT:
  1. //import some important flash libraries.
  2. import flash.events.KeyboardEvent;
  3. import flash.events.Event;
  4. import flash.display.MovieClip;
  5.  
  6. //initializes variables.
  7. var speed:Number = 0.08;
  8. var xspeed:Number = 0;
  9. var yspeed:Number = 0;
  10. var friction:Number = 0.98;
  11. var gravity:Number = 0.04;
  12. var thrust:Number = 0.8;
  13. var key_left:Boolean = false;
  14. var key_right:Boolean = false;
  15. var key_up:Boolean = false;
  16. var key_down:Boolean = false;
  17.  
  18. //Checks if the player presses a key.
  19. stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
  20. stage.addEventListener(KeyboardEvent.KEY_UP,KeyUp);
  21.  
  22. //Lets the function main play every frame.
  23. addEventListener(Event.ENTER_FRAME,Main);
  24.  
  25. //create the function main.
  26. function Main(event:Event){
  27.     CheckKeys();
  28.     MoveHero();
  29.     CheckCollision();
  30. }
  31.  
  32. //create the function KeyDown.
  33. function KeyDown(event:KeyboardEvent){
  34.     if(event.keyCode == 37){        //checks if left arrowkey is pressed.
  35.         key_left = true;
  36.     }
  37.     if(event.keyCode == 39){        //checks if right arrowkey is pressed.
  38.         key_right = true;
  39.     }
  40.     if(event.keyCode == 38){        //checks if up arrowkey is pressed.
  41.         key_up = true;
  42.     }
  43.     if(event.keyCode == 40){        //checks if down arrowkey is pressed.
  44.         key_down = true;
  45.     }
  46. }
  47.  
  48. function KeyUp(event:KeyboardEvent){
  49.     if(event.keyCode == 37){        //checks if left arrowkey is released.
  50.         key_left = false;
  51.     }
  52.     if(event.keyCode == 39){        //checks if right arrowkey is released.
  53.         key_right = false;
  54.     }
  55.     if(event.keyCode == 38){        //checks if up arrowkey is released.
  56.         key_up = false;
  57.     }
  58.     if(event.keyCode == 40){        //checks if down arrowkey is released.
  59.         key_down = false;
  60.     }
  61. }
  62.  
  63. function CheckKeys(){
  64.     if(key_left){
  65.         xspeed -= speed;
  66.     }
  67.     if(key_right){
  68.         xspeed += speed;
  69.     }
  70.     if(key_up){
  71.         yspeed -= speed*thrust;
  72.     }
  73.     if(key_down){
  74.         yspeed += speed*thrust;
  75.     }
  76. }
  77.  
  78. function MoveHero(){
  79.     hero.x += xspeed;
  80.     hero.y += yspeed;
  81.     xspeed *= friction;
  82.     yspeed += gravity;
  83.     yspeed *= friction;
  84.     hero.rotation += xspeed;
  85. }
  86.  
  87. function CheckCollision(){
  88.     //Checks if left border hits the wall.
  89.     if(wall.hitTestPoint(hero.x-(hero.width-5)/2,hero.y,true)){
  90.         hero.x = 275;
  91.         hero.y = 200;
  92.         xspeed = 0;
  93.         yspeed = 0;
  94.     }
  95.     //Checks if right border hits the wall.
  96.     if(wall.hitTestPoint(hero.x+(hero.width-5)/2,hero.y,true)){
  97.         hero.x = 275;
  98.         hero.y = 200;
  99.         xspeed = 0;
  100.         yspeed = 0;
  101.     }
  102.     //Checks if upper border hits the wall.
  103.     if(wall.hitTestPoint(hero.x,hero.y-(hero.height-5)/2,true)){
  104.         hero.x = 275;
  105.         hero.y = 200;
  106.         xspeed = 0;
  107.         yspeed = 0;
  108.     }
  109.     //Checks if lower border hits the wall.
  110.     if(wall.hitTestPoint(hero.x,hero.y+(hero.height-5)/2,true)){
  111.         hero.x = 275;
  112.         hero.y = 200;
  113.         xspeed = 0;
  114.         yspeed = 0;
  115.     }
  116.     //Now do the same for our coin.
  117.     if(hero.hitTestObject(coin)){
  118.         coin.x = Math.random()*510+20; //Changes the x of the coin to a random number between 20 and 530.
  119.         coin.y = Math.random()*360+20; //Changes the y of the coin to a random number between 20 and 380.
  120.     }
  121. }

The coin - 3rd attempt

ACTIONSCRIPT:
  1. //import some important flash libraries.
  2. import flash.events.KeyboardEvent;
  3. import flash.events.Event;
  4. import flash.display.MovieClip;
  5.  
  6. //initializes variables.
  7. var speed:Number = 0.08;
  8. var xspeed:Number = 0;
  9. var yspeed:Number = 0;
  10. var friction:Number = 0.98;
  11. var gravity:Number = 0.04;
  12. var thrust:Number = 0.8;
  13. var key_left:Boolean = false;
  14. var key_right:Boolean = false;
  15. var key_up:Boolean = false;
  16. var key_down:Boolean = false;
  17.  
  18. //Checks if the player presses a key.
  19. stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
  20. stage.addEventListener(KeyboardEvent.KEY_UP,KeyUp);
  21.  
  22. //Lets the function main play every frame.
  23. addEventListener(Event.ENTER_FRAME,Main);
  24.  
  25. //create the function main.
  26. function Main(event:Event){
  27.     CheckKeys();
  28.     MoveHero();
  29.     CheckCollision();
  30. }
  31.  
  32. //create the function KeyDown.
  33. function KeyDown(event:KeyboardEvent){
  34.     if(event.keyCode == 37){        //checks if left arrowkey is pressed.
  35.         key_left = true;
  36.     }
  37.     if(event.keyCode == 39){        //checks if right arrowkey is pressed.
  38.         key_right = true;
  39.     }
  40.     if(event.keyCode == 38){        //checks if up arrowkey is pressed.
  41.         key_up = true;
  42.     }
  43.     if(event.keyCode == 40){        //checks if down arrowkey is pressed.
  44.         key_down = true;
  45.     }
  46. }
  47.  
  48. function KeyUp(event:KeyboardEvent){
  49.     if(event.keyCode == 37){        //checks if left arrowkey is released.
  50.         key_left = false;
  51.     }
  52.     if(event.keyCode == 39){        //checks if right arrowkey is released.
  53.         key_right = false;
  54.     }
  55.     if(event.keyCode == 38){        //checks if up arrowkey is released.
  56.         key_up = false;
  57.     }
  58.     if(event.keyCode == 40){        //checks if down arrowkey is released.
  59.         key_down = false;
  60.     }
  61. }
  62.  
  63. function CheckKeys(){
  64.     if(key_left){
  65.         xspeed -= speed;
  66.     }
  67.     if(key_right){
  68.         xspeed += speed;
  69.     }
  70.     if(key_up){
  71.         yspeed -= speed*thrust;
  72.     }
  73.     if(key_down){
  74.         yspeed += speed*thrust;
  75.     }
  76. }
  77.  
  78. function MoveHero(){
  79.     hero.x += xspeed;
  80.     hero.y += yspeed;
  81.     xspeed *= friction;
  82.     yspeed += gravity;
  83.     yspeed *= friction;
  84.     hero.rotation += xspeed;
  85. }
  86.  
  87. function CheckCollision(){
  88.     //Checks if left border hits the wall.
  89.     if(wall.hitTestPoint(hero.x-(hero.width-5)/2,hero.y,true)){
  90.         hero.x = 275;
  91.         hero.y = 200;
  92.         xspeed = 0;
  93.         yspeed = 0;
  94.     }
  95.     //Checks if right border hits the wall.
  96.     if(wall.hitTestPoint(hero.x+(hero.width-5)/2,hero.y,true)){
  97.         hero.x = 275;
  98.         hero.y = 200;
  99.         xspeed = 0;
  100.         yspeed = 0;
  101.     }
  102.     //Checks if upper border hits the wall.
  103.     if(wall.hitTestPoint(hero.x,hero.y-(hero.height-5)/2,true)){
  104.         hero.x = 275;
  105.         hero.y = 200;
  106.         xspeed = 0;
  107.         yspeed = 0;
  108.     }
  109.     //Checks if lower border hits the wall.
  110.     if(wall.hitTestPoint(hero.x,hero.y+(hero.height-5)/2,true)){
  111.         hero.x = 275;
  112.         hero.y = 200;
  113.         xspeed = 0;
  114.         yspeed = 0;
  115.     }
  116.     //Now do the same for our coin.
  117.     if(hero.hitTestPoint(coin.x,coin.y,true)){
  118.         coin.x = Math.random()*510+20; //Changes the x of the coin to a random number between 20 and 530.
  119.         coin.y = Math.random()*360+20; //Changes the y of the coin to a random number between 20 and 380.
  120.     }
  121. }

And that's all for today.

Download source codes and thank Tim Edelaar for the contribution

First Triqui’s milestone: 250,000 plays – considerations

This is the first milestone for Triqui: 250,000 plays.

I know there are portals that reach that number in a day (or less), anyway for a portal made in a few hours, I think it's an important step.

If you want to know more about Triqui, I suggest you to read these posts:

Ramblings about Flash game portals

Play Flash games on Triqui.com

More ramblings about Flash game portals

And now it's time to show you something about Triqui:

Ads placements

At the moment I am trying to monetize Triqui only with Adsense, so I placed one ad in the homepage and one ad in the page where you can play games.

The ads are placed in two very different areas, I made this in order to collect some data about interaction between the user and the ads.

As you can see from the picture, in the first page the ad is at the very top of the screen, while in the second one it's in the middle of the page.

The theory is: very few people will look at the first ad because they are looking at the games, and a lot of people will look at the second one because it's just under the game they are playing (and watching)

Let's see some numbers:

Home page CTR: 0.12
Game page CTR: 1.31

Home page eCPM: 0.14
Game page eCPM: 2.22

Obviously the game page ad is a lot more profitable than the home one.

Some of you may argue some clicks in the game page may be caused accidentally because the ad is too close to the game.

Yes... maybe... but I don't think this represents more than 10% of the total clicks.

Driving traffic

The only way I promoted Triqui was through this blog, and with two self-sponsored games: Jamag and Bees n' Flowers.

According to Google analytics, this is the chart of the visits to Triqui Triqui when the games got the frontpage of an important portal (no matter which portal).

As you can see, the "portal effect" is quite strong, and if you consider an average 5 plays per user, in its best day the portal scored 7,259 visitors and more than 35,000 plays with a 2.22 eCPM.

Not that bad, if you consider there is still no reason to return to Triqui once you visited it.

Actually my plan is breaking the average 1,000 daily visitors, with some new features to be added soon.

Again, I know 1,000 visitors is nothing, but the entire portal is nothing, don't forget there are no more than 100 php lines.

Search Engines

I did not that much to rank in search engines, but in some cases I had some nice surprises... I am the first relevant result for umbrella trick and the second one for operation darkness strike.

I am not talking about Bloons, but they drive some traffic to the site, and that's enough at the moment.

Final ramblings

Remember... if you can make some money developing Flash games, you can make even more money hosting a Flash gaming portal. You just need to drive some traffic on it and have something that will make visitors return.

Now I am planning a rating/reviewing system to the portal, just to see if I manage to fidelize some players.

Meanwhile, I would like to hear the voice of some small portal owners.

What to do when you are looking for pixel graphics for your game and run out of ideas

You are trying to design some decent pixel graphics for your tile based game and all you have is a Photoshop document with some crap on it.

How many times did it happen in your life?

Here they are a couple of clues to help you in this task.

Once upon a time...

Look what I found on Wikipedia:

"RPG Maker (1st release: December 17, 1992) is a program that allows users to create their own role-playing games. Most versions include a tile set based map editor, (tilesets are called chipsets in pre-XP versions), a simple scripting language for scripting events, and a battle editor. All versions include initial premade tilesets, characters, and events which can be used in creating new games. An interesting feature of the PC Versions of RPG Maker programs is that a user can create new tilesets and characters, and add any new graphics he/she wants. Several sites have developed, dedicated to helping users share their creations."

Now the question is: so what?

Well, read once again this: "An interesting feature of the PC Versions of RPG Maker programs is that a user can create new tilesets and characters, and add any new graphics he/she wants".

So if you google for rpg maker chipset images or rpg maker tileset images, you will find a lot of sites with free tile based pixel art for your use or inspiration.

And it's not over... there is a site called Charas containing an online character generator.

As you can see from the picture, it's very easy to have your character with a 4 way walking animation in a matter of seconds, with thousands of options to custom it.

I hope this hint will make you save some time when you are looking for pixel graphics and run out of creativity. It saved mine for sure.

Adding a new twist to the prototype of a Flash game like Poux

Do you remember the Poux tutorial series?

If not, then read parts 1, 2 and 3 and take a look at the finished project known as Christmas Couples.

I always say using prototypes to create games is a good idea, and the almost 7,000,000 plays Christmas Couples had since its release confirm my theory.

Anyway, the "twist" is you must remove adjacent tiles by drawing on them.

You must connect two or more adjacent tiles with the same color with the "pen", and if you have the precision of a surgeon, you can also connect tiles diagonally!

Oh, well, take the commented actionscript Read more

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

Next Page →

Posts