Playing a sequence of given frames using ActionScript3 Flash - actionscript-3

I Am beginner with Flash and ActionScript 3
I have 8 lip code for a character that i did create in different frames, so i want to play my animation frame by frame but with a different order to form a phrase that my character will say
I did try it on my own but i did not successed:
stop();
var tableau = new Array();
tableau[0]=2;
tableau[1]=4;
tableau[2]=1;
tableau[3]=7;
tableau[4]=8;
tableau[5]=1;
tableau[6]=7;
for(var i =0;i<tableau.length;i++){
trace(tableau[i]==this.currentFrame);
if(tableau[i]==this.currentFrame){
gotoAndPlay(tableau[i]);
trace(this.currentFrame);
}
}

It's pretty much simple. What you need is to subscribe to the special event that fires once per frame and move the playhead once per frame according to the plan.
stop();
var Frames:Array;
// This will prevent things from overlapping
// if one of the frames on the list is the
// current one and playhead will hit here
// once again (and try to execute code).
if (Frames == null)
{
Frames = [2,4,1,7,8,1,7];
addEventListener(Event.ENTER_FRAME, onFrame);
}
function onFrame(e:Event):void
{
// Get the next frame index and remove it from the list.
var aFrame:int = Frames.shift();
// If there are no more frames to show,
// unsubscribe from the event.
if (Frames.length < 1)
{
removeEventListener(Event.ENTER_FRAME, onFrame);
}
gotoAndStop(aFrame);
}

Related

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

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.

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);
}

Sound won't stop when I go back to a previous Stage with code

i have 4 scenes and i put my script for music in scene 2 and then i jump to scene 3 but when i go back to scene 2 and press pause or stop, my music wont do that, but when i play, the music play and i get 2 music start :(, can anybody help the script ?
regards im newbie,
stop();
import flash.events.MouseEvent;
import flash.media.SoundChannel;
//declaring all variables
var isPlaying:Boolean = false;// boolean type of variables can be true or false only
var myMusic = new soothing();// saving music in a varaible
var myChannel:SoundChannel = new SoundChannel();// sound channel Class to stop
var lastPosition:Number = 0;
play_btn.addEventListener(MouseEvent.CLICK, onPlayClick);
pause_btn.addEventListener(MouseEvent.CLICK, onPauseClick);
stop_btn.addEventListener(MouseEvent.CLICK, onStopClick);
function onPlayClick(event:MouseEvent):void
{
if (isPlaying == false)
{
isPlaying = true;
myChannel = myMusic.play(lastPosition);
}
myChannel.addEventListener(Event.SOUND_COMPLETE, completeHANDLER);
function completeHANDLER(event:Event):void
{
lastPosition = 0;
isPlaying = false;
}
}
function onPauseClick(event:MouseEvent):void
{
isPlaying = false;
lastPosition = myChannel.position;
myChannel.stop();
}
function onStopClick(event:MouseEvent):void
{
if (isPlaying == true)
{
isPlaying = false;
lastPosition = 0;
myChannel.stop();
}
}
homebtn.addEventListener(MouseEvent.CLICK, qnextScene);
function qnextScene(event:MouseEvent):void
{
gotoAndStop(1, "Scene 2");
}
gallerybtn.addEventListener(MouseEvent.CLICK, nxtScene);
function nxtScene(event:MouseEvent):void
{
gotoAndStop(1, "Scene 3");
}
mebtn.addEventListener(MouseEvent.CLICK, nextsScene);
function nextsScene(event:MouseEvent):void
{
gotoAndStop(1, "Scene 4");
}
Ahhh, yes, the infamous stage sound bug I spent four months chasing down.
One fix: DON'T GO BACKWARDS ON STAGES. They're quite buggy.
Instead, what you put on a given stage, instead put inside a MovieClip. Create two functions instead each of those major MovieClips, one to start all the sounds, animations, etc that need to happen when it appears. The other to STOP sounds, animations, etc.
Then, set up a SINGLE stage with code to swap between these.
One other issue you're going to run into when you start in on this approach is that variables will seemingly clear themselves spontaneously. This is due to the nature of the timeline.These master movieclips should have ONE FRAME ONLY, and stop(); must be the first line of code after the import. If you have multiple frames on these master movieclips, or if you neglect stop, things will keep re-initializing, which is a pain in the butt.
(Heading this off at the pass: yes, code on the timeline is
acceptable, as long as all the code relates directly to the object it
is on the timeline OF. Pure code should be parked in the document
class and linked classes. The idea that you should never put code on
the timeline is a relic practice from AS2.)

Randomize Saved movieclips stored on children

I'm having a hard time with some code in actionscript 3.0. I don'y know how to randomize the movieclips stored on child and pick only 8 movieclips wherein there are 10 movieclips stored. I hope you'll be able to help me with this problem. thanks
Here is the code:
//start stage function
this.mainmc.addEventListener (Event.ENTER_FRAME, setupStage1);
this.waitingCounter=0;
//set up current stage
function setupStage1 (e:Event) {
//wait for timeline
if (this.waitingCounter<2) {
this.waitingCounter++;
//not ready yet, do nothing
return;
}
//Start the timer
timer.start();
//hide hint
this.mainmc.hintmc.visible=false;
//hide star animation
this.mainmc.starAnimation.visible=false;
//listener for hint button
this.mainmc.hintbut.addEventListener (MouseEvent.CLICK, showHint1);
//create objects array
this.obArr=[];
//count the objects on stage
for (var n=0; n<this.mainmc.numChildren; n++) {
//get the children
var ob=this.mainmc.getChildAt(n);
//only take movie clips
if (ob is MovieClip) {
//only count the movie clips that have name declared
if (ob.myname!=null) {
//push to array
this.obArr.push (MovieClip(ob));
}
}
}
on the code above, the code will store all the movieclips that are present in the stage. it stores them in a child. each 10 movieclips has a variable name "myname".
If you simply want to randomly sort items within an array, use the array.sort method and within your sort function, simply create a random number between 1 and 2. If it's 1, return true, if it's 2, return false. Here is an actionscript 2 snippet along with a link to a couple of tutorials:
var a:Array = new Array(“a”, “b”, “c”, “d”, “e”);
function shuffle(a,b):Number {
var num : Number = Math.round(Math.random()*2)-1;
return num;
}
var b:Array = a.sort(shuffle);
trace(b);
http://mrsteel.wordpress.com/2007/05/26/random-array-in-as2-as3-example-using-sort/
http://sierakowski.eu/list-of-tips/75-random-sort-function-comes-handy-when-building-applications-with-playlists.html
This is a much longer and more in-depth tutorial:
http://active.tutsplus.com/tutorials/actionscript/quick-tip-how-to-randomly-shuffle-an-array-in-as3/

As3 How to remove or update bitmapdata for a new level?

I'm making a maze game. The character can't walk through the walls of the maze (because of a collition detection between the bitmapdata from the character and the bmd from the walls). When the character arrives at a door, the next level/frame should appear with a new maze (new bounds)
For the next level (next frame), I made a new maze with different walls. But the bitmapdata from the first maze is still 'active'. So even though there's a new maze, the bitmapdata from the previous walls is invisible but still drawn on the stage.
My question to you is:
I want to change the bounds/maze every frame, how can I remove the previous bitmapdata so the character won't walk through the bounds of the next maze? Or is it possible to make an array from the different 'bounds'?
stop();
var isRight:Boolean=false;
var isLeft:Boolean=false;
var isUp:Boolean=false;
var isDown:Boolean=false;
var speed:int = 10;
var mazeRect:Rectangle = bounds.getBounds(this);
var charRect:Rectangle = char.getBounds(this);
var boundsBmpData = new BitmapData(mazeRect.width, mazeRect.height, true, 0);
var charBmpData = new BitmapData(charRect.width, charRect.height, true, 0);
boundsBmpData.draw(bounds);
charBmpData.draw(char);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, moving);
function keyPressed(event:KeyboardEvent):void
{
if(event.keyCode==39){
isRight=true}
if(event.keyCode==37){
isLeft=true}
if(event.keyCode==38){
isUp=true}
if(event.keyCode==40){
isDown=true}
}
function keyReleased(event:KeyboardEvent)
{
if(event.keyCode==39){
isRight=false}
if(event.keyCode==37){
isLeft=false}
if(event.keyCode==38){
isUp=false}
if(event.keyCode==40){
isDown=false}
}
function moving(e: Event): void
{
var newx: Number = char.x - (isLeft ? speed : 0) + (isRight ? speed : 0);
var newy: Number = char.y - (isUp ? speed : 0) + (isDown ? speed : 0);
if(!boundsBmpData.hitTest(new Point(bounds.x, bounds.y),
255,
charBmpData,
new Point(newx, newy),
255))
{
char.x = newx;
char.y = newy;
}
if(char.hitTestObject(door))
{
onHitTest();
}
}
function onHitTest() : void
{
nextFrame();
}
Maybe try calling dispose() on old BitmapData first and then create new one?
After looking at the FLA, there were a few issues.
the main one is that though you switched frames, you did not reset your pointers to the bounds object, the door object, and the char object. So you were still tied to the old ones programmatically, though not visually.
I put the declarations into a method called setupFrame(), and call it from your onHitTest() method.
I added a check in onHitTest() to make sure that the bounds object exists in the current frame before setting up the frame. If not, the game stops.
The actions and char layers now extend across the entire game timeline, since they are reused.
char object is now repositioned each frame using points found in the startPts array, instead of having to recreate it each time.
removed the event listeners during the frame setup, and add them at the end of the frame setup. This prevents possible errors from listening to the events.
This is a pretty good effort at creating a simple game engine. Just fyi, gamedev.stackexchange.com is a place devoted to all levels of game development, and you can ask more theoretical questions there.
HTH!