anthkris

Correct Player Position

Recommended Posts

Howdy all,

I have another question. I'm making an endless runner with the method of moving the tiles to the left and assigning the player an equal and opposite velocity so that it stays in the same place. The problem is that the player doesn't stay in the same place. I've added a velocity of 0 on jump, so the problem isn't that the player is jumping forward. There are just almost imperceptible little movements (I've logged out the player.x during the course of the game and it will move back and forth 5 or 10 pixels) which sometime snowball into big issues where the player hits the left edge of the screen. I haven't been able to isolate the root cause of the problem.

The player can collect coins, hearts, and can hit enemies, however, I'm checking overlap on each of these, not collide.

Here is the update function in my Game.js:

update: function() {
    
    /* COLLISION WITH POOLS */
    if (this.player.alive) {
      this.platformPool.forEachAlive(function(platform, index) {
        this.game.physics.arcade.collide(this.player, platform, this.hitWall, null, this);
        this.enemiesPool.forEachAlive(function(enemy, index) {
          this.game.physics.arcade.collide(enemy, platform);
        }, this);
        
        // update floor tile speed constantly
        platform.forEach(function(floor) {
          floor.body.velocity.x = -this.levelSpeed;
        }, this);
        
        //check if platform needs to be killed
        if(platform.length && platform.children[platform.length - 1].right < 0) {
          platform.kill();
        }
      }, this);
      
      // update coin and life sprite speed constantly
      this.coinsPool.forEachAlive(function(coin) {
         coin.body.velocity.x = -this.levelSpeed;
      }, this);
      
      this.lifePool.forEachAlive(function(life) {
          life.body.velocity.x = -this.levelSpeed;
      }, this);
      
      this.game.physics.arcade.overlap(this.player, this.coinsPool, this.collectCoin, null, this);
      this.game.physics.arcade.overlap(this.player, this.lifePool, this.collectLife, null, this);
      this.game.physics.arcade.overlap(this.player, this.enemiesPool, this.hurtPlayer, null, this);
      this.game.physics.arcade.collide(this.enemiesPool, this.projectilesPool, this.killEnemy, null, this);
      
      
      this.processDelayedEffects();
      
      /* CHECK PLAYER BOOLEANS */
      if (this.player.body.touching.down && !this.isHit && !this.isShooting) {
        this.player.play('running');
        this.player.body.velocity.x = this.levelSpeed;
      }
      
      if (!this.player.body.touching.down) {
        this.player.body.velocity.x = 0;
      }
      
      if (!this.player.body.touching.down && this.isJumping) {
        //if up in the air
        //console.log('player is in the air');
        
        //this.player.x = 400;
        this.canShoot = true;
      }
      
      if (this.isShooting && this.player.body.touching.down) {
        //if shooting
        this.isShooting = false;
        this.player.body.velocity.x = this.levelSpeed;
      } 
      
      /* CONTROLS */
      if(this.cursors.up.isDown || this.game.input.activePointer.isDown){
        this.playerJump();
      } else if (this.cursors.up.isUp || this.game.input.activePointer.isUp) {
        this.isJumping = false;
      }
      if(this.spaceKey.isDown){
        this.shoot();
      }

      /* PLATFORM CREATION */
      //if the last sprite in the platform group is showing, then create a new platform
      //console.log(this.currentPlatform.children);
      if(this.currentPlatform.length && this.currentPlatform.children[this.currentPlatform.length - 1].right < this.game.world.width) {
        this.createPlatform();
      }
      
      /* KILL SWITCH */
      //kill coins that leave the screen
      this.coinsPool.forEachAlive(function(coin){
        if (coin.right <= 0){
          coin.kill();
        }
      }, this);
      
      //kill enemies that leave the screen
      this.enemiesPool.forEachAlive(function(enemy){
        if (enemy.right <= 0 || enemy.left <= 200){
          enemy.kill();
        }
      }, this);
    
    }
    
    /* ALLOW ENEMIES TO REMAIN ON PLATFORMS AFTER DEATH  */
    this.platformPool.forEachAlive(function(platform, index){
        this.enemiesPool.forEachAlive(function(enemy, index){
          this.game.physics.arcade.collide(enemy, platform);
        }, this);
      }, this);
    
    /* CHECK IF PLAYER NEEDS TO DIE */
    if(this.player.top >= this.game.world.height || this.player.left <= 0 || this.myLivesLeft <= 0) {
      //alpha doesn't work when bitmapData sprite is continuously redrawn
      //so only run gameOver once
      this.player.play('dying');
      this.playerLives.destroy(true, true);
      this.speedUpTimer.destroy();
      this.nextLevelTimer.timer.destroy();
      if(this.gameOverCounter <= 0) {
        this.gameOver();
        this.gameOverCounter++;
      }
      
    }
  },

Any suggestions would be appreciated!

Share this post


Link to post
Share on other sites

I had the similar issue with Caveman Grru. The player was suppose to be more or less in the middle of the screen and his velocity was matching the movement of everything in the opposite direction, but when it was staying behind (bug mentioned by you, or the player was stuck behind a terrain obstacle) too much, I was increasing his running speed (velocity) a bit, so he could move a little faster and reach the middle of the screen again.

Share this post


Link to post
Share on other sites

Physics systems are kinda indeterminate. They don't settle to steady states, they have little jiggles, all that stuff. This isn't a Phaser- or even JS-specific problem (for fun and profit add 0.1 and 0.2 in your favorite language and check the result). Your best bet is to rethink your approach. Instead of figuring out how to smooth those little jiggles, how could you avoid them completely?

What if the player wasn't *really* colliding with the platform, but floating above it because you know where the platforms are? Since there's only one player and you generally know where the enemies/coins are, you could collide them yourself by checking rectangle bounds. That kind of stuff. Alternately, throwing things at a static player while animating things to look like they're moving could work, too.

BTW, check out "outOfBoundsKill" on sprites -- they kill themselves when going out of the world. There's even an "outOfCameraBoundsKill".

Share this post


Link to post
Share on other sites

Thanks for the replies @end3r and @drhayes I was (sigh) thinking of actually scrapping the whole thing and trying a different infinite runner approach where only the player moves, based on the Create an Endless Runner book. But perhaps I can try the custom collision or readjusting the velocity first...

And, good point about the outOfBoundsKill. I could replace those kill functions with that.

Share this post


Link to post
Share on other sites

Just wanted to update here that I spent today looking at the Create a Procedural Endless runner book and, with relatively few code changes, I've changed the entire methodology of the structure from one where the platforms move to one where the player is the only element moving. This introduced a few new minor issues (such as positioning of certain sprites like the coin count and life count), but the major glitches appear to have been fixed!

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.