owen

How do I make a sprite immovable and impassable?

Recommended Posts

I want to have a sprite which to all intents and purposes behaves like a tile.  It is meant to be impassable by the player (or indeed other sprites) and does not move.  The player cannot pass through it nor can anything else.  It is like a solid brick wall.  It just sits there.

 

The only reason I want this to be a sprite - rather than a tile - is because at a certain point during the game I want to make it disappear gracefully with some animation.  (When player collects a key).

 

The problem I am getting is that although the sprite displays properly, it's not impassable.  When the player collides, it 'pushes' the sprite out of the way.

 

I have the following in my update() function:   (yellowPadlocks is the sprite group containing the wannabe-immovable sprite)

game.physics.arcade.collide(player, yellowPadlocks);

How do I simply put a sprite on the screen and make it immovable, solid, impassable and immovable by any other sprite including the player sprite?

 

The following seems to have absolutely no effect, though the console output confirms it's running the code.

 

spriteGroup.forEach(function (s) {            console.log("making padlock impassable");            s.immovable = true;            s.allowGravity = false;            s.body.gravity.x = 0;            s.body.gravity.y = 0;            s.body.velocity.x = 0;            s.body.velocity.y = 0;            s.body.enable = false;        }, this);

Any ideas what I am doing wrong?

 

Thanks

Owen

Share this post


Link to post
Share on other sites

I have exactly the same problem. I have a boat and I want my player to stand on the boat.

In the create() method where I add the sprite, I declare the following according to your code:

    this.boat = this.game.add.sprite(3700, 535, 'Boat');

    this.game.physics.arcade.enable(this.boat);

    this.boat.immovable = true;
    this.boat.body.moves = false;
    this.boat.allowGravity = false;
    this.boat.body.gravity.x = 0;
    this.boat.body.gravity.y = 0;
    this.boat.body.velocity.x = 0;
    this.boat.body.velocity.y = 0;
    this.boat.body.enable = false;

And in the update() method, I have the following:

    this.game.physics.arcade.collide(this.player, this.boat);

But my player just passes through the boat. It's not a spriteGroup. It's a sprite that I am loading from an image, it is not there in the tilemap. Where am I going wrong?

Share this post


Link to post
Share on other sites

And right before you check the rest of my post jsut check what happens when you set this.boad.body.enable to true instead of your false (actually why false when you want physics interaction phaser docs say that you disabled all collision and overlap calls on your boat)?

After, you should first show your player code as well, in advance I'll ask you if your player has body.immovable set to true?

Share this post


Link to post
Share on other sites

Thank you for your reply.

I am not sure which one is your post in thread. But I already did check what happens when I set "this.boat.body.enable = true". With it set as "true", the player kind of goes through the boat in slow motion and finally when the player sprite has passed through the boat, it quickly falls down and out of the view. If I set it to "false", this resistance from the boat is absent and the player completely goes through the boat as if it was not present at all.

I have also tried to set "this.player.immovable = true", it does not seem to make any difference at all.

My code right now is very dirty as well as unstructured and I do not have a separate object as well. I am just going to paste the current condition of the Game.js which has all of the code for the level:

// Game State: the actual game where the FUN takes place.
//
// -init: is called upon State initialization. If you need to send parameters
// to the State this is where they’ll be accessible (more on that later)
//
// -preload: this is where the assets are loaded.
//
// -create: this is called upon asset loading completion.
//
// -update: this is called on every game tick. Basically it’s called “many times
// per second” so this is where you want to include things that need to be
// constantly tested such as collision detection.

var SideScroller = SideScroller || {};

SideScroller.Game = function(){};

SideScroller.Game.prototype = {

  preload: function() {

    // For FPS
    this.game.time.advancedTiming = true;

  },

  create: function() {
    this.level1_bg = this.game.add.tileSprite(0, 0, 3710, 700, 'level1_bg');

    this.map = this.game.add.tilemap('level1');

    //the first parameter is the tileset name as specified in Tiled, the second is the key to the asset

    this.map.addTilesetImage('Spritesheet_35px', 'Spritesheet_35px');

    this.map.addTilesetImage('Water_2', 'Water_2');

    //create layers

    this.backgroundlayer = this.map.createLayer('backgroundLayer');

    this.blockedLayer = this.map.createLayer('blockedLayer');

    this.rockLayer = this.map.createLayer('rockLayer');

    this.waterLayer = this.map.createLayer('waterLayer');

    this.barricadeLayer = this.map.createLayer('barricadeLayer');

    //collision on blockedLayer

    this.map.setCollisionBetween(1, 100000, true, 'barricadeLayer');
    this.map.setCollisionBetween(1, 100000, true, 'blockedLayer');
    this.map.setCollisionBetween(1, 100000, true, 'rockLayer');

    //resizes the game world to match the layer dimensions

    this.backgroundlayer.resizeWorld();

    //create player

    this.player = this.game.add.sprite(100, 260, 'sin_spritesheet');

    this.player.animations.add('stand', Phaser.Animation.generateFrameNames('', 0, 0, '.png', 2), 10, true, false);

    this.player.animations.add('run', Phaser.Animation.generateFrameNames('', 1, 8, '.png', 2), 10, true, false);

    this.player.animations.add('jump', Phaser.Animation.generateFrameNames('', 9, 15, '.png', 2), 10, true, false);

    this.boat = this.game.add.sprite(3700, 535, 'Boat');

    //this.map.setCollisionBetween(1, 100000, true, 'Boat');

    //enable physics on the player

    this.game.physics.arcade.enable(this.player);
    this.game.physics.arcade.enable(this.boat);

    this.boat.immovable = true;
    this.boat.body.moves = false;
    this.boat.allowGravity = false;
    this.boat.body.gravity.x = 0;
    this.boat.body.gravity.y = 0;
    this.boat.body.velocity.x = 0;
    this.boat.body.velocity.y = 0;
    this.boat.body.enable = true;

    //player gravity

    this.player.body.gravity.y = 1000;
    this.player.immovable = true;

    //properties when the player is ducked and standing, so we can use in update()

    var playerDuckImg = this.game.cache.getImage('playerDuck');

    this.player.duckedDimensions = {width: playerDuckImg.width, height: playerDuckImg.height};

    this.player.standDimensions = {width: this.player.width, height: this.player.height};

    this.player.anchor.setTo(0.5, 1);

    this.player.health = 10;
    this.player.maxHealth = 10;

    this.healthbar = this.game.add.image(20, 550,'preloadbar');
    this.healthbar.cropEnabled = true;
    this.healthbar.fixedToCamera = true;

    console.log("Health bar width at create(): ", this.healthbar.width);

    //the camera will follow the player in the world

    this.game.camera.follow(this.player);

    //move player with cursor keys

    this.cursors = this.game.input.keyboard.createCursorKeys();

  },

  update: function() {

    //collision

    this.game.physics.arcade.collide(this.player, this.barricadeLayer, this.playerHit, null, this);

    this.game.physics.arcade.collide(this.player, this.rockLayer, this.playerRockHit, null, this);

    this.game.physics.arcade.collide(this.player, this.blockedLayer);

    this.game.physics.arcade.collide(this.player, this.boat);

    //only respond to keys and keep the speed if the player is alive

    if(this.player.alive) {

      if(this.cursors.right.isDown && this.cursors.up.isDown) {

        this.player.animations.play('jump');
        this.player.body.velocity.x = 300;
        this.player.scale.setTo(1);

      } else if(this.cursors.left.isDown && this.cursors.up.isDown) {

        this.player.animations.play('jump');
        this.player.body.velocity.x = -300;
        this.player.scale.setTo(-1, 1);

      } else if(this.cursors.right.isDown) {

        this.player.animations.play('run');
        this.player.body.velocity.x = 300;
        this.player.scale.setTo(1);

      } else if(this.cursors.left.isDown) {

        this.player.animations.play('run');
        this.player.body.velocity.x = -300;
        this.player.scale.setTo(-1, 1);

      } else if(this.cursors.up.isDown) {

        this.player.animations.play('jump');
        this.player.scale.setTo(1);

      } else if(!this.cursors.right.isDown || !this.cursors.left.isDown) {

        this.player.body.velocity.x = 0;
        this.player.animations.play('stand');
        this.player.scale.setTo(1);

      }

      if(this.cursors.up.isDown) {

        this.playerJump();

      } else if(this.cursors.down.isDown) {

        this.playerDuck();

      }

      if(!this.cursors.down.isDown && this.player.isDucked) {

        //change image and update the body size for the physics engine

        this.player.loadTexture('sin_spritesheet');

        this.player.body.setSize(this.player.standDimensions.width, this.player.standDimensions.height);

        this.player.isDucked = false;

      }

      //restart the game if reaching the edge

      if(this.player.x >= this.game.world.width) {

        this.game.state.start('Game');

      }

    } else {
      //stop moving to the right

      this.player.body.velocity.x = 0;

      //change sprite image

      this.player.loadTexture('playerDead');

      //go to gameover after a few miliseconds

      this.game.time.events.add(1500, this.gameOver, this);
    }

  },

  render: function() {

    this.game.debug.text(this.game.time.fps || '--', 20, 70, "#00ff00", "40px Courier");

  },


  playerJump: function() {

    if(this.player.body.blocked.down) {

      this.player.animations.play('jump');
      this.player.body.velocity.y -= 700;

    }

  },

  playerDuck: function() {

    //change image and update the body size for the physics engine

    this.player.loadTexture('playerDuck');

    this.player.body.setSize(this.player.duckedDimensions.width, this.player.duckedDimensions.height);

    //we use this to keep track whether it's ducked or not

    this.player.isDucked = true;

  },

  playerHit: function(player, barricadeLayer) {

    //if hits on the right side, die

    if(player.body.blocked.right) {

      //set to dead (this doesn't affect rendering)

      //this.player.alive = false;

      this.player.health -= 1;
      this.player.body.x -= 30;
      cropWidth = (this.player.health / this.player.maxHealth) * this.healthbar.width;

      console.log("Health bar width at playerHit() - collision with barricadeLayer: ", cropWidth);

      this.healthbar.crop(new Phaser.Rectangle(0, 0, cropWidth, this.healthbar.height));

      if (this.player.health <= 0)
      {
          this.player.alive = false;
      }

    }

  },

  playerRockHit: function(player, rockLayer) {

    //if hits on the right side, die

    if(player.body.blocked.down) {

      console.log("Killing Degir because collision with RockLayer.");

      //set to dead (this doesn't affect rendering)

      this.player.alive = false;

      //stop moving to the right

      this.player.body.velocity.x = 0;

      //change sprite image

      this.player.loadTexture('playerDead');

      //go to gameover after a few miliseconds

      this.game.time.events.add(1500, this.gameOver, this);

    }

  }
};

I hope the code helps. 

Thank you again for your reply! ( :

Best,
Ashin

Share this post


Link to post
Share on other sites

Well in your code there is play set to immovable as well as your boat. Two immovable objects can't collide together collision call on them won't work. Remove immovable from your player. Btw you sure you need

this.boat.body.moves = false;

?

Could you set up jsfiddle sample of your code? It will make things much easier to solve. Unless someone wants to go through your entire code of course. Btw you can take as an example one of the phaser templates on phaser website in section learning - there is a player sprite and some platforms, platforms don't move and player walks on them, that's sounds similar to what you need doesn't it?

Share this post


Link to post
Share on other sites

I am not sure where I was going wrong. But I removed all the properties from the boat. And added only two properties - immovable = true and allowGravity = false to the boat. And that was good enough. My character could then stand on the boat. But now I have so many other problems. I think first I need to structure my project well. Thank you for all the help!

Share this post


Link to post
Share on other sites

I'm having a little trouble with this too - the above answers won't work for me.

I have two immovable sprites stacked on top of each other (wooden boxes) that the player needs to destroy to pass through. If the lower box is destroyed the box on top of it should fall down, however, with the above solutions (body.immovable = true, body.moves = false) you end up with a floating box above where the previous/destroyed one used to be.

body.immovable = true, body.moves = false | sprite doesn't react to gravity
body.immovable = true, body.moves = true | sprites react to gravity but overlap. So you end up with both boxes overlapping.
body.immovable = false, body.moves = true | sprites react to gravity and collide with each other...but now move when player walks into them.

I've tried bumping up the body.mass and body.friction to see if I can make the body so solid it simply can't be moved by the player walking into it...but I can't seem to get that to work either.

Any ideas?

Thanks!!

Share this post


Link to post
Share on other sites
On 11/08/2017 at 4:47 PM, nglenister said:

I'm having a little trouble with this too - the above answers won't work for me.

I have two immovable sprites stacked on top of each other (wooden boxes) that the player needs to destroy to pass through. If the lower box is destroyed the box on top of it should fall down, however, with the above solutions (body.immovable = true, body.moves = false) you end up with a floating box above where the previous/destroyed one used to be.

body.immovable = true, body.moves = false | sprite doesn't react to gravity
body.immovable = true, body.moves = true | sprites react to gravity but overlap. So you end up with both boxes overlapping.
body.immovable = false, body.moves = true | sprites react to gravity and collide with each other...but now move when player walks into them.

I've tried bumping up the body.mass and body.friction to see if I can make the body so solid it simply can't be moved by the player walking into it...but I can't seem to get that to work either.

Any ideas?

Thanks!!

This could be a bit tricky. While creating my game, the boat was only the beginning of the problems. Have you considered this solution? 

It's probably worth mentioning, that a big realisation at the end of my game was my choice of the Physics System. Arcade Physics System has some limitations in terms of the kind of gameplay that it can generate. 

 If you do end up solving this problem, I would love to know how you went about it.

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.