AS3 - Catch the ball game - actionscript-3

I'm making a little app where you can drag and drop a ball. When you hit a sphere with this ball, you get a point and the ball moves to a random cordinate. My problem is that, after you have hitted the sphere the first time, it changes position, but you can hit it again. Here is the code (without the drag and drop)
ball.addEventListener(Event.ENTER_FRAME, hit);
var randX:Number = Math.floor(Math.random() * 540);
var randY:Number = Math.floor(Math.random() * 390);
function hit(event:Event):void
{
if (ball.hitTestObject(s)){ //s is the sphere
s.x = randX + s.width;
s.y = randY + s.width;
}
}

It seems that your randX and randY variables will only get evaluated once.
Therefore, if the hit test for the ball returns true, the x/y coordinates of the sphere will change the first time, but never again. How about trying this:
function hit(event:Event):void
{
if (ball.hitTestObject(s))
{
//s is the sphere
s.x = Math.floor(Math.random() * 540) + s.width;
s.y = Math.floor(Math.random() * 390) + s.height; // note I changed width to height
}
}

Related

Actionscript: Very slow movieclip

I am drawing a circular line to varying degrees. I wish the animation to last about 0.5 seconds. For reasons I can not work out its running very slowly.
What is weird is that if I skip the tween and call the function tweenToNext it renders instantly.
var degrees:int;
var posX:int = 102;
var posY:int = 102;
var rad:int = 100;
var mc:MovieClip = new MovieClip();
addChild(mc);
mc.graphics.lineStyle(5, 0xFF0000, 1);
mc.graphics.moveTo(posX, posY - rad)
mc.i = -Math.PI / 2;
tweenToNext();
function tweenToNext(per:Number = 360):void {
degrees += 1;
if (mc.i <= (3 * Math.PI / 2) && degrees < per) {
var x:Number = posX + Math.cos(mc.i) * rad;
var y:Number = posY + Math.sin(mc.i) * rad;
mc.graphics.lineTo(x, y);
mc.i += Math.PI / 180;
TweenLite.to(mc, 0.001, {onComplete:tweenToNext});
}
}
I have tried Timer and setTimeout but these produce the same slow speed.
Flash application runs on frame-to-frame basis: frame render - script execution - frame render - script execution - frame render - script execution - and so on. That also means that whatever smallest delay you're putting there, the next call will not happen before next script execution phase, basically, next frame. Thus - guess what - your circle drawing takes 360 frames. 12 seconds if you have 30 FPS, for example.
If you want to make something synchronize with the real time, you need a different approach. I didn't check if this works, but I hope you'll get the idea and fix the mistakes if any.
var degrees:int;
var posX:int = 102;
var posY:int = 102;
var rad:int = 100;
var mc:MovieClip = new MovieClip;
addChild(mc);
mc.graphics.lineStyle(5, 0xFF0000, 1);
mc.graphics.moveTo(posX, posY + rad);
// Now, magic time.
// Save time since app start (in milliseconds).
var startTime:int = getTimer();
// 1000 milliseconds = 1 second.
var drawingTime:int = 1000;
// Store the maximum degree to draw.
var degreeLimit:int = 360;
// Call it every frame.
mc.addEventListener(Event.ENTER_FRAME, onDraw);
function onDraw(e:Event):void
{
// Now we need to check how much time passes since last frame
// and update the drawing accordingly.
var timeProgress:Number = (getTimer() - startTime) / drawingTime;
var drawingProgress:Number = degrees / degreeLimit;
// When the drawing progress catches the time progress
// the loop will end. It will resume on the next frame.
while (drawingProgress < timeProgress)
{
degrees += 1;
// It's better than a property on target canvas,
// which could be Sprite or Shape, they wouldn't take random fields.
var anAngle:Number = degrees * Math.PI / 180;
var tox:Number = posX + Math.cos(anAngle) * rad;
var toy:Number = posY + Math.sin(anAngle) * rad;
mc.graphics.lineTo(tox, toy);
// We should know when to stop it.
if (dergees >= degreeLimit)
{
mc.removeEventListener(Event.ENTER_FRAME);
return;
}
// Update the drawing progress.
drawingProgress:Number = degrees / degreeLimit;
}
}

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 Missile Logic

I want to create a simple missile object, which moves at a set speed and rotates towards a specific target at a given rotation speed. However, I'm having trouble figuring out the math of it. This is my code so far:
private function enterFrame(e:Event):void {
// Rotate the missile towards the target.
var targetAngle:Number = getAngle(target.x, target.y, x, y);
if (targetAngle < 0) {
targetAngle += 360;
}
if (targetAngle - turnSpeed > rotation) {
rotation += turnSpeed;
} else if (targetAngle + turnSpeed < rotation) {
rotation -= turnSpeed;
} else {
rotation = targetAngle;
}
// Set the target point to move to based on angle and speed.
var newX:Number = x + Math.sin(degreesToRadians(rotation)) * speed;
var newY:Number = y + Math.cos(degreesToRadians(rotation)) * speed;
// Move to new location
x = newX;
y = newY;
}
private function getAngle (x1:Number, y1:Number, x2:Number, y2:Number):Number {
var dx:Number = x2 - x1;
var dy:Number = y2 - y1;
return (Math.atan2(dy,dx) * 180) / Math.PI;
}
private function degreesToRadians(degrees:Number):Number {
return degrees * Math.PI / 180;
}
I've been trying to debug it using trace and such, but I can't seem to figure out where the problem is, most likely because there are many problems and I can't tell if I've fixed one because the others are masking it. I suspect that the issue(s) lie somewhere in the rotation calculations, since I'm pretty sure that the movement part is working as it should, but I can't say for sure.
At any rate, whatever I do, the missiles always seem to fly off in random directions, sometimes tracking towards straight up, or straight down, or just looping around after nothing in particular.

Playing a random frame inside MovieClip with AS3

I have a movie clip (goalkeeper) with different positions in different frames (inside), I would like to play a random frame after executing a function to make the goalkeeper move to a determinate position, there are 6 frames with 6 different positions so I need to play 1 position randomly, this is the code that should go to the random number after ball is kicked:
function moveBall()
{
var targetX:Number = mouseX;
var targetY:Number = mouseY;
var angle = Math.atan2(targetY,targetX);
ball.x = mouseX + Math.cos(angle);
ball.y = mouseY + Math.sin(angle) ;
ballRotation = true;
if (ballRotation==true)
{
goalkeeper_mc.gotoAndStop( Random Frame);//Here is when I need to go and play the random frame everytime function is executed
}
Thanks a lot for your help guys, sorry for bothering again, I searched the web for some examples but I found many of them really complicated for a newbie like me.
refer a following code.
you must randomize from 1 frame to last Frame.
Math.random () of the range is greater than 0 and less than 1(floating-value). by use it implements available.
function moveBall()
{
var targetX:Number = mouseX;
var targetY:Number = mouseY;
var angle = Math.atan2(targetY,targetX);
ball.x = mouseX + Math.cos(angle);
ball.y = mouseY + Math.sin(angle) ;
ballRotation = true;
if (ballRotation==true)
{
goalkeeper_mc.gotoAndStop(int(Math.random * (goalkeeper_mc.totalFrames)+1));
}
}
goalkeeper_mc.gotoAndStop(1 + Math.floor(Math.random() * goalkeeper_mc.totalFrames));

as3 rotational drag / acceleration

Sprite.rotation+=10;
Sprite.rotation*=0.97;
because in as3 the system goes from 180 to -180 I don't know how to apply a drag to a constantly rotating object if it moves either direction. Do I have to convert to radians somehow and then do something? I am pretty bad with math.
I'm not sure "drag" makes sense with the code you've posted. What you've shown would slowly wind the object back to 0 rotation.
If you want a drag/acceleration effect, create a separate variable with your acceleration factor, which you apply every frame. Then, you can apply a factor to that variable to slow rotation down/speed it up.
Something like:
private var _rotationAcceleration:Number = 0;
private var _dragFactor:Number = 0.97;
private var _clip:Sprite;
private function startSpin():void {
_rotationAcceleration = 10.0;
}
private function enterFrameListener(event:Event):void {
_clip.rotation += _rotationAcceleration;
_rotationAcceleration *= _dragFactor;
}
I think you're looking for this:
private function updateRotation():void
{
var _dx:Number = _player.x - stage.mouseX; // rotate _player mc to mouse
var _dx:Number = _player.y - stage.mouseY; // rotate _player mc to mouse
// which way to rotate
var rotateTo:Number = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (rotateTo > _player.rotation + 180) rotateTo -= 360;
if (rotateTo < _player.rotation - 180) rotateTo += 360;
// ease rotation
var _trueRotation:Number = (rotateTo - _player.rotation) / 5; // rotation speed 5
// update rotation
_player.rotation += _trueRotation;
}
public 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);
}
return r;
}
public function getDegrees(radians:Number):Number
{
return Math.floor(radians/(Math.PI/180));
}
It actually does goes from 180 to -180 (contrary to what Reuben says), but higher/lower values get automatically corrected to that range (i.e. 181 is converted to -179)... one way to work with this is to use an auxiliary variable for your math (animation or whatever) and then assign it to the rotation, say:
myVar+=10;
myVar*=.97;
clip.rotation=myVar;