Hugbot

Draggable Body Lagging

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

Share this post


Link to post
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;};

Share this post


Link to post
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;  }};

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.