A Flash Developer Resource Site

Results 1 to 17 of 17

Thread: trajectory help

  1. #1
    Junior Member
    Join Date
    Apr 2006
    Posts
    13

    trajectory help

    ive been trying to do this project where the player can choose the angle and the power of your shot and try to hit the other player, but i cant seem to get the coding right at all. can sum1 plz help? thanx

  2. #2
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    We'll have to build a physics engine. Don't worry, it's not as scary as it sounds. Basically, for every new projectile you create we'll give it some inital conditions and then let Flash do all the hard work.

    It's going to take a bit of code though, so you still interested? Otherwise I don't want to spend ages writing it all and explaining it.
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  3. #3
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    ye! thanx a lot, ive been looking all over. ye, i know a bit about physics, the equations and etc. like displacement and initial velocity and stuff like that, i just dont know how to put it into flash.

    thanx a lot. if u cant code it den dont worry.

    -darksauce

  4. #4
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    The way the physics engine works is like this. The projectile will have forces acting on it in different directions. These are forces like wind and gravity. Our physics engine will work out the sum of all these force (called the net force). Then, using Newton's famous eqution net force = mass x acceleration, we can work out the acceleration. We then need to mutiply this value by very small change in time. This is because although the acceleration is actually changing, we can approximately say it stays constant for a small time interval. This gives us a change in velocity, which we can then add to the current velocity and hence work out how far to move. This might seem like a lot, but it actually works out very simple. If you want to see this argument in a bit more depth and with a small example, look at another post I made here.

    Now, to make things easier I'm going to use objects to simulate vectors. This makes the calcualtions (and the code) a bit easier in the long run. All the forces, velocities and accelerations are really vectors, meaning that they have two components - one in the x direction, and one in the y direction. When I create a new force like gravity, I'm going to create a new object and give it an x and a y component. In the case of gravity, the x component will be zero, and the y component will be 9.81 (I'm not going to include the mass becuase I'm going to assume they aren't going to be allowed to change the mass in this game, so we might as well ignore it). Let's have a look at some code:

    code:

    //Set up two objects for the two forces - gravity and wind;
    //Create a gravity vector;
    var gravity:Object = {x:0, y9.81*this.mass)};
    //Create a wind vector;
    var wind:Object = {x:20, y:0};

    //Here's the simulate function that each will run for each new projectile;
    function simulate() {
    //Small change in time;
    var dt:Number = 1/50;
    //Create the net force object;
    var netForce:Object = {x:0, y:0};


    //Add gravity and wind to the netForce;
    netForce.x += wind.x;
    //I'm allowing for the fact the the wind might have a y component;
    netForce.y += gravity.y + wind.y;

    //Now that we have the netForce, divide by the mass to get the acceleration;
    var a:Object = new Object();
    a.x = netForce.x / this.mass;
    a.y = netForce.y / this.mass;

    //Mulitply by a small change in time and add this to the velocity;
    this.v.x += a.x * dt;
    this.v.y += a.y * dt;

    //Move based on this velocity;
    this._x += this.v.x;
    this._y += this.v.y;
    }

    //Now whenever we create a new projectile, we run this function on it. This will
    //set the mass and the inital velocity and set 'simulate' to run on each frame.
    function initProjectile(mc:MovieClip, m:Number, v:Object) {
    //Set the mass;
    mc.mass = m;
    //Set the inital velocity;
    mc.v = v;
    //Set the onEnterFrame;
    mc.onEnterFrame = simulate;
    }

    //Create a new variable to index the particles;
    var index:Number = 0;

    //Attach a projectile to the stage, and then apply initProjectile to it.
    var newP:MovieClip = _root.attachMovie("ball", "ball"+(index++), _root.getNextHighestDepth());
    //Set initial x and y;
    newP._x = 0;
    newP._y = Stage.height - newP._height / 2;
    //Run initProjectile on newP;
    initProjectile(newP, 10, {x:0, y:-10});



    You'll need to set the fps to 60, and have a clip in the library set to Export for ActionScript with a linkage name of ball. As you can see, the wind force can have x and y components, and this is taken into account when the forces are added.

    When we attach a new particle to the stage, we always run initProjectile on it. The first argument just tells the function what the reference of the new clip is. The second argument is just an object with an x and a y property, which represents the inital velocity. Let's put all this creation stuff into an onPress event for a button. Call the button fireBtn.

    code:

    //Create a new variable to index the particles;
    var index:Number = 0;

    fireBtn.onPress = function() {
    //Attach a projectile to the stage, and then apply initProjectile to it.
    var newP:MovieClip = _root.attachMovie("ball", "ball"+(index++), _root.getNextHighestDepth());
    //Set initial x and y;
    newP._x = 0;
    newP._y = Stage.height - newP._height / 2;
    //Run initProjectile on newP;
    initProjectile(newP, {x:0, y:-10});
    }



    Now when you press the button, a new projectile appears and moves under the effect of the forces. All we need to do now is add two text fields, one for the user to input the angle of shot, and one for the inital velocity. Call them angleTxt and velTxt. Now to the button, we add new steps to work out the inital velocity:

    code:

    fireBtn.onPress = function() {
    //Attach a projectile to the stage, and then apply initProjectile to it.
    var newP:MovieClip = _root.attachMovie("ball", "ball"+(index++), _root.getNextHighestDepth());
    //Set initial x and y;
    newP._x = 0;
    newP._y = Stage.height - newP._height / 2;

    //Calculate the inital velocity;
    var initalVel:Object = new Object();
    //They'll probably want to enter in degrees, so we'll have to convert to radians;
    initalVel.x = Number(velTxt.text) * Math.cos(Number(-angleTxt.text) / 180 * Math.PI);
    initalVel.y = Number(velTxt.text) * Math.sin(Number(-angleTxt.text) / 180 * Math.PI);

    //Run initProjectile on newP with initalVel;
    initProjectile(newP, initalVel);
    }



    There are a few other things to tidy up. Firstly, if the ball falls below the stage height, then you want to remove it, so put this in the simulate function near the bottom:

    code:

    if (this._y + this._height / 2 > 400) {
    this.removeMovieClip();
    }



    Secondly, restict the text inputs so they can only accept numbers. For angle, the number must be in the range 0 - 90, so you'll need to put some if statements on the fire button to make sure that its within range.

    code:

    //Restrict the values;
    angleTxt.restrict = "0-9";
    velTxt.restrict = "0-9";



    Enclosed is the full .fla file. You might find that the velocity is a bit sensitive, so you might want to take their value and divide it by 2 or 3 to maks it a bit smaller before you calculate the inital velocity.

    Any more questions, just let me know.
    Attached Files Attached Files
    Last edited by dmonkey; 09-29-2007 at 06:21 AM.
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  5. #5
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    the coding is really good i cant seem to launch the "ball" movie clip. do i hav to create anything else to go with it? or is dat it?


    nb: dont worry, i figured it out. Now how do i make it that that when the angle changes, the movie clip turret moves accordingly? like if the player chose 45 degrees, how can i make the turret also point 45 degrees?

    and how can we change the x and y position of the ball? i want it so that it is being fired by a cannon, but the way it is programmed now is that it shoots out from the bottom left corner. and is it possible to make the ball a movie clip with its own actions rather than being linked than fired? because when i test it it doesnt show but when i publish it then it shows.

    help is much appreciated, thanx
    Last edited by darksauce; 04-16-2006 at 02:32 AM.

  6. #6
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    The inital x and y values are set in the button press behaviour. If you want the ball to come from the end of the cannon, you'll have to do some more trig. To make the cannon rotate, simply set its _rotation value to Number(angleTxt.text). I'm not sure what you mean about making the ball "a movie clip with its own actions".
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  7. #7
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    dont worry about the "ball" bit, everything is just about right now, i just need to know how to make another player so that once one player shoots, all his actions will be disabled until his next go. how would that be programmed?

  8. #8
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    Just disable his fire button.

    code:

    fireBtn.enabled = false;



    If you have two fire buttons, one for P1 and one for P2, you can set the start positions of each player's projectile differently, but they'll use the same piece of code to actually move the projectile. You also might want to think about setting the wind randomly on each persons go, and displaying this on screen to the player's can think about adjusting their shots to take the wind into account.
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  9. #9
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    thanx, it works. is there a way to enable the velocity or power into a power meter which the player must time to get the poewr they want?

    like:
    power
    |_________|________|

    or sumthin? thanx alot so far

  10. #10
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    The velocity that you get out of the text field is just a number, so you can get it from anywhere. Create a 2 new clips called powerBar1 and powerBar2, and make them rectangular bars. Now in your fireBtn codes, replace velTxt.text with powerBar1._xscale and powerBar2._xscale. This will give you a number between 0 and 100, so you might want to divide it by something to reduce the range.

    To make the power bar move up and down, just alter the _xscale on every frame:

    code:

    function oscillate() {
    //Check it is that player's turn;
    if (this.myTurn) {
    if (_xscale < 0) {
    this.dir = 1;
    } else if (_xscale) > 100) {
    this.dir = -1;
    }
    this._xscale += this.dir;
    }
    }

    //Set the inital directions;
    powerBar1.dir = -1;
    powerBar2.dir = -1;

    //Set whose turn it is;
    powerBar1.myTurn = true;
    powerBar2.myTurn = false;

    //Set the onEnterFrame;
    powerBar1.onEnterFrame = oscillate;
    powerBar2.onEnterFrame = oscillate;



    To stop the power bar from moving, you set "myTurn" on that clip to false. So on your fireBtn for player 1, you would set powerBar1.myTurn = false and powerBar2.myTurn = true.
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  11. #11
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    ive tried making the power bars but it doesnt seem to work. i have done everything you hav told me to do. can u make the .fla to show me how it works? and if possible, can u include some trig codes/ examples to show the turret moving and the ball launching out of it?

    help is appreciated. thanx

  12. #12
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    This is more help than I would usually give, but I thought that this was quite interesting anyway, so here's the .fla. It's not perfect, but it'll do the job. Feel free to change anything you want - as long as you keep the instance names the same it should work fine.

    Hope this helps.
    Last edited by dmonkey; 09-29-2007 at 06:21 AM.
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  13. #13
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    dat was awesome! thanx. it seems like everything is going like its supposed to when i tested it, it seemed like there was some kind of wind? how would i display this? in a movieclip or wat? thanx for your help this far. i'll show u the next installment of this game.

    thanx alot, your help is appreciated

  14. #14
    All 1s and 0s dmonkey's Avatar
    Join Date
    Nov 2005
    Location
    Leeds, UK
    Posts
    606
    Hi,

    The wind is an object, and it's the second thing that I defined (line 5 I think). To display this on the screen, you could draw a horizontal arrow, call it 'arrow', and set it's direction like this:

    code:

    arrow._rotation = Math.atan2(wind.y, wind.x) / Math.PI * 180;



    You might need to add or subtract 90 degrees to make it point in the right direction (maybe more depending on if you drew the arrow to the left or to the right initally, but it will be either 90, 180 or 270). To make it more difficult, you could make this wind change direction now and then, simply by changing the x and y values of the wind:

    code:

    wind.x = -20;
    wind.y = 0;



    This will make the wind blow to the left. By making y non-zero, you can add upwards and downwards components to the wind (remember that a positive value for y means that the wind blows down). Each time you change the value of the wind that you'll have to update the direction of the arrow.

    I'm glad that I was able to help!
    "If I have seen further, it is by standing on the shoulders of giants." - Sir Isaac Newton

  15. #15
    Junior Member
    Join Date
    Apr 2006
    Posts
    13
    just a quick post. u know the cannon rite? when the player types in the angle, the cannon automatically points to the desired angle. But i want it so that the cannon kinda eases/motion-tweens its direction to the given angle. How would this be programmed?

    by the way, the wind display does not seem to work. i applied the code to the arrow but it remains static. the code:

    onClipEvent (load) {
    arrow._rotation = Math.atan2(wind.y, wind.x) / Math.PI * 180;
    }

    but it still doesnt seem to point in the right direction, no matter where i place it in the stage. help plz
    Last edited by darksauce; 04-24-2006 at 02:17 AM.

  16. #16
    Senior Member
    Join Date
    Apr 2006
    Posts
    1,059
    heh just use a
    if(cannon._rotation < targetrotation){
    cannon._rotation+=5 }

    (well youll prolly have to tweak that but you get the idea im sure)

    in where ever your update interval thing is

    (or you could use a tween ...tween is prolly easier but i dont know the code off the top of my head)

    [edit] Dmonkey thats some good stuff btw

  17. #17
    Junior Member
    Join Date
    Jul 2006
    Posts
    1
    if possible, do you think you could post the finished game as an .fla file so i could have a look at it? i'm new to flash and am curious as to how it all works and where you are pasting the code.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center