ChrisC14 Posted May 11, 2014 Share Posted May 11, 2014 I have a group of enemies that I loop through and perform various actions with, in my update loop. Basically it checks if each enemy in the group is either at a wall and should turn back, or at a ledge of a platform, and should either 1) turn back, 2) jump, 3) fall off the ledge. The problem I'm having is that nothing is working properly as the update of course happens 60 times a second, and it rapidly checks the conditions and makes decisions. My attempted solution is to attach a timer to each of the enemies in the group, and check if the timer is expired before attempting these actions. Then in the actions function I start the timer, which should run for a couple of seconds. The theory being that after taking an action, it should delay attempting again (per enemy) and by that time the enemy has moved on and the condition (at the ledge, etc.) has passed. I can't figure out a) if this possible and how to do it in Phaser. Since the timer object seems to require a callback, I thought I would make a callback function set/change a flag on the enemy that tracked if it could perform the action or not. I have code like this: Enemy creation: spawnSlime: function() { // create a new slime var yellowSlime = this.slimes.create(760 + Math.random() * 100, 70 + Math.random() * 60, 'medSlime'); yellowSlime.anchor.setTo(0.5, 0.5); yellowSlime.animations.add('slime-walk', [0, 1, 2, 4, 3, 2, 1, 0], 6, true); this.physics.arcade.enable(yellowSlime); this.physics.arcade.collide(yellowSlime, this.layer_world); yellowSlime.body.gravity.y = this.GRAVITY; yellowSlime.body.collideWorldBounds = true; yellowSlime.play('slime-walk'); yellowSlime.speed = -(Math.random() * 40); // create a timer for each slime yellowSlime.actionTimer = this.game.time.create(false); yellowSlime.actionTimer.loop(2000, function(){yellowSlime.actionReady=true;}, this); // ready for actions, which the timer will be used to provide a pause between actions yellowSlime.actionReady = true; yellowSlime.body.velocity.x = yellowSlime.speed; // console.log(yellowSlime.body.velocity.x); yellowSlime.slimeID = this.slimeCounter += 1; console.log('new slime ID: '+yellowSlime.slimeID) },As you can see I attempt to attach a timer to the slime there, and a callback anonymous function which changes the actionReady state. Here is the code for the slime actions: // slime actions this.slimes.forEach(function(thisSlime){ // collide all slimes with world this.physics.arcade.collide(thisSlime, this.layer_world); this.physics.arcade.overlap(thisSlime, this.lavas, this.lavaDamage, null, this); // Slime meets obstacle or ledge.. either turn back, fall off ledge, or jump console.log('actionReady: '+thisSlime.actionReady); if (thisSlime.actionReady) { if (thisSlime.body.blocked.down) { // slime is on the ground // don't check this slime again for 2 seconds thisSlime.actionReady = false; console.log('about to start timer'); thisSlime.actionTimer.start(); if (thisSlime.body.blocked.left) { // go right thisSlime.body.velocity.x = thisSlime.speed; } else if (thisSlime.body.blocked.right) { // go left thisSlime.body.velocity.x = -thisSlime.speed; } else if (this.tileGet(thisSlime, this.layer_world, 'right') == 0) { // slime on ledge, drops off to the right if ((Math.random() * 3) > 2) { // 1 in 3 chance to jump, otherwise fall off ledge // make slime jump thisSlime.body.velocity.y += 60; console.log('slime'+thisSlime.slimeID+' is jumping'); } else { thisSlime.body.velocity.x = -thisSlime.speed; console.log('slime'+thisSlime.slimeID+' is going back left'); } } else if (this.tileGet(thisSlime, this.layer_world, 'left') == 0) { // slime on ledge, drops off to the left if ((Math.random() * 3) > 2) { // 1 in 3 chance to jump, otherwise fall off ledge // make slime jump thisSlime.body.velocity.y += 60; console.log('slime'+thisSlime.slimeID+' is jumping'); } else { thisSlime.body.velocity.x = thisSlime.speed; console.log('slime'+thisSlime.slimeID+' is going back right'); } } else { // no conditions met, keep actionReady as true thisSlime.actionReady = true; } } }So this function checks the actionReady boolean, and then attempts the actions by first checking the conditions (at a wall or ledge). I have a tileGet function that checks what tile is beyond the ledge, which works. If at a wall it just turns around. However if at a ledge, it makes a random choice for turn back | jump | continue and fall off ledge. As mentioned the timer starting is supposed to change the condition for a couple of seconds so that the slime is not checking/making decision rapidly, canceling them out. I'm not getting an error here, but the slimes are just always falling off the ledge, and the condition seems to be rapidly checked, as if the timer isnt working, as evidenced by my console output: https://www.dropbox.com/s/minssx6l754g03k/Screenshot%202014-05-10%2022.23.36.png When I tried a function instead of an anonymous function, I would get an error. The call:yellowSlime.actionTimer.loop(2000, this.readyForAction(yellowSlime), this);and the function: readyForAction: function(entity) { entity.actionReady = true; },Any help would be appreciated. Keep in mind that I'm not an expert in javascript, I'm still learning, so there may well be js problems - and I'm not quite sure if/how the Phaser timer function can be used for this. thanksChris Link to comment Share on other sites More sharing options...
jpdev Posted May 11, 2014 Share Posted May 11, 2014 The way you set that up I would just get rid of the timer and do it this way: - remove all timer stuff (including the actionReady flag) - on slime creation dothis.actionTimestamp = 0;- instead of the actionReady check you check this:if (this.actionTimestamp < game.time.time) { this.actionTimestamp = game.time.time + 2000;//... your action logic here}Since game.time.time always is the current time in milliseconds, this way any time the slime takes an action, it notes the current time + 2000ms .. and only takes another action if the current time is bigger then this value. (So only if two seconds or 2000 milli seconds have elapsed). Link to comment Share on other sites More sharing options...
ChrisC14 Posted May 11, 2014 Author Share Posted May 11, 2014 You, Sir, are a genius. That sounds like a much better idea, which I'm going to try to implement now. Cheers. Link to comment Share on other sites More sharing options...
ChrisC14 Posted May 12, 2014 Author Share Posted May 12, 2014 It works - just one change I should mention, it turned out to be this.game.time.now (and not time.time). Link to comment Share on other sites More sharing options...
Recommended Posts