Unable to addChild on MouseCoordinations - actionscript-3

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()

Related

How to loop background music while end game conditions are not met in ActionScript 3?

I am fairly new to action script and need to know how to loop BG music. I know other languages you could do something like
while(!endGame){
sound.play();
}
but I can't seem to find the syntax for how to do this in AS, or maybe there is a better way? It's a 7 second clip so I need it to continue to loop until end conditions are met.
AS3 provides two methods to deal with this. The most straightforward is telling the play command the number of times you want a sound to repeat using it's loops parameter.
https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play()
The second method - which gives you more control - is a bit more complicated. Basically you're starting the sound and add a listener which monitors playback of the sound. If it finished playing a SOUND_COMPLETE event will fire and it's callback function can restart the playback.
To give you an example:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
public class Main extends Sprite
{
private var sound:Sound;
private var soundChannel:SoundChannel;
public function Main():void
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
sound = new Sound();
var urlRequest:URLRequest = new URLRequest("sound.mp3");
sound.load(urlRequest);
soundChannel = sound.play();
soundChannel.addEventListener(Event.SOUND_COMPLETE, soundFinished);
}
public function soundFinished(event:Event):void
{
soundChannel.removeEventListener(Event.SOUND_COMPLETE, soundFinished);
soundChannel = sound.play();
soundChannel.addEventListener(Event.SOUND_COMPLETE, soundFinished);
}
}
}

Unable to stop spawning an enemy

Okay so here's the dealio.
The code below is what I use to spawn a single enemy periodically in my horror game. He spawns at the window every 10 seconds, then every 6 seconds later, he enters the room and you're essentially dead already, because 5 seconds after that you get a lovely jumpscare. The moment the enemy shifts from the window to the bedroom is when I want the window enemy to stop spawning.
EnemyShipTimer is the timer that spawns the enemy.
enemyTimer is the timer that counts how long the enemy has been at
the window, and then in the room.
In the main file, I've attempted to get rid of the enemy a number of ways, to no effect.
So function gtfo is my latest attempt at removing the enemy, by trying to stop the spawning from the class file itself. It still hasn't worked. Maybe I need to somehow remove the class file from my game, but I have no idea how. Please help! ;A;
PS, countClick counts how many clicks you've done to make the enemy go away, although when I make him go away, room enemy still spawns :c
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.events.TimerEvent;
import flash.text.TextField;
public class EnemyShip extends MovieClip
{
private var clickCount:int = 0;
private var enemyShipTimer:Timer;
private var enemyTimer:Timer;
public function EnemyShip()
{
this.x = 900;
this.y = 214;
addEventListener(MouseEvent.CLICK, addClick);
addEventListener(MouseEvent.CLICK, countclick);
addEventListener(TimerEvent.TIMER, gtfo);
}
function gtfo(e:TimerEvent):void{
if (enemyTimer.currentCount==5)
enemyShipTimer.stop();
stage.removeChild(this);
}
function addClick(event:MouseEvent):void
{
clickCount = clickCount + 1;
trace("Clickage : " + clickCount);
}
function countclick(event:MouseEvent):void
{
if (clickCount ==4)
{
stage.removeChild(this);
}
}
}
}
The following is the relevant main timeline code that may be clashing with the code (I have updated the package class as per #Karma 's helpful instructions c: though the enemy still spawns; I think what the problem is now is that the timer functions clash with timer functions I've put in my main timeline, and I attempted to sort of move them into the package class but I don't know how to add the necessary movieclips so that I won't get access of undefined property errors so I separated the two once more
enemy is the window spawning enemy.
mosnta is the room spawning enemy.
sod is the screen of death (game over screen) which does not play at all.
var enemyShipTimer:Timer;
function sendEnemy(e:Event)
{
var enemy = new EnemyShip();
stage.addChild(enemy);
var enemytimer = new Timer (1000, count);
enemytimer.start();
enemyShipTimer = new Timer(10000);
enemyShipTimer.addEventListener("timer", sendEnemy);
enemyShipTimer.start();
enemytimer.addEventListener(TimerEvent.TIMER, countdowndesu);
function countdowndesu(e:Event):void{
if (enemytimer.currentCount>5){
trace("ur ded");
enemytimer.removeEventListener(TimerEvent.TIMER, countdowndesu);
mosnta.visible=true;
enemy.visible=false;
if (enemytimer.currentCount==8){
sod.visible=true;
sod.gotoAndPlay(2);
}
}
}
}
Not really understanding the dynamics of how your game works, but here's an altered version of your code with working Timers. Maybe this will help you figure out how to fix your issues
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class EnemyShip extends MovieClip
{
private var clickCount:int = 0;
private var enemyShipTimer:Timer;
private var enemyTimer:Timer;
public function EnemyShip()
{
this.x = 900;
this.y = 214;
//only need one click handler
addEventListener(MouseEvent.CLICK, addClick);
//Instantiate Timers
enemyShipTimer = new Timer(10000); //10 seconds
enemyTimer = new Timer(6000); //6 seconds
//add TimerEvent listeners onto Timer Objects
enemyShipTimer.addEventListener(TimerEvent.TIMER, gtfo);
enemyTimer.addEventListener(TimerEvent.TIMER, enemyTimerHandler);
//Start the timers
enemyShipTimer.start();
enemyTimer.start();
}
//This gets called every 10 seconds
private function gtfo(e:TimerEvent):void
{
trace("enemy spawns at window");
if (enemyTimer.currentCount == 5) {
enemyShipTimer.stop();
stage.removeChild(this);
}
}
//This gets called every 6 seconds
private function enemyTimerHandler(e:TimerEvent):void
{
trace("enemy moves to room");
}
private function addClick(event:MouseEvent):void
{
clickCount ++;
trace("Clickage : " + clickCount);
if (clickCount == 4)
{
stage.removeChild(this);
}
}
}
}

making a symbol move by keyboard not showing result and when published it not reads stop(); but replays it again and again

I am new to actionscript ,
My document class is ,
package
{
//list of our imports these are classes we need in order to
//run our application.
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class engine extends MovieClip
{
// moved ourShip to a class variable.
private var Circle:circle = new circle()
//our constructor function. This runs when an object of
//the class is created
public function engine()
{
addFrameScript(0, frame1);
addFrameScript(1, frame2);
}
// frame 1 layer 1 --------------------------------------------------
public function frame1()
{
stop();
}
//-------------------------------------------------------------------
// frame 2 layer 1 --------------------------------------------------
public function frame2()
{
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
//-------------------------------------------------------------------
}
}
i made two frames first contains button and the other circle which i want to move but it not moves and it stays in the middle on second frame
My button class is
package
{
//imports
import flash.events.MouseEvent;
import flash.display.SimpleButton;
import flash.display.MovieClip;
//-------
public class start extends SimpleButton
{
public function start()
{
addEventListener(MouseEvent.CLICK, onTopClick);
addEventListener(MouseEvent.MOUSE_OVER, onBottomOver);
}
function onTopClick(e:MouseEvent):void
{
MovieClip(root).gotoAndStop(2)
}
function onBottomOver(e:MouseEvent):void
{
}
}
}
And my as of circle movieclip is
package
{
//imports
import flash.display.MovieClip;
import flash.display.Stage;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class circle extends MovieClip
{
private var speed:Number = 0.5;
private var vx:Number = 0;
private var vy:Number = 0;
private var friction:Number = 0.93;
private var maxspeed:Number = 8;
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
x+=vx;
y+=vy
}
function keyHit(event:KeyboardEvent):void {
switch (event.keyCode) {
case Keyboard.RIGHT :
vx+=speed;
break;
case Keyboard.LEFT :
vx-=speed;
break;
case Keyboard.UP :
vy-=speed;
break;
case Keyboard.DOWN :
vy+=speed;
break;
}
}
}
}
I am sorry to post so much for you guys to read but stackoverflow is the only website where anyone helps me !
You have made several major errors. First, addFrameScript() isn't a proper way to place code on frames, use Flash's editor to place code on timeline. (IIRC you will have to make a single call out of your two in order to have all the code you add to function) And, whatever code you added to a frame of a MC is executed each frame if the MC's currentFrame is the frame with code. Thus, you are adding a function "frame2()" that places the Circle in the center of the stage each frame! You should instead place it at design time (link it to a property) into the second frame, or in a constructor, or you can use one single frame and Sprite instead of MovieClip, and instead of using frames you can use container sprites, adding and removing them at will, or at an action.
The other major mistake is adding an event listener inside an enterframe listener - these accumulate, not overwrite each other, so you can have multiple functions be designated as listeners for a particular event, or even one function several times. The latter happens for you, so each frame another instance of a listening keyHit function is added as a listener. The proper way to assign listeners is either in constructor, or in any function that listens for manually triggered event (say, MouseEvent.CLICK), but then you have to take precautions about listening for more than once with each function, and listening only with those functions you need right now.
EDIT:
Okay. Your code was:
addFrameScript(0, frame1);
addFrameScript(1, frame2);
The more correct way should be:
addFrameScript(0,frame1,1,frame2);
The reason is, the call to addFrameScript replaces all the timeline code with what you supply within here. The function is undocumented, perhaps by the reason of its affects on the stage and AS3 environment. The closest thing to the documentation on addFrameScript() so far is this link.
Next: Your code is:
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
x+=vx;
y+=vy
}
The correct way of writing this is as follows:
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE,init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
}
public function loop(e:Event) : void
{
x+=vx;
y+=vy
}
The listeners should be assigned in constructor, if they are permanent or you want them to be active as soon as you create an object. The KeyboardEvent listeners are separate case, as in order for them to function you have to assign them to stage, which is not available right at the time of creating the object, so you need an intermediate layer - the init() function, that is only called when the object is added to stage. At this point stage is no longer null, and you can assign an event listener there. Note, if you want to make your circles eventually disappear, you have to remove the listener you assigned to stage at some point of your removal handling code.
Next: Your code:
public function frame2()
{
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
Correct code should be:
public function frame2():void
{
if (Circle.parent) return; // we have added Circle to stage already!
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
See, you are calling this every time your MC is stopped at second frame, thus you constantly reset Circle's coordinates to stage center, so you just cannot see if it moves (it doesn't, as you have assigned the keyboard listener not to stage).
Perhaps there are more mistakes, but fixing these will make your MC tick a little bit.

custom mouse hiding behind objects as3

i have this here http://www.nzombie.eshost.es/ with a custom mouse. It works perfect, only that when it is behind another movie clip it "hides" itself. I don't know what's wrong. Any advice or help with be appreciated. Here's the mouse class:
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.ui.Mouse;
public class myCursor extends MovieClip
{
public function myCursor(stage):void
{
stop();
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
addEventListener(Event.REMOVED_FROM_STAGE, onRemove);
}
private function updateCoor(e:MouseEvent):void
{
x = e.stageX;
y = e.stageY;
e.updateAfterEvent();
}
private function onDown(e:MouseEvent):void
{
updateCoor(e);
gotoAndStop(2);
}
private function onUp(e:MouseEvent):void
{
updateCoor(e);
gotoAndStop(1);
}
private function onMove(e:MouseEvent):void
{
Mouse.hide();
updateCoor(e);
}
private function onRemove(e:Event):void
{
Mouse.show();
stage.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
removeEventListener(Event.REMOVED_FROM_STAGE, onRemove);
}
}
}
If you are adding multiple things to the stage at runtime it would be worth overriding addChild so that everything is added at index 1, leaving the cursor (at index 0) always on top.
Something like this:
override public function addChild(value:displayObject):void
{
var index:uint = 1;
if(value is myCursor){index = 0;}
addChildAt(value, index);
}
Or simply only ever add new display objects using addChildAt(displayObject, 1) and be sure to add your cursor class at 0;
I believe the issue lies not in this class, but in the class where you add myCursor object.
The buttons might have been added after the cursor & so the cursor lies behind the buttons in the display list. Try adding the myCursor after the buttons have been added to stage.

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;