Jump to content

Need some Tilemap and camera performance tips.


j0hnskot
 Share

Recommended Posts

Hello there!

I got a tilemap  and a sprite. I make the camera follow the sprite. 

But when the camera starts moving i got  10+ fps drops.

 

I guess this is because of the tilemap. Are there any ways to decrease this loss of fps?

My layer's size is 6400x480 (32x32 tiles)  If i reduce the size i will probably gain some fps. But that's my last option since it reduces the size of the level.

 

Any tips are appreciated!

Link to comment
Share on other sites

It's hard to say from such a complete game (great idea btw!) but I'd probably recommend commenting out various parts of the code (the HUD update and other bits) and see how the fps changes. I'm not completely convinced the issue is the camera following - you could comment out the camera follow part of the code and see if the game's fps drops even when the camera isn't following the player. If it doesn't, then maybe you could rather than using the camera to follow the player (which may be a little bit over-engineered for a simple scroller such as this) just apply a constant speed to the camera to make it scroll at the same speed as the player.

Link to comment
Share on other sites

Before the scrolling starts the  fps counter is ~30 fps. When the scrolling start it goes to ~20 fps.

Yesterday i tried disabling the follow() and the fps stayed at 30 so i guess this is a part of it. I'll try disabling  more like the hud like you said and i'll let you know.

 

(thank you for your comment on the idea!) 

Link to comment
Share on other sites

If you're only getting 30fps in the first place, something is definitely taxing your devices already - Phaser should typically run at 60fps. Something happening in one of your update/render loops that's impacting performance to the degree that the small amount of extra impact from scrolling is affecting the game much worse than it should.

Link to comment
Share on other sites

hmmm..  nothing changed.. but one thing i just saw is that the fps don't change when the scrolling starts.. so i loaded a layer-test-example i created for a github issue concerning the performance of tilemap layers and huh...  the same problem occurred in my example (where there is no other code that could interfere at all)    i should have 60 fps straight in my example ... at least it was that way some weeks ago...http://test.xapient.net/phaser/ALL/layers.html?count=1

 

i closed chromium browser and reloaded everything.. now i have 60fps in my example AND in your game !       still don't know why but i had a similar problem 3 days ago on my nexus7 where my mario game had 30fps instead of 60fps.. maybe you hit a new phaser bug somehow?

Link to comment
Share on other sites

I am stripping down my code and it drives me nuts. Every thing i stop from running gives me nothing or 1 fps maximum.

Then i tried a tutorial of phaser , the one in the resources with the dude and the stars falling. On this example the same device runs on 31 fps max.

 

Maybe i'm hunting ghosts here and the phone just sucks enough ?

Link to comment
Share on other sites

I have the same issue on my project, FPS drops from 60 to 40 when the camera scrolls to follow the player. My tilemap is not that big, 800 x 2016 pixels with 32px tiles.

 

So I tried to display FPS on the Sci Fly phaser example: same thing happens, FPS is at 60 when no scrolling occurs and drops to 40 when camera is moving.

 

On your example valuerror, FPS drops from 60 to 50 with one layer and from 60 to 25 with 4 layers.

 

Such a drop sounds weird on a laptop with solid hardware, what do you think?

 

Renderer is webgl (Firefox on Ubuntu).

Link to comment
Share on other sites

I had the same issue, especially on firefox, but also on chrome (but not on ie, no joke).
Everytime I've combined tilemap scroll (top down map) with camera following the player, frame rate goes down from 55-60 to under 15-30fps, which causes collision detection to fail. My solution was to have the camera fixed to screen and use a zelda like scene scrolling for the tilemaps.

Link to comment
Share on other sites

It should be pointed out that neither the Phaser camera nor many of the other features are inherently fully optimised for a specific game type; their lower performance is the tradeoff you pay for ease of use. All the camera does is follow an object, which is pretty low-level.

 

What's interesting is that despite the maturity of modern hardware and frameworks, the cross-platform nature means many of the same old performance tricks are still very much applicable. If you look into scrolling routines for tile-based games, you'll often find that instead of a camera moving around the map, the map itself is moved around and tiles outside of the 'camera' (usually the screen) are clipped with a very fast rectangular routine - Phaser's per-sprite bounds checking is not as optimal. Along with some additional logic that reduces the rate of update (or stops it entirely) of items outside of the camera, the results are much more performant, regardless (within reason) of the size of your world - one thing we do have over old hardware is much more memory!

 

The bottom line is that old-fashioned optimisation techniques are just as relevant today as they were 20 or 30 years ago, and as game developers these are definitely relevant to your interests so you can squeeze every last drop of performance out of your games.

Link to comment
Share on other sites

@marvster Yes zelda-like scrolling surely increases performance. I'll work like that if i don't find another way to boost performance.

 

@lewster  If i understand correctly, you suggest to move the tiles towards the player instead of moving the camera? Or this is the way phaser works?

As you saw i got some moving platforms in the game. Moving all the tilemap and the sprites towards the player wouldn't it be more expensive? 

Sorry if i didn't understand your explanation.

 

 

As for my phone. I don't know why , but running an empty scene with nothing but an fps counter runs at 35fps max. Either there is a fps limit or i don't know what the heck happens.

Link to comment
Share on other sites

@lewster  If i understand correctly, you suggest to move the tiles towards the player instead of moving the camera? Or this is the way phaser works?

As you saw i got some moving platforms in the game. Moving all the tilemap and the sprites towards the player wouldn't it be more expensive? 

Sorry if i didn't understand your explanation.

 

A Tilemap is a kind of special group whose contents are assembled by reading data in a particular format, but beyond that I don't believe it includes much in the way of optimisation. The camera then moves around this group just as it would do in  any other scenario. A more optimal strategy for a tile-based game (and one used in most that I know of) is to instead of building the entire group of objects at the beginning then scrolling around them, to rather only build the part of the tilemap that's needed to display onscreen - and scroll that part around, adding tiles to the leading sides as it scrolls, and culling them from the trailing sides. With object pooling to simply move culled tiles to a place where they're about to be shown and changing their texture frame, this can be very fast. Look here for a nice example.

 

Unfortunately I expect that type of functionality would fall outside of the realms of what Phaser can (and indeed should) be doing within the framework, as it would likely break the camera in any other scenario, or lead to there being a need for two separate cameras; a tilemap camera and a normal camera. Phaser is attempting to provide a unified and wide-ranging SDK to help get the ball rolling, but if you're keen on very specific functionality or high performance for your specific type of game, you'll have to dig a little deeper and start expanding Phaser's repertoire yourself.

Link to comment
Share on other sites

Thanks lewster32, that's really interesting, I will keep digging on that.

 

Still, can anyone explains me why valueerror examples work perfectly at 60 fps with canvas renderer on my laptop but drops to 20 fps with webgl renderer? Is it somehow because my GPU is crap? Is it because browsers on Ubuntu don't play well with the GPU?

 

Or are they any other possible explanation?

Link to comment
Share on other sites

I think when running GPU stuff in the browser in Linux often all bets are off; there are many things that can go wrong or be bottlenecked and I don't think there are many people around who can claim to understand the issue fully. The only way to be sure is to get the browser profiler out and see where the bottlenecks lie.

Link to comment
Share on other sites

@lewster I did some tweaks to the tilemap by using objects instead of tiles to be able to move everything towards the player and the fps are stable now.

There is little fps increase but the huge problem is kinda solved. The next step is to brainstorm a way to use object pooling and spawning the tiles on demand.

If anyone got an idea please inform me!

Link to comment
Share on other sites

Create a group for your tiles and fill it with a number of sprites (you may have to play with the number to see how low you can get it without running out mid-game) and then implement something like in the link I provided.

 

The (slightly) tricky part will be writing a routine which analyses the data you use to store your maps and decides which column of tiles to draw at the leading edge of the scroll. In side-scrolling games of old, the maps were often stored top to bottom, left to right, rather than left to right, top to bottom - this allowed the scrolling routine to sequentially grab a column of tiles at once and initialise them past the right-hand side of the screen. If you can't arrange your tiles in this format a little bit of maths could help you grab columns of tiles at a time.

 

For each column you grab from your data format, you'd loop through them and do something like this:

// create a pool of tiles and assume you're using a sprite sheet/atlas to set the framesvar tiles = game.add.group();tiles.createMultiple(100, 'tile', 0, false);// getColumn would be a function you write which grabs an array from your data format// at the specified x position containing the type of tile, with 'empty' being a special// tile which represents empty space (surprisingly!) but could be 'ground', 'spikes' etcvar column = getColumn(x);// our simple culling routine - do this first to free up as many tiles as you can before// populating the leading edge of the scroll with new tilestiles.forEach(function(tile) {  // remove any tiles that have moved off the left-hand side of the screen  if (tile.x < TILE_WIDTH) {    tile.kill();    // ... here you may want to do other cleanup work like resetting all of    // the tile's properties, removing callbacks, tweens etc.  }});var tile; // placeholder for operating on individual tilesfor (var t = 0, len = column.length; t < len; t++) {  // ensure the tile for this row is not empty  if (column[t] !== "empty") {    // get a currently not in use tile from the pool    tile = tiles.getFirstDead();    // make sure we have a tile - if this fails we need to ensure we're culling tiles    // properly; if we are, increase our pool size    if (tile) {      // revive this tile and place it just to the right of the screen and at the right      // height by multiplying the loop index by a constant that represents the height      // of your tiles      tile.reset(game.width.x, t * TILE_HEIGHT);      // set the tile to the correct frame      tile.frameName = column[t];      // ... here you would also set any other properties for this sprite - be careful      // that all properties are reset or you may have revived sprites carrying over      // properties, tweens and callbacks set previously    }  }}

This code makes some assumptions; that the tiles are evenly sized and that the game only scrolls in one direction. It's easily adapted to allow the game to scroll in the opposite direction, but will require a bit more work to allow it to work in four directions.

 

This routine has some things missing which you'll have to fill in the blanks for - namely the scrolling method itself, which should have a scrollPosition and also a way of knowing when it's scrolled more than one tile's width so it can call this routine to add new tiles to the leading edge.

Link to comment
Share on other sites

  • 2 years later...

Maybe this will help someone who is looking for tips:

I have a game with a tilemap made in Tiled. The tilemap is 128 x 128 in size with tiles of 16 x 16 resulting in a small sandbox world of 2048 x 2048 pixels.

Now the game was running okay, but on an older laptop of mine it had some lag dropping in fps from 60 to 40/30 when moving the camera. (i'm not even talking about mobile, that i still have to tackle).

First thing i did was putting the visible property of the 2 layers of the map to false. Which stopped rendering the tilemap, but kept all the game objects still colliding the map.

Then i got rid of the tilesetimage, which i did not need anymore.

Then i went back to Tiled and exported the whole map as an image and added that image as background to the level.

in the preload:

game.load.image('levelflat', 'assets/sprites/level.png');

and in the create function:

var levelbg = game.add.image(0, 0, 'levelflat');

That made a very noticeable boost i must say. Resulting in no more lag on the old laptop. Even on mobile it was almost there, but there still was another element causing lag on mobile.

Now i must note that this probably won't work with very large levels. It all depends on how large you can make the images of the backgrounds.

 

Link to comment
Share on other sites

  • 2 weeks later...
On 19/11/2016 at 10:39 PM, Quinten said:

Maybe this will help someone who is looking for tips:

Oh yes it was really helpful !

I've got some lags on my app and didn't manage to find why before seeing your post.

I've had rendering problems after game start scrolling with some renders taking 40ms or more. I've did what you say, turn off visibility on tilemap and add back image as tilesprite and it's like night and day. (my game 8992px large ...) I'm now at 60fps during all the game.

 

Thank you for this tip :)

Link to comment
Share on other sites

6 hours ago, dieedi said:

Oh yes it was really helpful !

I've got some lags on my app and didn't manage to find why before seeing your post.

I've had rendering problems after game start scrolling with some renders taking 40ms or more. I've did what you say, turn off visibility on tilemap and add back image as tilesprite and it's like night and day. (my game 8992px large ...) I'm now at 60fps during all the game.

 

Thank you for this tip :)

No problem you're welcome :)

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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