AS3 array indexOF - arrays

I am working on a game and have trouble with this array. There is all fruits on the stage which is generated from the array fruit. When the appel will hit the basket, we will count them. The melon is not to be counted. How do i find out if the current fruit is an appel or a melon?
var array_fruit:Array = new Array(appel1_mc, appel2_mc, melon_mc);
var appelsOnstage:Array = new Array();
var appelsCollected:Number = 0;
for (var i:int = 0; i<10; i++) {
var pickappels = array_fruit[int(Math.random()* array_fruit.length)];
var spel_appels:MovieClip = new pickappels();
addChild(spel_appels);
spel_appels.x = (Math.random() * 800) + 100;
spel_appels.y = Math.random() * -500;
spel_appels.speed = Math.random() * 10 + 2;
appelsOnstage.push(spel_appels);
}
stage.addEventListener(Event.ENTER_FRAME, catchappels);
function catchappels(e:Event):void {
for (var i:int = appelsOnstage.length-1; i > -1; i--) {
var currentfruit:MovieClip = appelsOnstage[i];
if (currentfruit.hitTestObject(basket_mc)) {
if(array_fruit.indexOf(currentfruit) == melon_mc ){
trace("melon");
} else {
trace("no melon");
appelsCollected++;
}
}
}
}

a_fruit.indexOf(currentfruit) = -1 all the time
The problem here is the confusion between classes and objects.
a_fruit holds classes, which are to be instantiated by this code
var pickappels = array_fruit[int(Math.random()* array_fruit.length)];
var spel_appels:MovieClip = new pickappels();
appelsOnstage holds objects of those classes and is filled here
appelsOnstage.push(spel_appels);
Classes and objects are - excuse the pun! - apples and oranges, very different things.
A class is like a blueprint for a building or a recipe for a meal. You cannot compare objects with classes and expect them to be the same.
Instead, you should find the class of an object, and then compare this class to another class. For this, you use the is operator. Something like
if(currentfruit is melon_mc)
should do the trick to tell you if you have a melon or not.

indexOf is going to return an int value. See my edit to your code below.
if (currentfruit.hitTestObject(basket_mc)) {
if(array_fruit.indexOf(currentfruit) == 2 ){
trace("melon");
} else {
trace("no melon");
appelsCollected++;
}
}
indexOf takes two arguments. The first is the exact element you are searching for. The second argument is the index position to start the search from. The default is position 0.
See the API documentation here. (Always good to give these a quick read first).

You should use is operator here, for better coding. What if you'd change the positions of classes in your arrays?
if ((currentfruit is appel1_mc) || (currentfruit is appel2_mc)) {
// apple
}

Just in pseudo code to figure a possible way to deal with this issue.
On the timeline :
import com.fruits.Fruit;
import com.fruits.Melon;
import com.fruits.Apple
var fruit_1:Melon = new Melon();
var fruit_2:Apple = new Apple();
if(fruit_1 is Melon){
trace("anyway my SuperclassName is : " + fruit_1.getType());
trace (fruit_1.getMyType());
trace("");
}
if(fruit_2 is Apple){
trace("anyway my SuperclassName is : " + fruit_2.getType());
trace (fruit_2.getMyType());
trace("");
}
in com.Fruit.as :
package com.fruits {
public class Fruit {
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
public function Fruit() {
trace ("I'm a Fruit");
}
public function getType():String{
var type:String = getQualifiedSuperclassName(this)
var str:String = (type);
return str;
}
}
}
In com.Melon :
package com.fruits {
public class Melon extends Fruit {
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
public function Melon() {
super();
trace ("Melon says : ");
trace (" because I'm Fruit and not happy to be a Melon");
trace("");
}
public function getMyType():String{
var type:String = getQualifiedClassName(this)
var str:String = ("Im a " + type);
trace("Class said : I worth nothing because I'm an Fruit and not proud to be an Melon");
str += "\n" + "but in fact I'm a " + getQualifiedSuperclassName(this)
return str;
}
}
}
In com.Apple :
package com.fruits {
public class Melon extends Fruit {
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
public function Melon() {
super();
trace ("Melon says : ");
trace (" because I'm Fruit and not happy to be a Melon");
trace("");
}
public function getMyType():String{
var type:String = getQualifiedClassName(this)
var str:String = ("Im a " + type);
trace("Class said : I worth nothing because I'm an Fruit and not proud to be an Melon");
str += "\n" + "but in fact I'm a " + getQualifiedSuperclassName(this)
return str;
}
}
}
This is just an idea, tell me more about your target and if this may help You...
Best regards Nicolas.
PS : I'm sorry but my English is really bad. so I tried to figure me the issue...
You may perhaps forget about indexOf and use addChild anytime You want to set an object/instance over another one....
So You don't have to check about the indexes.
addChild(some old Child) will make the "old Child" be on the the last index (over the other instances).
Sorry I didn't wrote your code but the title said that you want to check if the fruit is a Melon or an Apple...
Sorry if I misunderstood. :(

Related

Use an array of values for a slider

I want to use an array of id, for my little slider-viewer I'm building. I just want to display multiple things using 2 buttons next and previous.
For now I use something like this, using only 2 url id, but I need at least 20 urlid in my viewer :
var urlid1 = 'd3885ca76ac54e958c2855a4fbd3dbf3';
var urlid2 = '3aa64527d1614998b4812bfefbbc896a';
function Next() {
client.init( urlid2 );
}
function Previous() {
client.init( urlid1 ); }
So I've never use an array before, and the things I tried didn't work. Do you know a proper way to do that ?
This seems straight forward enough
var index = 0;
var array = ["url1", "url2", "url3", ...]
function next() {
index++;
if(index > array.length) {
index = 0;
}
client.init(array[index]);
}
function previous() {
index--;
if(index < 0) {
index = array.length;
}
client.init(array[index]);
}
It may be better practice to actually refactor those changes to the index variable to other functions to enable reuse, but this should give you an idea of how it is done.
If client is something that you have wrote then you might want to look at the naming of your functions, init is normally reserved for instantiating the class as new, from your example you seem to be changing a resource so you may want a function name like client.show(); or client.update();
Thank's Varedis.
Final code is :
var index = 0;
var array = ["0e4b4e0789bf41c7b05129a76de0abb0","3aa64527d1614998b4812bfefbbc896a","d3885ca76ac54e958c2855a4fbd3dbf3","8f927023e10c40b9b22d3c13df7c08aa"];
client.init(array[index]);
function next() {
index++;
if(index >= array.length) {
index = 0;
}
client.init(array[index]);
}
function previous() {
index--;
if(index < 0 ) {
index = array.length-1;
}
client.init(array[index]);
}
I had to use " index = array.length-1; " but I can't explain it. You know why ? How index could be 5 if I only have 4 values ?

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

How can I tell which language was detected with HighlightJS?

For what it's worth, I'm using angularjs and https://github.com/pc035860/angular-highlightjs. I want to know which language was detected and if there's any way to do this.
If this library doesn't do it, are there any that do?
You could search for the hljs class with JavaScript and then find the language class associated with it (assuming the language class is the last class). Example with jQuery:
function findLanguageOfHLJSWithID(id) {
var foundClasses = jQuery('#' + id + '.hljs').attr('class').split(' ');
return foundClasses[foundClasses.length - 1];
}
If you want all the languages highlighted on the page, use this function:
function findAllHLJSLanguages() {
var tempClasses = jQuery('.hljs'), foundClasses = [];
for (var iter = 0; iter < tempClasses.length; iter++) {
var tempClassesSplit = $(tempClasses[iter]).attr('class').split(' ');
foundClasses.push(tempClassesSplit[tempClassesSplit.length - 1]);
}
return foundClasses;
}

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.

Flash AS3, how to index a hashmap with integer keys

Here's the deal.
Right now I have a dictionary of game states
history = new Dictionary();
Each state's key being a timestamp(int)
history[100] = currentState;
history[500] = currentState;
history[699] = currentState;
My question is, how can I find the most recent game state. Let's say I want to know what the state was like at 670, I want the most recent history that's not greater than 670 (I don't want to show the future). This would be history[500].
Right now I'm looping through every key, to find the most recent one. Is there some way I can index these timestamps, so I can search faster than linear time? (I'll have a lot of keys!) Maybe I don't want a dictionary?
You can use a binary search (divide and conquer) approach where you save the states in a sorted array, and you recursively:
divide the array into two halves
if the array contains one item, return that item
determine which half would contain the correct result
go to step 1
This should find the result in logarithmic time. (Note that log2(1,000) ~ 10 and log2(10,000) ~ 13)
Here is a draft (and non tested) implementation:
class HistoryEntry
{
public var timestamp:int;
public var state:GameState;
public function HistoryEntry(timestamp:int, state:GameState)
{
this.timestamp = timestamp;
this.state = state;
}
}
class History
{
private var states:Array;
public function History()
{
super();
states = [];
}
public function addState(state:State):void
{
var timestamp:int = getTimer();
var entry:HistoryEntry = new HistoryEntry(timestamp, state);
states.push(entry);
}
public function getStateBefore(timestamp:int):State
{
return doGetStateBefore(timestamp, 0, states.length - 1);
}
// Recursive function
private function doGetStateBefore(timestamp:int, beginIndex:int, endIndex:int):State
{
if (beginIndex == endIndex) {
return states[beginIndex];
}
var beginEntry:HistoryEntry = states[beginIndex];
var endEntry:HistoryEntry = states[endIndex];
if (beginEntry.timestamp == timestamp) {
return beginEntry.state;
}
if (endEntry.timestamp == timestamp) {
return endEntry.state;
}
var middleIndex:int = (beginIndex + endIndex) / 2;
var middleEntry:HistoryEntry = states[middleIndex];
if (midleEntry.timestamp >= timestamp) {
return doGetStateBefore(timestamp, beginIndex, middleIndex);
} else {
return doGetStateBefore(timestamp, middleIndex + 1, endIndex);
}
}
}
I introduced the class HistoryEntry so that I get typed objects from the array because using dynamic objects will have a negative impact on performance.

Resources