move an object from left to right in 1 minute - actionscript-3

I want to move an Object in Flash from left to right in 1 minute
I tried to do it like this but it is less than 1 minute
addEventListener(Event.ENTER_FRAME, move);
function move(e:Event):void{
this.myObject.x += 1;
}
How can I move myObject in 1 minute and also Stop it when in end of the screen in right?

Try creating a Tween by minimally editing the example given in the documentation:
import fl.transitions.Tween;
import fl.transitions.easing.*;
var myTween:Tween = new Tween(myObject, "x", None.easeNone, 0, stage.stageWidth, 60, true);
You want to find the starting and end points for the position that suits your needs which are not exactly clear from your question.

var duration_ms:int = 60*1000;
var offset:Number = 100;
var start_time_ms:int = getTimer();
var start_pos_x:int = mc.x;
var end_pos_x:int = mc.x+offset;
addEventListener(Event.ENTER_FRAME, Loop);
function Loop(e:event):void {
var elapsed_ms:int = getTimer() - start_time_ms;
if (elapsed_ms<duration_ms) {
mc.x = start_pos_x + ((end_pos_x-start_pos_x)*(elapsed_ms/duration_ms));
}
}

Related

How do I adjust drag speed of an object?

Ok, I am developing a game that requires the player to drag an object and place it inside of a jar. I found it to be much easier to designate an x coordinate limitation in order to determine when the object they are dragging should simulate dropping into the jar. The code that I have so far works perfectly. However, the action script that is initiated when the object crosses the x coordinate limit is ignored when the players move the object too fast over the x limit. I think that I can fix this problem by limiting how fast the object can be dragged. Does anyone have any direction on how this can be accomplished?
Here is my code:
jarFront.mouseEnabled = false; jarFront.mouseChildren = false;
// animate buttons in
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
import flash.events.Event;
var objArray:Array = new Array;
objArray.push(obj1);
objArray.push(obj2);
objArray.push(obj3);
var objPosition:Point;
function dragobj(e:Event):void {
e.currentTarget.startDrag();
objPosition = new Point( e.currentTarget.x, e.currentTarget.y);
}
function dragobjStop(e:Event):void {
e.currentTarget.stopDrag();
e.currentTarget.x = e.currentTarget.x;
e.currentTarget.y = objPosition.y;
objPosition = null;
}
for (var i:uint = 0; i < objArray.length; i++) {
objArray[i].addEventListener(MouseEvent.MOUSE_DOWN, dragobj);
objArray[i].addEventListener(MouseEvent.MOUSE_UP, dragobjStop);
}
// Drop in jar
var HighH:int=400;
var HighW:int=400;
var LowH:int=-200; var LowW:int=0;
var HighyH:int=170;
var HighyW:int=170;
var LowyH:int=0; var LowyW:int=0;
this.addEventListener( Event.ENTER_FRAME, goJar)
function goJar( e:Event ):void
{
if (obj1.x > 400 && obj1.x < 440) {
obj1.stopDrag();
//set back or tween position
obj1.x = 83;
obj1.y = -300;
this.setChildIndex(obj1,1)
var ct1_1:Tween = new Tween(obj1, "y", None.easeNone, obj1.y, obj1.y=Math.floor(Math.random()*(1+HighyH-LowyH))+LowyH, .2, true);
var ct1_2:Tween = new Tween(obj1, "rotation", Bounce.easeOut, 0, 180, 1, true);
var ct1_3:Tween = new Tween(obj1, "x", None.easeNone, obj1.x, obj1.x=Math.floor(Math.random()*(1+HighH-LowH))+LowH, .2, true);
} else {
// keep inside jar
if (obj1.x > -330 && obj1.x < -260) {
obj1.stopDrag();
//set back or tween position
obj1.x = 83;
obj1.y = -300;
this.setChildIndex(obj1,1)
var ct1_4:Tween = new Tween(obj1, "y", None.easeNone, obj1.y, obj1.y=Math.floor(Math.random()*(1+HighyH-LowyH))+LowyH, .2, true);
var ct1_5:Tween = new Tween(obj1, "rotation", Bounce.easeOut, 0, 180, 1, true);
var ct1_6:Tween = new Tween(obj1, "x", None.easeNone, obj1.x, obj1.x=Math.floor(Math.random()*(1+HighH-LowH))+LowH, .2, true);
}
}
}
Also, it would be VERY helpful if there was a way to include everything below "//Drop in jar" in the array functions above so that this action script can be automatically applied to obj2 and obj3.
You have no code in there that limits the movement of the dragged object whatsoever. If you want to limit the object position simply pass a Rectangle object to the startDrag method.
Thanks BotMaster, based on your direction I modified my code like so:
var rectangle1:Rectangle = new Rectangle(400, -665, 1156, 1052);
var rectangle2:Rectangle = new Rectangle(-376, -665, 721, 1052);
var candyPosition:Point;
function dragCandy(e:Event):void {
if (e.currentTarget.x > 400) {
e.currentTarget.startDrag(false, rectangle1);
candyPosition = new Point( e.currentTarget.x, e.currentTarget.y);
} else {
e.currentTarget.startDrag(false, rectangle2);
candyPosition = new Point( e.currentTarget.x, e.currentTarget.y);
}
}
Basically, what happens here:
If the object is at an x position greater than 400, then dragging will be constrained to rectangle1
Once the object has been dragged to a specific x position outside of the jar, it will be tweened inside of the jar.
Now that the object is in the jar, its new x position will be less than 400 and dragging will now be constrained to rectangle2.
Now, when the object is dragged up our of the jar and on top of the hitTestObject, it will be tweened back to a random position out side of the jar.

How to decrement Timer variable - AS3

Well, I have two TIMER type variables in my code AS3, but there comes a certain part
of my game, I have to decrement the value of them.
var tempo1:Timer = new Timer(4000);
var tParada:Timer = new Timer(2000, 1);
I wonder how can I do to go decrementing these values, starting from an external class ...
Thank U.
Just decriment the delay every time the timer fires.
var tempo1:Timer = new Timer(4000);
tempo1.addEventListener(TimerEvent.TIMER, tick);
var minValue:int = 1000;
tempo1.start();
function tick(e:TimerEvent):void {
if(tempo1.delay - 100 >= minValue){
tempo1.delay -= 100;
}
}
Or, if wanted it smoother, you could do something like this:
import flash.events.TimerEvent;
import flash.utils.Timer;
import fl.transitions.Tween;
import fl.transitions.easing.*;
var tempo1:Timer = new Timer(33); //30 times a seconds or so
tempo1.addEventListener(TimerEvent.TIMER, tick);
var curTickTime:int = 4000;
tempo1.start();
function tick(e:TimerEvent):void {
if(tempo1.delay * tempo1.currentCount >= curTickTime){
trace("tick"); //this should effectively be a tick
tempo1.reset();
tempo1.start();
//do whatever you do on a tick
}
}
//tween the tick delay from the starting value to 100ms over a period of 5 seconds
var tween:Tween = new Tween(this, "curTickTime", Strong.easeOut, curTickTime, 100, 5, true);

Why the Tween Class don't work inside a for with Flash AS3?

Problem
I'm trying to make a Tween with many Movieclips using the for command, like this:
for(var i:int = 0; i < mcArray.length; i++) {
new Tween(mcArray[i], "x", Regular.easeOut, 0, 100, 1.0, true);
}
But it doesn't works. I've tried change the code as follow down:
var tween:Tween = new Tween(mcArray[i], "x", Regular.easeOut, 0, 100, 1.0, true);
And it doesn't works too.
I can't use the setInterval or Timer because the Movieclips should be synchronized and the it may cause problems.
Is there a way to do this?
AS3 Tween engine, very bad: by design, by performance etc.
If you can't use Greensock library for animation, you could use GTween, It's great tweening engine under MIT Licence. Even without support and continuous improvement, engine is much better than Tween by Adobe.
Working example, after start, if will collect every object in the center of scene:
package {
import com.gskinner.motion.GTween;
import com.gskinner.motion.easing.Sine;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Point;
public class StackOverflow extends Sprite {
public function StackOverflow() {
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, onAdded);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
setup();
}
private function createDummyObjects(size:uint):Array {
var result:Array = [], i:uint, object:Shape;
for (i; i < size; ++i) {
object = new Shape();
object.graphics.beginFill(Math.random() * 0xFFFFFF);
object.graphics.drawCircle(0, 0, 20);
result[i] = object;
}
return result;
}
private function setup():void {
var objects:Array = createDummyObjects(10);
var i:uint, len:uint = objects.length, item:DisplayObject, middle:Point = new Point(stage.stageWidth >> 1, stage.stageHeight >> 1);
for (i; i < len; ++i) {
item = objects[i];
item.x = Math.random() * stage.stageWidth;
item.y = Math.random() * stage.stageHeight;
addChild(item);
new GTween(item, 1 + Math.random() * 4, {x: middle.x, y: middle.y}, {ease: Sine.easeInOut});
}
}
}
}
I tried your exact code and it works just fine. You need to load your array initially, and I'm not seeing your code for that.
Try this: make two test MovieClips and put 'em on stage with instance names 'boxA' and 'boxR' Then run this code:
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
var A:Array = new Array();
A.push(boxB); A.push(boxR);
for(var i:int = 0; i < A.length; i++)
{
new Tween(A[i], "x", Regular.easeOut, 0, 100, 1.0, true);
}
Works, no?
If everything in your code is correct and the code is running perfectly fine, and the tweens just aren't working, then this may be caused by Flash's garbage collector killing your tweens before they can finish.
This issue is relatively well known I think. I have run into this issue myself. Here is an article explaining the cause and how to fix it. http://www.scottgmorgan.com/as3-garbage-collection-the-reason-your-tweens-are-ending-early/
Essentially what you have to do is make sure you have a reference to your tween somewhere in your code.
Here is some code you can try to actually see it happening:
var mcs:Array = [];
var tweens:Array = [];
for (var j:int = 0; j < 50; j++) {
for (var i:int = 0; i < 50; i++) {
var mc:MovieClip = new MovieClip ();
mc.graphics.beginFill (0xff0000);
mc.graphics.drawRect (0, 0, 5, 5);
mc.graphics.endFill ();
mc.x = j * 6;
mc.y = i * 6;
mcs.push (mc);
this.addChild (mc);
new Tween (mc, "x", None.easeNone, mc.x, mc.x + 500, 2, true);
//tweens.push (new Tween (mc, "x", None.easeNone, mc.x, mc.x + 500, 2, true));
}
}
In theory every single red square in this code should tween to the right, but only about half do, for me at least. However if you comment out the second last line and uncomment the last line, it should now work because the array holds a reference to each tween.

Shaking effect - Flash CS6 ActionScript3.0

This question is related to ActionScript 3.0 and Flash CS6
I am trying to make an object shake a bit in a certain for some seconds. I made it a "movieclip" and made this code:
import flash.events.TimerEvent;
var Machine_mc:Array = new Array();
var fl_machineshaking:Timer = new Timer(1000, 10);
fl_machineshaking.addEventListener (TimerEvent.TIMER, fl_shakemachine);
fl_machineshaking.start ();
function fl_shakemachine (event:TimerEvent):void {
for (var i = 0; i < 20; i++) {
Machine.x += Math.random() * 6 - 4;
Machine.y += Math.random() * 6 - 4;
}
}
When testing the movie I get multiple errors looking exactly like this one:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Historieoppgave_fla::MainTimeline/fl_shakemachine()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
Also, the object doesnt shake, but it moves steadily upwards to the left a bit every tick.
To the point:
I wish to know how I stop the script after the object is not in the stage/scene anymore and also how to make it shake around, as I do not see what is wrong with my script, please help, thank you ^_^
AStupidNube brought up a great point about the original position. So adding that to shaking that should be a back and forth motion, so don't rely on random values that may or may not get you what you want. Shaking also has a dampening effect over time, so try something like this:
Link to working code
• http://wonderfl.net/c/eB1E - Event.ENTER_FRAME based
• http://wonderfl.net/c/hJJl - Timer Based
• http://wonderfl.net/c/chYC - Event.ENTER_FRAME based with extra randomness
**1 to 20 shaking items Timer Based code - see link above for ENTER_FRAME code••
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.utils.Timer;
public class testing extends Sprite {
private var shakeButton:Sprite;
private var graphic:Sprite;
private var shakerPos:Array;
private var shakers:Array;
private var numShakers:int = 20;
private var dir:int = 1;
private var displacement:Number = 10;
private var shakeTimer:Timer;
public function testing() {
this.shakers = new Array();
this.shakerPos = new Array();
this.addEventListener(Event.ADDED_TO_STAGE, this.init);
}
private function init(e:Event):void {
this.stage.frameRate = 30;
this.shakeTimer = new Timer(33, 20);
this.shakeTimer.addEventListener(TimerEvent.TIMER, this.shake);
this.graphics.beginFill(0x333333);
this.graphics.drawRect(0,0,this.stage.stageWidth, this.stage.stageHeight);
this.graphics.endFill();
this.createShakers();
this.shakeButton = this.createSpriteButton("Shake ");
this.addChild(this.shakeButton);
this.shakeButton.x = 10;
this.shakeButton.y = 10;
this.shakeButton.addEventListener(MouseEvent.CLICK, this.shakeCallback);
}
private function createSpriteButton(btnName:String):Sprite {
var sBtn:Sprite = new Sprite();
sBtn.name = btnName;
sBtn.graphics.beginFill(0xFFFFFF);
sBtn.graphics.drawRoundRect(0,0,80,20,5);
var sBtnTF:TextField = new TextField();
sBtn.addChild(sBtnTF);
sBtnTF.text = btnName;
sBtnTF.x = 5;
sBtnTF.y = 3;
sBtnTF.selectable = false;
sBtn.alpha = .5;
sBtn.addEventListener(MouseEvent.MOUSE_OVER, function(e:Event):void { sBtn.alpha = 1 });
sBtn.addEventListener(MouseEvent.MOUSE_OUT, function(e:Event):void { sBtn.alpha = .5 });
return sBtn;
}
private function createShakers():void {
var graphic:Sprite;
for(var i:int = 0;i < this.numShakers;i++) {
graphic = new Sprite();
this.addChild(graphic);
graphic.graphics.beginFill(0xFFFFFF);
graphic.graphics.drawRect(0,0,10,10);
graphic.graphics.endFill();
// add a 30 pixel margin for the graphic
graphic.x = (this.stage.stageWidth-60)*Math.random()+30;
graphic.y = (this.stage.stageWidth-60)*Math.random()+30;
this.shakers[i] = graphic;
this.shakerPos[i] = new Point(graphic.x, graphic.y);
}
}
private function shakeCallback(e:Event):void {
this.shakeTimer.reset();
this.shakeTimer.start();
}
private function shake(e:TimerEvent):void {
this.dir *= -1;
var dampening:Number = (20 - e.target.currentCount)/20;
for(var i:int = 0;i < this.numShakers;i++) {
this.shakers[i].x = this.shakerPos[i].x + Math.random()*10*dir*dampening;
this.shakers[i].y = this.shakerPos[i].y + Math.random()*10*dir*dampening;
}
}
}
}
Now this is a linear dampening, you can adjust as you see fit by squaring or cubing the values.
You have to remember the original start position and calculate the shake effect from that point. This is my shake effect for MovieClips. It dynamically adds 3 variables (startPosition, shakeTime, maxShakeAmount) to it. If you use classes, you would add them to your clips.
import flash.display.MovieClip;
import flash.geom.Point;
function shake(mc:MovieClip, frames:int = 10, maxShakeAmount:int = 30) : void
{
if (!mc._shakeTime || mc._shakeTime <= 0)
{
mc.startPosition = new Point(mc.x, mc.y);
mc._shakeTime = frames;
mc._maxShakeAmount = maxShakeAmount;
mc.addEventListener(Event.ENTER_FRAME, handleShakeEnterFrame);
}
else
{
mc.startPosition = new Point(mc.x, mc.y);
mc._shakeTime += frames;
mc._maxShakeAmount = maxShakeAmount;
}
}
function handleShakeEnterFrame(event:Event):void
{
var mc:MovieClip = MovieClip(event.currentTarget);
var shakeAmount:Number = Math.min(mc._maxShakeAmount, mc._shakeTime);
mc.x = mc.startPosition.x + (-shakeAmount / 2 + Math.random() * shakeAmount);
mc.y = mc.startPosition.y + (-shakeAmount / 2 + Math.random() * shakeAmount);
mc._shakeTime--;
if (mc._shakeTime <= 0)
{
mc._shakeTime = 0;
mc.removeEventListener(Event.ENTER_FRAME, handleShakeEnterFrame);
}
}
You can use it like this:
// shake for 100 frames, with max distance of 15px
this.shake(myMc, 100, 15);
BTW: In Flash, you should enable 'permit debugging' in your 'publish settings' to have more detailed errors. This also gives back the line numbers where your code is breaking.
update:
Code now with time / maximum distance separated.
Here is a forked version of the chosen answer, but is a bit more flexible in that it allows you to set the frequency as well. It's also based on time as opposed to frames so you can think in terms of time(ms) as opposed to frames when setting the duration and interval.
The usage is similar to the chosen answer :
shake (clipToShake, durationInMilliseconds, frequencyInMilliseconds, maxShakeRange);
This is just an example of what I meant by using a TimerEvent as opposed to a ENTER_FRAME. It also doesn't require adding dynamic variables to the MovieClips you are shaking to track time, shakeAmount, and starting position.
public function shake(shakeClip:MovieClip, duration:Number = 3000, frequency:Number = 30, distance:Number = 30):void
{
var shakes:int = duration / frequency;
var shakeTimer:Timer = new Timer(frequency, shakes);
var startX:Number = shakeClip.x;
var startY:Number = shakeClip.y;
var shakeUpdate:Function = function(e:TimerEvent):void
{
shakeClip.x = startX + ( -distance / 2 + Math.random() * distance);
shakeClip.y = startY + ( -distance / 2 + Math.random() * distance);
}
var shakeComplete:Function = function(e:TimerEvent):void
{
shakeClip.x = startX;
shakeClip.y = startY;
e.target.removeEventListener(TimerEvent.TIMER, shakeUpdate);
e.target.removeEventListener(TimerEvent.TIMER_COMPLETE, shakeComplete);
}
shakeTimer.addEventListener(TimerEvent.TIMER, shakeUpdate);
shakeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, shakeComplete);
shakeTimer.start();
}
-4 <= Math.random() * 6 - 4 < 2
You add this offset to Machine.x 20 times, so chances for moving to the left is greater, than to the right.
It seems that you looking for something like this:
for each (var currentMachine:MovieClip in Machine_mc)
{
currentMachine.x += Math.random() * 6 - 3;
currentMachine.y += Math.random() * 6 - 3;
}

make an object move directly towards a point and stop when it reaches it

How can I make my object stop when it reaches the destination i gave it with my mouse click? The code makes the object move towards the point of a mouse click but I can't seem to find out how to make it stop, because it will almost never pass the specific destination point. :/ Somebody who knows how to accomplish this?
public function onMouseDown(evt:MouseEvent)
{
if (this._character != null)
{
_character.isMoving = false;
_character.dx = 0;
_character.dy = 0;
targetX = mouseX - _character.x;
targetY = mouseY - _character.y;
var angle:Number = Math.atan2(targetY,targetX);
var dx:Number = Math.cos(angle) * _character.speed;
var dy:Number = Math.sin(angle) * _character.speed;
_character.dx = dx;
_character.dy = dy;
_character.isMoving = true;
}
}
public function updateCharacter(e:Event):void
{
if (this._character.isMoving)
{
this._character.x += this._character.dx;
this._character.y += this._character.dy;
}
}
Easiest way to do it would be to calculate the angle to the point you want to stop at each time you move. This value should remain the same if you're moving in a straight line until you pass the point you're trying to stop at, at which point it will change drastically.
Once this happens, simply move your object back to the position it should have stopped at before you render it again.
I've created a demo with source code for you. There's a fair amount of code, so rather than posting everything here you can download the source instead:
http://martywallace.com/testing/gotoPoint.zip
Try this
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Guest extends MovieClip
{
var walkSpeed:Number = 5;
var oldPosX;
var oldPosY;
public function Guest()
{
stage.addEventListener(MouseEvent.CLICK, walk);
}
function walk(event:MouseEvent):void
{
oldPosX = parent.mouseX;
oldPosY = parent.mouseY;
rotation = Math.atan2(oldPosY - y,oldPosX - x) / Math.PI * 180;
addEventListener(Event.ENTER_FRAME, loop);
}
function loop(event:Event):void
{
// see if you're near the target
var dx:Number = oldPosX - x;
var dy:Number = oldPosY - y;
var distance:Number = Math.sqrt((dx*dx)+(dy*dy));
if (distance<walkSpeed)
{
// if you are near the target, snap to it
x = oldPosX;
y = oldPosY;
removeEventListener(Event.ENTER_FRAME, loop);
}
else
{
x = x+Math.cos(rotation/180*Math.PI)*walkSpeed;
y = y+Math.sin(rotation/180*Math.PI)*walkSpeed;
}
}
}
}
Similar questions have been asked many times.
However, see the code in my answer here that should explain how to move and stop.
Movement of Objects in a simulation