PDA

View Full Version : Trouble communicating between classes.



NJB
January 26th, 2009, 02:04 PM
I'm having a little trouble with adapting to AS3.
I'm trying to call a function from a class that I've instantiated on the main timeline from another class that I've also instantiated on the timeline.
The function I'm trying to call adds a line to a string that acts as a game terminal so that even if the game glitches for someone without the source code, it would be possible to read the variable changes and functions called. (it also doubles up as an input for unlocking characters and levels that are otherwise hidden)

Main Timeline:

import britland.Character;
import game.terminal;
var GameTerm=new Terminal();
var TeaGirl=new Character("Tea Girl");

game.terminal.as:

package game{
class terminal {
var termData:String;
var termComm:Array;
public function terminal():void {
this.addEntry("Terminal Initiated.");
}
public function addEntry(input:String) {
termData+=("\n"+input);
trace(termData);
}
}
}

britland.character.as

package britland{
public class Character {
var charName:String;
var charHP:int;
var charHit:int;
var charKick:int;
var charSpec:int;
var charBlock:int;
public function Character(CName:String) {
charName=CName;
//trace("Character Created:"+charName);
(*see note).GameTerm.addEntry("Character: "+charName+" created.");
}
}
}
* I've tried both "flash.display.DisplayObject.stage" and "this.parent.parent" here after discovered that "_root" has been removed and "root" doesn't work in the same way.

Any help would be most welcome.

cbeech
January 26th, 2009, 02:42 PM
instead from the class, cast the root as a MovieClip to target the root, and then the terminal instance as you are doing - so more like:

MovieClip(root).GameTerm.addEntry("...");

however this also may not work until the instance has been added to the Display List. so an alternative solution is to pass an instance of the root timeline to the class within the constructor, also setting up a property within the class to 'store' the reference:

var TeaGirl = new Character(this, 'Tea Girl');

//::in the Character class add
private var doc:Object;

public function Character(scope, CName) {
doc = scope;
charName = CName;
doc.GameTerm.addEntry(...);
}

NJB
January 26th, 2009, 03:30 PM
With the first solution, I'm afraid to say that not much happened, this is the output it gave me:

1180: Call to a possibly undefined method MovieClip.�
1120: Access of undefined property root.�

the second one shows promise, but it's failing to recognise the terminal now:
Tried a few of the obvious things, (like checking that the constructor is spelled correctly and such) but aside from that, I'm not sure what to do.
Error Message:


1180: Call to a possibly undefined method terminal.�

Thanks a million for your input though!

cbeech
January 26th, 2009, 04:16 PM
you're welcome :) but in further review, i see that there may be a few other things you want to do in your classes depending on their purpose and structure in the game. in most situations you are going to want to 'extend' a class from one of the base Flash classes, such as MovieClip, this will grant you access to the properties and methods of the base class which you can then (and likely will) use within other methods of the class. to do so (as example) you write this like:

public class Character extends MovieClip { ... }

now another aspect that seems to be missing here is that whenever you are using AS files to define your classes you have to 'import' the base classes that you will be accessing within the class. so the 'reason' that you got an error in the first solution above is that there was not the class necessary to cast the root as a MovieClip. (however since there is no associtated Library asset at this point, it is likely that this will not work for you) so often we will import a base Flash package, or you can pull each in individually. so, the import statement belongs within the package object and previous to the class definition, like for example:

package britland{
import flash.display.*;
import flash.events.*;
public class Character extends MovieClip {
...
}
}

now you will be able to use 'MovieClip' within your class to cast the root and access the timeline. (although there are other ways to go about this as well) and as I'd mentioned, you still may not be able to do so until an instance of the class is added to the Display list of the root using addChild. (which is seems is not really the purpose of your class here - so this probably wont work for you)

as to the 'terminal' issue - i notice that in the constructor line you have: new Terminal() - when the name of your class is 'terminal'... not only spelling but 'case' makes a difference in Flash, they must be identicle. so the constructor should read:

var GameTerm:terminal = new terminal();

NJB
January 26th, 2009, 04:39 PM
Yeah, I'm trying not to import anything at the moment, as I'd rather have a few classes that don't repeat a lot of the code, Character for example will be a class that is extended by "player" and "enemy" which I'll be coding once I've got everything I need in character.as coded and running smoothly. the only thing that the two classes that will extend this will do is set the name, stats and control type (human input/AI).

The on the terminal question, sorry, I'd already updated the uppercase problem but hadn't changed the code in the top post.
interestingly though, when I change "var GameTerm = new terminal();" to "var GameTerm:terminal = new terminal();" it throws up a new error in addition to the first one:
1046: Type was not found or was not a compile-time constant: terminal.

cbeech
January 26th, 2009, 05:05 PM
ahhh, i see. then these super classes will import the needed bases - ok, however it will make things difficult for you unless you at least set up a those 'empty' classes (with the bases and extensions) previous to building these - just a thought.

i think you need to remove the directory path from the package statements in both classes AS files - since you are importing them in the main timeline and calling the full class path there.

NJB
January 26th, 2009, 05:13 PM
I've just realised what the error was, and I could kick myself for being this thick.
I forgot to make the terminal class public. that was why it wasn't being instantiated, it couldn't be accessed!
it's working... for now.
I think I'll have to go and pray to (insert generic deit(y/ies) here that I won't have too many other troubles.

I'm not quite sure I understand the second part of your post by the way. I keep the package declaration in because otherwise it throws up a lot of errors about the class not being defined.

Thanks again for helping me out.