Ninjadoodle

Timer and Array question (SOLVED)

Recommended Posts

Hi guys

I'm trying to setup a timer for each sprite in an array, but 'm doing something wrong.

I'm pretty sure the timer looses track of which sprite it's supposed to update, but I'm not sure how to type it correctly.

for (i = 0; i < 10; i++) {

    this.monsters[i].blink = function() {
        this.monsters[i].eye.animations.play('blink');
        this.monsters[i].blinkTimer = this.rnd.realInRange(2, 6);
        this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this);
    }
}

this.monsters[i].blinkTimer = this.rnd.realInRange(2, 6);

this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this);

If anyone could help that would be awesome!

Thank you in advance for any help :)

Share this post


Link to post
Share on other sites

Hi guys, thanks for the feedback!

I can get everything running fine if I execute the function straight away, so there is no problem there.

The issue I have is -

I'm attaching a timer to each sprite in the array, but the timer looses track of the 'i' variable.

Basically each monster in an array is given a timer, and after the time is up the monster should blink.

I can't seem to figure out how to make this work correctly.

I'm pretty sure it's got something to do with .bind() ... but can't figure out how to use it.

Thank you again!

Share this post


Link to post
Share on other sites

 

this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this);

The last parameter here is callbackContext, which is the object that will become "this" in the function. You can pass "this.monsters" instead of "this" here, so you won't need i variable inside the function.

This should work:

for (i = 0; i < 10; i++) {
    this.monsters[i].blink = function() {
        this.eye.animations.play('blink');
    }
    this.monsters[i].blinkTimer = this.rnd.realInRange(2, 6);
    this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this.monsters[i]);
}

 

Share this post


Link to post
Share on other sites

Sorry, I'm an idiot, I didn't see that you already bind this in events through the two lines below the loop - I actually thought that you put there to show which part was giving you trouble considering they are exactly same as the ones in the blink function.

This variably is binded ok as a phaser game (I guess?). But inside your blink function there is no variable i, so this.monsters doesn't exist so you can't call any properties/funcitons on it. You change this.time.events.add(yourTime, yourFunction, this) into this.time.events.add(yourTime, yourFunction, this.monsters) outside your blink function and not use it inside, just call the animation inside nothing else as this.eye.animations.play('blink');.

After your post I have a question, are you sure you want the last two lines in

for (i = 0; i < 10; i++) {

    this.monsters[i].blink = function() {
        this.monsters[i].eye.animations.play('blink');
        this.monsters[i].blinkTimer = this.rnd.realInRange(2, 6);
        this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this);
    }
}

this.monsters[i].blinkTimer = this.rnd.realInRange(2, 6);

this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this);

be outside the loop? Unless you hid some code from us then you should be having troubles with variable i, because last two lines are called only once and with variable i = 10 which is outside your array (I guess?). Or did I miss anything else?

Share this post


Link to post
Share on other sites

Hi @Fatalist

You are a legend, that works perfectly, thank you heaps for the explanation!

I have one more question ...

If I want to reset the timer inside the monster blink function, I can no longer use "this", as that is now tied to "this.monsters"

How do I assess - "this.time.events.add" - from inside the monster blink function

Thanks again for your help!

Share this post


Link to post
Share on other sites

Hi @AzraelTycka

I'm not always the best at explaining (it sounds right, until I read it back lol).

Basically what I'm trying to do is start off with a random blink (after a number of seconds (hence the last two lines)m then call the function to blink again after another random interval.

I gather it might not be re best way of doing it?

Thanks for your help!

Share this post


Link to post
Share on other sites

No problem ; )

13 minutes ago, Ninjadoodle said:

If I want to reset the timer inside the monster blink function, I can no longer use "this"

You can store the outer "this" in another variable:

var game = this;
for (i = 0; i < 10; i++) {
    this.monsters[i].blink = function() {
        this.eye.animations.play('blink');
        this.blinkTimer = game.rnd.realInRange(2, 6);
        game.time.events.add(Phaser.Timer.SECOND * this.blinkTimer, this.blink, this);
 
    }
    this.monsters[i].blinkTimer = this.rnd.realInRange(2, 6);
    this.time.events.add(Phaser.Timer.SECOND * this.monsters[i].blinkTimer, this.monsters[i].blink, this.monsters[i]);
}

 

Share this post


Link to post
Share on other sites

@Ninjadoodle

I think it's fine I'm jsut idiot who should have asked before answering ;-).

It's just that because you put last two lines outside of your for loop, you will never get any blinks because:
 

monsters = [..] // it's length is 10, last index is 9

for loop

{

  // something done here

}

// you call this.monsters[i].blinkTimer after for loop ended which leaves i at 10, but your monsters array has max index 9, so next two lines result in error in javascript

this.monsters[i].blinkTimer

this.time.events.add(...)

And even if you had one more monster which you didn't loop through before, it would still be the only monster which would be blinking because you never initiated other monsters to blink in the first place (never called blink function on them).

Well, @Fatalist already answered your question before so you can ignore my rumble anyway ;-).

Btw you can store timer in vars, so you can get back to them later. Also for repetition there is a loop timer which does - obviously - calls the event the same way as you are trying. You can also check it in the examples here. I haven't tried it but the docs don't note delay (or tick?) as a readonly property, so you can probably just change it when the event is fired (but don't quote me on that, I haven't tried it but it should be simple to try so check it for yourself). Otherwise you can just call your game variable inside your blink function directly, something like yourgame.game.time.events should work - depends on your structure.

 

Share this post


Link to post
Share on other sites

Hi @AzraelTycka

Thank you for your help! I think I'm the idiot who should proofread what he writes lol.

You're completely right, the last two line should be in the loop, after the function - I think I need to sleep more haha.

I really appreciate your help and tips!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.