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
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
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.
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:
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.
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
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.
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
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?
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
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 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
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?
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
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.
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:
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
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:
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.