Array getting Keyboard Input - arrays

This code is from a tutorial, I do understand it - just not the array. I know arrays hold values in their indexes (array[1]=something, array[2]=something...)
But how does the array "keys" have the Keyboard.RIGHT value in the update function?
package
{
-imports here-
public class Main extends Sprite
{
var keys:Array = [];
var ball:Sprite = new Sprite();
public function Main():void
{
ball.graphics.beginFill(0x000000);
ball.graphics.drawCircle(0, 0, 50);
ball.graphics.endFill;
addChild(ball);
ball.x = stage.stageWidth / 2;
ball.y = stage.stageHeight / 2;
ball.addEventListener(Event.ENTER_FRAME, update);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
private function update(e:Event):void {
if (keys[Keyboard.RIGHT]) {
ball.x += 5;
}
}
function onKeyDown(e:KeyboardEvent):void {
keys[e.keyCode] = true;
}
function onKeyUp(e:KeyboardEvent):void {
keys[e.keyCode] = false;
}
}
}
(Because, to give a value to a variable in Pascal for an example, I'd have to write readln (array[1]) - this would give whatever value the user typed to array[1]).
So, I don't see how keys[] is getting keyboard input :P

e.keyCode is an integer. When the onKeyDown gets called, the code uses the integer to set a value in the array to true.
For example, if the RIGHT key is pressed on the keyboard, e.keyCode would be 39, so the code is the same as keys[39] = true;.
If you look at the documentation for Keyboard you will see that Keyboard.RIGHT is defined as 39. http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/ui/Keyboard.html
On the next frame the update event fires.
When you write an if statement without an ==, it kinda does it for, so the if statement is essentially saying
if(keys[39] == true) {
ball.x += 5;
}

Related

How can I move back to Element 0 in an array to reset a loop?

I have an array that loops through a bunch of images to make an animation but will change to another array animation once a condition is met. After that array is over, it does return to the first. However, it picks up where it left off instead of resetting. I need it to return at Element 0 each time. Any ideas?
private var csScript : Main;
var textures : Texture[];
var changeInterval : float = 0.33;
var textures2 : Texture[];
var changeMe : boolean = false;
function Awake() {
//Get the CSharp Script
csScript = this.GetComponent("Main");
//Don't forget to place the 'CSharp1' file inside the 'Standard Assets' folder
}
function Update() {
if( textures.length == 0 ) // nothing if no textures
return;
// we want this texture index now
var index : int = Time.time / changeInterval;
var index2 : int = Time.time / changeInterval;
// take a modulo with size so that animation repeats
if(csScript.janneleIsWaiting) {
index = index % textures.length;
// assign it
renderer.material.mainTexture = textures[index];
}
if(csScript.janelleWorried) {
print("so so worried");
index2 = index2 % textures2.length;
// assign it
renderer.material.mainTexture = textures2[index2];
reset();
}
}
function reset() {
yield WaitForSeconds(.35);
csScript.janneleIsWaiting = true;
csScript.janelleWorried = false;
csScript.janelleHappy = false;
}

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

Using variable A to control variable B

I have a function called FarmClick, and I want it to check the current MovieClip's array. For example:
var farmSpot1:("id",int,int);
var farmSpot2...
I need the clickEvent to capture the MovieClips name and check it's array for the 0th element to see whether it's empty, or not...
My code so far:
public function FarmClick(event: MouseEvent): void {
var CurrentSlot = event.currentTarget.name
if ([event.currentTarget.name[0]] = "empty") {
stage.addChild(menu);
menu.x = 400;
menu.y = 90;
this.menu.buyCornBtn2.addEventListener(MouseEvent.CLICK,buyCorn2);
} else if (farmEmpty == true && itemSelected != "none") {
selected();
} else if (farmEmpty == false) {
farmHarvest();
}
}
It took me a minute to figure out just exactly what it was that you're asking.
So basically, your movie clip's name would be farmSpot[someNumber] and you have an array with the same name?
in that case, to reference the array variable, you need to use the this keyword.
you can add any array subscripts after you've referenced it like so:
private var farmSpot1:Array = ["id", int, int];
public function FarmClick(event:MouseEvent): void
{
if (this[event.currentTarget.name][0] == "") // wasnt sure if you meant the string "empty" or just an empty string, so i just put an empty string
{
// do whatevs
}
}

AS3 flash, Array objects are carrying over into next frame and causing null object error

//I commented out the section that I was trying, but so far nothing has been working. I know I need to set up a loop or something of that kind to get rid of the items in the array, but I'm not sure how to get the right outcome.
THANKS SO MUCH
import flash.utils.Timer;
import flash.display.MovieClip;
import flash.events.Event;
var loveXCounter: Number = 0;
healthLove_txt.text = "Wrong Words: 0";
var insideLoveXCount = new Timer(4000, 0)
insideLoveXCount.addEventListener(TimerEvent.TIMER, countLoveX);
insideLoveXCount.start();
var loveXList: Array = ["Hate", "Abhor", "Vile", "Dislike", "Enmity", "Illwill", "Loath", "Neglect", "Repulse", "Resent"];
function countLoveX(e: TimerEvent) {
var loveXName: String = loveXList[Math.floor(Math.random() * loveXList.length)];
var loveXReference: Class = getDefinitionByName(loveXName) as Class;
var myLoveX = new loveXReference;
myLoveX.x = Math.random() * 700;
myLoveX.y = -10;
myLoveX.speed = 5;
myLoveX.addEventListener(Event.ENTER_FRAME, fallingLoveX);
addChild(myLoveX);
loveXList.splice(loveXName, 1);
}
function fallingLoveX(e: Event): void {
if (e.target.hitTestObject(fb_mc)) {
e.target.visible = false;
loveXCounter = loveXCounter + 1;
e.target.removeEventListener(Event.ENTER_FRAME, fallingLoveX);
healthLove_txt.text = "Wrong Words: " + loveXCounter;
if (loveXCounter == 5) {
while( loveXList.length > 0 )
{
this.removeChild( loveXList[loveXList.length - 1] );
loveXList.pop();
}
MovieClip(root).gotoAndStop(137);
loseBook_mc.gotoAndStop("loseLove");
}
}
if (e.target.y < 800) {
e.target.y += e.target.speed;
if (e.target.y > 800) {
e.target.y = 800;
}
} else {
e.target.visible = false;
}
}
stop();
I can see that the line...
loveXList.splice(loveXName, 1);
...might be causing problems. Firstly, the first parameter of the Array .splice method should be of type int. You are passing in a String. To remedy that, store the randomly selected index of the loveXList Array in an int variable, use that get your loveXName String and use the int again to splice out the correct String from the loveXList Array, ie:
var randomIndex:int = Math.floor(Math.random() * loveXList.length);
var loveXName: String = loveXList[randomIndex];
...
loveXList.splice(randomIndex, 1);
Secondly, you will quickly run out of Strings to splice out of the loveXList Array so, at the start of the countLoveX function, check if loveXList.length>0. If loveXList.length==0 you may want to stop the timer.

Mouse Events for objects in an array in Flash

I am not sure how to make this clear but : Is there a way to allow mouse event register with objects in an array? I have multiple objects being added to stage from an array and i would like to call different functions after said objects are clicked on ? I have this:
function makeEnemies():void
{
//create humans
var tempEnemy:MovieClip;
var wolf:MovieClip;
tempEnemy = new Enemy2();
tempEnemy.cacheAsBitmap = true;
tempEnemy.speed = 20;
tempEnemy.x = Math.round(Math.random() * 800);
tempEnemy.y = Math.round(Math.random() * 480);
addChild(tempEnemy);
enemies.push(tempEnemy);
}
function moveEnemies():void
{
var tempEnemy:MovieClip;
for (var i:int =enemies.length-1; i>=0; i--)
{
tempEnemy = enemies[i];
if (tempEnemy.x > stage.stageWidth)
{
tempEnemy.x = stage.stageWidth;
}
if (tempEnemy.y > stage.stageHeight)
{
tempEnemy.y = stage.stageHeight;
}
tempEnemy.x += Math.round(Math.random() * tempEnemy.speed);
tempEnemy.y -= Math.round(Math.random() * tempEnemy.speed);
tempEnemy.addEventListener(MouseEvent.CLICK, scoreM);
function scoreM(event:MouseEvent):void
{
makeBite(tempEnemy.x, tempEnemy.y);
removeEnemy(i);
score++;
score_txt.text = String(score);
}
function removeEnemy(idx:int)
{
removeChild(enemies[idx]);
enemies.splice(idx,1);
}
And i get an error
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/removeChild()
at veinsVtest_fla::MainTimeline/removeEnemy()
at MethodInfo-67()
You won't need an Array for this job. Like Man of Snow said. Use event.currentTarget will point to the "clicked on Enemy"
tempEnemy.addEventListener(MouseEvent.CLICK, scoreM);
function scoreM(event:MouseEvent):void
{
var clickedOnEnemy:MovieClip = event.currentTarget as MovieClip;
//Now you have your enemy, do whatever you please with him.
makeBite(clickedOnEnemy.x, clickedOnEnemy.y);
//And farewell, my enemy ... time to remove him.
removeChild(clickedOnEnemy);
clickedOnEnemy = null;
score++;
score_txt.text = String(score);
}
* EDIT **
There are several ways to implement "removeAllEnemies".
One way to do it is to use have another MovieClip to hold all enemies created.
So create a movieClip and add it to stage.
var enemiesWrapper : MovieClip = new MovieClip();
addChild(enemiesWrapper);
And then instead of add enemy to root
addChild(tempEnemy); //Instead of doing this
Add them to this MovieClip instead.
enemiesWrapper.addChild(tempEnemy); //Do this instead
Note that your removeChild has to be updated accordingly
enemiesWrapper.removeChild(clickedOnEnemy);
And for "removeAllEnemies" function
function removeAllEnemies() {
while(enemiesWrapper.numChildren > 0) {
enemiesWrapper.removeChildAt(0);
}
}
Replace removeEnemy(i); with removeEnemy(event.currentTarget);
You cannot remove an integer, because it isn't a child. However, I'm assuming you want to remove the MovieClip that was clicked, and it looks like removeEnemy calls removeChild() on the parameter. If not, do you mind showing your removeEnemy function?

Resources