Create a Flash game like Deflection – part 3

Multipart tutorial: available parts 1, 2, 3

In this 3rd part we are going to create a complete game with exit and two levels.

Read parts 1 and 2 if you haven't done it already.

I'll also fix a bug reported by Questo:

I was playing around and if you right click while making a line it sotps the ball but the ball keeps moving when you put lines on it. it’s pretty cool.

It's not a difficult task since the game engine is already working... I just created a makelevel function that handles level creation with a switch

ACTIONSCRIPT:
  1. // create game object
  2. game = {gravity:0, dragging:false, clip:_root.game_mc, stageW:500, stageH:400, maxV:20};
  3. // starting level
  4. level = 1;
  5. // function that prepares the level
  6. function makelevel(level) {
  7.     // flag that states if we can draw line or not
  8.     can_draw = false;
  9.     // flag that states if the player drew a line
  10.     player_drew = false;
  11.     // next movie depth for the current drawing line
  12.     nextLineDepth = 0;
  13.     // create the exit
  14.     _root.attachMovie("exit", "exit", 1);
  15.     // create the movieclip that will contain maze lines
  16.     _root.createEmptyMovieClip("lines", 2);
  17.     lines.lineStyle(1, 0xff0000);
  18.     // create a movie which represents a line drawn by mouse
  19.     _root.createEmptyMovieClip("mouseLine", 3);
  20.     // create array for vectors of lines drawn by mouse
  21.     game.mouseV = new Array();
  22.     // create the ball
  23.     _root.attachMovie("ball", "ball", 4);
  24.     game.myOb = {clip:ball, airf:1, b:1, f:1, r:10, lastTime:getTimer()};
  25.     // drawing and placing assets according to level number
  26.     switch (level) {
  27.     case 1 :
  28.         exit._x = 100;
  29.         exit._y = 300;
  30.         game.myOb.p0 = {x:20, y:80};
  31.         // vectors x/y components
  32.         game.myOb.vx = 0;
  33.         game.myOb.vy = 12;
  34.         // create first vector
  35.         // point p0 is its starting point in the coordinates x/y
  36.         // point p1 is its end point in the coordinates x/y
  37.         game.v = new Array();
  38.         game.v[0] = {p0:{x:50, y:40}, p1:{x:450, y:40}};
  39.         game.v[1] = {p0:{x:50, y:40}, p1:{x:50, y:360}};
  40.         game.v[2] = {p0:{x:50, y:360}, p1:{x:450, y:360}};
  41.         game.v[3] = {p0:{x:100, y:80}, p1:{x:400, y:320}};
  42.         break;
  43.     case 2 :
  44.         exit._x = 100;
  45.         exit._y = 350;
  46.         game.myOb.p0 = {x:250, y:250};
  47.         // vectors x/y components
  48.         game.myOb.vx = 12;
  49.         game.myOb.vy = 0;
  50.         // create first vector
  51.         // point p0 is its starting point in the coordinates x/y
  52.         // point p1 is its end point in the coordinates x/y
  53.         game.v = new Array();
  54.         game.v[0] = {p0:{x:200, y:0}, p1:{x:200, y:120}};
  55.         game.v[1] = {p0:{x:200, y:150}, p1:{x:200, y:400}};
  56.         game.v[2] = {p0:{x:300, y:0}, p1:{x:300, y:400}};
  57.         game.v[3] = {p0:{x:0, y:300}, p1:{x:200, y:300}};
  58.         game.v[4] = {p0:{x:200, y:150}, p1:{x:300, y:150}};
  59.         break;
  60.     }
  61.     // draw and calculate all parameters for the wall vectors
  62.     for (x=0; x<game.v.length; x++) {
  63.         lines.moveTo(game.v[x].p0.x, game.v[x].p0.y);
  64.         lines.lineTo(game.v[x].p1.x, game.v[x].p1.y);
  65.         updateVector(game.v[x], true);
  66.     }
  67.     // flag to see if I pressed the right mouse button
  68.     right_click = false;
  69. }
  70. // phyisically making the level
  71. makelevel(level);
  72. _root.onEnterFrame = function() {
  73.     // checking right mouse button
  74.     if (Key.isDown(2)) {
  75.         right_click = true;
  76.     }
  77.     _root.runMe();
  78.     // checking the distance from the exit
  79.     dist_x = ball._x-exit._x;
  80.     dist_y = ball._y-exit._y;
  81.     distance = dist_x*dist_x+dist_y*dist_y;
  82.     // arbitrary distance, I don't want the ball to just touch the exit, I want the ball to be a bit inside the exit
  83.     if (distance<256) {
  84.         // level up...
  85.         level++;
  86.         makelevel(level);
  87.     }
  88. };
  89. // function to draw the points, lines and show text
  90. function drawAll(v) {
  91.     // place ob mc
  92.     v.clip._x = v.p1.x;
  93.     v.clip._y = v.p1.y;
  94. }
  95. // main function
  96. function runMe() {
  97.     // start to calculate movement
  98.     var ob = game.myOb;
  99.     // add air resistance
  100.     ob.vx *= ob.airf;
  101.     ob.vy *= ob.airf;
  102.     // dont let it go over max speed
  103.     if (ob.vx>game.maxV) {
  104.         ob.vx = game.maxV;
  105.     } else if (ob.vx<-game.maxV) {
  106.         ob.vx = -game.maxV;
  107.     }
  108.     if (ob.vy>game.maxV) {
  109.         ob.vy = game.maxV;
  110.     } else if (ob.vy<-game.maxV) {
  111.         ob.vy = -game.maxV;
  112.     }
  113.     // update the vector parameters                
  114.     updateObject(ob);
  115.     // check the walls for collisions
  116.     for (x=0; x<game.v.length; x++) {
  117.         var w = game.v[x];
  118.         var v = findIntersection(ob, w);
  119.         v = updateVector(v, false);
  120.         var pen = ob.r-v.len;
  121.         // if we have hit the wall
  122.         if (pen>=0) {
  123.             // move object away from the wall
  124.             ob.p1.x += v.dx*pen;
  125.             ob.p1.y += v.dy*pen;
  126.             // change movement, bounce off from the normal of v
  127.             var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
  128.             var vb = bounce(ob, vbounce);
  129.             ob.vx = vb.vx;
  130.             ob.vy = vb.vy;
  131.         }
  132.     }
  133.     /********************************************************************/
  134.     // CODE ADDED BY SRDJAN SUSNIC
  135.     // check the lines created by mouse for collisions
  136.     x = 0;
  137.     while (x<game.mouseV.length) {
  138.         var w = game.mouseV[x];
  139.         var v = findIntersection(ob, w);
  140.         v = updateVector(v, false);
  141.         var pen = ob.r-v.len;
  142.         // if we have hit the wall
  143.         if (pen>=0) {
  144.             // move object away from the wall
  145.             ob.p1.x += v.dx*pen;
  146.             ob.p1.y += v.dy*pen;
  147.             // change movement, bounce off from the normal of v
  148.             var vbounce = {dx:v.lx, dy:v.ly, lx:v.dx, ly:v.dy, b:1, f:1};
  149.             var vb = bounce(ob, vbounce);
  150.             ob.vx = vb.vx;
  151.             ob.vy = vb.vy;
  152.             // remove the clip and vector array of the collided line
  153.             game.mouseV[x].lineClip.removeMovieClip();
  154.             game.mouseV.splice(x, 1);
  155.         } else {
  156.             x++;
  157.         }
  158.     }
  159.     // END OF CODE ADDED BY SRDJAN SUSNIC  
  160.     /********************************************************************/
  161.     // reset object to other side if gone out of stage
  162.     if (ob.p1.x>game.stageW+ob.r) {
  163.         ob.p1.x = -ob.r;
  164.     } else if (ob.p1.x<-ob.r) {
  165.         ob.p1.x = game.stageW+ob.r;
  166.     }
  167.     if (ob.p1.y>game.stageH+ob.r) {
  168.         ob.p1.y = -ob.r;
  169.     } else if (ob.p1.y<-ob.r) {
  170.         ob.p1.y = game.stageH+ob.r;
  171.     }
  172.     // draw it                
  173.     drawAll(ob);
  174.     // make end point equal to starting point for next cycle
  175.     ob.p0 = ob.p1;
  176.     // save the movement without time
  177.     ob.vx = ob.vx/ob.timeFrame;
  178.     ob.vy = ob.vy/ob.timeFrame;
  179. }
  180. // function to find all parameters for the vector
  181. function updateVector(v, frompoints) {
  182.     // x and y components
  183.     if (frompoints) {
  184.         v.vx = v.p1.x-v.p0.x;
  185.         v.vy = v.p1.y-v.p0.y;
  186.     } else {
  187.         v.p1.x = v.p0.x+v.vx;
  188.         v.p1.y = v.p0.y+v.vy;
  189.     }
  190.     // length of vector
  191.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  192.     // normalized unti-sized components
  193.     if (v.len>0) {
  194.         v.dx = v.vx/v.len;
  195.         v.dy = v.vy/v.len;
  196.     } else {
  197.         v.dx = 0;
  198.         v.dy = 0;
  199.     }
  200.     // right hand normal
  201.     v.rx = -v.dy;
  202.     v.ry = v.dx;
  203.     // left hand normal
  204.     v.lx = v.dy;
  205.     v.ly = -v.dx;
  206.     return v;
  207. }
  208. function updateObject(v) {
  209.     // find time passed from last update
  210.     var thisTime = getTimer();
  211.     var time = (thisTime-v.lastTime)/100;
  212.     // we use time, not frames to move so multiply movement vector with time passed
  213.     v.vx *= time;
  214.     v.vy *= time;
  215.     // add gravity, also based on time
  216.     v.vy = v.vy+time*game.gravity;
  217.     v.p1 = {};
  218.     // find end point coordinates
  219.     v.p1.x = v.p0.x+v.vx;
  220.     v.p1.y = v.p0.y+v.vy;
  221.     // length of vector
  222.     v.len = Math.sqrt(v.vx*v.vx+v.vy*v.vy);
  223.     // normalized unti-sized components
  224.     v.dx = v.vx/v.len;
  225.     v.dy = v.vy/v.len;
  226.     // right hand normal
  227.     v.rx = -v.vy;
  228.     v.ry = v.vx;
  229.     // left hand normal
  230.     v.lx = v.vy;
  231.     v.ly = -v.vx;
  232.     // save the current time
  233.     v.lastTime = thisTime;
  234.     // save time passed
  235.     v.timeFrame = time;
  236. }
  237. // find intersection point of 2 vectors
  238. function findIntersection(v1, v2) {
  239.     // vector between center of ball and starting point of wall
  240.     var v3 = {};
  241.     v3.vx = v1.p1.x-v2.p0.x;
  242.     v3.vy = v1.p1.y-v2.p0.y;
  243.     // check if we have hit starting point
  244.     var dp = v3.vx*v2.dx+v3.vy*v2.dy;
  245.     if (dp<0) {
  246.         // hits starting point
  247.         var v = v3;
  248.     } else {
  249.         var v4 = {};
  250.         v4.vx = v1.p1.x-v2.p1.x;
  251.         v4.vy = v1.p1.y-v2.p1.y;
  252.         // check if we have hit side or endpoint
  253.         var dp = v4.vx*v2.dx+v4.vy*v2.dy;
  254.         if (dp>0) {
  255.             // hits ending point
  256.             var v = v4;
  257.         } else {
  258.             // it hits the wall
  259.             // project this vector on the normal of the wall
  260.             var v = projectVector(v3, v2.lx, v2.ly);
  261.         }
  262.     }
  263.     return v;
  264. }
  265. // find new vector bouncing from v2
  266. function bounce(v1, v2) {
  267.     // projection of v1 on v2
  268.     var proj1 = projectVector(v1, v2.dx, v2.dy);
  269.     // projection of v1 on v2 normal
  270.     var proj2 = projectVector(v1, v2.lx, v2.ly);
  271.     var proj = {};
  272.     // reverse projection on v2 normal
  273.     proj2.len = Math.sqrt(proj2.vx*proj2.vx+proj2.vy*proj2.vy);
  274.     proj2.vx = v2.lx*proj2.len;
  275.     proj2.vy = v2.ly*proj2.len;
  276.     // add the projections
  277.     proj.vx = v1.f*v2.f*proj1.vx+v1.b*v2.b*proj2.vx;
  278.     proj.vy = v1.f*v2.f*proj1.vy+v1.b*v2.b*proj2.vy;
  279.     return proj;
  280. }
  281. // project vector v1 on unit-sized vector dx/dy
  282. function projectVector(v1, dx, dy) {
  283.     // find dot product
  284.     var dp = v1.vx*dx+v1.vy*dy;
  285.     var proj = {};
  286.     // projection components
  287.     proj.vx = dp*dx;
  288.     proj.vy = dp*dy;
  289.     return proj;
  290. }
  291. /********************************************************************/
  292. // CODE ADDED BY SRDJAN SUSNIC
  293. // declare starting point of the current drawing line
  294. var lineX1, lineY1;
  295. // declare ending point of the current drawing line
  296. var lineX2, lineY2;
  297. // when we click...
  298. onMouseDown = function () {
  299.     // get starting point of line according to current mouse position
  300.     lineX1 = _root._xmouse;
  301.     lineY1 = _root._ymouse;
  302.     // set drawing flag so we can draw a line when mouse is moved
  303.     can_draw = true;
  304. };
  305. // when we move mouse...
  306. onMouseMove = function () {
  307.     if (can_draw) {
  308.         // the player is drawing!
  309.         player_drew = true;
  310.         // get ending point of line according to current mouse position
  311.         lineX2 = _root._xmouse;
  312.         lineY2 = _root._ymouse;
  313.         // clear the previous line drawn by mouse
  314.         mouseLine.clear();
  315.         // set the drawing style
  316.         mouseLine.lineStyle(2, 0x00dd00);
  317.         // move the pen to the starting position
  318.         mouseLine.moveTo(lineX1, lineY1);
  319.         // draw the line to the ending position
  320.         mouseLine.lineTo(lineX2, lineY2);
  321.     }
  322. };
  323. // when we release...
  324. onMouseUp = function () {
  325.     if (player_drew and !right_click) {
  326.         // clear the line drawn by mouse
  327.         mouseLine.clear();
  328.         // create a new movie clip which contains the line previously drawn by mouse
  329.         var tmp = mouseLine.createEmptyMovieClip("newLine", 10+nextLineDepth);
  330.         tmp.lineStyle(5, 0x0000ff);
  331.         tmp.moveTo(lineX1, lineY1);
  332.         tmp.lineTo(lineX2, lineY2);
  333.         // increase movie depth for the next line
  334.         nextLineDepth++;
  335.         // add the parameters of previously created line to the end of line vectors array
  336.         // lineClip parameter is used to store previously created line movie clip
  337.         // so we can remove it when ball bounces from it
  338.         index = game.mouseV.length;
  339.         game.mouseV[index] = {p0:{x:lineX1, y:lineY1}, p1:{x:lineX2, y:lineY2}, b:1, f:1, lineClip:tmp};
  340.         // calculate all parameters for the created line vector
  341.         updateVector(game.mouseV[index], true);
  342.         // set drawing flag so we can't draw a line when mouse is moved
  343.         player_drew = false;
  344.     }
  345.     // if the released button was after a right click, then don't draw the new line              
  346.     if (right_click) {
  347.         right_click = false;
  348.         mouseLine.clear();
  349.     }
  350.     can_draw = false;
  351. };
  352. // END OF CODE ADDED BY SRDJAN SUSNIC  
  353. /********************************************************************/

And now you can play this two levels game... take the blue ball to the green circle.

Now you have all the basics to create your own Deflection game... so I expect to see something interesting on NewGrounds in a few hours.

Download the full source code and show me what you did.

Multipart tutorial: available parts 1, 2, 3

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (8 votes, average: 5 out of 5)
Loading ... Loading ...
If you found this post useful, please consider a small donation.
» Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.

6 Responses to “Create a Flash game like Deflection – part 3”

  1. Niall Lavigne on July 25th, 2008 8:11 pm

    Awesome, you got the tutorial finished.

    I can’t wait to see the creations people come up with with this! (:

  2. Questo on July 25th, 2008 10:02 pm

    It wasn’t so much of a bug as it was me doing what I wasn’t supposed to do. But wow you fixed it!

  3. RanDum on August 25th, 2008 1:45 am

    Awsome, you amaze me again.

    I am making a game similar to stick cs, but with the ability to choose from a pool of pre-unlocked weapons before gameplay and I’m having trouble with the action script on saving progress and unlocks.
    can you help?

  4. Rolpege on March 31st, 2009 8:25 pm

    It has a bug. Sometimes, the ball freezes.

Leave a Reply




Trackbacks

  1. Create a Flash game like Deflection - part 2 : Emanuele Feronato - italian geek and PROgrammer on July 25th, 2008 6:48 pm

    [...] Multipart tutorial: available parts 1, 2, 3 [...]

  2. Create a Flash game like Deflection : Emanuele Feronato - italian geek and PROgrammer on July 25th, 2008 6:49 pm

    [...] Multipart tutorial: available parts 1, 2, 3 [...]

Posts