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.
I've made a very simple 'game' where a circle is created and when clicked a new circle is added and clicking the new circle adds another while clicking any old circles 'ends' the game. I'm going to have a simple endgame screen with a restart button. I apologize if the code is messy, it is for practice in FlashDevelop.
The problem is I am trying to call my "endGame" class function in Main but I receive the error: "(58): col: 5 Error: Incorrect number of arguments. Expected 1." Line 58 is my call to endGame()
The weird part is that I receive the error even with endGame completely empty. I've posted both sections below and marked (**) the endGame call in main.
Main class
package Fun
{
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Shape;
import flash.events.MouseEvent;
public class Main extends Sprite
{
public var circles:Array;
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);
// entry point
makeacircle()
}
public function makeacircle():void
{
circles = new Array();
var addcirc:addcircle;
addcirc = new addcircle((Math.random() * 999999))
circles.push(addcirc)
addChild(addcirc)
addcirc.x = 300
addcirc.y = 200
addEventListener(eventclass.LOOP, movecirc);
addcirc.addEventListener(MouseEvent.CLICK, transition )
function transition(e:MouseEvent):void
{
addcirc.removeEventListener(MouseEvent.CLICK, transition);
dispatchEvent ( new eventclass(eventclass.LOOP))
addcirc.addEventListener(MouseEvent.CLICK, gameover)
}
function gameover(e:MouseEvent):void
{
for each (var circle:addcircle in circles)
{
removeChild(circle)
}
circles.length = 0
** endGame()
}
}
public function movecirc(Eventclass:eventclass):void
{
var addcirc:addcircle;
addcirc = new addcircle((Math.random() * 1000000))
circles.push(addcirc);
addcirc.addEventListener(MouseEvent.CLICK, looper)
addChild(addcirc);
for each (var circle:addcircle in circles)
{
circle.x = (Math.random() * 600)
circle.y = (Math.random() * 400)
}
function looper(e:MouseEvent):void
{
addcirc.removeEventListener(MouseEvent.CLICK, looper)
dispatchEvent ( new eventclass( eventclass.LOOP))
addcirc.addEventListener(MouseEvent.CLICK, gameover)
}
function gameover(e:MouseEvent):void
{
for each (var circle:addcircle in circles)
{
removeChild(circle)
}
circles.length = 0
}
}
}
}
endGame
package Fun
{
import flash.display.Sprite;
public class endGame extends Sprite
{
public function endGame():void
{
}
}
}
Without the call to endGame() the code runs perfect and everything I want occurs. I'm just not sure why the endGame function is claiming to require arguments.
We have several problems here.
First: you should ALWAYS use semicolon, not when you remember.
Second: the cause of problem is you are calling endGame() as if it's a function
You have a Class endGame so this is the correct use of it:
var eg : endGame = new endGame();
From what i see you should learn a bit more about OOP before using Classes
i simply have one layer which has two frames
frame 1 : menu with only one button
frame 2 : blank but with document class want to put Movie Clip named circle
I want to put it that way because i will program the symbol to draw ....(till now wrote nothing)
In document class till now i have written
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 ourShip:circle = new circle()
//our constructor function. This runs when an object of
//the class is created
public function engine()
{
ourShip.x = stage.stageWidth / 2;
ourShip.y = stage.stageHeight / 2;
addChild(ourShip)
}
}
}
First frame button as file :
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
{
}
}
}
By the way i only know addchild (which i wrote in as here,right now it would display circle in both frame 1 and frame 2 but i want it in only frame 2)
Because of how the Flash timeline works, you can only add something to a frame when you are there. So you can do,
goToAndStop(3);
addChild(myClip);
But then if you leave frame 3 it is gone forever.
You can
Add the code to the individual frame of the timeline, or
You can create a simple Event listener like below
Adding Event Listener:
addEventListener(Event.ENTER_FRAME, function() {
if (this.currentFrame == 3) {
addChild(myClip)
}
})
so I've really been struggling trying to add an audio slider to my game the last couple days and I've about had it, so, let me preface this by saying I have tried EXTREMELY hard and I would love to fully understand the solution, but at this point I really just want the solution, so the more specific you can be the better.
I've thought of a number of approaches, but my actionscript skills have been too faulty to pull any of them off. Let me explain my setup a bit. I have a fully functional class that is an audio slider. It plays music, slides, does everything perfect. Now, I'm sticking it in my document class. I thought it was easiest to call this function right at the very beginning (as my title screen shows up), EVEN THOUGH I don't want music to be playing right now at the title screen. So I thought I would call it, then just simply not play the music yet. So now I have it called from my document class. Now, I want to be able to click on the options button and then addChild the audio slider. I have actually accomplished this and it works. Finally....the hard part. I want to click the play game button and then have the music start playing WHILE BEING LINKED to the options slider which has the possibility of already being moved. Really...just a standard audio slider.
I'm really stuck on linking the options screen audio slider to the music actually playing in the game. I thought I would call the Volume() function (my audio slider), and then once my playscreen starts up, call it again and then just run a method of the Volume() class from within my playscreen class. This seems to lead to problems though...and this is where I lose it. By calling the Volume() class again, am I totally reinstating my audio? Like does this mean that I'm erasing everything I have done with my audio slider in the options panel? It seems to be...because it just starts playing at the default value.
So here's some detailed code of what I'm doing. I was thinking of using navigation events, but like I said, I'm not the greatest flash programmer yet and when I tried using them before I ran into trouble. Here are my main concerns in the code.
1) Calling new_Volume in my playScreen class (called SimpleMenuMain). Does this wipe out everything I've done in my document class when I called Volume()?
2) Towards the end of the Volume() class, I made a stopMusic function. Whenever I call it from my document class, it only works if I have not yet pressed play game, further leading me to believe I'm erasing whatever I do in the options panel before pressing play game.
3) Should I be using navigation events (custom events)? If so, how exactly do I do it? I understand how to use them in general (I've already used 5 in this game), but all of my navigation events go to my document class, so I'm guessing there's some subtlety with them I'm not quite understanding. I have a custom events class..I'll post that as well.
Thank you for all the help =) this has been killing me. I will wittle down these classes to the relavent info.
Document Class
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.ProgressEvent;
public class SMGDocClass extends MovieClip
{
public var playScreen:SimpleMenuMain;
public var titleScreen:TitleScreen;
public var gameOver:GameOver;
public var loadingProgress:LoadingProgress;
public var optionScreen:OptionScreen;
public var new_Volume:Volume;
public function SMGDocClass()
{
loadingProgress = new LoadingProgress();
loadingProgress.x = 0;
loadingProgress.y = 0;
addChild( loadingProgress );
loaderInfo.addEventListener( Event.COMPLETE, onCompletelyDownloaded,false,0,true );
loaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgressMade,false,0,true );
}
public function showTitleScreen():void
{
titleScreen = new TitleScreen();
titleScreen.addEventListener(NavigationEvent.START,onRequestStart,false,0,true);
titleScreen.addEventListener(NavigationEvent.OPTIONS,onRequestOptions,false,0,true);
titleScreen.x = 0;
titleScreen.y = 0;
addChild(titleScreen);
removeChild(loadingProgress);
new_Volume = new Volume();
new_Volume.stopMusic();
stage.focus = playScreen;
stage.stageFocusRect = false;
}
public function onStickman1Death(stickman1Event:Stickman1Event):void
{
var finalScore:Number = playScreen.getFinalScore();
var finalClockTime:Number = playScreen.getFinalClockTime();
gameOver = new GameOver();
gameOver.addEventListener(NavigationEvent.RESTART,onRequestRestart,false,0,true);
gameOver.addEventListener(NavigationEvent.MAINMENU,onRequestMainMenu,false,0,true);
gameOver.x = 5;
gameOver.y = 6;
gameOver.setFinalScore( finalScore );
gameOver.setFinalClockTime( finalClockTime );
addChild(gameOver);
new_Volume.stopMusic();
removeChild(playScreen);
playScreen = null;
}
public function onRequestStart( navigationEvent:NavigationEvent ):void
{
playScreen = new SimpleMenuMain();
playScreen.addEventListener( Stickman1Event.DEAD, onStickman1Death,false,0,true );
playScreen.x = 0;
playScreen.y = 0;
addChild( playScreen );
dispatchEvent(new Stickman1Event(Stickman1Event.DEAD));
removeChild(titleScreen);
titleScreen = null;
stage.focus = playScreen;
stage.stageFocusRect = false;
}
public function restartGame():void
{
playScreen = new SimpleMenuMain();
playScreen.addEventListener(Stickman1Event.DEAD, onStickman1Death,false,0,true);
playScreen.x = 0;
playScreen.y = 0;
addChild(playScreen);
removeChild(gameOver);
gameOver = null;
}
public function onRequestMainMenu( navigationEvent:NavigationEvent):void
{
titleScreen = new TitleScreen();
titleScreen.addEventListener(NavigationEvent.START,onRequestStart,false,0,true);
titleScreen.addEventListener(NavigationEvent.OPTIONS,onRequestOptions,false,0,true);
titleScreen.x = 0;
titleScreen.y = 0;
while(numChildren > 0)
{
removeChildAt(0);
}
addChild(titleScreen);
stage.focus = playScreen;
stage.stageFocusRect = false;
}
public function onCompletelyDownloaded( event:Event ):void
{
gotoAndStop(3);
showTitleScreen();
}
public function onProgressMade( progressEvent:ProgressEvent ):void
{
loadingProgress.setValue( Math.floor( 100 * loaderInfo.bytesLoaded / loaderInfo.bytesTotal ) );
}
public function onRequestOptions(navigationEvent:NavigationEvent):void
{
optionScreen = new OptionScreen();
optionScreen.addEventListener(NavigationEvent.MAINMENU,onRequestMainMenu,false,0,true);
optionScreen.x = 0;
optionScreen.y = 0;
addChild(optionScreen);
removeChild(titleScreen);
}
}
}
Play Screen Class
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.media.SoundChannel;
public class SimpleMenuMain extends MovieClip {
public var gameTimer:Timer;
public var stickman1:Stickman1;
public var new_Volume:Volume;
public function SimpleMenuMain() {
currentLevelData = new LevelData( 1 );
setBackgroundImage();
new_Volume = new Volume();
gameTimer = new Timer(25);
gameTimer.addEventListener(TimerEvent.TIMER, onTick, false, 0, true);
gameTimer.start();
addEventListener( Event.ADDED_TO_STAGE, onAddToStage );
}
public function onAddToStage(event:Event):void
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPress,false,0,true);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyRelease,false,0,true);
}
public function onTick(timerEvent:TimerEvent):void
{
var stickman1HasBeenHit:Boolean = false;
var i:int = army1.length - 1;
var enemy1:Enemy1;
while ( i > -1 )
{
enemy1 = army1[i];
if (enemySpeed == 1)
{
enemy1.moveABit(3,-1.5);
}
if (enemySpeed == 2)
{
enemy1.moveABit(3.6,-1.8);
}
if ( PixelPerfectCollisionDetection.isColliding( stickman1, enemy1, this, true ) )
{
getFinalScore();
gameTimer.stop();
bgmSoundChannel.stop();
stickman1HasBeenHit = true;
}
if ( enemy1.y > 400 )
{
removeChild( enemy1 );
army1.splice( i, 1 );
}
i = i - 1;
}
var i:int = army2.length - 1;
var enemy2:Enemy2;
while ( i > -1 )
{
enemy2 = army2[i];
if (enemySpeed2 == 1)
{
enemy2.moveABit(6,-3);
}
if (PixelPerfectCollisionDetection.isColliding(stickman1, enemy2, this, true ) )
{
gameTimer.stop();
bgmSoundChannel.stop();
stickman1HasBeenHit = true;
}
if ( enemy2.y > 400 )
{
removeChild( enemy2 );
army2.splice( i, 1 );
}
i = i - 1;
}
if (stickman1HasBeenHit)
{
dispatchEvent(new Stickman1Event(Stickman1Event.DEAD));
}
}
}
Volume Class
package {
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.net.URLRequest;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.geom.Rectangle;
public class Volume extends Sprite {
public var snd:Sound = new Sound();
public var channel:SoundChannel = new SoundChannel();
//URLRequest=new URLRequest("solitude.wav");
//Make sure you pass URLRequest an audio file on your computer.
public var req:BackgroundMusic = new BackgroundMusic();
public var boundary:Rectangle;
public var sprite:Sprite;
public var slider:Sprite;
public var xPos:Number;
public var yPos:Number;
public var vol:Number;
/*
Our request is loaded into the sound object and plays through
our channel. Volume is initially set at 50% and passed as a
transformation to our our channels soundTransform property
(a fancy way of saying volume). The init() function is called.
*/
public function Volume() {
this.addEventListener(Event.ADDED_TO_STAGE, onStage,false,0,true);
startMusic();
}
/*
The init function creates and draws a rectangle and circle
to the stage and centers them based on the height and
width of the stage. In addition, a rectangle object is
created to 'contain' the sliding circle, like an imaginary box.
We pass -100 as the x value because it is added relative
to our sprite. If we set its x value at 0, or the sprites default x
value,the boundary would stop and start at the slider sprite. Change
-100 to 0 in the rectangle object to get a better idea of its use.
*/
public function onStage(e:Event):void
{
//We remove it immediately so that it doesn't get called multiple times
//As the instance is added to the display list tree
this.removeEventListener(Event.ADDED_TO_STAGE, onStage);
xPos = 320;
yPos = 132;
/* Now that we have a reference to the stage, let's go ahead and create our slider */
init();
}
public function init():void {
sprite = new Sprite();
channel.stop();
sprite.graphics.beginFill(0x999999);
sprite.graphics.drawRect(xPos,yPos,100,5);
sprite.graphics.endFill();
addChild(sprite);
sprite.x-=sprite.width/2;
slider = new Sprite();
slider.graphics.beginFill(0xFF0000);
slider.graphics.drawCircle(xPos+50,yPos, 15);
slider.graphics.endFill();
addChild(slider);
slider.addEventListener(MouseEvent.MOUSE_DOWN, dragSlider);
stage.addEventListener(MouseEvent.MOUSE_UP, stopSlider);
boundary=new Rectangle(-100,0,100,0);
}
/*
dragSlider runs when the use holds the mouse button down. A
startDrag method is used on our sprite where we specify boundary
as our dragging limits. A new event handler designed
to change the mouse volume is subsequenlty called per frame, where
the slider.x property determines volume.
*/
public function dragSlider(event:MouseEvent):void {
slider.startDrag(false,boundary);
slider.removeEventListener(MouseEvent.CLICK, dragSlider);
slider.addEventListener(Event.ENTER_FRAME, changeVolume);
}
/*
Stops dragging and removes the event listener to save on space. Again,
volume will be based on the sliders current x position, which is
constantly being recalculated per frame because we used an
ENTER_FRAME event.
*/
public function stopSlider(event:MouseEvent):void {
slider.stopDrag();
slider.removeEventListener(MouseEvent.MOUSE_UP, stopSlider);
}
/*
This function is constantly recalculating the vol variable
based on the sliders x position, relative to the length of
our rectangle. Creates a decimal range from 0 to 1, where 1
represents 100% volume and 0 represents mute. Anything exceeding
100% causes distortion.
*/
public function changeVolume(event:Event):void {
vol=1+Math.round(slider.x)/100;
channel.soundTransform=new SoundTransform(vol);
}
public function onBackgroundMusicFinished(event:Event):void
{
channel = req.play();
channel.addEventListener( Event.SOUND_COMPLETE, onBackgroundMusicFinished );
vol=1;
channel.soundTransform=new SoundTransform(vol);
}
public function startMusic():void
{
channel=req.play();
channel.addEventListener( Event.SOUND_COMPLETE, onBackgroundMusicFinished,false,0,true );
vol=1;
channel.soundTransform=new SoundTransform(vol);
}
public function playMusic():void
{
channel = req.play();
}
public function stopMusic():void
{
channel.stop();
}
}
}
Navigation Event Class
package
{
import flash.events.Event;
public class NavigationEvent extends Event
{
public static const RESTART:String = "restart";
public static const START:String = "start";
public static const MAINMENU:String = "mainmenu";
public static const OPTIONS:String = "options";
public static const STOPMUSIC:String = "stopmusic"
public function NavigationEvent( type:String, bubbles:Boolean = false, cancelable:Boolean = false )
{
super( type, bubbles, cancelable );
}
public override function clone():Event
{
return new NavigationEvent( type, bubbles, cancelable );
}
public override function toString():String
{
return formatToString( "NavigationEvent", "type", "bubbles", "cancelable", "eventPhase" );
}
}
}
Options Screen Class
package {
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.ui.Mouse;
import flash.net.SharedObject;
import flash.events.Event;
public class OptionScreen extends MovieClip {
public var mainMenuButton:SimpleButton;
private var new_Volume:Volume;
public var myEvent:Event;
public function OptionScreen() {
Mouse.show();
new_Volume = new Volume();
addChild(new_Volume);
mainMenuButtonOptions.addEventListener(MouseEvent.CLICK, onClickMainMenu,false,0,true);
}
public function onClickMainMenu(mouseEvent:MouseEvent):void
{
dispatchEvent( new NavigationEvent(NavigationEvent.MAINMENU));
}
}
}
Finally....Title Screen Class
package
{
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.ui.Mouse;
public class TitleScreen extends MovieClip
{
public var startButton:SimpleButton;
public function TitleScreen()
{
Mouse.show();
startButton.addEventListener( MouseEvent.CLICK, onClickStart,false,0,true );
titleOptionsButton.addEventListener( MouseEvent.CLICK, onClickOptions,false,0,true );
}
public function onClickStart( event:MouseEvent ):void
{
dispatchEvent( new NavigationEvent( NavigationEvent.START ) );
}
public function onClickOptions( event:MouseEvent ):void
{
dispatchEvent( new NavigationEvent( NavigationEvent.OPTIONS ) );
}
}
}
You can change the volume on individual SoundChannels, or globally on the SoundMixer class. Your current implementation is the former, and defined every time you instantiate your class.
See Adobe's Controlling sound volume and panning.
You can also set global volume and pan values for all sounds at once
using the soundTransform property of the SoundMixer class, as the
following example shows:
SoundMixer.soundTransform = new SoundTransform(1, -1);
You could also store your volume and reference it as a global/static variable.
public static var soundLevel:Number = 100;
public function changeVolume(event:Event):void {
soundLevel = 1+Math.round(slider.x)/100;
channel.soundTransform=new SoundTransform(soundVolume);
}
This way, any slider object changes the same variable. Of course, then you're left with needing to update N number of soundObjects to the new soundLevel, which is why using the SoundMixer is a better solution.
No. The new instance of Volume class doesn't overwrite the SoundChannel previously created. However, because Volume is a DisplayObject, if its only reference was on the stage, and starting your game takes to you a different frame, the old Volume object would be removed from the DisplayList and could be garbage collected.
Definitely sounds like you're moving between frames, in which case the older Volume object would be removed from DisplayList and GC'ed. This comes up a lot, but I'll reiterate: don't use stage frames. There are better (less headache inducing) ways of programming what you need.
Your choice of Nav events is discretional. You could just as easily write a nav class which handles all input events as they come from the system, and appropriately call your methods. Personally, I don't like Flash style events. There's often other data I want to pass to my methods apart from the usual variable suspects, thereby leading to clutter induced by custom events. You could also clear that up with global state tracking, and simply reference your current state from your generic methods to determine their response to any given nav event.
I'm new to Actionscript 3 and I'm wanting to allow a circle to move down using the down arrow on the keyboard. Here's my code:
package {
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Circle extends MovieClip {
public function Circle() {
// constructor code
var speed:int = 3;
addEventListener(KeyboardEvent.KEY_DOWN,keyIsDown);
function keyIsDown(event:KeyboardEvent) {
if(event.keyCode == Keyboard.DOWN) {
y = y+=speed;
}
}
}
}
}
When I test it, nothing happens when I press the down key. Anyone know what's wrong with the code?
Try adding KeyBoard events to the stage instead of to the class. Additionally, I would not nest functions like that, bad practice in general. Also the line y = y+=speed; is confusing, shouldn't it just be y += speed; ?
EDIT: Sorry, I guess stage will be null in the constructor, I've added a ADDED event listener.
Try this:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Circle extends MovieClip {
public function Circle() {
// constructor code
var speed:int = 3;
addEventListener(Event.ADDED, onAdded);
}
private function onAdded(event:Event) {
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyIsDown);
}
private function keyIsDown(event:KeyboardEvent) {
if(event.keyCode == Keyboard.DOWN) {
y += speed;
}
}
}
}