Block property ActionScript 3 - actionscript-3

I don't know why I'm getting this error in AS3, "Access of undefined property Block.".
I was following a tutorial and copied the code as it is,
function mainLoop (e:Event) {
for (var i = 0; i < numChildren; i++){
if (getChildAt(i) is Block)
{
var bb = getChildAt(i) as Block;
if (bb.hitTestPoint(mouseX, mouseY))
{
trace("hit");
}
}
}
}
Maybe a missing import? Although FlashDevelop didn't automatically add as it does sometimes so I'm a bit clueless

You should have class definition for Block. It could be exported as part of .swc library or defined in code. Without definition of Block class of cause you will have errors.
Also you could improve your main loop, you shouldn't perform several times same lookup with getChildAt and operations is and as also could be optimised:
function mainLoop(e:Event) {
var block:Block, len:int = numChildren, i:int;
for (i = 0; i < len; i++) {
block = getChildAt(i) as Block;
if (block != null) {
if (block.hitTestPoint(mouseX, mouseY)) {
trace("hit");
}
}
}
}

Related

Reference with static type error

I have an ActionScript 3 function looking like this:
private function removeEntry(myT:Vector.<MyType>):void
{
for (var i:Number; = myT.length - 1; i >= 0; i--)
{
if(!myT[i].condition)
{
removeChild(myT[i]);
myT.removeAt(i);
}
}
}
Unfortunately I get the following nasty error:
Description Resource Path Location Type Call to a possibly undefined
method removeAt through a reference with static type
Vector.. (...) Flex Problem
What am I missing here?
I solved this by using slice instead of removeAt:
private function removeEntry(myT:Vector.<MyType>):void
{
for (var i:Number; = myT.length - 1; i >= 0; i--)
{
if(!myT[i].condition)
{
removeChild(myT[i]);
myT.slice(i, 1);
}
}
}

How to sort objects in a sprite without blinking?

public function resort():void {
while (tickets.numChildren > 0) {
tickets.removeChildAt(tickets.numChildren - 1);
}
for(var i:int = 0; i < ticketsBought.length; i++)
{
var t:TicketCard = ticketsBought[i] as TicketCard;
tickets.addChild(t);
}
}
after this function executes, the tickets are blinking visually, but I don't want that, is there a way to sort objects in the stage without blinking?
I think you can use the setChildIndex method of the DisplayObjectContainer class (see documentation) to reorder your objects without removing and then re-adding them.
Unfortunately I'm not in a position to test this at the moment, but I think the following should work:
public function resort():void {
for(var i:int = 0; i < ticketsBought.length; i++)
{
var t:TicketCard = ticketsBought[i] as TicketCard;
tickets.setChildIndex(t, i);
}
}

Error #1010 after splicing from array

I have an issue here. Every five seconds the spawnEnemies is fired. It creates a movieclip, sets it position and adds it to the stage and an array. In the function checkBullet I check if the bullet hits one of the enemies. If it does, the bullet and the enemy are removed from the stage, and the enemy is spliced from the array. But an error is thrown once I hit an enemy:
TypeError: Error #1010: A term is undefined and has no properties.
If I comment out the arrayEnemies.splice(i,1) line, it works fine but then it isn't removed from the array. This is in itself not an issue, but naturally I don't like to keep unnecessary data in my array. Any help on this?
function checkBullet(event:Event) {
if(stage.contains(mcBullet)) {
for(var i:int = 0; i < arrayEnemies.length; i++) {
if(arrayEnemies[i].hitTestPoint(mcBullet.x, mcBullet.y, true)) {
stage.removeChild(mcBullet);
this.removeChild(arrayEnemies[i]);
arrayEnemies.splice(i,1);
bulletOnStage = false;
}
}
if(mcBullet.x > 800) {
stage.removeChild(mcBullet);
bulletOnStage = false;
}
}
}
function spawnEnemies(event:TimerEvent) {
var enemie:MovieClip = new box_mc();
enemie.name = "mcBox" + event.currentTarget.currentCount;
enemie.x = 850;
enemie.y = Math.floor(Math.random()*(1+155)+255);
addChild(enemie);
arrayEnemies.push(enemie);
}
function moveEnemies(event:Event) {
for(var i:int = 0; i < arrayEnemies.length; i++) {
arrayEnemies[i].x -= 5;
}
}
This will be caused by working on an array that you are interating through, you should hold a ref to the stuff you want to remove then do it after the loop.
Your problem is that if the bullet hits two enemies, you try to remove it from the stage twice. This will throw an ArgumentError.
If you need to test against all enemies (assuming multiple enemies can be hit by the same bullet), you also need to decrement i when you remove an element from your enemy array.
function checkBullet(event:Event) {
if(stage.contains(mcBullet)) {
if(mcBullet.x > 800) {
stage.removeChild(mcBullet);
bulletOnStage = false;
}
for(var i:int = 0; i < arrayEnemies.length; i++) {
if(arrayEnemies[i].hitTestPoint(mcBullet.x, mcBullet.y, true)) {
if(stage.contains(mcBullet)){
stage.removeChild(mcBullet);
}
this.removeChild(arrayEnemies[i]);
arrayEnemies.splice(i,1);
bulletOnStage = false;
i--;
}
}
}
}
Bit of an older question but thought I'd throw in my answer too for anyone that might end up here.
Like Neil said, editing an array that you're itterating through (in this case arrayEnemies) can cause concurrent update problems.
My prefered solution is to use a seperate toRemove array and remove them after the update, for example:
var enemies:Array();
//Lets assume at some point this is populated with Enemy objects
function update():void
{
var toRemove:Array = new Array();
//May want to keep and clear an array instead to avoid creating a new one each update
foreach(var enemy:Enemy in enemies)
{
enemy.update();
if(enemy.markedForRemoval())
toRemove.push(enemy);
}
foreach(var enemy:Enemy in toRemove)
enemies.splice(enemies.indexOf(enemy), 1);
}

AS3: How to remove a MovieClip created and placed on stage through an array?

I'm making a game in flash and am using arrays to dynamically create items and place them inventory. LongSword is a MovieClip. I place the movieclip in the array like so:
function buyitem1(e:Event):void
{
if(Store.itemslot.length < 6 && Store.currentMenu == 1 &&score >= 450)
{
Store.itemslot.push(new LongSword);
}
}
Now I'm trying to remove the movieclip from the stage when the LongSword is "sold". How can i remove this longsword? I've tried:
for(var i:int = 0; i < Store.itemslot.length; i++)
{
if(Store.itemslot[i] == LongSword)
{
stage.removeChild(Store.itemslot[0]);
}
}
Ive also tried:
for(var i:int = 0; i < Store.itemslot.length; i++)
{
if(Store.itemslot[i] == new LongSword)
{
stage.removeChild(Store.itemslot);
}
}
and several variations. any ideas?
Try something like:
for each(var i:MovieClip in Store.itemslot)
{
if(i is Longsword)
{
var n:int = Store.itemslot.indexOf(i);
Store.itemslot.splice(n, 1);
if(i.parent) i.parent.removeChild(i);
break; // Only remove one Longsword.
}
}
If there are multiple instances of Longsword in the array, you may want to keep a reference to each instance somewhere for better comparison.

Actionscript 3.0: display object walker in strict mode

This is a document class for a display object walker. Make sure to turn off the strict mode (howto here) when testing the class. Also put some stuff on the stage. When the strict mode is turned off the object walker works just fine. However, I want to make it work in strict mode too. I have tried changing the problematic parts, and addig (dispObj as DisplayObject), with no luck.
package {
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
public class DisplayWalker extends MovieClip {
public function DisplayWalker() {
showChildren(stage, 0);
}
private function padIndent(indents:int):String {
var indent:String = "";
for (var i:uint = 0; i < indents; i++) {
indent += " ";
}
return indent;
}
private function showChildren(dispObj:DisplayObject, indentLevel:Number):void {
for (var i:uint = 0; i < dispObj.numChildren; i++) {
var obj:DisplayObject = dispObj.getChildAt(i);
if (obj is DisplayObjectContainer) {
trace(padIndent(indentLevel), obj, obj.name);
showChildren(obj, indentLevel + 1);
} else {
trace(padIndent(indentLevel), obj);
}
}
}
}
}
Your class will generate compile time errors in Strict mode because you're trying to access the numChildren and getChildAt methods, which aren't available on the DisplayObject class, but first on one of it's subclasses, DisplayObjectContainer.
The reason it is working in non-Strict mode is that, at runtime, you're effectively passing in subclasses of DisplayObjectContainer (Stage, Sprite, etc).
Just replace DisplayObject with DisplayObjectContainer as the type for dispObj in your showChildren method. DisplayObjects cannot have children and are always leafs in the display object tree, something your showChildren method will have to account for.
Stiggler is on the right track, but properly didn't see that you already check for DisplayObjectContainers.
You just need to modify your code slightly. I didn't test the code, but in any case you should be able to figure it out ;)
private function showChildren(dispObj:DisplayObject, indentLevel:Number):void
{
var dOC:DisplayObjectContainer = dispObj as DisplayObjectContainer;
if(dOC == null)
{
trace(padIndent(indentLevel),obj);
}
else
{
trace(padIndent(indentLevel), obj, obj.name);
var obj:DisplayObject = null;
for (var i:uint = 0; i < dispObj.numChildren; i++)
{
obj = dOC.getChildAt(i);
showChildren(obj, indentLevel + 1);
}
}
}