mismatched argument count in actionscript - actionscript-3

I keep getting this ArgumentError: Error #1063: Argument count mismatch on Car(). Expected 1, got 0. I'm confused cause I am passing staggerPosition to Car(). but it still says it is expecting 1 argument. If that is not what the error means how do I fix it? I double-checked all of my connections.
...
package {
import flash.display.*;
import flash.events.*;
public class cityAPP2 extends MovieClip {
private var carList: Array;
private var nCars: int = 16;
public function cityApp2() {
//TASK 1: ADD 16 CARS
carList = new Array();
var staggerPosition: int = 15;
for (var i: int = 0; i < nCars; i++) {
var car: Car = new Car(staggerPosition);
staggerPosition += 20;
car.x = car.mX;
car.y = car.mY;
addChild(car);
carList.push(car);
}
//TASK 2: REGISTER A LISTENER EVENT
addEventListener(Event.ENTER_FRAME, update);
}
public function update(event: Event) {
for (var i: int = 0; i < nCars; i++) {
carList[i].moveIt();
carList[i].x = carList.mx;
}
}
}
}
package {
import flash.display.*;
import flash.events.*;
public class Car extends MovieClip {
//DATA MEMBERS
public var mX: int;
public var mY: int;
public var directionFactor: int;
public var velocity: Number;
public var endZone: int;
public function Car(yPosition:int) {
this.mY = yPosition;
//TASK 1: COMPUTE THE DIRECTION
this.directionFactor = (Math.floor(Math.random() * 2) == 0) ? -1 : 1;
//TASK 2: SET THE SCALE, mX, mY, AND ENDZONE
this.scaleX = this.directionFactor;
if (this.directionFactor == -1) {
this.endZone = 800;
} else {
this.endZone = -100;
}
this.mX = endZone;
//TASK 3: SET THE VELOCITY TO RUN A RANDOM VALUE
this.velocity = Math.floor(Math.random() * 15 + 2) * this.directionFactor;
}
public function moveIt(): void {
//TASK 1: UPDATE THE X LOCATION OF THE CAR
this.mX += this.velocity;
trace(this.mX);
// TASK 2: ROTATE THE WHEELS OF THE CAR
//TASK 3: CHECK IF THE CAR HAS MOVED OFF THE SCREEN
if (this.directionFactor == -1 && this.mX < -200 || this.directionFactor == 1 && this.mX > 850) {
this.mX = endZone;
}
}
}
}
...

You likely have an instance of Car on the stage somewhere (not created in code). When you do this the constructor will be called with no arguments.
You can either remove that instance from the stage or add a default value for your argument so it won't cause an error:
public function Car(yPosition:int = 0) {
...
}

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

Error: Call to a possibly undefined method crearNotaS through a reference with static type Class

I'm new at programming and I'm working on a 'minigame' for my career.
I'm getting this error, hope someone can help me out.
public class Notas
{
public var stage:Stage;
public var velocidad:int = 5;
public var i:int = 0;
public var notaS:Array = new Array(16);
public var notaD:Array = new Array(16);
public function Notas(escenario:Stage)
{
stage = escenario;
}
public function Inicializar():void
{
crearNotaS(0xFFFFFF, 30, 10, 0, 0);
}
public function Destruir():void
{
if (notaS[i].y < 720)
{
for (i = 0; i < notaS.length; i++)
{
stage.removeChild(notaS[i])
}
}
}
public function Mover():void
{
notaS[i].y += velocidad;
}
public function drawRect(color:uint, ancho:int, alto:int, x:int, y:int):Sprite
{
var dj:Sprite = new Sprite();
dj.graphics.beginFill(color,1);
dj.graphics.drawRect(0,0,ancho,alto);
dj.graphics.endFill();
dj.x = x;
dj.y = y;
return(dj);
}
public function asignarNotas():void
{
notaS[0] = 1
}
public function crearNotaS(color:int, ancho:int, alto:int, x:int, y:int):void
{
var contador:int = 0;
for (i = 0; i < notaS.length; i++)
{
if (notaS[i] == 1 && i == 0)
{
notaS[i] = drawRect(color, ancho, alto, x, y);
stage.addChild(notaS[i]);
notaS[i].y = -alto / 2;
}
else if (notaS[i] == 1 && i > 0)
{
for (j = i; j < notaS.length; j++)
{
contador = i - j
notaS[i] = drawRect(color, ancho, alto, x, notaS[j].y + alto * contador);
stage.addChild(notaS[i]);
return;
}
}
}
}
}
Its supposed to create a array of squares (only if the content of the index is a 1, if it is a 0 then it won't create the square there.) one on top of each other and then move them all down, like a guitar hero.
Probably the way im doing it isn't proper but well, its the 1st thing i'm doing on my own...
ActionScript is an object oriented Language. Classes are supposed to be objects too and when you want to access their methods you either need to make an instance of them first or make sure the target function is of type "Static", which has limitations of its own.
This is all about core concepts which you need to know before running your code. I suggest taking a look at some tutorials about classes. This might be a good start:
Tutorial: Understanding Classes in AS3 Part 1
But about your code. It misses some imports and variable definitions, not a major flaw though. Im able to run your code. I will attach a zip file containing the AS3 AIR project which i created to test the code: Test Project
You could do this yourself in couple of steps:
Create an As3 project in the IDE of your choice. (I use FlashDevelop)
Declare the variable of type YourClass (Notas) which holds instance of your class
before using functions of your class make an instance of your class and store it in the variable.
viola, use public methods and properties of your class by accessing the variable you created.
this is the main function:
package
{
import flash.display.Sprite;
/**
* ...
* #author tkiafar
*/
public class Main extends Sprite
{
private var _not:Notas;
public function Main():void
{
if (stage) {
_not = new Notas(this.stage);
_not.asignarNotas();
_not.Inicializar();
}
}
}
}
this is your class that resides in the main package (beside main.as):
package
{
import flash.display.Sprite;
import flash.display.Stage;
public class Notas
{
public var stage:Stage;
public var velocidad:int = 5;
public var i:int = 0;
public var j:int = 0;
public var notaS:Array = new Array(16);
public var notaD:Array = new Array(16);
public function Notas(escenario:Stage)
{
stage = escenario;
}
public function Inicializar():void
{
crearNotaS(0xFF00FF, 30, 10, 0, 0);
}
public function Destruir():void
{
if (notaS[i].y < 720)
{
for (i = 0; i < notaS.length; i++)
{
stage.removeChild(notaS[i])
}
}
}
public function Mover():void
{
notaS[i].y += velocidad;
}
public function drawRect(color:uint, ancho:int, alto:int, x:int, y:int):Sprite
{
var dj:Sprite = new Sprite();
dj.graphics.beginFill(color, 1);
dj.graphics.drawRect(0, 0, ancho, alto);
dj.graphics.endFill();
dj.x = x;
dj.y = y;
return (dj);
}
public function asignarNotas():void
{
notaS[0] = 1
}
public function crearNotaS(color:int, ancho:int, alto:int, x:int, y:int):void
{
var contador:int = 0;
for (i = 0; i < notaS.length; i++)
{
if (notaS[i] == 1 && i == 0)
{
notaS[i] = drawRect(color, ancho, alto, x, y);
stage.addChild(notaS[i]);
notaS[i].y = -alto / 2;
}
else if (notaS[i] == 1 && i > 0)
{
for (j = i; j < notaS.length; j++)
{
contador = i - j
notaS[i] = drawRect(color, ancho, alto, x, notaS[j].y + alto * contador);
stage.addChild(notaS[i]);
return;
}
}
}
}
}
}
after all i have some suggestions:
seperate the array that contains control indexes and the one that contains sprites.
avoid making variables public. in your case there is no need for accessing them outside your class, but if you need to make them accessible, use getters/setters. google "getters/setters in as3".
invent some naming standards of your own. google "rules of naming in as3".

Actionscript 3.0 - MouseEvents not working

I'm trying to code a sort of strategy game through FlashDevelop and I'm getting problems when trying to use Events (particularly MouseEvents). It's not so much that the events are returning errors, it's just that they don't do anything, not even getting a trace.
I'm trying to make the hexagons HexObject image invisible when clicked on (just a simple test to see if the MouseEvent is actually working).
This is my code:
Main.as
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* ...
* #author Dean Sinclair
*/
public class Main extends Sprite {
public var gameInitialised:Boolean = false;
public var MIN_X:int = 0;
public var MAX_X:int = stage.stageWidth;
public var MIN_Y:int = 0;
public var MAX_Y:int = stage.stageHeight - 100;
public var GameGrid:HexGrid = new HexGrid(MIN_X, MAX_X, MIN_Y, MAX_Y);
public var blackBG:Shape = new Shape();
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
addEventListener(Event.ENTER_FRAME, update);
// entry point
}
private function update(event:Event):void {
if (gameInitialised == false) {
GameGrid.initialiseGrid();
initialiseBackground();
gameInitialised = true;
}
updateGraphics();
}
public function drawGrid():void {
for (var x:int = 0; x < GameGrid.TOTAL_X; x++) {
for (var y:int = GameGrid.yArray[x][0]; y < GameGrid.yArray[x][1]; y++) {
if (x != GameGrid.nox || y != GameGrid.noy) {
GameGrid.Grid[x][y].update();
this.stage.addChild(GameGrid.Grid[x][y].image);
}
}
}
}
public function updateGraphics():void {
this.stage.addChild(blackBG);
drawGrid();
}
public function initialiseBackground():void {
blackBG.graphics.beginFill(0x000000, 1);
blackBG.graphics.lineStyle(10, 0xffffff, 1);
blackBG.graphics.drawRect(0, 0, stage.stageWidth-1, stage.stageHeight-1);
blackBG.graphics.endFill();
}
}
}
HexGrid.as
package {
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
* #author Dean Sinclair
*/
public class HexGrid extends Sprite {
public static var HEX_RADIUS:int = 0;
public static var HEX_DIAMETER:int = 0;
public static var GRID_WIDTH:int = 0;
public static var GRID_HEIGHT:int = 0;
public var TOTAL_X:int = 0;
public var MIN_X:int = 0;
public var MAX_X:int = 0;
public var MIN_Y:int = 0;
public var MAX_Y:int = 0;
public var Grid:Array;
public var yArray:Array;
public function HexGrid(min_x:int, max_x:int, min_y:int, max_y:int) {
super();
MIN_X = min_x;
MAX_X = max_x;
MIN_Y = min_y;
MAX_Y = max_y;
}
public function initialiseGrid():void {
setGridDetails();
setLineLengths();
setGridPositions();
}
public function setGridDetails():void {
HEX_RADIUS = 25;
HEX_DIAMETER = 2 * HEX_RADIUS;
GRID_WIDTH = (((MAX_X - MIN_X) / HEX_DIAMETER) - 1);
GRID_HEIGHT = ((((MAX_Y - 100) - MIN_Y) / (HEX_DIAMETER - (HEX_DIAMETER / 3))) - 3);
TOTAL_X = GRID_WIDTH + Math.floor((GRID_HEIGHT - 1) / 2);
}
private function setLineLengths():void {
yArray = new Array(TOTAL_X);
for (var a:int = 0; a < TOTAL_X; a++) {
yArray[a] = new Array(2);
}
for (var x:int = 0; x < TOTAL_X; x++) {
if (x < GRID_WIDTH) {
yArray[x][0] = 0;
}else {
yArray[x][0] = (x - GRID_WIDTH + 1) * 2;
}
yArray[x][1] = 1 + (2 * x);
if (yArray[x][1] > GRID_HEIGHT) {
yArray[x][1] = GRID_HEIGHT;
}
trace("Line", x, " starts at", yArray[x][0], " ends at", yArray[x][1]);
}
}
public var nox:int = 5;
public var noy:int = 3;
private function setGridPositions():void {
var hexState:int = 4;
Grid = new Array(TOTAL_X);
for (var x:int = 0; x < TOTAL_X; x++) {
Grid[x] = new Array(yArray[x][1]);
for (var y:int = yArray[x][0]; y < yArray[x][1]; y++) {
if(nox!=4 || noy!=6){
Grid[x][y] = new HexObject(HEX_DIAMETER + (HEX_DIAMETER * x) - (HEX_RADIUS * y), HEX_DIAMETER + (HEX_DIAMETER * y) - ((HEX_DIAMETER / 3) * y), HEX_RADIUS, 2);
}
}
}
}
}
}
HexObject.as
package {
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* ...
* #author Dean Sinclair
*/
public class HexObject extends Sprite {
[Embed(source = "../images/hexagons/hex_darkRed.png")]
private var DarkRedHex:Class;
[Embed(source = "../images/hexagons/hex_lightBlue.png")]
private var LightBlueHex:Class;
[Embed(source = "../images/hexagons/hex_midGreen.png")]
private var MidGreenHex:Class;
public var image:Bitmap = new LightBlueHex();
protected var state:int = 0;
private var radius:int = 0;
public function HexObject(xPos:int, yPos:int, hexRadius:int, hexState:int) {
super();
x = xPos;
y = yPos;
state = hexState;
radius = hexRadius;
checkState();
initialiseGraphics();
}
private function checkState():void {
switch(state) {
case 1: // plains
image = new MidGreenHex();
break;
case 2: // hills
break;
case 3: // rock
image = new DarkRedHex();
break;
case 4: // water
image = new LightBlueHex();
break;
default:
break;
}
}
private function initialiseGraphics():void {
image.visible = true;
image.width = radius * 2;
image.height = radius * 2;
image.x = x - radius;
image.y = y - radius;
}
private function onMouseClick(e:MouseEvent):void {
image.visible = false;
trace("image.visible =", image.visible);
}
public function update():void {
image.addEventListener(MouseEvent.CLICK, onMouseClick);
}
}
}
I've tried countless methods to get the events working, but none have had any success. Any sort of solution to this would be a lifesaver as I've been toiling over this for hours, thanks!
My problem was fixed by VBCPP, I was using the class Bitmap which cannot dispatch MouseEvents. The solution was to take image from HexObject and put it inside an container of type Sprite, with the logical one being the object it was in. I just had to add the following code inside HexObject.as:
this.addChild(image);
and then just refer to the Object in future as opposed to image.

All my references to the stage method are throwing null reference errors in as3

I'm not sure what the change was that caused this, but suddenly i'm getting null object references in all the cases that I use the stage method as a parameter. My code is too long to fit all the different instances, so I'll just attach one or two.
package com.Mass.basics1
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class Main extends MovieClip
{
public var ourPlanet:Cosmo = new Cosmo(stage);
public var ourAsteroid:Asteroid = new Asteroid();
private var numStars:int = 80;
private var numAsteroids:int = 5;
public static var a:Number = 0;
private var stageRef:Stage;
//public var ourAsteroid:Asteroid = new Asteroid(stage);
//private var ourAsteroid:Asteroid = new Asteroid();
//our constructor function. This runs when an object of
//the class is created
public function Main()
{
//create an object of our ship from the Ship class
stop();
//add it to the display list
stage.addChild(ourPlanet);
ourPlanet.x = stage.stageWidth / 2;
ourPlanet.y = stage.stageHeight / 2;
this.stageRef = stageRef;
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), stage.getChildIndex(ourPlanet));
}
for (var o:int = 0; o < numAsteroids; o++)
{
stage.addChildAt(new Asteroid(), stage.getChildIndex(ourPlanet));
}
My debugger tells me there is a null object reference at line 13, and this code is from my engine. Cosmo is another external file that is linked to a symbol. I'll post the code from there, but there are about 4 of these errors across 4 different .as files, but it'd be too much code to put in here, so I'll just add from one other file I think would be important.
Code From Cosmo.as
package com.Mass.basics1
{
import flash.display.MovieClip;
import flash.display.Stage;
import com.senocular.utils.KeyObject;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.text.TextField;
public class Cosmo extends MovieClip
{
private var stageRef:Stage;
private var key:KeyObject;
private var speed:Number = 20;
private var vx:Number = 0;
private var vy:Number = 0;
private var friction:Number = 0.93;
private var maxspeed:Number = 8;
public var destroyed:Boolean = false;
public function Cosmo(stageRef:Stage)
{
this.stageRef = stageRef;
var key:KeyObject = new KeyObject(stage);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
//keypresses
if (key.isDown(Keyboard.A))
vx -= speed;
else if (key.isDown(Keyboard.D))
vx += speed;
else
vx *= friction;
if (key.isDown(Keyboard.W))
vy -= speed;
else if (key.isDown(Keyboard.S))
vy += speed;
else
vy *= friction;
//update position
x += vx;
y += vy;
//speed adjustment
if (vx > maxspeed)
vx = maxspeed;
else if (vx < -maxspeed)
vx = -maxspeed;
if (vy > maxspeed)
vy = maxspeed;
else if (vy < -maxspeed)
vy = -maxspeed;
//ship appearance
rotation = vx;
scaleX = (maxspeed - Math.abs(vx))/(maxspeed* 4) + 0.75;
//stay inside screen
if (x > stageRef.stageWidth)
{
x = stageRef.stageWidth;
vx = -vx;
}
else if (x < 0)
{
x = 0;
vx = -vx;
}
if (y > stageRef.stageHeight)
{
y = stageRef.stageHeight;
vy = -vy;
}
else if (y < 0)
{
y = 0;
vy = -vy;
}
}
}
}
I'm also getting an error here at line 26 for the same thing.
Code from another file
package com.senocular.utils {
import flash.display.Stage;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
/**
* The KeyObject class recreates functionality of
* Key.isDown of ActionScript 1 and 2
*
* Usage:
* var key:KeyObject = new KeyObject(stage);
* if (key.isDown(key.LEFT)) { ... }
*/
dynamic public class KeyObject extends Proxy {
private static var stage:Stage;
private static var keysDown:Object;
public function KeyObject(stage:Stage) {
construct(stage);
}
public function construct(stage:Stage):void {
KeyObject.stage = stage;
keysDown = new Object();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
}
flash_proxy override function getProperty(name:*):* {
return (name in Keyboard) ? Keyboard[name] : -1;
}
public function isDown(keyCode:uint):Boolean {
return Boolean(keyCode in keysDown);
}
public function deconstruct():void {
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.removeEventListener(KeyboardEvent.KEY_UP, keyReleased);
keysDown = new Object();
KeyObject.stage = null;
}
private function keyPressed(evt:KeyboardEvent):void {
keysDown[evt.keyCode] = true;
}
private function keyReleased(evt:KeyboardEvent):void {
delete keysDown[evt.keyCode];
}
}
}
In this file, i'm getting errors at lines 23 and 29. Thanks in advance, let me know if you need more information of any kind.
The stage property is going to be null until added to the display list hierarchy of the stage. You can't add the object to the stage until after the constructor is executed, so therefore you won't ever be able to access stage in the constructor. It's going to be null.
Call the construct method after creating the instance and adding it to the stage's display list hierarchy.

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?