can't get delete function to work properly AS3 - arrays

I have a Volcano class. It's purpose is to randomly spray lavaMass.
In the main class I have made it so that when my character hits the lava, everything is removed, and the deleteLava() function is called.
My problem is that with the deleteLava() function, my Volcano class stops making lava after a few 'deaths'.
Now i gets a little complicated to explain.
I found out that inside the deleteLava() function I should also remove the lavaMass from the array, for it to keep making lava no matter how many 'deaths'.
I used 'lavaSpray.shift();', and tried 'splice'..
And this worked! Except that it doesn't delete all the lavaMass, so everytime the character dies a few of the lavaMass objects keeps hanging around in the level, not moving. So after many 'deaths' there is a lot of lavaMass objects just standing still, not moving and not being deleted.
Here's the volcano class:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Volcano extends MovieClip {
var lavaSpray:Array = [];
var lavaNum:Number;
var world:World;
public function LavaThing() {
addEventListener(Event.ENTER_FRAME, makeLava)
}
public function deleteLava()
{
this.parent.removeChild(this)
for (var m = 0; m < lavaSpray.length; m++) {
if (lavaSpray[m].parent) {
lavaSpray[m].parent.removeChild(lavaSpray[m]);
}
}
}
function makeLava (e:Event)
{
lavaNum = Math.random()*70
if (lavaSpray.length<20)
{
if (lavaNum > 68.15)
{
var lavaMass = new LavaMass();
lavaSpray.push(lavaMass);
addChild(lavaMass);
lavaMass.scaleY = 0.5;
lavaMass.scaleX = 0.5;
lavaMass.x += 90;
lavaMass.y += Math.random()*30
lavaMass.y -= Math.random()*30
}
}
for each (lavaMass in lavaSpray)
{
lavaMass.x += 4;
if (lavaMass.parent && lavaMass.x > 800)
{
lavaMass.parent.removeChild(lavaMass);
lavaSpray.shift();
}
}
}
}
}
I hope someone knows what I'm talking about. Thanks in advance.
I put up a video with my problem:
https://www.youtube.com/watch?v=rYxYHB7rcgY&feature=youtu.be

I suspect the issues is:
you don't remove the ENTER_FRAME Event Listener when you delete the lava.
removing the child doesn't mean you deleted it's listener.
so you may remove all the lava , but still the ENTER_FRAME creates more !
you have to remove it your self.
so you have to add
removeEventListener(Event.ENTER_FRAME, makeLava)
as the first line at your function deleteLava()
....
or you may add
addEventListener(Event.REMOVED_FROM_STAGE, onRemoved)
and create onRemoved(e:Event){} function
then inside this function remove any listener you Added , including the ENTER_FRAME & the REMOVED_FROM_STAGE
try to read more about these subjects
Game Loop
entity system framework
Pool Object pattern
I may but links , but I prefer you Google them , and read from different resources - whatever the language they are explained with -
good luck

just for clarrifying your question.. You added the lavamass inside the volacano class? and you need to remove lavamass or volcano ? Dp you get any error during compilation? Also i encountered some thing like this when developing a shooting game, the removed bullets shows up after removing the bullerts. What i did was , i just added the bullets into a empty movieclip and removed the entire clip.

Related

Checking shot collisions and removing shot and target in AS3

Last year was my first successful year in teaching my students to create catch and avoid games in Flash with AS3. This year is getting better. Each year I come here for help at least once.
I'm trying to add shooting into the possibilities for their second game project. I can make the shot happen from the ship, gun, whatever, and make it move, and get rid of it when it is off screen, but have not figured out a clean way to have both the shot and the target go away (removeChild and array.splice) upon collision.
The code I have sort of works, but I keep getting the error,
TypeError: Error #1010: A term is undefined and has no properties. at
DropShootV02_fla::MainTimeline/checkShots()
.
Normally I know that this is because of a mismatch between objects and index numbers, but this is related to the call to a second array in removing boxes and bullets.
For simplicity I'll just include the shooting code. Similar organization creates and drops the boxes.
Any help is appreciated. BTW we are not using external script in an AS file.
var shotSpeed = 18;
var shots:Array = new Array();
import flash.events.MouseEvent;
import flash.events.Event;
stage.addEventListener(MouseEvent.CLICK, fireLaser);
function fireLaser(e:MouseEvent):void
{
if (gameOn==true)
{
var shot:Shot=new Shot();
addChild(shot);
shots.push(shot);
shot.gotoAndStop(1);
shot.x = user.x;
shot.y = user.y;
trace(shots.length);
}
}
addEventListener(Event.ENTER_FRAME, moveShot);
function moveShot(e:Event):void
{
for (var i:int=shots.length-1; i>=0; i--)
{
shots[i].y -= shotSpeed;
if (shots[i].y < -25)
{
removeChild(shots[i]);
shots.splice(i,1);
}
}
}
addEventListener(Event.ENTER_FRAME, checkShots);
function checkShots(e:Event):void
{
for (var i:int=shots.length-1; i>=0; i--)
{
for (var k:int=boxes.length-1; k>=0; k--)
{
if (shots[i].hitTestObject(boxes[k]))
{
if (boxes[i].type == "good")
{
score--;
scoreDisplay.text = "Score:" + score;
}
if (boxes[i].type == "bad")
{
score++;
}
removeChild(boxes[k]);
boxes.splice(k,1);
//if I leave this part out I get no errors,
//but but the bullet goes on to strike again
removeChild(shots[i]);
shots.splice(i,1);
}
}
}
}
Thanks kaarto:
I had tried that previously and kept getting the same error. I used that elsewhere in this game code. Turns out I needed to moderate how often the player was shooting. I changed from shooting with the mouse to using space instead and now the problem is gone. Break is definitely a good one here.
Merge move shot and checkShots in one ENTER_FRAME handler.

Cannot push past 1 element to basic AS3 Array

I am very new to this and hoping it's something that should have been obvious.
When I run the code below, the Array newHole and newArray both return 1 on the trace. Originally the code was built with only the newHole array, but I created the newArray in the hopes of troubleshooting. It did not help. The class for bulletHole contains no extra code so I didn't post that.
Thank you.
import flash.display.*;
import flash.events.*;
import flash.ui.Mouse;
Mouse.hide();
var myReticle:MovieClip;
var holeArray:Array = new Array();
var randomHole:Number = randomNumber(1, 5);
var newHole:bulletHole = new bulletHole();
var newArray:Array = new Array();
stage.addEventListener(MouseEvent.MOUSE_MOVE, followReticle);
stage.addEventListener(MouseEvent.CLICK, myFire);
stage.addEventListener(MouseEvent.CLICK, checkCount);
function followReticle(event:MouseEvent):void
{
myReticle.x = mouseX;
myReticle.y = mouseY;
}
function myFire(int):void
{
stage.addChild(newHole);
newHole.x = myReticle.x;
newHole.y = myReticle.y;
//holeArray.push(newHole);
newHole.gotoAndStop(randomHole);
//trace(holeArray.length);
}
function checkCount(int):void
{
newArray.push("A");
trace(newArray.length);
}
function randomNumber(low:Number=0, high:Number=1):Number
{
return Math.floor(Math.random() * (1+high-low)) + low;
}
Most likely the issue is that the code you've posted is running over and over again. In other words, you have a looping timeline that eventually goes back to the frame that the code you've shown is on.
Whenever that frame is reached, you have the following:
var holeArray:Array = new Array();
Which creates a new array replacing what used to be in that var.
To solve this, you either need to:
take the code out of the timeline (put it in a class file and attach that as the document class of your project)
re-architect your timeline so the first frame is only reached 1 time
put some checks in so that the code only runs the first time the frame is reached.
Here is an example of the latter option:
//just define the array, don't create it
var holeArray:Array;
//if the array is null, create it (it will only be null the first time this code is run
if(!holeArray){
holeArray = new Array();
}
This line is incorrect:
function myFire(int):void {
Because the function is triggered from a mouse event listener it should read:
function myFire(e:MouseEvent):void {
What you are doing is passing a undefined int to the function. Hope this helps.
EDIT: You should delete the clickCount event listener and function as they're not needed.
Also notice that you should move this line to the top of your myFire function or else you will keep replacing this MovieClip instead of creating it again:
var newHole:bulletHole = new bulletHole();

Instantiation attempted on a non-constructor

I'm trying to make a bomb catching game (I'm actually using the code from the AS3 Classroom in a Book on arrays). As soon as I changed the word fruit to bomb in the code I got error 1007. With the exception of changing basket_mc to eod_mc and fruit to bomb (I used command-F and replaced with case sensitive on) I haven't changed much. It worked with eod_mc, but doesn't with bomb.
var bombArray:Array = new Array(bomb);
var bombsOnstage:Array = new Array();
var bombsCollected:int = 0;
var bombsLost:int = 0;
for (var i:int = 0; i<20; i++) {
var pickBomb = bombArray[int(Math.random() * bombArray.length)];
var bomb:MovieClip = new pickBomb();
addChild(bomb);
bomb.x = Math.random() * stage.stageWidth-bomb.width;// bomb.width is subtracted from the random x position to elimate the slight possibility that a clip will be placed offstage on the right.
bomb.y = Math.random() * -500;
bomb.speed = Math.random() * 15 + 5;
bombsOnstage.push(bomb);
}
eod_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragEod);
stage.addEventListener(MouseEvent.MOUSE_UP, dragStop);
function dragEod(e:Event):void {
eod_mc.startDrag();
}
function dragStop(e:Event):void {
eod_mc.stopDrag();
}
stage.addEventListener(Event.ENTER_FRAME, catchBomb);
function catchBomb(e:Event):void {
for (var i:int = bombsOnstage.length-1; i > -1; i--) {
var currentBomb:MovieClip = bombsOnstage[i];
currentBomb.y += currentBomb.speed;
if (currentBomb.y > stage.stageHeight - currentBomb.height) {
currentBomb.y = 0 - currentBomb.height;
bombsLost++;
field2_txt.text = "Total Bombs Detonated: " + bombsLost;
}
if (currentBomb.hitTestObject(eod_mc)) {
bombsCollected++;
removeChild(currentBomb);
bombsOnstage.splice(i,1);
field1_txt.text = "Total Bombs Caught: " + bombsCollected;
if (bombsCollected >= 20) {
eod_mc.gotoAndStop(20);
} else if (bombsCollected > 15) {
eod_mc.gotoAndStop(15);
} else if (bombsCollected>10) {
eod_mc.gotoAndStop(10);
} else if (bombsCollected>5) {
eod_mc.gotoAndStop(5);
}
}
}
if (bombsOnstage.length <= 0) {
field1_txt.text = "You Win! You have defused the bombs.";
field2_txt.text = "";
stage.removeEventListener(Event.ENTER_FRAME, catchBomb);
}
if (bombsLost >= 20) {
field1_txt.text = "Sorry you lose. You have lost your foot!";
field2_txt.text = "";
stage.removeEventListener(Event.ENTER_FRAME, catchBomb);
for (var j:int = bombsOnstage.length-1; j > -1; j--) {
currentBomb = bombsOnstage[j];
removeChild(currentBomb);
bombsOnstage.splice(j,1);
}
}
}
Maybe to avoid making your programming life more twisted than it is now...
There are objects and classes in programming, a class is a description of a set of objects, say "table" (or, as it's better to differ in names for classes and variables, "Table", first letter capitalized) is a name of a class. An instance or an object is a structure that belongs to one or more classes, with Object being the topmost, as everything in programming is either an object or a "simple variable", that is, a number, a true/false, a string of characters (these are object types in AS3 too, though, Number, Boolean, String, but these generally not need to be instantiated via new) or probably some other simple type I don't remember right now.
Classes have properties and methods. A property is something that can be requested off any object of the class, say "height" for tables. Properties can be of any type, including nested objects, depending on what your base class is. Say stage in AS3 is a property of any DisplayObject which is used to get the only Stage object there is at runtime[1]. Methods are what any object of a class can be told to do. Say, bombs fall, explode, MovieClips can be told to stop(), etc. You write class code keeping in mind that all of the objects of this class will have to behave exactly like you've written, but since they can differ in properties, you can give them conditional behavior. For example, if a bomb has already exploded, it cannot blow up once more.
A variable, whether a property or a standalone var (if you declare one in a function) is a reference to an object of a given type. Say var i:int refers to some kind of an integer. Simple type vars are containers instead, that is, i=2; will place a 2 in the referred integer, and i=j; will copy the value from j into i, while var theStage:Stage=this.stage will instead create a reference to an existing object, and if that object will change, the reference will give you the changed object instead of its previous state. An array is a collection of variables, reachable by indexes, in AS3 they don't have to be of one type, and a Vector is a typed array.
Next, the lifetime of objects. An object only lives while there's an active reference to it, whether in a property of another alive object, or in a visible variable, or in an event listener (AS3 specific). An object is created via new ClassName(<parameters>), lives while you can reach it somehow, and is destroyed once you have no active links to it and Flash player decides to run garbage collector. Prior to this programmers had to deallocate objects themselves, a rudiment can be seen at BitmapData.dispose(). So, in order to avoid Flash player to run out of free memory, take full control over creation and destruction of links. You don't need to care for simple vars, they are being cared for by Flash player.
A lot of basic functions for interactions has already been implemented in AS3, look for them and examples of how they work in Adobe's manual, navigate through packages in the lower left, most of the interactive stuff is in flash.display package, refer to other packages as necessary.
Hope this will bring you some insight into programming basics.
[1]: There is one stage unless you're doing a load of an SWF, then there could be more, one Stage per one SWF.

AS3: Creating and accessing movieclips from an array

I know there are quite similar questions here, but I haven't found the proper details. What would be helpful is definitely an explanation of the problems, and perhaps a base example, that anyone who searches later may be able to apply. (Not asking that you write it for me, I just find the examples helpful) I don't want to upset anyone and am kind of worried to post in a forum...
I am wondering alternatives to creating a screen based off tiles created from an array. I have been having an issue myself trying to access the movieclips that have been placed on screen, and trying to trace to find a way to reference them hasn't been working.
Anyway, take something basic like an array, and connecting it to movieclips, then how to access the movieclip itself once done. So I have been working on this, and used many different online resources, so I'm sure a lot of this is going to look familiar, just in a much messier way.
This takes the array to make the movieclips appear (Im sure at least one part in here is unnecessary, and I'm thinking I'm doing something wrong here that makes it not work out later) So this works, but feels pretty bulky.
Both are from the same main class file.
function makeWorld (anyMap, tileW, tileH) {
var worldWidth = anyMap[0].length;
var worldHeight = anyMap.length;
var MAP = this.addChild(new mapHolder());
function tiler(MAP, i, j, tileW, tileH, tile)
{
MAP.addChild(tile);
tile.x = (j * tileW);
tile.y = (i * tileH);
}
for (var i = 0; i < worldWidth; ++i) {
for (var j = 0; j < worldHeight; ++j) {
var curTile:int = anyMap[i][j];
if (curTile == 101) {
var tile1 = new tileGround();
tiler (MAP, i, j, tileW, tileH, tile1);
...
else {
var tile3 = new empty();
tiler (MAP, i, j, tileW, tileH, tile3);
}
}}}
Then there is attempting to reference it, where I'm having the issue. I don't know what to call this.MAP.tileGround by, and I have tried many things. I've read it's not such a good idea to reference by name when not very advanced so I wanted to avoid that sort of thing too.
addEventListener (Event.ENTER_FRAME, hits);
function hits (event:Event) {
var tileCatchG:MovieClip = this.MAP.tileGround;
if(tileCatchG.hitTestPoint(this.MAP.Char.x + leftBumpPoint.x, this.MAP.Char.y + leftBumpPoint.y, true)){
leftBumping = true;
} else {
leftBumping = false;
}
...
}
Thank you!
In looking over what you're doing a second time it would appear that you should have a reference to the 2-indexed array that represents the map.
You can create a regular (single indexed) Array at the top of the file like
public var tileArray:Array = [];
Then where you create them push them into the array
var tile1 = new tileGround();
tileArray.push(tile1);
then to reference them all you can just run a simple loop
for each(var tile:MovieClip in tileArray)
{
//Do stuff
if(tile instanceof tileGround)
{
//Do stuff specific to tileGround
}
}

Flash Resetting array values

I was working on a test project that I will later incorporate into a much larger work that is a simple quiz game. I made an array with my questions:
var questions1:Array=["nitrogen dioxide","sulfur hexafluoride",..."]
and in a second layer I made a button that cycles through the questions randomly.
import flash.events.MouseEvent;
var qno=0;var rnd1;
function change_question(){
rnd1=Math.ceil(Math.random()*questions1.length)-1;
q.text=questions1[rnd1];
if(questions1[rnd1]=="X"){change_question();}
questions1[rnd1]="X";
}
change_question();
next_b.addEventListener(MouseEvent.CLICK, ButtonAction1);
function ButtonAction1(eventObject:MouseEvent){
qno++;change_question();
}
This part works great, because I was following a tutorial. Text appears in a dynamic text box I created as it should. This tutorial taught to change the value of the array to X with every choice and to ignore choose a different question every time it encountered an X
After it cycles through all the questions I basically get an infinite loop in my output section of flash because it can't find any more non-X values. I was hoping someone had information on how to press a button an change the array back to its default settings so that a teacher (because that is who it is for) has a way of resetting the file when they have reached the end of the quiz.
Thanks everyone!
As per my understanding you wanted to randomize your questions and after showing all the entire questions you wanted to reset your questions.
As per your code you get a random question and updating the same array by pushing value 'X'. Rather than doing this what you need to do is to preserve the array only randomize its position. So that you can use the same value once you cover your all questions
I have added code here.
import flash.events.MouseEvent;
var qno=0;var rnd1;
var questions1:Array=["nitrogen dioxide","sulfur hexafluoride","carbon dioxide","carbon monooxide"];
var nAttmeptedCount = 0;
var shuffledLetters:Array;
function change_question()
{
if(qno == questions1.length)
{
qno = 0;
resetQuestion()
}
else
{
q.text = questions1[shuffledLetters[qno]];
qno++;
}
}
function resetQuestion()
{
shuffledLetters = new Array(questions1.length);
for(var i=0;i<shuffledLetters.length;i++)
{
shuffledLetters[i] = i;
}
shuffledLetters.sort(randomize);
}
function randomize ( a : *, b : * ) : int {
return ( Math.random() > .5 ) ? 1 : -1;
}
resetQuestion()
change_question();
next_b.addEventListener(MouseEvent.CLICK, ButtonAction1);
function ButtonAction1(eventObject:MouseEvent){
change_question();
}
In above solution after showing all questions I have reset the questions automatically. you can modify code as per your requirement. If you want to do the reset questions you can put you code qno = 0;resetQuestion() on button click.
hope above solution work for you.

Resources