I'm trying to call the punch function from my player class inside another class but for some reason it gives me this error:
1180: Call to a possibly undefined method Punch.
I'm not sure why it gives me this error. I even made the functions public.
This is the class where i am calling it from:
package
{
public class Player extends MovieClip
{
public function Player()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyPressed);
addEventListener(Event.ENTER_FRAME,Update);
}
function KeyPressed(event:KeyboardEvent):void
{
//If on floor
if (CanJump)
{
//If A key is down
if (event.keyCode == 65)
{
//Punch
Punch(true);
}
}
}
function Update(event:Event)
{
//Do stuff
}
}
}
and this is what I am trying to call:
package
{
public class ComboSequence extends ComboHandler
{
public function ComboSequence(clipName:String, par:BaseObject, _oList:ObjectList)
{
// constructor code
super(clipName, par, _oList);
}
public function Punch(PunchKey:Boolean)
{
if (currentAttack != null)
{
if (Recovery <= 0 && FollowUpTime > 0)
{
currentAttack = currentAttack.GetNextAttack(PunchKey);
if (currentAttack != null)
{
SetAnimation(currentAttack.animName);
Recovery = currentAttack.Recovery;
FollowUpTime = currentAttack.Recovery + 25;
}
}
}
if (FollowUpTime > 0)
{
FollowUpTime--;
}
else
{
currentAttack = null;
}
if (Recovery > 0)
{
Recovery--;
}
}
}
}
When you call Punch() on its own inside the player class, ActionScript is looking for a Player.Punch() method. Your method is on the ComboSequence class. You're probably trying to do something like this:
var comboSequence:ComboSequence = new ComboSequence();
comboSequence.Punch()
Keep in mind that while this code will run, it probably won't do what you want it to do. I guess you want to keep an instance of ComboSequence in your player object. If that doesn't make sense to you, it would be a good idea to do some background reading on ActionScript and object-oriented programming in general.
You need to import ComboSequence into the Player class and call Punch though that like
ComboSequence.Punch. andypaxo is right in his post, you'd need to instantiate it somewhere within the Player class.
One note about your code, though, you should not name functions with a capital letter. Class names typically start with a capital letter, but not the methods within.
package
{
import ComboSequence; //you may need the package path if its in a package, something like com.classes.ComboSequence, where com.classes is the folder that ComboSequence is saved.
public class Player extends MovieClip
{
public function Player()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyPressed);
addEventListener(Event.ENTER_FRAME,Update);
}
function KeyPressed(event:KeyboardEvent):void
{
//If on floor
if (CanJump)
{
//If A key is down
if (event.keyCode == 65)
{
//Punch
ComboSequence.Punch(true);
}
}
}
function Update(event:Event)
{
//Do stuff
}
}
}
also, regarding your "missing rightParen" error, rightParen means right parenthesis, or ), leftParen would be (. That error means you are missing a ) somewhere. Often times it can mean you added an extra one somewhere, thus closing a section of parenthesis you didn't mean to close, which would leave one unpaired parenthesis somewhere.
Related
While experimenting with a basic coding stuff, I wondered, if a value returned by a method called by a delegate, could be used or captured. In other words, where will the return value will go ?
For example :
class Main extends Sprite
{
public var mc:MyMc;
function Main()
{
mc.addEventListener( "myClick" , myClick);
}
function myClick(e:Event):String //returning a string
{
return "What happens to this return value ???"
}
}
class MyMc extends MovieClip
{
function MyMc()
{
addEventListener( MouseEvent.CLICK , onClick);
}
function onClick(e:Event):String //returning a string
{
dispatchEvent(new Event("myClick"));
}
}
As I know it's not possible to do, but, there are at least some ways to implement the logic similar to what you've told about.
For example, you may call a method of a dispatcher, from a listener method:
class Main extends Sprite
{
public var mc:MyMc;
function Main()
{
mc.addEventListener("myClick" , myClick);
}
function myClick(e:Event):void
{
mc.specialMethod("some string");
}
}
class MyMc extends MovieClip
{
function MyMc()
{
addEventListener(MouseEvent.CLICK , onClick);
}
function onClick(e:Event):void
{
dispatchEvent(new Event("myClick"));
}
public function specialMethod(param:String):void
{
// Do something to the param
}
}
Also, you may think about dispatching an event from the Main class, and listen to it in the MyMc class, or pass a callback, which returns a string, from Main to the MyMc.
It's according to you and your needs to return something from the listener function because normally it must return nothing :
... This function must accept an Event object as its only parameter and must return nothing, ...
but you can of course get the returned value(s), take a look on this little example :
var light_on:Boolean = false;
btn_light_on.addEventListener(MouseEvent.CLICK, btn_on_onPress);
btn_light_off.addEventListener(MouseEvent.CLICK, btn_off_onPress);
function btn_on_onPress(e:MouseEvent): Boolean {
light_on = true;
if(e.target === btn_light_off){
light_on = false;
}
return light_on;
}
function btn_off_onPress(e:MouseEvent): void {
trace('The light is', btn_on_onPress(e) ? 'on' : 'off');
}
Hope that can help.
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;
}
}
}
This is where the object is created, a new instance is created when the space key is pressed:
/* SHOOTING */
function fireRocket():void
{
if (fireHold == 0)
{
fireHold = 1;
var Timer = setInterval(fireDelay,fireRate);
function fireDelay()
{
fireHold = 0;
clearInterval(Timer);
}
if (rocketContainer.numChildren < 7)
{
trace(rocketContainer.numChildren)
var rocketGameObject = new rocketObject ;
rocketContainer.addChild(rocketGameObject);
rocketGameObject.x = spaceShip.x + 35;
rocketGameObject.y = spaceShip.y + 35;
}
else
{
trace("Too many rockets present");
}
}
}
Once a hit is confirmed (via the hit test below), the following should run:
function hitTest(evt:Event):void
{
/* HIT TEST */
for (var i=0; i < rocketContainer.numChildren; i++)
{
for (var j=0; j < enemyContainer.numChildren; j++)
{
if (rocketContainer.getChildAt(i).hitTestObject(enemyContainer.getChildAt(j)))
{
trace(rocketContainer.getChildAt(i));
rocketContainer.getChildAt(i).removeThis();
}
}
}
}
This is the class that is meant to handle movement and removal of the object when called using a method:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.DisplayObject;
public class rocketClass extends MovieClip
{
public function rocketClass()
{
this.addEventListener(Event.ENTER_FRAME,rocketMove);
}
function rocketMove(evt:Event):void
{
this.x += 20;
if (this.x > stage.stageWidth)
{
removeThis();
}
}
public function removeThis():void
{
trace("reached")
this.parent.removeChild(this);
this.removeEventListener(Event.ENTER_FRAME, rocketMove);
}
}
}
Now when I do trace(rocketContainer.getChildAt(i)); in the hit confirmed, it returns [object rocketObject]. So I can only assume it is successfully detecting the fact that it is an object, this being the object that I want to remove.
BUT, when I want to remove it using a method of a class like this rocketContainer.getChildAt(i).removeThis(); I get the following error:
1061: Call to a possibly undefined method removeThis through a reference with static type flash.display:DisplayObject
You need to cast rocketContainer.getChildAt(i) to your class rocketObject, because getChildAt() return DisplayObject. It will be looks like:
(rocketContainer.getChildAt(i) as rocketClass).removeThis();
or
rocketClass(rocketContainer.getChildAt(i)).removeThis();
P.S. In AS3 preferable that class name was started from symbol in uppercase. rocketClass -> RocketClass.
P.P.S. And part "class" in class name is unnecessary.
Just to reiterate what I said in my comment and what Crabar wrote in his answer, you need to cast to the appropriate Class when you are using getChildAt(int).
Crabars answer should work, and here is an alternative way (not that much different.) for better readability.
var temp:rocketClass = rocketContainer.getChildAt(i) as rocketClass;
temp.removeThis();
One point of confusion might be: why does hitTestObject() work? The answer to this: because hitTestObject() is a method of the DisplayObject class.
I hope the title isn't too confusing.
I know you are able to access a movieclip that is inside another movieclip, like I had done;
function allowResourceCollection():void {
caveman.btn_CollectResources2.addEventListener(TouchEvent.TOUCH_TAP, checkResourceCollection);
}
but I have now changed it so that inside of the movieclip caveman there is another movieclip cavemanmenu that is AS Linkage btncavemanMenu and inside of cavemanmenu is btn_CollectResources2 so I tried the following;
function allowResourceCollection():void {
caveman.cavemanmenu.btn_CollectResources2.addEventListener(TouchEvent.TOUCH_TAP, checkResourceCollection);
}
and I get this error;
TypeError: Error #1009: Cannot access a property or method of a null
object reference. at
stoneApp_new_fla::MainTimeline/allowResourceCollection()[stoneApp_new_fla.MainTimeline::frame1:104]
I'm so confused at what is going on. All I am trying to do is by clicking on caveman, cavemanmenu pops up and I am able to tap on btn_CollectResources2 which is nested inside of cavemanmenu. Here is all the code in the section so you understand;
var myMovieClip:MovieClip = new btncavemanMenu();
//Caveman Menu
function allowTapCaveman():void {
caveman.addEventListener(TouchEvent.TOUCH_TAP, cavemanMenu);
}
function cancelTapCaveman():void {
caveman.removeEventListener(TouchEvent.TOUCH_TAP, cavemanMenu);
}
function cavemanMenu(event:TouchEvent):void {
addChild(myMovieClip);
myMovieClip.x = caveman.x;
myMovieClip.y = caveman.y;
//myMovieClip.addEventListener(TouchEvent.TOUCH_TAP, cavemanMenu);
//caveman.gotoAndStop(2);
//trace('2');
if (caveman.currentFrame == 2){
cancelTapCaveman();
allowTapCavemanClose();
}
}
function allowTapCavemanClose():void {
caveman.addEventListener(TouchEvent.TOUCH_TAP, cavemanMenuClose);
}
function cancelTapCavemanClose():void {
caveman.removeEventListener(TouchEvent.TOUCH_TAP, cavemanMenuClose);
}
function cavemanMenuClose(event:TouchEvent):void {
cancelTapCavemanClose();
removeChild(myMovieClip);
//caveman.gotoAndStop(1);
allowTapCaveman();
//trace('1');
}
function allowResourceCollection():void {
caveman.btncavemanMenu.btn_CollectResources2.addEventListener(TouchEvent.TOUCH_TAP, checkResourceCollection);
}
function cancelResourceCollection():void {
caveman.btn_CollectResources2.removeEventListener(TouchEvent.TOUCH_TAP, checkResourceCollection);
}
function checkResourceCollection(event:TouchEvent):void {
if(remaningActions >= 1){
spawnWood();
spawnFood();
spawnStone();
remaningActions -= 1;
updateTextBox();
}
if(remaningActions <= 0){
trace("not enough actions")
}
}
As you can see, I used to have it so it would just change the frame in the movieclip caveman but because I need to create multiple caveman then I need to be able to have the menu pop up below them wherever they are and creating a child and bringing it in like that was the only way I could find. Thanks.
The event bubbles so the depth of the dispatching MovieClip does not matter. In fact, it is easier to let them be handled by caveman.
function allowResourceCollection():void {
caveman.addEventListener(TouchEvent.TOUCH_TAP, checkResourceCollection);
}
I highly recommend following naming conventions ...
This is AS3 question.
I have Class "addadd", "Symbol1"(Button1), "Symbol2"(Button2).
In "addadd" I have 3 functions. Function "StanishevFadd" creates object and add Event Listener, function "stanishevFremove" removes Event Listener and function "frameDOstanishev" that will be triggered when the event is added.
So, I obviously want to trigger the event from Symbol1 and stop the same event from Symbol2. Unfortunately doesn't work this way. I am totally confuzed. For example if I want to add and remove the event listener from Symbol1 only - YES works, but I am not able to create event from Symbol1 and remove the same event from Symbol2 in class addadd. Please help guys, please!
public class addadd
{
var stanishev:stanishev_line = new stanishev_line;
public function addadd()
{
}
public function stanishevFadd()
{
Main.display.addChild(stanishev);
stanishev.gotoAndPlay("start");
stanishev.addEventListener(Event.ENTER_FRAME, frameDOstanishev);
}
public function stanishevFremove()
{
stanishev.removeEventListener(Event.ENTER_FRAME, frameDOstanishev);
}
public function frameDOstanishev(e:Event)
{
trace (stanishev.currentFrame);
}
}
//------------------------------
public class Symbol1 extends SimpleButton
{
var call_creator:addadd = new addadd;
public function Symbol1()
{
// constructor code
addEventListener(MouseEvent.MOUSE_OVER, eventResponse);
}
function eventResponse(e:MouseEvent)
{
call_creator.stanishevFadd();
}
}
//----------------------
public class Symbol2 extends SimpleButton
{
var call_creator:addadd = new addadd;
public function Symbol2()
{
// constructor code
addEventListener(MouseEvent.MOUSE_DOWN, eventResponse2);
}
function eventResponse2(e:MouseEvent)
{
call_creator.stanishevFremove();
}
}
OK, I am not sure what the overall purpose of this whole thing, so I am going to call this thing OddView. I'm going to try to get close to what it looks like you are trying to do in a more OO way.
I believe it should be possible for you to encapsulate all of this behavior without involving your Main Class, and there are a lot of reasons not to involve it, especially not with static variables like you're doing.
public class OddView extends Sprite {
protected var _btn1:SimpleButton;
protected var _btn2:SimpleButton;
protected var _stanishev:StanishevLine;//note I changed your Class name to be more in line with AS3 standards
public function OddView() {
super();
}
public function get btn1():SimpleButton {
return _btn1;
}
public function set btn1(value:SimpleButton):void {
if (value != _btn1) {
if (_btn1) {
removeEventListener(MouseEvent.MOUSE_OVER, goToState2);
}
_btn1 = value;
if (_btn1) {
_btn1.addEventListener(MouseEvent.MOUSE_OVER, goToState2);
}
}
}
public function get btn2():SimpleButton {
return _btn2;
}
public function set btn2(value:SimpleButton):void {
if (value != _btn2) {
if (_btn2) {
removeEventListener(MouseEvent.MOUSE_OVER, goToState1);
}
_btn2 = value;
if (_btn2) {
_btn2.addEventListener(MouseEvent.MOUSE_OVER, goToState1);
}
}
}
public function get stanishev():StanishevLine {
return _stanishev;
}
public function set stanishev(value:StanishevLine):void {
if (value != _stanishev) {
if (_stanishev) {
cleanUp(null);
}
_stanishev = value;
initStanishev();
}
}
public function initStanishev():void {
if (_stanishev) {
_stanishev.visible = true;
_stanishev.goToAndPlay('start');
addEventListener(Event.ENTER_FRAME, showStanishevFrame);
addEventListener(Event.REMOVED_FROM_STAGE, cleanUp);
}
}
public function goToState1(e:Event) :void {
goToAndStop(1);
}
public function goToState2(e:Event):void {
goToAndStop('State2');
}
public function showStanishevFrame(e:Event):void {
if (stanishev) {
trace('current frame', stanishev.currentFrame);
}
}
public function cleanUp(e:Event):void {
removeEventListener(Event.ENTER_FRAME, showStanishevFrame);
removeEventListener(Event.REMOVED_FROM_STAGE, cleanUp);
}
}
Note that I'm assuming that you're going to apply OddView as the Base Class of a library symbol. I'm not including any instantiation or positioning logic, since I tend to use the stage for those things.
Note that the reason I check for existence on the stage instances is that it is theoretically possible for someone to assign OddView as the Base Class and not put a btn1, btn2, or stanishev on the stage of that library symbol.
However, this Class is written assuming you're going to handle the visual parts of those 3 items by placing btn1, btn2, and stanishev on the stage where you want them to be.
Also note that I strongly suspect that most of this is completely unnecessary. It's quite possible that you could handle most of this by simply using the over state of btn1. However, that doesn't completely account for why you want to only remove the event listener and take no other action when btn2 is cicked. So I went for "overkill" in the absence of real info about what you're actually trying to accomplish.
Note on the edits
Note what I'm doing there in the setter--if there was already a value stored, we remove the listeners that were on that old, outgoing, listener. Then if the incoming value is not null, we add the new listener.
I still suspect you don't need to do so much, but considering the information you have provided, this should help point you in the right direction.
You could make the variable stanishev in you addadd class a static variable. However I would not recommend doing this, one reason being you can only have one instance of stanishev. Hopefully #Amy Blankenship will tell you how to completely redesign your program, because it needs to be redesigned. This approach will work though, you should also add conditionals to the functions that add and remove eventListeners to stanishev to see if stanishev already has an eventlistener or does not have one.
public class addadd
{
public static var stanishev:stanishev_line = new stanishev_line;
public function addadd()
{
}
public function stanishevFadd()
{
Main.display.addChild(stanishev);
stanishev.gotoAndPlay("start");
stanishev.addEventListener(Event.ENTER_FRAME, frameDOstanishev);
}
public function stanishevFremove()
{
stanishev.removeEventListener(Event.ENTER_FRAME, frameDOstanishev);
}
public function frameDOstanishev(e:Event)
{
trace (stanishev.currentFrame);
}
}
public class Symbol1 extends SimpleButton
{
public function Symbol1()
{
// constructor code
addEventListener(MouseEvent.MOUSE_OVER, eventResponse);
}
function eventResponse(e:MouseEvent)
{
addadd.stanishev.stanishevFadd();
}
}
public class Symbol2 extends SimpleButton
{
public function Symbol2()
{
// constructor code
addEventListener(MouseEvent.MOUSE_DOWN, eventResponse2);
}
function eventResponse2(e:MouseEvent)
{
addadd.stanishev.stanishevFremove();
}
}