hollowdoor Posted January 14, 2015 Share Posted January 14, 2015 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 More sharing options...
rich Posted January 15, 2015 Share Posted January 15, 2015 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 More sharing options...
hollowdoor Posted January 16, 2015 Author Share Posted January 16, 2015 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 More sharing options...
hollowdoor Posted January 16, 2015 Author Share Posted January 16, 2015 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.htmlhttp://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 More sharing options...
Recommended Posts