Jump to content

how should I render a tile map?


HS_Dave
 Share

Recommended Posts

Hello all!

 

I'm struggling a little wrapping my head around programming principles with PIXI. I'm a sort of old fashioned programmer who started gamedev in C many (..many) years ago and now primarily program in C#. I have never used flash or anything like it so even the concept of a "stage" was alien to me and i've been trying to figure this all out just by browsing through the docs!

 

I'm having a play around and trying to create a JS class for rendering tile maps (both standard and iso etc). In my head I am expecting: a source tile sheet with ALL the maps tiles. A destination buffer, be it a canvas or (the way I have chosen) a render target texture. A way to just blit rects from the source tile sheet to the destination buffer.

 

I quickly realised I would need to break my sheet up into textures - that is okay and I have (successfully) written code to do that. But then I found I could not draw these textures to where I wanted on the destination - the docs tell me they will be drawn at 0,0 unless I create a sprite object out of them (...why? can't we have a x/y?? I'm okay with sprite objects in general but for tiles, really?)

 

This is where I lose it a bit.  In my render method I clear away last frames tiles and create sprites for the new ones, setting a coordinate. Later on I will using a bit of logic to do a sort of fuzzy update where it only replaces the tiles it needs to (which is why i chose a render texture, if camera hasnt moved no need to redraw at all!) but for now I just wanted to get the standard "brute force" technique working.

 

It works, on my pc in chrome, it reports 60fps. On my phone (lumia 925) however it reports 0.6fps! Juding by how well the other pixi examples ran i'm CERTAIN i'm doing it wrong. How SHOULD I be doing this?

 

For reference, here is the method that inits a map and cuts up the sprite sheet:

	HS_TileMap.prototype.NewMap = function(PixiRenderer, MapType, MapWidth, MapHeight, MapTileSheet, TileWidth, TileHeight, RenderWidth, RenderHeight)	{		this.MapType = MapType;		this.MapWidth = MapWidth;		this.MapHeight = MapHeight;			this.TileWidth = TileWidth;		this.TileHeight = TileHeight;		this.RenderWidth = RenderWidth;		this.RenderHeight = RenderHeight;		this.MapData = new Array(MapWidth);				this.PixiRenderer = PixiRenderer;		this.RenderSurface = new PIXI.RenderTexture(PixiRenderer, RenderWidth, RenderHeight);		this.RenderSurfaceSprite = new PIXI.Sprite(this.RenderSurface);				//I expect the MapTileSheet to be a PIXI base texture.  I'll make some proper sprites from it now		var SheetWidth = MapTileSheet.width;		var SheetHeight = MapTileSheet.height;		var TotalTiles = (SheetWidth / TileWidth) + (SheetHeight / TileHeight);				this.TileSprites = new Array(TotalTiles);				var TextureBuffer;		var TileID = 0;				for (var tx = 0; tx < SheetWidth; tx += TileWidth)		{			for (var ty = 0; ty < SheetHeight; ty += TileHeight)			{				TextureBuffer = new PIXI.Texture(MapTileSheet, { x: tx, y: ty, width: TileWidth, height: TileHeight});								PIXI.TextureCache[TileID] = TextureBuffer;				this.TileSprites[TileID++] = TextureBuffer;							}		}				for (var x = 0; x < MapWidth; x++)		{			this.MapData[x] = new Array(MapHeight);						for (var y = 0; y < MapHeight; y++)			{				this.MapData[x][y] = new HS_TileData();				this.MapData[x][y].TileID = -1;				this.MapData[x][y].Passable = true;			}		}			}

and here is my (so very slow) Render method:

	HS_TileMap.prototype.RenderMap = function()	{		if (this.NextMapRefreshType & MapRefreshType.Full)		{			this.DisplayContainer.removeChildren();						for (var x = 0; x < this.MapWidth; x++)			{				for (var y = 0; y < this.MapHeight; y++)				{					if (this.MapData[x][y].TileID == -1)						continue;											var Tile = new PIXI.Sprite(this.TileSprites[this.MapData[x][y].TileID]);					var TilePos = this.GetTileScreenPos(x, y);					Tile.x = TilePos.x + (this.RenderWidth / 2);					Tile.y = TilePos.y;										this.DisplayContainer.addChild(Tile);				}			}		}				if (!(this.NextMapRefreshType & MapRefreshType.None))		{			this.RenderSurface.render(this.DisplayContainer, false);		}		}

MapRefreshType is just an enum (or as close as I could make work in js) of bit flags which will ultimately tell the method what sort of draw to perform, but for now it's just doing a full re-draw.

 

sorry if there is stupid code in this - I have programmed for a long time but never very much in JS and this is my first time in pixi XD help? 

Link to comment
Share on other sites

But then I found I could not draw these textures to where I wanted on the destination - the docs tell me they will be drawn at 0,0 unless I create a sprite object out of them

 

Of course, you don't draw textures, you draw sprites. A BaseTexture describes a source, usually an image. A Texture describes a frame into that source. A Sprite describes the positional data necessary to draw that texture.

 

I'm okay with sprite objects in general but for tiles, really?)

 

Why not? if they all share a single texture object it is one single draw call.

 

Clearing and redrawing will be stupid expensive. Instead create the tiles that you need to display the screen and move them around and reassign textures.

 

For a good example look at how I implement tiled map support in Phaser (which uses pixi). The Phaser objects I use are basically just PIXI objects slightly modified to the technique translates.

 

https://github.com/englercj/phaser-tiled

Link to comment
Share on other sites

Thanks for your reply xerver! Okay, so basically maintain a width x height array of Sprites and instead of clearing them from the display container just update their texture? easy enough!

 

do not be so dismissive of "drawing a texture" though - I understand these days that sprites are basically textured quads but it wasnt that long ago we were still blitting everything and even more modern libs like xna/monogame support at least the technique (spritebatches, render(x, y) etc) even if under the hood it does it the modern way.

 

My concern is that if I support zooming out on a tile map and need a lot of extra sprite "containers" to draw all the tiles then its just such a waste of ram when something like a tilemap doesnt want a persistant sprite, just a quick blit :/ but I guess thats just the way it is.

 

googling around I found: https://github.com/GoodBoyDigital/pixi.js/issues/141 where the pixi dev mentions they could add an x/y ... that would be so awesome for edge cases like this. Of course the concern is would it be hardware accelerated - which it could be depending on how its implemented! :)

Link to comment
Share on other sites

do not be so dismissive of "drawing a texture" though - I understand these days that sprites are basically textured quads but it wasnt that long ago we were still blitting everything and even more modern libs like xna/monogame support at least the technique (spritebatches, render(x, y) etc) even if under the hood it does it the modern way.

 

I'm not trying to be dismissive, I'm just telling you what the objects in PIXI are for. I think you're confusing a gl texture and a PIXI Texture. That is not what PIXI Textures are, but nothing stops you from bliting around gl textures. If you want it to run through the system renderer (CanvasRenderer, WebGLRenderer) then it needs to be in the system.

 

 

 

My concern is that if I support zooming out on a tile map and need a lot of extra sprite "containers" to draw all the tiles then its just such a waste of ram when something like a tilemap doesnt want a persistant sprite, just a quick blit :/ but I guess thats just the way it is.

 

Then you should create a custom object with a custom ObjectRenderer that does what you want to do specifically. Pixi is written to be extensible. Think of Pixi like SFML but more features and a little higher level.

 

 

 

googling around I found: https://github.com/G...i.js/issues/141 where the pixi dev mentions they could add an x/y ... that would be so awesome for edge cases like this. Of course the concern is would it be hardware accelerated - which it could be depending on how its implemented!  :)

 

If you look at the docs, we did add that :)

 

http://pixijs.github.io/docs/PIXI.RenderTexture.html#render

 

You can specify a transform matrix to apply the object you are drawing.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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