I am totally new at Flash CS6 Action script 3. I have to do an assignment of a scene that have to have mouse, keyboard, enter frame, and time events. Every time I test the movie out, I keep on getting an error that says, 'duplicate function definition' about the 'enter frame event' and 'timer event' functions'. I have tried to rename the functions, but it didn't work. Is there another solution to this? Also, could you please show some examples? Thanks!
QuestionMC.addEventListener(MouseEvent.CLICK, onClick);
QuestionMC.addEventListener(MouseEvent.ROLL_OVER, questionOver);
QuestionMC.addEventListener(MouseEvent.ROLL_OUT, questionOut);
function questionOver(event:MouseEvent):void
{
event.target.alpha = .5;
}
function questionOut(event:MouseEvent):void
{
event.target.alpha = 1;
}
function onClick(event:MouseEvent):void
{
//trace("click!!!");
event.target.y -= 15;
event.target.rotation += 45;
}
QuestionMC.buttonMode = true;
stage.addEventListener(KeyboardEvent.KEY_DOWN, jump);
stage.addEventListener(KeyboardEvent.KEY_UP, land);
function jump (event:KeyboardEvent): void
{
trace(event.keyCode);
YoshiMC.y -= 50
stage.removeEventListener(KeyboardEvent.KEY_DOWN, jump);
stage.addEventListener(Event.ENTER_FRAME, flip);
}
function land (event:KeyboardEvent): void
{
YoshiMC.y += 50
stage.addEventListener(KeyboardEvent.KEY_DOWN, jump);
stage.removeEventListener(Event.ENTER_FRAME, flip);
}
function flip(event:Event):void
{
YoshiMC.rotation += 45;
YoshiMC.x += 20;
}
var jumpTimer:Timer = new Timer(5000,1);
jumpTimer.addEventListener(TimeEvent.TIMER, jump);
function jump (event:TimerEvent):void
{
planteaterMC.play();
}
jumpTimer.start();
var link:URLRequest = new URLRequest("");
buttongoeshere.addEventListener(MouseEvent.CLICK, clickHere);
function clickHere(event:MouseEvent):void
{
navigateToURL(link);
}
buttongoeshere.buttonMode = true;
Your jump function is declared twice, here:
function jump (event:KeyboardEvent): void
and here:
function jump (event:TimerEvent):void
You just need to rename one of them
Related
I have some problems with my character's walking command. It delays its movement for a bit before it actually moves. And then at times it completely ignores the command to stop walking when I released the key.
Code:
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;
hero.gotoAndStop(1);
var rightPressed: Boolean = new Boolean(false);
var leftPressed: Boolean = new Boolean(false);
var upPressed: Boolean = new Boolean(false);
var downPressed: Boolean = new Boolean(false)
var heroSpeed: Number = 10;
var keys: Array = [];
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(Event.ENTER_FRAME, gameLoop);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
function keyDownHandler(KeyEvent: KeyboardEvent): void {
if (keys[Keyboard.RIGHT]) {
rightPressed = true;
} else if (keys[Keyboard.LEFT]) {
leftPressed = true;
} else if (keys[Keyboard.DOWN]) {
downPressed = true;
} else if (keys[Keyboard.UP]) {
upPressed = true;
}
}
function keyUpHandler(KeyEvent: KeyboardEvent): void {
if (keys[Keyboard.RIGHT]) {
rightPressed = false;
hero.gotoAndStop(4)
} else if (keys[Keyboard.LEFT]) {
leftPressed = false;
hero.gotoAndStop(2)
} else if (keys[Keyboard.DOWN]) {
downPressed = false;
hero.gotoAndStop(1);
} else if (keys[Keyboard.UP]) {
upPressed = false;
hero.gotoAndStop(3);
}
}
function gameLoop(loopEvent: Event): void {
if (rightPressed) {
hero.x += heroSpeed;
hero.gotoAndStop(8)
}
if (leftPressed) {
hero.x -= heroSpeed;
hero.gotoAndStop(6)
}
if (downPressed) {
hero.y += heroSpeed;
hero.gotoAndStop(5);
}
if (upPressed) {
hero.y -= heroSpeed;
hero.gotoAndStop(7);
}
}
function onKeyDown(e: KeyboardEvent): void {
keys[e.keyCode] = true;
}
function onKeyUp(e: KeyboardEvent): void {
keys[e.keyCode] = false;
}
Warnings:
Scene 1, Layer 'Actions', Frame 1, Line 68, Column 10 Warning: 1090: Migration issue: The onKeyDown event handler is not triggered automatically by Flash Player at run time in ActionScript 3.0. You must first register this handler for the event using addEventListener ( 'keyDown', callback_handler).
Scene 1, Layer 'Actions', Frame 1, Line 72, Column 10 Warning: 1090: Migration issue: The onKeyUp event handler is not triggered automatically by Flash Player at run time in ActionScript 3.0. You must first register this handler for the event using addEventListener ( 'keyUp', callback_handler).
You should get rid of the two extra KeyboardEvent handlers (onKeyUp and onKeyDown), and move the code you have there into keyUpHandler and keyDownHandler. That will solve those migration warnings (because onKeyUp and onKeyDown were special methods in AS2), and it may be the solution to your other problem: I guess sometimes the onKeyDown handler gets executed after keyDownHandler, which means the boolean values in your array are not set yet and no movement will start.
Even better: also get rid of the array with booleans (and keys! you're abusing an Array for Dictionary use) and do it like this:
function keyDownHandler(KeyEvent: KeyboardEvent): void {
if (event.keyCode==Keyboard.RIGHT]) {
rightPressed = true;
}
//etc
}
I'm trying to make simple shooting game with Fiat Multipla falling up to bottom of the screen. I have created function to generate falling multipla and within this function I have a problem.
The main issue is that after change of multideath status to 1 "Death" function does nothing even if It is kept with ENTER_FRAME. Child becomes invisible as I implemented it in multipla movieclip, but even after response from there with Death = 1, nothing happens.
I'm new to all this, I've met and solved few issues during programming, but here's my brickwall for now. Code's either failing completely or I don't know something that's obvious. As I said, I'm newbie.
Thanks a lot for help!
Here's the function:
import flash.events.Event;
import flash.desktop.NativeApplication;
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
Mouse.hide();
var velocity = 0;
var ammo = 6;
LGUI.LGUIammo.gotoAndStop(6);
var counter = 0;
function multiplarain()
{
var x1 = Math.ceil(Math.random() * 280);
var y1 = -200;
var random:Multipla = new Multipla();
var life = 265;
var multideath = 0;
random.x = 100 + x1;
random.y = y1
addChild(random);
random.gotoAndStop(1);
setChildIndex(random, +1);
addEventListener(Event.ENTER_FRAME, Death);
function Death(event:Event):void
{
if(multideath >= 1)
{
removeEventListener(Event.ENTER_FRAME, Death);
removeChild(random);
}
}
addEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);
function fl_EnterFrameHandler(event:Event):void
{
if(random.y >= 680)
{
removeEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler)
removeChild(random);
trace("rofl");
}
}
random.addEventListener(Event.ENTER_FRAME, fl_AnimateVertically);
function fl_AnimateVertically(event:Event)
{
velocity = velocity + 0.000035;
random.y += 1.5 + velocity;
}
random.addEventListener(TouchEvent.TOUCH_TAP, fl_TapHandler);
function fl_TapHandler(event:TouchEvent):void
{
counter = counter + 1;
ammo -= 1;
}
if(ammo == 6)
{
LGUI.LGUIammo.gotoAndStop(6);
}
if(ammo == 5)
{
LGUI.LGUIammo.gotoAndStop(5);
}
if(ammo == 4)
{
LGUI.LGUIammo.gotoAndStop(4);
}
if(ammo == 3)
{
LGUI.LGUIammo.gotoAndStop(3);
}
if(ammo == 2)
{
LGUI.LGUIammo.gotoAndStop(2);
}
if(ammo == 1)
{
LGUI.LGUIammo.gotoAndStop(1);
}
if(ammo <= 0)
{
LGUI.LGUIammo.gotoAndStop(7);
}
HGUI.saved.text = counter;
this.addEventListener( Event.ENTER_FRAME, handleCollision)
var kucyk = LGUI.LGUIlife.lifeitself;
function handleCollision(e:Event):void
{
if (random.hitTestObject(LGUI))
{
kucyk = LGUI.LGUIlife.lifeitself;
kucyk.width -= 0.1;
}
/*if (kucyk.width == 0.75)
{
trace("cycki");
NativeApplication.nativeApplication.exit();
}*/
}
}
and here's multipla's movieclip in library code:
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
this.addEventListener(TouchEvent.TOUCH_TAP, fl_TapHandler2);
function fl_TapHandler2(event:TouchEvent):void
{
this.gotoAndPlay(2);
}
addEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);
function fl_EnterFrameHandler(event:Event):void
{
if(this.currentFrame == 60)
{
this.visible = false;
MovieClip(root).multideath = 1;
trace(MovieClip(root).multideath);
removeEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);
removeEventListener(Event.ENTER_FRAME, fl_TapHandler2);
}
}
it's been like 10 years since I last time worked with AS2 but I'd guess that this Multipla sets the multideath property in the wrong place. If i remember corrctly, root is the top-most level (your application). So if your first code is not on the main timeline but in a movieclip that is on the main timeline it won't work. Try to put a trace into the Death function to see if the multideath is really changing there:
trace(multideath);
try this in the multipla code:
parent.multideath = 1;
instead of
MovieClip(root).multideath = 1;
And I'm asking myself why do you need so many enter frame listeners? You can have just one and combine all animations in one function.
Also you don't need to check for multideath on every frame, just remove the movieclip in a separate function:
function removeMultipla():void
{
removeChild(random);
}
Just call this function from your Multipla instead of setting the multideath property:
parent.removeMultipla();
I'm trying to get the bat character to remove the jack/2/3 child(s) in my game here, but I keep getting the ArgumentError: Error #2025. I understand that I may be removing a child twice, perhaps? I'm looking around and I'm not really experienced in this stuff so I'm having a hard time understanding what needs to be done to fix this issue. Can someone tell me what needs to be done with my code specifically, please?
var jack:pumpkin = new pumpkin();
var jack2:pumpkin = new pumpkin();
var jack3:pumpkin = new pumpkin();
var score:Number = 0;
scoreBox.text = String(score);
addChild(jack);
jack.x = 125;
jack.y = 285;
addChild(jack2);
jack2.x = 270;
jack2.y = 310;
addChild(jack3);
jack3.x = 445;
jack3.y = 285;
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveLeft);
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveRight);
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveUp);
stage.addEventListener(KeyboardEvent.KEY_UP, bump);
function moveLeft(e:KeyboardEvent):void {
if (e.keyCode == 37) {
bat.x -= 5;
}
}
function moveRight(e:KeyboardEvent):void {
if (e.keyCode == 39) {
bat.x += 5;
}
}
function moveDown(e:KeyboardEvent):void {
if (e.keyCode == 40) {
bat.y += 5;
}
}
function moveUp(e:KeyboardEvent):void {
if (e.keyCode == 38) {
bat.y -= 5;
}
}
function bump(e:KeyboardEvent):void {
stage.addEventListener(Event.ENTER_FRAME, bumpIt);
function bumpIt(e:Event):void {
if (bat.hitTestObject(jack)) {
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
removeChild(jack);
score++;
scoreBox.text = String(score);
}
if (bat.hitTestObject(jack2)) {
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
removeChild(jack2);
score++;
scoreBox.text = String(score);
}
if (bat.hitTestObject(jack3)) {
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
removeChild(jack3);
score++;
scoreBox.text = String(score);
}
}
}
Due to the nested bumpit() event handler, on every key up you're adding another enter frame event if your hit-test has no collision.
On KeyboardEvent.KEY_UP, event handler calls bump() which adds an Event.ENTER_FRAME listener that will call bumpIt().
If bat.hitTestObject() is true, you remove Event.ENTER_FRAME.
If not, you still have the Event.ENTER_FRAME listener firing bumpIt() every frame.
So, every key up you're potentially adding another frame handler.
If ten key up events occurred and none of them hit test your objects, you are now calling bumpIt ten times a frame.
If you need to hit test on key up, just put the logic there:
stage.addEventListener(KeyboardEvent.KEY_UP, bump);
function bump(e:KeyboardEvent):void {
if (bat.hitTestObject(jack)) { /* ... */ }
}
Or, if you're tracking an animation sequence after key up, maybe add some state variable, such as:
var isFlying:Boolean = false;
stage.addEventListener(KeyboardEvent.KEY_UP, bump);
function bump(e:KeyboardEvent):void {
// If bat is already flying, don't add another frame handler
if (isFlying)
return;
// Otherwise, indicate bat is now flying and add frame handler
isFlying = true;
stage.addEventListener(Event.ENTER_FRAME, bumpIt);
}
Then, if your hit-test works and you remove your frame handler, reset the state variable:
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
isFlying = false;
Another solution is to remove the nested handlers. Because you have nested bumpIt() inside bump(), you are seeing cumulative firing of callbacks due to scope:
function bump():void {
function bumpIt():void { /* ... */ }
}
Simply promote bumpIt():
function bump():void { /* ... */ }
function bumpIt():void { /* ... */ }
I am trying to make a game that involves hitting keys/clicking buttons at the right time. I want to have the button/indicator hidden until the right time but am having a bit of trouble getting it to display. This is the code I have for it so far.
var count:Number = 5;
var myTimer:Timer = new Timer(1000, count);
myTimer.addEventListener(TimerEvent.TIMER, countdown);
myTimer.start();
function countdown(event:TimerEvent): void {
timer_txt.text = String((count)-myTimer.currentCount);
}
btnthing.addEventListener(MouseEvent.CLICK, btnclick);
btnthing.visible=false;
while (((count)-myTimer.currentCount)==1) {
btnthing.visible=true;
}
function btnclick(e:MouseEvent): void {
if (((count)-myTimer.currentCount) == 1) {
myTimer.stop();
btnthing.visible=false;
time_txt.text = "Yay!";
} else {
myTimer.stop();
gotoAndStop(3);
}
}
So far my code starts the timer and displays a countdown. If I remove the part that hides/shows the button, everything works fine.
var count:Number = 5;
var myTimer:Timer = new Timer(1000, count);
myTimer.addEventListener(TimerEvent.TIMER, countdown);
myTimer.start();
function countdown(event:TimerEvent): void {
timer_txt.text = String((count)-myTimer.currentCount);
}
btnthing.addEventListener(MouseEvent.CLICK, btnclick);
function btnclick(e:MouseEvent): void {
if (((count)-myTimer.currentCount) == 1) {
myTimer.stop();
btnthing.visible=false;
timer_txt.text = "Yay!";
} else {
myTimer.stop();
gotoAndStop(3);
}
}
If anyone could help me get this right that would be awesome. Thanks!
You're not using the 'while' loop correctly. Change it to a 'if' statement and put it inside the countdown function like this:
function countdown(event:TimerEvent): void
{
timer_txt.text = String((count)-myTimer.currentCount);
if (((count)-myTimer.currentCount)==1) {
btnthing.visible=true;
}
}
so that your code tests for the currentCount on each tick of the timer and finally does something about it.
Read up on 'while' loops - they don't do exactly what you think they do and it's easy to get 'em into infinite repitions if you don't increment the thing that you're changing within the loop.
I have a few .as files. They are: MainClass.as, FrontEnd.as, Levels.as, and Hero.as. My problem (as far as I know) is in my Hero.as file. Let me descibe how I have it all set up thusfar because I have been a bit concerned that there are better ways of doing things in AS3.
MainClass.as makes a variable of FrontEnd (menus, namely the main menu) and calls it up (addChild).
FrontEnd.as are my menus. buttons and whatnot...
Levels.as right now just calls up level 1 when the start new game button is pressed on the main menu. Had one hell of a time figuring out how to use functions from a different .as file. Hero.as I will add my code for. I'm posting the whole thing because I don't know where my problem is.
public class Hero extends MovieClip
{
public var roger:player = new player();
private var animationState:String = "down";
public var facing:String = "down";
private var isLeft:Boolean = false;
private var isRight:Boolean = false;
private var isUp:Boolean = false;
private var isDown:Boolean = false;
public var currentPlayer:MovieClip = roger;
public function Hero()
{
addEventListener(Event.ENTER_FRAME, loop);
addEventListener(Event.ADDED_TO_STAGE, onStage);
trace(currentPlayer);
}
public function onStage( event:Event ):void
{
removeEventListener( Event.ADDED_TO_STAGE, onStage );
}
public function addCurrentPlayer():void
{
roger.x = stage.stageWidth * .5;
roger.y = stage.stageHeight * .5;
addChild(roger);
currentPlayer = roger;
setBoundaries();
}
public function keyDownHandler(event:KeyboardEvent)
{
if (event.keyCode == 39)//right press
{
isRight = true;
}
if (event.keyCode == 37)//left pressed
{
isLeft = true;
}
if (event.keyCode == 38)//up pressed
{
isUp = true;
}
if (event.keyCode == 40)//down pressed
{
isDown = true;
}
}
public function keyUpHandler(event:KeyboardEvent)
{
if (event.keyCode == 39)//right released
{
isRight = false;
}
if (event.keyCode == 37)//left released
{
isLeft = false;
}
if (event.keyCode == 38)//up released
{
isUp = false;
}
if (event.keyCode == 40)//down released
{
isDown = false;
}
}
public function loop(Event):void
{
if (currentPlayer == null)
{
addCurrentPlayer();//make sure at least roger is on the screen
}
currentPlayer.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
currentPlayer.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
//----------------------------------0
//Animation States
//----------------------------------0
if (isDown == true)
{
currentPlayer.y += 5;
animationState = "walk_down";
facing = "down";
currentPlayer.gotoAndStop(animationState);
}
else if (isUp == true)
{
currentPlayer.y -= 5;
animationState = "walk_up";
facing = "up";
currentPlayer.gotoAndStop(animationState);
}
else if (isRight == true)
{
currentPlayer.x += 5;
animationState = "walk_right";
facing = "right";
currentPlayer.gotoAndStop(animationState);
}
else if (isLeft == true)
{
currentPlayer.x -= 5;
animationState = "walk_left";
facing = "left";
currentPlayer.gotoAndStop(animationState);
}
//----------------------------------0;
//IDLE STATES
//----------------------------------0
else if (isDown == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isUp == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isRight == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isLeft == false)
{
currentPlayer.gotoAndStop(facing);
}
}
public function setBoundaries():void
{
var halfHeight:int = currentPlayer.height * .5;
var halfWidth:int = currentPlayer.width * .5;
if(currentPlayer.y <= 1)
{
currentPlayer.y += halfHeight;
}
else if(currentPlayer.y > stage.stageHeight)
{
currentPlayer.y -= halfHeight;
}
else if(currentPlayer.x <= 1)
{
currentPlayer.x += halfWidth;
}
else if(currentPlayer.x > stage.stageWidth)
{
currentPlayer.x -= halfWidth;
}
}
}
}
trace(currentPlayer); is giving me [object player] instead of the instance name "roger". (Later on I want more playable characters.) I'm not sure if the problem is there or in my levels file, which I'll post here. (not as long as Hero.as)
public class Levels extends MovieClip
{
var currentLevel:MovieClip;
public function Levels()
{
addEventListener(Event.ADDED_TO_STAGE, onStage);
}
private function onStage(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
}
public function gotoLevelOne():void
{
var levelOne:LevelOne = new LevelOne();
var hero:Hero = new Hero();
addChild(hero);
levelOne.x = stage.stageWidth * .5;
levelOne.y = stage.stageHeight * .5;
addChild(levelOne);
currentLevel = levelOne;
hero.currentPlayer.x = 100;
hero.currentPlayer.y = 100;
addChild(hero.currentPlayer);
}
}
}
If I remove = roger; from var currentPlayer:MovieClip = roger; it gives me #1009 null object even though I told it in addCurrentPlayer() to change currentPlayer to roger. On level 1, everything shows up but I can't move my character. I know that it worked when I was working on his animations and I would call him to the main menu. Everything worked on him. What's the problem now?
Firstly, there's a lot of things wrong with your code:
In your Hero Class, the 'onStage' Event handler doesn't actually do anything other than remove the event listener that triggers it. While it's good practice to remove the event listener, there should be some other purpose to the Event handler. If there isn't you can remove it and not bother listening for the ADDED_TO_STAGE Event.
Similarly, in your Levels Class 'onStage' Event handler you attempt to remove the event, but name the wrong handler. I assume you want to remove the event handler and then run the 'gotoLevelOne' method. If so, just have the Event.ADDED_TO_STAGE listener call 'gotoLevelOne' and then remove the Event listener there:
public function Levels()
{
addEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
}
public function gotoLevelOne():void
{
removeEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
// class continues....
OK, so to your question:
You will be getting the null error because you are referring to currentPlayer from outside the Hero Class, before calling addCurrentPlayer (where it is set).
If you temporarily define currentPlayer as a private variable, the compiler should give you a line number where you first refer to currentPlayer from OUTSIDE the Hero Class (the error will be something like 'Class X is trying to access a private (or non-existent) property of Y Class').
You can then sort out WHY you are accessing currentPlayer before calling addCurrentPlayer. You may also want to think about if currentPlayer NEEDS to be public (if so, then what is 'addCurrentPlayer' for? That function effectively works as a setter for currentPlayer).
EDIT:
At the moment you are adding new KEY_DOWN and KEY_UP event listeners EVERY frame of your game loop. This is unnecessary. Add them both ONCE in the initialisation of your game (perhaps in your Hero's onStage handler), and count on them to trigger the appropriate handlers.
You will want to add the KEY_DOWN and KEY_UP listeners to 'stage', not currentPlayer, so:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
You will need to add the listeners AFTER your Hero instance has been added to the Stage though, so it has access to 'stage'. That's why it makes sense to add the listeners in the Hero's onstage handler.