Oh, I missed your answer. Thanks a lot. I ended with something pretty 
similar, but decided to stay with pyglet (kept the code though. Maybe I'll 
have to switch to rabbyt).

On Saturday, July 27, 2013 6:47:23 PM UTC+2, Ryexander wrote:
>
> This is How I did my tile map with rabbty.
>
> ecentialy I have 2 numpy arrays, the first (stored in table) is a 3 
> dimensional array of the tilemap and it's layers. the only thing the table 
> array olds in ints that represent an spesfic tile from a tileset. those 
> ints are turned into actual textures inside the cache (the cache attempts 
> to generate the texture if it hasn't been requested yet and provide the 
> same texture ID for every request made for the same tile. the textur are 
> returned from the cache as pyglet image objects and the get_texture() 
> method is used to retrieve the texture for rabbyt
>
> the other numpy array is a dtype=object array that is of the same 'shape' 
> (same size in all 3 dimentions) as the tile table you can ignore the 
> order='F' part as that is just to maintain comparability with my other code.
>
> you will notice that at first the tilemap is initialized with blank tiles 
> (self.blank_tile is a empty pyglet image) and then has all the proper 
> images set in the update method..
> my table class is a class built on top of numpy and it's _data attribute 
> holds the actual numpy array that has a 'F' ordering hence why my sprite 
> array has teh same ordering. you cna ignore this part and use a strait 
> numpy array for your table and use default ordering. it wont effect how it 
> works ore the speed.
>
> the update methods used a third numpy array 'tile_ids' to keep track of 
> which tile in the tile map has which Id. by finding all the indexes where 
> this tile_ids array does not match the table and can know each index who'es 
> textue I need to update.
>
> set_image is mostly unimportant all it does in drop a new rabbyt sprite 
> with the right texture into the array to set the right tile for the tile 
> map postilion.
>
> and now we get to the draw method
> and it's REALLY simple
> all I do is first size the 3 dimensional array that is the tile map to 
> obtain ONLY the sprites visible on the screen.
> next I loop through the z dimention of the tilemap as that holds the 
> layers of the map.
> then for ever z I take the 2 dim array that holds that layer and flatten 
> it to a one dimensional array. and pass that 1 dim array of visible sprites 
> in that layer to rabbyt_render_unsorted which is a really fast c loop that 
> calls render on each sprite.
> the result is a render of the tilemap that only includes the visible 
> sprites. and a REALLY easy to manipulate tilemap
>
>
> def createTilemap(self):
>     '''
>     create the tilemap
>     '''
>     shape = self.table.getShape()
>     sprites = numpy.empty(shape, dtype=object, order='F')
>     for x in xrange(shape[0]):
>         for y in xrange(shape[1]):
>             for z in xrange(shape[2]):
>                 sprites[x, y, z] = self.makeSprite(x, y, z)
>     return sprites
>
> def makeSprite(self, x, y, z, texture=None):
>     xpos = x * 32 + 16
>     ypos = ((self.table.getShape()[1] - y) * 32) - 32 + 16
>     if texture == None:
>         texture = self.blank_tile.get_texture()
>     sprite = rabbyt.Sprite(texture, x=xpos, y=ypos)
>     return sprite
>
> def update(self):
>     '''
>     checks for change in tile ids and updates the tilemap
>     '''
>     #if the arn't the same size
>     if self.tile_ids.shape != self.table.getShape():
>         self.resize(*self.table.getShape())
>     #find the tiles who's ids have changed
>     indexes = numpy.argwhere(self.table._data != self.tile_ids)
>     #we have the idexes of the tiles we need to update so copy 
>     #the changed data over so we don;t have to update again
>     self.tile_ids[:] = self.table._data[:]
>     for index in indexes:
>         self.set_image(tuple(index), self.tile_ids[tuple(index)])
>
>
> def set_image(self, index, id):
>     '''
>     change the bitmap of a tile (by making a new sprite)
>     '''
>     #if for some reason the sprite does not exist (ie. the map was 
> resized) make it
>     x, y, z = index
>     if self.tiles[index] == None: 
>         self.tiles[index] = self.makeSprite(x, y, z)
>         
>     flag = False
>     #get the tile bitmap
>     if id < 384:
>         if id <= 47:
>             bitmap = self.blank_tile
>         else:
>             #get the filename
>             autotile = self.autotile_names[int(id) / 48 - 1]
>             #get the right pattern
>             pattern = id % 48
>             #collect the tile form the cache checking the local project 
> folder
>             #and the system RTP folder
>             bitmap = self.cache.AutotilePattern(autotile, pattern)
>             if not bitmap:
>                 bitmap = self.cache.AutotilePattern(autotile, pattern)
>             if not bitmap:
>                 flag = True
>                 bitmap = self.blank_tile
>     #normal tile
>     else:
>         #get the tile bitmap
>         bitmap = self.cache.Tile(self.tileset_name, id, 0)
>         if not bitmap:
>             bitmap = self.cache.Tile(self.tileset_name, id, 0)
>         if not bitmap:
>             flag = True
>             bitmap = self.blank_tile
>     #draw the tile to the surface
>     self.tiles[index].texture = bitmap.get_texture()
>
> def Draw(self, x, y, width, height):
>     '''
>     draw the layers of the map
>     '''
>     on_screen = self.tiles[x:x + width, y:y + height]
>     if not self.LayerDimming or self.activeLayer > on_screen.shape[2]:
>         #draw the dimlayer first
>         self.dimmingSprite.render()
>     for z in xrange(on_screen.shape[2]):
>         if z == self.activeLayer and self.LayerDimming:
>             if self.dimmingSprite != None:
>                 self.dimmingSprite.render()
>         rabbyt.render_unsorted(on_screen[:, :, z].flatten()) 
>
>
> if you need further explanation feel free to ask.
>
>
> On Friday, July 19, 2013 5:07:01 PM UTC-6, Fred wrote:
>>
>> Hello,
>>
>> I'm using pyglet to make an old-fashioned 2D RPG engine. A map is made of 
>> layers (up to 10), each layer is made of tiles (21 * 15 tiles). A map can 
>> be big (more than 100 x 100 tiles), and sometimes infinite (toric).
>>
>> The map is rendered in a single batch, each layer is attached to an 
>> OrderedGroup. 
>> A tile from a layer is attached to a sprite (in 'static' mode), but I 
>> keep only tiles that are effectively on screen (in a list). When a tile 
>> goes outside the screen, the sprite is destroyed (it's removed from the 
>> list so I suppose it's destroyed since there are no references on it 
>> anymore), and to the contrary, when a new tile comes inside the screen, I 
>> add a new sprite to the group. I've read they are slow operations, but I 
>> don't see a better way (the maps are too big to keep all the sprites).
>>
>> My problem is that I have performances issues for the biggest maps : I 
>> reach at most 5 fps, where I'd like to have 60. Event for smaller ones 
>> (only 3 layers), I get 30 - 40 fps.
>>
>> Am I doing it the wrong way (and if so, could you please point me better 
>> ideas) or is my goal clearly unreachable using Python + pyglet, and would 
>> require C++/OpenGL code ?
>>
>> Thanks in advance !
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/pyglet-users.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to