简体   繁体   中英

How to reverse platform generation in Phaser game?

I am creating an endless runner. At the moment when the left arrow key is pressed the player moves left, the camera follows him and the ground tiles below the player are destroyed as they move out of the world bounds on the right and are recreated just before they move into the world bounds on the left. This allows him to keep running forever without running out of ground. My code works perfectly, but with one problem: I want the player to be running to the right of the game, NOT to the left. Please note I do not need the player to be able to move both ways. I can make the camera follow the player to the right instead of the left by doing the following: I remove the negative from -this in

this.world.setBounds(-this.player.yChange, 0, ...);

so it becomes

this.world.setBounds(this.player.yChange, 0, ...);

Now when the right arrow key is pressed the camera follows the player as he runs right, but the ground tiles do not regenerate and he runs out of ground. So basically I need to reverse the direction in which the ground is regenerating but I can't figure out how to do it. As everything is working to the left, I am sure it's a few simple settings, perhaps some negatives that need to be made positive? I have been on this for days and can't figure it out. Is anyone able to see an obvious solution? I'd be so grateful.

My code is below, or see the codepen link: https://codepen.io/clownhead/pen/BqyqOm

    var Jumper = function() {};
Jumper.Play = function() {};

Jumper.Play.prototype = {

  preload: function() {
    this.load.image( 'hero', 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/836/dude.png' );
    this.load.image( 'pixel', 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/836/pixel_1.png' );
  },

  create: function() {
    // background color
    this.stage.backgroundColor = '#6bf';

    // scaling
    this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
    this.scale.maxWidth = this.game.width;
    this.scale.maxHeight = this.game.height;
    this.scale.pageAlignHorizontally = true;
    this.scale.pageAlignVertically = true;
    this.scale.setScreenSize( true );

    // physics
    this.physics.startSystem( Phaser.Physics.ARCADE );

    // camera and platform tracking vars
    this.cameraXMin = 99999;
    this.platformXMin = 99999;

    // create platforms
    this.platformsCreate();

    // create hero
    this.heroCreate();

    // cursor controls
    this.cursor = this.input.keyboard.createCursorKeys();
  },

  update: function() {
    // this is where the main magic happens
    // the x offset and the width of the world are adjusted
    // to match the furthest point the hero has reached
    this.world.setBounds(-this.hero.xChange, 0, this.world.width + this.hero.xChange, this.game.height);

    // the built in camera follow methods won't work for our needs, we create a custom one

    this.cameraXMin = Math.min( this.cameraXMin, this.hero.x - this.game.width + 130 );
    this.camera.x = this.cameraXMin;

    // hero collisions and movement
    this.physics.arcade.collide( this.hero, this.platforms );
    this.heroMove();

     // these are pooled so they are very performant
    this.platforms.forEachAlive( function( elem ) {
      this.platformXMin = Math.min( this.platformXMin, elem.x );
      if( elem.x > this.camera.x + this.game.width ) {
        elem.kill();
        this.platformsCreateOne( this.platformXMin - 70, this.world.height - 50, 50 );
      }
    }, this );
  },

  shutdown: function() {
    // reset everything, or the world will be messed up
    this.world.setBounds( 0, 0, this.game.width, this.game.height );
    this.cursor = null;
    this.hero.destroy();
    this.hero = null;
    this.platforms.destroy();
    this.platforms = null;
  },

  platformsCreate: function() {
    // platform basic setup
    this.platforms = this.add.group();
    this.platforms.enableBody = true;
    this.platforms.createMultiple( 10, 'pixel' );

    // create a batch of platforms that start to move across the level
    for( var i = 0; i < 9; i++ ) {
      this.platformsCreateOne( this.world.width - 70 - 70 * i, this.world.height - 50, 50);
    }
  },

  platformsCreateOne: function( x, y, width ) {
    // this is a helper function since writing all of this out can get verbose elsewhere
    var platform = this.platforms.getFirstDead();
    platform.reset( x, y );
    platform.scale.x = width;
    platform.scale.y = 16;
    platform.body.immovable = true;
    return platform;
  },

  heroCreate: function() {
    // basic hero setup
    this.hero = game.add.sprite( this.world.centerX, this.world.height - 69, 'hero' );
    this.hero.anchor.set( 0.5 );

    // track where the hero started and how much the distance has changed from that point
    this.hero.xOrig = this.hero.x;
    this.hero.xChange = 0;

    // hero collision setup
    // disable all collisions except for down
    this.physics.arcade.enable( this.hero );
    this.hero.body.gravity.y = 500;
    this.hero.body.checkCollision.up = false;
    this.hero.body.checkCollision.left = false;
    this.hero.body.checkCollision.right = false;
  },

  heroMove: function() {
    // handle the left and right movement of the hero
    if( this.cursor.left.isDown ) {
      this.hero.body.velocity.x = -400;
    } else if( this.cursor.right.isDown ) {
      this.hero.body.velocity.x = 400;
    } else {
      this.hero.body.velocity.x = 0;
    }

    // handle hero jumping
    if( this.cursor.up.isDown && this.hero.body.touching.down ) {
      this.hero.body.velocity.y = -350;
    } 

    // wrap world coordinated so that you can warp from top to bottom
    this.world.wrap( this.hero, this.hero.width / 2, false );

    // track the maximum amount that the hero has travelled
    this.hero.xChange = Math.max( this.hero.xChange, Math.abs( this.hero.x - this.hero.xOrig ) );

  }
}

var game = new Phaser.Game( 500, 300, Phaser.CANVAS, '' );
game.state.add( 'Play', Jumper.Play );
game.state.start( 'Play' );

So the relevant bit of your code is essentially this:

this.camera.x = this.cameraXMin;

If we look at how the code is behaving, it's keeping track of the where the hero is, and then taking into account where the hero was.

this.cameraXMin = Math.min( this.cameraXMin, this.hero.x - this.game.width + 130 );

This works great as long as the hero is moving to the left, since x keeps getting smaller. However, once you start moving to the right, where they first started (say 0) will always be lower than where they go (which will get higher and higher).

So, instead of tracking the Math.min you need the Math.max . You'll need to refactor your code more than this, but making the following tweaks will get you along the right path.

In create you'll have to set a better default:

// Instead of setting this to a high number, I would start it where the camera starts. Or just set it to 0.
this.cameraXMin = this.camera.x;

Now in your update , have it Math.max :

this.cameraXMin = Math.max( this.cameraXMin, this.hero.x - this.game.width + 130 );

Your platform code will also need to be changed, but the above should give you an idea of what would need to be changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM