A3 Arrays of movieClips - arrays

[AS3.0] I'm currently working on my graduation diploma and I have a problem with managing movieClips with the same instance name..sort of. I'm creating an array of objects with this Class an Arrays in frame 1:
package
{
import flash.display.MovieClip;
public class createFractionBuilding
{
public function createFractionBuilding(_fractionBuildingMovieClip:MovieClip, _fractionBuildingLevel:Number,_fractionBuildingCost:Number, _fractionBuildingFrame:Number)
{
fractionBuildingLevel = _fractionBuildingLevel;
fractionBuildingCost = _fractionBuildingCost;
fractionBuildingMovieClip = _fractionBuildingMovieClip
fractionBuildingFrame = -fractionBuildingFrame
}
public var fractionBuildingLevel:Number,fractionBuildingCost:Number,fractionBuildingFrame:Number;
public var fractionBuildingMovieClip:MovieClip
}
}
On main timeline I'm refering to this Class by creating an Array of objects:
var allHumanBuildingsList:Array = new Array();
var humanCapitolBuildingProperties:createFractionBuilding = new createFractionBuilding(humanCapitol_mc,1,1000,1);
var humanCastleBuildingProperties:createFractionBuilding = new createFractionBuilding(humanCastle_mc,2,1000,1);
allHumanBuildingsList.push(humanCapitolBuildingProperties);
allHumanBuildingsList.push(humanCastleBuildingProperties);
For this to work I have to have movieclip called "humanCapitol_mc" or "humanCastle_mc" in this frame (1).
But in frame (2) I want to refer to this movieClip with such function:
function humanBuildingLevelCheck()
{
for (var a:Number = 0; a < allHumanBuildingsList.length; a++)
{
trace (String(allHumanBuildingsList[a].fractionBuildingMovieClip))
if (allHumanBuildingsList[a].fractionBuildingLevel == 2){
allHumanBuildingsList[a].fractionBuildingMovieClip.gotoAndStop(3)
} else if (allHumanBuildingsList[a].fractionBuildingLevel == 1){
allHumanBuildingsList[a].fractionBuildingMovieClip.gotoAndStop(2)
}
}
}
humanBuildingLevelCheck()
(Each MovieClip on first frame is blank, on second is one picture, on third is different one)
Everything works, when the array creation code is in frame two, but it won't work the way I want: first I create variables and objects and then I change it's values dynamically. Do you have an idea, how could that work?

Make it global. If one variable is declared in keyframe 1, you can't see it in keyframe 2 but if you declare it in one layer that has only one keyframe then it will be visible anywhere within that timeline.

Related

Use value from array to set addeventListner to multiple buttons

I'm making a game that have multiple instance of a MC in stage (a1,b1,c1....a2,b2,c2,d2,etc)
Every time to make a listener i have to write
Object(this).sopa.c1.btn.addEventListener(MouseEvent.CLICK, c1Click);
and create a function like this
function c1Click(event:MouseEvent):void
{
checkString += "c1";
var TFc1:TextFormat = Object(this).sopa.c1.letra.getTextFormat(0,1);
TFc1.color = 0xff0022;
Object(this).sopa.c1.letra.setTextFormat(TFc1);
check();
}
but whit that many buttons (more than 100) is to long writing them one by one.
So i think put the values (instance names) of the buttons in an array. Something like this
var casillas:Array = [a1, b1,c1];
for (var i:uint = 0; i < casillas.length; i++)
{
casillas[i].addEventListener(MouseEvent.CLICK, a1presion);
trace(casillas[i])
}
but i cant get the value of the array element just a [object SimpleButton].Have anyone any ideas how to do this: I'm new in as3 i worked all my life in as2 and this is way to hard to understand for me.
This is where Object Oriented Programming shines. You encapsulate all properties and methods into a single object. You can then create as many of these objects, and watch as they function individually with the behavior specified inside.
Here's a simple button class I sometimes use myself:
package buttons {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class SimpleButton extends MovieClip {
public function SimpleButton() {
addEventListener(MouseEvent.MOUSE_OVER, mOver);
addEventListener(MouseEvent.MOUSE_OUT, mOut);
addEventListener(MouseEvent.MOUSE_DOWN, mDown);
buttonMode = true;
}
protected function mOver(e:MouseEvent):void {
gotoAndStop(2);
}
protected function mOut(e:MouseEvent):void {
gotoAndStop(1);
}
protected function mDown(e:MouseEvent):void {}
}
}
Then create as many instances as you like, and store them in some container so that you can get rid of them at some point in the destruction of the program.
var buttons:Vector.<SimpleButton> = new Vector.<SimpleButton>();
buttons.push(new SimpleButton());
buttons.push(new SimpleButton());
buttons.push(new SimpleButton());
Firstly, I have to agree with Iggy, what you are trying to do will ultimately be more re-usable and easy to understand if it were written using Object Oriented code.
However, from what you have already written, I think you are saying is that you are struggling to create an event handler that is generic to all your buttons? So if you need to get the string name of the MovieClip as well as the actual clip reference maybe you could do something like this:
var casillas:Array = ["a1", "b1", "c1"]; //Have an array of the names of the buttons
for (var i:uint = 0; i < casillas.length; i++)
{
var mcReference:MovieClip = this.sopa[ casillasNames[i] ]; //Use the string reference to get hold of the button
mcReference.btn.addEventListener(MouseEvent.CLICK, _handleButtonClick); //Add a listener to the same "btn" child of the casilla as you did before.
}
you need a listener
function _handleButtonClick(e:Event)
{
var buttonReference:* = e.target;
So e.target in this instance should be the same object that you added to the array earlier (a1 or b1 or c1 depending on which one is clicked)
Now I'm going to make some leaps about how those MovieClips (a1,b1,c1) are structured (I'm guessing they are all the same just with different data in?)
function _handleButtonClick(event:MouseEvent):void
{
var clickedButtonReference:* = e.target;
for(var i:int = 0; i< casillas.length; i++)
{
if(this.sopa[ casillasNames[i] ].btn == clickedButtonReference) //Check each button on the stage to see if it is the one that has been clicked.
{
checkString += casillasNames[i];
//To find this bit "this.sopa.c1.letra" there are two options either
var selectedLetra = this.sopa[ casillasNames[i] ].letra; //Using the string name of the MC to find it.
//or
var selectedLetra = clickedButtonReference.parent.letra; //Or using the fact that we know that the original MC contains both the btn and the letra as children.
//Once we have it though the rest of your function should work ok.
var TFc1:TextFormat= selectedLetra.getTextFormat(0,1)
TFc1.color = 0xff0022;
selectedLetra.setTextFormat(TFc1);
check();
//Just add a break to stop searching for the button since we have found it.
break;
}
}
}

Giving each object that share the same class, their own individual variables that won't affect the other variables

Good Evening/ Morning.
This is a games related question.
I am facing an issue where I have three objects, (three goblins) data typed to the same class.
These three objects are in an array and data typed to that class, and initialized as the array.
private var goblin1:Goblin = new Goblin();
private var goblin2:Goblin = new Goblin();
private var goblin3:Goblin = new Goblin();
So the variables above have been then placed into an array.
private var aGoblinArray = new Array(container.goblin1, container.goblin2, container.goblin3);
After placing the objects into an array I have looped through all of my goblins.
for (var i:int = 0; i < aGoblinArray.length; i++)
{
var goblin:Goblin = aGoblinArray[i];
}
now I have a hitTest in the for loop and the hitTest is:
if (goblin.hitTestPoint(_character.x + 100, _character.y - 45, true))
{
goblinCanMove = false;
trace("lance hits");
//hitOnce
if (!hitOnce)
{
hitOnce = true;
trace("take on damage");
}
goblin.moveBack();
goblin.minusHealth();
}
This means if this player hits any of the goblins, they will do this function.
How ever in the goblin class.
public static var goblinLife; int;
goblinLife = 2;//put in main constructor
public function minusHealth():void
{
goblinLife --;
checkDeath();
}
private function checkDeath():void
{
if (goblinLife == 0)
{
parent.removeChild(this);
}
}
the problem is, if I hit goblin1, then goblinLife would = 1. This means all othet goblins(goblin2 and 3) will have 1 life. Since they share the same class.
if goblin1 dies, he is removed and the var goblinLife would = 0;
Now I can reset it back to 2, but this will fix half of the problem.
My question is, is there a way on how I can make sure each goblin has it's own individual life system. Thank you in advance.
Thank you very much Pan and Marty!
Static meant that it could be changed from any class and any function.
Private means that it will be protected to each individual goblin.
From changing
public static var goblinLife; int;
to
private var goblinLife; int;
it means that each individual goblin will have their own variable, that no other class or object of the same class can change.
Thank you Pan and Martyn. I guess I need to read AS3 101: Quick Tip – When to Use Static Properties and Methods and other coding books!

Actionscript 3 eventlisteners, hittestobject and arrays of custom objects

Another desperately stuck first year student here. And I have to use FlashCS as my coding environment. And it sucks. So I'll try some well constructed and clear questions. There is:
public var object: symbol1;
public var objectarray: Array = new Array();
in my main. Then a function there that uses a timer and spawns a new object and pushes it onto the array:
object = new symbol1;
objectarray.push(object)
but then when I trace() the .length of the array it displays TWO numbers of the array length every timer period in the output. As in:
1 1 2 2 3 3
etc. This is my first mystery. Why two not one? because there is no way I'm calling the function that includes the trace () twice. Also I think I need to be able to remove my object from the objectarray when it goes off the stage, but the objectarray.pop() doesn't seem to work if I use it like so in a function:
if (object.y == stage.stageHeight)
objectarray.pop()
As in I try trace() the array.length before and after the .pop(), but it just keeps going up by one every timer period.
And the other, bigger issue is I want to know if you are allowed to put the .addEventListeners that you usually place right under the main function of any class into a statement loop. As in I've got
class extends Main {
class function() {
for (var i:Number = 0; i < objectarray.length; i++){
objectarray[i].addEventListener(Event.ENTER_FRAME, collision);}}
And then, if it is allowed, the program doesn't seem to enter the collision function of this same class anyway.
function collision (event:Event) : void{
if (this.hitTestObject(object)){
trace('hit');}}
so I searched and ended up adding a
var clip:MovieClip = MovieClip(e.target);
in the first line of the function, but then it didn't work and I realized I on't understand what's it meant to do, what's going on anymore and what is the syntax for this casting.
Thank you very much.
Edit/Update: adding more of my code eventhough I hate copypasting it like this. This is the symbol class that is going to change when an object of another class hits it
public class Head extends Main {
public function Head(){
this.stop();
for (var i:Number = 0; i < nicesnowflakearray.length; i++){
nicesnowflakearray[i].addEventListener(Event.ENTER_FRAME, snowhit);
}
}
public function snowhit(event:Event) : void {
if (this.hitTestObject(nicesnowflake)){
//I changed this line to (e.currentTarget.hitTestObject(nicesnowflake)) as Atriace suggested, but nothing changed, and I just don't understand why my version wouldn't work.
trace("hit");
}
}
And this is the class that spawns the objects that are supposed to hit the Head object:
public class Main extends MovieClip {
public var nicesnowflake: fallingsnow;
var nicesnowflakespawntimer: Timer = new Timer(1000);
public var nicesnowflakearray: Array = new Array();
public function Main() {
nicesnowflakespawntimer.addEventListener(TimerEvent.TIMER, nicesnowflakespawn);
nicesnowflakespawntimer.start();
}
public function nicesnowflakespawn(event:TimerEvent) : void {
nicesnowflake = new fallingsnow;
nicesnowflake.x = Math.random()* stage.stageWidth;
nicesnowflake.y = - stage.stageHeight + 100;
nicesnowflakearray.push(nicesnowflake);
stage.addChild(nicesnowflake);
trace(nicesnowflakearray.length);
}
Why two, not one?
Anytime you extend another class, it implicitly calls the parent class' constructor. We know this as super(), and can be quite handy. This is why you're getting doubles on your trace statement. Technically, you can choose not to call super().
.pop()
It should remove the last element from that array, however, I'm thinking that if an arbitrary object leaves the stage, you can't be gauranteed it'll be the last element. Ergo, you want splice()
if (object.y == stage.stageHeight) {
objectarray.splice(objectarray.indexOf(object), 1)
}
Event Listeners
I didn't follow your quandary, so I'll just try to rewrite what I think you were trying to do.
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
private var objectarray:Array = []; // Note, I haven't populated it with anything, I'm assuming you have.
private var theWall:MovieClip = new MovieClip(); // I haven't added this to the stage, or given it shape. You need to for hitTestObject to work.
public function Main() {
// This is your constructor.
for (var i:Number = 0; i < objectarray.length; i++) {
objectarray[i].addEventListener(Event.ENTER_FRAME, collision);
}
}
private function collision(e:Event):void {
if (e.currentTarget.hitTestObject(theWall)) {
trace('hit');
}
}
}
}
Of note, you may want to look at a guide to hitTestObject() if it's giving you issues.

AS3 using an array in 2 different classes

for my school I have to create a small flash game.
I'm trying to create a sidescrolling flying game where you can also drop bombs.
The thing I'm not sure about is my bombs array I created this array in my plane class where the bomb movieclip is added to the array but I want to remove the bomb after it collided with an object in the bomb class but I'm not quite sure how to go about this the pushing of the bombs into the array goes fine. so this is what I have so far with regards to the array
for the variables:
public var bomb:MovieClip;
public var bombs:Array;
In the main function
public function McPlane() {
bombs = new Array();
In my update function
if(Input.bomb){
if(bombs.length <=1){
var bomb = new Bomb();
stage.addChild(bomb);
bomb.x = this.x + 30;
bomb.y = this.y + 16;
bombs.push(bomb);
so far this all works,
my question is can I use the same array in my bomb class where I want to... pop the array when it collides with other objects? and if so how do I go about it ?
You could remove the bomb from bombs in plane class.Add an event listener for bomb when it created in plane class and the bomb will dispatch the target event when it collides.
var bomb = new Bomb();
stage.addChild(bomb);
bomb.addEventListener("bombCollides", onBombCollideHandler);
private function onBombCollideHandler(e:Event):void {
var bomb:Bomb = e.target as Bomb;
if (bomb) {
var index:int = this.bombs.indexOf(bomb);
//if find the target bomb, remove it
if (index != -1) {
bombs.splice(index, 1);
}
}
}
In Bomb class
public class Bomb {
private function collide():void {
//do some check if collide
this.dispatchEvent("bombCollides");
}

having issues working with movie clips inside of an array [as3]

In a game I'm making, I'm trying to have sprites put on top of a hit box. The best way I could think of accomplishing this is to make two arrays; one for the hit boxes, and one for the sprites, and then have the sprites stay on top of their respective hit-box via a for loop that will be in its own script.
Problem is, is that when I try to get the MovieClips in either of the arrays to do anything, it doesn't work. If I do a trace on the X or Y location of the sprites, I get "undefined" in my terminal. I'm going to explain this from the top down.
Here is an excerpt from my class that contains the for loop (Dasengine is my main class fyi)
for(var i:Number = 0; i < Dasengine.ovrcnt.length; i++){
trace(Dasengine.ovrcnt[i].x); //returns "undefined"
trace(Dasengine.ovrcnt[i]); //returns "object Onmea"
Dasengine.ovrcnt[i].x = Dasengine.enemycnt[i].x;//this isn't working
}
In another script when an enemy spawns, they go through this method.
if(ENEMY SPAWN CONDITION IS MET ){
Dasengine.baddie = new nme_spawn.Enemya(); //ENEMY HITBOX
Dasengine.Obaddie = new nme_overlay.Onmea(); //ENEMY's sprite
Dasengine.enemycnt[cntup] = [Dasengine.baddie]; //Enemy's Hit box movie clip is put in array meant for holding enemy movie clips
Dasengine.ovrcnt[cntup] = [Dasengine.Obaddie]; //Enemy sprites that go over the hit boxes are stored here
cntup++; //this is so movie clips are put in new parts of the array
}
in my main class, the movie clips are declared as follows also I have the addChild functionality in there.
public static var Obaddie:nme_overlay.Onmea;
//^variable for sprite
public static var baddie:nme_spawn.Enemya;
//^variable for hitbox
also Obaddie= Overlay baddie. Its the MovieClip that acts as what goes on top of the hitbox, this is what the player will see
badde = is simply the hitbox. This contains the "meat" of the enemy ai.
I talked about this with some friends and they thought I might need to define what 'X' is inside of the class of the object that is in the array. So I did the following
package nme_overlay {
import flash.display.*;
import flash.events.*;
import nme_spawn.*;
public class Onmea extends MovieClip{
// Constants:
// Public Properties:
// Private Properties:
public static var xloc:int = 0;
// Initialization:
public function Onmea() {
this.addEventListener(Event.ENTER_FRAME, overlaya);
}
private function overlaya(e:Event){
xloc = 55;
//trace(xloc);
}
}
}
and then for the looping class I did this
for(var i:Number = 0; i < Dasengine.enemycnt.length; i++){
trace(Dasengine.ovrcnt[i]);//returns "object Onmea"
trace(Dasengine.ovrcnt[i].xloc);//still returns "undefined"
}
Your xloc variable is static--it belongs to nme_overlay, the Class, not any particular instance. If you were to do this in your code AND you had strict mode on (which I suspect you do not, because there's a lot of stuff in your code that should be giving you at least warnings), you'd get an error that would tell you exactly that:
for(var i:Number = 0; i < Dasengine.enemycnt.length; i++){
trace(Dasengine.ovrcnt[i]);//returns "object Onmea"
trace(nme_overlay(Dasengine.ovrcnt[i]).xloc);//still returns "undefined"
}

Resources