AS3 OOP inheritance and functions - actionscript-3

I am hoping someone could help me with a problem I am having trying to integrate as3 code from a puzzle I have created into my game FLA file.
In Game.fla I have a main class called Engine that contains that calls a number of empty movie clips from the library to the stage and then populates each movie clip with assets from the library. Each movie clip has its own class associated with it.
I have created each puzzle in a separate file with its own main class to test and make sure the puzzles work, when I try to add the code for a puzzle to a movieclip class I am getting a number of errors
output error
**Warning** The linkage identifier 'feedback2' was already
assigned to the symbol 'wrong_box', and cannot be assigned
to the symbol 'graphics/scrambleAssets/wrong_box',
since linkage identifiers must be unique.
and compiler error
Line 132 1136: Incorrect number of arguments. Expected 1.
line 132 is this:
if(ques_num==words.length){removeChild(checker);
f3=new feedback3;
addChild(f3);
f3.x=100;
f3.y=100;
}else{
getword();}
Main Class
public function show_level1Puzzle(){
level1Puzzle_screen = new level1Puzzle(this);
remove_levelChooseBoy();
addChild(levelPuzzleBoy_screen);
level1Puzzle_screen.x=510;
level1Puzzle_screen.y=380;
}
** Class for level1Puzzle**
package actions {
import flash.display.MovieClip;
public class level1Puzzle extends MovieClip {
public var main_class:Engine;
// variables used in puzzle
var words:Array = new Array;
Var rand1:int;var rand2:int;
var i:int; //variable used for loop iterations
// more variables
public function level1Puzzle(passed_class:Engine) {
main_class = passed_class;
public function getword(passed_class:Engine) {
main_class = passed_class;
words=["cat","dog"];
current_word=words[ques_num];
setTiles(current_word.length);
ques_num++;
}
public function setTiles(a) {tileArray=[ ];
for(i=0;i<a;i++){
var tempclip:Tile =new Tile;addChild(tempclip);
tempclip.x=300+(i*180);tempclip.y=200;tempclip.tag=i;
tempclip.original_posx=tempclip.x;
tempclip.original_posy=tempclip.y;
tileArray[i]=tempclip;
var tempclip2:Placeholder =new Placeholder;addChild(tempclip2);
tempclip2.x=300+(i*180);tempclip2.y=400;
targetArray[i]=tempclip2;
}//for i
scramble_word(a);
}
//MORE FUNCTIONS FOR PUZZLE

This function has a parameter :
public function getword(passed_class:Engine) {
main_class = passed_class;
words=["cat","dog"];
current_word=words[ques_num];
setTiles(current_word.length);
ques_num++;
}
On line 132, you are not passing a parameter, so that is the reason for the error message.

Related

as3 #1009 error code provided. "Null Object reference"

hi I'm relatively new to as3 (this year) and I'm getting this error
typer error #1009 cannot access a property or method of a null object
reference. at FoodObject/collisionTest()
i was hoping anyone could help
package {
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.*
import flash.utils.*
import flash.display.Stage;
public class GameScene1 extends Scene {
//public variables
//character & scenery
public var mainChar: Character;
public var testFood: FoodObject;
//constructor is used to create all necessary objects for this scene and display them
public function GameScene1(gm_: Manager) {
//constructor
super(gm_);
trace("GameScene 1 constructor");
//character
mainChar = new Character;
addChild(mainChar);
mainChar.x = 200;
mainChar.y = 200;
testFood = new FoodObject;
addChild(testFood)
testFood.x = 50
testFood.y = 200
the food object class is here.
package {
import GameScene1
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
public class FoodObject extends MovieClip {
public var Game1:GameScene1;
public function FoodObject() {
//constructor code
this.addEventListener(Event.ENTER_FRAME, collisionTest)
}
public function collisionTest(e:Event)
{
if (this.hitTestObject(Game1.mainChar))
{
trace("it works")
}
}
}
}
game manager here:
package {
import flash.display.MovieClip;
public class Manager extends MovieClip {
//stores which scene is currently loaded
public var curScene:Scene=null;
public function Manager() {
//constructor
trace("Manager Construct")
GoToScene("menu");
}
public function GoToScene(name:String)
{
if (curScene) //there was a scene already
{
curScene.OnLeaveScene(); //call its OnLeaveScene function to remove all objects
removeChild(curScene);
}
if(name=="menu") curScene = new MenuScene(this);
if(name=="select") curScene = new SelectScene(this);
if(name=="game1") curScene = new GameScene1(this);
if(name=="game2") curScene = new GameScene2(this);
if(name=="game3") curScene = new GameScene3(this);
if(name=="credit") curScene = new CreditScene(this);
addChild(curScene);
}
}
Your problem is that the concerns of your classes are not separate:
Your Scene knows both the Character and the Food object, you instantiate both classes there, nothing wrong with that.
The problem starts when you are trying to do something in the Food object, that requires knowledge of the character. The thing is: the Food object doesn't know anything about the Character.
You can solve this by simply passing the reference of Character to your Food object. In order to do this, modify the constructor like so:
private var character:Character;
public function FoodObject(character:Character) {
//constructor code
this.addEventListener(Event.ENTER_FRAME, collisionTest)
this.character = character;
}
The usage of said constructor in your Scene changes as follows:
testFood = new FoodObject(mainCharacter);
This way, Food knows the character and can do stuff with it, for example do collision tests:
public function collisionTest(e:Event)
{
if (this.hitTestObject(character)) // ==== this line changed
{
trace("it works")
}
}
However, this raises an important issue: Why should Food know the Character at all?
Sure enough, you want to do the collision test, which requires both objects.
But why do you want to do it in the Food object?
Doing the collision check in Food is cumbersome, because you have to pass a reference to Character in order to do it there.
The much preferred way of doing this is to do the collision check where both objects participating in the check are already known.
In your case, this is the Scene.
Think about how easy it is to do the check in Scene:
testFood.hitTestObject(mainCharacter);
It's that simple, because everything you need is already there.
To recap:
The collision check requires knowledge of 2 objects that you want to
check.
In order to do the check in either one, you have to pass a reference
of the other. (Character to Food as seen above or the other way
round)
It is a lot easier to do the check in some place that already knows
both objects, because no reference have to be passed around.
Your original code failed because Game1 in FoodObject is never assigned a value and therefore remains null.
Invoking methods on null causes the error you experienced.
You forgot to take the instance of GameScene1 class using new keyword.
public var Game1:GameScene1;
public function FoodObject() {
//constructor code
var _manager:Manager = new Manager();
Game1 = new GameScene1(_manager)
this.addEventListener(Event.ENTER_FRAME, collisionTest);
}
public function collisionTest(e:Event):void{
....
}

Object On Stage Cannot Be Accessed From External Class

I have an external ActionScript class, which is called Menu.as, trying to access objects on the stage using the following code:
MovieClip(parent).fullmenu_mc.x = 80;
Although the program compiles, I get Error #1009: Cannot access a property or method of a null object reference
I don't see how this is possible since the object is already on the stage and just needs to be accessed. Am I somehow accessing the object incorrectly?
I also tried the following code inside Menu.as:
import EngineClass;
var engine : EngineClass = new EngineClass();
engine.fullmenu_mc.x = 80;
which gives the same runtime error. Any thoughts are welcome!
Short Version:
Basically you first need to setup a variable that acts a reference name to your on-stage movieclip. You can instead make it a public static variable if you want other Class files imported to also control this variable (and therefore also the movieclip) from their own Class code.
So define a public static var menuMC : MovieClip = new MovieClip(); then when Stage + stage items is available (since Flash processes code first then makes a Stage + items after), we update definition to know the instance name of on-stage object it represents by saying: menuMC = DisplayObjectContainer(getChildByName("fullmenu_mc")) as MovieClip;
Now you can update via any imported external class using a line like: Main.menuMC.x = 200; (where Main is the name of Class that holds the definition of what menuMC means).
Long Version:
Assuming you have some setup like this.
fullmenu_mc = instance name of Object on stage
Main.as = your FLA's document Class file attached to hold the main running code
External.as = some other external Class file that will also control the
on-stage MC
Note: If your code is on the timeline instead of a (Main.as) document class let me know to update (if possible), but the above Classes setup would be easier...
In Main.as.. (define variable and also run a function that is inside external Class)
package
{
import flash.display.MovieClip;
import flash.display.*;
import flash.events.*;
import External;
public class Main extends MovieClip
{
public var ExtClass : External = new External; //init the external class
public static var menuMC : MovieClip = new MovieClip(); //reference to on-stage MC
public function Main ()
{
if (stage != null) { Init(); } //do Init function if SWF loaded ok...
else { addEventListener (Event.ADDED_TO_STAGE, Init); } //or do the function when ready..
}
//If stage is available then we can now do this
public function Init (event:Event = null) :void
{
//update menuMC to know it means some item "X" on stage. "X" is instance name
menuMC = DisplayObjectContainer(getChildByName("fullmenu_mc")) as MovieClip;
trace("menuMC is type : " + menuMC); //if ok then traces [object MovieClip]
menuMC.x = 10; //just for testing
ExtClass.accessTest(); //run some function in External class
}
}
}
Now in External.as we can control the fullmenu_mc (now known as menuMC) like so..
public function accessTest () :void
{
//access stage item using Static Variable from Main Class
Main.menuMC.x += 500;
trace("Full_menu... new x-pos is : " + Main.menuMC.x);
}

AS3 Class Error

I am trying to make a game in flash using AS3. I am making a class file that set the parameters for creating a new planet, but when I then add the actions to the first frame of the timeline, it immediately gives me an error. I am new to action script and would love any help. My code should work as far as I know. Here it is:
The actions menu contains this code on the first frame -
var zuun:MovieClip = new Planet();
The class "Planet" looks like this, and is saved in a file name "Planet.as" and is targeted at my main file.
package {
import flash.display.MovieClip;
public class Planet extends MovieClip {
private var planetname:String;
public function Planet() {
// constructor code
}
public function setName(a:String):void {
planetname = a;
}
public function getName():String {
return planetname;
}
}
}
EDIT
The error i'm getting is this -
Error: Error #2136: The SWF file file:///Users/mike/Desktop/jonah/bindings.swf contains invalid data.
at Planet/frame1()[Planet::frame1:1]
Thanks

stage.loaderInfo.parameters works but LoaderInfo(this.root.loaderInfo).parameters doesn't

I am passing Flashvars in my game.html file.
MyClass is the Document class name for my game.swf
public class MyClass extends MovieClip {
public function MyClass() {
loaderInfo.addEventListener(Event.COMPLETE, _Init);
}
public function _Init(e:Event) {
var parameters:Object = LoaderInfo(this.root.loaderInfo).parameters;
// There is nothing in parameters object.
}
}
My game.fla contains various layers on the main timeline. I have another game which has only one layer and that game loads the parameters correctly. I am finding this very strange.
Note:
trace root.name in the above code -> instance8 (there are 8 layers in the time line)
trace root.name in the other game (in which flashvars is working) -> root1 is the traced output
Am I missing something very basic here?
Solved this but couldn't understand the reason
So, I changed the line
var parameters:Object = LoaderInfo(this.root.loaderInfo).parameters;
to
var parameters:Object = stage.loaderInfo.parameters;
Why did the first approach didn't work?

AS3: Access my Main.as from a movieclip on stage

Using Adobe Flash Professional CS6, AS3
Please let me know if I need to provide any more info
I am trying to set up a navigation menu and my question is, "How do I get a MovieClip to call a function in my Main.as file from the Stage?" There is only one frame (I do not want more) and the different menu screens, which are just MovieClips, are added to the stage with AS when needed. I have a public function in the file Main.as called _About(), that my MovieClip, "MenuScreen", cannot access. I can successfully have _Menu() add a MovieClip to the stage with eventListeners, but when the mc makes the call back to change screens I get this error:
TypeError: Error #1034: Type Coercion failed: cannot convert flash.display::Stage#51ca0d1 to flash.display.MovieClip. at MenuScreen/clickAbout()[MenuScreen::frame1:32]
Frame1:32's code is:
MovieClip(parent)._About();
Line 51 in my Main.as is:
public function _About():void
{
trace("The About Function");
}
Below I have detailed more about Main.as with most of the fat trimmed.
package
{
import stuff
public class Main extends MovieClip
{
//Load the screen MCs onto the stage
public var _menu:MenuScreen = new MenuScreen();
public var _about:AboutScreen = new AboutScreen();
public var isMenu:Boolean = true;
public var isAbout:Boolean = false;
public function Main()
{
_Menu();
}
public function _Menu():void
{
isMenu = true;
stage.addChild(_menu);
}
public function _About():void
{
trace("The About Function");
}
An easy solution to your problem would be to add the menu items not to the stage! Instead add them to your main class. This way the parent of your items is instead main.as
But then you need to cast the parent to Main
Main(parent)._About();
Also not very nice. The items should not now what is behind them.
The best way is to do it, is to dispatch events from the different screens.
Means: you create your screen objects an there are dispatching custom events when a screnn change should happen.
dispatchEvent(new Event("showAbout"));
in your main class you handle the events like:
public function Main()
{
_Menu();
_menu = new MenuScreen();
_menu.addEventHandler("showAbout", showAboutHandler);
}
public function showAboutHanlder(e:Event):void
{
_About();
}
Even more better is a custom event with a screen identifier as a param. This way you just add one handler and decide in the handler code which screen to be displayed.
With the event handling in place, your menu items have no direct connection to the main. Also the main needs no further information about the screen classes.
Set static property :
public static var instance:Main;
public function Main(){
instance = this;
_Menu();
}
and then from anywhere You can use code :
Main.instance._About();
It would help to see MenuScreen's complete class, but here's what's probably going on:
You're instantiating at public var _menu:MenuScreen = new MenuScreen(); and when this happens it's probably making the call to MovieClip(parent)._About() before you've added MenuScreen to the stage at stage.addChild(_menu); - It doesn't have a parent yet when this occurs and the error incurs.
Two ways to get around this:
Add a required parameter in MenuScreen's constructor that references your Main class. Your constructor in MenuScreen would start with public function MenuScreen($main:Main){ and when you instantiate MenuScreen from Main class you would write public var _menu:MenuScreen = new MenuScreen(this); now you can use $main._About() in MenuScreen's constuctor.
In MenuScreen's constructor add a listener that checks when it's been added to the stage: addEventListener(Event.ADDED_TO_STAGE, addedStage). In the function addedStage you can properly call for a parent or the stage, and MovieClip(parent)._About() will probably work here.