as3 1119: Access of possibly undefined property getters/setters - actionscript-3

It would be amazing if someone could expand on the current answer, Thanks.
full error
Line 22 1119: Access of possibly undefined property CharacterX through a reference with static type flash.display:DisplayObject.
I'm trying to set a variable for the object shark, that is already defined in the object character
First time using setters in flash, so I might not be doing this right.
code I'm using to set the variable I tried to comment out the stuff I thought was irrelevant to this issue, not actually commented out in real code.
var character:Character;
//var bullet:Bullet=null;
//var bullets:Array = new Array();
//var enemies:Array = new Array();
//character=new Character(bullets);
addChild(character);
var shark:Shark=new Shark();
addChild(shark);
//var enemy:Enemy=null;
////var i:int;
//for (i=0; i<10; i++) {
//enemy = new Enemy(Math.random()*stage.stageWidth, Math.random()*stage.stageHeight);
//addChild(enemy);
// enemies.push(enemy);
//}
//stage.addEventListener(Event.ENTER_FRAME, colTest);
//function colTest(e:Event ):void {
// if(character.hitTestObject(turtle)){
// character.gotoAndStop("Turtle");
// }
//}
shark.setT(character.x, character.y)
class in which I'm attempting to define a variable using the function above.
package
{
import flash.display.*;
import flash.events.*;
public class Shark extends MovieClip
{
var CharacterX:Number = 0;
var CharacterY:Number = 0;
public function Shark()
{
this.x = 300;
this.y = 200;
addEventListener(Event.ENTER_FRAME,playGame);
}
public function setT(characterx:Number,charactery:Number){
CharacterX = characterx - this.x;
CharacterY = charactery - this.y;
}
function playGame(event:Event):void
{
var ease:int = 20;
var speed:int = 10;
var targetX:int = root.CharacterX - this.x;
var targetY:int = root.CharacterY - this.y;
var rotation = Math.atan2(targetY,targetX) * 180 / Math.PI;
cut code off here, didn't want to make a code dump can get you anything that might be relevant just ask.
Here is a pastebin of all of the code if it might help,
Shark class:
Actions on Frame 1:
Character class

Let me start by saying I can't spot the exact problem here, but I have some ideas. Your error 1999 says that something of the type display object is trying to change your variable. This happens a lot when you use parent.myMethod() because parent is typed as display object. You would fix this by typecasting like (parent as MovieClip).myMethod
In your case I don't see the exact source of this problem. But you could try using this.characterX in your setT function

Related

Incorrect number of arguments. Expected 2

I'm making a game where you are a soccer goalie and the ball(brazuca) keeps on falling down and you have to collect it, but I keep getting the incorrect number of arguments error. I'm fairly new to coding and I know that the error means something unexpected happened in the brackets where the error happened but I can't figure out how to fix it. It would be great if anyone can help me with this issue.
class Gamescreen2
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.*;
import flash.ui.Mouse;
import flash.media.SoundChannel;
public class Gamescreen2 extends MovieClip
{
public var goalie:GoaliePlay;
var gameMusic:GameMusic;
var gameChannel:SoundChannel;
var speed:Number;
//public var army:Array;
public var army2:Array;
//public var gameTimer:Timer;
public var gameTimer2:Timer;
public static var tick:Number;
public static var score:Number;
public function Gamescreen2()
{
goalie = new GoaliePlay();
addChild (goalie);
gameMusic = new GameMusic;
gameChannel = gameMusic.play(0,999);
score = 0;
//army = new Array();
army2 = new Array();
//gameTimer = new Timer(25);
gameTimer2 = new Timer(25);
//gameTimer.addEventListener(TimerEvent.TIMER, onTick);
gameTimer2.addEventListener(TimerEvent.TIMER, onTick);
gameTimer2.start();
tick = 0;
}
public function onTick(timerEvent:TimerEvent):void
{
tick ++;
if (Math.random() < 0.05)
{
var randomX:Number = Math.random() * 550;
var goalieB= new GoalieB(0,0);
army2.push (goalieB);
addChild (goalieB);
}
for each (var goalieB:GoalieB in army2)
{
goalieB.moveDownABit();
if(goalieB.y == 420)
{
score--
trace(score);
this.scoreTxttwo.text = score.toString();
}
if (goalie.collisionArea.hitTestObject(goalieB))
{
goalieB.x == 550;
score += 10;
}
if (score < 1)
{
score = 0;
}
}
}
}
}
class BrazucaPlay
package
{
import flash.display.MovieClip;
public class BrazucaPlay extends MovieClip
{
var speed:Number;
public function BrazucaPlay(startX:Number, startY:Number)
{
x = startX;
y = startY;
speed = Math.random();
}
public function moveDownABit():void
{
//two speed enemies
if (speed >= .25)
{
y = y + 3;
}
}
}
}
Might be the constructor of your GameMusic class.
gameMusic = new GameMusic;
You should have brackets like so:
gameMusic = new GameMusic();
Same with this line:
var newBrazuca = new BrazucaPlay;
Should be:
var newBrazuca = new BrazucaPlay();
If, after adding brackets () you still receive the error, then you should check your custom classes BrazucaPlay and GoaliePlay and make sure their constructors aren't expecting parameters. Also check this function: brazuca.moveDownABitB().
The constructor is the function that is named after the class and is what first runs when instantiate an object. So you do var newBrazuca = new BrazucaPlay(); there is a constructor function in the BrazucaPlay class that would look something like this:
public function BrazucaPlay(){
//some code.
}
If that function actually looked something like this:
public function BrazucaPlay(myParameter:String){ }
Then that would throw the error you're getting because it's expecting you to pass a parameter to it (in this case a string like new BrazucaPlay("blah blah blah"))
EDIT
Now that you've posted more code, the cause is quite clear. The constructor of your BrazucaPlay class is expecting two arguments (a starting x/y position). So when you instantiate a new BrazucaPlay instance, you are required to pass it those two parameters:
var newBrazuca = new BrazucaPlay(0,0);//you need to pass two numbers (starting x and y)
If you don't want to do this, you can change the code to make those parameter OPTIONAL.
//this makes the parameters default to 0 if no value is passed in
public function BrazucaPlay(startX:Number = 0, startY:Number = 0)
{
x = startX;
y = startY;
speed = Math.random();
}
Welcome, user. Okay, a couple of things...
First, just so you know, we need the entire error, as CyanAngel said. It helps us prevent digging through the entire code. (For more tips about getting started, go to stackoverflow.com/help)
Second, this is what your error message means: You are passing the wrong number of arguments (values) to a function. The function requires exactly two, and you're passing more or less than you should.
This is why we need the error: it has the line number of the error, letting us/you narrow in on it directly.

AS3 Cannot access a property or method of null object reference, issue with gotoAndPlay

so I'm still fairly new to AS3 and I'm getting my head around the errors and stuff and I'm trying to figure out why this is not working how it should, the function still executes but it leaves an error on my console. Here is my code:
import flash.events.MouseEvent;
import flash.display.MovieClip;
stop();
var activeHitArray:Array = new Array(word_select_box);
var activeDropArray:Array = new Array(answer1_word, answer2_word, answer3_word);
var hitPositionsArray: Array = new Array();
for (var numi:int = 0; numi < activeDropArray.length; numi++) {
activeDropArray[numi].buttonMode = true;
activeDropArray[numi].addEventListener(MouseEvent.MOUSE_DOWN, mousedown1);
activeDropArray[numi].addEventListener(MouseEvent.MOUSE_UP, mouseup1);
hitPositionsArray.push({xPos:activeDropArray[numi].x, yPos:activeDropArray[numi].y});
}
function mousedown1(event:MouseEvent):void {
event.currentTarget.startDrag();
setChildIndex(MovieClip(event.currentTarget), numChildren - 1);
}
function mouseup1(event:MouseEvent):void {
var dropindex1:int = activeDropArray.indexOf(event.currentTarget);
var target:MovieClip = event.currentTarget as MovieClip;
target.stopDrag();
if(target.hitTestObject(activeDropArray[dropindex1])){
// target.x = activeHitArray[dropindex1].x;
//target.y = activeHitArray[dropindex1].y;
if(answer1_word.hitTestObject(word_select_box)){
gotoAndStop("6");
}
} else {
target.x = hitPositionsArray[dropindex1].xPos;
target.y = hitPositionsArray[dropindex1].yPos;
}
}
And the Error I'm getting through is:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at game_flv_fla::MainTimeline/frame6()
at flash.display::MovieClip/gotoAndStop()
at game_flv_fla::MainTimeline/mouseup1()
The only thing I can think of is that it is something to do with the gotoAndPlay() because when I place a trace into it's place I get no errors.
I copied your code, compiled and lauched it in Flash IDE. It works! :)
There were no errors.
But I know where the isue may lay. The addEventListeners are still on, no matter if there still are the objects they were linked to. You need to clean all active things before going to next frame:
if(target.hitTestObject(activeDropArray[dropindex1])){
if(answer1_word.hitTestObject(word_select_box)){
for (var i:uint = 0; i < activeDropArray.length; i++) {
activeDropArray[i].removeEventListener(MouseEvent.MOUSE_DOWN, mousedown1);
activeDropArray[i].removeEventListener(MouseEvent.MOUSE_UP, mouseup1);
}
gotoAndStop("6");
}
}

1120: Access of undefined property shuffledArray

Please can you help me out I am new to as3 and I am trying to create a shuffled deck using the Fisher-Yates Algorithm. When I run the code with ctrl-enter it compiles with no errors but when I try to output it with trace(); it comes back with:
Scene 1, Layer 'actions', Frame 1, Line 6 1120: Access of undefined property shuffledArray.
Like I said I am new to this and it will be me doing something very stupid but all the same i'm stuck.
Here is the code
package src.CardDeck
{
public class CardDeck
{
public var allCards:Array = [];
public var cardNames:Array;
public var cardValues:Array;
public var gameType:String;
public var drawnCards:uint = 0;
public function CardDeck(game:String)
{
gameType = game;
cardNames = ["Ace","Two","Three",
"Four","Five","Six",
"Seven","Eight","Nine",
"Ten","Jack","Queen","King"];
if(gameType == "texasholdem")
{
cardValues = [1,2,3,4,5,6,7,8,9,10,10,10,10];
}
makeSuit("Spade");
makeSuit("Heart");
makeSuit("Diamond");
makeSuit("Club");
}
function makeSuit(suitString:String):void
{
var card:Object;
for(var i:uint = 0; i < cardNames.length; i++)
{
card = {};
card.cardType = suitString;
card.cardName = cardNames[i];
card.cardValue = cardValues[i];
card.isDrawn = false;
allCards.push(card);
}
}
public function shuffleFisherYates():Array
{
var shuffledArray:Array = [];
var randomCardIndex: int;
do
{
randomCardIndex = Math.floor(Math.random()* allCards.length);
shuffledArray.push(allCards[randomCardIndex]); // add to mix
allCards.splice(randomCardIndex,1); // remove from deck
}while(allCards.length); // Meaning while allCards.length != 0
return shuffledArray;
}
}
}
and here is the .fla actions layer
import src.CardDeck.CardDeck;
var deck:CardDeck = new CardDeck("texasholdem");
trace(shuffledArray);
I know its probably something silly but i'm struggling.
Thanks in advance!
Paul
var deck:CardDeck = new CardDeck("texasholdem");
trace(shuffledArray);
This doesn't work because shuffledArray isn't defined there.
Try :
var deck:CardDeck = new CardDeck("texasholdem");
var array:Array = deck.shuffleFisherYates();
for(var i:int=0; i<array.length; i++)
{
trace(array[i].cardName);
trace(array[i].cardType);
trace(array[i].cardValue);
trace(array[i].isDrawn);
}
"shuffledArray" is a property inside of your CardDeck object. To access public methods and properties within it, you need to use the dot syntax:
trace(deck.shuffleFisherYates());
However, depending on what you are doing, you may not need to really be accessing the array directly, if your CardDeck object is meant to control the entire deck.

Add multiple movieclips, not replacing the old ones

So, in short, my problem is this. I am using a variable which is a movieclip loaded from an external swf. I want to "spawn" multiple instances of the movieclip that all react to the same code, so for example if I say var1.x = 100, they all are at 100x. But my problem is when I run addChild(var1) multiple times(I'm not actually typing in addChild(var1) over and over, I just have it set to add them at random times), the new child just replaces the old one, instead of making multiple movieclips. Should I do something like
var var1:MovieClip
var var2:MovieClip = new var1 ?(which doesnt work for me btw, gives me errors)
Oh, heres the code, and also, I am pretty new to as3 fyi, still don't even know how arrays work, which was my second guess to the problem.
var zombieExt:MovieClip;
var ldr2:Loader = new Loader();
ldr2.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded2);
ldr2.load(new URLRequest("ZombieSource.swf"));
function swfLoaded2(event:Event):void
{
zombieExt = MovieClip(ldr2.contentLoaderInfo.content);
ldr2.contentLoaderInfo.removeEventListener(Event.COMPLETE, swfLoaded2);
//zombieExt.addEventListener(Event.ENTER_FRAME, moveZombie)
zombieExt.addEventListener(Event.ENTER_FRAME,rotate2);
function rotate2 (event:Event)
{
var the2X:int = playerExt.x - zombieExt.x;
var the2Y:int = (playerExt.y - zombieExt.y) * 1;
var angle = Math.atan(the2Y/the2X)/(Math.PI/180);
if (the2X<0) {
angle += 180;
}
if (the2X>=0 && the2Y<0) {
angle += 360;
}
//angletext.text = angle;
zombieExt.rotation = (angle*1) + 90;
}
playerExt.addEventListener(Event.ENTER_FRAME,spawn1);
function spawn1 (event:Event)
{
if(playerExt.y < 417)
{
var someNum:Number = Math.round(Math.random()*20);
if(someNum == 20)
{
addChild(zombieExt)
zombieExt.x = Math.round(Math.random()*100)
zombieExt.y = Math.round(Math.random()*100)
}
}
}
}
addChild() does not create new instances. It is used to add an already created instance to the display list. If you call addChild() multiple times on the same instance then you are just readding itself.
Also each instance is unique, you can not globally change the x position of an instance by changing another one of them. What you would do is as Henry suggests and add each new instance of a MovieClip into an array, then whenever you change something you can loop through the array and apply the changes to each instance.
You can not go var2:MovieClip = new var1 either since var1 is an instance and not a class.
Here's a different method of receiving loaded MovieClips, which i use when i need many copies of the item.
in the swf you are loading, give the target movieclip a linkage name in the library, for this example i will use "foo"
private var loadedSwfClass:Class
private var newZombie:MovieClip;
private var zombieArray:Array = new Array();
function swfLoaded2(event:Event):void
{
loadedSwfClass = event.target.applicationDomain.getDefinition("foo");
for(var n:int = 0; n<100; n++){
newZombie = new loadedSwfClass()
zombieArray.push(newZombie);
addChild(newZombie);
}
}
as per this tutorial
http://darylteo.com/blog/2007/11/16/abstracting-assets-from-actionscript-in-as30-asset-libraries/
although the comments say that
var dClip:MovieClip = this;
var new_mc = new dClip.constructor();
this.addChild(new_mc);
will also work.
It sounds like you might be accessing the same instance some how in your code. It would be helpful to see your code to figure this one out.
If I wanted to load in one swf files and add a MovieClip multiple times I would place it in the library of that SWF file. And then instantiate it and store it into an object pool or a hash or some list.
// after the library were finished loading
var list:Array = [];
for(var i:int=0; i<10; i++) {
var myCreation:MySpecialThing = new MySpecialThing();
addChild(myCreation);
list.push(myCreation);
}
where my library would contain a linkage to the class MySpecialThing.
Calling addChild(var1) multiple times on the same parent doesn't have any effect (unless you have added another child to the same parent in between, in which case it will change the child index and bring var1 to the top). If you call it on different parents, it will just change the parent of var1, doesn't duplicate. Call addChild(new MovieClassName()) at random times instead to add new copies of it. Use an array as suggested here to access them later.
Wow, thanks there henry, just using an array did exactly what I needed, and made things alot simpler.
when you load in using a loader you only get 1 instance, however you can do some funky reflection to determine what class type the given loader.content is, and then instantiate them using that. For Example:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_completeHandler);
loader.load(new URLRequest("ZombieSource.swf"));
var classType:Class;
function loader_completeHandler(evt:Event):void
{
var loadInfo:LoaderInfo = (evt.target as LoaderInfo);
var loadedInstance:DisplayObject = loadInfo.content;
// getQualifiedClassName() is a top-level function, like trace()
var nameStr:String = getQualifiedClassName(loadedInstance);
if( loadInfo.applicationDomain.hasDefinition(nameStr) )
{
classType = loadInfo.applicationDomain.getDefinition(nameStr) as Class;
init();
}
else
{
//could not extract the class
}
}
function init():void
{
// to make a new instance of the ZombieMovie object, you create it
// directly from the classType variable
var i:int = 0;
while(i < 10)
{
var newZombie:DisplayObject = new classType();
// your code here
newZombie.x = stage.stageWidth * Math.random();
newZombie.x = stage.stageHeight * Math.random();
i++;
}
}
Any problems let me know, hope this helps.

Finding (loaded) image size in AS3 (Action Script 3.0)

Im currently using the following function to load an image, however i could not figure out a way to find the width of the loaded image, which i intend to use before placing the next image using the same function.
Note that q is a a variable (a number) which is used to load differant images.
=X i need help obtainning the loaded image width...
function LoadImage(q)
{
var imageLoader:Loader = new Loader();
var image:URLRequest = new URLRequest("GalleryImages/Album1/"+q+".jpg");
imageLoader.load(image);
addChild (imageLoader);
imageLoader.x = 0 + CurrentXLength;
imageLoader.y = 0;
imageLoader.name = "image"+q;
trace(imageLoader.x)
}
You can't know the width of the bitmap until it's actually loaded:
function LoadImage(q)
{
var imageLoader:Loader = new Loader();
var image:URLRequest = new URLRequest("GalleryImages/Album1/"+q+".jpg");
imageLoader.contentLoader.addEventListener(Event.COMPLETE, ImageLoaded);
imageLoader.load(image);
addChild (imageLoader);
...
private function ImageLoaded(e:Event):void
{
var imageLoader:Loader = Loader(e.target.loader);
var bm:Bitmap = Bitmap(imageLoader.content);
var CurrentXLength = bm.width;
....
Alternativly this link might be helpful? Haven't tried it myself ...
I just asked for de width property of loader object:
var loader:Loader;
function loadImage(dir:String):void {
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, placeImage);
var urlReq:URLRequest = new URLRequest(direccion);
loader.load(urlReq);
}
function placeImage(o:Event):void {
loader.x = (1360 - loader.width)/2;
loader.y = (768 - loader.height)/2;
addChild(loader);
}
Where 1360 and 768 are the canvas dimensions...
To access the width you must do it within the function assigned to handle Event.COMPLETE.
"You will want an array containing the items you wish to load. You should probably load this data in with XML so it is dynamic and scalable. Once the xml data is loaded it should be assigned to an array in whatever fashion you like. The reason that we must use an array in this situation, rather then just using the XML object, which is essentially an array, is because you need the know an objects width so that you can base the next objects X position off of the last objects X position plus its WIDTH.
With XML it is common to use a for loop and just iterate through "x" amount of times. We do not want this, in this case. To obtain the "WIDTH" property of the loaded asset, it must be accessed from within the function assigned to fire when the loader fires Event.COMPLETE. Once the image has completed it will remove the item from the array, set a variable as to the lastX and lastWidth, and then get the next item in the array and start all over. Eventually the array is empty and the process is complete.
-Note: I will skip loading the XML and just inject the data into the array myself.
package
{
import flash.display.Sprite;
import flash.display.Loader;
import flash.net.URLRequest;
public class DocumentClass extends Sprite
{
private var _array:Array;
private var _lastX:Number;
private var _lastWidth:Number;
public function DocumentClass():void
{
_array = new Array();
//Add Items to an array however you wish. I did it
//this way to make it easier to read on this site.
_array.push({name: "image1", path: "path/to/image1"});
_array.push({name: "image2", path: "path/to/image2"});
_array.push({name: "image3", path: "path/to/image3"});
loadImage();
}
private function loadImage():void
{
if(_array.length > 0)
{
var loader:Loader = new Loader();
addChild(loader);
var request:URLRequest = new URLRequest(_array[0].path); //Loads first item in the array each time.
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.x = _lastX + _lastWidth;
laoder.load(request);
_lastX = loader.x; //We set after so we are ready for the next.
_array.shift(); //Remove the first item from the array.
}
}
function onImageLoaded(e:Event):void
{
_lastWidth = e.target.width;
loadImage(); //Attempt to load another image if the array isn't empty.
}
}
}
I hope this helps, the code isn't tested, but the concept seems valid.
Yeah I used scott's answer but it's worth noting that 'imageLoader.contentLoader' should be 'imageLoader.contentLoaderInfo' in the LoadImage() function. Solved the width prob for me-- thanks mang