Draw random way in ActionScript - actionscript-3

I'd like to move an AS 3 movieclip randomly. This is what I currently have, bound to the ENTER_FRAME event. This obviously moves the movieclip from the left upper to the right lower edge, so I need some kind of switch to add/substract the target positions.
function movePsycho(e:Event):void {
e.target.y += Math.random()*2;
e.target.x += Math.random()*2;
if (e.target.y >= stage.height || e.target.x >= stage.width)
e.target.removeEventListener(Event.ENTER_FRAME, movePsycho);
}

You don't need add/substract thing. You just have to make sure not only you get positive values out of your random, but negatives too, so it runs to all sides.
Try changing your random generating lines to this:
e.target.y += Math.random()*10 - 5;
e.target.x += Math.random()*10 - 5;
This will work if you want to make it move in a 5px radius.
I just realized you may want to generate a new random point on the screen, then move to that point and when your object reaches the destination generate another random point to go to. So if that's the case, try this:
mc.addEventListener(Event.ENTER_FRAME, onFrame);
var dirX:int = mc.x;
var dirY:int = mc.y;
function generateRandomPoint():void
{
dirX = Math.random() * stage.stageWidth;
dirY = Math.random() * stage.stageHeight;
}
function onFrame(e:Event):void
{
mc.x += (dirX - mc.x) * 0.1;
mc.y += (dirY - mc.y) * 0.1;
if(Math.abs(dirX - mc.x) < 1 || Math.abs(dirY - mc.y) < 1)
generateRandomPoint();
}

i don't know actionscript but you may find help with this
http://www.actionscript.org/forums/showthread.php3?t=270725

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

How to have an object hover back and forth constrained within a specific radius?

I have a sprite in a movie symbol that I would like to hover back and forth within a 360 radius. I was hoping to make it smooth and random. Never really venturing from its original xy cordinates.
I've tried to create some stipulations with if statements and a starting momentum. Like this:
var num = 2;
stage.addEventListener(Event.ENTER_FRAME, hover);
function hover(evt:Event):void{
//start it moving
cloudWhite.y += num;
cloudWhite.x += num;
//declare these variables
var cX = cloudWhite.x;
var cY = cloudWhite.y;
// object travels 10 pixels
var cXP = cX + 10;
var cXN = cX - 10;
var cYP = cY + 10;
var cYN = cY - 10;
// if object goes 10 pixels reverse direction of momentum (maybe)
if (cX >= cXP) {
num = -2;
}
if (cX <= cXN){
num = 2;
}
if (cY >= cYP) {
num = 2;
}
if (cY <= cYN){
num = 2;
}
Clearly this is super wrong because when it runs the object just either goes to 0,0 or to some place that only the math gods know of.
I am clearly a noob at this kind of math so i apologize but I am very excited to learn the trig behind this.
Thank you for your help and thank you for reading.
You are setting all your variables inside the ENTER_FRAME loop, so none of your conditions ever evaluates to true. On every single frame you are doing this:
cloudWhite.x += 2;
cX = cloudWhite.x;
cXP = cX + 10; // Must == cloudWhite's previous x + 10 + 2;
cXN = cX - 10; // Must == cloudWite's previous x -10 + 2;
if(cX > cXP)... // Can never be true.
if(cX < cXN)... // Can never be true.
What you need to do is:
1) Store the original position of cloudWhite somewhere outside the loop, and store it before the loop begins.
2) Define your bounds relative to the original position of cloudWhite, again before your loop begins. Also define the amount you are going to change the position with each iteration.
3) Start your loop.
4) Increment the current position of cloudWhite on each iteration. Add a little random in here if you want the shape to move in a random manner.
5) Check if the new position of cW is outside your bounds and adjust the direction if it is.
The sample below is crude and jerky but I don't know exactly what effect you're looking for. If you want smoother, longer movements in each direction, consider using the Tween class or a Tween library such as the popular Greensock one, instead of incrementing / decrementing the position manually. There's a useful discussion of this here: http://www.actionscript.org/forums/archive/index.php3/t-163836.html
import flash.display.MovieClip;
import flash.events.Event;
// Set up your variables
var original_x:Number = 100; // Original x
var original_y:Number = 100; // Original y
var x_inc:Number = 5; // X Movement
var y_inc:Number = 5; // Y Movenent
var bounds:Number = 50; // Distance from origin allowed
// Doesn't take into account width of object so is distance to nearest point.
// Create an MC to show the bounds:
var display:MovieClip = addChild(new MovieClip()) as MovieClip;
display.graphics.lineStyle(1, 0x0000FF);
display.graphics.beginFill(0x0000FF, 0.5);
display.graphics.drawRect(0-bounds, 0-bounds, bounds * 2, bounds *2);
display.x = original_x;
display.y = original_y;
addChild(display);
// Create our moving mc:
var mc:MovieClip = addChild(new MovieClip()) as MovieClip;
mc.graphics.beginFill(0xFF0000, 1);
mc.graphics.drawCircle(-10, -10, 20);
// Position it:
mc.x = original_x;
mc.y = original_y;
addChild(mc);
// Loop:
function iterate($e:Event = null):void
{
// Move the mc by a random amount related to x/y inc
mc.x += (Math.random() * (2 * x_inc))/2;
mc.y += (Math.random() * (2 * y_inc))/2;
// If the distance from the origin is greater than bounds:
if((Math.abs(mc.x - original_x)) > bounds)
{
// Reverse the direction of travel:
x_inc == 5 ? x_inc = -5 : x_inc = 5;
}
// Ditto on the y axis:
if((Math.abs(mc.y - original_y)) > bounds)
{
y_inc == 5 ? y_inc = -5 : y_inc = 5;
}
}
// Start the loop:
addEventListener(Event.ENTER_FRAME, iterate);
This should get you started. I'm sure there are any number of other ways to do this with formal trig, but this has the benefit of being very simple, and just an extension of your existing method.

Enemy rotates very strangely

I have this problem: there is this enemy which rotates to my player. While "orbiting" the enemy with my player I can see that the enemy is rotating towards my player.
And then the enemy suddenly turns around 360 degrees and facing to my player again. I don't know why it does this strange 360 degree turn but it happens every time when I orbit the enemy for a few seconds. I don't know where the problem might be.
tempEnemy.dX = tempEnemy.x - player.x;
tempEnemy.dY = tempEnemy.y - player.y;
tempEnemy.rotateTo = toDegrees(getRadians(tempEnemy.dX, tempEnemy.dY));
if(tempEnemy.frame < 0) tempEnemy.frame += 360;
if(tempEnemy.frame > 359) tempEnemy.frame -= 360;
tempEnemy.trueRotation = int((tempEnemy.rotateTo - tempEnemy.frame) / tempEnemy.rotateSpeed);
tempEnemy.vX += (player.x - tempEnemy.x) / tempEnemy._speed;
tempEnemy.vY += (player.y - tempEnemy.y) / tempEnemy._speed;
tempEnemy.vX *= tempEnemy.decay;
tempEnemy.vY *= tempEnemy.decay;
Update:
private function toDegrees(radians:Number):Number
{
var degrees:Number = Math.floor(radians * 180 / Math.PI);
//trace (degrees);
return degrees;
}
private function getRadians(deltaX:Number, deltaY:Number):Number
{
var radian:Number = Math.atan2(deltaY, deltaX);
if (deltaY < 0)
{
radian += (2 * Math.PI);
}
return(radian);
}
Without seeing your getRadians function, perhaps you're passing 360° calculating a reflex angle?
Maybe something like:
var degrees:Number = Math.atan2(tempEnemy.y - player.y, tempEnemy.x - player.x) * 180 / Math.PI;
var delta:Number = degrees - tempEnemy.rotation;
while (delta <= -180)
delta += 360;
while (delta > 180)
delta -= 360;
Compensate degrees with the resting angle of your enemy display object design.
It sounds like you've used a timeline tween. Either use a code tween, or grab the tween I used here http://flexdiary.blogspot.com/2010/04/sample-code-for-oop-timeline-insideria.html. I don't remember what exactly I did to make the timeline tween go full circle, rather than twisting back before restarting, but you should be able to export and reuse the tween.
If you want to use a code tween, you can either use Flash's built in tween classes or use a library like Tweensy.

Movement in AS3

I am learning AS3. How can I move a symbol?
My Code
var counter:int = new int();
counter = 0;
var point:symbol1 = new symbol1();
addChild(point);
point.x = 25 + 50;
point.y = 25 + 50;
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
function move_handler(e) {
if (e.keyCode == Keyboard.SPACE) {
while (counter < 200)
{
trace(counter);
point.x += 1;
counter += 1;
}
}
}
But when I press space the symbol is to fast. How can edit the speed of the point?
You need to use an ENTER_FRAME event :
stage.addEventListener(Event.ENTER_FRAME,stageEnterFrame);
function stageEnterFrame(e:Event):void{
displayObject.x+=1
}
The displayList is updated only after code execution, that's why your object move so 'fast'.
This link may help you understand the process.
At the moment you are waiting for the user to press the space bar and then moving the symbol to the right by one pixel 200 times.
But as OXMO456 has said all 200 times that it moves to the right happen at the same time as if you had manually typed "point.x += 1;" 200 times.
if your intention is to only let it move to the right 200 times then you could replace the while statement with an if statement:
if(counter<200){
trace(counter);
point.x+=1;
counter+=1;
}
You could then change the speed it moves at by changing the number after "point.x+=".
An even better way of changing the speed would be by using a variable to make it clearer what the number does. This also makes it easier to use that number for other things, like moving in other directions at the same speed.
Here's what the finished code would look like with these changes and a bit of clean up:
var counter:int = 0; // setting this variable as you define it saves space
var speed:Number = 1; // here's the speed variable (declared as a number so you can have fractions)
var point:symbol1 = new symbol1();
addChild(point);
point.x = 75; // 25+50 is 75, one less thing for flash to work out
point.y = 75;
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
function move_handler(e) {
if (e.keyCode == Keyboard.SPACE) {
if (counter < 200)
{
trace(counter);
point.x += 1;
counter += 1;
}
}
}
Does that make sense?
Do it like this:
Point.x += 0.2; instead of point.x += 1;
this event type is what you want:
' stage.addEventListener(Event.ENTER_FRAME,enterFrameHandler)'
Use tween:
import libraries:
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
var myTween:Tween = new Tween(ball, "x", Strong.easeOut, ball.x, ball.x + 100, 5, true);
This code moving your object ("ball") to 100 on "x" axis in 5s.
Your while loop is making it fast, if you remove your while statement then it will work on SPACE DOWN
Welcome to the world of AS3.
Your description of your problem is a little vague, but i think i know what you what to do. You want to tween a display object (symbol1) 200 px right everytime you hit space? if so, here is how you do it:
import flash.events.KeyboardEvent;
import flash.events.Event;
var destinationX:int = 0; // this contains the point's destination x
var point:symbol1 = new symbol1(); // best practice is to name all your classes starting with upper case, like Symbol1, not symbol1
addChild(point);
point.x = 25 + 50;
point.y = 25 + 50;
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
stage.addEventListener(Event.ENTER_FRAME, render);// run render function every frame
function move_handler(e:KeyboardEvent):void{// another best practice, when injecting a variable into a function declare what type the variable is, in this case e is a KeyboardEvent. :void when not returning any values from the function, basically all functions you make in the beginning should look like this
if (e.keyCode == Keyboard.SPACE) {
destinationX += 200;// add 200 to destinationX
}
}
function render(e:Event):void{ // runs every frame, if you set your fps to 30, then this will run 30 times a second
if(destinationX > point.x){//Check if point's destination x is more than the points current x position
point.x += 1;// add 1 to points x. you can change this if you want it to go faster
}
}
Check out the Greensock library - it will take all the onEnterFrame complexity out for you and has some great features.
Full doc and examples at http://www.greensock.com/
You need this
var counter:int = new int();
var vel = 1; //<------- Move 1 pixel by frame
counter = 0;
var point:symbol1 = new symbol1();
addChild(point);
point.x = 25 + 50;
point.y = 25 + 50;
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
function move_handler(e) {
if (e.keyCode == Keyboard.SPACE) {
stage.addEventListener(Event.ENTER_FRAME,moveEnterFrame);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, move_handler);
}
}
function moveEnterFrame(e:Event):void{
point.x += vel;
counter ++;
if(counter >= 200){
stage.removeEventListener(Event.ENTER_FRAME,moveEnterFrame);
counter = 0;
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
}
}
ENTER_FRAME is the same of While.
stage.addEventListener(Event.ENTER_FRAME, nameFunction); //this event execute fps ones on default 24 frames for seconds
var speed:int = 5;
function nameFunction(ev:Event){
simbol.x += speed;
}
Draw anything and name it in the instance name box ..... so this well speed up and down by the space key ...... i use the frame rate
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
stage.addEventListener(Event.ENTER_FRAME,stageEnterFrame);
var fremCount:int;
var upDown:int;
function stageEnterFrame(e:Event):void{
if(fremCount<30 && upDown==0){
box.x+=1
fremCount++
}
if(fremCount==30){
upDown=1;
trace("For next : "+fremCount , upDown);
}
if(upDown==1){
box.x-=1
fremCount--;
}
if(upDown==1 && fremCount==0){
upDown=0;
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void{
if (e.keyCode == Keyboard.SPACE){
trace("Success!"+stage.frameRate);
stage.frameRate += 5;
if (stage.frameRate>150){stage.frameRate=0;}
}
}
import flash.events.Event;
var point:MovieClip = new Symbol1();
addChild(point);
point.x = 25 + 50;
point.y = 25 + 50;
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
function move_handler(e)
{
if (e.keyCode == Keyboard.SPACE)
{
stage.addEventListener(Event.ENTER_FRAME, moveRight);
}
}
function moveRight(evt:Event):void
{
point.x+=1;
}
I think this is exactly what you need. Firtly you create and call upon the key_down function. Inside this function you want to call for the move function itself. This is the function I created at the bottom. To make it stop at for example 200px I suggest to work with an if-statement and a removeEventlistener.
Please note that I changed some small codings eg "var point:MovieClip = new Symbol1(); " to make it appropriate for my symbol.
why not declare your counter variable as Number (not as int)
var counter:Number = new Number();
then change your statment as
point.x += 0.1;
counter += 0.1;
this will slow down your Point movieclip. you can change motion by changing 0.1 to any value you want.
The reason why your symbol is too fast is that your while loop iterates your point.x value 200 times in only one loop. To limit your symbol position, you must use an if statement instead of a while loop:
var point:symbol1 = new symbol1();
point.x = 75; // 25 + 50;
point.y = 75; // 25 + 50;
addChild(point);
const SPEED:Number = 0.7;
const DX:int = 200; // distance to cover
var counter:Number = 0; // counts the distance covered
stage.addEventListener(KeyboardEvent.KEY_DOWN, move_handler);
function move_handler(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE && counter < DX)
{
point.x += SPEED;
counter += SPEED;
trace(counter); // stops at 200
}
}
Use the Enter Frame method.
Please don't hardcode as well :P
If you are starting you may want to consider giving one of the many existing tween engines in order to get smooth results quickly.