As3 calling array outside of function - arrays

I am kind of new to AS3 and programming itself.
I have this issue. I want to be able to use the Pl_array and En_array outside of AfterLoad function, but I always get undefined value. I am writing the code inside the timeline not .as file. Does it matter?
I was trying to return them from function but since it's related to listener i just dont know how to do it also i was trying to make them public.
Here is code on first frame:
import flash.events.MouseEvent;
stop();
Btn_start.addEventListener(MouseEvent.CLICK, onStartClick);
function onStartClick(me:MouseEvent):void{
gotoAndStop("Dictionary");
}
and here is on the second called Dictionary:
import flash.events.Event;
import flash.utils.Timer;
import flash.events.MouseEvent;
stop();
var myTextLoader:URLLoader = new URLLoader();
var Txt_array:Array=new Array(); //tablica wczytanych zwrotów
var Pl_array:Array=new Array();
var En_array:Array=new Array();
var myTimer:Timer = new Timer(1000);
myTextLoader.addEventListener(Event.COMPLETE, onLoaded); //listener na koniec wczytywania pliku tekstowego
function onLoaded(e:Event):void { //funkcja wywoływana przez listener na koniec wczytywania pliku
Txt_array = e.target.data.split(/\n/); //
dispatchEvent(new Event("Load_END"));
}
myTextLoader.load(new URLRequest("Zwroty.txt"));
this.addEventListener("Load_END", AfterLoad); //kod wykonywano po wczytaniu pliku tekstowego
function AfterLoad(e:Event):void{
for each (var s:String in Txt_array){// pętla która rozdziela tekst na polski i angielski
var i:int=0;
En_array[i]=s.substr(0, s.indexOf("-")-1);
Pl_array[i]=s.substr(s.indexOf("-")+2, s.length);
i++;
} //koniec fora
}//koniec funkcji
Begin.addEventListener(MouseEvent.CLICK, test);
function test(e:Event):void{
trace(En_array[1]);
}
//funkcja wyświetlająca string w txt_load
function ShowString (txt_show:String):void{
load_txt.text = txt_show;
}
function ShowOpinion(txt_opinion:String):void{
opinion_txt.text=txt_opinion;
}
function HideOpinion():void{
opinion_txt.text=" ";
}
//funkcja porównująca łańcuchy
function Compare(txt_a:String,txt_b:String):Boolean{
if (txt_a==txt_b){
return true;
}
return false;
}
//up_btn.useHandCursor=true;
//up_btn.addEventListener(MouseEvent.MOUSE_OVER, switch_bg);
//function switch_bg(me:MouseEvent):void{
//var newColor:ColorTransform = me.target.transform.colorTransform;
//newColor.color = 0x1000C6;
//me.target.transform.colorTransform = newColor;
//}
on test function i always get undefined while tracing. I was trying to find solution in Google but couldn't.

This code looks like it should work but if you're trying to access the first element in En_array you need to remember indexing starts at 0, not 1. You might also want to make sure En_array is not empty before reading any of its values. Try this:
if (En_array.length > 0)
trace(En_array[0]);

it sometimes take some seconds to load data first. After loading then read data from array. In timeline, loading must not be at the same frame with the reading process, unless otherwise, explicitly loaded in first line of code then followed by reading.

You have mess in your code. Lets make it simpler:
import flash.events.Event;
import flash.utils.Timer;
import flash.events.MouseEvent;
stop();
var myTextLoader:URLLoader = new URLLoader();
var Txt_array:Array;
var Pl_array:Array;
var En_array:Array;
/* Good practice is to create object when you relay need it */
var myTimer:Timer = new Timer(1000);
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
function onLoaded(e:Event):void {
Txt_array = e.target.data.split(/\n/); // now we create new array
afterLoad(Txt_array);
}
function afterLoad(array):void{ // it is good habit to start function names from small letter
En_array = [];// create arrays
Pl_array = [];
for each (var s:String in array){
En_array.push(s.substr(0, s.indexOf("-")-1));
Pl_array.push(s.substr(s.indexOf("-")+2, s.length));
// push let you add items more efficient and you don't need index
}
}
myTextLoader.load(new URLRequest("Zwroty.txt"));
Now everything should be fine :) Just remember to check if objects (in your case arrays) have elements you want to use (etc. array.lenght>0 or array=null)

Related

Why does my function not return the data I expect?

Here's my code, creating an array from a text file. If I trace it inside the function "onloaded", I see my array. But it returns me nothing outside the function. Why?
var myTextLoader:URLLoader = new URLLoader();
var myArray:Array = new Array();
myTextLoader.load(new URLRequest("list.txt"));
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
function onLoaded(e:Event) {
myArray = e.target.data.split(/\n/);
// if trace(myArray); here - I see my array.
}
trace(myArray); // - output is clear, also it can't define a property, if I'm looking for .length
This is the order of events that is occurring in your program:
myArray is being created.
myTextLoader starts to load the contents list.txt.
An event listener is added to myTextLoader, which will cause a function to be executed when list.txt is finished loading.
You trace the contents of myArray. There is nothing currently in myArray.
myTextLoader finishes loading list.txt
The onLoaded function is called
Data is added to myArray
To summarize, myArray is empty when you're trying to trace it. If you want to wait until the contents of list.txt are added to the array, then just put your loop into the onLoaded function instead.
Option 1:
var myTextLoader:URLLoader = new URLLoader();
var myArray:Array = new Array();
myTextLoader.load(new URLRequest("list.txt"));
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
function onLoaded(e:Event)
{
myArray = e.target.data.split(/\n/);
for (var i:int = 0; i < myArray.length; i++)
{
trace(myArray[i]);
}
}
If you need to access the array later on, from another function, one solution is to store the array inside a variable with greater scope. In the below example, after the onLoaded function executes, you could then access the array from myArrayLoopFunction().
Option 2:
public class Main extends MovieClip
{
public var myArray:Array = new Array();
public function Main()
{
var myTextLoader:URLLoader = new URLLoader();
myTextLoader.load(new URLRequest("list.txt"));
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
function onLoaded(e:Event)
{
myArray = e.target.data.split(/\n/);
}
}
public function myArrayLoopFunction()
{
for (var i:int = 0; i < myArray.length; i++)
{
trace(myArray[i]);
}
}
}
The reason why it returns nothing outside the function is that is has no data in it. That is because the data has not yet been loaded into the array. Your trace(myArray) outside the function will execute immediately when the data has not yet been saved, but your trace(myArray) inside the function which is a callback function that executes when the load function on the URLLoader is done, when you have loaded the file and therefore has data.

AS3 Array items not splicing properly

I'm attempting to make a small game where the user mouses over the circles that fall from the ceiling for points. The circles are added to a container and pushed into an array to hold them, and are removed and spliced when they are mouse-over'd or go off stage.
Everything works fine, until two circles are removed at nearly the same time, whether it be from falling off stage at the same time or mousing over two of them extremely fast. When this happens, the child on stage is removed, but the object is still left in the array, meaning another circle cannot take its place, leaving one less circle spawning every time the issue happens.
Code on main timeline:
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.MovieClip;
import flash.display.Sprite;
var ballContainer:Sprite = new Sprite();
addChild(ballContainer);
var maxBalls:uint = 10;
var balls:Array = [];
var ballTypes:Array = [GreenBall];
var ballChances:Array = [800];
var ballVelocities:Array = [1.5];
var ballAccelerations:Array = [1.02];
stage.addEventListener(Event.ENTER_FRAME, onTick);
function onTick(e:Event):void {
while (balls.length < maxBalls){
addBall();
}
}
function addBall():void {
var ballType = ballTypes[0];
var ball = new ballType;
ball.x = Math.ceil(Math.random()*(stage.stageWidth - ball.width));
ball.y = 0 - (ball.height*1.5);
ballContainer.addChild(ball);
balls.push(ball);
}
Code in GreenBall:
import flash.events.Event;
var mainStage = Sprite(root);
var index = mainStage.balls.indexOf(this);
var velocity:Number = mainStage.ballVelocities[0]*randomNumber(0.5, 1.5);
var acceleration:Number = mainStage.ballAccelerations[0];
this.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
function onMouseOver(e:MouseEvent):void {
this.removeEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
removeBall();
}
this.addEventListener(Event.ENTER_FRAME, onTick);
function onTick(e:Event):void {
this.y += velocity;
velocity = velocity*acceleration;
if (this.y > stage.stageHeight + this.height){
this.removeEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
removeBall();
}
}
function removeBall():void {
mainStage.balls.splice(index, 1);//doesn't get spliced if balls are removed too quickly
mainStage.ballContainer.removeChild(this);
this.removeEventListener(Event.ENTER_FRAME, onTick);
}
function randomNumber(min:Number, max:Number):Number {
return Math.random()*(max - min) + min;
}
So what's going on? Did I set something up incorrectly? How can I go about fixing this issue?
Any help would be appreciated greatly.
Your logic is flawed - the index should be calculated when the removal occurs. When you remove objects from an array via splice, the index of all the elements after the one you removed is decreased by one.
This means that if you have 10 balls and remove the first, the index value you have for every other ball will be incorrect and you'll be removing the wrong ball from your array on subsequent removals.
Moving the indexOf statement to the removeBall method should solve the issue:
function removeBall():void
{
var index:int = mainStage.balls.indexOf(this);
if(index >= 0)
{
mainStage.balls.splice(index, 1);
mainStage.ballContainer.removeChild(this);
this.removeEventListener(Event.ENTER_FRAME, onTick);
}
}
To make it easy on yourself, you could extend Array and make a remove function:
public dynamic class List extends Array
{
public function remove(item:*):void
{
var i:int = indexOf(item);
if(i >= 0) splice(i, 1);
}
}

error With changing x and y positions of movieclip using array

I'm trying to create a program using Action Script 3.0 where I click an element, click on another element, the first element goes to the second element.
This is My code:
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.display.MovieClip;
import flash.events.MouseEvent;
stop();
var Plchange:MovieClip;
var As:Array = new Array(A1,A2,A3,A4,A5,A6,A7,A8,A9);
var Bs:Array = new Array(B1,B2,B3,B4,B5,B6,B7,B8,B9);
var Cs:Array =new Array(C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12);
var Cs1:Array=new Array(C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24);
for ( var i:int =0; i<=8 ;i++)
{
As[i].addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ gotoPlace(me, As[i])});
Bs[i].addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ gotoPlace(me, Bs[i])});
}
for ( var Y:int =0; i<=12 ;Y++)
{
Cs[Y].addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ Set(me, Cs[Y])});
Cs1[Y].addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ Set(me, Cs1[Y])});
}
function gotoPlace(event:MouseEvent, boing:MovieClip)
{
boing = Plchange;
}
function Set(event:MouseEvent, clip:MovieClip)
{
Plchange.x = clip.x;
Plchange.y = clip.y;
}
I'm getting an error:
TypeError: Error #1010: A term is undefined and has no properties.
at NineMen_fla::MainTimeline/frame1()
where am I going wrong? Please tell me.
First, in gotoPlace you should type Plchange = boing; not vice versa. And second, you have to check if Plchange is assigned a value within function Set(). Like this:
var Plchange:MovieClip=null;
function gotoPlace(event:MouseEvent, boing:MovieClip)
{
Plchange = boing;
}
function Set(event:MouseEvent, clip:MovieClip)
{
if (!Plchange) return; // Plchange is not assigned
Plchange.x = clip.x;
Plchange.y = clip.y;
}

How to declare array with custom indices, in Unity JavaScript?

I'm looking for a way to store variables of same type in an array, and access them by their names. Like in PHP you do:
$array = array();
$array['first member']=$var1;
$array['another member']=$var2;
// so on
I want to do a similar thing in Unity3D's JavaScript. I have AudioClip variables, currently used like this:
#pragma strict
var Audio_Goal:AudioClip;
var Audio_Miss:AudioClip;
var Audio_Saved:AudioClip;
function PlaySound_Goal()
{
audio.PlayOneShot(Audio_Goal);
}
function PlaySound_Miss()
{
audio.PlayOneShot(Audio_Miss);
}
of course this requires one function per audioclip, which is ugly.
I want to do it like this:
function PlayAudio(audioname:String)
{
audio.PlayOneShot(AudioArray[audioname]);
}
How can I do this?
You need to use something like a dictionary:
#pragma strict
import System.Collections.Generic;
var AudioArray = new Dictionary.<string,AudioClip >();
// add to dict
AudioArray["one"] = AudioClip.Create(/**/); //see AudioClip.Create(...) for arguments
// play from dict
audio.clip = AudioArray["one"];
audio.Play();
You can do something like:
var myAudioClips: AudioClip[];
function Start() {
// Your stuff...
}
function PlayAudio(audioname:String)
{
for (var myClip in myAudioClips) {
if (audioname.Equals(myClip.name)) {
audio.PlayOneShot(myClip);
}
}
}
And then add all of your clips in the array by dragging them using the editor.
You should be able to use Enumerable.Zip>, but because it's not available in UnityScript, I think this is the best you can do:
var names : List.<String>;
var clips : List.<AudioClip>;
var keyFunc = function(kvp : KeyValuePair.<String, AudioClip>) kvp.Key;
var valueFunc = function(kvp : KeyValuePair.<String, AudioClip>) kvp.Value;
var dictionary = names.Select(
function(name, index) new KeyValuePair.<String, AudioClip>(name, clips[index])
).ToDictionary(keyFunc, valueFunc);
I don't know why you need to store the Funcs. This code compiles, but won't run:
var dictionary = names.Select(
function(name, index) new KeyValuePair.<String, AudioClip>(name, clips[index])
).ToDictionary(function(kvp) kvp.Key, function(kvp) kvp.Value);
Report it as a bug if you want. I don't want to, because I don't think the devs need to waste any more time on this language.

calling swf with an array, not working with my string in flash

I'm trying to get my SWF loader to work with an array so I can call my swf files via one code, using buttons.
This is the problem I am getting:
Scene 1, Layer 'actions', Frame 2, Line 68 1067: Implicit coercion of a value of type Array to an unrelated type String.
I am not too good with arrays, or strings, or coding tbh, i'm not too sure what the problem is, I understand it, my array and my string don't work together,basically, but I don't know how to fix it, if it can be fixed/work with the code I am using.
just some help and being pointed in the right direction would be a treat
var swfList:Array = ["imagegallery.swf", "videoplayer.swf"];
var SWFLoader = new Loader;
var SWFRequest = new URLRequest (swfList) ;
SWFLoader.load (SWFRequest) ;
function loadSWF(file:String, container:MovieClip=null):void
{
if(container == null) container = MovieClip(root);
if(SWFLoader != null)
{
if(SWFLoader.parent) SWFLoader.parent.removeChild(SWFLoader);
}
addChild (SWFLoader);
}
vidPlayer_btn.addEventListener (MouseEvent.CLICK, goVidPlayer);
function goVidPlayer (e:MouseEvent):void
{
loadSWF("videoplayer.swf");
}
imageGallery_btn.addEventListener(MouseEvent.CLICK, goImageGallery);
function goImageGallery(e:MouseEvent):void
{
loadSWF("imagegallery.swf");
}
To access items within an array use this format:
var SWFRequest = new URLRequest(swfList[i]);
Where i is the position in array (starting at zero).
For instance:
var SWFRequest = new URLRequest(swfList[0]);
gives the same result as:
var SWFRequest = new URLRequest("imagegallery.swf");
Did away with the array but still "have one code for both buttons instead of two separate codes".
// Looks unnecessary
// var swfList:Array = ["imagegallery.swf", "videoplayer.swf"];
// Transfer inside loadSWF()
// var SWFRequest = new URLRequest (swfList); // needs a url String parameter
// SWFLoader.load (SWFRequest);
var SWFLoader = new Loader(); // Don't forget the parenthesis
vidPlayer_btn.addEventListener (MouseEvent.CLICK, goVidPlayer);
imageGallery_btn.addEventListener(MouseEvent.CLICK, goImageGallery);
function goVidPlayer (e:MouseEvent):void
{
loadSWF("videoplayer.swf");
}
function goImageGallery(e:MouseEvent):void
{
loadSWF("imagegallery.swf");
}
function loadSWF(file:String, container:MovieClip=null):void
{
// What for?
// if(container == null) container = MovieClip(root);
if(SWFLoader != null)
if(SWFLoader.parent)
SWFLoader.parent.removeChild(SWFLoader);
var SWFRequest = new URLRequest (file) ;
SWFLoader.load (SWFRequest);
addChild (SWFLoader);
}

Resources