Best way to end a function that contains an array in AS3 - arrays

So I'm real new to AS3 and I'm trying to figure out a solution to end a function I created for a matching game. I want to have the function end when all the cards are used up in the array. What is the easiest way to go about this?
private var games:Object = {
easy:{
tiledeck:[1,1,2,2]
,xOffset:450
,yOffset:320
,incrementX:200
,incrementY:200
,columns:2
,rows:2
}
,hard:{
tiledeck:[1,1,2,2,3,3,4,4]
,xOffset:235
,yOffset:320
,incrementX:200
,incrementY:200
,columns:4
,rows:2
}
};
public function KT(game:String){
buttonMode = true
var gameConfig = games[game];
var tiledeck:Array = gameConfig.tiledeck.concat();
for (var x=1; x<=gameConfig.columns; x++){
for (var y=1; y<=gameConfig.rows; y++){
var random_card = Math.floor(Math.random() * tiledeck.length);
var tile:animalTile = new animalTile();
tile.animal = tiledeck[random_card];
tiledeck.splice(random_card,1);
tile.gotoAndStop(5);
tile.x = (x - 1) * gameConfig.incrementX + gameConfig.xOffset;
tile.y = (y - 1) * gameConfig.incrementY + gameConfig.yOffset;
tile.addEventListener(MouseEvent.CLICK,tile_clicked);
addChild(tile);
}
}
}

Your problem is not what you think it is.
The array is properly discarded from memory.
However, you used addChild(tile). This means you'll also have to removeChild(tile). Personally, I recommend adding a DisplayObjectContainer that you add the cards to. Kinda like a plastic sheet to put the cards on. Then, when the user presses the back button, you remove the plastic sheet... and all the cards come with it.
You haven't provided the code for the back button though, so I can't help you with integrating this functionality. My advice: Make some sort of game object responsible for cleanup, so all the button has to do is game.exitGame(); and then whatever code you use to go back right now.

Related

Trying to hide an object in an array when it is clicked, works without an array but not with? Actionscript 3.0

I am making a little game and I have an array. The array contains 4 characters. When one of the characters is clicked the opacity should turn to 0, if another is clicked the same should also happen.
So far I have put the array into a function but the function will only hide one of the characters, and not even the one which is clicked. Could anyone help me please? Here is the code I have:
for(var g:int = 0; g<ghostsL.length; g++){
ghostsL[g].addEventListener(MouseEvent.CLICK, clickGrey)
};
function clickGrey(e:MouseEvent):void{
this.ghostsL[i].alpha = 0;
var npoint:NPoint = new NPoint();
npoint.play();
};
We do not know what this.ghostsL[i] is.
Why don't you just do it this way:
function clickGrey(e:MouseEvent):void{
MovieClip(e.currentTarget).alpha = 0;
var npoint:NPoint = new NPoint();
npoint.play();
};

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
}
}

Actionscript 3.0 Get all instances of a class?

I got a ton of movieclips in a class. Is there a more efficient way to apply a function to every instance in the class other than this?
var textArray:Array = [
interludes.interludeIntro.interludeBegin1,
interludes.interludeIntro.interludeBegin2,
interludes.interludeIntro.interludeBegin3,
interludes.interludeIntro.interludeBegin4,
interludes.interludeIntro.interludeBegin5,
interludes.interludeIntro.interludeBegin6,
interludes.interludeIntro.interludeBegin7,
//... ... ...
interludes.interludeIntro.interludeBegin15
];
for each (var interludeText:MovieClip in interludeBeginText)
{
interludeText.alpha = 0 //clear all text first
}
Also for some reason this doesn't work:
interludes.interludeIntro.alpha = 0;
It permanently turns that class invisible, even if I try to make specific instances visible later with:
interludes.interludeIntro.interludeBegin1.alpha = 1;
I have NO idea why the above doesn't work. I want to turn every single instance in the class interludeIntro invisible, but I want to turn specific instances visible later.
(btw I have no idea how to insert code on this website, pressing "code" doesn't do anything, so pardon the bad formatting)
I'm not really sure what you're asking, but what may be useful is that, in ActionScript you can refer to properties by name, like myObject["someProperty"].
Using that, you can iterate over properties if they follow some naming scheme, so for example:
for (var i:int = 1; i <= 15; i ++)
interludes.interludeIntro["interludeBegin" + i].alpha = 0;
That iterates over interludes.interludeIntro.interludeBegin1 through ...15 and sets their alpha properties to 0.
When you do that:
interludes.interludeIntro.alpha = 0;
you turn the movie clip and all its children invisible.
So later when you do that:
interludes.interludeIntro.interludeBegin1.alpha = 1;
You make the movie clip visible, but since its parent is still invisible, you don't see anything. The solution is to loop through the movie clips and make each of them invisible/visible.
// Keep the parent visible at all time
interludes.interludeIntro.alpha = 1;
for (var i:int = 0; i < textArray.length; i++) {
textArray[i].alpha = 0;
}
// Now this will work:
interludes.interludeIntro.interludeBegin1.alpha = 1;

Moving objects in array

I have an array which is filled with platforms that are supposed to move.
var MovingPlatformArray:Array = new Array();
for (var c:int = numChildren - 1; c >= 0; c--){
var child3:DisplayObject = getChildAt(c);
if (child3.name == "movingplatform"){
MovingPlatformArray.push(child3);
}
}
this.addEventListener(Event.ENTER_FRAME,ctrl_birdie);
function ctrl_birdie(e:Event):void{
for(var c in MovingPlatformArray){
MovingPlatform[c].y += speed;
if(MovingPlatformArray[c].hitTestPoint(birdie.x,birdie.y,true)){
birdtelleryvertrager=0;
birdtellery = 0;
birdie.y-=14;
}
if(movingplatform.y <= 25){
speed = 2;
}
if(movingplatform.y >= 350){
speed = -2;
}
}
Right now I have 2 moving platforms in this array. But only one moves up and down. But they both register a touch with the birdie. Am I doing something wrong?
In your listener, you're only setting the position of one platform, which ever one "movingplatform" is a reference to. As all your stage instances of moving platforms are named "movingplatform", one lucky platform is getting referenced by name (the rest ignored), instead of what you intended, which is to use the references in your array and adjust each platform.
You probably meant for movingplatform to be a local variable in your event handler, declared something like this:
var movingplatform:DisplayObject = MovingPlatformArray[c] as DisplayObject;
I'd recommend using a for each loop in place of the for in, because I think it's a little cleaner, but this is a minor style thing:
for each (var platform:DisplayObject in MovingPlatformArray)
{
platform.y += speed;
... rest of your code ...
}
For the sake of clarity, I edited the loop variable to be platform instead of movingplatform, to avoid confusion of having a local variable shadow a stage instance (i.e. this.movingplatform). I wanted it to be clear that the stage instance name is not being used here, because the unintentional instance name reference in your code is the source of your problem in the first place.
As far as i'm concerned, you have two options. use a for each, as adam smith suggested or use a for-loop as it was intended to be used :)
for(var c:uint = 0; c < MovingPlatformArray.length; c++){...
and btw: should "MovingPlatform[c].y += speed;" not be "MovingPlatformArray[c].y += speed;"?
edit: looking at your code, i would also suggest you use MovingPlatformArray[c].hitTestObject(birdie) instead of MovingPlatformArray[c].hitTestPoint(birdie.x,birdie.y,true)
If I were you, I would bring the logic for the platform out, and store it in a class. (Ideally you would do this for the birdie object as well). I have created an example below. The movieclips on the stage should extend Platform rather than MovieClip so they invoke the methods at the bottom.
// Use vectors if you know all the items are going to be the same type
var platforms:Vector.<Platform> = new <Platform>[];
for (var c:int = numChildren - 1; c >= 0; c--){
var child:DisplayObject = getChildAt(c);
// You shouldn't check against names (as per the original post). Because
// names should be unique
if (child is Platform){
platforms.push(child);
// This could be random so each platform has a different range
// This means platform 1 could go from y 30 to y 400, platform 2
// could go from y 60 to y 200, etc
child.setRange(25, 400);
}
}
this.addEventListener(Event.ENTER_FRAME, gameLoop);
// Have an overall game loop
function gameLoop(e:Event):void {
// Loop over the platforms
platforms.forEach(function(item:Platform, i:int, a:Vector.<Platform>):void {
// Hit test function in the class means you only have to pass in one mc
// rather than the points and a boolean
if(item.hitTest(birdie)) {
birdtelleryvertrager=0;
birdtellery = 0;
birdie.y-=14;
}
// Removed the movement logic, this should be kept out of the game loop
// plus how much better does this read?
item.move();
});
}
Then in a class location somewhere, like in a folder game/activeObjects
// A class for the platform stored else where
package game.activeObjects
{
import flash.display.MovieClip;
/**
*
*/
public class Platform extends MovieClip {
private const SPEED:Number = 2;
private var _direction:int = 1;
private var _minimumHeight:Number = 25;
private var _maximumHeight:Number = 350;
public function Platform() {
}
public function setRange(minimumHeight:Number, maximumHeight:Number) {
_minimumHeight = minimumHeight;
_maximumHeight = maximumHeight;
}
public function move():void {
this.y += SPEED * _direction;
if(this.y <= _minimumHeight) {
_direction = 1;
} else if(this.y >= _maximumHeight) {
_direction = -1;
}
}
public function hitTest(mc:MovieClip):Boolean {
return hitTestPoint(mc.x,mc.y,true);
}
}
}

multiple instances of the same object spaced out using a loop is only creating one

I had a hard time trying to word my question properly, so i'm sorry if it seems confusing. Also i'm using the flixel library in flash builder. It may not be that important butcause probably anyone that knows a little more than me or even a little AS3 could probably see what i'm doing wrong.
Anyway, what i'm trying to do is basically create 10 instances of this square object I made. all I have to do is pass it an x an y coordinate to place it and it works. so ive tested if i just do:
var testsquare:Bgsq;
testsquare = new Bgsq(0,0);
add(testsquare);
it works fine and adds a square at 0,0 just like i told it to, but i want to add 10 of them then move the next one that's created 25 px to the right (because each square is 25px)
my problem is that I only ever see 1 square, like it's only making 1 instance of it still.
anyone possibly have an idea what I could be doing wrong?
var counter:int = 0;
var bgsqa:Array = new Array;
for (var ibgs:int = 0; ibgs < 10; ibgs++)
{
bgsqa[counter] = new Bgsq(0,0);
bgsqa[counter].x += 25;
add(bgsqa[counter]);
counter++;
}
There's a lot you're doing wrong here.
First off, you're using a pseudo-iterator (counter) to access array elements through a loop instead of, well, using the iterator (ibgs).
Second, I don't see anything in the array (bgsqa) you're iterating through. It's no wonder you're having problems. Here's what you should do.
var bgsqa:Array = [];
for(var i:int=0;i<10;i++)
{
var bgsq:Bgsq = new Bgsq(i * 25, 0);
add(bgsq);
bgsqa.push(bgsq);
}
That should probably do it if your post is accurate.
for (var ibgs:int = 0; ibgs < 10; ibgs++)
{
bgsqa[counter] = new Bgsq(0,0);
bgsqa[counter].x = counter * 25;
add(bgsqa[counter]);
counter++;
}
They start at 0, so applying += is simply adding 25 to 0. This should do the trick.

Resources