how to pause multiple symbols with mouse click in flash AS3 - actionscript-3

I have been using actionscript 3 to control my animations,
I can play and reset the video but not able to pause globally.
There are totally 3 symbols,
1st Parent movieclip
2nd child moviclip with animation--> I am able to pause this.
3rd child movieclip with animation--> I am unable to pause this
Script
package lib {
import flash.display.MovieClip;
import flash.events.*;
public class Controlstry extends MovieClip {
public function Controlstry() {
// constructor code
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(evt=null)
{
if(video_mc != null)
{
playBtn.addEventListener(MouseEvent.MOUSE_DOWN, playVideo);
pauseBtn.addEventListener(MouseEvent.MOUSE_DOWN, pauseVideo);
replayBtn.addEventListener(MouseEvent.MOUSE_DOWN,replayVideo);
}
}
private function playVideo(evt:MouseEvent)
{
if(video_mc.currentFrame == video_mc.totalFrames)
{
video_mc.gotoAndPlay(2);
}
else
{
video_mc.play();
}
}
private function pauseVideo(evt:MouseEvent)
{
video_mc.stop();
}
private function replayVideo(evt:MouseEvent)
{
video_mc.gotoAndPlay(2);
}
}
}

It's not very clear from your code as to what are the three movie clips which you want to control.
Assuming you have 3 movie clips nested into each other, you can call stop() on each one of them to stop their animation (assuming they have a timeline animation)
So if your structure looks like this : a-->b-->c, where a is the parent, b a child of a, and c a child of b, you can call
a.stop();
a.b.stop();
a.b.c.stop();
This is obviously assuming the fact that you have instance names declared for the child properties in the IDE.
Hope this helps.
EDIT:
As per your sent FLA, you should do the following steps to achieve what you want:
Go inside video_mc on your stage, and select Layer 9, and give it an instance name of 'backgroundMC'.
Modify your script like this:
package lib {
import flash.display.MovieClip;
import flash.events.*;
public class Controlstry extends MovieClip {
public function Controlstry() {
// constructor code
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(evt:Event=null)
{
if(video_mc != null)
{
playBtn.addEventListener(MouseEvent.CLICK, playVideo);
pauseBtn.addEventListener(MouseEvent.CLICK, pauseVideo);
replayBtn.addEventListener(MouseEvent.CLICK,replayVideo);
}
}
private function playVideo(evt:MouseEvent)
{
if(video_mc.currentFrame == video_mc.totalFrames)
{
video_mc.gotoAndPlay(2);
video_mc.backgroundMC.gotoAndPlay(1);
}
else
{
video_mc.play();
video_mc.backgroundMC.gotoAndPlay(1);
}
}
private function pauseVideo(evt:MouseEvent)
{
video_mc.stop();
video_mc.backgroundMC.gotoAndStop(1);
}
private function replayVideo(evt:MouseEvent)
{
video_mc.gotoAndPlay(2);
video_mc.backgroundMC.gotoAndPlay(1);
}
}
}
A couple of things to note here:
Use MouseEvent.CLICK if you want it to respond to click events. You had used MouseEvent.DOWN
Always give events a type like evt:Event and not just evt=null.
if(video_mc != null) can be easily checked by if(video_mc).
Hope this answers the question.

Related

How to make a class file apply an eventhandler to instance or object on main stage asides from itself?

I'm pretty new with ActionScript 3 and I'm stuck with trying to perform the following above in a class file. I tried to look for a solution online, but I can't find a suitable answers, perhaps because I'm not looking for the right search terms, etc.
Anyway, I'm trying to make a basic animation in Adobe Animate CC in an FLA file, "Campfire.FLA", where pressing the mouse down on a Campfire causes a piece of Coal attaching to a levitating stick to glow, and cooldown upon letting go of the mouse button. On the main timeline, I can execute it fine, but I want to transfer the information to a class file/ document file, but to no avail.
The code is what I used on the FLA's main timeline, Frame 1, and it works below works perfectly fine:
stop();
/* Instance names:
Fire = Instance of "FireButton"; simplebutton.
STween = Instance of "Stick Tween"; MovieClip, simple tween animation the object, "MarshmallowStick" moving.
Stick = Instance of "Marshmallow Stick"; MovieClip.
CoalRock = Instance of "Coal"; MovieClip.
*/
Fire.addEventListener(MouseEvent.MOUSE_DOWN, RockHot)
function RockHot(e: MouseEvent): void {
stopPlayReverse();
// Causes Coal and Stick to play their animation upon clicking Fire.
STween.Stick.play();
STween.Stick.CoalRock.play();
}
Fire.addEventListener(MouseEvent.MOUSE_UP, RockCold)
function RockCold(e: MouseEvent): void {
STween.Stick.CoalRock.addEventListener(Event.ENTER_FRAME, playReverse, false, 0, true);
STween.Stick.gotoAndPlay(1);
// Upon letting go of mouse button, it causes the coal to cool down/ play reverse. Stick resets to Frame 1.
}
function playReverse(e: Event): void {
if (STween.Stick.CoalRock.currentFrame == 1) {
stopPlayReverse();
// If Coal is back on Frame 1, it stops.
} else {
STween.Stick.CoalRock.prevFrame();
// If Coal is not on Frame 1 it continues going reverse where it left off.
}
}
function stopPlayReverse(): void {
if (STween.Stick.CoalRock.hasEventListener(Event.ENTER_FRAME)) {
STween.Stick.CoalRock.removeEventListener(Event.ENTER_FRAME, playReverse);
// Stops the function playreverse()
}
}
However, when trying to migrate the information into an ActionScript File I ran into a couple of problems. First I tried making an ActionScript 3 class file for each of the objects above much of the information is blank because I had no idea how to communicate eventhandlers between them. Much of the information for the MovieClips have no information, "MarshmallowStick" is below:
package {
import flash.display.MovieClip;
public class MarshmallowStick extends MovieClip {
public function MarshmallowStick() {
// Empty, no constructor code.
}
}
}
For the "Fire" Class file I tried something like:
package {
import flash.display.*;
import flash.events.*;
import Coal;
public class FireButton extends SimpleButton {
public var CoalRock = Coal;
public function FireButton() {
Coalrock = new Coal ();
this.addEventListener(MouseEvent.CLICK, RockHot)
function RockHot(e: MouseEvent): void {
CoalRock.play();
trace("OK");
trace(CoalRock);
}
}
}
}
However, it turned out that upon testing, The file only appeared to create a new object named CoalRock, and is not related to the one on the mainstage. So clicking the FireButton causes only the new object to play.
I tried making a document class as seen below in a file named "Main.as":
package {
import flash.display.*;
import flash.events.*;
public class Main extends MovieClip {
public var Fire: FireButton;
public var CoalRock: Coal;
public var Stick: MarshmallowStick;
public var STween: StickTween;
public function Main() {
CoalRock = new Coal();
Fire = new FireButton();
Stick = new MarshmallowStick();
/*
addChild(Fire);
addChild(CoalRock);
addChild(Stick);
addChild(STween);
*/
// RIP, well it's pretty much the same code as above. Just without the nested symbols/ objects.
Fire.addEventListener(MouseEvent.MOUSE_DOWN, RockHot)
function RockHot(e: MouseEvent): void {
stopPlayReverse();
//Eye + Emblem glow
Stick.play();
CoalRock.play();
trace("OK");
}
Fire.addEventListener(MouseEvent.MOUSE_UP, RockCold)
function RockCold(e: MouseEvent): void {
CoalRock.addEventListener(Event.ENTER_FRAME, playReverse, false, 0, true);
Stick.gotoAndPlay(1);
}
function playReverse(e: Event): void {
if (CoalRock.currentFrame == 1) {
stopPlayReverse();
} else {
CoalRock.prevFrame();
}
}
function stopPlayReverse(): void {
if (CoalRock.hasEventListener(Event.ENTER_FRAME)) {
CoalRock.removeEventListener(Event.ENTER_FRAME, playReverse);
}
}
}
}
}
But it only turned out that it only affects objects added via the addChild() well as far as I have tested. But the main point of this is for the script to affect objects that already exist on the main stage/ scene.
If you want to see how it plays/ suppose to play out, you can take the main timeline code and paste it into an FLA file with instances of the ones provided.
I don't know how Stack will format it. / / is suppose to be multi-line comments.
That's one elaborate question.
The thing you (probably) need the most is some feudal hierarchy so that objects tend to their own and their direct children, but not deeper and totally not upwards:
Container → (interface method) → Child → (tends to own children)
Container ← (status event) ← Child
Normally, a child must not know of its parent and should communicate with status events. This way you can put such a child into any container with no risk of that child possibly reaching upwards expecting some parent structure that is not there.
So, your problems.
First. Accessing the objects that already exist on the main timeline. Well, the only trick is not to create new ones but to get references to the existing ones.
package
{
// Imports.
public class Main extends MovieClip
{
// If you have an instance of MarshmallowStick with the
// instance name "Stick" on the main timeline,
// you don't need to do anything else.
//
// Default publish settings are to auto-declare
// the main timeline instance into the
// appropriately named variable.
public var Stick:MarshmallowStick;
P.S. Figure the Stick out of Tween by yourself.
Second. To access Coal inside Stick you need to declare an appropriate variable inside the correspondent class. Also, it makes a lot of sense to put the things needed to play things forward and backward as close to the objects they operate as it is possible.
package
{
import flash.events.Event;
import flash.display.MovieClip;
public class MarshmallowStick extends MovieClip
{
// You don't seem to need a separate class for Coal.
// Having it as a regular MovieClip will suffice.
public var Coal:MovieClip;
// Call this to play animation forward.
public function playNormal():void
{
removeEventListener(Event.ENTER_FRAME, onReverse);
gotoAndPlay(1);
Coal.play();
}
// Call this to play animation backward.
public function playReverse():void
{
Coal.stop();
gotoAndPlay(1);
addEventListener(Event.ENTER_FRAME, onReverse);
}
// This method does not need to be seen from the outside
// so declare it as private rather than public.
private function onReverse(e:Event):void
{
if (Coal.currentFrame > 1)
{
Coal.prevFrame();
}
else
{
playNormal();
}
}
// Call this to stop playing into any direction.
public function stopPlaying():void
{
stop();
Coal.stop();
removeEventListener(Event.ENTER_FRAME, onReverse);
}
}
}
Third. Avoid declaring functions inside functions. You can read up what closures are and how to handle them in AS3, but for the time being (and probably for the foreseeable future) you won't need them.
package
{
// Imports.
public class Main extends MovieClip
{
public var Fire:SimpleButton;
public var Stick:MarshmallowStick;
public function Main()
{
Fire.addEventListener(MouseEvent.MOUSE_DOWN, makeHot);
// The rest of the code.
}
function makeHot(e:MouseEvent):void
{
Stick.playNormal();
trace("OK");
}
Fourth. Do not subclass buttons. It is pretty enough to create a simple class-free button and subscribe to its MouseEvent.CLICK or MouseEvent.MOUSE_DOWN events to process all the necessary actions in some place that knows what this buttons is for. I said that above already. Feudal hierarchy. Button should fire an event, then its holder should capture that event and react. The button itself should not know where it is or what its purpose is, even less to try doing things.

Main class was not the first class which was called in ActionScript 3.0

I have a weird problem in a game which I want to create. At first I have created a project without external classes.
On the root I have three Characters and one Level. Also there is a script for the key listeners and I have eventListeners to register the level, levelElements, coins and the characters. Then I have a CharacterControl MovieClip in the library. This MovieClip contains the character behaviour. As example walk, jump, idle, gravity if not colliding to the ground. There are also different events and eventListeners.
The scripts are on the timeline. If I call in both timelines a trace-function, the root was called before the CharacterController.
After that in my next exercise I created a document class Main. Now there are all root scripts. And for the CharacterController I also copied the timeline code and put it into an external class.
Now my problem is that the CharacterController class is called before the main class gets called. This leads to the problem that the eventListener and events can't get called in right order. There are happening a few errors. No Coin and no Character collides on the ground or a plattform. Everything is falling down.
How can I achieve that the Main gets called at first? Should I remove the characters and create them by script?
EDIT:
Ok, I give a short example which shows the basic problem without the complex code of my game.
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
trace("main was called");
}
}
}
package {
import flash.display.MovieClip;
public class My_Circle extends MovieClip {
public function My_Circle() {
// constructor code
trace("circle was called");
}
}
}
Here are some pictures of the configuration and structure of my project:
I need Main called as first. I think it's a basic problem in as3.
You'd make the class file of your stage Main.as in the properties pane.
Edit: Interesting. Just replicated this. I believe then that flash/air constructs elements so they're ready to be put on the stage instead of constructing the stage first and elements after. You should put the code you want to execute for your circle in some sort of init function and execute it in.
package
{
import flash.display.MovieClip;
public class Main extends MovieClip
{
public function Main()
{
super();
trace("Hello");
(circle_mc as Circle).init();
}
}
}
Circle:
package
{
import flash.display.MovieClip;
public class Circle extends MovieClip
{
public function Circle()
{
super();
}
public function init():void
{
trace("World");
}
}
}
ok, I figured out a simple solution how you can make it by code. At first I think it's a better solution to create the object (circle, character, whatever) by code.
The timeline code:
import flash.events.Event;
Main.setStageRef(this.stage); //Super-important
stop();
The Main class code:
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.DisplayObject;
import flash.events.Event;
public class Main extends MovieClip {
public static var stageRef : Object = null;
var movieClipExample : My_Circle;
public function Main() {
this.addEventListener(Event.ENTER_FRAME,this.afterMainTimeLine);
stage.addEventListener("myEvent", myEventFunction);
}
public function afterMainTimeLine(e:Event) {
trace("Hello");
movieClipExample = new My_Circle;
movieClipExample.init();
stageRef.addChild(movieClipExample);
removeEventListener(Event.ENTER_FRAME, this.afterMainTimeLine);
this.addEventListener(Event.ENTER_FRAME,this.updateFunction);
}
public function updateFunction(e:Event){
movieClipExample.moveFunction();
}
public function myEventFunction(_event: Event) {
trace("myEvent was triggered");
}
//Getter/setter for stage
public static function setStageRef(_stage : Object) : void
{
stageRef = _stage;
}
public static function getStageRef() : Object
{
return stageRef;
}
}
}
The Object code (as example My_Circle):
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.DisplayObject;
public class My_Circle extends MovieClip {
public function My_Circle()
{
stageRef = Main.getStageRef();
trace("World");
this.x = x;
this.y = y;
var evt = new Event("myEvent", true);
stageRef.dispatchEvent(evt);
}
public function init():void
{
trace("Created Circle");
this.x = 300;
this.y = 100;
}
function moveFunction(){
this.y += 1;
}
}
}
The output is following:
Hello
World
myEvent was triggered
Created Circle
Maybe this could be helpful for others.
Just one thing. For different objects from the same class it's better to use an array. The position (maybe) should be random.

AS3: class not functioning properly

Sorry for a blurry title, but this is probably the best way I can describe the issue that seems absurd to me by now.
I need a simple action done by an MC: going to a certain frame. I couldn't get it to work, although I had an exact same type of action done by another Movie Clip in the same class code. Here's how I did it:
if (currentItem.type == "blue") {
guy.gotoAndPlay("blue")
}
Yes, the class I'm referring to ('guy') is extended as a Movie Clip. Again, exact same code works fine with other Clips. I tried another method: switching the frame from the Clip's class, the frame it switches to is defined by a variable which is changed by main class. But somehow, this doesn't work either. It gives me the 1069 error. Here's the code of the 'guy' class:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class guy extends MovieClip
{
public static var gotoer:String = "fffuuu"
public function shaman_armsUp()
{
super();
addEventListener(Event.ADDED_TO_STAGE, init)
}
public function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init)
armLoop()
}
public function armLoop():void {
if (gotoer == "brown") {
this.gotoAndPlay("brown")
}
if (gotoer == "red") {
trace(gotoer)
this.gotoAndPlay("red")
}
}
}
}
Is there anyone who has a logical explanation for this? Can this be caused by a bug?
maybe the code you are writing in the method shaman_armsUp() should be moved to the constructor?
Follow my edited version of your class guy (also, renamed to Guy, follow the class name convention)
package
{
import flash.display.FrameLabel;
import flash.display.MovieClip;
import flash.events.Event;
// renaming the class name (guy to Guy)
public class Guy extends MovieClip
{
// not sure if using an static variable for this case is the best idea, but I decided to keep because I don't know your initial idea
public static var gotoer:String = "fffuuu";
public function Guy()
{
// move the addedToStage event to the constructor
super();
addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
}
public function shaman_armsUp()
{
}
public function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
armLoop();
}
public function armLoop():void
{
// Note: the value of gotoer is "fffuuu" and there is no conditional for it.
// are you chaging this value before calling armLoop? because when the init method is called it has the same value
// why not try something like:
// checking if the frame exist and if so, calling the gotoAndPlay method (try to imagine if you have 100 frame names? the old approach will be very hard to maintain
if (hasFrameLabel(gotoer))
{
this.gotoAndPlay(gotoer);
}
else
{
trace('frame: ', gotoer, ' not found');
}
/*
if (gotoer == "brown")
{
this.gotoAndPlay("brown");
}
if (gotoer == "red")
{
trace(gotoer);
this.gotoAndPlay("red");
}
*/
}
// helper function to avoid calling a frame that doesn't exist
private function hasFrameLabel(frameLabel:String):Boolean
{
var returnValue:Boolean;
const obj:Object = this.currentLabels;
for each (var i:FrameLabel in obj)
{
if (i.name == frameLabel)
{
returnValue = true;
break;
}
}
return returnValue;
}
}
}

Disabling Nested MovieClips After Removing Parent Movieclip

In some of the level MovieClips I have for my Flash game, there is a certain MovieClip that controls a custom-built camera that I've created. Both the camera and the MovieClip function correctly and smoothly. However, whenever a level is completed and removed from the game, I get an Error #1009 not recognizing the checkCameraZoom function. Also, this MovieClip is not added dynamically with code, but rather placed in the specified level MovieClips from the Library before run-time. Is there any possible way to fix this error?
ZoomOutArea Class:
package com.engine.assetHolders
{
import com.engine.documentClass.*;
import flash.display.*;
import flash.events.*;
public class ZoomOutArea extends MovieClip
{
public function ZoomOutArea():void
{
this.visible = false;
this.addEventListener(Event.ADDED_TO_STAGE, initZoomOutArea);
// constructor code
}
public function initZoomOutArea(event:Event):void
{
this.addEventListener(Event.ENTER_FRAME, checkCameraZoom);
}
public function checkCameraZoom(event:Event):void
{
if (Document.getInstance != null)
{
if (this.hitTestObject(MovieClip(parent.parent).player.playerHitArea))
{
this.hitTestZoom(0.6);
}
if (! this.hitTestObject(MovieClip(parent.parent).player.playerHitArea))
{
this.hitTestZoom(1);
}
}
}
public function hitTestZoom(zoomLevel):Number
{
MovieClip(parent.parent).cameraScale = zoomLevel;
return zoomLevel;
}
}
}
You register the class for ENTER_FRAME events when it's added to the stage, but you never unregister it. So that's why it keeps going even after it has been removed from the stage, and has no parent anymore.
You could add another listener for Event.REMOVED_FROM_STAGE and then remove the checkCameraZoom listener:
public function initZoomOutArea(event:Event):void
{
this.addEventListener(Event.ENTER_FRAME, checkCameraZoom);
this.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
}
private function onRemoved(event:Event):void
{
this.removeEventListener(Event.ENTER_FRAME, checkCameraZoom);
}

make a preloader class instead of having it in the document class

I have built a basic preloader that runs in my document class. I'm having trouble with it. I'm guessing its due to what a class can and can not access from the stage?
theres 2 problems. the first is that I cant change the keyframe the stage is on from the class. the second is im getting an error 1009 if I comment that out.
package
{
import flash.display.MovieClip
import flash.events.Event;
import flash.events.ProgressEvent;
public class Pre extends MovieClip
{
public function Pre()
{
loaderInfo.addEventListener(Event.COMPLETE,downloadFin);
loaderInfo.addEventListener(ProgressEvent.PROGRESS,preloadProgress);
function preloadProgress(progressEvent:ProgressEvent):void
{
var floatLoaded:Number=loaderInfo.bytesLoaded/loaderInfo.bytesTotal;
var newW:Number=this.width*floatLoaded;
this.Fill.width=newW;
}
function downloadFin(event:Event):void
{
trace('fin')
//stage.gotoAndStop(3);//frame with game
}
}
}
}
I recommend you to dispatch an event when the preloader is ready, making yor preloader more generic. Then add a listener in the document class like this:
private function setupPreloader() : void
{
preloader.addEventListener(Event.COMPLETE , onPreloaderComplete);
preloader.start();
}
private function onPreloaderComplete(event : Event) : void
{
preloader.removeEventListener(Event.COMPLETE, onPreloaderComplete);
preloader.dispose();
gotoAndStop(3);
}