AS3 Dynamically change image of object - actionscript-3

How does one change image of already created object
Let's say I have an empty class named Icon and on runtime I want to change its image to something and add it on stage. The image can be from the library as another object or just a bitmap.
var icon1 = new Icon(myIcon);
...
public class Icon extends MovieClip {
public function Icon(icon:Class) {
//change image
addChild(this);
}
EDIT: in java I used to do it like this:
new Icon(myIcon);
...
public class Icon {
public Image image;
public String icon;
public Icon(String icon) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(icon + ".png"));
image = ii.getImage();
this.icon = icon;
}
and on paint method I just type icon1.image to show on screen and also can change image if needed by accessing this variable.
Is this possible to do it something like this on as3?

Let's say I have an empty class named Icon and on runtime I want to
change its image to something
Before code make sure you prepared by following these example steps...
1) Open the Library (ctrl+L) and right click to choose "create new symbol" of MovieClip type and give it the name Icon then look at the Advanced tab further below...
2) Tick the box called "Export For ActionScript" and that should auto-fill a box called Class with text saying Icon. Click OK and you are ready.
3) Add one or two images to Library and right-click to choose "properties" and again like step (2) in the linkage section you tick the "Export for AS" option and give a name you prefer to type later via code. We'll assume you chose names like Pic1 and Pic2. Notice as well that the "base Class" for these bitmaps is bitmapData? That's the data you change to update your image by code.
So to update dynamically by code... Create a bitmap and update its pixel data with any bitmapData from Library. Something like:
//# in your imports...
import flash.display.MovieClip;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.getQualifiedClassName;
import flash.utils.*;
....
//# in vars declarations...
public var my_icon : Icon = new Icon ();
public var my_BMP : Bitmap;
public var str_Type : String = ""; //later holds library object type for checks
....
//# later in your code
stage.addChild(my_icon); //looks invisible since empty
my_BMP = new Bitmap; //create new instance
my_icon.addChild ( my_BMP ); //add the empty bitmap into Icon
change_Icon ( Pic1 ); //parameter can be Library's Bitmap or Movieclip
Making the change_Icon function...
If you just kept it bitmaps (PNG files?) you could use a simple function like this...
public function change_Icon ( in_Param : Class ) : void
{
my_BMP.bitmapData = new in_Param as BitmapData; //replace pixels of existing bitmap container
}
But since you say it could be anything, sometimes a Bitmap or sometimes a MovieClip, well in that case you have to check the input and handle accordingly.
public function change_Icon ( in_Param : * ) : void
{
//# Check the input type and handle it
str_Type = String ( getDefinitionByName( String( getQualifiedSuperclassName(in_Param) ) ) );
if ( str_Type == "[class BitmapData]" )
{
trace ( "this object is a Bitmap..." );
my_BMP.bitmapData = new in_Param as BitmapData; //replace pixels of existing bitmap container
}
if ( str_Type == "[class MovieClip]" )
{
trace ( "this object is a Movieclip..." );
var temp_MC = new in_Param();
var temp_BMD : BitmapData = new BitmapData( temp_MC.width, temp_MC.height );
my_BMP.bitmapData = temp_BMD; //assign data to this bitmap
temp_BMD.draw (temp_MC); //update by drawing
}
}

After adding your icons (image files) to your library, converting them to MovieClips and setting their AS linkage like this, for example :
You can use, for example, a Sprite object to load your icon inside your Icon class instance where your Icon class can be like this, for example :
package {
import flash.display.Sprite;
public class Icon extends Sprite
{
private var _icon:Sprite;
public function Icon(IconClass:Class): void
{
_icon = new IconClass();
addChild(_icon);
}
public function changeIcon(IconClass:Class): void
{
removeChild(_icon);
_icon = new IconClass();
addChild(_icon);
}
}
}
Then in your main code, you can use that class :
import Icon;
var icon:Icon = new Icon(PHPIcon);
addChild(icon);
then to change the icon, you've just to call the changeIcon() function :
icon.changeIcon(JSIcon).
Edit :
If you don't want to call addChild() to add your Icon class's instance to it's parent container, the constructor of your Icon class can be like this for example :
public function Icon(container:DisplayObjectContainer, IconClass:Class): void
{
container.addChild(this);
_icon = new IconClass();
addChild(_icon);
}
then for its instance
var icon:Icon = new Icon(this, PHPIcon);
Hope that can help.

Thanks finally now I have a base class to work with on future projects, I also use list so all I have to do is call new Icon(myIcon, x, y, this);
package {
import flash.display.Sprite;
import flash.display.DisplayObjectContainer;
public class Icon extends Sprite {
public static var list:Array = new Array();
private var icon:Sprite;
private var n:int;
public function Icon(IconClass:Class, x:int, y:int, container:DisplayObjectContainer):void {
container.addChild(this);
icon = new IconClass();
n = list.push(this);
addChild(icon);
this.x = x; this.y = y;
}
public function changeIcon(IconClass:Class):void {
removeChild(icon);
icon = new IconClass();
addChild(icon);
}
public function removeIcon():void {
this.parent.removeChild(this);
list.splice(n-1,1);
}
}
}

Related

Setting a TextField's text from a document class file

I've searched for a while, and nothing is working for me. I'm trying to make an idle game with my friend (who's doing graphics), and I'm just learning AS3 so I thought it'd be an easy-ish project to start with. I don't know how to make a health textbox that outputs the remaining health left. I searched for at least an hour and nothing I found has worked. Here's all my coding. I have numbers embedded for the textbox. The textbox's instance name is "health" so it's not too hard to find.
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip {
public var originalValue:Number = 10;
public var remainingValue:Number = uint(originalValue);
public var clickDamage:Number = 1;
public var health:TextField = String(originalValue);
public var moneyCount:Number=0;
public var mineralValue:Number=5;
public var destroyedCount:Number=0;
mineral.addEventListener(MouseEvent.CLICK, takeDamage);
public function takeDamage(e:Event):void
{
remainingValue = remainingValue - clickDamage;
if (remainingValue <= 0) {
remainingValue = originalValue;
moneyCount += mineralValue;
destroyedCount++;
}
health.text=String(remainingValue);
}
}
}
All I have for symbols so far is my textbox(health) and my button(mineral). Also, what's the difference between an instance name for a textbox symbol, and the instance name for the textbox inside? Sorry if it's a bad question, I'm just really confused and it's ticking me off because I've been trying to work around this problem for a while.
I think your main issue is a lack of understanding of how class files work. I've reworked your class file below and added some comments:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip {
public var originalValue:Number = 10;
public var remainingValue:Number = 10; //no need to convert to uint
public var clickDamage:Number = 1;
public var health:TextField; //you can't assign a string to a text field var //health = String(originalValue);
public var moneyCount:Number=0;
public var mineralValue:Number=5;
public var destroyedCount:Number=0;
//mineral.addEventListener(MouseEvent.CLICK, takeDamage);
//in class files, you can't have lines of code outside of methods/functions create a constructor like below:
//the constructor function must match the name of class, and will run whenever you create an instance of this class
public function Main(){
mineral.addEventListener(MouseEvent.CLICK, takeDamage);
health.text = originalValue; //now assign the text to the text field
//this assumes you have a text field on the main timeline with the instance name of "health"
}
public function takeDamage(e:Event):void
{
remainingValue = remainingValue - clickDamage;
if (remainingValue <= 0) {
remainingValue = originalValue;
moneyCount += mineralValue;
destroyedCount++;
}
health.text= remainingValue.toString();
}
}
}
If (as may be gleamed from comment in your question), you have your health text field encapsulated in a symbol/movie clip, you'll need to access it like so:
myHealthSymbolInstanceName.myHealthTextBoxInstance.text = value;

Adding eventlisteners in main document class for external classes

I have a small project I'm trying to help learn as3. It is a variation from the book Foundation Game Design with Actionscript 3.0. I am using an fla only to have a document class. All art is loaded within the as files. In the book, he just put all the code in the document class, I followed along and it worked as expected. I am trying to break out the code into separate classes to get a handle on OOP. One class makes a background - Background.as, one makes a character - Character.as, and one makes a button, which I instantiate 6 times for 6 different buttons - GameButton.as. And of course there is GameWorld.as which is the document class. Everything loads and shows up as expected. However when I try and add an eventListener for the buttons, I don't get any response. I have tried putting the eventListener in the GameButton.as and also tried it in the GameWorld.as neither of which has worked. Also I pass a reference to the stage when instantiating the various classes, because when I tried to addChild in the GameWorld.as, nothing would show up. I searched the site and found something similar, but it didn't seem to help. Thank you in advance for any advice you my have. Here is the code:
GameWorld.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.DisplayObject
import flash.events.MouseEvent;
import GameButton;
import Character;
import Background;
[SWR(width = "550", height = "400", backgroundColor = "#FFFFFF", frameRate = "60")]
public class GameWorld extends Sprite
{
//public variables
//Background
public var gameBackground:Background;
//Character
public var catCharacter:Character;
//Buttons
public var upButton:GameButton;
public var downButton:GameButton;
public var growButton:GameButton;
public var shrinkButton:GameButton;
public var vanishButton:GameButton;
public var spinButton:GameButton;
public function GameWorld ()
{
//Add the background to the stage
gameBackground = new Background("../images/background.png", stage);
//Add the character(s) to the stage
catCharacter = new Character("../images/character.png", stage);
//Set initial character position
catCharacter.CharacterPos(225, 150);
//Add the buttons to the stage
upButton = new GameButton("../images/up.png", stage, 25, 25);
downButton = new GameButton("../images/down.png", stage, 25, 85);
growButton = new GameButton("../images/grow.png", stage, 25, 145);
shrinkButton = new GameButton("../images/shrink.png", stage, 425, 25);
vanishButton = new GameButton("../images/vanish.png", stage, 425, 85);
spinButton = new GameButton("../images/spin.png", stage, 425, 145);
//Button event handlers
upButton.addEventListener(MouseEvent.CLICK, upButtonHandler);
}
public function upButtonHandler(event:MouseEvent)
{
trace("You clicked the up button!");
catCharacter.CharacterMove(15);
}
}
}
GameButton.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
public class GameButton extends Sprite
{
//public variables
public var stageRef:Stage;
public var urlRequest:URLRequest;
public var gameButtonLoader:Loader;
public var gameButtonSprite:Sprite;
//Constructor
public function GameButton (urlRequest:String, stageRef:Stage, xPos:Number, yPos:Number)
{
this.stageRef = stageRef
this.urlRequest = new URLRequest();
gameButtonLoader = new Loader();
gameButtonSprite = new Sprite();
this.urlRequest.url = urlRequest;
gameButtonLoader.load(this.urlRequest);
gameButtonSprite.addChild(gameButtonLoader);
this.stageRef.addChild(gameButtonSprite);
gameButtonSprite.buttonMode = true;
gameButtonSprite.x = xPos;
gameButtonSprite.y = yPos;
}
}
}
Character.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
public class Character
{
//private variables
private var stageRef:Stage;
private var urlRequest:URLRequest;
private var characterLoader:Loader;
private var characterSprite:Sprite;
//public variables
public var character_x_pos:Number;
public var character_y_pos:Number;
//Constructor
public function Character (urlRequest:String, stageRef:Stage)
{
this.stageRef = stageRef;
this.urlRequest = new URLRequest();
characterLoader = new Loader();
characterSprite = new Sprite();
this.urlRequest.url = urlRequest;
characterLoader.load (this.urlRequest);
characterSprite.addChild (characterLoader);
this.stageRef.addChild (characterSprite);
characterSprite.mouseEnabled = false;
}
//Set the position of the character
public function CharacterPos(xPos:Number, yPos:Number):void
{
characterSprite.x = xPos;
characterSprite.y = yPos;
}
//Move the position of the character
public function CharacterMove( yPos:Number):void
{
characterSprite.y -= yPos;
}
}
}
Background.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
public class Background
{
//Private variables
private var stageRef:Stage;
private var urlRequest:URLRequest;
private var backgroundLoader:Loader;
private var backgroundSprite:Sprite;
//Constructor
public function Background (urlRequest:String, stageRef:Stage)
{
this.stageRef = stageRef;
this.urlRequest = new URLRequest();
backgroundLoader = new Loader();
backgroundSprite = new Sprite();
this.urlRequest.url = urlRequest;
backgroundLoader.load (this.urlRequest);
backgroundSprite.addChild (backgroundLoader);
this.stageRef.addChild (backgroundSprite);
backgroundSprite.mouseEnabled = false;
}
}
}
All art is loaded within the as files.
This is not an approach I recommend. There's a reason God gave us the Flash IDE--and it's not to write code! Any time you're spending on layout and viduals in code is just wasted, unless you have an actual requirement to change the visuals at runtime. The fact that your paths are all hard-coded suggests that you don't have that requirement.
So let's step back and imagine that you have a Symbol that contains 6 Symbols that you've created as just Flash buttons (when you select Button as the Symbol type). These will be SimpleButtons, but in the Class below we're just going to type them as DisplayObject. The Class doesn't care what they are, but using Simplebutton gives them up, over, down and hit states that require no code.
Note that the below assumes you have "automatically declare stage instances" off, which is IMO the best way to do things.
package view {
public class NavBar extends Sprite {
//because you put these on stage in the Symbol, they will be available in the constructor
public var upButton:DisplayObject;
public var downButton:DisplayObject;
public var growButton:DisplayObject;
public var shrinkButton:DisplayObject;
public var rotateButton:DisplayObject;
public var vanishButton:DisplayObject;
//makes it easier to do the same setup on all buttons
protected var allButtons:Vector.<DisplayObject> = <DisplayObject>([upButton, downButton, growButton, shrinkButton, rotateButton, vanishButton]);
public function NavBar() {
super();
for each (var btn:DisplayObject in allButtons) {
btn.buttonMode = true;
btn.mouseChildren = false;
btn.addEventListener(MouseEvent.CLICK, onButtonClick);
}
}
protected function onButtonClick(e:MouseEvent):void {
switch (e.target) {
case upButton:
dispatchEvent(new CharacterEvent(CharacterEvent.UP));
break;
case downButton:
dispatchEvent(new CharacterEvent(CharacterEvent.DOWN));
break;
case growButton:
dispatchEvent(new CharacterEvent(CharacterEvent.GROW));
break;
case shrinkButton:
dispatchEvent(new CharacterEvent(CharacterEvent.SHRINK));
break;
case rotateButton:
dispatchEvent(new CharacterEvent(CharacterEvent.ROTATE));
break;
case vanishButton:
dispatchEvent(new CharacterEvent(CharacterEvent.VANISH));
break;
default:
break;
}
}
}
}
Note that there's zero layout code. This code is dependent on a custom Event Class. I'm going to write that Event Class so that it always bubbles. That way, it can be dispatched anywhere on the display list and received at the top level:
package control {
class CharacterEvent extends Event {
public static var UP:String = 'characterUp';
public static var DOWN:String = 'characterDown';
public static var GROW:String = 'characterGrow';
public static var SHRINK:String = 'characterShrink';
public static var ROTATE:String = 'characterRotate';
public static var VANISH:String = 'characterVanish';
public function CharacterEvent(type:String) {
super(type, true, true);//always bubbles
}
public function clone():Event {
return new CharacterEvent(type);
}
}
}
Now, if you want to manually handle instantiation of the Symbol that has view.NavBar as its base class, it will look like this:
package {
public var navBar:NavBar;
class GameWorld {
public function GameWorld() {
try {
var navClass:Class = getDefinitionByName('NavBarSymbol') as Class;
} catch (e:Error) {
trace('You need to have a Library symbol called NavBarSymbol');
}
if (navClass) {
navBar = new navClass() as NavBar;
//unnecessary layout code here
//Note that this is NOT the responsibility of the child Class!
addChild(navBar);
}
//instantiate character
...
//by listening to the whole Document, you can add other things that
//dispatch Character events on the display list, like a keyboard listener
addEventListener(CharacterEvent.UP, moveCharacterUp);
//listeners for the rest of the character events...
}
public function moveCharacterUp(e:CharacterEvent):void {
//character move logic
}
//other handlers
}
}
Personally, I'd just add the navBar to the stage, and then there's no need to manage it at all (not even reference it with a variable), simply add the event listeners for the various character events.
The root of your problem doesn't seem to be the character code. However, I'm going to give you a few "best practice" pointers about it.
The convention in AS3 is for Class members (properties and methods) to be camel case starting with a lower case letter. So, characterPos() and characterMove().
Your Class already contains character in the name, so really these should just be pos() and move() (though there's no need now to shorten position()).
The only thing your child Classes are doing with their references to the parent are adding themselves. They don't need and shouldn't have a reference to the parent for this purpose. It is the parent's responsibility to add the Children (or the responsibility of the Flash Player if you use the stage).
That said, you could give your Character a reference to the parent Class typed as IEventDispatcher and allow the Character to listen to this channel. This concept is called an event bus.
Note that the reason that so many people do what you're doing is that Adobe failed to document how to properly use OOP with the timeline. Unfortunately, by the time a few of us started documenting that around late 2009/early 2010, the damage was done and everyone assumed that if you wanted to write good code you had to pretend the timeline and stage didn't exist.
I know I've covered a lot of ground, and probably most of what I said directly contradicts what you thought you knew, so please don't hesitate to ask any questions you might have.

Unable to have Flash Component (SWC) access the library in live preview

I am building a set of Flash components with the ability to replace the skin of the component with another one in the library.
Currently, I am able to access the library after running the application, but not during live preview and I'd like to know if it is possible for the component to access the library while running in live preview mode (the mode where you can drag the component around the stage and change its properties in the Component Parameters window)
Here is a simplified code that just looks to see if there is a symbol of the name specified and than instantiates it and adds it as a child.
package
{
import fl.core.UIComponent;
import flash.display.MovieClip;
import flash.system.ApplicationDomain;
/**
* ...
* #author Roy Lazarovich
*/
public class CompTest extends UIComponent
{
private var customfile :String;
public function CompTest()
{
}
override protected function configUI():void
{
}
override protected function draw():void
{
super.draw();
}
private function setCustomFile():void
{
if (ApplicationDomain.currentDomain.hasDefinition(customfile))
{
var c:Class = Class(ApplicationDomain.currentDomain.getDefinition(customfile));
var mc:MovieClip = new c();
addChild(mc);
}
}
[Inspectable(name = "_Custom File", defaultValue = "")]
public function set _customfile(value:String):void
{
customfile = value;
setCustomFile();
drawNow();
}
}
}
Thanks!
I'm not entirely sure what you have already tried to fix this situation. But hopefully this might help.
Right click on the MovieClip in your library, select Linkage and give it a class name, ie. MyThing.
In your code,
newMyThing = new MyThing();
this.addChild(newMyThing);
trace("tada!");
Hope that helps or gets you closer to a solution.
This works for me in LivePreview, as long as I apply it in configUI, and not draw:
public class EditableBitmap extends UIComponent
{
protected var placeholder:String = "None";
protected var bitmap:Bitmap;
protected var scale:Number = 1;
[Inspectable(name = "Placeholder", type = String, defaultValue="None")]
public function set Placeholder($value:String):void
{
placeholder = $value;
configUI();
}
public function get Placeholder():String { return placeholder; }
public function EditableBitmap()
{
//Console.Debug("NEW EditableBitmap");
super();
}
override protected function configUI():void
{
//Console.Debug("EditableBitmap configUI: " + width);
if (!isNaN(width))
{
wDim = width;
hDim = height;
graphics.clear();
graphics.beginFill(0x000000, 0.1);
graphics.drawRect(0, 0, wDim, hDim);
}
if (placeholder != "None" && placeholder != "")
{
var asset:Class = getDefinitionByName(placeholder) as Class;
var data:BitmapData = new asset() as BitmapData;
bitmap = new Bitmap(data);
}
super.configUI();
}
override protected function draw():void
{
if (bitmap)
{
addChild(bitmap);
bitmap.x = off_x * scale;
bitmap.y = off_y * scale;
bitmap.scaleX = bitmap.scaleY = scale;
}
}
}
NOTE: When I'm working on the FLA where I am editing the component, the bitmap is only displayed from the library inconsistenty. Sometimes it works, sometimes it doesn't. But when I export the SWC and then import the component to another movie, it works every time, in LivePreview as well as at runtime.
UPDATE
It seems this doesn't work in CS6 unless the symbol is already embedded in the component .SWC I wanted to see if I could trick it, by embedding one image in the SWC and then replacing it with another of the same name in the destination file. This didn't work, but it did point me to how you can do this:
So, it's a bit laborious, but you could work around this by:
1) Creating a dummy asset for each property in the component SWC.
2) Overriding this using a custom class in the file where you deploy the component
... all of which may be more trouble than it's worth, but which should provide a solution to the problem.

How to assign properties of a component inside an MC loaded from a Library?

I have a Library item: MovieClip with a single ComboBox component inside. The item has a Class assigned to it, myMC.
What I want to achieve is that a call from the main movie like var mmc:myMC = new myMC( stage); would:
initialize the ComboBox instance's values;
place the myMC instance on stage (or inside another MC).
So inside the myMC Constructor I wrote smth like:
public function myMc( theStage:flash.display.Stage) {
if( stage == null) this.addEventListener( Event.ADDED_TO_STAGE, init);
theStage.addChild( this);
}
public function init( e:Event = null) {
var Data:Array= new Array(
{'label1' : 'item1'},
{'label2' : 'item2'},
{'label3' : 'item3'}
);
cbox.dataProvider = new DataProvider( Data);
}
cbox is the name of ComboBox instance within myMC.
What happens is that the ComboBox doesn't have any values assigned. This is a simplified example of my problem, whereas the actual case involves more UI components — all of them miss their values.
Debugger show the component objects of correct type, with the values - but they miss from the stage objects shown!
Please explain, what am I doing wrong - and why does the instance on stage is somehow different from the AS instantiated Object?
Ok, seems that it was my mistake: wrong types and messy code.
Here's an example that works afterall. So, maybe its not the best practice to put an object onstage by its own constructor, however this works. The working example sources.
Main document has a class DocTest:
package {
import flash.display.Sprite;
import libItem;
public class DocTest extends Sprite {
public function DocTest() {
var instance:libItem = new libItem( this);
}
}
}
And the library item has a ComboBox and a text field inside, and the following Class code attached:
package {
import fl.data.DataProvider;
import flash.display.Sprite;
import flash.events.Event;
public class libItem extends Sprite{
public function libItem( theParent:flash.display.Sprite) {
if( stage == null) this.addEventListener( Event.ADDED_TO_STAGE, init);
else init();
theParent.addChild( this);
}
public function init( e:Event = null) {
var Data:Array= new Array(
{label:'label1', data: 'item1'},
{label:'label2', data: 'item2'},
{label:'label3', data: 'item3'}
);
cbox.dataProvider = new DataProvider( Data);
x = 200;
y = 100;
myText.text = 'Woo-hoo!';
}
}
}
Hope this helps someone. Sorry for the studid question.

AS3.0: Acces properties of created instance from 2nd class

I'm building a small game.
On my document class i create a instances of the class Character and Level with the following code:
//add the Level
level = new TileGrid();
level.y = 100;
level.x = 400;
addChild(player);
//add our player
player = new Character();
player.y = 150;
player.x = 400;
addChild(player);
I also create a controller class which handles the user input. (for example checks if the player is able to move to the right.)
I also create eventlisteners for keyboardevents and stuff.
When a key is pressed i want to check if the movement is possible by calling the checkTile(tileNumber) function of the TileGrid class from within the controller class.
The controller class looks like this:
package {
import flash.events.KeyboardEvent;
import flash.events.Event;
public class Controller{
//Constructor code
public function Controller(){}
//Keyboard pressed -> move character
public function keyPressed(evt:KeyboardEvent):void
{
trace(level.checkTile(30));
}
}
And the TileGrid class looks something like this:
package {
import flash.events.KeyboardEvent;
import flash.events.Event;
public class TileGrid{
//Constructor code
public function TileGrid(){
//Creating all the tiles and adding them to the stage.
}
//Check if a certain tile is walkable
public function checkTile(tileNumberType){
if(tileNumberType > 15){
return false;
}else{
return true;
}
}
}
But when i test this i get the following error:
Line 81 1120: Access of undefined property level.
When i try: trace(Object(parent).level.checkTile(30)); i get: 1120: Access of undefined property parent.
How can i access methods from one class with an instance from a second class ?
I think you must do something like this:
...
// somewhere in your document class (or somewhere else)
var player:Character = new Character();
var level:TileGrid = new TileGrid();
var controller:Controller = new Controller(player, level);
...
// in your Controller class
private var level:TileGrid;
private var player:Character;
public Controller(player:Character, level:TileGrid) {
this.player = player;
this.level = level;
}
public function keyPressed(event:KeyboardEvent):void {
level.checkTile(30); // in this line "level" means "this.level"
}
In that case you must say which player and which level the controller must control. The controller is a class that has no knowledge of any other class. The variables are not global (in your example, and they shouldn't be) so you can't acces them from everywhere.
Classes in AS can't access their context. This means that if I have:
function foo():void
{
var k:MyCustomClass = new MyCustomClass();
var j:MyOtherClass = new MyOtherClass();
}
the two instances j and k don't know about each other.
In this particular case, however, because you're clearly dealing with a parent structure, it is possible to get the parent's properties. This is possible because you have a path to the variable in a public scope.
Try this instead:
trace(Object(parent).level.checkTile(30));
Also note the Object(parent). A DisplayObject's parent is a DisplayObjectContainer, which does not have a level property. By wrapping parent in Object, however, you're telling Flash, "It's OK, you should look for this property at runtime not when compiling."