Jump to content

Draggable Body Lagging


Hugbot
 Share

Recommended Posts

Hello there. Been playing with Phaser, it's pretty cool. Not sure if this has been asked before, I tried fairly hard in order to answer this on my own.

 

I have a sprite (a space ship) that has has had input.enableDrag set for it. This works without issue.

I have also enabled arcade physics. Which also work fine.

 

The issue here is that when I drag the sprite the body associated with the sprite, the body lags behind on movement. This creates an interesting "race condition" where the body is updating to the position that the sprite actually is at, and in turn is having the wrong collision location being checked.

 

I'm not quite sure how to fix this. Are there any suggested work arounds or ways to fix this?

post-8124-0-24797700-1397242402.png

Link to comment
Share on other sites

Rich,
 
Thank you so much for taking the time to respond to this question. I really appreciate the input you provided, however, by default my Ship "class" already disabled the moves property for the body portion of the sprite.
 
Is there something else that could be contributing to this?

 

Below is my class declaration for the ship.

Ship = function(x, y) {  //Object configurations  // self = this;  this.imageName = 'rocket';  this.fakeStartY = 0;  this.fakeEndY = -1000;  this.fakeVelocityY = 0;  this.fakeAccelerationY = 1;  this.distanceTravelledY = 0;  this.playerPressingShip = false;  this.shipMaxYVelocity = 10;  this.numberOfHitsCanTake = 10000;  //Phaser creation  Phaser.Sprite.call(this, game, x, y, this.imageName);  //Phaser Configurations  this.anchor.setTo(0.5, 0.5);  this.inputEnabled = true;  this.alive = true;  game.add.existing(this);  game.physics.enable(this, Phaser.Physics.ARCADE);  this.input.enableDrag();  this.input.allowVerticalDrag = false;  this.body.collideWorldBounds = true;  this.body.moves = false;  this.body.immovable = true;  this.body.bounce.set(0);};Ship.prototype = Object.create(Phaser.Sprite.prototype);Ship.prototype.constructor = Ship;Ship.prototype.update = function() {  this.detectPlayerInput();  this.performFakePhysicsStep();  if(this.numberOfHitsCanTake == 0) {    this.body.velocity.setTo(0,0);    this.kill();    this.destroy();  }};Ship.prototype.detectPlayerInput = function() {  if((game.input.mousePointer.isDown || game.input.pointer1.isDown)     && Phaser.Rectangle.contains(this.body, game.input.worldX, game.input.worldY)) {    this.playerPressingShip = true;  }  else {    this.playerPressingShip = false;  }};Ship.prototype.performFakePhysicsStep = function() {  if(this.playerPressingShip) {    this.body.velocity.y += this.fakeAccelerationY;    if(this.body.velocity.y > this.shipMaxYVelocity) {      //console.log("derp");      this.body.velocity.y = this.shipMaxYVelocity;    }  }  else {    this.body.velocity.y -= (this.fakeAccelerationY*.5);    if(this.body.velocity.y < 0) {      this.body.velocity.y = 0;    }  }  this.distanceTravelledY += this.body.velocity.y;};
Link to comment
Share on other sites

Hey Rich,

 

In order to provide more information I'm attaching the main state script I'm using for gameplay.

var playerShip;function Play() {  //var self = this;  this.background;  this.playerShip;  this.shipStartX = 380;  this.shipStartY = 500;  //0 - randomly generating along x, with random 15 degree angles, at random speeds  //1 - generating a line  //2 - generating a sin wave  this.asteroidGenerationType = 0;  this.asteroidGenerationTimer = 0;  this.asteroidGenerationTimeLimit = 50;  this.asteroidGenerationTypeIsRandom = false;  this.asteroidTimerIsRandom = false;  this.asteroidTimerRandomMin = 30;  this.asteroidTimerRandomMax = 60;  this.asteroidMinRotation = 225;  this.asteroidMaxRotation = 315;  this.asteroidDefaultSpeed = 100;};Play.prototype = {  preload: function() {    game.load.image('asteroid', 'images/asteroid_1.png');    game.load.image('starfieldBackground', 'images/Starfield.png');    game.load.image('rocket', 'images/white_rocket.png');    game.load.spritesheet('explosion', 'images/cartoon_explosion.png', 283, 237, 10);  },  create: function() {    game.world.setBounds(0,0,800,600);    game.physics.startSystem(Phaser.Physics.ARCADE);    //-------------------------------------------------------------------------    this.background = game.add.tileSprite(0,0,800,600,'starfieldBackground')    //-------------------------------------------------------------------------    playerShip = new Ship(this.shipStartX, this.shipStartY);    this.playerShip = playerShip;    game.camera.follow(this.playerShip, Phaser.Camera.FOLLOW_LOCKON);    //-------------------------------------------------------------------------    asteroidGroup = game.add.group();    this.asteroidGroup = asteroidGroup;    this.asteroidGroup.enableBody = true;    //    var style = { font: "52px Arial", fill: "#ffffff", align: "center" };    this.gameOverText = game.add.text(game.world.centerX, game.world.centerY-100, "Game Over!\nWould you like to play again?", style);    this.gameOverText.anchor.set(0.5);  },  render: function() {    // game.debug.spriteBounds(this.playerShip);    game.debug.body(this.playerShip);    for(var i = 0; i < this.asteroidGroup.children.length; i++) {      // game.debug.spriteBounds(asteroidGroup.children[i]);      game.debug.body(asteroidGroup.children[i]);    }    // game.debug.spriteInfo(playerShip, 32, 32);    //game.debug.spriteInfo(asteroid, 32, 32);    game.debug.text("Distance Travelled: " + this.playerShip.distanceTravelledY, 500, 32);    game.debug.text("Asteroid Generation Timer: " + this.asteroidGenerationTimer, 450, 64);  },  update: function() {    // if(game.input.keyboard.isDown(Phaser.Keyboard.M)) {    //   this.generateExplosion(200, 200);    // }    if(!this.playerShip.alive) {      //console.log("player is dead");      this.gameOverText.visible = true;    }    else {      this.gameOverText.visible = false;    }    game.physics.arcade.collide(this.asteroidGroup, this.asteroidGroup);    game.physics.arcade.collide(this.playerShip, this.asteroidGroup, this.performShipCollisionWithAsteroidLogic, null, this);    this.changeAsteroidGroupsSpeedRelativeToShip();    this.performAsteroidGenerationLogic();    this.moveTileBackgroundBasedOnShipVelocity(this.playerShip);    this.modifyAsteroidGroupSpeedBasedOnShipVelocity(this.asteroidGroup, this.playerShip);    this.performAsteroidDestroyCheck();  },  performShipCollisionWithAsteroidLogic: function(player, asteroid) {    this.generateExplosion(asteroid.x, asteroid.y);    asteroid.destroy();    player.numberOfHitsCanTake -= 1;  },  generateExplosion: function(x,y) {    var explosion = game.add.sprite(x, y, 'explosion', 5);    animation = explosion.animations.add('explode');    explosion.animations.play('explode', 25, false);    explosion.anchor.setTo(.5,.5);    explosion.scale.setTo(.5,.5);    animation.onComplete.add(function() { explosion.kill(); }, this);  },  changeAsteroidGroupsSpeedRelativeToShip: function() {    for(var i = 0; i < this.asteroidGroup.children.length; i++) {      if(this.playerShip.body.velocity.y == 0) {        this.asteroidGroup.children[i].asteroidDefaultSpeed = 300;      }      else {        this.asteroidGroup.children[i].asteroidDefaultSpeed = 100;      }    }  },  performAsteroidDestroyCheck: function() {    for(var i = 0; i < asteroidGroup.children.length; i++) {      asteroidGroup.children[i].performDestroyLogic(this.playerShip);    }  },  performAsteroidGenerationLogic: function() {    this.asteroidGenerationTimer += 1;    if(this.asteroidGenerationTimer > this.asteroidGenerationTimeLimit) {      var leftBounds = game.camera.world.x;      var rightBounds = game.camera.world.x + game.camera.width;      var startYGeneration = game.camera.y - 50;      if(this.asteroidGenerationType == 0) {        for(var i = 0; i < (Math.floor(Math.random()*4) + 4); i++) {          var selectedPositionX = (Math.random() * (rightBounds - leftBounds));          var selectedRotaion = this.selectRandomNumberInRangeWithIncrement(225,315,15);          var topLineBound = 300;          var bottomLineBound = 10;          var selectedPositionY = game.camera.world.y - (Math.random() * (topLineBound - bottomLineBound));          this.generateAsteroidInGroup(asteroidGroup, selectedPositionX, selectedPositionY, selectedRotaion, this.asteroidDefaultSpeed);        }      }      else if(this.asteroidGenerationType == 1) {        var topLineBound = 300;        var bottomLineBound = 10;        var startY = game.camera.world.y - (Math.random() * (topLineBound - bottomLineBound));        var endY = game.camera.world.y - (Math.random() * (topLineBound - bottomLineBound));        var numberOfAsteroidsToGenerate = Math.floor(Math.random() * 8);        var generateSameAngle = Math.floor(Math.random() * 2);        this.generateAsteroidGroupLine(asteroidGroup,                                       game.camera.world.x,                                       (game.camera.world.x + game.camera.world.width),                                       startY,                                       endY,                                       numberOfAsteroidsToGenerate,                                       generateSameAngle);      }      else if(this.asteroidGenerationType == 2) {      }      else {        console.log("asteroid generation type not anticipated");      }      this.asteroidGenerationTimer = 0;      //Resets the generation type settings      if(this.asteroidGenerationTypeIsRandom) {        this.asteroidGenerationType = Math.floor(Math.random()*2);        if(this.asteroidGenerationType == 0) {          this.asteroidTimerIsRandom = false;          this.asteroidGenerationTimeLimit = 30;        }        else if(this.asteroidGenerationType == 0) {          this.asteroidTimerIsRandom = true;          this.asteroidTimerRandomMin = 30;          this.asteroidTimerRandomMax = 50;        }      }      //Resets the timer settings      if(this.asteroidTimerIsRandom) {        var newTimeOffset = Math.random() * (this.asteroidTimerRandomMax - this.asteroidTimerRandomMin)        this.asteroidGenerationTimeLimit = this.asteroidTimerRandomMin + newTimeOffset;      }    }  },  generateAsteroidGroupLine: function(groupToAddTo, startX, EndX, startY, EndY, numberOfAsteroidsToGenerate, generateSameAngle ) {    var xStepSize = (EndX - startX)/numberOfAsteroidsToGenerate;    var yStepSize = (EndY - startY)/numberOfAsteroidsToGenerate;    var currentX = startX;    var currentY = startY;    var startingAngle = this.selectRandomNumberInRangeWithIncrement(225,315,15);    for(var i = 0; i < numberOfAsteroidsToGenerate; i++) {      if(!generateSameAngle) {        startingAngle = this.selectRandomNumberInRangeWithIncrement(225,315,15);      }      var new_asteroid = new Asteroid(currentX, currentY);      new_asteroid.fireBasedOnAngle(startingAngle, this.asteroidDefaultSpeed);      groupToAddTo.add(new_asteroid);      //console.log(currentY);      currentX += xStepSize;      currentY += yStepSize;    }  },  generateAsteroidInGroup: function(groupToAddTo, startX, startY, startingAngle, startingSpeed) {    var new_asteroid = new Asteroid(startX, startY);    new_asteroid.fireBasedOnAngle(startingAngle, startingSpeed);    groupToAddTo.add(new_asteroid);  },  modifyAsteroidGroupSpeedBasedOnShipVelocity: function(asteroidGroup, ship){    for(var i=0; i < asteroidGroup.children.length; i++) {      this.modifyAsteroidSpeedBasedOnShipVelocity(asteroidGroup.children[i], ship);    }  },  modifyAsteroidSpeedBasedOnShipVelocity: function(asteroid, ship) {    asteroid.x += ship.body.velocity.x;    asteroid.y += ship.body.velocity.y;  },  moveTileBackgroundBasedOnShipVelocity: function(ship) {    this.background.tilePosition.y += ship.body.velocity.y;  },  selectRandomNumberInRangeWithIncrement: function(rangeStart, rangeEnd, incrementStep) {    var numberOfIndices = ((rangeEnd - rangeStart)/incrementStep)+1;    var randomNum = (((Math.floor(Math.random()*numberOfIndices))*incrementStep)+rangeStart);    return randomNum;  }};
Link to comment
Share on other sites

Not sure if anyone else has taken a look at this, but i've managed to sort of resolve the issue with this bit of code being applied in the update function.

//cludgy fix for draggable body laggingthis.playerShip.body.x = this.playerShip.world.x - this.playerShip.width/2;this.playerShip.body.y = this.playerShip.world.y  - this.playerShip.height/2;

I'm not thrilled with the solution, so I'd be more than happy to hear any alternative suggestions to this fix as it still lags behind the sprite just a bit.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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