Remove all Instance on stage as3 - actionscript-3

Im having trouble on removing instances on the stage.
The error I keep getting after I click the button 2 times is
"The supplied DisplayObject must be a child of the caller"
Can somebody help me with this?
package src
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
var positionY:Number = 80;
var positionX:Number = 0;
var motion:MovieClip;
var fCombo:Array = new Array();
var n:Number;
public function Main()
{
generate.addEventListener(MouseEvent.MOUSE_UP, loop);
generate.addEventListener(MouseEvent.MOUSE_DOWN, remove);
n = Number(inputText.text);
}
function loop(me:MouseEvent):void
{
var combo:Array = [Punch, Kick, Knee, Elbow];
n = Number(inputText.text);
for(var i:Number = 0;i < n;i++ )
{
motion = new combo[randomNumber(4)]();
fCombo.push(motion);
motion.y = positionY;
motion.x = positionX;
positionX += 100;
addChild(motion);
if (i == 4 || i == 9 || i == 14)
{
positionY += 40;
positionX = 0;
}
}
}
function remove(me:MouseEvent):void
{
for (var j:Number = 0; j < n; j++ )
{
removeChild(fCombo[j]);//error
}
positionY = 80;
positionX = 0;
}
function randomNumber(max:Number):Number
{
return(Math.floor(Math.random() * max ));
}
}
}

You're adding the new objects you create to the array, and then using that to remove them. But you're forgetting to either create a new list or remove the objects from the old list. So, when time comes to loop over the list you're trying to remove objects that have already been removed.
You can fix this in several ways, one is to remove objects from the stage AND array in your loop:
function remove(me:MouseEvent):void
{
while(fCombo.length)
{
removeChild(fCombo.pop());
}
positionY = 80;
positionX = 0;
}

targetDisplayObject.parent.removeChild( targetDisplayObject ); does the trick assuming the parent is not null.

Related

ActionScript 3 - Error #1010: A term is undefined and has no properties

When testing my project, I got this error :
TypeError: Error #1010: A term is undefined and has no properties. firegame.as:115]
at firegame/checkhitammo()[..\Desktop\Flash\firegame.as:115
at firegame/mainloop()[..Desktop\Flash\firegame.as:77
I don't understand why and if I change the if statement to something simple it's all work fine.
This is my code :
package {
import flash.display.*;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
public class firegame extends MovieClip {
var tiger:Tiger = new Tiger();
var enemys:Array = new Array();
var scorea:Number = 0;
var ammoleft:Number = 0;
var ammo:Array = new Array();
var setint:Timer = new Timer(110);
var setenemy:Timer = new Timer(980);
var newenemy:Number;
var hitcheck:Array = new Array();
var totallength:Number;
public function firegame() {
startgame();
}
public function startgame() {
addplayer();
stage.addEventListener(MouseEvent.MOUSE_MOVE, moveplayer);
stage.addEventListener(MouseEvent.MOUSE_DOWN, shotfire);
stage.addEventListener(MouseEvent.MOUSE_UP, shotfirestop);
setint.addEventListener(TimerEvent.TIMER, shotfirestart);
setenemy.addEventListener(TimerEvent.TIMER, addenemy);
stage.addEventListener(Event.ENTER_FRAME, mainloop);
setenemy.start();
}
public function addplayer():void {
tiger.y = 200;
tiger.x = 507;
addChild(tiger);
}
public function moveplayer(e:MouseEvent):void {
tiger.y = mouseY;
tiger.x = 507;
}
public function shotfire(e:MouseEvent):void {
setint.start();
}
public function shotfirestop(e:MouseEvent):void {
setint.stop();
}
public function shotfirestart(e:TimerEvent):void {
var fire:Fire = new Fire();
fire.x = 460;
fire.y = mouseY;
addChild(fire);
ammoleft -= 1;
ammo.push(fire);
}
public function addenemy(e:TimerEvent):void {
var enemy:Enemy = new Enemy();
enemy.x = 0;
enemy.y = Math.floor(Math.random() * (370 - 30) + 30);
addChild(enemy);
enemys.push(enemy);
}
public function mainloop(e:Event):void {
setscoreandammo();
moveammo();
moveenemy();
checkhitammo();
}
public function moveammo():void {
for (var i:int = 0; i < ammo.length; i++) {
ammo[i].x -= 15;
if (ammo[i].x < -30) {
removeChild(ammo[i]);
ammo[i] = null;
ammo.splice(i, 1);
}
}
}
public function moveenemy():void {
for (var b:int = 0; b < enemys.length; b++) {
enemys[b].x += 5;
if (enemys[b].x > 590) {
removeChild(enemys[b]);
enemys[b] = null;
enemys.splice(b, 1);
}
}
}
public function setscoreandammo():void {
score.text = String(scorea);
leftammo.text = String(ammoleft);
}
public function checkhitammo():void {
for (var i:int = ammo.length; i >= 0; i--) {
for (var b:int = enemys.length; b >= 0; b--) {
if (ammo[i].hitTestObject(enemys[b])) { // <--- this is the line where the error is fired
removeChild(ammo[i]);
ammo[i] = null;
ammo.splice(i, 1);
removeChild(enemys[b]);
enemys[b] = null;
enemys.splice(b, 1);
scorea += 50;
break;
}
}
}
}
}
}
Your specific problem is right here...
public function checkhitammo():void {
for (var i:int = ammo.length; i >= 0; i--) {
for (var b:int = enemys.length; b >= 0; b--) {
...you are starting the counters i and b with the length of the array, instead of the position of the last index. It should read...
public function checkhitammo():void {
for (var i:int = ammo.length - 1; i >= 0; i--) {
for (var b:int = enemys.length - 1; b >= 0; b--) {
That is, the length is 1-based, and positions are 0-based
first of all, all your for loops only has increment by 1 you may want to use like this
for (var i in ammo) {
for (var b in enemys) {
you just have to loop through array until something happens and break out of loop to make sure it doesn't check twice.
in this line
if (ammo[i].hitTestObject(enemys[b])) {
the error says program cannot find object in the array list, since it's just array it does not throw error like null pointer exception
if you swap ammo with enemys you will see that hitTestObject is trying to access a null object
and you don't really need to call this
ammo[i] = null;
since its already being removed

how to make Astar pathfinding can used by multi enemy?

i have learn A star pathfinding from "AdvancED_ActionScript_Animation" e-book:
List item
i make node class, Node.as .
i make grid class, Grid.as .
i make AStar class, AStar.as .
and the main clas, Game.as .
A-star Pathfinding is work, but just 1 player.
how to make it work in multi player?
spoiler
4.Game.as :
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
public class Game extends Sprite
{
private var _cellSize:int = 30;
private var _grid:Grid;
private var _player:Sprite;
private var _index:int;
private var _path:Array;
public function Game()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
makePlayer();
makeGrid();
stage.addEventListener(MouseEvent.CLICK, onGridClick);
}
private function makePlayer():void
{
_player =new Sprite();
_player.graphics.beginFill(0x336633);
_player.graphics.drawCircle(0,0,5);
_player.graphics.endFill();
_player.x = Math.random() * 100;
_player.y = Math.random() * 100;
addChild(_player);
}
private function makeGrid():void
{
_grid = new Grid(10,10);
for (var i:int =0; i < 10; i++)
{
_grid.setWalkable(Math.floor(Math.random()*10),
Math.floor(Math.random()*10),false);
}
drawGrid();
}
private function drawGrid():void
{
graphics.clear();
for (var i:int =0; i < _grid.numCols; i++)
{
for (var j:int =0; j<_grid.numRows; j++)
{
var node:Node = _grid.getNode(i,j);
graphics.lineStyle(0);
graphics.beginFill(getColor(node));
graphics.drawRect(i *_cellSize,
j*_cellSize,_cellSize,
_cellSize);
}
}
}
private function getColor(node:Node):uint
{
if (! node.walkable)
{
return 0;
}
if (node == _grid.startNode)
{
return 0xcccccc;
}
if (node == _grid.endNode)
{
return 0xcccccc;
}
return 0xffffff;
}
private function onGridClick(event:MouseEvent):void
{
var xpos:int =Math.floor(mouseX/_cellSize);
var ypos:int =Math.floor(mouseY/_cellSize);
_grid.setEndNode(xpos,ypos);
xpos = Math.floor(_player.x / _cellSize);
ypos = Math.floor(_player.y / _cellSize);
_grid.setStartNode(xpos,ypos);
drawGrid();
findPath();
}
private function findPath():void
{
var astar:AStar = new AStar();
if (astar.findPath(_grid))
{
_path = astar.path;
_index = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
private function onEnterFrame(event:Event):void
{
var targetX:Number = _path[_index].x * _cellSize
+ _cellSize / 2;
var targetY:Number = _path[_index].y * _cellSize
+ _cellSize / 2;
var dx:Number = targetX - _player.x;
var dy:Number = targetY - _player.y;
var dx2:Number = targetX - _box.x;
var dy2:Number = targetY - _box.y;
var dist2:Number =Math.sqrt(dx2*dx2+dy2+dy2);
var dist:Number =Math.sqrt(dx*dx+dy+dy);
if (dist<1)
{
_index++;
if (_index >= _path.length)
{
removeEventListener(Event.ENTER_FRAME,onEnterFrame);
}
}
else
{
_player.x += dx * .5;
_player.y += dy * .5;
}
}
}
}
I am not going to go the extra mile and code this for you. (Anyone else can feel free to do that)
What you need to do is create a function that accepts a start node and end node, and returns the path. Something like this :
public function getPath(starNode:Point, endNode:Point):Array
{
// get your path by utilizing the astar instance
// return that path array
// note that I have used Points to store the x,y location
// you'll need to apply those values to the grid before your astar call
// using the setStarNode and setEndNode methods of the grid instance
}
Then you can modify the code that is used in your enterFrame, to utilize an array containing path data for any player/enemy you want.
For example you might have a function you call for each entity such as :
public function followPath(entity:MovieClip, pathData:Array, pathIndex:int):void
{
// your modified code from onEnterFrame
// replace _player variable with entity
// replace _path variable with pathData
// replace _index with pathIndex
}
If you understand OOP well enough, you might want to create a class for your player/enemy entities that has properties for pathData and pathIndex. If you do that, than you can just call an update method that will update their movement each frame using the pathData and pathIndex properties of that instance.
This is a basic approach you could use to accomplish your goal.

Checkbox add elements to array

I'm seem having problem with inserting an element to an array.
What I'm trying to do is if the CheckBox is tick it would insert an element in the array and if the checkbox is unticked remove the element from the array
package src
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
var positionY:Number = 80;
var positionX:Number = 0;
var motion:MovieClip;
var fCombo:Array = new Array();
var n:Number;
var combo:Array = new Array();
public function Main()
{
Basic.selected = true;
Basic.addEventListener(Event.CHANGE, change);
generate.addEventListener(MouseEvent.MOUSE_UP, loop);
generate.addEventListener(MouseEvent.MOUSE_DOWN, remove);
n = Number(inputText.text);
var combo:Array = [];
}
function loop(me:MouseEvent):void
{
var combo:Array = [Punch, Kick, Knee, Elbow];
n = Number(inputText.text);
for(var i:Number = 0;i < n;i++ )
{
motion = new combo[randomNumber(combo.length)]();
fCombo.push(motion);
motion.y = positionY;
motion.x = positionX;
positionX += 100;
addChild(motion);
if (i == 4 || i == 9 || i == 14 || i == 19)
{
positionY += 40;
positionX = 0;
}
}
}
function remove(me:MouseEvent):void
{
var k:Number = n
while(fCombo.length)
{
removeChild(fCombo.pop());
}
positionY = 80;
positionX = 0;
}
function randomNumber(max:Number):Number
{
return(Math.floor(Math.random() * max ));
}
function change(e:Event):void
{
if (Basic == true)
{
combo.push(UpperCut); //this movieclip won't insert inside the array
}
}
}
}
I guess Basic is a checkBox, So
if (Basic == true)
{
combo.push(UpperCut); //this movieclip won't insert inside the array
}
Should be
if (Basic.selected == true)
{
combo.push(UpperCut); //this movieclip won't insert inside the array
}

How can I set the damage level of enemy

Thanks in advance...
I am having little bit doubt in my logic for setting the Damage level to the enemy in game. Following is my Enemy Class
package scripts.enemy
{
import flash.display.MovieClip;
import flash.events.*;
import flash.display.Stage;
public class Enemy1 extends MovieClip
{
private var BG:MovieClip;
private var speed:Number = 0.5;
private var ease:Number = .005;
private var rad:Number = 57.2957795;
public function Enemy1(BG:MovieClip) : void
{
var RandomX:Array = new Array(-150,-200,-250,-300,-350,-400,-450,-500,-550,150,200,250,300,350,400,450,500,550);
var RandomY:Array = new Array(-150,-200,-250,-300,-350,-400,150,200,250,300,350,400);
var r:int = (Math.random() * 18);
var s:int = (Math.random() * 12);
x = RandomX[r];
y = RandomY[s];
this.BG = BG;
addEventListener(Event.ENTER_FRAME, moveEnemy); //false, 0, true);.
}
private function moveEnemy(e:Event):void
{
var dx:Number = x - 10;
var dy:Number = y - 10;
this.x -= dx * ease;
this.y -= dy * ease;
this.rotation = (Math.atan2(dy,dx) * rad) + 180;
}
}
}
And Here is some of code that giving me trouble from my Main class
// ......... Function for Checking the Collision between Bullet And Enemy...........
private function checkCollision(mc:MovieClip):Boolean
{
var test:Point = mc.localToGlobal( new Point());
for (var i = 0; i < enemies1.length; i++)
{
tempEnemy1 = enemies1[i];
if (kill == true)
{
if (tempEnemy1.hitTestPoint(test.x,test.y,true))
{
enemies1.splice(i, 1);
bg_mc.removeChild(tempEnemy1);
createDead(Dead1,deadArray1,tempEnemy1.x,tempEnemy1.y,tempEnemy1.rotation);
Score += 10;
Scr_txt.text = String(Score);
bugsKill += 1;
kill = false;
return true;
}
}
}
if (Level >= 2)
{
for (var j = 0; j < enemies2.length; j++)
{
tempEnemy2 = enemies2[j];
if (kill == true)
{
if (tempEnemy2.hitTestPoint(test.x,test.y,true))
{
bug2HitCount -= 1;
if (bug2HitCount == 0)
{
enemies2.splice(j, 1);
bg_mc.removeChild(tempEnemy2);
createDead(Dead2,deadArray2,tempEnemy2.x,tempEnemy2.y,tempEnemy2.rotation);
Score += 20;
Scr_txt.text = String(Score);
bugsKill += 1;
kill = false;
//bug2HitCount = bug2HitRate;
return true;
}
kill = false;
return true;
}
}
}
}
return false;
}
private function removeElement(removeList:Array):void
{
for (var i = 0; i < removeList.length; i++)
{
bg_mc.removeChild(removeList[i]);
}
}
//...........Function Checking the Collission Between Bunker And Enemy..............
private function collideEnemy(deadArray:Array,enemyArray:Array,rate:Number):void
{
var enemy:MovieClip;
for (var i = 0; i < enemyArray.length; i++)
{
enemy = enemyArray[i];
if (enemy.hitTestObject(bunker_mc))
{
life_mc.scaleX -= rate;
if (life_mc.scaleX <= 0.05)
{
stage.removeEventListener(Event.ENTER_FRAME,updateCollission);
Timer1.stop();
Mouse.show();
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUpFun);
stage.removeEventListener(Event.ENTER_FRAME,updateStage);
stage.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownFun);
(player.parent).removeChild(player);
(bunker_mc.parent).removeChild(bunker_mc);
(life_mc.parent).removeChild(life_mc);
(sniper_mc.parent).removeChild(sniper_mc);
removeElement(bullets);
EndFun();
gunFire = false;
gotoAndStop("end");
Level = 1;
}
}
}
}
//...........function of Timer Complete Event.....................
private function TimerEnd(e:TimerEvent):void
{
EndBug();
gotoAndStop("end");
}
//...........function of Timer Complete Event.....................
private function EndBug():void
{
HelpTimer = new Timer(1000,1);
HelpTimer.addEventListener(TimerEvent.TIMER_COMPLETE,HelpFun);
HelpTimer.start();
stage.removeEventListener(Event.ENTER_FRAME,updateStage);
stage.removeEventListener(Event.ENTER_FRAME,updateCollission);
function HelpFun(Event:TimerEvent)
{
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUpFun);
stage.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownFun);
gunFire = false;
bg_mc.removeChild(player);
bg_mc.removeChild(bunker_mc);
(life_mc.parent).removeChild(life_mc);
bg_mc.removeChild(sniper_mc);
EndFun();
Score = 0;
Level += 1;
totalBugs += 5;
}
}
//..................Function for ending the Game And removing the Reamining Enemies.................
private function EndFun():void
{
Mouse.show();
removeElement(dustArray);
if (Level == 1)
{
removeElement(enemies1);
removeElement(deadArray1);
gotoAndStop("level2");
}
if (Level == 2)
{
removeElement(enemies1);
removeElement(deadArray1);
removeElement(enemies2);
removeElement(deadArray2);
gotoAndStop("level3");
}
if (Level == 3)
{
......
}
.....................
.....................
}
}
}
In this code I have added a new type of Enemy in Level 2 and I have also written code for its HitTest property..In which each enemy of level 2 requires more than 1 bullet to kill.. But when I shoot a bullet to one enemy and then I shoot another bullet to another enemy of same type the another enemy gets killed. It means that the second enemy is getting killed in only 1 single bullet.. So how can I solve this issue..?
Please Help.. Thanks in advance..
The problem in your code lies within the checkCollision function. It basically goes over the first for loop and ignores the second. But it's best if you just assign the enemies health by adding a health parameter within your Enemy class and have each bullet decrease their health by 1. That way, you can just go through your array and remove any enemies that reach 0 health.
EDIT: I just looked over your code again and realized it's the bug2HitCount that's screwing everything up.

Collision detection for loop problem, only one array item tested?

[I apologise if this isn't really an in depth question, but I wanted to solve this once and for all]
I was trying to get look into quadtrees, but already ran into trouble getting collision detection without any optimization working properly. Did a search and found a pretty neat example:
http://wonderfl.net/c/kyLx
(onenterframeC part mostly)
Trying to imitate this, it won't work the same.
Only some collisions are detected between particular objects. When the objects are not moving it seems to work alot better for some reason.
I really can't figure out whats the problem, the code is essentially the same as the sample. I did not blindy copy pasted it, I understands whats happening except for this part:
if (j <= i)
continue;
J would never become bigger that I right? The line also completely removes any working collisions for me.
Here is what I did:
[view result here: http://martinowullems.com/collision.swf
Main class
package
{
import com.martino.objects.Square;
import com.martino.world.TestWorld;
import flash.display.MovieClip;
import flash.events.Event;
import net.hires.debug.Stats;
/**
* ...
* #author Martino Wullems
*/
public class CollisionTest extends MovieClip
{
var world:TestWorld;
public function CollisionTest()
{
addEventListener(Event.ADDED_TO_STAGE, onStage);
}
private function onStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onStage);
SetupWorld();
addChild(new Stats());
}
private function SetupWorld():void
{
world = new TestWorld();
addChild(world);
addObjects(50);
}
private function addObjects(amount:int):void
{
for (var i:int = 0; i < amount; ++i) {
var square:Square = new Square(14);
world.addObject(square);
square.x = Math.random() * stage.stageWidth;
square.y = Math.random() * stage.stageHeight;
square.speedX = (Math.random() * 1) + 1;
square.speedY = (Math.random() * 1) + 1;
}
}
}
}
TestWorld
package com.martino.world
{
import com.martino.objects.Ball;
import com.martino.objects.CollisionObject;
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author Martino Wullems
*/
public class TestWorld extends MovieClip
{
public var objects:Array;
public function TestWorld()
{
initWorld();
}
private function initWorld():void
{
objects = new Array();
addEventListener(Event.ENTER_FRAME, loopWorld);
}
private function loopWorld(e:Event):void
{
for (var i:int = 0; i < objects.length; i++) {
MoveObject(objects[i]);
CheckCollision(i, objects[i]);
}
}
private function CheckCollision(i:int, object:CollisionObject):void
{
//for (var j:int = i + 1; i < objects.length; j++) {
for (var j:int = 0; j < objects.length; j++) {
//if (j <= i)
//continue;
var objectB:CollisionObject = objects[j];
//hittest
if (object.hitTestObject(objectB)) {
object.isHit = true;
objectB.isHit = true;
}else {
object.isHit = false;
objectB.isHit = false;
}
/////////////////
// CHECK X Y //
////////////////
/*if (object.x + object.width < objectB.x) {
} else if (object.x > objectB.x + objectB.width) {
object.isHit = objectB.isHit = false;
} else if (object.y + object.height < objectB.y) {
object.isHit = objectB.isHit = false;
} else if (object.y > objectB.y + objectB.height) {
object.isHit = objectB.isHit = false;
} else {
object.isHit = objectB.isHit = true;
}*/
object.debugDraw();
objectB.debugDraw();
}
}
private function MoveObject(object:CollisionObject):void
{
object.x += object.speedX;
object.y += object.speedY;
////////////////////
//check boundaries//
////////////////////
if (object.x > stage.stageWidth)
{
object.speedX *= -1;
}else if (object.x < 0)
{
object.speedX *= -1;
}else if (object.y > stage.stageHeight)
{
object.speedY *= -1;
}else if (object.y < 0)
{
object.speedY *= -1;
}
}
public function addObject(object:CollisionObject):void
{
objects.push(object);
addChild(object);
}
}
}
CollisionObject
package com.martino.objects
{
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
* ...
* #author Martino Wullems
*/
public class CollisionObject extends Sprite
{
public var size:int;
public var speedX:int = 0;
public var speedY:int = 0;
public var graphic:Sprite;
var sleeping:Boolean = false;
public var isHit:Boolean = false;
public function CollisionObject()
{
addEventListener(MouseEvent.MOUSE_DOWN, grab);
addEventListener(MouseEvent.MOUSE_UP, letGo);
}
private function grab(e:MouseEvent):void
{
startDrag();
speedX = 0;
speedY = 0;
}
private function letGo(e:MouseEvent):void
{
stopDrag();
}
public function Collision():void{
}
//////////////////////
// setter and getter//
//////////////////////
public function set isHit(value:Boolean):void {
_isHit = value;
graphic.visible = _isHit;
hitGraphic.visible = !_isHit;
}
public function get isHit():Boolean {
return _isHit;
}
}
}
Square
package com.martino.objects
{
import flash.display.Sprite;
/**
* ...
* #author Martino Wullems
*/
public class Square extends CollisionObject
{
public var hitGraphic:Sprite;
public function Square(Size:int)
{
size = Size;
drawSquare();
}
private function drawSquare():void
{
graphic = new Sprite();
graphic.graphics.beginFill(0xFF0000);
graphic.graphics.drawRect(0, 0, size, size);
graphic.graphics.endFill();
addChild(graphic);
hitGraphic = new Sprite();
hitGraphic.graphics.beginFill(0x0066FF);
hitGraphic.graphics.drawRect(0, 0, size, size);
hitGraphic.graphics.endFill();
addChild(hitGraphic);
hitGraphic.visible = false;
}
override public function Collision():void {
trace("I collided with a friend (inside joke)");
}
public override function debugDraw():void {
if (isHit) {
graphic.visible = false;
hitGraphic.visible = true;
}else {
graphic.visible = true;
hitGraphic.visible = false;
}
}
}
}
Any help would greatly be appreciated, want to get further on this !
EDIT: Changed some stuff, there is progress but stuff still is unclear to me !
Changed some things in TestWorld.as:
package com.martino.world
{
import com.martino.objects.Ball;
import com.martino.objects.CollisionObject;
import flash.display.MovieClip;
import flash.events.Event;
/**
* ...
* #author Martino Wullems
*/
public class TestWorld extends MovieClip
{
public var objects:Array;
public function TestWorld()
{
initWorld();
}
private function initWorld():void
{
objects = new Array();
addEventListener(Event.ENTER_FRAME, loopWorld);
}
private function loopWorld(e:Event):void
{
var object:*;
for (var i:int = 0; i < objects.length; i++) {
MoveObject(objects[i]);
//CheckCollision(i);// doesn't work here for some reason [case 1]
}
CheckCollision(0); //[case 2]
}
private function CheckCollision(i:int):void
{
//test collision
for (var i:int = 0; i < objects.length; i++){ //only use in case 2
var elementA:CollisionObject;
var elementB:CollisionObject;
elementA = objects[i];
for (var j:int = i + 1; j < objects.length; j++) {
if (j <= i){
continue; //j resets each I loop and therefor sets collision to false while it could be true
}
elementB = objects[ j ]// as ObjSprite;
if (elementA.hitTestObject(elementB)) {
elementA.isHit = elementB.isHit = true;
}
}
} //[case 2]
}
private function MoveObject(object:CollisionObject):void
{
object.x += object.vx;
object.y += object.vy;
////////////////////
//check boundaries//
////////////////////
if (object.x > stage.stageWidth)
{
object.vx *= -1;
}else if (object.x < 0)
{
object.vx *= -1;
}else if (object.y > stage.stageHeight)
{
object.vy *= -1;
}else if (object.y < 0)
{
object.vy *= -1;
}
object.isHit = false;// where do we check when it isn't colliding? this seems messy!
}
public function addObject(object:CollisionObject):void
{
objects.push(object);
addChild(object);
}
}
}
Also added a setter and getter in collisionobject (so section before the edit).
Not sure why I can't put the checkcollision inside the loop on the enter frame function? (when I do no collisions are shown). And placing "isHit = false" inside moveobjects to reset a check for a hit also seems pretty messy.
I can't seem to find out when the objects aren't colliding to reset them I guess.
Making an else statement on the hittest to check if there is no collision doesn't work, seems logical since there could be collisions with more than just 2 items in the hittestcheck.
Any idea's ?
I had to look at the original source to understand this. It is below, for reference.
This line
if (j <= i) continue;
is a permutation check; it basically makes sure that each combination only gets checked once, instead of multiple times. However, for this, you need to have two For loops - an inner one and an outer one.
You've done the same thing with the following line:
for (var j:int = i + 1; i < objects.length; j++) {
Try using that for loop instead of the one that starts from zero. Leave the "if j <= i" line commented, though. I think that will solve your problem. (Those two statements can't coexist in this loop; if used together, they'll cause the problems you're describing.)
Good luck.
Original source from website:
for (i = 0; i < myrects.length; i++) {
elementA = myrects[ i ] as ObjMyRect;
for (j = 0; j < myrects.length; j++) {
if (j <= i)
continue;
elementB = myrects[ j ] as ObjMyRect;
if (elementA.rect.x + elementA.rect.width < elementB.rect.x) {
} else if (elementA.rect.x > elementB.rect.x + elementB.rect.width) {
} else if (elementA.rect.y + elementA.rect.height < elementB.rect.y) {
} else if (elementA.rect.y > elementB.rect.y + elementB.rect.height) {
} else {
elementA.isHit = elementB.isHit = true;
}
}
}
(For what it's worth, I think that this guy's code actually checks objects against themselves for collision - he should change the "if j <= i" line to "if j < i". You solved this problem with your original for loop.)
Couple of things, after looking at his code, and reviewing your code.
This part IS necessary to make sure you don't waste time going through the loop and re-checking items that have already been compared.
if (j <= i)
continue;
Imagine you have 3 items in the array, and compare item 3 to item 0. Then you compare item 3 to item 1, and item 3, to item 2. THEN you compare item 2 to... item 3? You've already done that. You want to compare item 2 to anything lesser than itself so you avoid duplicates.
Your code is close to his, but you've swapped out his version of the hitTest (which uses position + dimension) with the already-defined hitTestObject. I'm only seeing one hit-test on the first square. Something seems off in that... I'd drop some trace statements in there and see what's up.
Last, when you uncomment his code, does it work?