Removing an Object when it hits another object AS3 - actionscript-3

Beginner here. I have a symbol on the timeline with an instance name of 'island', so basically I want to remove the cells that hits the 'island'
if (cell.hitTestObject (island)) {
if(stage.contains(cell))
removeChild (cell);
}
I tried this one under the moveCell function but it only removes one cell instead of every cell that hits the island. Thanks everyone!
Here's my code so far:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Main extends MovieClip {
public var cell:Cell;
public var group:Array;
public var gameTimer:Timer;
public function Main() {
cell = new Cell (400, -15);
addChild (cell);
group = new Array();
var newCell = new Cell (100, -15);
group.push ( newCell);
addChild(newCell);
gameTimer = new Timer (25);
gameTimer.addEventListener(TimerEvent.TIMER,moveCell);
gameTimer.start();
}
public function moveCell (timerEvent:TimerEvent):void {
if (Math.random() < 0.01) {
var randomX:Number = Math.random() * 700;
var newCell:Cell = new Cell (randomX, -15);
group.push (newCell);
addChild(newCell);
}
for each(var i:MovieClip in group) {
if (i.hitTestObject(island)) {
i.visible = false;
//i.parent.removeChild(i);
var score:int = 0;
score ++;
scoreOutPut.text = score.toString();
}
}
}
}
}`

You got the "Cannot access a property or method of a null object reference" because you've removed the Cell object from the DisplayObjectContainer (its parent) but not from the group array, so in the next iteration of your for loop, that object didn't exist anymore and that error will be fired.
To avoid that you can do like this :
for(var i:int = 0; i < group.length; i++)
{
var cell:Cell = Cell(group[i]);
if (cell.hitTestObject(island))
{
cell.parent.removeChild(cell);
group.splice(i, 1);
score++;
}
}
For the score, it should be a global property for all your class to get updated every time.
Also, for your code to be more organised and clearer, it's better to put every task in a single method.
For example, for creating cells, you can use a createCell() method :
// 0 is the default value of __x and -15 is the default one of __y
private function createCell(__x:Number = 0, __y:Number = -15): void
{
var cell:Cell = new Cell(__x, __y);
group.push(cell);
addChild(cell);
}
Then you can use it in any place in your code, for example, for your two first cells that you create in the constructor :
public function Main()
{
// ..
createCell(400);
createCell(100);
// ...
}
Or inside the moveCell() method :
if (Math.random() < 0.01)
{
var randomX:Number = Math.random() * 700;
createCell(randomX);
}
Also, if you don't really need that a property or a method to be public, don't put it as public.
...
Hope that can help.

Related

AS3: Why is a line created with .graphics appearing in two different places and when removed with parent.visible = false, only one goes?

Nobody seems to have this question already so I asked it because I've spent a few hours trying to debug this and can't find a solution;
Essentially, I have a function called draw, which is declared in my document class:
public function draw(Target: MovieClip,mX: int,mY: int,lX: int,lY: int):void {
Target.graphics.clear();
Target.graphics.lineStyle(1,0x000000,1);
Target.graphics.moveTo(mX,mY);
Target.graphics.lineTo(lX,lY);
}
I call it later to draw two lines, on two different MovieClips:
draw(Line,Line.mX,Line.mY,Mirror.x + (Mirror.width / 2),Line.lY);
draw(nextLine,(Mirror.x + (Mirror.width / 2)),200,(Mirror.x + (Mirror.width / 2)),0);
where
var Line: MovieClip = new MovieClip();
var Mirror: MovieClip = new mirror();
and Mirror is draggable, so Mirror.x changes whenever it is dragged.
Line is a line made using .graphics and Line.mX is equal to the Line.graphics.moveTo X value last time it was modified. Line.mY is the same, but for the Y coordinate. I set these values by doing this:
Line.mX = 0;
Line.mY = 200;
Line.lX = 550;
Line.lY = 200;
But with whatever values I want to draw the line, with lX and lY being equal to the X and Y coordinates of Line.graphics.lineTo. Then I draw Line using my draw function like this:
draw(Line,Line.mX,Line.mY,Line.lX,Line.lY);
Then it gets more complex because, actually, Line is just one line in an array of lines, created like this:
public var lines = [line0,line1,line2,line3,line4,line5,line6,line7,line8];
and each of those lines is created like this (with 0 being replaced by the line's number, respectively):
public var line0: MovieClip = new MovieClip();
then I give each line a number and a name, add them to the stage and hide them like this:
for each(var setupLine:MovieClip in lines) {
setupLine.num = (lines.indexOf(setupLine));
setupLine.name = ('line' + setupLine.num);
addChild(setupLine);
setupLine.visible = false;
}
Then, after making line0 visible, because I need to see it at the start, I loop through each line in a function that runs on ENTER_FRAME, and set the value of nextLine to a different value each time I run the loop like this:
for each(var Line:MovieClip in lines) {
nextLine = this['line' + (Line.num + 1)];
}
Within that loop, I then loop through a few other arrays, then check for a collision with the selected Line and another selected MovieClip from another array, which I wont go into or this question will be longer than the code for node.js.
So essentially, if the collision with the two MovieClips is present, I draw the line that I mentioned at the top of my question. But for some reason, although Line draws correctly, nextLine draws correctly, but a duplicate of it is drawn across the Y axis at 0, and stops where nextLine is on the Y axis (nextLine is vertical, so it has the same Y value at the start as at the end).
Even stranger, when I try to hide nextLine if the collision with the two MovieClips is no longer present, using this code:
nextLine.visible = false;
it only hides the version of nextLine that runs along the top of the stage, which I didn't even intend to create in the start.
EDIT
here is a link to the current source code
Here is a link to the entire project files with the original source code
copy/paste the new source code from the pastebin link to get the new version
Thanks in advance,
-Raph
I figured out how to do this, code is
package {
import flash.events.*;
import flash.utils.*;
import flash.display.*;
[SWF(backgroundColor="0xbdc3c7")]
public class LightStage extends MovieClip {
//import classes
public var globeClass:Globe = new Globe();
public var mirrorClass:Mirror = new Mirror();
public var lineClass:Line = new Line();
//create all stage objects
public var curLine:Line
public var nextLine:Line;
public var curMirror:Mirror;
//create containers
public var mirrors:Vector.<Mirror> = new Vector.<Mirror>(); //a vector is an array, but every member has to be (or subclass) the specified class
public var globes:Vector.<Globe> = new Vector.<Globe>();
public var lines:Vector.<Line> = new Vector.<Line>();
trace('lightstage: working');
//create level object
public var curLevel:int = -1;
//create dependent variables
public var kill: Boolean = true;
//init function
public function LightStage() {
//setup MovieClips
var i:int = 0;
for (i = 0; i < 4; i++) {
mirrors.push(new Mirror());
}
for (i = 0; i < 4;i++ ) {
globes.push(new Globe());
}
var tmpLine:Line;
for (i = 0; i < 10; i++) {
tmpLine = new Line();
lines.push(tmpLine);
addChild(tmpLine);
tmpLine.visible = false;
}
//create ENTER_FRAME listener
stage.addEventListener(Event.ENTER_FRAME,enterFrame);
//start the game
levelUp();
}
//levelUp function
public function levelUp() {
curLevel++;
curLine = lines[curLevel]; //set line to the current level
curLine.curX = 0;
curLine.curY = 200;
curLine.draw(550, 200);
curLine.visible = true;
//show and position mirrors and globes
curMirror = mirrors[curLevel];
addChild(curMirror);
curMirror.x = 250;
curMirror.y = 350;
var curGlobe:Globe = globes[curLevel];
addChild(curGlobe);
curGlobe.x = 100;
curGlobe.y = 50;
//set mirror types
curMirror.gotoAndStop(2);
trace("you are now on level " + (curLevel + 1) + "!");
}
//ENTER_FRAME function
public function enterFrame(event:Event) {
//line1.visible = true;
for (var i:int = 0; i < lines.length;i++){
if (i < lines.length - 1) nextLine = lines[i + 1]; //check for out of bounds before assignment next line
if (lines[i].visible == true) {
kill = true;
for each(var mirror:Mirror in mirrors) {
if (lines[i].visible && mirror.stage && mirror.hitTestObject(lines[i])) { //for efficiency, do the hit test last in the if statement
for each(var globe:Globe in globes) {
//Looped through Mirrors and Lines and checked for collision - if collision is present, we loop through globes here
if (nextLine && nextLine.stage) {
addChild(nextLine);
}
//check for active globes
if (lines[i].visible && lines[i].hitTestObject(globe)) {
//check if the selected line touches the selected globe - if it does then we will start the timer for that globe
if (!globe.running){
globe.start();
//trace('timing');
kill = false;
}
}
else {
globe.reset();
}
switch(mirror.currentFrame) {
case 1:
break;
case 2:
//trace('live a life you will remember' + Math.random());
if(nextLine) nextLine.visible = true;
lines[i].draw(mirror.x + (mirror.width / 2),lines[i].curY);
if (nextLine) {
nextLine.curX = mirror.x + (mirror.width / 2);
nextLine.curY = 200;
nextLine.draw(mirror.x + (mirror.width / 2), 0);
}
kill = false;
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
trace(mirror.currentFrame);
kill = false;
break;
}
}
}
else if (lines[i].visible && mirror.stage && lines[i].stage){
if (kill && nextLine){
nextLine.graphics.clear();
nextLine.visible = false;
}
}
}
}
}
}
}
}
//MIRROR CLASS DECLARATION
import flash.events.MouseEvent;
class Mirror extends MovieClip {
trace('mirror: working');
public function Mirror() {
this.addEventListener(MouseEvent.MOUSE_DOWN,onDown,false,0,true);
}
private function onDown(e:MouseEvent):void {
//add the mouse up listener on the stage, that way it's consistent even if the user drags so fast that the mouse leaves the bounds of the mirror
stage.addEventListener(MouseEvent.MOUSE_UP, onUp, false, 0, true);
this.startDrag();
}
private function onUp(e:MouseEvent):void {
//we need to remove the listener from the stage now
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp, false);
this.stopDrag();
}
}
//LINE CLASS DECLARATION
import flash.display.Graphics;
class Line extends MovieClip {
trace('line: working');
public var curX:int;
public var curY:int;
public function Line():void {
}
public function draw(toX:int,toY:int):void {
graphics.clear();
graphics.lineStyle(1,0x000000,1);
graphics.moveTo(curX,curY);
graphics.lineTo(toX, toY);
curX = toX;
curY = toY;
}
}
//GLOBE CLASS DECLARATION
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.utils.Timer;
class Globe extends MovieClip {
trace('globe: working');
private var timer:Timer = new Timer(3 * 100, 5);
public function Globe():void {
timer = new Timer(300, 5);
timer.addEventListener(TimerEvent.TIMER, repeatShine, false, 0, true);
}
public function reset():void {
timer.reset();
}
public function start():void {
timer.start();
}
public function get running():Boolean { return timer.running; };
private function repeatShine(e:TimerEvent):void {
}
}

As3 Error: Error #1009: Cannot access a property or method of a null object reference

I seem to be having an error with my inventory system.
This is my class:
package
{
import flash.display.*;
public class InventoryDemo extends MovieClip
{
var inventory:Inventory;
public function InventoryDemo()
{
inventory = new Inventory(this);
inventory.makeInventoryItems([d1,d2]);
}
}
}
I have already placed d1 and d2 objects in a second keyframe.
And this is the child class:
package
{
import flash.display.*;
import flash.events.*;
public class Inventory
{
var itemsInInventory:Array;
var inventorySprite:Sprite;
public function Inventory(parentMC:MovieClip)
{
itemsInInventory = new Array ;
inventorySprite = new Sprite ;
inventorySprite.x = 50;
inventorySprite.y = 360;
parentMC.addChild(inventorySprite);
}
function makeInventoryItems(arrayOfItems:Array)
{
for (var i:int = 0; i < arrayOfItems.length; i++)
{
arrayOfItems[i].addEventListener(MouseEvent.CLICK,getItem);
arrayOfItems[i].buttonMode = true;
}
}
function getItem(e:Event)
{
var item:MovieClip = MovieClip(e.currentTarget);
itemsInInventory.push(item);
inventorySprite.addChild(item);
item.x = itemsInInventory.length - 1 * 40;
item.y = 0;
item.removeEventListener(MouseEvent.CLICK,getItem);
item.addEventListener(MouseEvent.CLICK,useItem);
}
function useItem(e:Event)
{
var item:MovieClip = MovieClip(e.currentTarget);
trace(("Use Item:" + item.name));
}
}
}
The code works when I try it in a black project with only d1 and d2 in the stage. Can any one help me solve this?
Your error suggests that d1 and d2 are not created at the time that you call
inventory.makeInventoryItems([d1,d2]);
You suggest that you have created d1 and d2 in the second keyframe, but if InventoryDemo is your DocumentClass, then it will run before you reach the second keyframe.
So, if you want to use d1 and d2 you either need to move them to the first frame, or you need to not try and use them until the second frame of the Movie has occurred.
If you want to keep d1 and d2 on the second frame, then you need to take the call out of the constructor and into a new function that you call on the second frame:
public function InventoryDemo()
{
//Do nothing here
//inventory = new Inventory(this);
//inventory.makeInventoryItems([d1,d2]);
}
public function initialiseInventory():void
{
//Initialise you inventory here.
inventory = new Inventory(this);
inventory.makeInventoryItems([d1,d2]);
}
Then on the 2nd frame of your timeline call the function:
initialiseInventory();
stop();

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.

How to make new bubbles stack in my Bubble Shooter game?

I'm making a Bubble Shooter game, and I'm trying to make the bubble I'm fireing to stack and then be at the right place in the column. The bubbles I've placed on the board looks like this:
000000000000000
000000000000000
000000000000000
000000000000000
There's 4 rows with 15 bubbles. This is the code I have written so far:
Main
package {
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.SpreadMethod;
public class Main extends Sprite {
private const ROT_SPEED:uint=2;
private const R:uint=18;
private const DEG_TO_RAD:Number=0.0174532925;
private const BUBBLE_SPEED:uint=10;
private var bubbleArr:Array=new Array();
private var loadArr:Array=new Array();
private var cannon:cannon_mc;
private var bubble:bubble_mc;
private var row:uint=0;
private var col:uint=0;
private var left:Boolean=false;
private var right:Boolean=false;
public var bubCont:Sprite;
private var loadCont:Sprite;
private var fire:Boolean=false;
private var vx,vy:Number;
public function Main() {
placeContainer();
placeCannon();
loadBubble();
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onKUp);
addEventListener(Event.ENTER_FRAME,onEFrame);
trace("row= "+row+" , col= "+col);
}
private function placeCannon():void {
cannon=new cannon_mc();
addChild(cannon);
cannon.y=385.5;
cannon.x=320;
}
private function onKDown(e:KeyboardEvent):void {
switch(e.keyCode) {
case 37 :
left=true;
break;
case 39 :
right=true;
break;
case 38 :
if (! fire) {
fire=true;
var radians=(cannon.rotation-90)*DEG_TO_RAD;
vx=BUBBLE_SPEED*Math.cos(radians);
vy=BUBBLE_SPEED*Math.sin(radians);
}
break;
}
}
private function onKUp(e:KeyboardEvent):void {
switch(e.keyCode) {
case 37 :
left=false;
break;
case 39 :
right=false;
break;
}
}
private function onEFrame(e:Event):void {
if (left) {
cannon.rotation-=ROT_SPEED;
}
if (right) {
cannon.rotation+=ROT_SPEED;
}
if (fire) {
bubble.x+=vx;
bubble.y+=vy;
if (bubble.x<59) {
bubble.x=59;
vx*=-1;
}
if (bubble.x>(59+R*R)) {
bubble.x=59+R*R;
vx*=-1;
}
if (bubble.y<(40)) {
bubble.y=40;
}
}
}
public function placeContainer():void {
var iRow:Boolean=false;
bubCont=new Sprite();
addChild(bubCont);
for (var i:uint=0; i<4; i++) {
if (! iRow) {
for (var j:uint=0; j<15; j++) {
bubbleArr[i]=new Array();
bubbleArr[i][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i][j],i,j);
bubCont.addChild(bubble);
iRow=true;
row++;
col++;
}
} else {
for (j=0; j<15; j++) {
bubbleArr[i]=new Array();
bubbleArr[i][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i][j],i,j);
bubble.x=77+j*2*R;
bubCont.addChild(bubble);
iRow=false;
row++;
col++;
}
}
}
}
private function loadBubble():void {
addChild(bubble);
bubble.gotoAndStop(Math.floor(Math.random()*6))+1;
bubble.x=320;
bubble.y=410;
}
}
bubble_mc class:
package {
import flash.display.MovieClip;
public class bubble_mc extends MovieClip {
public function bubble_mc(val:uint,row:uint,col:uint) {
gotoAndStop(val+1);
name=row+"_"+col;
x=59+col*36;
y=40+row*32;
}
}
I have absolutley no idea how to make the bubbles stack together.. I have tried using hitTestObject-function and I have tried to write my own function that checks for collision and then calls a function that is supposed to place the bubble in the right place, but it doesn't work and I dont know why. I'm getting a error called TypeError: Error #1010.
Here is the collision function and the parkBubble function- which is supposed to place the bubbles in the right place:
private function parkBubble(bubble:bubble_mc,row:int,col:int):void {
var iRow:Boolean=false;
for (var j:uint=0; j<col; j++) {
trace("first for loop ");
for (var i:uint=row; i>0; i--) {
trace("second for loop ");
if (bubbleArr[i][j]!=null) {
trace("first if loop ");
if (! iRow) {
trace("second if loop ");
bubbleArr[i+1]=new Array();
bubbleArr[i+1][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i+1][j],(i+1),j);
bubCont.addChild(bubble);
iRow=true;
row++;
col++;
} else {
trace("first for loop after else ");
bubbleArr[i+1]=new Array();
bubbleArr[i+1][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i+1][j],(i+1),j);
bubble.x=77+j*2*R;
bubCont.addChild(bubble);
iRow=false;
row++;
col++;
}
}
}
}
removeChild(bubble);
fire=false;
loadBubble();
trace("slutet av parkBubble ");
}
private function collide(bub:bubble_mc):Boolean {
var dist_x:Number=bub.x-bubble.x;
var dist_y:Number=bub.y-bubble.y;
return Math.sqrt(dist_x*dist_x+dist_y*dist_y)<=2*R-4;
}
Was the TypeError on this line?
var placed_bubble:bubble_mc=new bubble_mc([row][col],row,col);
The [row] is an array, and [col] is an array. But the constructor expects an unsigned integer:
public function bubble_mc(val:uint,row:uint,col:uint) {
In order to copy the bubble to the bubble container, pass the frame number:
var placed_bubble:bubble_mc=new bubble_mc(bubble.currentFrame-1, row, col);
This might not be the only problem. TypeError often results from a variable not being defined, which could be from some other code that modifies the variable "bubble". For example, placeContainer assigns the bubbles in the container to the variable "bubble".
The function parkBubble always sets "iRow" to false, but if the bubble collides with a row above it that is odd you want iRow to be true.
var row:uint=Math.floor(bubble.y/(40+R*Math.sqrt(3)));
var iRow:Boolean= row % 2 == 1 ? true : false;
After it is at least compiling, you'll have less problems if you go back and simplify and optimize the math with some constant names. Then you'll more easily see the above code for calculating the row is not quite right. It should subtract the top margin (40). That is obvious with named constants:
private const Y_PER_ROW:int = int(R * Math.sqrt(3));
private const TOP:int = 40;
...
var row:uint = int((bubble.y - TOP) / Y_PER_ROW);
I would double-check your other calculations, too. Puzzle Bobble games usually set the odd rows to horizontally offset at radius, not at 2 radius (2 * R). So they fit together like hexagons.
The placeContainer function could be simplified. Most of the code in even or odd rows is the same, so could be taken out of the if block. And in this code you posted, I don't see why you need "row++" and "col++" in placeContainer. This is equivalent and easier to read:
for (var i:uint=0; i<4; i++) {
var xOffset:int = (i % 2) * 2 * R;
for (var j:uint=0; j<15; j++) {
bubbleArr[i] = new Array();
bubbleArr[i][j] = int(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i][j], i, j);
bubble.x += xOffset;
bubCont.addChild(bubble);
row++;
col++;
}
}
Then, the collision detection code could be simplified and optimized to avoid calculations when the bubble is far away and avoid the expensive square-root calculation:
Circle Collision Detection HTML5 Canvas
http://cgp.wikidot.com/circle-to-circle-collision-detection

AS3 Creating an array of objects

I would like to add a bunch of cars to the stage, and store them in an array as objects. The problem is I hate using external AS files and would like to keep it as simple as possible.
I tried doing :
var car:Object = {carcolor:String,carscale:Number,carpower:Number};
var test:Array = new Array()
for (var i:Number=0; i<10; i++) {
test.push(car)
}
The problem is if I try to set a value of one object in the like
test[1].carscale = 5
Every object in the array gets their attribute carscale set to 5.
Is there any way I can do this without using external class files?
While you should use external AS files (its a good practice), here's the reason why you are having the issue, and I'm going to explain line-by-line
var car:Object = {carcolor:String,carscale:Number,carpower:Number};
//This creates an object called car. Suppose it saves it in memory at "location" 0x12345
var test:Array = new Array();
//This creates an empty array
for (var i:Number=0; i<10; i++) {
test.push(car);
//This adds the object "car" to the array
//Since Object is a reference type, its memory location is actually added to the array
//This means you added 0x12345 to the array (10 times over the loop)
}
//The array now contains
[0x12345, 0x12345, 0x12345, .......];
//So now
test[1]; //returns the object at 0x12345
test[1].carscale=5; //sets the carscale property of the object at 0x12345
Since all objects in the array point to the same location, getting any of them will actually return the same object. This means that all of them will show carscale as 5
A solution to this would be:
var test:Array = new Array();
for (var i:Number=0; i<10; i++) {
var car:Object = {carcolor:String,carscale:Number,carpower:Number};
test.push(car);
}
A better, REAL Object oriented solution would be to create a class called Car and then instead of doing
var car:Object = {carcolor:String,carscale:Number,carpower:Number};
you use
var car:Car = new Car();
The Car.as class would be like this:
public class Car {
public function Car() {
//this is the constructor, initialize the object here
//Suppose the default values of the car are as follows:
carcolor="red";
carscale=5;
carpower=1000;
}
public var carcolor:String;
public var carscale:Number, carpower:Number;
}
In fact, you could even use another constructor that automatically sets the properties based on arguments:
public function Car(_color:String, _scale:Number, _power:Number) {
carcolor=_color;
carscale=_scale;
carpower=_power;
}
and call it as
var car:Car=new Car("red", 5, 1000);
In fact, the car before carcolor, carscale and carpower is not even necessary because it is obvious when you put them in a class called Car.
Like TheDarkIn1978 said you're pushing a reference of your car instance into your array. When you change the value of one instance's property the same happens for each reference.
The simple answer is to create a new object upon each interation of your for loop like in the following:
var test:Array = [];
for (var i:Number = 0; i < 10; i++)
{
var car:Object = {carcolor:String, carscale:Number, carpower:Number};
test.push(car);
}// end for
[UPDATE]
I know you said that you didn't want to use "external classes" but there are advantages to using a custom class object to store values as opposed to a Object object. Here is an example:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var cars:Vector.<Car> = new Vector.<Car>();
cars.push(new Car("red", 1, 1));
cars.push(new Car("blue", 2, 2));
cars.push(new Car("green", 3, 3));
trace(cars[2].color); // output: green
}// end function
}// class
}// end package
internal class Car
{
private var _color:String;
private var _scale:Number;
private var _power:Number;
public function get color():String { return color; }
public function get scale():String { return scale; }
public function get power():String { return power; }
public function Car(color:String, scale:Number, power:Number)
{
_color = color;
_scale = scale;
_power = power;
}// end function
}// end class
This is a good example of creating an object for the sole purpose of storing values that never change by only allowing the object's properties to be set upon initiation and using getter methods to make the values read only.
I feel dumb, I found the answer here :
http://board.flashkit.com/board/showthread.php?t=792345
You're pushing the Object reference to the array, not a unique Object each time. You have to do something like:
for(var temp=0;temp<100;temp++){
var roomData:Object=new Object;
roomData.first_time=true;
rooms.push(roomData);
}
you're adding the same object to the array multiple times. you need to create new instances of your car object.
EDIT:
although it would be a best practice to create your own "Car" class and create new instances of it, even if it's only a small object with 3 properties, here's a quick example that should get you started.
package
{
//Imports
import flash.display.Sprite;
//Class
public class Main extends Sprite
{
//Constants
private static const DEFAULT_CAR_COLOR:Number = 0x000000;
private static const DEFAULT_CAR_SCALE:Number = 1.0;
private static const DEFAULT_CAR_POWER:int = 50;
//Properties
private var carsArray:Array;
//Constructor
public function Main():void
{
init();
outputCarColors();
}
//Initialize
private function init():void
{
carsArray = new Array();
for (var i:int = 0; i < 10; i++)
{
carsArray.push(CreateCar(Math.random() * 0xFFFFFF));
}
}
//Output Car Colors
private function outputCarColors():void
{
for (var i:int = 0; i < carsArray.length; i++)
{
trace("Color of car " + i + " : " + carsArray[i].carColor);
}
}
//Create Car Object
private function CreateCar(carColor:Number = DEFAULT_CAR_COLOR, carScale:Number = DEFAULT_CAR_SCALE, carPower:int = DEFAULT_CAR_POWER):Object
{
var result:Object = new Object();
result.carColor = carColor;
result.carScale = carScale;
result.carPower = carPower;
return result;
}
}
}