Rotating Angle Calculation AS3 - actionscript-3

I am writing a code where there are different rings on the stage, and a ball is rotating in one of these orbits. On click, the ball leaves its ring and travels normal to the ring. On its way if it hits another ring, it starts rotating in that ring from the point it hits the ring. I could successfully code the initial part of the code. but I am getting a problem when the ball hits another ring, it does not start from the location it hit. Instead it starts rotating in the ring from a different position. I hope I am clear with my doubt. It is somewhat similar to this game https://play.google.com/store/apps/details?id=com.drgames.orbit.jumper
here is my code in enter frame :
if(!isTravelling){
rad = Math.abs(angle * (Math.PI / 180)); // Converting Degrees To Radians
_ball.x = currOrbit.x + (currOrbit.width / 2) * Math.cos(rad); // Position The Orbiter Along x-axis
_ball.y = currOrbit.y + (currOrbit.width / 2) * Math.sin(rad); // Position The Orbiter Along y-axis
trace(_ball.x+" , "+_ball.y);
angle -= speed; // Object will orbit clockwise
_ball.rotation = (Math.atan2(_ball.y - currOrbit.y, _ball.x - currOrbit.x) * 180 / Math.PI) + 90;
}
for(var i = 0; i < orbits.length; i++){
if(orbits[i] != currOrbit){
if(ObjectsHit(orbits[i], _ball)){
currOrbit = orbits[i];
_ball.rotation = (Math.atan2(_ball.y - currOrbit.y, _ball.x - currOrbit.x) * 180 / Math.PI) + 90;
isTravelling = false;
stage.addEventListener(MouseEvent.CLICK, onClick);
}
}
}
if(isTravelling){
_ball.x += Math.cos(rad) * speed * 2;
_ball.y += Math.sin(rad) * speed * 2;
}

You seem to have forgotten to calculate the starting angle for the new orbit:
if(!isTravelling){
rad = Math.abs(angle * (Math.PI / 180)); // Converting Degrees To Radians
_ball.x = currOrbit.x + (currOrbit.width / 2) * Math.cos(rad); // Position The Orbiter Along x-axis
_ball.y = currOrbit.y + (currOrbit.width / 2) * Math.sin(rad); // Position The Orbiter Along y-axis
trace(_ball.x+" , "+_ball.y);
_ball.rotation = angle // no need for calculating the angle again
angle -= speed; // Object will orbit clockwise
}
for(var i = 0; i < orbits.length; i++){
if(orbits[i] != currOrbit){
if(ObjectsHit(orbits[i], _ball)){
currOrbit = orbits[i];
angle = (Math.atan2(_ball.y - currOrbit.y, _ball.x - currOrbit.x) * 180 / Math.PI) + 90; // Calculate the starting angle on the new orbit
_ball.rotation = angle // Set the balls rotation to the angle
isTravelling = false;
stage.addEventListener(MouseEvent.CLICK, onClick);
}
}
}
if(isTravelling){
_ball.x += Math.cos(rad) * speed * 2;
_ball.y += Math.sin(rad) * speed * 2;
}
This should fix it. Please note that you might have to add or subtract 90 degrees to your balls rotation (_ball.rotation = angle + 90) because im not 100% sure about that.

Related

As3 Trigonometry and math

i'm trying to create a minigame with circles rotating around circles
however, i have a problem when i shoot the circle and it hits the second circle it doesnt continue the angle but "jumping" to the other side i'm sure it something with the angle var that should reset or something. can you help me im getting nervous around here... :(
check the example
This is my code for the enter frame function that deals with the circles
public function UpdateCircles(e:Event):void
{
for (var i:int = 0; i < EnemySpriteVector.length; i++)
{
EnemySpriteVector[i].rotation += EnemySpriteVector[i].enemyspeed;
}
var rad:Number = angle * (Math.PI / 180); // Converting Degrees To Radians
if (IsplayerShoot)
{
playerSprite.x += Math.cos(rad) * PlayerCircleShootSpeed;
playerSprite.y += Math.sin(rad) * PlayerCircleShootSpeed;
for (var j:int = 0; j < EnemySpriteVector.length; j++)
{
if (EnemySpriteVector[j].hitTestPoint(playerSprite.x,playerSprite.y) && (EnemySpriteVector[j].IsCircleHit == false))
{
trace("hit");
EnemySpriteVector[j].IsCircleHit = true;
removeChild(EnemySpriteVector[0]);
EnemySpriteVector.splice(0, 1);
var EnemySprite:Sprite = new EnemySpriteClass();
EnemySpriteVector.push(EnemySprite);
addChild(EnemySprite);
EnemySprite.x = Math.random() * stage.stageWidth;
EnemySprite.y = Math.random() * stage.stageHeight;
IsplayerShoot = false;
}
}
}
else
{
playerSprite.x = EnemySpriteVector[0].x + EnemySpriteVector[0].radius * Math.cos(rad); // Position The Orbiter Along x-axis
playerSprite.y = EnemySpriteVector[0].y + EnemySpriteVector[0].radius * Math.sin(rad); // Position The Orbiter Along y-axis
angle += EnemySpriteVector[0].enemyspeed; // Object will orbit clockwise
playerSprite.rotation = (Math.atan2(playerSprite.y - EnemySpriteVector[0].y, playerSprite.x - EnemySpriteVector[0].x) * 180 / Math.PI); //only rotates the player circle itself
}
}
Looks like when the pink circle hits the green one it simply continues its rotation from where it left of. A quick solution would be to add 180 degrees to the angle. Keep in mind this will only work for static objects. If you want a more dynamic environment I would recommend using vectors (linear algebra). Vector math is really easy to understand and it hides a lot of complex trigonometry. You can start here :)

As3: Math, I'm too stupid for this. (trigonometry)

Okay, so I made some ai where a guard is following my character.
I am using this code:
private function getDegrees(radians:Number):Number
{
//return Math.floor(radians/(Math.PI/180));
return radians / 0.01745 | 0;
}
private function getRadians(delta_x:Number, delta_y:Number):Number
{
var r:Number = Math.atan2(delta_y, delta_x);
if (delta_y < 0)
{
//r += (2 * Math.PI);
r += 6.283;
}
return r;
}
And then in the loop
if(isShooting)
{
// calculate rotation based on mouse X & Y
_dx = this.x - _root.assassin.x;
_dy = this.y - _root.assassin.y;
// which way to rotate
_rotateTo = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (_rotateTo > this.rotation + 180) _rotateTo -= 360;
if (_rotateTo < this.rotation - 180) _rotateTo += 360;
// ease rotation
_trueRotation = (_rotateTo - this.rotation) / _rotateSpeedMax;
// update rotation
this.rotation += _trueRotation;
gotoAndStop(5);
isWalking = false;
isStanding = false;
}
The thing is, the guard rotates weirdly, it's as if he isn't looking at the player. It's as if the player is somewhere else. Dunno, it just doesn't work.. I have no idea what is wrong with the code!
You should just compute the relative angle
_rotateTo = getDegrees(getRadians(_dx, _dy));
_trueRotation = (_rotateTo - this.rotation) / _rotateSpeedMax;
then normalize this to be as close to zero as possible
_trueRotation = (_trueRotation+900) %360 - 180;
and then cut this to the maximal rotation per step
_trueRotation = max(_trueRotation,_rotateSpeedMax* _timestep);
_trueRotation = min(_trueRotation,-_rotateSpeedMax*_timestep);
and use this then to update the forward direction
this.rotation += _trueRotation;
Speed usually is change per time, so there should be a multiplication with some time step for semantic consistency. Of course, you may have the time step equal to 1, or rotateSpeedMax is really a rotateMaxAngle (per step), then the multiplication with timestep can be removed.
To keep the rotation positive you should use modulus 360 like below for readability and (code) simplicity until and unless it's a clear performance issue: (I think this is right for AC3, just looked it up online quick)
_rotateTo = _rotateTo % 360;
The other possible issue is with how you define _dx and _dy. I'm guessing that the assassin is facing in the opposite direction as intended. The fix is to useI'm thinking it should either be:
_dx = _root.assassin.x - this.x;
_dy = _root.assassin.y - this.y;

Movieclip to spawn in a set parameter

I like to make a movieclip randomly spawn in a set area. But theres a little more to it, usually you'd have something like the X pos set to something like 250 (say the centre) and the Y pos set to be math.random but it won't work for how I'd like it.
I'm making a First Person Shooter and want the Enemy movieclip to spawn off stage but from the Top, Bottom, Left and Right of the stage as shown in the quick annotated image here.
Is this possible to be done? If so how could I achive this?
Thanks for your help.
Something dirty like this would work
_enemy.x = _enemy.y = 0;
while(_enemy.x >= 0 && _enemy.x <= stage.stageWidth)
{
_enemy.x = Math.random() * (stage.stageWidth * 3) - stage.stageWidth;
}
while(_enemy.y >= 0 && _enemy.y <= stage.stageHeight)
{
_enemy.y = Math.random() * (stage.stageHeight * 3) - stage.stageHeight;
}
Or you could go for a more fancy approach, where enemies would spawn with a random angle on a circles edge. The enemies will always be spawned at a fixed distance from the stage's center, but this can easily be modified
var radius:Number = 800: // Set this to be greater than stage dimensions
var angle:Number = Math.random() * Math.PI * 2;
_enemy.x = (stage.stageWidth / 2) + ( Math.cos( angle ) * radius );
_enemy.y = (stage.stageHeight / 2) + ( Math.sin( angle ) * radius );

AS3 shooting in multiple directions

i am try trying to make space shooter game in which ship is able to rotate and shoot in all directions, now, i do know basics of trigonometry, but i stuck at this point and my brain seems to be frozen so i seek your help.
I have Ship.as and Turret.as , every ship contains some number of turrets, and this is loop that is responsible to create bullet for each turret on players input and its located in Ship.as.
for (var i:int = 0; i < turrets.length; i++)
{
var _pcos:Number = Math.cos(angle / 180 * Math.PI);
var _psin:Number = Math.sin(angle / 180 * Math.PI);
var bulletX:Number = center.x + turrets[i].distance * _pcos;
var bulletY:Number = center.y + turrets[i].distance * _psin;
var bullet:BulletBase = new bulletClass(bulletX, bulletY, angle);
layerBullets.add(bullet);
bullets.push(bullet);
}
variable center is point positioned in exact center of ships sprite, angle is ships rotation towards mouse, turret.distance is distance from center to turret
This is whats happening in Turret.as
public class Turret extends Point
{
private var ship:Ship;
public var distance:Number;
public var angle:Number;
/**
*
* #param x position with angle 0
* #param y position with angle 0
* #param distance distance from center of ship to turret
*/
public function Turret(x:Number = 0, y:Number = 0, ship:Ship = null)
{
super(x, y);
this.ship = ship;
this.x = x;
this.y = y;
var dx:Number = ship.center.x - x;
var dy:Number = ship.center.y - y;
angle = Math.atan2(dy, dx);
distance = Math.sqrt(dx * dx + dy * dy);
}
Now, what is happening with this code is that bullets seems like they are fired from same direction, only one bullet is behind.
I am not math expert and if anyone knows the answer i would really appreciate it.
var _pcos:Number = Math.cos((turret.angle + angle) / 180 * Math.PI);
var _psin:Number = Math.sin((turret.angle + angle) / 180 * Math.PI);
angle is angle of ship

find angle and velocity for a parabola that meet specific range

i'm a little ashamed to ask this, but i have tried a lot of different things and can't make it work.
i have a game that shots a bullet, i have made the code that calculates the parabola trajectory given a an angle and a velocity, but i'm trying to make the calculus needed to get the angle and velocity needed to reach X point (the user enemy tank) and i'm unable to make it work as i need.
my current code is:
var startingPointX:Number = globalCoord.x;
var startingPointY:Number = globalCoord.y;
var targetX:Number = tankPlayer.x;
var targetY:Number = tankPlayer.y;
//distance between user and enemy tank
var distanceTarget = Math.sqrt(( startingPointX - targetX ) * ( startingPointX - targetX ) + ( startingPointY - targetY ) * ( startingPointY - targetY ));
var fixedVel = (distanceTarget/10)*2;
var fixedG = bullet.g;
// launch angle
var o:Number = -(Math.asin((0.5 * Math.atan(fixedG * distanceTarget / fixedVel * fixedVel))) * 180 / Math.PI);
bullet.init(startingPointX, startingPointY, o, fixedVel);
and the functions in the bullet object that actually position the bullet in the parabola trajectory is:
public function init(x, y:Number, rot:Number, speed:Number) {
// set the start position
var initialMove:Number = 35.0;
this.x = x + initialMove * Math.cos(2 * Math.PI * rot / 360);
this.y = y + initialMove * Math.sin(2 * Math.PI * rot / 360);
this.rotation = rot;
//get speed
dx = speed * Math.cos(2 * Math.PI * rot / 360);
dy = speed * Math.sin(2 * Math.PI * rot / 360);
//animation
lastTime = getTimer();
addEventListener(Event.ENTER_FRAME,moveBullet);
}
public function moveBullet(event:Event)
{
//get the time passed
var timePassed:int = getTimer() - lastTime;
lastTime += timePassed;
//move bullet
dy += g * timePassed / 1000;
this.x += dx * timePassed / 1000;
this.y += dy * timePassed / 1000;
//bullet past the top of the screen
if (this.y < 0)
{
deleteBullet();
}
}
any help would be really useful, thanks ! :D
Regards,
Shadow.
If this is a ballistics problem in the sense that you project a particle from point A with velocity v at an angle theta and you want it to hit a point T where the y coordinates of A and T match (ie they lie on a plane perpendicular to the vector of gravitational force vector) then you can calculate the required angle and velocity from this equation (See your wiki link where this is defined):
R = (v * v * sin(2 * theta))/g
Here R is the distance travelled in the x direction from your start point A . The problem you are facing is you are trying to interpolate a parabola through just 2 points. There are an infinite amount of parabolas that will interpolate 2 points while the parabola through 3 points is unique. Essentially there are an infinite amount of choices for velocity and angle such that you can hit your target.
You will either need to fix the angle, or the velocity of the bullet in order to use the above equation to find the value you require. If not, you have an infinite number of parabolas that can hit your target.
The above assumes that air resistance is ignored.
EDIT : Thus if you know velocity v already you can get theta from simple rearrangement of the above :
( asin(g * R / (v * v)) ) / 2 = theta
Based on the suggestion from #mathematician1975 i resolved the code to this and works perfectly :D
var distanceTarget = startingPointX - targetX ;
var fixedVel = 100;
var fixedG = tmpB.g;
var o:Number = (0.5 * Math.atan((fixedG * distanceTarget / (fixedVel * fixedVel)))) * 180 / Math.PI;
//this is only necessary why the enemy tank is facing left
o -= 180;
what i made is:
set a fixed velocity as #mathematician1975 said, a lot bigger than before
the distance between starting and ending point is lineal and not using Pythagoras.
the -180 is just why the enemy tanks is facing left.
i hope someone would find it useful in the future :D
Regards,
Shadow.