How to stop a movieClip from playing in Flash CS6 AS3 (with Box2D) - actionscript-3

I've spent 14 hours on this problem. This is a basic collision checker that sets a MovieClip animation to play when a collision occurs. The clip is
currentBallObject.clip.
It works. The clips plays. But it repeats over and over.
private function checkCollisions():void
{
var i = balls.length;
while (i--)
{
var currentBallObject = balls[i];
if (currentBallObject.contact)
{
//condition hits ground
if (currentBallObject.ground)
{
currentBallObject.body.SetPosition(new b2Vec2(currentBallObject.startX / PIXELS_TO_METRE, currentBallObject.startY / PIXELS_TO_METRE));
currentBallObject.body.SetLinearVelocity(new b2Vec2(0, 0));
currentBallObject.body.SetAngularVelocity(0);
//currentBallObject.texture.pop();
}
else // it hit player
{
// assign clip texture to current position
currentBallObject.clip.x = currentBallObject.body.GetPosition().x * PIXELS_TO_METRE;
currentBallObject.clip.y = currentBallObject.body.GetPosition().y * PIXELS_TO_METRE;
// whisk old object away
currentBallObject.body.SetPosition(new b2Vec2(currentBallObject.startX / PIXELS_TO_METRE, currentBallObject.startY / PIXELS_TO_METRE));
currentBallObject.body.SetLinearVelocity(new b2Vec2(0, 0));
currentBallObject.body.SetAngularVelocity(0);
currentBallObject.contact = false;
}
}
}
}
I added this code to delete the MovieClip or somehow get rid of it after it has played through once. (42 frames). I also tried to add a frameListener and at least a dozen other suggestions. When I add
stop()
The animation doesn't play. It just loads the last frame. The code I have now is:
private function updateClips():void
{
var i = balls.length;
while (i--)
{
var currentBallObject = balls[i];
if(currentBallObject.clip)
{
var frame:int = currentBallObject.clip.currentFrame;
//trace(currentBallObject.clip.currentFrame);
if(frame == 42)
{
currentBallObject.clip._visible = false;
currentBallObject.clip.removeMovieClip();
currentBallObject.clip.enabled = -1;
}
}
}
}
I've tried counting the frames, putting it a run-once function, a frame exit listener, I am out of ideas. I just want to make a MovieClip run one time through. I also tried putting stop() in the timeline and then the animation didn't play. It just loaded the last frame.
Right now the collisions work but the animations stay on the screen forever, looping forever.
Edit: I got the code by Patrick to run without errors.
I added the event listener with the others like this:
_input = new Input(stage);
...
addEventListener(Event.ENTER_FRAME, oEF);
addEventListener(Event.ENTER_FRAME, update);
time_count.addEventListener(TimerEvent.TIMER, on_time);
time_count.start();
}
And then created a function:
private function oEF(e:Event):void{
var i = balls.length;
while (i--)
{
var currentBallObject = balls[i];
if (currentBallObject.clip.currentFrame >= currentBallObject.clip.totalFrames)
{
currentBallObject.clip.stop();
currentBallObject.clip.removeEventListener(Event.ENTER_FRAME, oEF);
if (currentBallObject.clip.parent) currentBallObject.clip.parent.removeChild(currentBallObject.clip);
}
}
}
But I still get the same problem as any other result. The MovieClip disappears on contact without the animation happening.
Through debugging I've learned more. The value of currentFrame starts off going 1-40 then stays at 40 for the rest of the execution.
So the MovieClip is always on the last frame for every object.

if clip is a MovieClip then you can use clip.totalFrames in an enterframe listener.
function oEF(e:Event):void{
if (this.currentFrame >= this.totalFrames){
this.stop();
this.removeEventListener(Event.ENTER_FRAME, oEF);
if (this.parent) this.parent.removeChild(this);
}
}
this.addEventListener(Event.ENTER_FRAME, oEF);

I figured it out.
if (currentBallObject.clip.currentFrame == currentBallObject.clip.totalFrames)
{
trace("Frame before kill: ", currentBallObject.clip.currentFrame);
currentBallObject.clip.x = 0;
currentBallObject.clip.y = 0;
}
The above block goes right after
var currentBallObject = balls[i];
It checks if the movieClip is on the last frame and then gets rid of the clip by setting clip.x & clip.y to 0. I could find no other way to stop the movie in this particular case.

Related

Timeline Seekbar in AS3

I'm trying a flash actionscript project to include a custom seekbar for timeline frame navigation. Now i could get dragger moving across the seekbar with respect to the totalframes. But dragging the seekbar brings error. Also i want to include timer to show the minute and seconds passed.
var ratio = 0;
ratio = this.totalFrames/main.line.width;
var go = 0;
var isComplete = false;
var tFrame = this.totalFrames;
var isPress = false;
stage.addEventListener(Event.ENTER_FRAME, drag);
function drag(event:Event):void {
if(main.dragger.x<=main.line.width){
main.dragger.x = this.currentFrame/ratio;
}
}
main.dragger.addEventListener(MouseEvent.MOUSE_DOWN, drag1);
function drag1(event:MouseEvent):void {
main.dragger.startDrag(false, new Rectangle(0, 9.2, main.line.width, 9.2));
isPress = true;
main.dragger.addEventListener(Event.ENTER_FRAME, frame);
}
function frame(event:Event):void
{
trace (this.currentFrame);
if(this.currentFrame < tFrame){
gotoAndPlay(Math.round(main.x*ratio));
}else{
gotoAndPlay(tFrame-1);
}
}
main.dragger.addEventListener(MouseEvent.MOUSE_UP,release);
function release(event:MouseEvent):void {
main.dragger.stopDrag();
main.dragger.removeEventListener(MouseEvent.MOUSE_DOWN, drag1);
}
when i click the dragger to move, it automatically jumps to starting position and also the gotoAndPlay jumps to that position and continuously stays there..
Attachment:
https://drive.google.com/open?id=0B4UOEUQTrhB0a21EaUpaUE52MGM
UPDATE
This is an other method found in adobe forum, But this also gives the same dragging problem.
var tl:MovieClip=this;
tl.addEventListener(Event.ENTER_FRAME,enterframeF);
paramF(tl,1,0,tl.totalFrames,slider.line.width); // create a horizontal slider movieclip that contains a track movieclip and a thumbscroll movieclip that do the obvious and have left-sided reg point
paramF(slider,0,1,slider.line.width-slider.thumbscroll.width,tl.totalFrames);
var scrollRect1:Rectangle=new Rectangle(0,0,slider.line.width-slider.thumbscroll.width,0);
function enterframeF(e:Event):void{
slider.thumbscroll.x=tl.m*tl.currentFrame+tl.b;
}
slider.thumbscroll.addEventListener(MouseEvent.MOUSE_DOWN,scrolldownF);
slider.thumbscroll.addEventListener(MouseEvent.MOUSE_UP,scrollupF);
function scrolldownF(e:MouseEvent):void{
tl.removeEventListener(Event.ENTER_FRAME,enterframeF);
slider.thumbscroll.startDrag(false,scrollRect1);
slider.addEventListener(Event.ENTER_FRAME,scrollF);
}
function scrollupF(e:MouseEvent):void{
tl.addEventListener(Event.ENTER_FRAME,enterframeF);
slider.thumbscroll.stopDrag();
slider.removeEventListener(Event.ENTER_FRAME,scrollF);
}
function scrollF(e:MouseEvent):void{
tl.gotoAndStop(Math.round(slider.thumbscroll.x*slider.m+slider.b));
}
function paramF(mc:MovieClip,x1:Number,y1:Number,x2:Number,y2:Number):void{
mc.m=(y1-y2)/(x1-x2);
mc.b=y2-mc.m*x2;
}

Problems with an object appearing on a frame I don't want it to appear on AS3

I am a total noob at AS3, roughly 1 year experience so please be lenient with me :)
I currently am making an endless runner game and I'm making the obstacles spawn using this method
var therespawn:RespawnObject;
var thecone:trafficcone;
var started:Boolean = false;
var dx:Number = 10;
var dy:Number = 10;
stage.addEventListener(Event.ENTER_FRAME, startGame);
addEventListener(Event.ENTER_FRAME, collision);
addEventListener(Event.ENTER_FRAME, coneCollision);
function startGame(evt:Event):void {
if (started == false) {
spawnHazard();
}
}
function spawnHazard() {
started = true;
therespawn = new RespawnObject();
addChild(therespawn);
thecone = new trafficcone();
addChild(thecone);
therespawn.x = -50;
therespawn.y = 310;
thecone.x = 600;
thecone.y = 310;
}
function collision(evt:Event):void {
thecone.x -= 15;
if(thecone.hitTestObject(therespawn)) {
thecone.x = 600;
}
}
Now the only way to finish the game or end it is to get hit by an obstacle which ive shown down below:
function coneCollision(evt:Event):void {
if(MainChar.hitTestObject(thecone)) {
gotoAndStop("frameFive");
}
}
Everytime the highscore frame appears the cone is still spawning and despawning, why is that?
I haven't declared them as global?
Any help appreciated, thanks!
You can fix your problem by setting started to false:
function coneCollision(evt:Event):void {
if(MainChar.hitTestObject(thecone)) {
started = false;
gotoAndStop("frameFive");
}
}
The flash timeline really only has to with the way MovieClips are visually displayed as children of the stage. Removing an object from the timeline doesn't just suddenly nullify all the code associated with that object. In other words, your ENTER_FRAME method still runs in the background even if the object is no longer a child of the Stage, regardless of the frame number for the MovieClip. If you're serious about coding you might consider investigating in Classes and Object Oriented AS3. Classes are much nicer to work with than the Flash timeline.

EventListener AS3 problems reset problems

Hey guys I am having a problem with Event Listeners in my AS3 file. I am trying to make this object that lasts for 83 frames to appear in a different location every time the parent (83 frame) movie clip resets. The problem is I have a function that places the object at a random y value which works great once. When it resets the ojbect appears on the same Y point. This is because I removeEventListener the function otherwise the object goes shooting off the screen when it loads. How do I call that event listener again without causing a loop that will shoot the object off screen?
Here is my code:
import flash.events.Event;
stop();
addEventListener(Event.ENTER_FRAME, SeaWeedPostion);
//stage.addEventListener(Event.ADDED_TO_STAGE, SeaWeedPostion);
function SeaWeedPostion(e:Event):void{
// if(newSeaWeed == 1) {
var randUint:uint = uint(Math.random() *500 + 50);
this.seaweedSet.y += randUint;
trace(randUint);
stopPos();
//}else{
//nothing
// }
}
function stopPos():void{
removeEventListener(Event.ENTER_FRAME, SeaWeedPostion);
//var newSeaWeed = 0;
}
function resetSeaWeed():void{
addEventListener(Event.ENTER_FRAME, SeaWeedPostion);
}
I have some // code in there from trying different things.
Anyone have any suggestions?
Thanks!
ENTER_FRAME event is triggered every frame, so rather than changing position on each frame maybe it's better to create a counter, count frames and if it reaches 82 change position of SeaWeed.
var counter:uint = 0;
Now add ENTER_FRAME listener
addEventListener(Event.ENTER_FRAME, onEnterFrame);
function SeaWeedPostion(e:Event):void {
counter++;
//Are we there yet?
if(counter < 83) {
//Nope, carry on
}
else {
//Yey!
changePosition();
counter = 0;
}
}
//Reset SeaWeed position when called
function changePosition() {
var randUint:uint = uint(Math.random() *500 + 50);
this.seaweedSet.y += randUint;
trace(randUint);
}

How can I work this out?

I am making a game where insects from above the screen move downwards to the bottom. The object is for the player to kill these insects with his/her mouse. When killed the insect should show a kill frame, where I have put in. The kill frame will stay there for 3 seconds and the object will be removed. This will also increase the player's score.
This code is written inside the insect:
function kill(event:MouseEvent):void
{
this.dead = true;
}
This code is written inside the background movieclip frame.
function moveEnemies():void
{
var tempEnemy:MovieClip;
for (var i:int =enemies.length-1; i>=0; i--)
{
tempEnemy = enemies[i];
if (tempEnemy.dead)
{
tempEnemy.gotoAndStop(21);
var myTimer:Timer = new Timer(3000);
myTimer.addEventListener(TimerEvent.TIMER, timerListener);
myTimer.start();
}
}
}
function timerListener (e:TimerEvent):void
{
for (var i:int =enemies.length-1; i>=0; i--)
{
if (tempEnemy.dead)
{
score++;
roachLevel.score_txt.text = String(score);
removeEnemy(i);
}
}
}
function removeEnemy(id:int)
{
removeChild(enemies[id]);
enemies.splice(id,1);
}
The problem that I am experiencing with this, is that whenever I click on the insects they stay there. I click on another one it stays there. Then another, then after a while they disappear and the score increases. Sometimes the death frame doesn't appear and they die as soon as I touch them. Could you please tell me how I can solve this?
You have to relocate score adding to enemy class, and assign a timeout to the particular squished enemy instead of the base class. The best place to do it is in kill() function.
function kill(e:MouseEvent):void {
this.dead=true;
gotoAndStop(21);
flash.utils.setTimeout(removeSelf,3000);
}
function removeSelf():void {
this.parent.removeChild(this);
}
Now, adjust the mechanics for scoring and tracking objects. First, if an object becomes dead, you immediately remove it from the array of enemies (it will handle its removal on its own) and give score for it. And second, all the other functional should be preserved.
for (var i:int=enemies.length-1;i>=0;i--) {
var tempEnemy=enemies[i];
if (tempEnemy.dead) {
score++;
enemies.splice(i,1);
} else {
tempEnemy.y++; // or other move function
}
}
This loop should be in an enterframe listener, so it'll be called once per frame. Also combining splicing and moving like here eliminates the need of placing movement code elsewhere, as you iterate through the array anyway.

AS3 gotoAndStop causes object to remove itself

I have a student who is working on a Tower Defense game in AS3 and has an issue that has stumped me. He is using hitTestObject to change the direction that a movieClip is moving. The movieClip has its own timeline with frames for the different directions that the object is facing and a linked .as file with the code for the behavior of the object.
When he calls gotoAndStop to change the internal frame of the movieClip, the removed event is triggered, but the object stays on the screen and no longer moves.
All of my searches find answers about removing objects, but I have not seen anything about preventing an object from removing itself.
The following code is a loop triggered by an ENTER_FRAME event in the .as class file for the movieClip object:
private function eFrame(event:Event):void
{
if (_root.isPaused == false)
{
//MOVING THE ENEMY
this.x += speed * xDir;
this.y -= speed * yDir;
if (health <= 0)
{
_root.currency += 4;
this.parent.removeChild(this);
}
if (this.x > 770)
{
this.parent.removeChild(this);
_root.health -= 10;
_root.gotHit = true;
}
//checking if touching any invisible markers
for (var i:int=0; i<_root.upHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var upMarker:DisplayObject = _root.upHolder.getChildAt(i);
if (hitTestObject(upMarker))
{
yDir = 1;
xDir = 0;
this.gotoAndStop(3);
}
}
for (i=0; i<_root.downHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var downMarker:DisplayObject = _root.downHolder.getChildAt(i);
if (hitTestObject(downMarker))
{
yDir = -1;
xDir = 0;
this.gotoAndStop(7);
}
}
for (i=0; i<_root.rightHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var rightMarker:DisplayObject = _root.rightHolder.getChildAt(i);
if (hitTestObject(rightMarker))
{
yDir = 0;
xDir = 1;
this.gotoAndStop(6);
}
}
for (i=0; i<_root.leftHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var leftMarker:DisplayObject = _root.leftHolder.getChildAt(i);
if (hitTestObject(leftMarker))
{
yDir = 0;
xDir = -1;
this.gotoAndStop(2);
}
}
}
}
private function remove(event:Event):void
{
trace("remove");
removeEventListener(Event.ENTER_FRAME, eFrame);
_root.enemiesLeft -= 1;
}
}
When the gotoAndStop line executes, the frame of the movieClip changes and then the code jumps directly to a function that is triggered by the REMOVED event.
Does anyone have an idea why the REMOVED event might be triggered by this code?
Thank you for your help.
The REMOVED Event is triggered by anything that is removed from the stage inside the MovieClip or Sprite that is containing it, if I'm not mistaken. And especially with MovieClips that have animation, things get removed and added everytime, for instance if some part of the animation ends on the timeline, or at keyframes.
Event.REMOVED_FROM_STAGE is dispatched only when the container itself is removed from stage. Maybe that's causing your confusion? I can't see from your code example exactly what event type you're listening for.
Where are you adding the remove-listener?
Without more information, I would guess that you are listening to a clip inside an animation, and that it's not there on all frames (or, maybe even more likely - that the instance is being swapped out for another, identical one, by flash pro. This can happen depending on in what order you added keyframes, the alignment of the moon and fluctuations in the ionosphere. It's easiest fixed by simply removing all key-frames and then re-creating them. And then never using flash pro for anything ever again.)