Jump to content

Vertical scrolling background with collisions in P2


joshgerdes
 Share

Recommended Posts

I am new to Phaser and I am currently working on my first game.  I'm am creating a vertical scroller and have come across some performance issues on mobile.  I have a 1024x4608 background with some 'land' that needs collision detection with the 'player' and the 'enemies' in the game. I've been trying a couple approaches but can't seem to find the sweet spot with the performance.  I was hoping someone would have some suggestions.  

 

Here's what I've tried so far:

 

1) Tilemap

this.load.tilemap('level01_map', 'assets/level01_map.json', null, Phaser.Tilemap.TILED_JSON);this.load.image('tiles', 'assets/tiles.png');this.map = this.add.tilemap('level01_map');this.map.addTilesetImage('main', 'tiles');this.map.createLayer('land');this.world.setBounds(0, 0, this.map.widthInPixels, this.map.heightInPixels);this.map.setCollisionByExclusion([], true, 'land');var bodyObjects = this.physics.p2.convertTilemap(this.map, 'land');for(var i = 0; i < bodyObjects.length; i++) {   bodyObjects[i].setCollisionGroup(this.gameGroups.landCG);  bodyObjects[i].collides(this.gameGroups.playerCG);  bodyObjects[i].collides(this.gameGroups.enemyCG);}

 

 

2) Sprite with polygons


this.load.image('level01', 'assets/level01.png');this.load.physics('level01_physics', 'assets/level01.json');this.world.setBounds(0, 0, 1024, 4608);this.map = this.add.sprite(0, 0, 'level01');this.map.widthInPixels = 1024;this.map.heightInPixels = 4608;var polygonCollisionSprite = this.add.sprite(15, 15);this.physics.p2.enableBody(polygonCollisionSprite, true);polygonCollisionSprite.fixedRotation = true;polygonCollisionSprite.body.motionState = Phaser.Physics.P2.Body.STATIC;polygonCollisionSprite.body.clearShapes();polygonCollisionSprite.body.loadPolygon('level01_physics', 'level01_left');polygonCollisionSprite.body.loadPolygon('level01_physics', 'level01_right');polygonCollisionSprite.body.setCollisionGroup(this.gameGroups.landCG);polygonCollisionSprite.body.collides(this.gameGroups.playerCG);polygonCollisionSprite.body.collides(this.gameGroups.enemyCG);
 
And here are my results testing on an iPhone 5:
  • Tilemap no collisions = 45fps

  • Tilemap with collisions = 20fps

  • Sprite/polygons no collisions = 45fps evens out to 60fps when less polygons in view 

  • Sprite/polygons with collisions = 8fps

  • Sprite/polygons (simple) no collisions = 60fps

  • Sprite/polygons (simple) with collisions = 30fps


Note: simple means I reduced the vertices in the polygons. (Simple = 6 shapes, Normal = 44 shapes)
 
The game is setup with 1024x640 in Phaser.CANVAS mode. Also, the all sprite assets, except the stuff for the background, are being load via one atlas texture.
 
Any thoughts?

 

Link to comment
Share on other sites

Just for an update, I did more testing around the sprite and polygons approach.

 

I currently have 13 'enemies' on the level that are loaded at the start of the level. I have the 'land' added to a collision group and I have the 'enemies' in a collision group.  I set the P2 body of the enemies to collide with the land collision group and the land sprite P2 body to collide with the enemies collision group.

 

Here is the relevant code:

item.body.collides(this.gameGroups.landCG, item.collided, item);

Part of the extended Sprite object ('item' above is this extended Enemy sprite object):

Enemy.prototype.collided = function(body1, body2) {  if(!this.hasCollided) {    this.scale.x *= -1;    this.speed *= -1;    this.body.velocity.x = this.speed;    this.hasCollided = true;  }};Enemy.prototype.endCollided = function(bodyB,shapeA,shapeB) {  this.hasCollided = false;};
This block of code allows the enemy to touch the edge of the 'land' and switch directions and go back and forth across the screen. I had to add the hasCollided boolean because for some reason the collided function gets called multiple times when a P2 body hits another. 
 
I have seen other games and examples with way more than 13 sprites on screen so I'm assuming there must be something inefficient with the collision code.  
 
Does anybody have any ideas on a better way for an enemy to travel back and forth between to other bodies?
 
Or what is the proper way to set up a sprite to move like this with P2 physics?
 
 
 
Link to comment
Share on other sites

Yet another testing update.  I tried another option of using a tilemap and polyline objects created in Tiled. I created 2 polylines to establish a left and right border with each polyline consisting of 5 segments.  This seems like a pretty simple collision border but the result was around 20fps on a mobile device.  So that seems like I have exhausted my options for implementing the map and the real issue is in the collision detection between the map objects and the enemy sprites.

 

Does anybody have an example on collision detection between sprites and background maps (either tilemap or polygons)?

 

Thanks in advance.

Link to comment
Share on other sites

just one question..  HOW do you prevent your enemy bodies form constantly swtiching direction?  are they flying over the ground? if not they should permanently collide with the ground an therefore fire the collided event all the time..  what did i miss?

 

 

in my first game i tried to make with phaser i used a narrowphase equation to find out it the player WILL collide with something only to the right or to the left

(because the enemys were walking on the ground which had the same collisiongroup as the walls i needed a way to find out when they were touchingRight or Left)

function touchingLeft(someone) {var xAxis = p2.vec2.fromValues(1,0);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 === someone.data || c.bodyB === someone.data) {var d = p2.vec2.dot(c.normalA, xAxis); // Normal dot Y-axisif (c.bodyA === someone.data) d *= -1;if (d < -0.5) result = true;}} return result;}function touchingRight(someone) {var xAxis = p2.vec2.fromValues(1,0);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 === someone.data || c.bodyB === someone.data) {var d = p2.vec2.dot(c.normalA, xAxis); // Normal dot Y-axisif (c.bodyA === someone.data) d *= -1;if (d > 0.5) result = true;}} return result;}

and then:  (velo is an initial speed i store on enemy.velo)

if (touchingLeft(enemy.body)||touchingRight(enemy.body)){enemy.body.x -= enemy.velo/50; enemy.velo *= -1;enemy.scale.x *=-1; } //set "back" enemy a few pixels to not fire touchingLeft/Right again and turn speed aroundenemy.body.velocity.x=enemy.velo;

but honestly  i don't know if this approach is any faster.. 

Link to comment
Share on other sites

To answer your qeustion @valueerror, I am working on a vertical scroller so when using the tilemap method the center portion of the map is blank (i.e. has no tiles defined) so the enemy bodies are not colliding with anything. I just use a background color for the stage to give the center color.  If I understand correctly, if you add tiles to the center portion of the map and do not want them to be part of the collision bodies defined for the tilemap you would exclude them like this:

var tilemap = game.add.sprite(0, 0, 'level01');tilemap.setCollisionByExclusion([1,2,3], true, 'land');

where 1,2,3 are the index values of the tiles you do not want to collide with. Link to the related docs: http://docs.phaser.io/Phaser.Tilemap.html#setCollisionByExclusion

 

Also, I have another question out there on specifically how to setup enemy body collisions for this scenario. I just added full test code so hopefully someone will be kind enough to help with a solution. Here's a link to the related post: http://www.html5gamedevs.com/topic/9709-performance-issues-with-p2-sprite-collisions/

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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