as3 navigation - gotoAndPlay script not working consistently - actionscript-3

I think I've made an error in logic somewhere but can't find it, I have a movie clip which contains 4 further animated movieclips, each with stop() actions at specific frames, and 2 buttons, 1 to move left and another to move right, the animations work as expected if the user clicks say right, right, right, right, left, left, left, left for the first time, but then things stop evaluating properly.
Am using switch case statements on a variable to pick out the mc to animate, would I be better of using an If Else statement? Heres my code, as may be obvious actionscript is not my forte!
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;
import fl.text.TLFTextField;
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
// Global variables
var mcWidth:int = 768;
var mcPosInc:int = 0;
var boxAnimPlay:int = 1;
var mcMoving:Boolean = false;
var buttonClicked:String = "right";
var mcLeft;
var mcRight;
addEventListener(Event.ENTER_FRAME, frameHandler);
// frame Handler
function frameHandler(event:Event):void
{
// Initialize button click events
controlGrp.bttn_left.addEventListener(MouseEvent.CLICK, goLeft);
controlGrp.bttn_right.addEventListener(MouseEvent.CLICK, goRight);
function goLeft(e:MouseEvent):void {
buttonClicked = "left";
// change position
if (mcPosInc > 0 && mcMoving == false) {
mcMoving = true;
mcPosInc --;
boxAnimPlay --;
// Scroll mc1
mcLeft = new Tween(mc1, "x", Regular.easeOut, mc1.x, mc1.x + mcWidth, 1.5, true);
mcLeft.addEventListener(TweenEvent.MOTION_FINISH, end);
function end(event:TweenEvent) {
mcMoving = false;
}
if (boxAnimPlay >= 1) {
switch (boxAnimPlay) {
case 3:
mc1.box4.gotoAndPlay(17);
mc1.box3.gotoAndPlay(31);
break;
case 2:
mc1.box2.gotoAndPlay(31);
mc1.box3.gotoAndPlay(46);
break;
case 1:
mc1.box1.gotoAndPlay(17);
mc1.box2.gotoAndPlay(46);
break;
}
}
trace(boxAnimPlay);
trace(buttonClicked);
}
}
}
// Play movie tests
function goRight(e:MouseEvent):void {
buttonClicked = "right";
// change position
if (mcPosInc < 3 && mcMoving == false) {
mcMoving = true;
mcPosInc ++;
boxAnimPlay ++;
// Scroll mc1
mcRight = new Tween(mc1, "x", Regular.easeOut, mc1.x, mc1.x - mcWidth, 1.5, true);
mcRight.addEventListener(TweenEvent.MOTION_FINISH, end);
function end(event:TweenEvent) {
mcMoving = false;
}
if (boxAnimPlay <= 4) {
switch (boxAnimPlay) {
case 1:
break;
case 2:
mc1.box1.gotoAndPlay(1);
mc1.box2.gotoAndPlay(1);
break;
case 3:
mc1.box2.gotoAndPlay(16);
mc1.box3.gotoAndPlay(1);
break;
case 4:
mc1.box3.gotoAndPlay(16);
mc1.box4.gotoAndPlay(1);
break;
}
}
trace(boxAnimPlay);
trace(buttonClicked);
}
// Add Text Labels to TitleGroup
switch (boxAnimPlay) {
case 1:
readout.text = "test";
break;
}
}

I fixed it, basically the frames I was targeting in the gotoAndPlay contained stop() statements, once I targeted the subsequent frames, ie
Instead of:
switch (boxAnimPlay) {
case 3:
mc1.box4.gotoAndPlay(17);
mc1.box3.gotoAndPlay(31);
break;
case 2:
mc1.box2.gotoAndPlay(31);
mc1.box3.gotoAndPlay(46);
break;
case 1:
mc1.box1.gotoAndPlay(17);
mc1.box2.gotoAndPlay(46);
break;
}
I used this:
switch (boxAnimPlay) {
case 3:
mc1.box4.gotoAndPlay(17);
mc1.box3.gotoAndPlay(32); // no stop on subsequent frame
break;
case 2:
mc1.box2.gotoAndPlay(32); // no stop on subsequent frame
mc1.box3.gotoAndPlay(47); // no stop on subsequent frame
break;
case 1:
mc1.box1.gotoAndPlay(17);
mc1.box2.gotoAndPlay(47); // no stop on subsequent frame
break;
}

Related

How to display or move sprite in as3 side scroller?

I have a sprite in my library called myRocket but it won't show up.
I made my sprite a movie clip then I deleted it off the actual page so it was just in the library. I thought using this code, the sprite would appear once I started up the game but it does not.
import flash.display.MovieClip;
stop() ;
removeChild(myButton);
var myReturn:Return=new Return();
addChild(myReturn);
myReturn.x=390;
myReturn.y=10;
myReturn.addEventListener(MouseEvent.CLICK, return1Function);
var up:Boolean;
var down:Boolean;
var left:Boolean;
var right:Boolean;
var speed:int;
function return1Function(evt:MouseEvent):void{
gotoAndStop("menu");
}
var myRocket:MovieClip;
addChild(myRocket);
myRocket.x=200;
myRocket.y=150;
function KeyboardDemo() {
myRocket.x = 200;
myRocket.y = 100;
addChild(myRocket);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressedDown);
}
function keyPressedDown(event:KeyboardEvent):void {
var key:uint = event.keyCode;
var step:uint = 5
switch (key) {
case Keyboard.LEFT :
myRocket.x -= step;
break;
case Keyboard.RIGHT :
myRocket.x += step;
break;
case Keyboard.UP :
myRocket.y -= step;
break;
case Keyboard.DOWN :
myRocket.y += step;
break;
}
}
You need to initialize your object before you place it to the stage. You have only declared a variable at the line "var myRocket:MovieClip;" instead it should at least (not sure about whatever logic you have there" read like above with "Return" whatever it was: var myRocket:MovieClip=new Rocket(); Here "Rocket" is the library name of the sprite.

Why is in my code a delay when it tries to display an object (AS3)?

I recently wrote down a flash programm using as3. In the Main class for the project I have an addChild method that is giving me some problems. The thing is that, when I run the movie and the child is supposedly displayed on the stage, there is a big delay in time before the image is rendered.
Here is the code in the Main class: (exact code lines below)
package code {
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.display.Graphics;
import code.particles.*;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.TextField;
// import this to access to the particles
public class Main extends MovieClip {
// set player vars
public var player1:Player;
public var player2:Player;
public var ball:Ball;
// set pause vars
public var pauseParticle:Particle2; // var used for the pause visual effects
public var pauseEffectMC:MovieClip = new MovieClip(); // var used for the pause visual effects
public var gameIsPaused:Boolean;
// set buff vars
public var buffTimer:Timer = new Timer(10000, 0);
public function Main() {
// constructor code
if (stage) init(); // init function
else addEventListener(Event.ADDED_TO_STAGE, init);
}
// init function:
public function init():void
{
// set movieClip class vars
player1 = new Player(stage, 75, 200); // important values: (stage, and two numbers for position)
player2 = new Player(stage, 650, 200); //same for player two
ball = new Ball(stage); // same for the ball
pauseParticle = new Particle2(stage, stage.stageWidth/2, stage.stageHeight/2);
// define movie clips (calling a function)
definePauseEffectMC();
// start timer
buffTimer.start();
// important: add childs (create the visuals)
stage.addChild(player1);
stage.addChild(player2);
stage.addChild(ball);
// add event listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyIsPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyIsReleased);
stage.addEventListener(Event.ENTER_FRAME, entFrame);
buffTimer.addEventListener(TimerEvent.TIMER, buffClock);
}
// constant function
public function entFrame(e:Event):void
{
ball.ballRotation(player1, player2); // call the function for movement in the ball class
ball.ballReset();
}
// key handlers function
public function keyIsPressed(e:KeyboardEvent):void
{
switch(e.keyCode) //key cases:
{
/* player 1:
*/
case 65: // a key
player1.left = true; // change values for vars inside player1
break;
case 68: // d key
player1.right = true;
break;
case 87: // w key
player1.up = true;
break;
case 83: // s key
player1.down = true;
break;
/* player 2:
*/
case 37: // left arrow
player2.left = true; // change values for vars inside player2
break;
case 39: // right arrow
player2.right = true;
break;
case 38: // up arrow
player2.up = true;
break;
case 40: // down arrow
player2.down = true;
break;
/* pause button
*/
case 32: // spacebar button
pauseGame();
break;
}
}
public function keyIsReleased(e:KeyboardEvent):void
{
switch(e.keyCode) //key cases:
{
/* player 1:
*/
case 65: // a key
player1.left = false; // change values for vars inside player1
break;
case 68: // d key
player1.right = false;
break;
case 87: // w key
player1.up = false;
break;
case 83: // s key
player1.down = false;
break;
/* player 2:
*/
case 37: // left arrow
player2.left = false; // change values for vars inside player2
break;
case 39: // right arrow
player2.right = false;
break;
case 38: // up arrow
player2.up = false;
break;
case 40: // down arrow
player2.down = false;
break;
}
}
// function to pause the game
public function pauseGame():void
{
if(gameIsPaused == false)
{
gameIsPaused = true; // revert boolean
buffTimer.stop();
ball.timer.stop();
stage.addChild(pauseEffectMC); // add the effect
stage.addChild(pauseParticle); // add the pause symbol
trace("Paused");
stage.frameRate = 0;
}
else
{
gameIsPaused = false; // revert boolean
buffTimer.start();
ball.timer.start();
stage.removeChild(pauseEffectMC); // remove the effect
stage.removeChild(pauseParticle); // remove the pause symbol
trace("Continue");
stage.frameRate = 60;
}
}
// function to define the pause effect mc
public function definePauseEffectMC():void
{
pauseEffectMC.graphics.beginFill(0x000000); // fill with color (black)
pauseEffectMC.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
pauseEffectMC.alpha = 0.6 // change the alpha
pauseEffectMC.graphics.endFill();
}
/* Buffs
*/
//
public function buffClock(e:TimerEvent):void
{
var buffOn:Boolean = randBoolean(0.3);
if(buffOn == true)
{
var buff:Buff = new Buff(stage, ball, player1, player2);
stage.addChild(buff);
}
}
// random boolean with probability (to get "true" in return) ("prob" must be between 0 and 1)
public function randBoolean(prob:Number):Boolean
{
var randNum:Number = Math.random(); // get a random number between 0 and 0.99
if(randNum <= prob)
{
return(true);
}
else
{
return(false);
}
}
}
}
And here is the exact code that is giving me problems:
// function to pause the game
public function pauseGame():void
{
if(gameIsPaused == false)
{
gameIsPaused = true; // revert boolean
buffTimer.stop();
ball.timer.stop();
stage.addChild(pauseEffectMC); // add the effect
stage.addChild(pauseParticle); // add the pause symbol
trace("Paused");
stage.frameRate = 0;
}
else
{
gameIsPaused = false; // revert boolean
buffTimer.start();
ball.timer.start();
stage.removeChild(pauseEffectMC); // remove the effect
stage.removeChild(pauseParticle); // remove the pause symbol
trace("Continue");
stage.frameRate = 60;
}
}
// function to define the pause effect mc
public function definePauseEffectMC():void
{
pauseEffectMC.graphics.beginFill(0x000000); // fill with color (black)
pauseEffectMC.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
pauseEffectMC.alpha = 0.6 // change the alpha
pauseEffectMC.graphics.endFill();
}
I tried different things, but I did not find a solution. I have run the programm in another computer, but it is still having a delay.
I just wanted to know if there is something wrong with my code that I have to modify, or if it is a flash error.
Thank you for reading.
~m5

How can I press keyboard to play vdo only once

I'm here again for your help :{ I have a question which I tried to google it but can't find the answer. Well,..May be there is an answer but I just can't make it works? I'm in a process of learning AS3 so let's say I'm still new here.
What I'm doing is making a keyboatd to respond with the vdo files I have. It is a very simple idea as press-n-play. Each keys has their vdos to play and if you press another button while the first one is still pressing, it'll play another vdo of its key. I have make this as boolean with function of keydown and keyup like this:
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.net.NetStream;
import flash.net.NetConnection;
import flash.media.Video;
var isLeft:Boolean = false;
var isRight:Boolean = false;
var video;
var nc;
var ns;
stage.addEventListener(KeyboardEvent.KEY_DOWN,onDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onUP);
this.addEventListener(Event.ENTER_FRAME,playVid);
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.client = this;
video = new Video(550,400);
addChild(video);
video.attachNetStream(ns);
function onDown(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case 37 :
//ns.play(TomAndJerry.flv);
isLeft=true;
break;
case 39 :
//ns.play(westler.flv);
isRight = true;
break;
}
}
function onUP(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case 37 :
isLeft = false;
break;
case 39 :
isRight = false;
break;
}
}
function playVid(e:Event):void
{
if (isLeft)
{
trace(kk);
ns.play(westler.flv);
isLeft = false;
}
else if (isRight)
{
trace(PP);
ns.play(TomAndJerry.flv);
//isRight = false;
}
}
I have tried making a keydown function without using any boolean or those true of false things to just play a vdo. It worked but, I still have the same problem that I can't find a solution which is ....
When you hold down the keyboard button the vdo will keep start at the beginning.
All I want is to play the vdo even the key is press down. If the vdo ends then play again as loop but if the key is up the vdo will play until it ends.
And if there are more than one button are holding down just play the vdo of the lastest pressed button.
T-T"
Thanks.
Ps. I have tried removeEventListener but, it made every buttons' function gone.
your playvid function is called each frame so i think it's normal your video don't start, I think you could try to change your code as follow:
// add net status handler event to check the end of the video
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
// remove this line
//this.addEventListener(Event.ENTER_FRAME,playVid);
/** a key is pressed **/
function onDown(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.LEFT:
// start the video just if the video don't play
if(!isLeft) ns.play("TomAndJerry.flv");
// video left is playing
isLeft = true;
// video right isn't playing
isRight = false;
break;
case Keyboard.RIGHT:
// start the video just if the video don't play
if(!isRight) ns.play("westler.flv");
// video rightis playing
isRight = true;
// video left isn't playing
isLeft = false;
break;
}
}
/** a key is released **/
function onUP(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.LEFT:
isLeft = false;
break;
case Keyboard.RIGHT:
isRight = false;
break;
}
}
/** net status change, verify if we reach the end of the video **/
function netStatusHandler(e:NetStatusEvent):void
{
// when netStatus code is NetStream.Play.Stop the video is complete
if (e.info.code == "NetStream.Play.Stop")
{
// right key is still pressed we loop the video
if( isRight ) ns.play("westler.flv");
// left key is still pressed we loop the video
else if( isLeft ) ns.play("TomAndJerry.flv");
}
}
I hope this will help you :)

Continuos Timer and object for a game AS3

I am currently working on a game where you need to survive as long as possible while dodging questions that come your way. (all with AS3)
At the moment I am going from 1 scene to another in between the game field and the question field, but everytime I go to the question scene the timer in the game scene resets itself. I was wondering if it was possible to have the timer continue while being in the question scene?
Also I have a movable character in between the menus which incidentally are also made in different scenes and the player is able to move him around, and I would very much like him to stay in the last position he was in the next screen, as in I move him to the top right in the main menu and when I go to the options menu I want him to still be in the top right and not in his initial position.
As for my timer this is the code I am using at the moment:
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.globalization.DateTimeFormatter;
var timer:Timer = new Timer(100);
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerTickHandler);
var timerCount:int = 0;
function timerTickHandler(Event:TimerEvent):void
{
timerCount += 100;
toTimeCode(timerCount);
}
function toTimeCode(milliseconds:int) : void {
//create a date object using the elapsed milliseconds
var time:Date = new Date(milliseconds);
//define minutes/seconds/mseconds
var minutes:String = String(time.minutes);
var seconds:String = String(time.seconds);
var miliseconds:String = String(Math.round(time.milliseconds)/100);
//add zero if neccecary, for example: 2:3.5 becomes 02:03.5
minutes = (minutes.length != 2) ? '0'+minutes : minutes;
seconds = (seconds.length != 2) ? '0'+seconds : seconds;
//display elapsed time on in a textfield on stage
timer_txt.text = minutes + ":" + seconds+"." + miliseconds;
}
And my character is using this code:
/* Move with Keyboard Arrows
Allows the specified symbol instance to be moved with the keyboard arrows.
Instructions:
1. To increase or decrease the amount of movement, replace the number 5 below with the number of pixels you want the symbol instance to move with each key press.
Note the number 5 appears four times in the code below.
*/
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var leftPressed:Boolean = false;
var rightPressed:Boolean = false;
rutte.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed);
function fl_MoveInDirectionOfKey(event:Event)
{
if (upPressed)
{
rutte.y -= 5;
}
if (downPressed)
{
rutte.y += 5;
}
if (leftPressed)
{
rutte.x -= 5;
rutte.scaleX = 1; // face left
}
if (rightPressed)
{
rutte.x += 5;
rutte.scaleX = -1; // face right
}
}
function fl_SetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = true;
break;
}
case Keyboard.DOWN:
{
downPressed = true;
break;
}
case Keyboard.LEFT:
{
leftPressed = true;
break;
}
case Keyboard.RIGHT:
{
rightPressed = true;
break;
}
}
}
function fl_UnsetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = false;
break;
}
case Keyboard.DOWN:
{
downPressed = false;
break;
}
case Keyboard.LEFT:
{
leftPressed = false;
break;
}
case Keyboard.RIGHT:
{
rightPressed = false;
break;
}
Thank you in advance for all the help you can give me.
Kind Regards.
in flash there is a fundamental aspect of how timeline and scenes works. Once you move away from a frame to another frame, The content of the frame and it's properties/states/actions are gone and reseted.
Personally I recommend you use a single scene with a timeline divided into frames labeled, there you can specify a layer for the actions and global variables, one for the user interface and another one for the specific actions of each frame. example:
So you never lose the reference of variables because the frame is not constantly recreated, all your important actions, including you timer, should be in your first frame.
I was testing, here you can see a working example: http://db.tt/FZuQVvt3. Here you can download the FLA file to be used as a base for your project: http://db.tt/RHG9G5lo

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. AS3

i'm trying to make a space invaders type game with bullets shooting and ships crashing into one another using the hitTestObject function but i can't get the removeChild(); function to work without the Error above. Here's the Code what should i do.
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.MovieClip;
var count:int = 1;
//adding the components
var NewBullet:MovieClip = new Bullet;
var Ship_M:MovieClip = new Ship;
Ship_M.x = 270;
Ship_M.y = 470;
addChild(Ship_M);
var Ship_E:MovieClip = new E_Ship;
Ship_E.x = 270;
Ship_E.y = 5;
addChild(Ship_E);
stage.addEventListener(Event.ENTER_FRAME , Rec);
function Rec(e:Event):void{
if (NewBullet.hitTestObject(Ship_E))
{
removeChild(Ship_E);
removeChild(NewBullet);
}
if (Ship_E.hitTestObject(Ship_M))
{
removeChild(Ship_E);
removeChild(Ship_M);
}
}
function Moves(e:Event):void{
NewBullet.y -= 30;
if (NewBullet.y < 0 )
{
removeChild(NewBullet);
count++;
removeEventListener(Event.ENTER_FRAME, Moves);
}
trace (count);
}
//For Moving the Spaceship
stage.addEventListener(KeyboardEvent.KEY_DOWN, Move);
function Move (event:KeyboardEvent):void{
switch(event.keyCode)
{
case 37:
if (Ship_M.hitTestObject(Stop_L1))
{
Ship_M.x -= 0;
}
else
{
Ship_M.x -= 10;
}
break;
case 38:
if (Ship_M.hitTestObject(Stop_U1))
{
Ship_M.x -= 0;
}
else
{
Ship_M.y -= 10;
}
break;
case 39:
if (Ship_M.hitTestObject(Stop_R1))
{
Ship_M.x -= 0;
}
else
{
Ship_M.x += 10;
}
break;
case 40:
if (Ship_M.hitTestObject(Stop_D1))
{
Ship_M.x -= 0;
}
else
{
Ship_M.y += 10;
}
break;
case 32:
addChild(NewBullet);
NewBullet.x = Ship_M.x;
NewBullet.y = Ship_M.y;
addEventListener(Event.ENTER_FRAME, Moves);
break;
default:
}
}
Replace yours
removeChild(SomeSprite);
with
if (SomeSprite.parent)
SomeSprite.parent.removeChild(SomeSprite);
An objects parent can only call removeChild.
You may not need this in your particular circumstance, but I have a helper function to remove a child and make it eligible for GC which goes like so:
private function remove(child:DisplayObject):void
{
if(child && child.parent)
{
child.parent.removeChild(child);
child = null;
}
}
Most likely you do removeChild(NewBullet) twice, first when it hits Ship_E and second when it leaves boundary. A simple solution will be whenever your NewBullet is removed from stage, set it a flag, say "enabled" which would mean the bullet can trigger events, and check it throughout your code whenever you have to check for the bullet.
Note, you have only one bullet, is it normal?