Great Games

Bow Street RunnerQuadradiusChick Chick BOOMMore BeerSomething AmissAgent Wing DefendersSeven Deadly SinsChromaBlastRed BaronNewgrounds Rumble100th Review!: Pico's Surprise PartyRailway To Heaven

Worth Checking Out

Zodiac TowerNFL BandwagonRailroad Ruckus Stunt Bike DrawPirates & TreasureBee DodgerAquacubesDrakojan Skies: AcolytesHead GamesTri-achnidHewittI Know Where Bruce Lee LivesEndless Zombie RampageDeep FreezeMissile Game 3D HSHovertanksAbstract SeaFive 'til

Link to us

Here are some button images you can download. We have buttons for fans, and buttons for developers that have been featured on the site.


 

Recent Visitors


July 14th, 2008

Create a Flash game like Deflection - part 2 - Posted by Emanuele Feronato

In the 1st part I showed you how to make a deflection engine starting from an old tutorial, now it’s time to let the player draw walls.

The idea comes from Srdjan Susnic, a reader who runs the blog Ask For Game Task.

The main task Srdjan accomplished was to add a mouse control so a player can draw lines from which the ball will bounce.

After collision between the ball and a line drawn by mouse, that line must be removed

The code is clear and well commented, but it seems to suffer a bug if the player just clicks the mouse without drawing.

It’s just a minor issue I fixed in a moment, and if you already read the original post, I just added the control if the player drew a line when he releases the mouse button with player_drew variable.

Anyway, this is the actionscript:

ACTIONSCRIPT:

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

And this is the result:

Now you can draw lines with the mouse and the only thing we need in order to have a complete game engine is handling the exit.

Any idea?

Download the source code and play.

Bookmark this page on Digg, Kinja, FURL, Redit & other sites

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.