GetDefinition in as3 using sprite class - actionscript-3

i have a problem. I have been able to run my game successfully using as3isolib library (IsoSprites), but when i search on the internet, the IsoSprites don't have the hitTestObject or hitTextPoint features. So, i changed the IsoSprites to the Sprite, but when i already changed the IsoSprites to the Sprite, i am getting this error:
1119: Access of possibly undefined property sprites through a
reference with static type flash.display:Sprite.
and it is pointed in:
Constant.dudeEfis.sprites = [efisFrontClass];
dudeEfis is Sprite
i am aware that the Sprite don't have the feature of:
dudeEfis.sprites
but the problem is, if i change the "dudeEfis" to the IsoSprite, i am not be able to get the hitTestObject or hitTestPoint. And if i change to the Sprite, i am getting that error. How do i solve it? The code that i am giving to you is for movement faces direction (when the player is facing south, so do the character)
Here is the code:
public static var loaderEfis:Loader;
public static var dudeEfis:Sprite; //public static var dudeEfis:IsoSprite;
public static var _numXEfis:Number = 0;
public static var _numYEfis:Number = 0;
Constant.loaderEfis = new Loader();
Constant.loaderEfis.load(new URLRequest("efis.swf"));
var efisFrontClass:Class = Constant.loaderEfis.contentLoaderInfo.applicationDomain.getDefinition("EfisFront") as Class;
if (Constant._numXEfis == 0 && Constant._numYEfis == 0)
{
Constant._numXEfis = Constant.dudeEfis.x;
Constant._numYEfis = Constant.dudeEfis.y;
Constant.dudeEfis.sprites = [efisFrontClass];
}
Any help will be appreciated! Thank you in advance!

Sounds like you already know what the problem is. One way you can solve this is to create your own class that extends the IsoSprite class then add the hitTestObject and hitTestPoint methods yourself, they're pretty easy to implement.
package {
import flash.display.DisplayObject;
import flash.geom.Point;
public class MyOwnSprite extends IsoSprite {
public function hitTestObject (object:DisplayObject):Boolean {
//some logic here
}
public function hitTestPoint (point:Point):Boolean {
//some logic here
}
}
}
This way you get to keep all the functionality of IsoSprite while having those two methods that you need.

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{
....
}

Access of undefined property issues in AS3

I am having a bit of trouble with some AS3. First time using this language and have more experience with web development then OOP so am getting a bit confused.
I am trying to make it so that when someone clicks a 'powerbutton' which is a "movieclip" symbol within flash then another symbol should then become visible. This is all being done within the Kitchen class.
The code for the main class is which i got from a youtube tutorial video i followed;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import Kitchen
public class DragFood extends MovieClip
{
protected var originalPosition:Point;
var myKitchen:Kitchen
public function DragFood() {
myKitchen = new Kitchen;
originalPosition = new Point (x, y);
buttonMode = true;
addEventListener (MouseEvent.MOUSE_DOWN, down);
}
protected function down (event:MouseEvent):void
{
parent.addChild(this);
startDrag();
stage.addEventListener (MouseEvent.MOUSE_UP, stageUp);
}
protected function stageUp (event:MouseEvent):void
{
stage.removeEventListener (MouseEvent.MOUSE_UP, stageUp);
stopDrag();
if (dropTarget)
{
if(dropTarget.parent.name == "bowl")
{
trace("The " + this.name + " is in the bowl");
this.visible = false;
} else {
returnToOriginalPosition();
}
} else {
returnToOriginalPosition();
}
}
protected function returnToOriginalPosition():void
{
x = originalPosition.x;
y = originalPosition.y;
}
}
}
Within it i call the other class;
import Kitchen
public class DragFood extends MovieClip
{
protected var originalPosition:Point;
var myKitchen:Kitchen
The code for the kitchen class is;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Kitchen extends MovieClip
{
// This is a function. This particular function has the same name as our class and therefore will be executed first
public function Kitchen()
{
// This is a "call" to another function that is defined later in the program.
init();
trace("Hello world");
}
public function init():void
{
// If we want an object (on the screen or otherwise) to be notified about an event we must add a listener for that event to that object.
// We also need to specify what happens everytime the event we are listening for happens.
PowerButton.addEventListener(MouseEvent.CLICK, handleButtonClicks);
}
//This function is called when the oven on button recieves a click.
public function handleButtonClicks(event:MouseEvent):void
{
OvenOn.visible = true;
trace("the oven is being switched on");
}
}
}
The issue i keep getting is that OvenOn and PowerButton are giving me a undefined access issue and im not sure how to fix it. I have found posts on similar subjects like - Access of Undefined property? Actionscript 3
but im not quite sure how to apply it to my issue if anyone could offer any help that would be great.
When you're programming on the timeline, code is referencing the local namespace, and objects you make there (movieclips, textfields, etc.) are automatically instantiated in that namespace so that you can simply call OvenOn.visible = true. However, for each class, their local namespace is whatever is inside the class, so unless you actually created a property on your class called OvenOn, it will most definitely give you Access of Undefined Property errors.
Think of each class as its own island. For them to touch eachother, they need some sort of connection. That connection can be made once the parent instantiates the class in its own namespace. For example...
var foo:String = "Hello!";
var bar:MyClass = new MyClass();
// At this point, whatever code runs inside of MyClass has no concept of foo, or how to access it.
addChild(bar);
// Now that we've added it to the stage, the bar has some properties that have automatically been populated such as "root", "parent", or "stage".
foo.someProperty = "World";
// Since this namespace has a variable pointing to the instance, we can change properties on that class.
Now that we've instantiated MyClass on the stage, we can reference parent properties the class didn't know about. Mind you, this is not necessarily best practice.
package
public class MyClass extends MovieClip {
var someProperty:String = "cheese";
public function MyClass() {
trace(parent.foo) // this will fail
addEventListener(Event.ADDED_TO_STAGE, test);
}
public function test(e:Event):void {
trace(this["parent"].foo); // this will succeed
}
}
}
If you absolutely must change something that is not part of your Kitchen class, pass either the parent of OvenOn or that object specifically as a property of Kitchen. You could do this a couple ways.
with the Constructor...
var something:*;
public function MyClass(someObject:*) {
something = someObject;
}
public function test():void {
something.visible = false;
}
...or by Assigning the Property...
var bar:MyClass = new MyClass();
bar.something = OvenOn;
bar.test(); // will turn off the OvenOn now that 'something' is pointing to it.

How AS3 class files.as work together with FLA file?

I have two questions: Can i write app using just *.as files, and then compile them somehow in SWF? (i am making myself a webpage now)
Secondly, please look at the code, my problem is the same - I can't render text field onto stage, to be visible.
Flash say's 'undefined method addChild.' and 'Access of undefined property tekstuKaste through a reference with static type Class.'
This is a constructor type class inic which kinda serves for initialization, cos all i do is, I make an instance OF THIS class in FLA file by ActionScript, and expect, all application to work.
package {
import pacinas.visuals.*;
import pacinas.visuals.AE_kanva;
public class inic {
public function inic() {
trace("===========");
trace("inicializēt un izsaukt visu no Kanvas klases");
trace("===========");
trace(" ");
var kanvas:AE_kanva = new AE_kanva();
trace(" ");
kanvas.varis();
trace(" ");
trace("===========");
trace("inicializēt un izsaukt visu no Lauki klases");
trace("===========");
trace(" ");
var laukiTxt:BE_tekstaLaukiPrimitive = new BE_tekstaLaukiPrimitive();
trace("");
laukiTxt.simpleText();
addChild(BE_tekstaLaukiPrimitive.tekstuKaste);
}
}
}
There is another EXTERNAL CLASS By whom i hoped to place a rectangles - that does not work too. Example:
package pacinas.visuals
{
import flash.display.Sprite;
public class AE_kanva extends Sprite
{
public function AE_kanva()
{
var kvad:Shape = new Shape();
kvad.graphics.beginFill(0xFF0000);
kvad.graphics.drawRect(0, 0, 100,100);
kvad.graphics.endFill();
addChild(kvad);
trace("konstruktors - zīmē kanvu");
}
public function varis()
{
trace("te glabaas variaabljus");
var ff:int = 4;
var dd:int = 8;
}
}
}
And here is class i hoped will make text box for me (to fill it with XML later)
package pacinas.visuals
{
import flash.text.*;
import flash.display.Sprite;
public class BE_tekstaLaukiPrimitive extends Sprite
{
public var tekstuKaste:TextField = new TextField();
private var kontinents:String = new String ("XML SATURU CMON! a123");
public function BE_tekstaLaukiPrimitive():void
{
trace("teksta rāmis = konstruktora klase");
addChild(tekstuKaste); <--CAN'T GET THIS TO WORK!!!
tekstuKaste.text = kontinents;
}
public function simpleText()
{
trace("nekonstruktora f-cija no Teksta lauki");
}
}}
p.s. I do not use document Class. Ok I will if it's needed. But how?
Can I write app using just *.as files, and then compile them somehow into a SWF?
Yes - using the Flex SDK you can write pure ActionScript and compile it down into a working SWF. FlashDevelop is a good IDE that takes advantage of this.
You will however need to understand how the document class works.
Flash says undefined method addChild. and Access of undefined property tekstuKaste through a reference with static type Class.
In your code, this line is causing your issue:
addChild(BE_tekstaLaukiPrimitive.tekstuKaste);
The first error undefined method addChild is because your class inic does not extend a class that implements the method addChild(). DisplayObjectContainer defines this method, so you'll want to extend that as a minimum, like this:
public class inic extends DisplayObjectContainer
The second error is because you're attempting to access a property of the class BE_tekstaLaukiPrimitive as if it were static. I suspect what you actually wanted to do was this:
addChild(laukiTxt); // laukiTxt is the instance you created.

AS3 - Error 1119: Access of possibly undefined property enemyList through a reference with static type Class.

I need to get access to a variable from another class and I keep getting error '1119: Access of possibly undefined property enemyList through a reference with static type Class.' I can't see what I do wrong since my variable is made 'public' and 'static'.
class where the variable is made.
package classes.enemy
{
imports ...
public class Enemy extends MovieClip
{
public static var enemyList:Array = new Array(); **
var speed:Number;
public function initialize()
{
var stageReff:Stage = this.stage as Stage;
addEventListener("enterFrame", enterFrame);
}
public function Enemy()
{
enemyList.push(this); **
this.x = 700;
this.y = Math.random()*200 + 50;
speed = Math.random()*5 + 5;
}
//code
}
}
class that needs access to the variable
package classes.ship
{
imports ...
public class Bullet extends MovieClip
{
var speed:Number;
public function initialize()
{
var stageReff:Stage = this.stage as Stage;
stage.addEventListener("enterFrame", enterFrame);
}
//code
function enterFrame(e:Event):void
{
this.x += speed;
trace(enemy.enemyList); **
}
}
}
Putted '**' behind the lines where the problem occurs and where the variable is made, just to make it clear.
Classes are in different folders (classes > enemy & classes > ship), don't know if that has anything to do with it.
Thanks in advance.
I came across the same problem and the solution is:
your class name is "enemy" and when you access it, it remains as class not object
try to make an object of your class
enemy1 = new enemy(); // in your bullet class
or if bullet is a movieclip in which enemy as its child movieclip, then change its instance name to enemy1 so you can access it as an object of its own class defination "enemy"
If you want to access a static property, you need to use the class it is defined in: Enemy.enemyList
Also make sure the class is imported properly in your ship's class: import classes.enemy.Enemy;
I had the same problem with error 1119 on as3.
I was pulling my hair off and then I noticed that there was an output message related to TLF text.
So I went to action script settings on the FLA file and merged into code the textlayout library.
Hope this helps.
Update 1 :
Don't forget also to import your class Enemy
I suppose that enemy in Bullet is a class instance, so you can't call a static property from an instance you need to call it with the class name where it is declared:
so in Bullet enemy should be Enemy
package classes.ship {
//...
import enemy.Enemy;
//...
function enterFrame(e:Event):void
{
this.x += speed;
trace(Enemy.enemyList); **
}

custom AS3 Loader class that uses a custom LoaderInfo class?

This is a question specifically about creating a custom Loader class as a followup to How do I modify existing AS3 events so that I can pass data?. If this wasn't the right way to go about this, let me know.
I have a custom Loader class and a custom LoaderInfo class. What I can't figure out is how to have the Loader class use the custom LoaderInfo class as it's contentLoaderInfo property.
package com.display {
import flash.display.Loader;
import com.display.CustomLoaderInfo;
public class CustomLoader extends Loader {
public var customData:*;
public function CustomLoader(passedData: *= null) {
customData = passedData;
}
}
}
^ Have to do something in there to make it have the new CustomLoaderInfo
package com.display {
import flash.display.LoaderInfo;
import flash.events.Event;
import com.events.CustomEvent;
public class CustomLoaderInfo extends LoaderInfo {
public var customData:*;
public function CustomLoaderInfo(passedData: *= null) {
customData = passedData;
}
override public function dispatchEvent(event:Event):Boolean {
var customEvent:CustomEvent = new CustomEvent(event.type, customData, event.bubbles, event.cancelable);
return super.dispatchEvent(customEvent);
}
}
}
^ That might work, but since I can't get CustomLoader to use it, I don't know yet.
I don't know how it fits into what you're doing, but you could not bother making an extended LoaderInfo at all. Loader.contentLoaderInfo has a property called loader that will return the Loader (or in this case CustomLoader) that was used. In theory you can just do this with the CustomLoader class that you have:
var loader: CustomLoader = new CustomLoader("Extra Data");
loader.load(new URLRequest("file.swf"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
function loaderComplete(event: Event) : void
{
var customData:* = (event.target.loader as CustomLoader).customData;
trace(customData); // Extra Data
}
You would have to override the function where the loaderinfo instance is created, and that might be in a private function. In the new function you could then instanciate your custom loaderInfo class instead, but you would also have to do anything else that the overwritten method does. You might run into some security sandbox problems with loadinfo as well. Overwriting a function like this is usually only posible when the function written with this in mind.
Alternatively you could use the prototype chain (read here) to change the loaderInfo class at runtime. But I wouldn't recommend it. It's not good practice in my opinion.
If you get this to work you still have the problem that your custom event will not work with any event that has properties not inheritet from the Event class (like the ProgressEvent that has progress related properties).
I would say you properly should look for another solution.
In the question you link to you talk about sending movieclip with your event. Have you thought about reaching the other way? When you recieve the event, you get a reference to the object that dispatched it (Event.target). Can you not use that reference to get the movieclip?
Perhaps you could explain your problem in more detail (maybe in a new question so you still keep this open), I am sure there is a better / easier way to solve it.
I needed something like this because I wanted to carry an index with the info ... ie - have something like event.target.index available after an event is triggered .. anyway i designed a class that contained the loader and the loader info... heres the class
public class LoaderBox extends Sprite {
public static var PROGRESS:String = "progress"
public static var COMPLETE:String = "complete"
public var id:int
public var index:int
public var loader:Loader
public var info:LoaderInfo
public var isOpen:Boolean
//
public var percent:Number = -1
public function load(path:String,idx:int=-1,nm:String=null){
loader = new Loader()
if (nm != null){
name = nm
}
index = idx
var req:URLRequest = new URLRequest(path)
info = loader.contentLoaderInfo
info.addEventListener(Event.COMPLETE,complete)
info.addEventListener(ProgressEvent.PROGRESS,progress)
isOpen = true
loader.load(req)
}
private function complete(e:Event):void{
isOpen = false
dispatchEvent(new Event(LoaderBox.COMPLETE))
}
private function progress(e:ProgressEvent):void{
if (e.target.bytesTotal>0){
percent = Math.floor(e.target.bytesLoaded/e.target.bytesTotal * 100)
}
dispatchEvent(new Event(LoaderBox.PROGRESS))
}
}
A potential issue with the flagged answer: if contentLoaderInfo spits out a IOError, you can't access the .loader property to access your custom loader class.
What I did is the following:
* in my custom loader class, create the following method:
public function requestError(event:Event):void {
dispatchEvent(event);
}
when adding a listener to contentLoaderInfo for the IOerror, point to the custom loader class's method:
_loaderCls.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, _loaderCls.requestError);
Then, add the same listener to your loader class and make it call any method you need. At that point, the event.target would be that of your custom loader class and you can add any extra info you need to that class:
_loaderCls.addEventListener(IOErrorEvent.IO_ERROR, requestError);
or you can do a better thing to pass data into the Loader class:
package com.display
{
import flash.display.Loader;
public class Loader extends flash.display.Loader
{
private var _obj:Object;
public function Loader():void
{
super();
}
public function get obj():Object
{
return _obj;
}
public function set obj(o:Object):void
{
_obj = o;
}
}
}