variable in class not returning updated value - actionscript-3

I'm relatively new to actionscript 3, and this one has me stumped. Here's my class;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Clicker extends MovieClip {
public var clicks:uint;
public var string:String;
public function Clicker() {
// constructor code
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
addEventListener(Event.ADDED_TO_STAGE, alignCentre);
string = "clicks: ";
clicks = 5; // I can change it here
}
public function clicked(e:MouseEvent):void{
clicks++;
trace(clicks); // it outputs updated value here
}
public function alignCentre(e:Event):void{
x = stage.stageWidth / 2 - width/2;
y = stage.stageHeight / 2 - height/2;
}
public function addedToStageHandler(e:Event):void{
this.stage.addEventListener(MouseEvent.CLICK, clicked);
}
public function get_clicks():uint{
trace(clicks); // gives me whatever I initialise it to in the constructor
return clicks;
}
}
}
I want to return the value of clicks from my Clicker class, but the value remains whatever I set it to in the constructor within get_clicks(), and I'm not sure why.
The variable has class scope, so why would it return the default value (in this case, 5) of clicks from get_clicks()? my clicked() method traces the correctly updated value. Is it a scope issue? I'm very confused.
This is my first frame where I create the object;
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import flash.text.TextField;
var clicks:TextField = new TextField();
var circle:Clicker = new Clicker();
clicks.text = circle.get_clicks().toString();
trace(circle.get_clicks());
addChild(circle);
addChild(clicks);
As you'd expect from the problem I'm having, trace spits out 5 over and over, and Clicks doesn't change from 5.
Edit:
There was a mistake, but fixing it has caused clicks not to update at all. I had a library version of the movieclip on my first frame rather than adding the object to the frame with addChild. Now that I've added circle, clicks does not update as my clicked() method isn't being triggered when I click my object.

Resolved:
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import flash.text.TextField;
var clicks:TextField = new TextField();
var circle:Clicker = new Clicker();
var myTimer:Timer = new Timer(100,0);
myTimer.addEventListener(TimerEvent.TIMER, timerListener);
function timerListener (e:TimerEvent):void{
trace("Timer is Triggered");
trace(circle.get_clicks());
clicks.text = circle.get_clicks().toString();
addChild(circle);
addChild(clicks);
}
myTimer.start();
Rather than use the timeline and frames, I wrapped the code I wanted to repeat in a timer listener. Works exactly as intended.

Related

Unable to addChild on MouseCoordinations

What i am trying to do is, to place a new tower each time on MouseX and MouseY. but it seems it isn't working Any Idea guys?
or if you can create a tileMap array and add new child of PrototypeTower each time when we click on the Tower (on x=50, y=400) to select and place wherever we want. When i click the the box at x=50, y=400, the startDrag() doesn't work.
Main.as
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.ui.Mouse;
public class Main extends Sprite
{
private var pTower:PrototypeTower = new PrototypeTower;
private var zTower:PrototypeTower = new PrototypeTower;
private var fTower:PrototypeTower = new PrototypeTower;
public function Main()
{
pTower.x = 50;
pTower.y = 400;
addChild(pTower);
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
pTower.addEventListener(MouseEvent.CLICK, onClicked);
}
private function onClicked(e:Event):void
{
removeEventListener(MouseEvent.CLICK, onClicked);
zTower.x = mouseX;
zTower.y = mouseY;
addChild(zTower);
zTower.startDrag();
addEventListener(MouseEvent.CLICK, onPlaced);
}
private function onPlaced(e:Event):void
{
removeEventListener(MouseEvent.CLICK, onPlaced);
zTower.stopDrag();
fTower.x = mouseX
fTower.y = mouseY;
addChild(fTower);
}
}
}
PrototypeTower.as
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class PrototypeTower extends MovieClip
{
public function PrototypeTower()
{
this.graphics.beginFill(0x00FF00);
this.graphics.drawRect(this.x, this.y, 20, 20);
this.graphics.endFill();
}
}
}
Thank you, i am totally noob, wondering around from days!
Sorry this is just a schematic for now. I'll try to refine it later if you need. Hopefully this clears some things up for you though
When you click the tower, add a new tower at the x,y of the mouse and do some sort of startDrag(tower) on the new tower you just added. Then when you click on the stage, stop the drag and set the new X,y
edit
You might try getting rid of all your removeEventListener calls
I think your problem is you are removing the event listener that gets added in your main function. Keep in mind that the main function (class constructor) for the document class only gets called once, so you add an event listener for ADDED_TO_STAGE only once, and then you remove it the first time you try to add anything to the stage, and you never put it back. Just don't remove it in the first place.
You are calling zTower.startDrag() before you add it to the stage. Do addChild(zTower) and then zTower.startDrag()

How to define that a child should only appear in one scene?

We are making an space impact game. Here are 3 of our classes. Our problem is that when we create our InimigoNoite, they appear all over the game(menus, other levels, etc), instead of only appearing in the Scene that we want. How should we restrict the child to only appear in the CenárioCidade?
We've tried to use gotoandPlay, addChildAt, and also tried to create the Inimigo not in the Main class, but in the Inimigo class itself, but it doesnt appear at all. Please can someone help us? Thank you very much!
KEY.as
package {
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class Key {
private static var initialized:Boolean = false;
private static var keysDown:Object = new Object();
public static function initialize(stage:Stage) {
if (!initialized) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.DEACTIVATE, clearKeys);
initialized = true;
}
}
public static function isDown(keyCode:uint):Boolean
{
return Boolean(keyCode in keysDown);
}
private static function keyPressed(event:KeyboardEvent):void {
keysDown[event.keyCode] = true;
}
private static function keyReleased(event:KeyboardEvent):void {
if (event.keyCode in keysDown) {
delete keysDown[event.keyCode];
}
}
private static function clearKeys(event:Event):void {
keysDown = new Object();
}
}
}
INIMIGO NOITE.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class InimigoNoite extends MovieClip{
var speed:Number;
static var list:Array = new Array();
var balaTimer: Timer;
function InimigoNoite(){
list.push(this);
this.x = 1160;
this.y = 150 + (450-150) * Math.random();
speed = Math.random()*5 + 5;
addEventListener("enterFrame", enterFrame);
var intervalo: Number = Math.random()*500 + 1000;
balaTimer = new Timer(intervalo);
balaTimer.addEventListener("timer", bala);
balaTimer.start();
}
function enterFrame (e:Event){
this.x -= speed;
if(this.x < -100){
matar();
return;
}
if(this.hitTestObject(SpaceImpact.navecnoite)){
matar();
}
}
function matar(){
var explosao = new ExplosaoNoite();
stage.addChild(explosao);
explosao.x = this.x;
explosao.y = this.y;
balaTimer.stop();
balaTimer.removeEventListener("timer",bala);
removeEventListener("enterFrame", enterFrame);
stage.removeChild(this);
for(var i in list){
if(list[i] == this){
delete list[i];
}
}
}
function bala(e:Event){
var b = new BalaInimigo();
b.x = this.x -50;
b.y = this.y;
stage.addChild(b);
}
}
}
MAIN.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class SpaceImpact extends MovieClip{
static var navecnoite:MovieClip;
var inimigoNoiteTimer:Timer;
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
}
}
You never stop the timer. So your inimigo is created and added every 8seconds.
Stop the timer in criaInimigo and/or use the timerComplete Event
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000,1);
inimigoNoiteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
//inimigoNoiteTimer.stop();//only needed if you use the 'timer'-Event
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
Right when you application starts, you are creating a new InimigoNoite every 8 seconds. Since you are adding them to the stage, they will appear over top anything you have on your timeline.
The issue (besides creating them when the application starts and never stopping your timer), is that when you through code use addChild, that child will stay on the screen until it's explicitly removed via removeChild (or one of it's parents are - but since the parent is stage that isn't going to happen).
I see that your have a hit test in the InimigoNoite class that can potentially remove it, but I don't see anywhere else where you remove it (so if the hit test never happens, it will never be removed from the stage regardless of scene).
It seem though that the solution to your problem is more advice on how to architect your application.
Don't use scenes.
Your best bet is to create a class file for each distinct state of your game. So something like this as a basic example:
Main Menu State
Game Play State(either 1 game state that encompasses all levels, or one state for each level - or both - depending on how much functionality changes between levels)
Game Over State
Make your game state class files extend Sprite or MovieClip, and if you want you can even create a new MovieClip in flash pro and attach the class to that (thereby being able to drop visual assets on the timeline).
So then your Main class would just be in charge of managing states (and any anything else that is global to the application)
package{
import flash.display.MovieClip;
import flash.events.Event;
public class SpaceImpact extends MovieClip {
private var menu:Menu; //Assumes you have a Menu.as class file
private var game:MainGame; //MainGame.as file
private var gameOver:GameOver; //GameOver.as file
public function SpaceImpact(){
Key.initialize(stage);
goMenu();
}
public function goMenu(e:Event = null):void {
removeAll();
menu = new Menu();
addChild(menu);
menu.addEventListener(Event.COMPLETE, startGame,false,0,true);
}
private function removeMenu():void {
if(menu){
if(menu.parent) removeChild(menu); //remove it from the screen
menu = null;
}
}
public function startGame(e:Event = null):void {
removeAll();
game = new MainGame();
addChild(game);
game.addEventListener(Event.COMPLETE, gameOver,false,0,true);
}
private function removeGame():void {
if(game){
if(game.parent) removeChild(game); //remove it from the screen
game = null;
}
}
public function gameOver(e:Event = null):void {
removeAll();
gameOver = new GameOver();
addChild(gameOver);
gameOver.addEventListener(Event.COMPLETE, goMenu,false,0,true);
}
private function removeGameOver():void {
if(gameOver){
if(gameOver.parent) removeChild(gameOver); //remove it from the screen
gameOver = null;
}
}
private function removeAll():void {
removeGameOver();
removeMenu();
removeGame();
}
}
}
then, your game state for example:
MainGame.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class MainGame extends MovieClip {
private var inimigoNoiteTimer:Timer;
public function MainGame() {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage, false, 0, true); //don't do anything until this object has been added to the screen
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//start spawning
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
addChild(inimigo);
}
//when whatever happens that makes your game finished
function gameComplete():void {
dispatchEvent(new Event(addEventListener.COMPLETE));
}
}
}

as3 - dispatch mouse event from external class

I am having problems understanding correctly how to dispatch events and capture them in another class.
In this case, I am trying to emulate a mouse click dispatched from an "clickM" class.
On stage I have 2 movieclips to test, a custom cursor and the listeners to capture the click event.
clickM:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event; //dispatcher
import flash.events.MouseEvent;// mouse event
public class clickM extends MovieClip {
private var delay: uint = 3000;
private var repeat: uint = 0; //se va por todo el tiempo
private var myTimer: Timer = new Timer(delay, repeat);
public function clickM() {
myTimer.start();
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
}
private function timerHandler(e: TimerEvent): void {
//repeat--;
//statusTextField.text = ((delay * repeat) / 1000) + " seconds left.";
trace ( "simulate click...");
//dispatchEvent(new MouseEvent(MouseEvent.CLICK));
this.dispatchEvent(new MouseEvent(MouseEvent.CLICK, true, false));
}
}
}
Stage code, rojo & morado are movieclips:
import flash.events.MouseEvent;
stage.addEventListener(Event.ENTER_FRAME, myFunction);
var mano: clickM = new clickM();
mano.name = "mano";
addChild (mano);
morado.addEventListener(MouseEvent.CLICK, cl);
rojo.addEventListener(MouseEvent.CLICK, cl);
stage.addEventListener(MouseEvent.CLICK, cl);
function myFunction(event: Event) {
mano.x = mouseX;
mano.y = mouseY;
}
function cl(e: MouseEvent) {
trace("click over " + e.target.name);
}
If I click over morado or rojo, there's no problem - I can get their names. If I just let the code run, I can't get their names, I just get "mano", which is the custom cursor I'm using.
How can I get the desired behavior?
Regards.
Add mouseEnabled=false; inside clickM constructor. This should make Flash to ignore your mano in the event dispatch phase, so the underlying object should be the primary target if there's any, otherwise the target will be the stage. If your custom cursor contains more movie clips, you should also add mouseChildren=false;.
public function clickM() {
mouseEnabled=false;
// possibly add this too
mouseChildren=false;
myTimer.start();
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
}

AS3 MouseEvent.CLICK Interaction on Different Indexes

I'm currently working through a AS3 game tutorial on Lynda.com and am coming across a problem with the MouseEvent.CLICK and child indexes. The game is a simple point and shoot, where the player must shoot all of the approaching enemies before they get too close. It works initially, however the custom cursor I added displays behind the enemies. However when I try and adjust the index (I've used the addChildAt function and moving the addChild(cursor) line of code below the enemy container initializer) the on click interaction, which is supposed to remove the enemy when clicked on, doesn't work.
My document class:
package {
import flash.display.*;
import flash.utils.*;
import flash.events.*;
import flash.ui.*;
public class Game extends MovieClip {
public var cursor:Cursor;
public var enemy:Enemy;
public var numberOfEnemies:uint;
public var enemyContainer:MovieClip;
public var enemyTimer:Timer;
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, init);
Mouse.hide();
}
public function init(event:Event):void {
cursor = new Cursor;
addChild(cursor);
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragCursor);
numberOfEnemies = 10;
enemyTimer = new Timer(1000, numberOfEnemies);
enemyContainer = new MovieClip();
addChild(enemyContainer);
enemyTimer.addEventListener(TimerEvent.TIMER, createEnemies);
enemyTimer.start();
}
public function dragCursor(event:MouseEvent) {
cursor.x = this.mouseX;
cursor.y = this.mouseY;
}
public function createEnemies(event:TimerEvent):void {
enemy = new Enemy();
enemy.x = 25 + Math.random() * (stage.stageWidth - 75);
enemy.y = 25 + Math.random() * (stage.stageHeight - 75);
enemyContainer.addChild(enemy);
enemy.timerStart();
}
}
}
My enemy class:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.ui.Mouse;
import flash.events.*;
public class Enemy extends MovieClip {
public var scaleObj:Number = 0.50;
public var growTimer:Timer;
public function Enemy() {
scaleX = scaleObj;
scaleY = scaleObj;
addEventListener(MouseEvent.CLICK, shootEnemy);
}
public function timerStart() {
growTimer = new Timer(50);
growTimer.addEventListener(TimerEvent.TIMER, objectGrow);
growTimer.start();
}
public function objectGrow(event:TimerEvent):void {
if(scaleObj <= 1.0) {
scaleObj += 0.01;
scaleX = scaleObj;
scaleY = scaleObj;
}
else {
killEnemy();
}
}
public function killEnemy():void {
this.parent.removeChild(this);
growTimer.stop();
}
public function shootEnemy(event:MouseEvent):void {
killEnemy();
}
}
}
There also is a cursor class, however there is no code beyond the package and class definers. Please let me know of any questions or comments you might have, thanks.
Most likely the Cursor object is intercepting the mouse click since it is above the Enemy object.
You can stop the Cursor from intercepting mouse events by setting in the cursor class:
this.mouseEnabled = false;
this.mouseChildren = false;
Also, you should ideally be using a native mouse cursor instead of manually creating your own. Check out this Adobe tutorial for an example.
Set your Cursor instance to not receive mouse events itself as it would block the click events from getting to the objects behind it. Code would be something like
cursor = new Cursor;
cursor.mouseEnabled = false;
cursor.mouseChildren = false;

as3 - how to add multi custom class into one asset?

I'm a new mem of as3. Today i make a work but i was stacked. pls help me:
My example:
• I have a Symbol in Library with linkage name: box_mc
import flash.display.MovieClip;
import flash.events.Event;
import Src.smoothAnimate;
var box_is:MovieClip = new box_mc();
box_is.name = 'box_na';
addChild(box_is);
var box_is:smoothAnimate = new smoothAnimate(); // ERROR 1151 HERE
• i have a custom class :
package Src
{
import flash.display.*;
import flash.events.Event;
/**
* ...
* #author Trunglvt
*/
public class smoothAnimate extends MovieClip
{
private var currentW:Number;
private var currentH:Number;
private var endX:Number;
private var endY:Number;
private var sp:Number;
function smoothAnimate() {
trace('trace');
}
public function changeSize(speed:Number, newW:Number, newH:Number) {
trace('test');
this.endX = newW; // get new size
this.endY = newH;
this.sp = speed;
this.addEventListener(Event.ENTER_FRAME, onFrame);
}
private function onFrame(e:Event) {
e.target.currentW = e.target.width;
e.target.currentH = e.target.height;
e.target.width += (e.target.endX - e.target.currentW) * e.target.sp;
e.target.height += (e.target.endY - e.target.currentH) * e.target.sp;
if (Math.floor(e.target.width) == Math.floor(e.target.endX) ||
Math.floor(e.target.height) == Math.floor(e.target.endY)) {
//stop function enterFrame here;
removeEventListener(Event.ENTER_FRAME, onFrame);
}
}
}
}
but when run is make error:
1151: A conflict exists with definition box_is in namespace internal.
i want when flash run, the box_is will be add in stage, resize by function changesize.
Pls help me.
Thank you.
When you say:
var box_is:smoothAnimate = new smoothAnimate();
This declaration will error. You previously declared box_is when you said:
var box_is:MovieClip = new box_mc();
Two var cannot have the same name in the same scope.
If you want to reuse the box_is symbol, don't use var. Just reassign box_is:
box_is = new smoothAnimate();