• Global community
• Language:
• Deutsch
• English
• EspaÃ±ol
• FranÃ§ais
• PortuguÃªs
• æ—¥æœ¬èªžã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£
Dedicated community for Japanese speakers
• í•œêµ­ ì»¤ë®¤ë‹ˆí‹°
Dedicated community for Korean speakers
Exit
• Re: Randomly change movement direction

Randomly change movement direction

Community Beginner ,
Jan 12, 2018 Jan 12, 2018

Copied

Hello

I am working on a program that has several objects moving over the screen.

Every object is supossed to move differently from the other objects.

What i canÂ´t figure out is how to make an object randomly turn and move the other direction.

Every object on stage now moves towards + X.

Here is my code

`import flash.display.Sprite;import flash.events.Event;var circArray :Array = new Array()var j = 0function drawCircs() {    for (var i = 0; i < 25; i ++) {        var circ :Sprite = new Sprite();        var fill :int = 0xffffff * Math.random();        var alfa :Number = 0.99 * Math.random();        var x0 :int = stage.stageWidth * Math.random();        var y0 :int = 400;        var radius :int = 20;        circArray.push(circ = new Sprite())                //puts the circle sprite in an Array        addChild(circArray);        circArray.graphics.lineStyle(1);        circArray.graphics.beginFill(fill, alfa);        circArray.graphics.drawCircle(x0, y0, radius);        circArray.graphics.endFill();        circArray.addEventListener(Event.ENTER_FRAME, move)        j += 1    }}function move (evt:Event) {                                //moves every circle sprite individually    var thisCirc = evt.currentTarget    thisCirc.x += Math.random() * 5    thisCirc.y -= Math.random() * 5}drawCircs()`
TOPICS
ActionScript

Views

2.1K

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Community Expert , Jan 12, 2018 Jan 12, 2018

Hi again.

I tried your approach but all the circles just kept moving in the same direction while shaking a bit.

Also, for better performance:

- Use vectors instead of arrays;

- Randomize the position of the object itself not the drawing parameters because it will be much harder for you to check for collisions, position the objects precisely, and so on;

- Try to always use only one enterFrame event for the sake of maintenance and performance;

- You used the new keyword when creating the circ object so

...

16 Replies 16
Community Expert ,
Jan 12, 2018 Jan 12, 2018

Copied

Hi.

It's because you are setting random x and y values at every tick for the movement. You have to predefine this values before you start moving your shapes.

I have a suggestion for you where I made some tweaks that I think that will greatly improve performance and achieve the result you want.

You only need to create an extra ActionScript class outside of your FLA. I did this because I wanted every circle to be a Shape, which is lighter than a Sprite. But Shapes are static classes, so we can't add properties to it dynamically. That's why I created a class called Circ to extend Shape but being able to receive dynamic properties.

Main code:

`import flash.display.Shape;import flash.display.DisplayObjectContainer;var circles:Vector.<Circ> = new Vector.<Circ>();function generateCircles(total:uint, container:DisplayObjectContainer):void{       for (var i:uint = 0; i < total; i++)    {        var circ:Circ = new Circ();               circ.graphics.lineStyle(1);        circ.graphics.beginFill(0xffffff * Math.random(), 0xffffff * Math.random());        circ.graphics.drawCircle(0, 0, 20);        circ.graphics.endFill();        circ.x = stage.stageWidth * Math.random();        circ.y = stage.stageHeight;        circ.moveX = -5 + Math.random() * 10;        circ.moveY = -5 + Math.random() * 10;        container.addChild(circ);        circles.push(circ);    }}function enterFrameHandler(event:Event):void{       for (var i:uint = 0, total:uint = circles.length; i < total; i++)    {        var circ:Circ = circles;               if (circ.x < -circ.width * 0.5)            circ.x = stage.stageWidth + circ.width * 0.5;                   else if (circ.x > stage.stageWidth + circ.width * 0.5)            circ.x = -circ.width * 0.5;               if (circ.y < -circ.height * 0.5)            circ.y = stage.stageHeight + circ.height * 0.5;                   else if (circ.y > stage.stageHeight + circ.height * 0.5)            circ.y = -circ.height * 0.5;               circ.x += circ.moveX;        circ.y += circ.moveY;    }}generateCircles(25, this);stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);`

Circle.as:

`package{    import flash.display.Shape;    public dynamic class Circ extends Shape    {        public function Circ()        {        }    }}`

Preview:

I hope it helps.

Regards,

JC

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Jan 12, 2018 Jan 12, 2018

Copied

Hello

Yes this is almost what i want to do.

To explain my problem better:

Im working on a bigger program or game rather where this code is supossed to be characters moving around on the screen so this is just a test to see how that is done before i put it into my bigger program.

I want the circles to start at y400 and move upwards (At this state they only move towards + X).

Correct me if im wrong but it seems like the program you made they do go both ways but ONLY that way (Either + X or - X) until theyre off screen.

What im looking for is how to make the circles randomly switch what way they are going and continue that way until the direction is changed again.

Im not very good at explaining my problem but I hope you understand

and again Thank you for the help

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Jan 12, 2018 Jan 12, 2018

Copied

Got it.

But what rule should we apply to make the char change direction? Time, distance travelled, collision?

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Jan 12, 2018 Jan 12, 2018

Copied

Ive got a rough version of it working but im sure theres a better way to do it. Idealy id like it to happen randomly (say if a variable that changed everytime the circles moved was greater than a certain number).

Heres the way i got it working:

`import flash.display.Sprite;import flash.events.Event;var circArray :Array = new Array()var circXArray :Array = new Array()var circX :int = 5var circY :int = 5var circCount :int = 300var difFlip :int = 500var div :int = 3var j = 0var k = 0function drawCircs() {    for (var i = 0; i < circCount; i ++) {        var circ :Sprite = new Sprite();        var fill :int = 0xffffff * Math.random();        var alfa :Number = 0.99 * Math.random();        var x0 :int = 400;        var y0 :int = 600;        var radius :int = 20;        circArray.push(circ = new Sprite());            //puts the circle sprite in an Array        addChild(circArray);        circArray.graphics.lineStyle(1);        circArray.graphics.beginFill(fill, alfa);        circArray.graphics.drawCircle(x0, y0, radius);        circArray.graphics.endFill();        circArray.addEventListener(Event.ENTER_FRAME, move)        circXArray.push(circX)        j += 1    }}function move (evt:Event) {                                //moves every circle sprite individually    var thisCirc = evt.currentTarget    var flip = Math.random() * difFlip    if (flip < difFlip / div) {        circXArray = -circXArray    }    thisCirc.x += circXArray    thisCirc.y -= circY    k += 1    if (k == circCount) {        k = 0    }}`

I dont know how to add a preview of the program like you did either

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Jan 12, 2018 Jan 12, 2018

Copied

Hi again.

I tried your approach but all the circles just kept moving in the same direction while shaking a bit.

Also, for better performance:

- Use vectors instead of arrays;

- Randomize the position of the object itself not the drawing parameters because it will be much harder for you to check for collisions, position the objects precisely, and so on;

- Try to always use only one enterFrame event for the sake of maintenance and performance;

- You used the new keyword when creating the circ object so there's no need to use it again when pushing this object to the array.

Here is an updated code.

The shapes now move based on their rotation values. At every 2 seconds each shape change its direction. Notice that you can uncomment three lines and change the object to the arrow I used below.

Main code:

`import flash.display.DisplayObjectContainer;import flash.utils.setInterval;//var objs:Vector.<Arrow> = new Vector.<Arrow>();var objs:Vector.<Circ> = new Vector.<Circ>();var interval:uint;const DEGREES:Number = Math.PI / 180;function generateObjects(total:uint, container:DisplayObjectContainer):void{        for (var i:uint = 0; i < total; i++)    {        //var obj:Arrow = new Arrow();        var obj:Circ = new Circ();                        obj.x = stage.stageWidth * Math.random();        obj.y = stage.stageHeight;        obj.rotation = -180 + Math.random() * 180;        obj.direction = obj.rotation;        obj.speedX = 2 + Math.random() * 3;        obj.speedY = 2 + Math.random() * 3;        obj.friction = 0.85;        container.addChild(obj);        objs.push(obj);    }}function enterFrameHandler(event:Event):void{        for (var i:uint = 0, total:uint = objs.length; i < total; i++)    {                //var obj:Arrow = objs;        var obj:Circ = objs;                if (obj.x < -obj.width * 0.5)            obj.x = stage.stageWidth + obj.width * 0.5;                    else if (obj.x > stage.stageWidth + obj.width * 0.5)            obj.x = -obj.width * 0.5;                if (obj.y < -obj.height * 0.5)            obj.y = stage.stageHeight + obj.height * 0.5;                    else if (obj.y > stage.stageHeight + obj.height * 0.5)            obj.y = -obj.height * 0.5;                            obj.rotation = lerp(obj.rotation, obj.direction, obj.friction);                obj.x = obj.x + obj.speedX * Math.cos(obj.rotation * DEGREES);            obj.y = obj.y + obj.speedY * Math.sin(obj.rotation * DEGREES);            }}function changeDirection():void{    for (var i:uint = 0, total:uint = objs.length; i < total; i++)        objs.direction = -180 + Math.random() * 180;        }function lerp(v1:Number, v2:Number, f:Number):Number{    return f * v1 + (1 - f) * v2;}generateObjects(25, this);stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);interval = setInterval(changeDirection, 2000);`

Circ.as code:

`package{    import flash.display.Sprite;    public dynamic class Circ extends Sprite    {        public function Circ()        {            graphics.lineStyle(1);            graphics.beginFill(0xffffff * Math.random(), 0xffffff * Math.random());            graphics.drawCircle(0, 0, 20);            graphics.endFill();        }    }}`

Preview:

(The preview is just a GIF. Please ignore the framerate.)

Regards,

JC

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Oct 29, 2020 Oct 29, 2020

Copied

Hi JoÃ£o,

I know this is an old thread but I was just wondering if there is any way to bounce the object when it hits the edge of the screen so that it keeps moving around the screen?

Something like this gif.

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Oct 30, 2020 Oct 30, 2020

Copied

Hi.

Sure. Here is a suggestion:

Timeline code:

``````import flash.display.DisplayObjectContainer;

const TOTAL:uint = 1000;
var objs:Vector.<Circ> = new Vector.<Circ>();

function generateObject(container:DisplayObjectContainer):void
{
var obj:Circ = new Circ();

obj.x = obj.width * 0.5 + Math.random() * (stage.stageWidth - obj.width);
obj.y = obj.height * 0.5 + Math.random() * (stage.stageHeight - obj.height);
obj.speedX = -5 + Math.random() * 5;
obj.speedY = -5 + Math.random() * 5;
objs.push(obj);
}

function enterFrameHandler(event:Event):void
{
if (objs.length < TOTAL)
generateObject(this);

for (var i:int = objs.length -1; i >= 0; i--)
{
var obj:Circ = objs[i];
var left:Number = obj.width * 0.5;
var right:Number = stage.stageWidth - obj.width * 0.5;
var top:Number = obj.height * 0.5;
var bottom:Number = stage.stageHeight - obj.height * 0.5;

if (obj.x < left)
{
obj.speedX = -obj.speedX;
obj.x = left;
}
else if (obj.x > right)
{
obj.speedX = -obj.speedX;
obj.x = right;
}
else if (obj.y < top)
{
obj.speedY = -obj.speedY;
obj.y = top;
}
else if (obj.y > bottom)
{
obj.speedY = -obj.speedY;
obj.y = bottom;
}

obj.x += obj.speedX;
obj.y += obj.speedY;
}
}

Circ.as code:

``````package
{
import flash.display.Sprite;
public dynamic class Circ extends Sprite
{
public function Circ()
{
graphics.beginFill(0xffffff * Math.random(), 0xffffff * Math.random());
graphics.drawCircle(0, 0, uint(2 + Math.random() * 4));
graphics.endFill();
}
}
}``````

I've applied some tweaks just for fun.

I hope this helps.

Regards,

JC

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Oct 30, 2020 Oct 30, 2020

Copied

Hi JoÃ£o,

Thank you so much for that, the code works great.

I'm now trying to apply it to a specific movieclip instead of generating a vector shape but I'm having trouble modifying the code for this. Are you able to explain how I would change the code to work with a movieclip called obj instead of generating a vector shape?

Thanks

AB

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Oct 30, 2020 Oct 30, 2020

Copied

Sorry I can't edit my post but was also wondering if there's a way to set the speed of the objects to be between certain numbers?

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Oct 31, 2020 Oct 31, 2020

Copied

Is there also a way to remove all the objects when you click the mouse and then to restart it again when you reclick?

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Oct 31, 2020 Oct 31, 2020

Copied

Hi.

You need to select the Movie Clip you want to use in the Library, right-click it, go to Properties... and check Export for ActionScript. The name in the Class field is the one you're gonna use in the code. So you would replace Circ in the code for Rec, for example.

I've applied some changes to the code in some places so now it uses a symbol called Rec that lives in the Library and I've also applied the mouse click interaction.

AS3 code:

``````import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;

const TOTAL:uint = 1000;
var container:DisplayObjectContainer = this;
var objs:Vector.<Rec> = new Vector.<Rec>();
var remove:Boolean = true;

function generateObject():void
{
var obj:Rec = new Rec();

obj.x = obj.width * 0.5 + Math.random() * (stage.stageWidth - obj.width);
obj.y = obj.height * 0.5 + Math.random() * (stage.stageHeight - obj.height);
obj.speedX = -5 + Math.random() * 5;
obj.speedY = -5 + Math.random() * 5;
obj.alpha = 0.2 + Math.random() * 0.8;
objs.push(obj);
}

function enterFrameHandler(event:Event):void
{
if (objs.length < TOTAL)
generateObject();

for (var i:int = objs.length -1; i >= 0; i--)
{
var obj:Rec = objs[i];
var left:Number = obj.width * 0.5;
var right:Number = stage.stageWidth - obj.width * 0.5;
var top:Number = obj.height * 0.5;
var bottom:Number = stage.stageHeight - obj.height * 0.5;

if (obj.x < left)
{
obj.speedX = -obj.speedX;
obj.x = left;
}
else if (obj.x > right)
{
obj.speedX = -obj.speedX;
obj.x = right;
}
else if (obj.y < top)
{
obj.speedY = -obj.speedY;
obj.y = top;
}
else if (obj.y > bottom)
{
obj.speedY = -obj.speedY;
obj.y = bottom;
}

obj.x += obj.speedX;
obj.y += obj.speedY;
}
}

function restart(e:MouseEvent):void
{
if (remove)
{
container.removeChildren();
objs.splice(0, objs.length);
stage.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
else

remove = !remove;
}

As for putting the speed value between certain numbers, I think that already happens here:

``````obj.speedX = -5 + Math.random() * 5; // number from -5 to 5
obj.speedY = -5 + Math.random() * 5; // number from -5 to 5``````

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Beginner ,
Nov 01, 2020 Nov 01, 2020

Copied

That worked great, I was able to change the code and have it work in my game.

Thanks so much for that and explaining how things work, really helped understand it.

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Nov 01, 2020 Nov 01, 2020

Copied

Have a nice weekend!

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Explorer ,
Jul 20, 2022 Jul 20, 2022

Copied

Hi, JoÃ£o Cesar...

That's amazing! I need this in HTML5 version, please...

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Jul 21, 2022 Jul 21, 2022

Copied

Sure.

Example 1:

``````var root = this;
var container = root.container; // container should be placed at 0,0
var degrees = Math.PI / 180;
var total = 25;
var changeDirectionDelay = 2000;
var libraryLinkage = "Arrow"; // linkage of the symbol in the Library

function main()
{
createjs.Ticker.timingMode = createjs.Ticker.RAF;
generateparticleects(total, container);
root.tickEvent = createjs.Ticker.on("tick", enterFrameHandler);
root.interval = setInterval(changeDirection, changeDirectionDelay);
}

function generateparticleects(total, container)
{
var i = 0;

for (i = 0; i < total; i++)
{

particle.x = lib.properties.width * Math.random();
particle.y = lib.properties.height;
particle.rotation = -180 + Math.random() * 180;
particle.direction = particle.rotation;
particle.speedX = 2 + Math.random() * 3;
particle.speedY = 2 + Math.random() * 3;
particle.friction = 0.85;
}
}

function enterFrameHandler()
{
var i, particle;

for (i = container.numChildren - 1; i > -1; i--)
{
particle = container.children[i];

if (particle.x < -particle.nominalBounds.width * 0.5)
particle.x = lib.properties.width + particle.nominalBounds.width * 0.5;
else if (particle.x > lib.properties.width + particle.nominalBounds.width * 0.5)
particle.x = -particle.nominalBounds.width * 0.5;

if (particle.y < -particle.nominalBounds.height * 0.5)
particle.y = lib.properties.height + particle.nominalBounds.height * 0.5;
else if (particle.y > lib.properties.height + particle.nominalBounds.height * 0.5)
particle.y = -particle.nominalBounds.height * 0.5;

particle.rotation = lerp(particle.rotation, particle.direction, particle.friction);
particle.x = particle.x + particle.speedX * Math.cos(particle.rotation * degrees);
particle.y = particle.y + particle.speedY * Math.sin(particle.rotation * degrees);
}
}

function changeDirection()
{
var i, particle;

for (i = container.numChildren - 1; i > -1; i--)
container.children[i].direction = -180 + Math.random() * 180;
}

function lerp(v1, v2, f)
{
return f * v1 + (1 - f) * v2;
}

main();``````

Example 2:

``````var root = this;
var container = root.container; // container should be placed at 0,0
var total = 1000;
var remove = true;
var w = lib.properties.width;
var h = lib.properties.height;
var libraryLinkage = "Rec"; // linkage of the symbol in the Library

function main()
{
createjs.Touch.enable(stage);
createjs.Ticker.timingMode = createjs.Ticker.RAF;
root.tickEvent = createjs.Ticker.on("tick", enterFrameHandler);
}

function generateparticleect()
{

particle.x = particle.nominalBounds.width * 0.5 + Math.random() * (w - particle.nominalBounds.width);
particle.y = particle.nominalBounds.height * 0.5 + Math.random() * (h - particle.nominalBounds.height);
particle.vX = -5 + Math.random() * 5;
particle.vY = -5 + Math.random() * 5;
particle.alpha = 0.2 + Math.random() * 0.8;
}

function enterFrameHandler()
{
var i;

if (container.numChildren < total)
generateparticleect();

for (i = container.numChildren - 1; i > -1; i--)
{
var particle = container.children[i];
var left = particle.nominalBounds.width * 0.5;
var right = w - particle.nominalBounds.width * 0.5;
var top = particle.nominalBounds.height * 0.5;
var bottom = h - particle.nominalBounds.height * 0.5;

if (particle.x < left)
{
particle.vX = -particle.vX;
particle.x = left;
}
else if (particle.x > right)
{
particle.vX = -particle.vX;
particle.x = right;
}
else if (particle.y < top)
{
particle.vY = -particle.vY;
particle.y = top;
}
else if (particle.y > bottom)
{
particle.vY = -particle.vY;
particle.y = bottom;
}

particle.x += particle.vX;
particle.y += particle.vY;
}
}

function restart()
{
if (remove)
{
container.removeAllChildren();
createjs.Ticker.off("tick", root.tickEvent);
}
else
root.tickEvent = createjs.Ticker.on("tick", enterFrameHandler);

remove = !remove;
}

main();``````

I hope it helps.

Regards,

JC

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Explorer ,
Jul 21, 2022 Jul 21, 2022

Copied

LATEST

Hi, JoÃ£o Cesar...

It works great! This is really awesome! And how about to change the speed of movement particles in code example 1 ?