Jump to content
This forum will be closing down. Please move to the respective dedicated project forums.

Triggering of sprites/obstacles falling randomnly


kriket
 Share

Recommended Posts

So I have a group of sprites/obstacles that are placed at the top of the world to start with. Once player enters/overlaps a trigger zone, a trigger function is called which makes the obstacles fall. But the obstacles fall randomly and there's a 2 second delay before another random obstacle falls.
 
I got as far as grabbing a random child.alive, but how can I keep going through the obstacleGroup until all alive children have been dealt with. Randomly, of course. I know there's a forEach method with every group, but dont know how I can implement in this situation.
 
    obstacleTrigger: function() {            Phaser.Math.getRandom(this.obstacleGroup.children.filter(function(child) {                if(child.alive) {                     /*  wait 2 seconds before falling  */                    if(this.nextShot > this.time.now){return;} // too early                                        /* make shot */                    child.body.kinematic = false;       /* (every child is immovable to start with (using p2 physics, kinematic = true), and make kinematic = false drops its under global gravity of p2, and once it overlaps floor, I call child.kill() in other function) */                    this.nextShot = this.time.now + 2000; // wait at least 2 seconds (2000ms) to next shot                }            }));            },

 

Link to comment
Share on other sites

Caveat: I have absolutely no experience using p2 whatsoever.

 

Why not make this an emitter, instead? Emitters have all the code for timing and killing and you could customize it further with a custom particle class. Emitters have a maximum number of particles that they emit, as well. Would that work?

Link to comment
Share on other sites

Caveat: I have absolutely no experience using p2 whatsoever.

 

Why not make this an emitter, instead? Emitters have all the code for timing and killing and you could customize it further with a custom particle class. Emitters have a maximum number of particles that they emit, as well. Would that work?

 

Emitter would be my last resort mate since I wait to avoid activating different systems throughout the game. Targetting mobile, and dont think emmiter's are quite what I am after. But innovative suggestion nonetheless ;)

 

 

Couldn't you do use the "countLiving" property? Like : 

obstacleTrigger: function() {  while(this.obstacleGroup.countLiving !== 0){    Phaser.Math.getRandom(this.obstacleGroup.children.filter(function(child) {    ....  }        },

 

I think this could work. 

 

 

I ran into a issue in my code below. Console is giving me "Uncaught TypeError: Cannot read property 'now' of undefined" for this line                     

if(this.nextShot > this.time.now) {
Full code block:
        while(this.obstacleGroup.countLiving !== 0){            Phaser.Math.getRandom(this.obstacleGroup.children.filter(function(child) {                if(child.alive) {//                    wait 1-3 seconds before falling                    if(this.nextShot > this.time.now) {                        return;                    } // too early                                        /* make shot */                    child.body.kinematic = false;                    this.nextShot = this.time.now + 1000; // wait at least 1 second (1000ms) to next shot                }        }));        }
Link to comment
Share on other sites

Hello,

 

phaser docs say that getRandom is deprecated so I'm not sure if I would use it because with future phaser versions there might not be this function at all.

 

Btw you can always go with simple reference.

var array =  [0, 1, 2, 3, 4];  // positions in your group of living bodiesfor (var i = 0; i < array.length; i++ ) {    var index = array[getRandomIntInRange(0 to 4)];    functionDoSomethingWithYourGroup(yourGroup[index]);    array.splice(index, 1);}

Or if you don't want to use timed events for all your bodies you can go instead of for loop with simple function and call it every time your 2 seconds are finished.

Link to comment
Share on other sites

Try this.game.time.now

 

didnt work mate. The problem is related to anonymous function. Anyway, better at javascript than me, can help me resolve this pls? Reading up more on anonymous functions and how to provide context to them. I had read up on this ages ago. 

Link to comment
Share on other sites

Hello,

 

phaser docs say that getRandom is deprecated so I'm not sure if I would use it because with future phaser versions there might not be this function at all.

 

Btw you can always go with simple reference.

var array =  [0, 1, 2, 3, 4];  // positions in your group of living bodiesfor (var i = 0; i < array.length; i++ ) {    var index = array[getRandomIntInRange(0 to 4)];    functionDoSomethingWithYourGroup(yourGroup[index]);    array.splice(index, 1);}

Or if you don't want to use timed events for all your bodies you can go instead of for loop with simple function and call it every time your 2 seconds are finished.

 

thanks for letting me know thats deprecated now. I am trying out your way instead. Will post results asap.

Link to comment
Share on other sites

Thanks a lot guys. Just getting the final code block ready using what @AzraelTycka suggested above since getRandom method is deprecated. But now I know how to bind and sort the scope out of anonymous functions properly. Many thanks. Will update soon on the code. 

Link to comment
Share on other sites

Hello,

 

phaser docs say that getRandom is deprecated so I'm not sure if I would use it because with future phaser versions there might not be this function at all.

 

Btw you can always go with simple reference.

var array =  [0, 1, 2, 3, 4];  // positions in your group of living bodiesfor (var i = 0; i < array.length; i++ ) {    var index = array[getRandomIntInRange(0 to 4)];    functionDoSomethingWithYourGroup(yourGroup[index]);    array.splice(index, 1);}

Or if you don't want to use timed events for all your bodies you can go instead of for loop with simple function and call it every time your 2 seconds are finished.

 

 

 

 

I am getting an error message. agWB4E2.png

    rockTrigger: function() {        var array =  [0, 1, 2, 3, 4];  // positions in your group of living bodies                while(this.rocks.countLiving !== 0){            for (var i = 0; i < array.length; i++ ) {                var index = array[getRandomIntInRange(0, 4)];            }            this.game.time.events.add(Phaser.Timer.SECOND * 2, this.rockFall(this.rocks[index]), this);            array.splice(index, 1);        }    },            rockFall: function(child) {        child.body.kinematic = false;    },

PS - I have learnt so much today. It feels awesome! Many thanks to such an amazing community.

Link to comment
Share on other sites

Thanks Skeptron.                 

var index = this.game.rnd.integerInRange(0, 4); 

also does the trick.

 

 

 

 

 

Anyway, onto something very important and strange. 

 

Check this out = http://testing9.site44.com/

 

Clicking on right, moves player right. Clicking on left of the screen, moves player left, clicking in middle = jump.

 

But notice, how when you collide with what was supposed to be the trigger (first rock), the player just stops responding. 

No errors in console. Ziltch.

 

Code here - https://www.dropbox.com/sh/fvuvfqa2hy9c4ad/AABzx1GHlhRrWpBZEd2fohTna?dl=0

Try running it in Brackets pls. Getting images loaded onto jsbin is something I have to learn and I am short on time atm so pls bare with me. Did I say, I am only playing with JS now   :)

 

 

Although, game.js is short, the code that concerns us is:

 

 

  create: function() {    this.game.physics.p2.setImpactEvents(true);    this.game.physics.p2.restitution = 0.5;    this.game.physics.p2.gravity.y = 300;    this.playerCollisionGroup = this.game.physics.p2.createCollisionGroup();    this.triggerCollisionGroup = this.game.physics.p2.createCollisionGroup();    this.rocksCollisionGroup = this.game.physics.p2.createCollisionGroup();        // TRIGGER for rocks fall    this.trigger = this.game.add.group();    this.trigger.enableBody = true;    this.trigger.physicsBodyType = Phaser.Physics.P2JS;    this.trigger.create(200, 500, 'rock1');          for(var i = 0; i < this.trigger.children.length; i++){            this.trigger.children[i].body.kinematic = true;            this.trigger.children[i].body.setCollisionGroup(this.triggerCollisionGroup);            this.trigger.children[i].body.collides([this.triggerCollisionGroup, this.playerCollisionGroup]);    }          // ROCKS    this.rocks = this.game.add.group();    this.rocks.enableBody = true;    this.rocks.physicsBodyType = Phaser.Physics.P2JS;          this.rocks.create(500, 100, 'rock2');    this.rocks.create(650, 300, 'rock2');    this.rocks.create(400, 300, 'rock2');    for(var i = 0; i < this.rocks.children.length; i++){            this.rocks.children[i].body.kinematic = true;            this.rocks.children[i].body.setCollisionGroup(this.rocksCollisionGroup);            this.rocks.children[i].body.collides([this.rocksCollisionGroup, this.playerCollisionGroup]);    }    this.player.body.setCollisionGroup(this.playerCollisionGroup);    this.player.body.collides(this.triggerCollisionGroup, this.rockTrigger, this);    this.player.body.collides(this.rocksCollisionGroup, this.gameOver, this);        },    
 
 
 
    rockTrigger: function() {        var array =  [0, 1, 2, 3, 4];  // positions in your group of living bodies                while(this.rocks.countLiving !== 0){            for (var i = 0; i < array.length; i++ ) {                var index = this.game.rnd.integerInRange(0, 4);            }            this.game.time.events.add(Phaser.Timer.SECOND * 2, this.rockFall(this.rocks[index]), this);            array.splice(index, 1);        }    },            rockFall: function(child) {//        child.body.kinematic = false;    },
Link to comment
Share on other sites

I'm really not familiar with P2JS and your way of creating groups and collisions, but what I found is that if you look at the Debug plugin (GG for using it, btw), you'll find that Rock1 is not in the same group as the other Rocks. That would explain that this very particular rock has a different behaviour (the crash).

 

EDIT : ok now I see you're just creating one child for this group. Why iterate over its length then? For future changes?

Link to comment
Share on other sites

I'm really not familiar with P2JS and your way of creating groups and collisions, but what I found is that if you look at the Debug plugin (GG for using it, btw), you'll find that Rock1 is not in the same group as the other Rocks. That would explain that this very particular rock has a different behaviour (the crash).

 

Yeah, as you can see from the code, trigger rock group is separate from the rocks that fall. TBH I would use another image for trigger but its was just a quick hack with the same rock image. The reason for separate group for trigger and other rocks is obviously cos on overlap, different functions will be called depending on what collided with what. I have to group everything cos player is grouped and when all the assets in my game are grouped, I dodnt think I will run into any glitches that arise from sprite VS group collisions. 

 

All I do is from the official tuts and examples. I am still learning p2 physics myself.

Link to comment
Share on other sites

And careful, the brackets of your for loop are poorly placed:

for (var i = 0; i < array.length; i++ ) {                var index = this.game.rnd.integerInRange(0, 4);            }            this.game.time.events.add(Phaser.Timer.SECOND * 2, this.rockFall(this.rocks[index]), this);            array.splice(index, 1);

Rock creation should be within the loop, just as array.splice

Link to comment
Share on other sites

Ok I think I found an issue : countLiving() is a method, not a property. Add the parenthesis.

 

And when it crashes like that, put breakpoints so that you can debug until crash point.

 

skeptron, I changed it to 

        while(this.rocks.countLiving() !== 0){
but still same issue. Player just freezes, no movement when clicking, and no errors. 
Link to comment
Share on other sites

And careful, the brackets of your for loop are poorly placed:

for (var i = 0; i < array.length; i++ ) {                var index = this.game.rnd.integerInRange(0, 4);            }            this.game.time.events.add(Phaser.Timer.SECOND * 2, this.rockFall(this.rocks[index]), this);            array.splice(index, 1);

Rock creation should be within the loop, just as array.splice

 

 

Rock creation? Where am I creating them? Can u pls elaborate? Srry, I know I have been a pain, but if I solve this, today would be legendary in terms of knowledge gained about phaser and JS. 

Link to comment
Share on other sites

Well, didin't think it needs to be pointed out. I used overally descriptive names for function calls to make sure that you cna understand what is that function supposed to do but you still need to make them on your own, that wasn't important in my suggestion after all ;-).

lol, yes. APIs and libraries all over the web nowadays, didnt think it was pseudocode. Helped a lot still. thx

Link to comment
Share on other sites

And careful, the brackets of your for loop are poorly placed:

for (var i = 0; i < array.length; i++ ) {                var index = this.game.rnd.integerInRange(0, 4);            }            this.game.time.events.add(Phaser.Timer.SECOND * 2, this.rockFall(this.rocks[index]), this);            array.splice(index, 1);

Rock creation should be within the loop, just as array.splice

 

you're right skeptron . Let me fix that and see if it works.

PS - I also think I have an infinite loop running. Let me debug and return if I still cant fix it. Am grateful for all the support.

Link to comment
Share on other sites

btw that random integer in range 0 to 4 was for that specific array which had length 5 [0, 1, 2, 3, 4], so if you are pointing to some larger array don't forget to adjust the numbers, in generall you can go with rndIntInRange(0, array.length - 1); as long as your array which you are pointing to is continuos (all alive bodies in the original array are as this: var orgArr = [b0, b1, b2, b3, b4]; and so on - where bX is an object for example, then you are referencig to this with your var array = [0, 1, 2, 3, 4]; in case orgArr  has more elements you need to extend your array as well - it's very simple to do it with one loop, no need to type it by hand.

 

If your array isn't continuous but is more like this: var orgArr = [b0, b1, dead, b3, dead, b5]; then probably easisest is to sort orgArr to [b0, b1, b3, b5, dead, dead] and change rndIntInRange(0, array.length - 1); to rndIntInRange(0, orgArr.countTotalLivingBodies - 1);

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...