Flash AS3 - Timer goes crazy after a few loops - actionscript-3

I've been making a "slideshow" where 4 images are animated in random order.
To prevent multiple animations to one image for example 3 times successively, I've write a little logic.
My problem : after a few times all the 4 images are animated (after the query 'array' is cleared the second time I think), the timer goes crazy and trace() random numbers in a high sequence rate without to animate the images, with would look creepy I think.
My code :
var myTimer:Timer = new Timer(2500);
myTimer.addEventListener(TimerEvent.TIMER, animate);
myTimer.start();
var array:Array = new Array();
var lastNum:int;
function animate(e:TimerEvent):void {
var num:int = getRandomNumber( 1, 4 );
trace( num );
if( array.indexOf( num ) < 0 && num != lastNum ) {
myTimer.delay = 2500;
if( num == 1 ) {
sideImg_start_1.play(); // comment this*
} else if( num == 2 ) {
sideImg_start_2.play(); // comment this*
} else if( num == 3 ) {
sideImg_start_3.play(); // comment this*
} else if( num == 4 ) {
sideImg_start_4.play(); // comment this*
}
array.push( num );
if( array.length == 4 ) {
array.splice(0, 4);
trace(" array cleared - " + array.length);
lastNum = num;
}
} else {
myTimer.delay = 100; // I've also tryed so make a higher delay
// like 500 but its the same problem...
}
}
function getRandomNumber( min:int, max:int ):int {
return Math.floor( Math.random() * ( 1 + max - min ) ) + min;
}
stop();
So guys, thanks for all your answers and your help :D
UPDATE:
First I've tried to simply call the 'animate()' function instead of defining a higher speed to the timer to call the next number fast, without to loose time, which would make the random animation look weird.
I've used animate(null); instead of myTimer.delay = 100; before, but then I was getting a STACKOVERFLOW error :P

For example if your lastNum is equal to 4, and you have 1,2 and 3 as new values, than you will end up with an infinite loop,
because you can't insert 4 (because it's equal to the lastNum) and you can't insert 1,2 or 3 because they are already in the array.
What you need to do is:
if (array.length == 4) {
array.splice(0, 4);
lastNum = num;
} else {
lastNum = 0; //<-- HERE
}

Related

How to make if chains

I am making a game for my assignment in AS3.0 and this isn't working.
All the variables and buttons are defined, I get no error but it just dose not function :
frame 2 layer 1
function CheckScene():void
{
P_HP = 5
E_HP = 1
A_D = 1
if(P_HP == 5)
if(E_HP == 2)
if(A_D == 1)
q = 1
if(P_HP == 5)
if(E_HP == 1)
if(A_D == 1)
q = 2
}
frame 2 layer 2
stop();
but.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndStopAtFrame);
function fl_ClickToGoToAndStopAtFrame(event:MouseEvent):void
{
gotoAndStop(5);
}
frame 3 layer 2
button_2.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndStopAtFrame_2);
function fl_ClickToGoToAndStopAtFrame_2(event:MouseEvent):void
{
if(q == 1)
gotoAndStop(5)
if(q == 2)
gotoAndStop(4)
}
Basically it goes to frame 4 if it works, or 5 if it doesn't. The if chain isn't working. I have no clue how to do this because this sort of thing works in excel (for checking multiple variables before execution).
See comments for help and explanation:
//use naming conventions : methods start with lower-case.
//fix method signature
private void checkScene()
{
//declare all variables
//use naming conventions : variables start with lower-case.
int p_HP = 5; // ; at the end of every statement
int e_HP = 1;
int a_D = 1;
int q = 0;
if(p_HP == 5) {
if(e_HP == 2) {
if(a_D == 1) {
q = 1;
}
}
}
//you could use an equivalent and shorter format:
//if( p_HP==5 && e_HP==2 && a_D==1) q=1;
if(p_HP == 5) {
if(e_HP == 1) {
if(a_D == 1) {
q = 2;
}
}
}
//you could use an equivalent and shorter format:
// if( p_HP==5 && e_HP==1 && a_D==1) q=2;
//add printout to check the result
System.out.println("q is "+q);
}
For future questions pleas post an MCVE

Flash : Action Script 3.0 : strange error when removing listeners and gotoandplay frame

I'm new to AS3. I searched for my error many times, but have not found an answer.
First, here is my code:
this.stage.scaleMode = StageScaleMode.EXACT_FIT;
this.stage.align = StageAlign.TOP_LEFT;
stop();
stage.addEventListener(Event.ENTER_FRAME , movecity);
stage.addEventListener(Event.ENTER_FRAME , timerfunc);
stage.addEventListener(Event.ENTER_FRAME , burgerfall);
var g:Number = 0 ;
var now:Number = 5;
var chips_no:int = 0 ;
var burger_no:int = 0;
function movecity(event:Event):void {
city.x = city.x - 3 ;
if(city.x <= -498 ){
city.x = 993;
}
}
function ontouch(event:MouseEvent , my:MovieClip){
my.y = (140 + (400 - 140) * Math.random())* (-1);
my.x = (60 + (400 - 60) * Math.random());
g=10;
if(my.name=="chips"){
chips_no +=1;
}
if(my.name=="burger"){
burger_no +=1;
}
if(my.name=="burger2"){
burger_no +=1;
}
}
function burgerfall(event:Event){
if(burger_no==1 && chips_no==1){
return stage.removeEventListener(Event.ENTER_FRAME, burgerfall),
stage.removeEventListener(Event.ENTER_FRAME, movecity),
stage.removeEventListener(Event.ENTER_FRAME, timerfunc),
gotoAndPlay(215);
}
g = g + 14;
burger.rotation += 20 ;
burger2.rotation += 25;
chips.rotation +=15;
burger.y = burger.y + g;
burger2.y = burger2.y + g;
chips.y = chips.y + g;
/////////////////// chips relocate
if(chips.y >=1730){
chips.y = -500 ;
g = 0.3 ;
if(chips.x <=240){
chips.x += Math.random()*400 ;
}else{
chips.x -= Math.random()*400 ;
}
}
// ///////////////// burger relocate
if(burger.y >= 1130){
burger.y = -109 ;
g = 0.3 ;
if(burger.x <=240){
burger.x += Math.random()*400 ;
}else{
burger.x -= Math.random()*400 ;
}
}
// ///////////////////// burger 2 relocate
if(burger2.y <= 1250){
burger2.y = -365 ;
g=0.3;
if(burger2.x <=240){
burger2.x += Math.random()*400 ;
}else{
burger2.x -= Math.random()*400 ;
}
}
}
function timerfunc(event:Event):void {
timer_text.text = String(int(now));
now-=0.05;
if(now <= 0){
stage.removeEventListener(Event.ENTER_FRAME , movecity);
stage.removeEventListener(Event.ENTER_FRAME , timerfunc);
stage.removeEventListener(Event.ENTER_FRAME , burgerfall);
gotoAndPlay(215);
}
}
burger2.addEventListener(MouseEvent.CLICK , function(me:MouseEvent):void {
ontouch(me, burger2)
});
burger.addEventListener(MouseEvent.CLICK , function(me:MouseEvent):void {
ontouch(me, burger)
});
chips.addEventListener(MouseEvent.CLICK , function(me:MouseEvent):void {
ontouch(me, chips)
});
===========================================
My game is to click on food. If you collect 1 burger and 1 chips you move to : level completed frame. If the timer counts to 0, the game over frame will shown.
The strange problem is about the stage statements. If I re-order the statements this way:
stage.addEventListener(Event.ENTER_FRAME , movecity);
stage.addEventListener(Event.ENTER_FRAME , timerfunc);
stage.addEventListener(Event.ENTER_FRAME , burgerfall);
Then you collect burgers and level complete frame is shown. If the time reaches zero the error 1009 shown about burgerfall() method !!
If I re-order the statements to this way :
stage.addEventListener(Event.ENTER_FRAME , movecity);
stage.addEventListener(Event.ENTER_FRAME , burgerfall);
stage.addEventListener(Event.ENTER_FRAME , timerfunc);
Then you collect burgers, the error 1009 shown about timerfunc() method! If the time reaches zero, the time out frame is shown without any errors!
Hopefully, will understand the issue.
There are so many people posting questions about Null Object Reference Error that I have decided just to paste the link to tutorial here.
Here it is
It is pretty easy to find the exact reason of the error in vast majority of cases. You should try to find exact line of code and exact reference that is null, at least (even if you do not understand why it happens). Then, people, who want to help you will spend less time guessing ))
EDIT:
As to your code... I see no specific need to have 3 different methods which is called on each Enter_Frame event. This is same game loop.

How to rearranged items in an inventory

I'm creating a game in AS3.
The player can grabb items and add it to his inventory in a line.
Everything is working, but I've got a bug when the player use an item wich is in the middle of the line.
It doesen't rearanged well..
(here is a video if I'm not very clear : http://ul.to/z7su5dqm or here https://drive.google.com/file/d/0B5-MjJcEPm3lTTlDV09MYWxMOFE/edit?usp=sharing)
I've got the code that add the item to the inventory :
public function addInvItem(itemName:String):void{
var itemRef:Object = getDefinitionByName(itemName.toLowerCase()+"Inv");
var addedItem:MovieClip = new itemRef;
addedItem.displayName = itemName;
if (playerItems.length < 8){ // This is for the top row of up to 4 items
addedItem.y = 520;
addedItem.x = 60 + (playerItems.length) * 100;
}
if (isUnique(addedItem)){
this.addChild(addedItem);
playerItems.push(addedItem);
allItems.push(addedItem);
addedItem.buttonMode = true;
addedItem.invItem = true;
addedItem.addEventListener(MouseEvent.CLICK, useItem, false, 0, true);
puzzle = Engine.puzzle;
puzzle.gotItem(addedItem.displayName);
}
So the first item is add at x= 60 and y = 520.
And then I've got this code in order to remove and rearranged the items :
public function removeInvItem(itemName:String):void{
removedItem = itemName;
var itemNum:int;
for (var i in playerItems){
if (playerItems[i].displayName == itemName){
playerItems[i].visible = false;
itemNum = i;
} else {
playerItems[i].visible = true;
}
}
playerItems = playerItems.filter(checkForItem);
// Rearrange the rest of the items
for (i in playerItems){
if (i >= itemNum){
playerItems[i].x -= 100;
}
}
}
Do you see where could be the error that push my first item ? (I suppose it came from playerItems[i].x -= 100).
I must find a way to tell the code that first item can't be less than x = 60 but the other must move x= -100 everytime their are used...
Any idea how I can do that ?
Thank you very much,
You are correct in assuming playerItems[i].x -= 100; is where the problem is caused. You are subtracting the current x position without any checks for if that falls over your inventory icon asset.
You could do something like this instead:
public function removeInvItem(itemName:String):void{
removedItem = itemName;
var itemNum:int;
for (var i in playerItems){
if (playerItems[i].displayName == itemName){
playerItems[i].visible = false;
itemNum = i;
} else {
playerItems[i].visible = true;
}
}
adjustInventory( itemNum );
}
public function adjustInventory( itemNum:int ):void {
var i:int;
for ( i=itemNum; i < playerItems.length; i++ ) {
//you can replace 60 with inventoryIcon.x + inventoryIcon.width instead
playerItems[i].x -= playerItems[i].x - 100 >= 60 ? 100 : playerItems[i].x - 60;
}
}
This evaluates the distance you are about to move before you do it, and only moves the necessary inventory items. I haven't tested this code but this should put you on the right path.

add scoring system to bubble burst game as3

first of all thanks a lot for taking interest in my question. I am trying to modify a flash as3 bubble burst game and add a scoring system to it. I am pasting the code where it detects the bubbles group and bursting them.
/**
* Checks single ball for touching another ball with the same color
* #param ball
*/
private function checkHit(ball:Ball):void {
_checkingNum++;
ball.checked = true;
var point:Point;
var point2:Point;
var d:Number;
var scorenet:Number;
for (var j:int = 0; j < _tabBalls.length; j++) {
if (Ball(_tabBalls[j]).color == ball.color) {
if (!_tabBalls[j].checked && !inTab(_theSame, _tabBalls[j])) {
point = new Point(ball.x, ball.y);
point2 = new Point(Ball(_tabBalls[j]).x, Ball(_tabBalls[j]).y);
d = countD(point, point2);
if (d < _BALL_WIDTH + 4) {
_theSame.push(_tabBalls[j]);
checkHit(_tabBalls[j]);
/*score system*/
scorenet = scorenet + 10;
trace (scorenet);
}
}
}
}
_checkingNum--;
if (_checkingNum == 0) {
if (_theSame.length >= 3) {
for (var i:int = 0; i < _theSame.length; i++) {
killBall(Ball(_theSame[i]));
Ball(_theSame[i]).kill();
}
_noeffect = 0;
} else {
_noeffect++;
if (_noeffect >= _MAX_NO_EFFECT) {
_noeffect = 0;
addNewLine();
}
}
}
}
Now I added a variable called scorenet and later I am trying to add 10 to it each time a bubble bursts but thats obviously not working. the trace is returning a value of '0' each time a bubble bursts so if in total of say 4 bubbles get burst it returns a value of 0 , 0 ,0 , 0 . I was wondering if there was someway to trace the number of 0 it returns and then add 10 to it each time , it will work fine then. Any help would be highly appreciated. Thanks.
You are using local variables to make scoring. local variables are lost when a method call is complete : it cannot be used to store persistent value like score. you should use member variables or static variables, which persists regardless of method calls.
Your calculation is NaN+10, because local variable scorenet is INITIALIZED every time checkHit() is called. so trace is showing "0". You have to deal with problem 1, or it will just be "10, 10, 10, 10..."
I added this
public var scorenet:Number = 0; //as variable
and added the score system
/score system/
if(_checkingNum > 1 ) {
scorenet = scorenet + _checkingNum + 10 ;
_mainTimeline.scoreField.text = scorenet;
} else if(_checkingNum >= 4 ) {
scorenet = scorenet + _checkingNum + 20 ;
_mainTimeline.scoreField.text = scorenet;
}

as3 var not listening to x--

So Ive got this code:
function speedUp():void
{
trace ("speed", playerSpeed);
//checks if any boosts are on
if (boostCheck == false) {j = playerSpeed}
//making speed limit
if (playerSpeed < speedLimit)
{
playerSpeed ++;
}
//increasing speed limit
if (speedLimitInc == 100)
{
speedLimit++;
speedLimitInc = 1;
}
trace ("______________j", j);
speedLimitInc ++;
if (boostCheck == true)
{
for (var i:int = boost.length-1; i>=0; i--)
{
var tempBoostN:int = boost[i];
trace ("__________tempBoostN", tempBoostN);
if (tempBoostN >= 0)
{boostCheck = true; colBoolean = false; tempBoostN--;}
else
{
boostCheck = false;
player.y = player.height + 30;
colBoolean = true;
}
if (playerSpeed >= j)
{
if (tempBoostN >= 150)
{
playerSpeed = playerSpeed -1;
} else if (tempBoostN <= 150 && tempBoostN >= 30) {
playerSpeed = playerSpeed - 2;
}
tempBoostN--;
}
}
}
}
Im getting a problem with tempBoostN variable, more to point, its not listening to commands. When the var is, say, 200 (its defined as an int) and I do tempBoostN-- like you see in code, it just stays 200.
I have tried defining the var as a Number as etc.. but it stays the same.
I have also checked that the 200 is actually a Number not a string (if var is int the it cant hold a string, right?) by doing trace(temBoostN - 1); and that worked.
CODE EXPLANATION:
Function handles playerSpeed, first it does usual behaviour (increasing the speed and stuff).
After that (the part where I get the problem) checks for speed boosts activated and for each it decreases the speed back to normal speed when the boost is deactivated. var j holds playerSpeed without any boosts and is used to check if boosts ran out.
All the vars in the code are defined and working properly.
I think what you actually want to do is get the decrement reflected in boost[i]. What is the type of 'boost[i]'. I believe it's int and that's why changing tempBoostN isn't changing boost[i]. There are 2 ways around it:
(1) You put Number in boost[i], so tempBoostN = boost[i] is a assignment by reference as against a value copy being done in case of int
(2) re-assign boost[i] = tempBoostN at the end of loop.