getChildByName loop inside mc - actionscript-3

I'm trying to get the getChildByName work by loop inside movieclip.
On library i have a movieclip called PlayScreen, inside PlayScreen i have another movieclip called Bg. PlayScreen is put on stage by MainClass (class document) and PlayScreen is link to MainRun class. Bg movieclip is manually added to the PlayScreen by dragging it in from the library.
here is my MainRun class.
public class MainRun extends MovieClip
{
public var flyClone:Array;
public var newFly:Fly_MC;
public var spX:Number = 550;
public var spY:Number = 400;
public function MainRun()
{
flyClone = new Array();
for(var i:int=0; i<10; i++)
{
newFly = new Fly_MC(Math.random()* spX, Math.random()* spY);
flyClone.push(newFly);
addChild(newFly);
newFly.name = "fly_" + i;
}
//...
bla();
}
and here i couldn't make the getChildByName work properly, and it return; Error #1009: Cannot access a property or method of a null object reference.
at MainRun/bla()
public function bla():void
{
for(var j:int=0; j< numChildren; j++)
{
getChildByName("fly_" + j).addEventListener(Event.ENTER_FRAME, randomMove);
//...
}
}
any suggestion?

name property of your MovieClip object must is a String value, but you are putting an int there.
Try adding String(j);
It's better to use your flyClone array instead of just getting objects by it's name.
Image what will happen if you add anything else to the DisplayList (addChild).
for(var j:int=0; j< flyClone.length; j++)
{
flyClone[j].addEventListener(...);
}

I am almost positive you have a child that is not a fly.
public function bla():void
{
for(var j:int=0; j< numChildren; j++)
{
var fly : Fly_MC = getChildByName("fly_" + j) as Fly_MC;
if( fly )
{
fly.addEventListener(Event.ENTER_FRAME, randomMove);
}
}
}
Why don't you just:
for each( var fly : Fly_MC in flyClone )
{
fly.addEventListener(Event.ENTER_FRAME, randomMove);
}
or better
addEventListener(Event.ENTER_FRAME, randomMoveFlies);
public function randomMoveFlies( e:Event ):void
{
for each( var fly : Fly_MC in flyClone )
{
//move flies;
}
}

for(var j:int=0; j< flyClone.length; j++)
{
(flyClone[j] as MovieClip).addEventListener(Event.ENTER_FRAME, randomMove);
}

Related

Trace is not working in Actionscript 3 Flash CS5

I am having an issue with using trace();
For example, at multiple points in my project (and other projects) I had trace statements, which functioned until recently. For some reason now, in the same projects where it worked before, trace no longer displays anything in the Output window.
I have checked and done the following:
Verified that the filter for Output is either None or Verbose
I'm publish previewing to Flash, not HTML
In the publish settings tab, "omit trace actions" is unchecked
Verified I have flash player debugger by double checking with right clicking on flashplayer window, and seeing the option "Debugger".
Reset workspace, just in case there was something funky going on.
Read 3 other posts in StackOverflow about same issue, tried each one's solution but yet to get it to work.
Does anyone have any ideas? I had added complete code.
package
{
//importing classes
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.events.Event;
//END importing classes
public class Main extends Sprite
{
//class level variables
private const FIELD_W:uint=9;
private const FIELD_H:uint=9;
private const NUM_MINES:uint=10;
private var mineField:Array=new Array();
private var game_container:Sprite=new Sprite();
private var tile:tile_movieclip;
private var timer:Timer=new Timer(1000);
private var toolbar:toolbar_mc;
private var gameOver:Boolean=false;
private var firstClick:Boolean=true;
private var remainingTiles:uint=FIELD_W*FIELD_H;
private var minesLeft:uint=NUM_MINES;
private var screenFrame:Screens;
//END class level variables
public function Main()
{
//Mine Field Creation
for (var i:uint=0; i<FIELD_H; i++)
{
mineField[i]=new Array();
for (var j:uint=0; j<FIELD_W; j++)
{
mineField[i].push(0);
}
}
trace("My dangerous mine field: "+mineField);
//END Mine Field Creation
addChild(game_container);
for (i=0; i<FIELD_H; i++)
{
for (j=0; j<FIELD_W; j++)
{
tile = new tile_movieclip();
game_container.addChild(tile);
tile.gotoAndStop(1);
tile.nrow=i;
tile.ncol=j;
tile.buttonMode=true;
tile.x=tile.width*j;
tile.y=tile.height*i;
tile.addEventListener(MouseEvent.CLICK,onTileClicked);
}
}
// end of tile creation
//time amangement and game over
toolbar = new toolbar_mc();
addChild(toolbar);
//var s_height:uint= stage.height;
toolbar.y=725;
timer.start();
timer.addEventListener(TimerEvent.TIMER,onTick);
//end of time management and game over
}//END Main function
private function onTick(e:TimerEvent):void
{
toolbar.message_text.text="Elapsed time: "+timer.currentCount+"s";
//trace("Elapsed time: "+timer.currentCount);
}
private function tileValue(row,col:uint):int
{
if (mineField[row]==undefined || mineField[row][col]==undefined)
{
return -1;
}
else
{
return mineField[row][col];
}
}
private function onTileClicked(e:MouseEvent):void
{
if (!gameOver && remainingTiles > 0)
{
var clicked_tile:tile_movieclip=e.currentTarget as tile_movieclip;
clicked_tile.removeEventListener(MouseEvent.CLICK,onTileClicked);
clicked_tile.buttonMode=false;
var clickedRow:uint=clicked_tile.nrow;
var clickedCol:uint=clicked_tile.ncol;
var clickedValue:uint=mineField[clickedRow][clickedCol];
if (firstClick)
{
firstClick=false;
//placing mines
var placedMines:uint=0;
var randomRow,randomCol:uint;
while (placedMines<NUM_MINES)
{
randomRow = Math.floor(Math.random()*FIELD_H);
randomCol = Math.floor(Math.random()*FIELD_W);
if (mineField[randomRow][randomCol] ==0)
{
if (randomRow!=clickedRow||randomCol!=clickedCol)
{
mineField[randomRow][randomCol] = 9;
placedMines++;
}
}
}//END placing Mines
// placing digits
for (var i:uint=0; i<FIELD_H; i++)
{
for (var j:uint=0; j<FIELD_W; j++)
{
if (mineField[i][j]==9)
{
for (var ii:int =-1; ii<=1; ii++)
{
for (var jj:int =-1; jj<=1; jj++)
{
if (ii!=0||jj!=0)
{
if (tileValue(i+ii,j+jj)!=9&&tileValue(i+ii,j+jj)!=-1)
{
mineField[i+ii][j+jj]++;
}
}
}
}
}
}
}
var debugString:String;
trace("My complete and formatted mine field: ");
for (i=0; i<FIELD_H; i++)
{
debugString="";
for (j=0; j<FIELD_W; j++)
{
debugString+=mineField[i][j]+" ";
}
trace(debugString);
}
// end of placing digits
// tile creation
}
if (e.shiftKey)
{
clicked_tile.gotoAndStop(5-clicked_tile.currentFrame);
remainingTiles--;
if (remainingTiles ==0)
{
timer.stop();
//Create a for loop involving string for number that appears on tiles
toolbar.message_text.text="WinBomb";
screenFrame = new Screens();
game_container.addChild(screenFrame);
screenFrame.gotoAndStop("win");
}
if (clickedValue ==9)
{
minesLeft--;
if (minesLeft==0)
{
timer.stop();
//Create a for loop involving string for number that appears on tiles
toolbar.message_text.text="Mine Free!!";
removeChild(toolbar);
screenFrame = new Screens();
game_container.addChild(screenFrame);
screenFrame.gotoAndStop("win");
}
}
}
else
{
//empty tile
if (clickedValue == 0)
{
floodFill(clickedRow,clickedCol);
}//END empty Tile
// numbered tile
if (clickedValue>0&&clickedValue<9)
{
clicked_tile.gotoAndStop(2);
clicked_tile.tile_text.text=clickedValue.toString();
remainingTiles--;
if (remainingTiles ==0)
{
toolbar.message_text.text="Mine Free!!";
removeChild(toolbar);
screenFrame = new Screens();
game_container.addChild(screenFrame);
screenFrame.gotoAndStop("win");
}
}// end of numbered tile
// mine
if (clickedValue==9)
{
clicked_tile.gotoAndStop(3);
timer.removeEventListener(TimerEvent.TIMER,onTick);
removeChild(toolbar);
screenFrame = new Screens();
game_container.addChild(screenFrame);
screenFrame.gotoAndStop("lose");
/*timer=new Timer(5000);
timer.start();
trace("Timer to End: "+timer.currentCount);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, loseScreen); screenFrame = new Screens();
*/
}// end of mine
}
}
else if (remainingTiles == 0)
{
timer.stop();
toolbar.message_text.text="Mine Free!!";
removeChild(toolbar);
screenFrame = new Screens();
game_container.addChild(screenFrame);
screenFrame.gotoAndStop("win");
}
}//END onTileClicked function
private function floodFill(row,col:uint):void
{
var emptyTile:tile_movieclip;
emptyTile=game_container.getChildAt(row*FIELD_W+col) as tile_movieclip;
if (emptyTile.currentFrame==1)
{
emptyTile.removeEventListener(MouseEvent.CLICK,onTileClicked);
emptyTile.buttonMode=false;
emptyTile.gotoAndStop(2);
if (mineField[row][col]>0)
{
emptyTile.tile_text.text=mineField[row][col].toString();
remainingTiles--;
}
else
{
emptyTile.gotoAndStop(5);
remainingTiles--;
}
if (mineField[row][col]==0)
{
for (var ii:int =-1; ii<=1; ii++)
{
for (var jj:int =-1; jj<=1; jj++)
{
if (ii!=0||jj!=0)
{
if (tileValue(row+ii,col+jj)!=9)
{
if (tileValue(row+ii,col+jj)!=-1)
{
floodFill(row+ii,col+jj);
}
}
}
}
}
}
}
}//END floodFill
/* private function loseScreen(e:TimerEvent)
{
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, loseScreen);
game_container.addChild(screenFrame);
screenFrame.gotoAndStop("lose");
}*/
}//END Main CLass
}//END package
Looking at the top part of your code, here's a slight re-arrangement. In this experiment I've taken the liberty of initializing your '_FIELD' variables. Try it. Does this solve your problem?
var mineField:Array = new Array;
var FIELD_H:int = 10;
var FIELD_W:int = 20;
for (var i:uint=0; i<FIELD_H; i++)
{
mineField[i]=new Array();
for (var j:uint=0; j<FIELD_W; j++)
{
mineField[i].push(0);
}
}
trace(mineField);
First
Your Main Class isn't correctly written. If it's imported, your compiler should output the following error message:
1114: The public attribute can only be used inside a package.
Because the general form of a Class is:
package myPackage
{
class MyClass
{
}
}
On the other hand
Specifically, this error message doesn't occur because you haven't probably imported your Main class:
File > ActionScript Settings > Document Class : Main

Action Script 3: Adding an gotoAndStop Animation

So the other day I found a tutorial on how to create a pattern lock screen in action script. To do so I had to create a class, I have a good grasp on how the class is working. But I want to add an animation so when the user goes over the dots in the pattern and animation plays. But I have no idea how to do something like this through the class. Here is the code I used in my class.
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.Strong;
public class Main extends Sprite
{
private var dots:Array = []; // Stores the in stage movieclips
private var pattern:Array = []; //The pattern entered by the user
private var pass:Array = [1,4,7,8,5,2,5]; //The correct pattern to proceed
public function Main():void
{
dots = [one,two,three,four,five,six,seven,eight,nine]; //add the clips in stage
addListeners();
}
private function addListeners():void //adds the listeners to each dot
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_DOWN, initiatePattern);
dots[i].addEventListener(MouseEvent.MOUSE_UP, stopPattern);
}
}
/* Adds a mouse over listener and uses it to add the number of the dot to the pattern */
private function initiatePattern(e:MouseEvent):void
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_OVER, addPattern);
}
pattern.push(dots.indexOf(e.target) + 1); //adds the array index number of the clip plus one, because arrays are 0 based
}
private function addPattern(e:MouseEvent):void
{
pattern.push(dots.indexOf(e.target) + 1); //adds the pattern on mouse over
}
private function stopPattern(e:MouseEvent):void //stops storing the pattern on mouse up
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].removeEventListener(MouseEvent.MOUSE_OVER, addPattern);
}
checkPattern();
}
private function checkPattern():void //compares the patterns
{
var pLength:int = pass.length;
var correct:int = 0;
for (var i:int = 0; i < pLength; i++) //compares each number entered in the user array to the pass array
{
if (pass[i] == pattern[i])
{
correct++;
}
}
if (correct == pLength) //if the arrays match
{
//Hides Sign In
MovieClip(root).LockScreen.visible = false;
MovieClip(root).RTID.visible = false;
MovieClip(root).SignIn.visible = false;
//Turns On Main Menu
MovieClip(root).gamemenu_mc.visible = true;
MovieClip(root).biggamesmenu_mc.visible = true;
MovieClip(root).totaltextmenu_mc.visible = true;
MovieClip(root).tmenu_mc.visible = true;
MovieClip(root).smenu_mc.visible = true;
MovieClip(root).optionsmenu_mc.visible = true;
}
pattern = []; //clears the user array
}
}
}
Easiest way I can think to do this is:
inside your dot movie clip, put a stop() action on the first frame
create your animation on the dot timeline and on the last frame of the animation put another stop().
In your mouse over function, tell the dot to play.
private function addPattern(e:MouseEvent):void
{
var dot:MovieClip = MovieClip(e.currentTarget);
if(dot.currentFrame < 2) dot.play(); //play only if on the first frame
pattern.push(dots.indexOf(dot) + 1); //adds the pattern on mouse over
}
Reset the dots animation
private function stopPattern(e:MouseEvent):void //stops storing the pattern on mouse up
{
for (var i:int = 0; i < dots.length; i++)
{
dots[i].removeEventListener(MouseEvent.MOUSE_OVER, addPattern);
dots[i].gotoAndStop(1); //go back to the first frame
}
checkPattern();
}
Alternatively, if you're just want something simple like a layer of the dot fading in/out or the size of the dot increasing, you could just use a tweening library and tween the appropriate property on mouse over.
If you wanted to draw lines to connect the dots, you could do this:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.Strong;
import flash.display.Shape;
public class Main extends Sprite
{
private var lineContainer:Shape = new Shape();
private var dots:Array = []; // Stores the in stage movieclips
private var pattern:Array = []; //The pattern entered by the user //don't make life hard, just store the object itself instead of the index
private var pass:Array;
public function Main():void
{
dots = [one,two,three,four,five,six,seven,eight,nine]; //add the clips in stage
pass = [one,four,seven,eight,five,two,five]; //The correct pattern to proceed
addChildAt(lineContainer, this.getChildIndex(one)); //the line container right behind the first dot.
addListeners();
}
private function addListeners():void //adds the listeners to each dot
{
var dotsLength:int = dots.length;
for (var i:int = 0; i < dotsLength; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_DOWN, initiatePattern);
dots[i].addEventListener(MouseEvent.MOUSE_UP, stopPattern); //you could attach this to `this` instead of each dot, same result
}
}
/* Adds a mouse over listener and uses it to add the number of the dot to the pattern */
private function initiatePattern(e:MouseEvent):void
{
pattern = []; //reset array
lineContainer.graphics.clear(); //clear lines
for (var i:int = 0; i < dots.length; i++)
{
dots[i].addEventListener(MouseEvent.MOUSE_OVER, addPattern);
}
addPattern(e); //trigger the mouse over for this element
}
private function addPattern(e:MouseEvent):void
{
//if (pattern.indexOf(e.currentTarget) == -1) { //wrap in this if statemnt if only wanted a dot to be selected once (like Android)
pattern.push(e.currentTarget); //adds the pattern on mouse over
drawLines();
var dot:MovieClip = MovieClip(e.currentTarget);
if(dot.currentFrame < 2) dot.play(); //play only if on the first frame
//}
}
private function drawLines():void {
lineContainer.graphics.clear(); //clear the current lines
lineContainer.graphics.lineStyle(5, 0xFF0000); //thickness (5px) and color (red) of the lines
if (pattern.length > 1) { //don't draw if there aren't at least two dots in the pattern
lineContainer.graphics.moveTo(pattern[0].x + pattern[0].width * .5, pattern[0].y + pattern[0].height * .5); //move to first
for (var i:int = 1; i < pattern.length; i++) {
lineContainer.graphics.lineTo(pattern[i].x + pattern[i].width * .5, pattern[i].y + pattern[i].height * .5); //draw a line to the current dot
}
}
lineContainer.graphics.endFill();
}
private function stopPattern(e:MouseEvent):void //stops storing the pattern on mouse up
{
for (var i:int = 0; i < dots.length; i++)
{
dots[i].removeEventListener(MouseEvent.MOUSE_OVER, addPattern);
dots[i].gotoAndStop(1); //go back to the first frame
}
checkPattern();
}
private function checkPattern():void //compares the patterns
{
var pLength:int = pass.length;
var correct:int = 0;
for (var i:int = 0; i < pLength; i++) //compares each number entered in the user array to the pass array
{
if (pass[i] == pattern[i])
{
correct++;
}
}
if (correct == pLength) //if the arrays match
{
//Hides Sign In
MovieClip(root).LockScreen.visible = false;
MovieClip(root).RTID.visible = false;
MovieClip(root).SignIn.visible = false;
//Turns On Main Menu
MovieClip(root).gamemenu_mc.visible = true;
MovieClip(root).biggamesmenu_mc.visible = true;
MovieClip(root).totaltextmenu_mc.visible = true;
MovieClip(root).tmenu_mc.visible = true;
MovieClip(root).smenu_mc.visible = true;
MovieClip(root).optionsmenu_mc.visible = true;
}
pattern = []; //clears the user array
lineContainer.graphics.clear(); //clear the lines
}
}
}

hitTestObject issue // remove stage Error #2025

hey :S I`m trying to make 2 things so far but neither work :(
The 1st is to make an Row of 5 Ships that position them selves from the top to left.Then add an Event to make them move down.
But every time i try to make a new Row of 5 new ships ... they position themselves after the last ship from the previous Row.I did think of a way to fix that by waiting the 1st Row of ships to go beyond the stage and then remove them from the stage and splice from the Array but ... when I increase the speed of spawning (when i have 2 rows with 5 ships on the stage or more)that does't work.
And the second error I think is from that fact .... that I have 2 rows at the same time on the stage.
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at MainClass/doShips()
at MainClass/everyFrame()
I dont know what exactly to paste from the code so i had to push everything in the MainClass of the FLA.fail :D but i did it neatly! so if anyone helped me he would track the code easily
so its a simple FLA.fail with 4 MC and in those 4 MC there is no code
a Bullet
a Ship with colour Yellow
a Ship2 with colour Green so i can see the randomising
and a Player with the class Turret
so the MainClass of the FLA is :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MainClass extends MovieClip {
protected var mouseSpeed:Number = 20;
protected var _thePlayer:Turret = new Turret();
protected var shipCount:Number;
protected var shipCount2:Number;
protected var shipArray:Array = new Array();
protected var counter:int = 0;
//variables for bullets
private var shootCooldown:Number = 0; //speed of the fire
private var firing:Boolean = false;//bullets triger
private var numToShoot:int = 1; //bullets
const MAX_COOLDOWN = 10; //bullets timer
protected var _bulletsArray:Array = new Array();
public function MainClass() {
_thePlayer.x = stage.stageWidth/2
_thePlayer.y = stage.stageHeight - _thePlayer.height/2
addChild(_thePlayer)
addEventListener(Event.ENTER_FRAME, everyFrame)
stage.addEventListener(MouseEvent.MOUSE_DOWN, startFire);
stage.addEventListener(MouseEvent.MOUSE_UP, stopFire);
}
private function startFire(ev:MouseEvent) {
firing = true;
}
private function stopFire(ev:MouseEvent) {
firing = false;
}
//every frame do this
protected function everyFrame(ev:Event):void{
//Moving The Turret
moveTheTurret();
//increase the counter every frame
counter++;
if(counter % 70 == 0){
//position the ships on the stage
positionShips();
}
//handle the ships when they are added on the stage
doShips();
//when to fire
updateFire();
//handle the bullets
doBullets();
}
//Moving The Turret
protected function moveTheTurret() {
if (mouseX > _thePlayer.x +15) {
_thePlayer.x += mouseSpeed;
} else if (mouseX < _thePlayer.x - 15) {
_thePlayer.x -= mouseSpeed;
} else {
_thePlayer.x = mouseX;
}
}
//createShips and position them
protected function positionShips() {
shipCount = 3;
shipCount2 = 2;
var gap = 10;
for (var i:int = 0; i < shipCount; i++) {
var s = new Ship();
shipArray.push(s);
}
for (var j:int = 0; j < shipCount2; j++) {
s = new Ship2();
shipArray.push(s);
}
var array:Array=new Array();
while (shipArray.length>0) {
var index:uint = Math.floor(Math.random() * shipArray.length);
array.push(shipArray[index]);
shipArray.splice(index,1);
}
shipArray = array;
//shipsArray has been randomized
for (var k:int = shipArray.length - 1; k >= 0; k--) {
addChild(shipArray[k]);
shipArray[k].x = shipArray[k].width/2 + (shipArray[k].width * k) + (gap*k);
}
}
//move the ships
protected function doShips() {
for (var i:int = shipArray.length - 1; i >= 0; i--) {
shipArray[i].y +=3 //make the Ships fall down
for (var bcount= _bulletsArray.length-1; bcount >= 0; bcount--) {
//if the bullet is touching the ship
if (shipArray[i].hitTestObject(_bulletsArray[bcount])) {
//if we get here it means there`s is a collision
removeChild(_bulletsArray[bcount]);
_bulletsArray.splice(bcount,1);
removeChild(shipArray[i]);
_bulletsArray.splice(i,1);
}
}
//if it gets over 380 remove from stage and splice from the array
if(shipArray[i].y > 380){ // stage.stageHeight)
removeChild(shipArray[i]);
shipArray.splice(i,1);
}
}
}
//when to fire
public function updateFire() {
//if we are currently holding the mouse down
if(firing == true){
fire();
}
//reduce the cooldown by 1 every frame
shootCooldown--;
}
//Shoot bullets
private function fire() {
if (shootCooldown <= 0) {
//reset the cooldown
shootCooldown = MAX_COOLDOWN
for (var i=0; i<numToShoot; i++){
//spown a bullet
var b = new Bullet();
//set the rotation of the bullet
b.rotation = -90
b.x = _thePlayer.x;
b.y = _thePlayer.y;
//add the bullet to the list/Array of _bulletsArray
_bulletsArray.push(b);
//add the bullet to the perent object;
addChild(b);
}
}
}
//handling the bullets
protected function doBullets(){
//make a for loop to iterate all the _bulletsArray on the screen
for (var bcount:int = _bulletsArray.length-1; bcount>=0; bcount--) {
//make the bullets move Up
_bulletsArray[bcount].y -=20;
//if the bullet is beyond the screen remove from the stage and the Array
if(_bulletsArray[bcount].y < 0){
removeChild(_bulletsArray[bcount])
_bulletsArray.splice(bcount,1);
}
}
}
}
}
I dont know how to fix neither of the 2 problems.Would be very thankful for any help!!!
Thanks in advance.

How do I add Child when two instances collide?

I'm trying to create a virtual life simulation, where when a boy fish and a girl fish collide they reproduce. This is my first time using external class files and I'm quite confused.
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip
{
var numBalls:Number = 3;
var bFishList:Array = new Array();
var gFishList:Array = new Array();
public static var bFish:BoyFish = new BoyFish ;
public static var gFish:GirlFish = new GirlFish ;
var fishName:Object = bFish.name;
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, enterFrameNow);
function enterFrameNow(event:Event):void {
// constructor code
for (var i = 0; i < numBalls; i++) {
var bFish:MovieClip = new BoyFish();
bFish.name = "bFish"+i;
addChild(bFish);
//variable ball a movieclip is a new instance of Ball
var gFish:MovieClip = new GirlFish();
// ball x and y value was in the middle of the stage
bFish.x = stage.stageWidth / 2;
bFish.y = stage.stageHeight / 2;
// add ball to stage
bFishList.push(bFish);
// ball x and y value was in the middle of the stage
gFish.x = stage.stageWidth / 2;
gFish.y = stage.stageHeight / 2;
// add ball to stage
addChild(gFish);
gFishList.push(gFish);
addEventListener(Event.ENTER_FRAME, hitTest);
function hitTest(event:Event):void {
for (i = 0; i < bFishList.length; i++) {
if (gFish.hitTestObject(bFishList[i]) == true) {
addChild(gFish);
gFishList.push(gFish);
trace("hit");
}
}
}
}
}
trace(bFishList);
trace(gFishList);
}
}
}
Here's the code from my Main.as file. I've tried for so long with the hitTestObject thing, and it's just not working for me.
Can anyone help me? I want it to add another instance to the stage when a bFish and a gFish collide.
You shouldn't add that many enterFrame events.
Add just one enterFrame handler, in your class, not as a local function, and add a nested loop into it.
//Somewhere in your Main() function :
addEventListener(Event.ENTER_FRAME, this.hitTest);
//In class Main
public function hitTest(event:Event):void
{
for (var i = 0; i < bFishList.length; i++)
{
for (var j = 0; j < gFishList.length; j++)
{
if (gFishList[j].hitTestObject(bFishList[i]))
{
var newFish:MovieClip = new GirlFish(); //Create it.
addChild(newFish);
gFishList.push(newFish);
}
}
}
}
Please note that if you aren't doing any more action, that could result of the creation of many girl fish each frame, which could eventually freeze the flashplayer.

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