Moving things inside a two-dimensional array in as3? - actionscript-3

I'm trying to create a clone of 2048 for a cs class in as3, and I'm having trouble with moving blocks around. I basically declare a 4x4 array:
var tiles:Array = new Array(new Array(4), new Array(4), new Array(4), new Array(4));
I set it all to empty string at the beginning:
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
tiles[i][j] = '';
}
}
I also have a display function in order to display the array on the frame:
function display():void{
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
if(tiles[i][j] != ''){
tiles[i][j].x = 50 + (107 * j)
tiles[i][j].y = 50 + (107 * i)
}
}
}
}
I also have a keydown event to move the tiles:
for(i = 0; i < 4; i++){
for(j = 0; j < 4; j++){
if(tiles[i][j] != ''){
switch (event.keyCode){
case Keyboard.LEFT:
tiles[i][0] = tiles[i][j]
break;
case Keyboard.RIGHT:
tiles[i][3] = tiles[i][j]
break;
case Keyboard.UP:
tiles[0][j] = tiles[i][j]
break;
case Keyboard.DOWN:
tiles[3][j] = tiles[i][j]
break;
}
tiles[i][j] = ''
}
}
}
It's supposed to set a new tile to the equivalent of the old tile, then set the old tile to '', but for some reason it sets both the new tile and the old tile to ''! I'm not sure what is going on here, can someone point me in the right direction?

Related

AS3: Removed Child Still Passes HitTest

I am making a game similar to doodle jump and I have a powerup MovieClip that appears every time the character bounces up. When the character collides with the powerup, I want it to add to the live score, and then disappear. But I want it to reappear after is has been removed so there is a constant stream of powerups (one for each time the character jumps).
The problem I'm having is that as soon as the first powerup is hit, it visually removes all future powerups but the character is still able to collide with them - constantly adding to the score rather than just once.
I made a recording that I think would help explain.
Here's the block of code I'm trying to fix:
//IF MyChicken TOUCHES CHICKEN LEG, SCORE GOES UP BY 2000
for (var c:int=0; c< 1; c++){
chickMc = powerUp[c];
if (MyChicken.hitTestObject(chickMc))
{
liveScore += 2000;
theScore.text = liveScore.toString();
tapSnd.play();
removeChild(chickMc);
}
}
In case it's something outside of this chunk, here's my whole code:
import flash.events.Event;
import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent;
import flash.display.MovieClip;
import flash.media.Sound;
import flash.events.MouseEvent;
var firstPass:int = 1;
var liveScore:int;
var accX:Number;
var myVect:Vector.<MovieClip> = new Vector.<MovieClip>(5,true);
var powerUp:Vector.<MovieClip> = new Vector.<MovieClip>(1, true);
var vAcceleration:Number = 0.5;
var vVelocity:Number = -20;
var middleScreen:Number = stage.height / 2;
//var newEnemy:enemy;
//var nmeMc:MovieClip;
var newChicken:chicken;
var chickMc:MovieClip;
var newBouncer:bouncer;
var tmpMc:MovieClip;
var poolSnd:poolSound = new poolSound();
var tapSnd:tapSound = new tapSound();
var btnAgain:gameOver;
stop();
// MONITOR THE ACCELEROMETER
var myAcc:Accelerometer = new Accelerometer();
myAcc.addEventListener(AccelerometerEvent.UPDATE, onAccUpdate);
function onAccUpdate(evt:AccelerometerEvent):void{
accX = evt.accelerationX;
}
//MONITOR THE ENTER_FRAME EVENT
stage.addEventListener(Event.ENTER_FRAME, onMyEnterFrame);
//INIT STAGE WITH PLATFORMS (bouncer)
if (firstPass == 1){
liveScore = 0;
accX = 0;
for (var i:int=0; i< 5; i++){
newBouncer = new bouncer;
newBouncer.x = Math.random()*stage.stageWidth;
newBouncer.y = 0 + i*stage.stageHeight/6;
myVect[i] = newBouncer;
addChild(newBouncer);
newBouncer.cacheAsBitmap = true;}
for (var c:int=0; c< 1; c++){
newChicken = new chicken;
newChicken.x = Math.random()*stage.stageWidth;
newChicken.y = 0 + c*stage.stageHeight/6;
powerUp[c] = newChicken;
addChild(newChicken);
newChicken.cacheAsBitmap = true;}
firstPass = 2;
}
function onMyEnterFrame(evt:Event):void{
//MOVE X DEPENDING ON THE ACCELEROMETER
MyChicken.x += (MyChicken.x - (MyChicken.x + accX * 20))*0.6;
//MOVE CHAR TO THE LEFT OR TO THE RIGHT
if(accX < 0) {
MyChicken.gotoAndStop(2);
}else{
MyChicken.gotoAndStop(1);
}
// VERTICAL SPEED OF MyChicken
vVelocity += vAcceleration;
if((MyChicken.y > middleScreen) && (vVelocity < 0)){
// MyChicken IS GOING UP
MyChicken.y += vVelocity;
}else{
if(vVelocity > 0){
// MyChicken IS GOING DOWN
MyChicken.y += vVelocity;
// TEST IF MyChicken HITS PLATFORM
for (var i:int=0; i< 5; i++){
tmpMc = myVect[i];
if (MyChicken.hitTestObject(tmpMc))
{
vVelocity = -20;
tapSnd.play();
}
}
//IF MyChicken TOUCHES CHICKEN LEG, SCORE GOES UP BY 2000
for (var c:int=0; c< 1; c++){
chickMc = powerUp[c];
if (MyChicken.hitTestObject(chickMc))
{
liveScore += 2000;
theScore.text = liveScore.toString();
tapSnd.play();
removeChild(chickMc);
}
}
}else{
// THE WORLD IS GOING DOWN
// WHEN MyChicken IS IN THE MIDDLE OF THE SCREEN
for (var m:int=0; m< 1; m++){
chickMc = powerUp[m];
chickMc.y -= vVelocity;
}
for (var j:int=0; j< 5; j++){
tmpMc = myVect[j];
tmpMc.y -= vVelocity;
}
liveScore += 5;
theScore.text = liveScore.toString();
}
}
//CHECK IF PLATFORMS ARE OUT OF THE SCREEN
if(myVect[0] != null){
for (var k:int=0; k< 5; k++){
tmpMc = myVect[k];
if(tmpMc.y > stage.stageHeight){
tmpMc.y = -5;
tmpMc.x = Math.random()*stage.stageWidth;
}
}
}
if(powerUp[0] != null){
for (var p:int=0; p< 1; p++){
chickMc = powerUp[p];
if(chickMc.y > stage.stageHeight){
chickMc.y = -5;
chickMc.x = Math.random()*stage.stageWidth;
}
}
}
//FAIL - IF CHICKEN FALLS OUT OF THE SCREEN
if (MyChicken.y > stage.stageHeight) {
btnAgain = new gameOver();
addChild(btnAgain);
btnAgain.x = 160;
btnAgain.y = 230;
btnAgain.theScoreFinal.text = liveScore.toString();
theScore.visible = false;
btnAgain.addEventListener(MouseEvent.MOUSE_DOWN, onPlayAgain);
//PAUSE GAME
MyChicken.y = -300;
vVelocity = 0;
vAcceleration = 0;
// PLAY FAIL SOUND
poolSnd.play();
}
// CLICKS ON THE PLAY AGAIN BUTTON
function onPlayAgain(evt:MouseEvent):void{
removeChild(btnAgain);
//NEW GAME
MyChicken.y = stage.stageHeight - 50;
MyChicken.x = stage.stageWidth / 2;
theScore.text = "0";
liveScore = 0;
vVelocity = -20;
vAcceleration = 0.5;
theScore.visible = true;
}
//STAGE BOUNDS MyChicken ON THE LEFT OR RIGHT OF THE SCREEN
if(MyChicken.x < 0) MyChicken.x = stage.stageWidth;
if(MyChicken.x > stage.stageWidth) MyChicken.x = 0;
}
Removing an object does not change its x/y coordinates or width/height (bounds). hitTestObject checks the two objects bounds - it does not take into consideration if an object is actually on the display tree or not. So even though you've successfully removed the object, the hit test will keep checking it. (as the object still exists, it just can't be seen)
You can remedy this by doing a check first to see if chickMc has been removed:
if (chickMc.parent && MyChicken.hitTestObject(chickMc))
The parent property of a display object will null after being removed from the stage.
Though instead of that, you may want to null the reference to the object so it can be garbage collected later:
for (var c:int=0; c< 1; c++){
chickMc = powerUp[c];
if (chickMc != null && MyChicken.hitTestObject(chickMc)){
liveScore += 2000;
theScore.text = liveScore.toString();
tapSnd.play();
removeChild(chickMc);
powerUp[c] == null; //now that powerup object isn't referenced anywhere and can be garbage collected (destroyed from memory)
}
}

testHitObject is returning an incorrect "true" value on the first few frames

if I add the else statement I do receive the "not hit" in my output window, so it looks like the statement only returns true on the first few frames, when it is supposed to return false. Now my problem is that the code wants to remove child objects before they've even been created. I just want to achieve basic collision detection between the enemy and the bullet so that i can remove both children when an enemy is shot. Please keep in mind that there will be multiple enemies and bullets on the stage at a given time.
I seemed to narrow down my problem. What was happening was the instance of an enemy would still exist, after i used the removeChild() function. Only now I couldn't see it for some reason. And its x and y properties were equal to 0. Therefore if I moved the ship to x = 0, it would have an "invisible" enemy collide with it. So I think my problem is I am not removing the instance properly? if not could you please help me?
` <pre>
var BulletsArr:Array = new Array();
var EnemysArray:Array = new Array();
for(i = 0; i < 5; i++)
{
BulletsArr[i] = new Bullet();
}
for(i = 0; i < 5; i++)
{
EnemysArray[i] = new Enemy();
//EnemysArray[i].x = 2000; //Fix
//EnemysArray[i].y = 2000; //Fix
}
stage.addChild(Ship);
Ship.addEventListener(Event.ENTER_FRAME, fnEnterFrame);
function fnEnterFrame(event:Event)
{
txtScore.text = "Score: " + score;
//Make Ship follow cursor
Ship.x = stage.mouseX;
//Boundries
if (Ship.x > 500)
{
Ship.x = 550 - 50;
}
if (Ship.x <= 0)
{
Ship.x = 0 ;
}
for(var i = 0; i < 5; i++){
for(var p = 0; p < 5; p++)
{
if(BulletsArr[i].hitTestObject(EnemysArray[p]))
{
remove(BulletsArr[i]);
removeChild(EnemysArray[p]);
}
for(i = 0; i < 5; i++)
{
BulletsArr[i].y -= 15;
}
for(i = 0; i < 5; i++)
{
EnemysArray[i].y += 5;
}
for(var z = 0; z < 5; z++)
{
if(Ship.hitTestObject(EnemysArray[z])
{
Ship.parent.removeChild(Ship);
EnemysArray[z].parent.removeChild(EnemysArray[z]);
trace("Game over");
}
}
for(i = 0; i < 5; i++)
{
var found:Boolean = false;
for(var p = 0; p < 5; p++)
{
if(BulletsArr[i].hitTestObject(EnemysArray[p]))
{
BulletsArr[i].parent.removeChild(BulletsArr[i]);
BulletsArr[i] = new Bullet();
EnemysArray[p].parent.removeChild(EnemysArray[p]);
EnemysArray[p] = new Enemy();
//EnemysArray[p].x = 2000;//fix
//EnemysArray[p].y = 2000;//fix
score += 50;
found = true;
break;
}
if(found)
{
break;
}
}
}
}
var count_Enemys:int = 0;
var Timer_3_sec:Timer = new Timer(3000, 0);
Timer_3_sec.start();
Timer_3_sec.addEventListener(TimerEvent.TIMER,spawn_ship);
function spawn_ship(Event:TimerEvent):void
{
if(count_Enemys >= 5)
{
count_Enemys = 0;
EnemysArray[count_Enemys].x = fl_GenerateRandomNumber(450) + 70;
EnemysArray[count_Enemys].y = 0 - fl_GenerateRandomNumber(250) - 100;
addChild(EnemysArray[count_Enemys]);
count_Enemys++;
}
else
{
EnemysArray[count_Enemys].x = fl_GenerateRandomNumber(450) + 70;
EnemysArray[count_Enemys].y = 0 - fl_GenerateRandomNumber(250) - 100;
addChild(EnemysArray[count_Enemys]);
count_Enemys++;
}
}
`</code>

Checking for straight combination in poker

I want to check for a straight combination in a poker game.
So, I have this array: var tempArr:Array = new Array;
I have this for sorting the array:
for (i = 0; i < 7; i++)
{
tempArr[i] = pValue[i];
}
tempArr.sort( Array.NUMERIC );
pValue is the value of the cards, it's have range from 2 to 14.
So, if I have this Array: tempArray = [2,3,3,4,5,5,6];
How can I check if I have a straight combination in my hand?
Set a bucket array to save if you got a card in hand
var t:Array = [];
//t[2] = 1;mean you have 2
// t[3] = 0;mean you don't have 3
//first initialize t
for(var i:int = 0; i < 15; i++)
{
t[i] = 0;
}
//then set the values from tempArray
for (var j:int = 0; j < tempArray.length; j++)
{
t[tempArray[j]] = 1;
}
//if you have a straight combination in your hand
//you will get a k that t[k] & t[k-1]& t[k-2] & t[k-3] & t[k-4] == 1
var existed:boolean = false;//the flag save if you got a straight combination
for (var k:int = t.length - 1; k >= 4; k--)
{
if (t[k] == 0)
{
continue;
}
if ((t[k] & t[k-1] & t[k-2] & t[k-3] & t[k-4]) == 1)
{
existed = true;
break;
}
}

Accessing variable names dynamically

I have the following scenario:
if (event.status == AMFResultEvent.SUCCESS) {
var lev1:uint = 0;
var lev2:uint = 0;
var lev3:uint = 0;
var lev4:uint = 0;
var lev5:uint = 0;
var lev6:uint = 0;
for (var i:int = 0; i < event.result.length; i++) {
if (mainLevel == "1") {
lev1++;
}
if (mainLevel == "2") {
lev2++;
}
if (mainLevel == "3") {
lev3++;
}
if (mainLevel == "4") {
lev4++;
}
if (mainLevel == "5") {
lev5++;
}
if (mainLevel == "6") {
lev6++;
}
}
for (var j:int = 1; j < 7; j++) {
_row = new StatisticsRow(event.result[j], this);
_rowsPlace.addChild(_row);
_row.y = (_row.height +1) * j;
_row.codeLevel.htmlText = j; // works as it should
// need to access variables lev1 - lev6, called by something like "lev"+j here:
_row.amount.htmlText =
}
// traces correct amounts of mainLevels from the i loop:
trace ("level 1: " + lev1);
trace ("level 2: " + lev2);
trace ("level 3: " + lev3);
trace ("level 4: " + lev4);
trace ("level 5: " + lev5);
trace ("level 6: " + lev6);
}
I'm missing something obvious here, as the ["lev"]+j doen't work. How can I dynamically acces the lev1 - lev6 in the j-loop? As the code comment at the bottoms shows, this traces as expected.
Thanks in advance!
You can access them with brackets, string concatenation, and the this keyword. Here's an example of how you would use bracket notation in a loop:
for (var i:int = 0; i <= 6; i++) {
var currLev = this["lev"+i];
// do stuff to currLev
}
Thanks for answering guys!
I had a lousy approach to my problem anyway, and should have used an array right away:
var mainLevels:Array = new Array();
for (var n:int = 1; n < 7; n++) {
mainLevels[n] = 0;
}
if (event.status == AMFResultEvent.SUCCESS) {
for (var i:int = 0; i < event.result.length; i++) {
var data = event.result[i];
var correctCode:String = data["correct"];
var mainLevelFound:uint = uint(correctCode.substr(0, 1));
for (var k:int = 1; k < 7; k++) {
if (k == mainLevelFound) {
mainLevels[k]++;
}
}
}
for (var j:int = 1; j < 7; j++) {
_row = new StatisticsRow(event.result[j], this);
_rowsPlace.addChild(_row);
_row.y = (_row.height +1) * j;
_row.codeLevel.htmlText = j;
// Now this works as a reference to mainLevels[*] created above!
_row.amount.htmlText = mainLevels[j];
}
Thanks again for your effort :)

How to make a variable loop in actionscript 3

I'm trying to make a loop that won't crash my flash application. I want variable CN to go from 1 to 10, and then 10 turns into 1 (1,2,3,4,5,6,7,8,9,10,1....). This is what I have so far...
var CN:int = 1;
for(int CN = 1; CN<100; CN++);
NumberCounter.text = String(CN);
Please help. I don't get this at all :( I'm a novice programmer so a lot of things I do won't make much sense.
Your question is a bit unclear. Are you trying to go from 1 to 10 then from 10 to 1 once (20 steps) or to go back and forth between 1 and 10 in 100 steps ?
If it's the first, you can try something like this:
for(var i:int = 0, j:int = 0; i < 20; i++){
if(i < 10) j++;
else j--;
trace(j);//put this in your text field
}
if it's the second:
for(var i:int = 0; j:int = 1, k:int = 0; i < 100; i++){
if(i % 10 == 0) j *= -1; //every 10 steps flip (multiply by -1) the increment direction(increase/decrease)
k += j;//increment k based on j which will either increase or decrease
trace(k);//use this value
}
However the textfield will update right away. If you want to display this change in time you can use the ENTER_FRAME event to increment (rather than the for loop) or a tween engine to animate the value
For an infinite loop:
while(true){
for(var CN:int=1; CN <= 10; CN ++) NumberCounter.text = String(CN);
}
To do it 10 times, which looks like your code is hinting at:
for (int x= 0; x< 10; x++){
for(var CN:int=1; CN <= 10; CN ++) NumberCounter.text = String(CN);
}
Try this
if(CN>1)
{
var CN:int = 1;
for(int CN = 1; CN<10; CN++);
NumberCounter.text = String(CN);
}
else
{
}
var Numberofwins = 0;
CN.addEventListener(Event.ENTER_FRAME, checkFrame);
function checkFrame(event:Event):void{
if(CN.currentFrame == 11){
CN.gotoAndPlay(1);
}
}
import flash.events.MouseEvent;
Submit.addEventListener(MouseEvent.CLICK, CheckIf8);
function CheckIf8(event:MouseEvent):void
{
if(CN.currentFrame == 8)
{
Numberofwins++;
trace (Numberofwins);
Scorebox.text = String(Numberofwins);
}
else
{
gotoAndStop("Loose1");
}
}
This was my solution