Jump to content

Why do sloped polylines in a tileset make a character bounce?


hollowdoor
 Share

Recommended Posts

I am testing Phaser's polyline handling for tilesets in a platformer.

 

Everything works as expected for flat surfaces, and undersides of surfaces, but there's a strange effect.

 

When the character jumps onto the surface of the a slope of a polyline the character bounces around like it's still jumping. After a bounce or two the character settles down on the sloped surface and slides down a little.

 

I'm using a json tilemap. There's a few unused variables because of testing, but this is the working code.

function preload () {        game.load.spritesheet('player', 'assets/player.png', 80, 50, 4);    game.load.image('tiles1', 'assets/tiles1.png'); // loading the tileset image    game.load.tilemap('map', 'assets/tiles2.json', null, Phaser.Tilemap.TILED_JSON); // loading the tilemap}function create () {    //game.world.setBounds(0, 0, 1600, 1200);        //	Enable p2 physics	game.physics.startSystem(Phaser.Physics.P2JS);		//  Turn on impact events for the world, without this we get no collision callbacks    game.physics.p2.setImpactEvents(true);    //gravity	game.physics.p2.gravity.y = 300;	//bounce    //game.physics.p2.restitution = 0.1;            map = game.add.tilemap("map");    map.addTilesetImage('tiles1'); // Preloaded tileset    layer = map.createLayer('Tile Layer 1'); // This is the default name of the first layer in Tiled    layer.resizeWorld(); // Sets the world size to match the size of this layer.        game.physics.p2.convertCollisionObjects(map, "ob1");    //map.setCollisionByExclusion([0], true, layer, true)            //game.physics.p2.convertTilemap(map, layer);        game.physics.p2.setBoundsToWorld(true, true, true, true, false);    player = game.add.sprite(game.world.centerX, game.world.centerY, 'player');    player.anchor.setTo(0.5, 0.5);    player.animations.add("run");            game.camera.follow(player);        game.physics.p2.enable(player);        player.body.fixedRotation = true;    //player.body.mass = 1.5;        cursors = game.input.keyboard.createCursorKeys();}var jumped = false;function update(){        var jump = checkIfCanJump(player),        run = jump;        if(!run && (player.body.velocity.y > -250 && player.body.velocity.y < 300)){        if(cursors.left.isDown)            player.body.velocity.x = -200;        else if(cursors.right.isDown)            player.body.velocity.x = 200;        else if(!jumped)            player.body.velocity.x = 0;        jumped = true;    }        if(run){        player.body.velocity.x = 0;        jumped = false;    }        if (cursors.left.isDown && run){        player.body.velocity.x = -250;        player.animations.play("run");//, 10, true);    }    else if (cursors.right.isDown && run)    {           player.body.velocity.x = 250;        player.animations.play("run", 10, true);    }else{                player.animations.stop();    }	    if(cursors.up.isDown && jump){// && player.body.touching.down){                        player.body.velocity.y = -300;    }}function checkIfCanJump(player) {    var yAxis = p2.vec2.fromValues(0, 1);    var result = false;    for (var i = 0; i < game.physics.p2.world.narrowphase.contactEquations.length; i++)    {        var c = game.physics.p2.world.narrowphase.contactEquations[i];        if (c.bodyA === player.body.data || c.bodyB === player.body.data)        {            var d = p2.vec2.dot(c.normalA, yAxis); // Normal dot Y-axis            if (c.bodyA === player.body.data) d *= -1;            if (d > 0.5) result = true;        }    }        return result;}
Link to comment
Share on other sites

Neither the player nor the polygon have been assigned any kind of material, so they'll use the slightly spongy defaults. You probably want a zero restitution and quite low friction material to get it to slide properly, but it's game specific, so tweak until it feels right.

Link to comment
Share on other sites

Thanks rich. I didn't know I needed material on the polygon. I must admit I don't know how to set material on one. I can set one on the player easy enough so I might try that. I'll have to look to see if there is an example on the main site for setting material on a polyline.

 

Also the polylines were in a concave shape. I tried a straight slope, and the player didn't bounce so that will help a little. I was just testing the extreme.

 

I didn't show those to you. Sorry for the omission.

 

A related issue is the polylines worked for collisions, but the polygons I tried let the player pass through. I don't know if polygons are just polylines linked together in the code sense, and not just the visual sense. I'm using "Tiled" to make the map.

Link to comment
Share on other sites

I can't believe how easy it was. Thank you so much Phaser team for your hard work.

 

After looking at some different examples I was able to figure out how it all came together. Here's the example for any one that has the same problem as me.

var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });var player,    cursors,    map;function preload () {        game.load.spritesheet('player', 'assets/player.png', 80, 50, 4);    game.load.image('tiles1', 'assets/tiles1.png'); // loading the tileset image    game.load.tilemap('map', 'assets/tiles2.json', null, Phaser.Tilemap.TILED_JSON); // loading the tilemap}function create () {    //game.world.setBounds(0, 0, 1600, 1200);        //	Enable p2 physics	game.physics.startSystem(Phaser.Physics.P2JS);		//  Turn on impact events for the world, without this we get no collision callbacks    game.physics.p2.setImpactEvents(true);    //gravity	game.physics.p2.gravity.y = 300;	//bounce    //game.physics.p2.restitution = 0.1;            map = game.add.tilemap("map");    map.addTilesetImage('tiles1'); // Preloaded tileset    layer = map.createLayer('Tile Layer 1'); // This is the default name of the first layer in Tiled    layer.resizeWorld(); // Sets the world size to match the size of this layer.        /*        The magic starts here.        The array of physics bodies to use material on.        */    var tile_bodies = game.physics.p2.convertCollisionObjects(map, "obj1");            game.physics.p2.setBoundsToWorld(true, true, true, true, false);    player = game.add.sprite(game.world.centerX, game.world.centerY, 'player');    player.anchor.setTo(0.5, 0.5);    player.animations.add("run");            game.camera.follow(player);        game.physics.p2.enable(player);        var kittyMaterial = game.physics.p2.createMaterial('playerMaterial', player.body),        tileMaterial = game.physics.p2.createMaterial('tileMaterial');    /*            Loop the array, and set the material.        */    for(var i=0; i<tile_bodies.length; i++){        tile_bodies[i].setMaterial(tileMaterial);    }        /*        Using contact material the player can have    precise physics interactions with tile objects.            */    var contactMaterial = game.physics.p2.createContactMaterial(playerMaterial, tileMaterial);        /*            Adjust the contactMaterial properties to your heart's content.    All kinds of shapes are now available through tile objects as physics bodies..            */    contactMaterial.friction = 0.3;     // Friction to use in the contact of these two materials.    contactMaterial.restitution = 1.0;  // Restitution (i.e. how bouncy it is!) to use in the contact of these two materials.    contactMaterial.stiffness = 1e7;    // Stiffness of the resulting ContactEquation that this ContactMaterial generate.    contactMaterial.relaxation = 3;     // Relaxation of the resulting ContactEquation that this ContactMaterial generate.    contactMaterial.frictionStiffness = 1e7;    // Stiffness of the resulting FrictionEquation that this ContactMaterial generate.    contactMaterial.frictionRelaxation = 3;     // Relaxation of the resulting FrictionEquation that this ContactMaterial generate.    contactMaterial.surfaceVelocity = 0;        // Will add surface velocity to this material. If bodyA rests on top if bodyB, and the surface velocity is positive, bodyA will slide to the right.        player.body.fixedRotation = true;    //player.body.mass = 1.5;        cursors = game.input.keyboard.createCursorKeys();}var jumped = false;function update(){        var jump = checkIfCanJump(player),        run = jump;        if(!run && (player.body.velocity.y > -250 && player.body.velocity.y < 300)){        if(cursors.left.isDown)            player.body.velocity.x = -200;        else if(cursors.right.isDown)            player.body.velocity.x = 200;        else if(!jumped)            player.body.velocity.x = 0;        jumped = true;    }        if(run){        player.body.velocity.x = 0;        jumped = false;    }        if (cursors.left.isDown && run){        player.body.velocity.x = -250;        player.animations.play("run");//, 10, true);    }    else if (cursors.right.isDown && run)    {           player.body.velocity.x = 250;        player.animations.play("run", 10, true);    }else{                player.animations.stop();    }	    if(cursors.up.isDown && jump){// && player.body.touching.down){                        player.body.velocity.y = -300;    }}function checkIfCanJump(player) {    var yAxis = p2.vec2.fromValues(0, 1);    var result = false;    for (var i = 0; i < game.physics.p2.world.narrowphase.contactEquations.length; i++)    {        var c = game.physics.p2.world.narrowphase.contactEquations[i];        if (c.bodyA === player.body.data || c.bodyB === player.body.data)        {            var d = p2.vec2.dot(c.normalA, yAxis); // Normal dot Y-axis            if (c.bodyA === player.body.data) d *= -1;            if (d > 0.5) result = true;        }    }        return result;}

The examples that solidified the concepts for me.

http://test.xapient.net/phaser/tilemapexample/index-p2.html

http://examples.phaser.io/_site/view_full.html?d=p2%20physics&f=contact+material.js&t=contact%20material

 

The documentation describing where the physics bodies come from.
http://docs.phaser.io/Phaser.Physics.P2.html#convertCollisionObjects

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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