I'm wondering if it is possible to reset / reload / reconstruct an array order?
I'm making this "Space Invaders" game and the enemy's need to restart to it's position when the game is being restarted. When I shoot down the enemy's and reset my game, the enemy's I've killed keep being gone.
So here's some of the code responsible:
var spiderArray:Array = new Array(enemyField.enemy1,enemyField.enemy2,
enemyField.enemy3,enemyField.enemy4,
enemyField.enemy5,enemyField.enemy6,
enemyField.enemy7,enemyField.enemy8,
enemyField.enemy9,enemyField.enemy10,
enemyField.enemy11,enemyField.enemy12,
enemyField.enemy13,enemyField.enemy14,
enemyField.enemy15,enemyField.enemy16,
enemyField.enemy17,enemyField.enemy18,
enemyField.enemy19,enemyField.enemy20,
enemyField.enemy21,enemyField.enemy22,
enemyField.enemy23,enemyField.enemy24,
enemyField.enemy25,enemyField.enemy26,
enemyField.enemy27,enemyField.enemy28,
enemyField.enemy29,enemyField.enemy30,
enemyField.enemy31,enemyField.enemy32,
enemyField.enemy33,enemyField.enemy34,
enemyField.enemy35,enemyField.enemy36,
enemyField.enemy37,enemyField.enemy38,
enemyField.enemy39,enemyField.enemy40,
enemyField.enemy41,enemyField.enemy42,
enemyField.enemy43,enemyField.enemy44,
enemyField.enemy45,enemyField.enemy46,
enemyField.enemy47,enemyField.enemy48,
enemyField.enemy49,enemyField.enemy50,
enemyField.enemy51,enemyField.enemy52,
enemyField.enemy53,enemyField.enemy54,
enemyField.enemy55,enemyField.enemy56,
enemyField.enemy57,enemyField.enemy58,
enemyField.enemy59,enemyField.enemy60,
enemyField.enemy61,enemyField.enemy62,
enemyField.enemy63,enemyField.enemy64,
enemyField.enemy65,enemyField.enemy66);
Now the place where the enemy's are being killed:
function enemyHitTest():void {
//for each of the three spiders
for(var i:int = 0; i < spiderArray.length; i++) {
//the each of the six bullets
for(var j:int = 0; j < 6; j++) {
//don't consider bullets that aren't in play:
if(bulletArray[j].y > SpelerMC.y) continue;
if(spiderArray[i].hitTestObject(bulletArray[j])) {
score += 10;
scoreTxt.text = score.toString();
trace("Invader " + i + " neergeschoten!");
spiderArray[i].parent.removeChild(spiderArray[i]);
bulletArray[j].x = j * 70 + 100;
bulletArray[j].y = 595;
}
}
}
Now I think I need to put some sort of theArray.pop(); or something, but don't know how to use it, but I need to place it in this function:
function startGame() {
trace("Start het spel opnieuw...");
gameTimer.addEventListener(TimerEvent.TIMER, onTick);
gameTimer.start();
enemyField.x = 400;
enemyField.y = 160;
SpelerMC.x = 83;
SpelerMC.y = 531;
}
Please help me! Have been searching for 5 hours already. Thanks in advance!
to remove element number i use array.splice(i, 1); ( http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#splice().com/en_US/FlashPlatform/reference/actionscript/3/Array.html#splice%28%29) but keep in mind that array.length will decrease
to reset the array just invoke spidersArray = new Array(enemyField.enemy1, etc) again
UPDATE
in in the enemyHitTest function i changed the removing condition to if(enemyArray[i].visible && enemyArray[i].hitTestObject(laserArray[j])) and enemyArray[i].parent.removeChild(enemyArray[i]); to enemyArray[i].visible = false;
and added
function respawnEnemies():void{
for(var i:int = 0; i < enemyArray.length; i++) {
enemyArray[i].visible = true;
}
}
to call it from startGame
full code here
upd 2
so the problem was not in resetting the array but in the fact that your enemyField and its' enemies were added to stage manually and removed programmatically so there was no code to call to bring them back
if all your instances should be preserved - e.g. you generate all actors at the beginning and later all of them are reused (at the new game) you can set an array of them and on each start game make a copy and remove "dead" enemies from the copied array
also better option is to use a vector e.g.
var enemies:Vector.<Enemy> = Vector.<Enemy>([]);//in brackets references to the instances of Enemy class
var inGame:Vector.<Enemy> = enemies.concat();
also 5hrs of research? please be patient and try harder,
best regards
Related
I have a little problem with my flash game. My array of birds (obstacles) everytime when they reach let's say x -800 they respawn at the starting position in everytime at random place in an array and it works well.
BUT
Every time it loops, birds 1 by 1 stacks at the first position of an array. It is weird.
public function setUpBirds() {
for (var i:int = 0 ;i< 10; i++) {
var mcClip:Bird = new Bird();
var yVal:Number = (Math.ceil(Math.random()*100));
birds.push(mcClip);
birds[i].x = 100 * i;
birds[i].y = yVal * i;
birdsContainer.addChild(mcClip);
}
}
private function moveBirds(event:Event):void {
birdsContainer.x = birdsContainer.x -10;
if (birdsContainer.x == -500) {
birdsContainer.x = 500;
setUpBirds();
}
}
Any ideas?
Everytime your birdsContainer has an x of 500, you call setUpBirds(), so let's step though and look at what's happening: (explained with code comments injected into your code)
First time setUpBirds runs:
for (var i:int = 0 ;i< 10; i++) {
//a new bird is created 10 times
var mcClip:Bird = new Bird();
var yVal:Number = (Math.ceil(Math.random()*100));
//you add it to the array
birds.push(mcClip);
//birds[1] properly refers to the item you just pushed into the array
birds[i].x = 100 * i;
birds[i].y = yVal * i;
birdsContainer.addChild(mcClip);
}
First time through, everything is great, your birds array has 10 items in it now.
Now, second time the function runs:
for (var i:int = 0 ;i< 10; i++) {
//create 10 more new birds (in addition to the last ones)
var mcClip:Bird = new Bird();
var yVal:Number = (Math.ceil(Math.random()*100));
//add to the array (which already has 10 items in it)
birds.push(mcClip); //so if i is 5, the item you just pushed is at birds[14]
//birds[i] will refer to a bird you created the first time through
//eg bird[0] - bird[9] depending on `i`, but really you want bird[10] = bird[19] this time around
birds[i].x = 100 * i; //your moving the wrong bird
birds[i].y = yVal * i;
//the new birds you create, will have an x/y of 0
//since birds[i] doesn't refer to these new birds
birdsContainer.addChild(mcClip);
}
Now you see the problem? your birds array now has 20 items in it, so you are now referencing the wrong item in the array.
To fix this, just set the x/y on the mcClip var instead of the array, or do birds[birds.length-1].x = 100 * i to use the last item added to the array.
On a side note, your performance is going to get pretty bad pretty fast creating 10 new birds all the time. You need to get rid of those old birds if you're constantly creating new ones.
Seems like what you probably WANT to do is just reposition the existing birds every loop, so that would look something like this:
for (var i:int = 0 ;i< 10; i++) {
//check if there is NOT a bird already at this position in the array
if(birds.length <= i || !birds[i]){
//no bird yet, so create it and add it and push it
var mcClip:Bird = new Bird();
birds.push(mcClip);
birdsContainer.addChild(mcClip);
}
//now set the position of the bird
var yVal:Number = (Math.ceil(Math.random()*100));
birds[i].x = 100 * i;
birds[i].y = yVal * i;
}
This way, you only ever creating 10 birds and you are just resetting the y position of those birds every loop.
Hey guys so I ran into a Bug with my code I have a Movie Clip Object called mainFish that is setup with the array aFishArray and I have the array setup in a for loop to check a HitTest with playerHook. Now everything works completely fine but the issue that I am having is when say two of the Fish hit the hook at the same time one of of the fish hooks on the hook and the other just stays on the screen and i run into my sound Object repeating over again and other errors. Here is my functions that I use to track the fish:
Here is my functions inside the ENTER_FRAME Game Loop:
//Check if fish is null then run function
if (mainFish == null)
{
checkPlayerHitFish();
}else
{
trackFish();
}
and the functions:
private function checkPlayerHitFish():void
{
//loop through all our fishes
for (var j:int = 0; j < aFishArray.length; j++)
{
//get current fish in j loop
var currentFish:mcMainFish = aFishArray[j];
//test if current fish is hitting current playerhook
if (currentFish.hitTestObject(playerHook))
{
//trace("hit initialized");
mainFish = currentFish;
//Stop the fish from moving
currentFish.stopFish();
//fishing reel sound
fishingReelSoundChannel;
fishReelSound = new fishingReel();
fishingReelSoundChannel = fishReelSound.play(0, 9999);
fishingReelBoolean = true;
}
}
}
and the trackFish Function:
private function trackFish():void
{
mainFish.x = playerHook.x;
mainFish.y = playerHook.y + 15;
}
Can anyone see if I am doing anything wrong or how to go about fixing this issue?
The problem is that while you're only allowing one fish to be moved by the hook, you're still checking for hits for all the fish. This both stops them, and creates a new sound file.
The way to avoid this is to stop checking for fish collisions after a fish has already been hooked. To do this you can break out of the loop once you hook a fish:
private function checkPlayerHitFish():void
{
//loop through all our fishes
for (var j:int = 0; j < aFishArray.length; j++)
{
//get current fish in j loop
var currentFish:mcMainFish = aFishArray[j];
//test if current fish is hitting current playerhook
if (currentFish.hitTestObject(playerHook))
{
//trace("hit initialized");
mainFish = currentFish;
//Stop the fish from moving
currentFish.stopFish();
//fishing reel sound
fishingReelSoundChannel;
fishReelSound = new fishingReel();
fishingReelSoundChannel = fishReelSound.play(0, 9999);
fishingReelBoolean = true;
//break out of the loop
break;
}
}
}
Notice the break near the bottom. This will cause you to "break" out of the loop, preventing any further iterations. That way it will stop checking for collisions after the first successful hit test, and only react to one fish.
Hey guys so i am developing a Game and i have an Array that keeps track of my 5 movie clips that are added to the stage by the array. I have a Player movie clip as well so the Player movie clip is Hittesting with all the 5 diamond movie clips which are added to the stage like so:
private var nPoints:Number = 5;..........
public function addPointsToStage():void
{
for (var i = 0; i < nPoints; i++)
{
trace(aPointsArray.length);
points = new mcGainPoints();
stage.addChild(points);
points.x = startPoint.x + (xSpacing * i);
points.y = startPoint.y - (ySpacing * i);
aPointsArray.push(points);
}
}
Now when the Player comes in contact with all the 5 movie clips everything works fine and the output for the array looks like this:
0
1
2
3
4
Then it continues to the next level.
But say that my Player doesnt hit any of the 5 movie clips or only hits a couple of them, when the next level is started the output looks like this:
5
6
7
8
9
and when the next level is started weird things start happening like points start adding to the highscore by themselves.
I think the problem is that im not destroying the array holding the 5 movie clips correctly this is the code i use to start the next level and destroy the array:
if(player.hitTestObject(mcGoal_1))
{
//Remove all points from array/stage
for (var i:int = 0; i < aPointsArray.length; i++)
{
if (aPointsArray[i].parent)
{
parent.removeChild(aPointsArray[i]);
}
startNextLevel();
}
The mcGoal_1 is the object of the game so if the player hits the goal_1 then destroy all array objects on screen and start next level. This is the startnextlevel function.
private function startNextLevel():void
{
//add points to next stage
addPointsToStage();
}
So can you see why when the next level starts the array isnt reset back to 01234? I think thats why the game has that bug of randomly adding points. Please any help will be appreciated
//Remove all points from array/stage
for (var i:int = 0; i < aPointsArray.length; i++)
if (aPointsArray[i].parent)
parent.removeChild(aPointsArray[i]);
// just one statement, no braces
aPointsArray.length=0; // clear the array itself, not just
// points from display list!
startNextLevel(); // now start level
An incorrect order of correct statements leads to a disaster. Always check your code flow, what executes now and what then, and how many times.
It doesn't look like you're removing anything from the array.
You can use a combination of .indexOf() and .splice() to remove items from an array:
function removeMc(clip:MovieClip):void
{
if(clip.parent) clip.parent.removeChild(clip);
// Also remove from array.
var index:int = aPointsArray.indexOf(clip);
aPointsArray.splice(index, 1);
}
It might also be worth simply emptying the array when you startNextLevel():
private function startNextLevel():void
{
aPointsArray.length = 0;
//add points to next stage
addPointsToStage();
}
Just assign your array to null value. so that array will start from begining whenever you require. i hope the following code code would helps you.
var nPoints:Number = 5;
var points:poin;
var aPointsArray:Array;
var startPoint:Number = 0;
var xSpacing:Number = 20;
var ySpacing:Number = 20;
addPointsToStage();
function addPointsToStage():void
{
aPointsArray = null;
aPointsArray = new Array();
for (var i:int = 0; i < 6; i++)
{
trace(aPointsArray.length);
points = new poin();
addChild(points);
points.x = 100+ (xSpacing * i);
points.y = 200 - (ySpacing * i);
aPointsArray.push(points);
}
}
Hey guys having a little trouble this might be easier than i am making it out to be.
But the problem that i am having is when i hittest my mcPoints with my mcPlayer it is only interacting with 4 out of 5 of the movie clips that are added to the stage by a for loop.
I have been struggling with this for the past two days and cant seem to pin point the problem, everything seems set up perfectly but maybe you can help.
These are my Variables:
public var mcPoints:smallGainPoints;
private var nPoints:Number = 5;
private var aPointsArray:Array;
Here is how i set up the 5 mcPoints Movie Clips to be added to stage:
private function addPointsToStage():void
{
var startPoint:Point = new Point((stage.stageWidth / 2) - 100, stage.stageHeight / 2);
var spacing:Number = 50;
for (var i = 0; i < nPoints; i++)
{
trace(aPointsArray.length);
mcPoints = new smallGainPoints();
aPointsArray.push(mcPoints);
stage.addChild(mcPoints);
mcPoints.x = startPoint.x + (spacing * i);
mcPoints.y = startPoint.y;
}
}
So that adds the 5 points movie Clips to the stage which are aligned horizontally.
And finally here is the loop that listens for the HitTestObject to Initiate:
private function checkPlayerHitPoints():void
{
for (var i:int = 0; i < aPointsArray.length; i++)
{
//get current point in i loop
var currentPoints:smallGainPoints = aPointsArray[i];
//test if player is hitting current point
if(player.hitTestObject(currentPoints))
{
//Add points sound effects
var pointsSound:Sound = new pointsPickUpSound();
pointsSound.play();
//remove point on stage
currentPoints.destroyPoints()
//remove points from array
aPointsArray.splice(i, 1);
trace(aPointsArray.length);
//Add plus 5 text to current points position
mcPlus5 = new plusFiveText();
stage.addChild(mcPlus5);
mcPlus5.x = (currentPoints.x);
mcPlus5.y = (currentPoints.y);
//Update high score text
nScore += 5;
updateHighScore();
}
}
}
So i added traces both for when the movie clips are added and when they are hit here are the values i get:
0
1
2
3
4
Hit: 4
Hit: 3
Hit: 2
Hit: 1
Also i call the addPointsToStage(); in my constructor for more information.
So from the values im getting it seems that the last value "0" isn't being interacted with, any ideas why? Please anything would be of use. Thanks so much!
i'm not exactly sure what your code is suppose to be doing. But when you remove element from array in loop you are lose one item.
You array is
[1][2][3][4][5]
When i=1 you remove element and get
[1][3][4][5]
next interation i=2 which means you never test agains value 3.
You should decrement i whenever you remove element from an array.
As a followup to the question, How to get associated URLRequest from Event.COMPLETE fired by URLLoader, how can I make the function work for loader object in a loop?
Here is my existing (rough) code; I always get the mylabel from the last element of the array.
var _loader = new Loader();
for (j = 0; j < 5; j++) {
//mylabel variable is correct setup in the loop
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
doneLoad(e, mylabel);
});
_loader.load(new URLRequest(encodeURI(recAC[j].url)));
}//for loop
As per the comments above, this won't work because:
1) You're just adding the same event listener 5 times to the loader.
2) You're just reseting your same loader object 5 times.
The final output will just be as though you only called it the last time.
There are a variety of ways to address this - loading stuff asynchronously is one of the great mindfucks of learning to code - but the simplest way is probably just to create five separate loaders.
I'd do something like this:
var loaders:Array = [];
var labels:Array = ["label1", "label2", "label3", "label4", "label5"];
for (var j:int = 0; j < 5; j++) {
loaders[j] = new Loader();
loaders[j].contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loaders[j].load(new URLRequest(encodeURI(recAC[j].url)));
}
function completeHandler(e:Event):void {
doneLoad(e.currentTarget, labels[loaders.indexOf(e.currentTarget)]);
}
The confusing part is finding a good way to keep track of which load is associated with which label etc, since in theory your loads can finish in any order. That's why I've got a separate label array there, and then you just match up the desired label with the loader that just finished loading.
I hope that helps!
the line belove should work but it returns -1, always.
loaders.indexOf(e.currentTarget);
Here my code
for(i; i < total; i++){
imgLoaderArray[i] = new Loader();
imgLoaderArray[i].contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, urlError);
imgLoaderArray[i].contentLoaderInfo.addEventListener(Event.COMPLETE, loaded);
imgLoaderArray[i].load(new URLRequest(xmlList[i].image));
}
function loaded(e:Event):void{
trace("index: "+imgLoaderArray.indexOf(e.currentTarget)); // return -1 every time
}