2d tile engine+animated tiles

634 views
Skip to first unread message

josch

unread,
Sep 8, 2008, 12:35:05 PM9/8/08
to pyglet-users
hi!
in my first attempt to build something useful i just threw together a
few lines of code that displayed animated water tiles.
i did this by creating a water animation and adding it to a batch as
sprites with the individual coordinates.
this does work correctly but surprisingly the framerate will drop
significantly to something like 0.6fps when i do this fullscreen with
60x38 tiles (tile width/height: 32px) for my 1920x1200 resolution.
so it seems not to be the right way to do this kind of thing.

another thing: i only need to draw those tiles that are currently on
the screen what is the best way to do this? i would use a batch to
draw all tiles but when i do this i would have to dynamically add and
remove sprites from the batch(es) and this seems costly

i read the heffalump tile engine code but there the tiles are
individually drawn and not in a batch.
with every draw two nestested loops will draw every sprite necessary
but isnt this inferior to using a batch?

3TATUK

unread,
Sep 8, 2008, 4:02:35 PM9/8/08
to pyglet-users
By 'batch' i'm guessing you mean list? Anyway.. don't store coord data
like that .. just attach an anchor_x and anchor_y to each image.

And... the only way I can think of at the moment for blitting only
those tiles that are 'on screen' is checking each image's anchor_x and
anchor_y for being <= window width and <= window height, respectively.

3TATUK

unread,
Sep 8, 2008, 4:04:55 PM9/8/08
to pyglet-users
* I meant >=, not <=. =>

josch

unread,
Sep 8, 2008, 4:19:21 PM9/8/08
to pyglet-users
no by batch i meant

batch = pyglet.graphics.Batch()
for img in images: #list of AbstractImages
pyglet.sprite.Sprite(img, batch=batch)
batch.draw()

which should be much faster than:

for sprite in sprites:
sprite.draw()

why is it faster to check each tile's position to be on the screen
than just addressing them by tile[x][y] with two nested loops??

Richard Jones

unread,
Sep 8, 2008, 5:44:54 PM9/8/08
to pyglet...@googlegroups.com
> another thing: i only need to draw those tiles that are currently on
> the screen what is the best way to do this? i would use a batch to
> draw all tiles but when i do this i would have to dynamically add and
> remove sprites from the batch(es) and this seems costly
>
> i read the heffalump tile engine code but there the tiles are
> individually drawn and not in a batch.
> with every draw two nestested loops will draw every sprite necessary
> but isnt this inferior to using a batch?

All of this is handled by the Cocos2d tile engine :)


Richard

josch

unread,
Sep 8, 2008, 8:10:50 PM9/8/08
to pyglet-users
well i just did not want to have the overhead of all those mighty
cocos transformations and animation stuff. i need it small and simple.
i just read a bit into the cocos tile engine code and it seem that on
each draw it fills a new pyglet batch with sprites - just as i
proposed in my first post.
maybe this really /is/ the best way to do it?

but then again - what about this issue with animated tiles?

Alex Holkner

unread,
Sep 8, 2008, 8:54:13 PM9/8/08
to pyglet...@googlegroups.com
On 9/9/08, josch <j.sc...@web.de> wrote:
>
> well i just did not want to have the overhead of all those mighty
> cocos transformations and animation stuff. i need it small and simple.
> i just read a bit into the cocos tile engine code and it seem that on
> each draw it fills a new pyglet batch with sprites - just as i
> proposed in my first post.
> maybe this really /is/ the best way to do it?

My PyWeek entry from March (http://partiallydisassembled.net/make_me/)
used tile rendering using batches. I didn't use sprites because the
creation time for each sprite was too high. I use Batch.add(..) to
create the vertices for the tile map. If all the images are located
in the same texture, the entire screen can be drawn as one primitive.
Culling is done by creating separate vertex lists for approximately
screen-sized areas of the map. These can then be added and removed
from the batch on-demand as the player moves around (tuning this took
quite some time). I didn't have any animated tiles, but these can be
done by either modifying the vertex texture coordinates to point into
the desired frame, or by swapping entire vertex lists (which would
probably be faster but more memory heavy).

I'm afraid the code in Make Me is far from publishable (it was written
in a week for a single game, after all), but you may find it useful to
mine for ideas.

Alex.

Richard Jones

unread,
Sep 8, 2008, 9:33:05 PM9/8/08
to pyglet...@googlegroups.com
On Tue, 9 Sep 2008, Alex Holkner wrote:
> My PyWeek entry from March (http://partiallydisassembled.net/make_me/)
> used tile rendering using batches. I didn't use sprites because the
> creation time for each sprite was too high.

Cocos tile engine uses sprites in a single batch, creating and destroying as
needed. It doesn't appear to suck when scrolling :)


Richard

josch

unread,
Sep 9, 2008, 5:26:20 AM9/9/08
to pyglet-users
yeah i just tested other few things.
batches seem the only choice as whenever i try to draw all sprites
individually it slows down beyond 1fps (for simple sprites and
animations).
if i draw the sprites in a batch then the fps goes all up to the 60fps
vsync value.
but with animations in the batch instead of raw sprites i still get
poor framerates so maybe i should prepare multiple batches for every
animation step so that this doesnt suck either.

stampson

unread,
Sep 9, 2008, 10:31:54 AM9/9/08
to pyglet-users

I did a test, filling the screen with animated sprites. It does slow
down a lot, although this machine was still able to maintain 30fps.

Based on my reading of the sprite class, it looks like using sprites
for tiling is perhaps not ideal - even less so with animated
textures. Because the sprite class allows for animations of variable
dimensions per frame, and different sprites sharing the same animated
texture are not necessarily in sync, every time the animation changes
the sprite has to recalculate several things.

If you are willing to go with the following restrictions, and write
some code for tile layers, I think you could get excellent
performance:

- all tiles oriented the same, all the same size
- all animated tiles animate in sync
- all frames of animation the same size

With the above restrictions, it should be possible to avoid most of
the recalculations which occur per animation frame when using
sprites. And each layer can be translated/scaled/rotated. If the
animations are in sync, the texture can be changed once per group,
regardless of whether the tile is animated or not.

So you would have a tile layer group, then a group for each texture
(animated or not). Each layer would be a static mesh of textured
quads, with a state change per base tile. Your performance would
depend more on the number of different textures, rather than the
quantity of tiles. Unless your levels are very large, you should not
have to worry about paging the tiles in/out, but doing so would not be
terribly hard.


-price

josch

unread,
Sep 9, 2008, 10:56:42 AM9/9/08
to pyglet-users
you speak about these lines:
vl = self.batch.add(self.cols * self.rows * 4, GL_QUADS, None,
('v2i', vertex_data),
('t3f', texture_data),
('c4B', color_data))
i still have a lot to learn so i opened up your make me code (nice
game btw) and will read and understand it in the next days.

what i do not want is to just use a faster lib like rabbyt sprites
(which afaik uses pyrex instead of ctypes to access opengl) just to
compensate for my still lacking skillz since i would really really
like to have everything in pure python so the user has to compile
nothing.
if you say that the following is doable with pyglet ctypes opengl and
high framerates even on hardware like radeon 9700 and athlon 2000+
style (yes this is old hardware but i do not want to do crysis here
right? :D ) then i am prepared to learn accordingly:
- 32x32pixel map tiles (water is animated)
- also playable on big resolutions - so up to ~2300 tiles on the
screen at the same time max
- two or three more optional layers for map objects like trees and
mountains
- those map objects are sometimes also animated

i started doing this in pygame and also got bad framerates so i hope
pyglet will save me here - i do not want pyrex/c bindings and will
only use them if i really have to thats why i ask the pro devs here ;)

thx for all your help
cheers

josch

On Sep 9, 2:54 am, "Alex Holkner" <alex.holk...@gmail.com> wrote:

Laurens

unread,
Sep 9, 2008, 11:08:10 AM9/9/08
to pyglet...@googlegroups.com
Hi,

that definately should be possible, but you might need to blit the tiles first
to a seperate surface/texture, and then blit that every gameframe instead of the
2300 tiles. If you want scrolling, you could just blit the borders and keep the
rest. For animated tiles etc. you might need to have a seperate layer, and only
update that.

But things like this, you should be able to pull off on the hardware you
specified; I did something similair in SDL back in the days, on similair
hardware.

Good luck!

Laurens

josch

unread,
Sep 9, 2008, 11:17:07 AM9/9/08
to pyglet-users
On Sep 9, 4:31 pm, stampson <stamp...@gmail.com> wrote:
> I did a test, filling the screen with animated sprites.  It does slow
> down a lot, although this machine was still able to maintain 30fps.
then i must've done something terribly wrong - i get only below 1fps
with this code: http://phpfi.com/351779 (there are 12 water tiles with
32x32px) the tile count in the nested loops matches for fullscreen
with my resolution.
>
> Based on my reading of the sprite class, it looks like using sprites
> for tiling is perhaps not ideal - even less so with animated
> textures.  Because the sprite class allows for animations of variable
> dimensions per frame, and different sprites sharing the same animated
> texture are not necessarily in sync, every time the animation changes
> the sprite has to recalculate several things.
so i should take the sprite code of pyglet and write my own with
removing unnecessary things?
>
> If you are willing to go with the following restrictions, and write
> some code for tile layers, I think you could get excellent
> performance:
>
> - all tiles oriented the same, all the same size
> - all animated tiles animate in sync
> - all frames of animation the same size
well in the end there will be more than water as terrain (but it is
the only animated terrain tile) - there will also be some objects on
the map from which some are also animated - these would be some more
layers above the terrain.
but yes for the terrain all tiles are 32x32 and water tiles are all
oriented the same and animate in sync
map objects will vary in size (width height being 32, 64, 96 or 128px)
and only sometimes be animated
>
> With the above restrictions, it should be possible to avoid most of
> the recalculations which occur per animation frame when using
> sprites.  And each layer can be translated/scaled/rotated.  If the
> animations are in sync, the texture can be changed once per group,
> regardless of whether the tile is animated or not.
>
> So you would have a tile layer group, then a group for each texture
> (animated or not).  Each layer would be a static mesh of textured
> quads, with a state change per base tile.  Your performance would
> depend more on the number of different textures, rather than the
> quantity of tiles.  Unless your levels are very large, you should not
> have to worry about paging the tiles in/out, but doing so would not be
> terribly hard.
>
> -price
thx for all the info! i still have to learn a lot on this topic - you
guys are very helpful in getting me started! :)

stampson

unread,
Sep 9, 2008, 4:33:37 PM9/9/08
to pyglet-users
I would start by getting an understanding of how pyglet uses vertex
lists, vertex attributes, groups, batches, etc, and the documentation
on setting opengl state per group. That won't be wasted knowledge, no
matter what you end up doing with pyglet. In my own experience,
getting pyglet to perform is a matter of understanding these things.
When you know how to do everything in a batch and have it all come out
in the right order, with minimal state changes, then you'll be flying.

I basically just wrote tons of little demo apps that made pyglet do
things with sprites, windows, etc and followed my nose wherever was
interesting. Then I picked a few challenges, like translating C/C++
demos to pyglet, and then bigger ones like a quake3 map renderer and
little physics toys.

Now I'm working on my first 'real' project. I ended up pulling an
idea off the shelf which I wasn't even considering for pyglet when I
started, but after all the exploration I see how it can work. And
I'll have it done faster with pyglet than anything else I know. My
wife actually commented that she thought I'd been playing a game all
day, but I was coding with pyglet =)

-price

josch

unread,
Sep 10, 2008, 7:54:16 AM9/10/08
to pyglet-users
hello again!

on my long travel to deeper pyglet knowledge i now tried to do as you
guys said and now use batches without creating sprites but by just
adding vertex and texture data to my batch.
here you can see my current demo code that oulines how i understand it
up to now: http://phpfi.com/352024

please correct me where I'm wrong but let me just shortly explain what
my understanding is about what the code does up to now:
upon creating the window my tile resource is loaded (despite the pcx
extension this is a png image). the resource module automagically adds
this to a TextureBin which manages a series of TextureAtlas'es which
itself stores images in one big texture. The resource will return a
TextureRegion that describes the placement of my image in this
TextureAtlas so i can access it in there.
next i set some lists and fill them once - this will be done later in
a loop to add more than one tile.
the vertex_data contains the coordinates of each square's corners on
the screen as four x/y coordinates.
the texture data stores the texture coordinates of my image in the
TextureAtlas.
the color_data stores the color of each of my tile's corner. this will
probably be overwritten by my texture.
then i add those four "corners" of my tile with their respective
coordinates and colors to the batch as a GL_QUAD.
the batch is then drawn in the on_draw() method

unfortunately my texture will not show up so a hint on what i'm still
doing wrong is very much appreciated.

thanks again for all your tips and help! i hope I'm a good student and
no bother here :)

cheers

josch

Alex Holkner

unread,
Sep 10, 2008, 8:21:44 AM9/10/08
to pyglet...@googlegroups.com
On 9/10/08, josch <j.sc...@web.de> wrote:
>
> hello again!
>
> on my long travel to deeper pyglet knowledge i now tried to do as you
> guys said and now use batches without creating sprites but by just
> adding vertex and texture data to my batch.
> here you can see my current demo code that oulines how i understand it
> up to now: http://phpfi.com/352024
>
> please correct me where I'm wrong but let me just shortly explain what
> my understanding is about what the code does up to now:
> upon creating the window my tile resource is loaded (despite the pcx
> extension this is a png image). the resource module automagically adds
> this to a TextureBin which manages a series of TextureAtlas'es which
> itself stores images in one big texture. The resource will return a
> TextureRegion that describes the placement of my image in this
> TextureAtlas so i can access it in there.
> next i set some lists and fill them once - this will be done later in
> a loop to add more than one tile.
> the vertex_data contains the coordinates of each square's corners on
> the screen as four x/y coordinates.
> the texture data stores the texture coordinates of my image in the
> TextureAtlas.
> the color_data stores the color of each of my tile's corner. this will
> probably be overwritten by my texture.

Actually the vertex colours will scale the texture colour; effectively
tinting it. Usually the colour needs to be white, which you've done.

> then i add those four "corners" of my tile with their respective
> coordinates and colors to the batch as a GL_QUAD.
> the batch is then drawn in the on_draw() method
>
> unfortunately my texture will not show up so a hint on what i'm still
> doing wrong is very much appreciated.

Just need to enable texturing and bind the texture. Ideally you would
do this in the group, so you can use different textures within the
same batch; but for now you can just add it where your blend state is
set.

glEnable(self.tile.target)
glBindTexture(self.tile.target, self.tile.id)

Alex.

>

josch

unread,
Sep 10, 2008, 10:24:18 AM9/10/08
to pyglet-users
wohoo this worked!! \o/
http://phpfi.com/352060
i already used the TextureGroup to automatically apply the state
changes you mentioned (by looking at the pyglet source TextureGroup
does excactly what you posted and even does glDisable() ) and also
draw a 60x38 grid of random water tiles (without animation yet).
however there are still a few issues:
first i disabled vsync and added an update function that (i hope) is
called as often as possible and get only around 110fps with core2duo/
gma965 - when i uncomment the clear() function in on_draw() i get up
to 180fps. but considering all the other stuff i will add (more layers
and animated tiles and map objects) isnt that a bit low? why?
also i got a bit troubled with the TextureGroup. It needs a texture
that it later will enable and bind and this works fine with using a
TextureAtlas as in my current code but when i try to use the
recommended resource.image module which automatically will create new
TextureAtlas'es - how do i get the (maybe multiple) textures then?

future questions:
when i now want to move on the map i have to refill the batch - i do
this via deleting the vertex_list and refilling the batch again with
add() right?
for animation it should suffice to only change the texture coordinates
in the vertex_list? another way to do animation would be to prepare
several vertex_lists with each animation step? i have to try out both
methods and compare how they perform later but at least for map
objects i have to change the textures directly as the objects there do
have different numbers of animation frames.

i hope i got all my questions covered now :)

thx for sharing your expertise!

On Sep 10, 2:21 pm, "Alex Holkner" <alex.holk...@gmail.com> wrote:

Lucio Torre

unread,
Sep 10, 2008, 11:02:36 AM9/10/08
to pyglet...@googlegroups.com
On Mon, Sep 8, 2008 at 9:10 PM, josch <j.sc...@web.de> wrote:
>
> well i just did not want to have the overhead of all those mighty
> cocos transformations and animation stuff. i need it small and simple.

One a side note, you can use cocos mostly without overhead by creating
a scene and replacing its draw method.

You control what transformations you get on that scene. So you can be
as fast as you want/can. But you also get the benefits of cocos if you
want to add more stuff.

Lucio.

Alex Holkner

unread,
Sep 10, 2008, 11:33:11 AM9/10/08
to pyglet...@googlegroups.com
On 9/11/08, josch <j.sc...@web.de> wrote:
>
> wohoo this worked!! \o/
> http://phpfi.com/352060
> i already used the TextureGroup to automatically apply the state
> changes you mentioned (by looking at the pyglet source TextureGroup
> does excactly what you posted and even does glDisable() ) and also
> draw a 60x38 grid of random water tiles (without animation yet).
> however there are still a few issues:
> first i disabled vsync and added an update function that (i hope) is
> called as often as possible and get only around 110fps with core2duo/
> gma965 - when i uncomment the clear() function in on_draw() i get up
> to 180fps. but considering all the other stuff i will add (more layers
> and animated tiles and map objects) isnt that a bit low? why?

Make sure you at least run python with "-O" option to disable OpenGL
error checking, which is expensive. Keep in mind that most of the
benefits of using batches come when batches are large -- you may find
that you get only reasonable performance now, but that same reasonable
performance with 10x the amount of geometry (in the same batch).

> also i got a bit troubled with the TextureGroup. It needs a texture
> that it later will enable and bind and this works fine with using a
> TextureAtlas as in my current code but when i try to use the
> recommended resource.image module which automatically will create new
> TextureAtlas'es - how do i get the (maybe multiple) textures then?

Use the texture target and id from the region returned by
resource.image. For images on a shared texture atlas (common case
with small images), the target and id will be the same. You can
safely create multiple TextureGroup's with the same target and id --
Batch will know that they can be grouped together efficiently if your
TextureGroup class correctly implements __eq__ and __hash__.

>
> future questions:
> when i now want to move on the map i have to refill the batch - i do
> this via deleting the vertex_list and refilling the batch again with
> add() right?
> for animation it should suffice to only change the texture coordinates
> in the vertex_list? another way to do animation would be to prepare
> several vertex_lists with each animation step? i have to try out both
> methods and compare how they perform later but at least for map
> objects i have to change the textures directly as the objects there do
> have different numbers of animation frames.

Sounds like a plan.

Alex.

josch

unread,
Sep 10, 2008, 11:40:01 AM9/10/08
to pyglet-users
hey lucio!

my decision against cocos2d has several reasons:
first and most important there is the learning aspect - i do want to
learn how these things work by doing my own experiments!
second i read a lot in the cocos code to learn - this is how i drew my
first tileset with adding sprites to a batch like cocos does.

i think i need too little from cocos to make it a useful dependency
and for the things i do use i would very much like to learn from cocos
how it does them and improve those for my specific application.
for example cocos has superb animation, particle, text and transition
effects but i need none of them. for the sprites i need no scaling,
rotating etc...
interesting for me are scenes and menu but i think that is not enough
for a reason to require cocos as a dependency

as for the cocos tile engine:
- cocos uses sprites to draw the batch (what i was told and
experienced is slower than using vertex lists)
- i need animated tiles and map objects
- i need the map objects' shadows to blit in two different alpha
values to the background terrain
as far as my knowledge goes now i'm better off in doing my own tile
engine

you sure did a great work with cocos2d and please do correct me if i'm
wrong with what i said :)

cheers

josch

On Sep 10, 5:02 pm, "Lucio Torre" <lucio.to...@gmail.com> wrote:

josch

unread,
Sep 10, 2008, 1:34:55 PM9/10/08
to pyglet-users
On Sep 10, 5:33 pm, "Alex Holkner" <alex.holk...@gmail.com> wrote:
> On 9/11/08, josch <j.scha...@web.de> wrote:
> Use the texture target and id from the region returned by
> resource.image.  For images on a shared texture atlas (common case
> with small images), the target and id will be the same.  You can
> safely create multiple TextureGroup's with the same target and id --
> Batch will know that they can be grouped together efficiently if your
> TextureGroup class correctly implements __eq__ and __hash__.

i did this first as i saw that resource.image also returned a simple
TextureRegion.
I also observed that the target and id will stay the same for the
first tiles and will change as more are added and new textures have to
be created.
My problem which i still do not fully understand is that when i now
load a lot of tiles and new textures with something like this:
images = [pyglet.roucource.image("/data/tiles/%d.png"%i) for i in
xrange(100)]
maybe this code will create several different Textures so that not all
of the TextureRegions returned do have the same target and id.
then i will create a group with a texture passed to it - or two groups
because two textures where needed to store those images? where do i
know that from?
when i then do batch.add() i have to specify ONE group and this group
will only update one texture so i kind of have to know which images i
can group together depending on in which texture they where put by
resource.image.
do i have to get this info manually by iterating over the created
TextureRegions and finding out how many Textures where needed?
you mentioned i should use several TextureGroups but this would imply
that i do have to call batch.add() several times for each group that i
create, right? i would then start creating one group per image loaded
and doing a batch.add() for each image separately.
but isnt it better to add as many vertices as possible in one
batch.add() ?

Alex Holkner

unread,
Sep 10, 2008, 2:10:28 PM9/10/08
to pyglet...@googlegroups.com
On 9/11/08, josch <j.sc...@web.de> wrote:
>

Use one group for every image, if you like. Batch will know how to
merge them back together.

> do i have to get this info manually by iterating over the created
> TextureRegions and finding out how many Textures where needed?
> you mentioned i should use several TextureGroups but this would imply
> that i do have to call batch.add() several times for each group that i
> create, right? i would then start creating one group per image loaded
> and doing a batch.add() for each image separately.
> but isnt it better to add as many vertices as possible in one
> batch.add() ?

Nope, once it's in the batch, if the groups are compatible (according
to their __eq__ and __hash__ methods), it doesn't matter how many
vertex lists were created with Batch.add; they all end up in the same
vertex domain.

Alex.

Lucio Torre

unread,
Sep 10, 2008, 8:32:07 PM9/10/08
to pyglet...@googlegroups.com
On Wed, Sep 10, 2008 at 12:40 PM, josch <j.sc...@web.de> wrote:
>
> hey lucio!
>
> my decision against cocos2d has several reasons:
[snip reasons]

thanks for the feedback josch! im just too much into being a salesman maybe :)

Lucio.

Richard Jones

unread,
Sep 10, 2008, 9:57:19 PM9/10/08
to pyglet...@googlegroups.com
On Thu, 11 Sep 2008, josch wrote:
> as for the cocos tile engine:
> - cocos uses sprites to draw the batch (what i was told and
> experienced is slower than using vertex lists)

The pyglet Sprites used by the cocos tile engine use vertex lists underneath -
approximately as fast as implementing a direct-to-vertex-list approach, with
a small overhead when the visible tiles set changes. It has the benefit that
it can use animated tiles through the standard pyglet Sprite animation
mechanism (I believe, I've not actually tried to use them).


Richard

josch

unread,
Sep 11, 2008, 1:50:38 PM9/11/08
to pyglet-users
Hi!
I wanted to give a short video on how far I came with your great help
so that you can see that your time wasnt in vain that that now there
is one more out there that actively dives into pyglet :).

http://rabenfrost.net/josch/heroes/moving.ogg
o animated water tiles
o moving by keyboard (even diagonally) and by dragging the mouse

I decided not to use the resource module but to manually use a
TextureAtlas that is just big enough to hold all the water tiles
(384x416 px for 156images) with their animation frames.
This way I can do animation by just changing the texture coordinates
in the vertex lists without any additional effort (for example without
checking if the next animation frame is still in the same texture as
the last).

Now I'm gonna wrap everything up in nice pythonic classes and stuff
and add the other layers.

It's amazing how much I learned the past three days!

cheers

josch

Alex Holkner

unread,
Sep 11, 2008, 8:24:49 PM9/11/08
to pyglet...@googlegroups.com
On 9/12/08, josch <j.sc...@web.de> wrote:
>
> Hi!
> I wanted to give a short video on how far I came with your great help
> so that you can see that your time wasnt in vain that that now there
> is one more out there that actively dives into pyglet :).
>
> http://rabenfrost.net/josch/heroes/moving.ogg
> o animated water tiles
> o moving by keyboard (even diagonally) and by dragging the mouse
>
> I decided not to use the resource module but to manually use a
> TextureAtlas that is just big enough to hold all the water tiles
> (384x416 px for 156images) with their animation frames.
> This way I can do animation by just changing the texture coordinates
> in the vertex lists without any additional effort (for example without
> checking if the next animation frame is still in the same texture as
> the last).

Sounds good. Note that the TextureAtlas above will automatically be
sized up to 512x512 (textures usually need to have dimensions of
powers of 2), so you can use some of the extra space in there for
"free" if you need it.

Alex.

josch

unread,
Sep 13, 2008, 5:58:43 AM9/13/08
to pyglet-users
As all begins to get bigger I need some additional advice.
For my viewport I manage vertext lists that i only need to modify in
their texture or coordinates to move around the map or do animations.
I only need to delete them and create new vertex lists with
batch.add() when the window is being resized.
the rest of the time i only access the vertex lists and modify their
parameters (tex_coords and vertices).
this is quite fast but the problem comes in when i need more than one
texture to draw my map because i can no longer simply swap the
textureregion when moving and animating as eventually the texture
itself has to change too.
as i understand it now i have to do a batch.add() again to attach a
TextureGroup that will do this for me.
again this works fine but calling batch.add() for every movement is
MUCH slower than just switching out the textureregions as i did
before.
any ideas on that?

cheers

josch

Alex Holkner

unread,
Sep 13, 2008, 8:25:16 AM9/13/08
to pyglet...@googlegroups.com
On 9/13/08, josch <j.sc...@web.de> wrote:
>
> As all begins to get bigger I need some additional advice.
> For my viewport I manage vertext lists that i only need to modify in
> their texture or coordinates to move around the map or do animations.
> I only need to delete them and create new vertex lists with
> batch.add() when the window is being resized.
> the rest of the time i only access the vertex lists and modify their
> parameters (tex_coords and vertices).
> this is quite fast but the problem comes in when i need more than one
> texture to draw my map because i can no longer simply swap the
> textureregion when moving and animating as eventually the texture
> itself has to change too.
> as i understand it now i have to do a batch.add() again to attach a
> TextureGroup that will do this for me.
> again this works fine but calling batch.add() for every movement is
> MUCH slower than just switching out the textureregions as i did
> before.
> any ideas on that?

You can actually migrate a vertex list from one group to another, but
this has a similar performance penalty. Ideally you would keep frames
of an animation in a single texture; vertices can then keep their
group. There's no problem with having multiple groups in a batch;
this is actually quite an efficient way of managing the drawing of
several textures.

Alex.

josch

unread,
Sep 13, 2008, 11:03:23 AM9/13/08
to pyglet-users
I do have all frames of the same animation in the same texture.
The problem arises when doing movements by just swapping the texture
coordinates.
say i have a 1x2 array of vertex lists. one is the water animation and
one is a static terrain tile.
i animate this by switching the textureregion of the water tile and i
move the scene by doing the same.
but when i want to draw the static terrain in the same vertex lists
where the animated water once was it is not enough to just switch the
vertex list's texture region. this will just fail and display junk.
my solution is to delete my two vertex lists with the water and the
static terrain, and create new ones by adding them to the batch in
their new positions.
i seem to lack a bit understanding here and hope you get what i want
to do.
in case this is not clear here is the code i use for now: http://phpfi.com/352930
the vertex_list list is created with several batch.add() for each tile
that are to be drawn on the screen.
for movement it is then only moved max. 32 px in each direction. after
that it is drawn at its original position and the textureregions are
swapped.
i hope you find some free time for this after pygame's end :)

On Sep 13, 2:25 pm, "Alex Holkner" <alex.holk...@gmail.com> wrote:

josch

unread,
Sep 13, 2008, 6:50:39 PM9/13/08
to pyglet-users
oups... after pyweek's end of course... ^^ my bad... :D
i will try out some other things in the train tomorrow.
besides the problem that i found no way to switch the texture in my
vertex list besides calling batch.add() again there is another issue
that tiles with transparency do not get transparent despite

pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA,
pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)

beeing set. the mouse cursor renders fine with transparency too.
i will have a look at those tomorrow and hope that i find anything
useful from the make me and cocos2d source.
any suggestions on sourcecode that dynamically draws multiple textures
on the screen without calling batch.add() ?
if possible i would like to create my vertex list only once (and on
resize of course) with batch.add() and after that only manipulate the
returned vertex lists while also beeing able to dynamically swap the
textures used in each vertex list.

so nice pyweek everybody! i hope there is much new educational code
for me to read!

josch

unread,
Sep 14, 2008, 2:18:08 AM9/14/08
to pyglet-users
okay i got the trick.
to do a vertex_list.delete() and batch.add() for each movement is no
problem as long as one does not pack each tile into its own vertex
list so that delete() and batch.add() are called very often (this
seems much overhead) but organizes all tiles with the same texture in
one vertex list that is added with one batch.add() per texture used to
draw the scene.
this way i call batch.add() only twice per redraw (because for now i
only do have two textures) and not once for every tile which gets
unacceptable if there are ~2300 tiles when i go fullscreen.
no i wonder how to best organize my images into textures. as i figured
it's best to have as few textures as possible to only need few
batch.add() calls. but then the question is how big a texture should
be at maximum? i have a few thousand tile types i want to draw.
plz correct me if i'm heading the wrong way ;)
cheers

josch

Alex Holkner

unread,
Sep 14, 2008, 5:27:37 AM9/14/08
to pyglet...@googlegroups.com
On 9/14/08, josch <j.sc...@web.de> wrote:
>
> okay i got the trick.
> to do a vertex_list.delete() and batch.add() for each movement is no
> problem as long as one does not pack each tile into its own vertex
> list so that delete() and batch.add() are called very often (this
> seems much overhead) but organizes all tiles with the same texture in
> one vertex list that is added with one batch.add() per texture used to
> draw the scene.

If a vertex list contains only tiles with the same texture, then you
don't need to remove/add it from/to the batch just to change texture;
just change the texture on the vertex list's group.

Forgive me if I misunderstand; I'm not entirely following your
description, and am a bit fuzzy headed after PyWeek to be reading
source code.

Alex.

josch

unread,
Sep 14, 2008, 7:15:17 AM9/14/08
to pyglet-users
yeah this is exactly what i do
i create a vertex list for each texture so that i am able to just swap
out the textureregion for animation and the coords for movement. i
think everything works now as expected and fast too so i dont think
that i still do much wrong ;)
but since i want to fill the textures my own for this reason it would
be nice to know how far it is reasonable to go for the texture size.
the maximum on my hardware seems to be 2048x2048 but what is a save
value on even five year old gfx cards?
i very much look forward to your pyweek contribution so please let me
be no hindrance :) since you cooperate with biccy again i'm very eager
to see her nice artwork, "make me" was one of the code pieces i
learned from the most so far!
cheers
josch

On Sep 14, 11:27 am, "Alex Holkner" <alex.holk...@gmail.com> wrote:

Alex Holkner

unread,
Sep 14, 2008, 7:43:00 AM9/14/08
to pyglet...@googlegroups.com
On 9/14/08, josch <j.sc...@web.de> wrote:

> but since i want to fill the textures my own for this reason it would
> be nice to know how far it is reasonable to go for the texture size.
> the maximum on my hardware seems to be 2048x2048 but what is a save
> value on even five year old gfx cards?

I haven't seen a graphics card that couldn't handle a 2048x2048
texture (that wasn't also broken in many other ways), so that's a
pretty safe assumption. You can query the max texture size at runtime
with glGet(), and have your program adapt in any case.

Alex.

josch

unread,
Sep 14, 2008, 3:28:25 PM9/14/08
to pyglet-users
another attempt to make the most of pyglet:

forget the code, it's unreadable anyway.
here are my ideas:

given the following view of a map:
(different chars mean there are different textures used)

ooooooooooooAAAA
oooooooooooooAAA
XoooooooooooooAA
XXoooooooooooooA
XXoooooooooooooo
Xooooooooooooooo
oooooooooooooooo

now we move the camera to the east by two steps

ooooooooooAAAAAA
oooooooooooAAAAA
ooooooooooooAAAA
oooooooooooooAAA
ooooooooooooooAA
oooooooooooooooA
oooooooooooooooo

how do we do this?
well, there are three posibilities that came to my mind:

1.
this is what i currently do:
for each different texture used by the tiles in the scene i create a
seperate vertex list with batch.add(). this would be three lists in
the first map view and two in the second containing all those tiles
that use this texture.
when the map is moved i only delete() the old lists and create new
ones again with batch.add()
actually up to now this is quite fast and i get 600fps while scrolling
but of course i dont know how it scales.

2.
one could also create one vertex list for every tile currently visible
on the screen. so there would be tiles_x*tiles_y vertex lists with one
GL_QUAD with 4 vertices each.
movement would be done by swapping the textureregions of every tile
and also swap the texture (respectively the group) by migrating the
vertexlist if necessary

3.
a last option that came to my mind is to dynamically delete and create
vertex lists.
in the example above one would delete() the list for the X texture and
resize() the other two.
then setting the new coordinates and textureregions in the resized
lists.

------------------------------------

and some additional thoughts about storing my tile images in textures.

of course i could use resource.image and i would like to use it as it
is nicely distribution independent (also usable with py2exe and
py2app) but with using it i would add some overhead in animation and
movement since i would have to check whether the new animation frame
is still in the same texture or not and then migrating the vertex list
to the new group (again overhead) and after that back again.
plz correct me but for this reason, isnt it most practical to let all
animation frames be in one texture?
and i see no way to do this with the ressource module so i will
probably implement my own loading mechanisms while borrowing stuff
from resource.py. is this the right way to do it?

Ragzouken

unread,
Sep 14, 2008, 5:22:34 PM9/14/08
to pyglet-users
Another option could be creating a custom group that uses glTranslate
as part of it's state to shift the view. You'd have to manually remove
offscreen tiles from the batch still.

I'm not sure if that's a horrible hack to put that into the group
system, but using glTranslate to move large amounts of rendering seems
like a good idea to me. (But I'm far from an expert ;D)

josch

unread,
Sep 16, 2008, 4:39:38 AM9/16/08
to pyglet-users
I now implemented the second method as a test.
moving around with only changing texture coords of each of the
displayed tiles' vertex lists is obviously a little bit faster than
creating new vertex lists the whole time - even if there are more
vertex lists this way.
animation speed stays the same whether i change the tex_coords of one
big vertex list for the water like in method 1 or change the
tex_coords for every vertex list tile in method 2.
one problem:
how do i update the group a vertex list belongs to? i have to do that
with migrate() right? but what do i enter for the batch? i constantly
get:

File "/usr/lib/python2.5/site-packages/pyglet/graphics/__init__.py",
line 409, in migrate
vertex_list.migrate(domain)
File "/usr/lib/python2.5/site-packages/pyglet/graphics/
vertexdomain.py", line 381, in migrate
new_start = domain.allocator.alloc(self.count)
File "/usr/lib/python2.5/site-packages/pyglet/graphics/
allocation.py", line 187, in alloc
raise AllocatorMemoryException(self.capacity + size - free_size)
pyglet.graphics.allocation.AllocatorMemoryException

so i'm still doing something wrong. is there an example of using
migrate - couldnt find one: not in cocos and not in the pyglet
examples or make me.
isn't changing a vertex list's texture a good idea?

i also still experiment with resource.image - by using it i would have
to change the texture even more often afaik

Alex Holkner

unread,
Sep 16, 2008, 5:50:50 AM9/16/08
to pyglet...@googlegroups.com
On Tue, Sep 16, 2008 at 6:39 PM, josch <j.sc...@web.de> wrote:
>
> I now implemented the second method as a test.
> moving around with only changing texture coords of each of the
> displayed tiles' vertex lists is obviously a little bit faster than
> creating new vertex lists the whole time - even if there are more
> vertex lists this way.
> animation speed stays the same whether i change the tex_coords of one
> big vertex list for the water like in method 1 or change the
> tex_coords for every vertex list tile in method 2.
> one problem:
> how do i update the group a vertex list belongs to? i have to do that
> with migrate() right? but what do i enter for the batch? i constantly
> get:
>
> File "/usr/lib/python2.5/site-packages/pyglet/graphics/__init__.py",
> line 409, in migrate
> vertex_list.migrate(domain)
> File "/usr/lib/python2.5/site-packages/pyglet/graphics/
> vertexdomain.py", line 381, in migrate
> new_start = domain.allocator.alloc(self.count)
> File "/usr/lib/python2.5/site-packages/pyglet/graphics/
> allocation.py", line 187, in alloc
> raise AllocatorMemoryException(self.capacity + size - free_size)
> pyglet.graphics.allocation.AllocatorMemoryException
>
> so i'm still doing something wrong.

Nope, that's a bug. Post a complete (small?) example that reproduces
it, please.

is there an example of using
> migrate - couldnt find one: not in cocos and not in the pyglet
> examples or make me.
> isn't changing a vertex list's texture a good idea?

It's a bit hairy ;-)

Alex.

josch

unread,
Sep 16, 2008, 7:41:33 AM9/16/08
to pyglet-users
okay i managed to boil my code down to 1/6 of its original size and
simulated my drawing: http://phpfi.com/353846
you can take and 32x32 image as the tile.
but i still suspect that there is something wrong on my side ;)

why is migrating vertex lists hairy?

when i combine resource.image with animation then i HAVE to switch the
group as i have no direct control over the texture my frames will be
packed into and the new animation frame could be in a new texture.

i also have to switch the group (respctively migrate the vertex list)
when i want to move around the map by switching the tile texture in my
vertex lists (which is what i have to do because there are more tile
types than even a 2048x2048 texture can handle)

so why is it hairy and not used very often? do i do it wrong?

this night a fourth method to do movement came to my mind and it's a
variance of my second method:
one could first delete tiles (respectively vertex lists) that will go
off screen,
then move the tiles that are still to be drawn
and then adding new vertex lists with batch.add() but obviously only
on the border
with this method no group changing would be necessary

i still do not know what method should be prefered.
method 1 seems to be a little too much overhead because batch.add() is
called to often - but is still acceptably fast
method 2 is like 4% faster than method 1 but needs to change the
texture of the vertex lists with migrate
method 3 seems a bit complicated because of the texture management
method 4 is also more complicated but combines method 1 and 2 to not
need any texture change

there is still the issue whether i should use resource.image() or not
- is the checking or storing of the texture each tile or animation
frame is packed into and the vertex list migration on animation worth
the convenience?

http://pyglet.googlecode.com/svn/trunk/DESIGN <= i read about scene2d.
how are you gonna do it? will your approach solve my problems?

On Sep 16, 11:50 am, "Alex Holkner" <alex.holk...@gmail.com> wrote:

Alex Holkner

unread,
Sep 16, 2008, 8:31:32 AM9/16/08
to pyglet...@googlegroups.com
On Tue, Sep 16, 2008 at 10:41 PM, josch <j.sc...@web.de> wrote:
>
> okay i managed to boil my code down to 1/6 of its original size and
> simulated my drawing: http://phpfi.com/353846
> you can take and 32x32 image as the tile.
> but i still suspect that there is something wrong on my side ;)

Thanks for the test case. Fixed in r2257 (in
branches/pyglet-1.1-maintenance) and r2258 (trunk).

>
> why is migrating vertex lists hairy?
>
> when i combine resource.image with animation then i HAVE to switch the
> group as i have no direct control over the texture my frames will be
> packed into and the new animation frame could be in a new texture.
>
> i also have to switch the group (respctively migrate the vertex list)
> when i want to move around the map by switching the tile texture in my
> vertex lists (which is what i have to do because there are more tile
> types than even a 2048x2048 texture can handle)
>
> so why is it hairy and not used very often? do i do it wrong?

It's just a complicated and error-prone (as you've discovered) method.
It's quite costly to do (though not as costly as delete+add), and if
you can think of other ways of organising your vertices, they'll
probably work better.

>
> this night a fourth method to do movement came to my mind and it's a
> variance of my second method:
> one could first delete tiles (respectively vertex lists) that will go
> off screen,
> then move the tiles that are still to be drawn
> and then adding new vertex lists with batch.add() but obviously only
> on the border
> with this method no group changing would be necessary

You don't need to move the tiles in this case: just glTranslate the
whole scene. This is similar to the method I used in Make Me, except
that I was adding several rows (about 2/3rds of a screenful) of tiles
at a time, rather than just the one that was required. Remember that
batches work fastest when you don't touch them, and there's usually
very little penalty for rendering off-screen (if the memory transfer
is fast, which is what batch gives you).

>
> i still do not know what method should be prefered.
> method 1 seems to be a little too much overhead because batch.add() is
> called to often - but is still acceptably fast
> method 2 is like 4% faster than method 1 but needs to change the
> texture of the vertex lists with migrate
> method 3 seems a bit complicated because of the texture management
> method 4 is also more complicated but combines method 1 and 2 to not
> need any texture change
>
> there is still the issue whether i should use resource.image() or not
> - is the checking or storing of the texture each tile or animation
> frame is packed into and the vertex list migration on animation worth
> the convenience?

resource.image doesn't give that much convenience. The image packing
procedure is available in the TextureBin and TextureAtlas classes, and
pyglet.resource.file gives you the path/zip-finding shortcut.
Creating your own resource function that packs into specific textures
shouldn't be difficult.

>
> http://pyglet.googlecode.com/svn/trunk/DESIGN <= i read about scene2d.
> how are you gonna do it? will your approach solve my problems?

That's a super-old document. (Richard: didn't we delete it?). I'm not
working on that area any more at all, but Richard's more or less taken
over (in the cocos2d project).

Alex.

josch

unread,
Sep 25, 2008, 10:10:17 AM9/25/08
to pyglet-users
hey alex!

thx for the long and helpful response!
i did exactly as you suggested:
* no usage of vertex list migrations but storing all tiles in one
2048x2048 textureatlas that i manually fill with resource.file images
* moving around with glTranslatef() rather than modifying the vertex
coords
* drawing 3/4 of the scene offscreen so that i have to update the
texture coords of my vertex list *very* seldom for moving around the
map

now another question: as i understood it, drawing offscreen makes
sense as it will leave the batch untouched a long time and thus will
increase performance. but recently i realized that i might have
accomplished this for now with the offscreen drawing but later on i
will have to change the batch anyway a *lot* of times as i have to
animate the water tiles and some map objects and as far as i
understood you, switching the texture coords for animation is touching
the batch so does it still make any sense to draw offscreen if the
batch will be touched regularly anyways?
cheers

josch

Luke Paireepinart

unread,
Sep 25, 2008, 10:40:33 AM9/25/08
to pyglet...@googlegroups.com
You could just keep track of animation state of each off-screen object (you must be keeping track of animation state (i.e. current frame, etc.) to animate anyway, right?)
and not actually switch the textures until they become on-screen, couldn't you?

Luke Paireepinart

unread,
Sep 25, 2008, 10:40:59 AM9/25/08
to pyglet...@googlegroups.com
Oh, I think I misunderstood you.   You mean you'd have to animate the on-screen objects, right?

josch

unread,
Sep 25, 2008, 11:14:34 AM9/25/08
to pyglet-users
my problem:
with drawing a lot of tiles offscreen i avoid having to update the
vertex lists' texture coords on every move but instead only on larger
movements and hence do not have to modify my batch very often - which
is good because a batch works fastest when not modified.

with "not very often" i mean: you can go around a 1600x1600 map in a
800x800 window without ANY retexturing of the vertex list EVER because
in this case the whole map would be drawn in one fell swoop (with 3/4
being offscreen of course)

but with my animations taking place every 1/6 second i have to modify
the batch anyway so i see no more need in drawing stuff offscreen to
prevent the batch from being modified - i do this anyway with the
animations.

as for the animation state: it doesnt matter but i store the current
state in the class i create for each object on the map so this is no
concern.

On Sep 25, 4:40 pm, "Luke Paireepinart" <rabidpoob...@gmail.com>
wrote:
> Oh, I think I misunderstood you.   You mean you'd have to animate the
> on-screen objects, right?

no, it's only about that i animate (and with this modify the batch)
periodically anyway with so there is no longer any point in reducing
the number of batch modifications by drawing stuff offscreen.

Dany0

unread,
Sep 25, 2008, 11:23:57 AM9/25/08
to pyglet-users
ok, I just saw this one. THIS IS HORRIBLE, CAN ANYONE SAY WHAT'S THIS
THREAD ABOUT?

josch

unread,
Sep 25, 2008, 12:50:42 PM9/25/08
to pyglet-users
it's about "how to make a fast tile engine with pyglet - from newbie
to pro"
all i used to get this far (as a complete pyglet and opengl beginner)
is the pyglet and make-me source, the pyglet api documentation and
this thread. so theoretically the same should be achievable for others
that only have these references and manuals (a lot of "manual" i got
from the pyglet source comments ;) ).
you can also watch some old videos about my past efforts on this -
they are also in this thread but made from very early versions of my
code.
i think all of this shows nicely how easy it is to get into the world
of game development using pyglet.

Alex Holkner

unread,
Sep 25, 2008, 5:25:32 PM9/25/08
to pyglet...@googlegroups.com

It may start to make less sense... it's a judgement call you'll have
to make based on your application behaviour. Luke's suggestion about
only animating on-screen texture coordinates while keeping off-screen
vertices around seems reasonable as well.

Alex.

josch

unread,
Sep 26, 2008, 3:58:11 AM9/26/08
to pyglet-users

On Sep 25, 11:25 pm, "Alex Holkner" <alex.holk...@gmail.com> wrote:
> It may start to make less sense... it's a judgement call you'll have
> to make based on your application behaviour.
exactly!
but to make this decision i have to get an understanding of what will
speed up things and what wont.
in make-me drawing a lot of offscreen was okay as the landscape was
not animated and the batch was really barely touched.

I quote you: "Remember that batches work fastest when you don't touch
them"

what does touching mean in this sense? is touching changing the
texture coordinate?
is touching every single modification to the vertex lists?

and is there a difference between different amounts of changes i can
do to the batch? like whether i update one vertex list in the batch or
two or whether i update a lot of texture coordinates in a given vertex
list or only a few ones.

i think these should be the final facts i have to know to make my
decisions on how to organize the stuff.

thanks again for all your help! i try to help others in #pyglet irc
too with my new knowledge - i hope i can be of some help for others
diving into this topic.

Python Nutter

unread,
Sep 26, 2008, 5:03:56 AM9/26/08
to pyglet...@googlegroups.com
This is the best damn thread I have read in a long time! Thats what
its about :-)

Thanks to josch and Alex I've learned a hell of a lot and I thank them
for the discourse. It makes me want to play along but I've just moved
house and no time from the wife to play until the house is sorted and
boxes unpacked.

Cheers for the convo guys,
PN

2008/9/26 Dany0 <men...@seznam.cz>:

Ragzouken

unread,
Sep 26, 2008, 5:06:38 AM9/26/08
to pyglet-users
Is it any more efficient to change only the y coords of a vertex
list's texture coords rather than both x and y if you know that frames
of the same animation are vertically aligned?

Alex Holkner

unread,
Sep 26, 2008, 5:35:30 AM9/26/08
to pyglet...@googlegroups.com
On 9/26/08, josch <j.sc...@web.de> wrote:
>
>
> On Sep 25, 11:25 pm, "Alex Holkner" <alex.holk...@gmail.com> wrote:
> > It may start to make less sense... it's a judgement call you'll have
> > to make based on your application behaviour.
>
> exactly!
> but to make this decision i have to get an understanding of what will
> speed up things and what wont.
> in make-me drawing a lot of offscreen was okay as the landscape was
> not animated and the batch was really barely touched.
>
> I quote you: "Remember that batches work fastest when you don't touch
> them"
>
> what does touching mean in this sense? is touching changing the
> texture coordinate?
> is touching every single modification to the vertex lists?

It just means that (like anything with computers), the less you do,
the faster it happens. Changing the size of a vertex domain is more
expensive than just modifying one in place, and creating a new domain
(i.e., by creating a vertex list that uses a previously unseen vertex
format) is still more expensive.

>
> and is there a difference between different amounts of changes i can
> do to the batch? like whether i update one vertex list in the batch or
> two or whether i update a lot of texture coordinates in a given vertex
> list or only a few ones.

For this kind of information you're best off creating some simple test
cases and measuring the performance. Bear in mind that these
measurements will be dependent on your video driver, and whether or
not VBOs are enabled.

Alex.

Alex Holkner

unread,
Sep 26, 2008, 5:37:47 AM9/26/08
to pyglet...@googlegroups.com

In general, yes; though the logic in iterating past every second (or
third) float in a vertex list may outweigh the benefit. Note that
using a slice with a step effectively implements the same operation,
though pyglet handles the iteration for you (probably slower than you
could have done, due to generality).

Alex.

Casey Duncan

unread,
Sep 26, 2008, 11:45:58 AM9/26/08
to pyglet...@googlegroups.com

I don't know if this was suggested before (I skimmed the thread and
didn't see mention), but it is possible to animate the vertex
coordinate without changing the vertex list itself by using a shader.
A possible method would be to store the tile type for each vertex as
an additional vertex attribute and pass a varying "time" value from
your application to the shader program to control the animation. The
shader would then alter the texture coordinates (perhaps shifting them
along the Y or Z for a 3D texture) according to the vertex attribute
(for instance leaving the coords alone for non-animated tiles) and the
time value. The major downside to this approach is it requires opengl
2.0, which may be a non-starter. The upside is zero CPU cost for
shaders running in the hardware.

Alternately, you could divide your vertex list into animated and
non-animated tiles and draw them separately. In one pass you could lay
down the non-animated tiles, and in a second the animated ones. So
long as the latter does not overdraw the non-animated tiles, it will
look the same and allow you to have the non-animated tiles have a
static vertex list. Thus you update a significantly smaller vertex
list to animate. This assumes that a large fraction of the tiles are
not animated, however.

Yet another approach would be to switch the base texture rather than
the texture coordinates. Rather than putting every possible tile type
over time in a single texture, only put ones that will be shown at the
same time. Then switch which texture is active to animate. If many or
most tiles are not animated, you can combine this idea with the above
and keep the non-animated texture completely separate, thus removing
redundant tile textures to save space. The downside to this is that
all animated textures would have to operate in lock-step (have the
same texture at the same time), which may not look as good. But you
could get around this by having multiple water types at the cost of
larger textures.

Still another approach would be to abandon updating the vertex list in
python (assuming doing that is the bottleneck) and write some C code
to generate it on the fly. You'll probably find yourself limited by
transfer bandwidth to the video card with this approach, In
native-code you can build a very large vertex array in short order.

The shader solution is probably the most ideal. I would probably go
for that and either disable animations when shaders are not available
or fallback to one of the other compromise solutions above.

hth,

-Casey

Ragzouken

unread,
Sep 26, 2008, 12:14:32 PM9/26/08
to pyglet-users
Is it possible to pause the animation with the shader solution?

On Sep 26, 4:45 pm, "Casey Duncan" <casey.dun...@gmail.com> wrote:
> On Fri, Sep 26, 2008 at 3:37 AM, Alex Holkner <alex.holk...@gmail.com> wrote:

Casey Duncan

unread,
Sep 26, 2008, 12:17:50 PM9/26/08
to pyglet...@googlegroups.com
Sure, if you don't change the time varying passed to the shader it would stop.

-Casey

josch

unread,
Oct 31, 2008, 8:10:30 PM10/31/08
to pyglet-users
I came a long way and I'm quite happy with what I have now. By making
my own experiments and trying out a lot of ideas i think I finally
managed to do a well performing engine for my needs.

http://tinyurl.com/6yeb2r

This is 11k GL_QUADS and I still have 19fps and can move around the
map without significant performance drops - I think it's still
playable fast and that is with the biggest resolution possible
(1920x1200) and one of the most crap hardware nowadays: X3000 gfx and
800MHz intel. As the player will probably have better gfx/processor
combined with a lower resolution and will effectively never play (only
have an overview) when 2x zoomed out I'm very happy with my results.
When zooming to normal and having normal resolutions like 1280x1024 i
draw at 80-120 fps so everything fine there.
I achieve this with vertex lists that i resize and fill on demand and
this is surprisingly fast - no vertex list migration and stuff there.

Now for the next step I need additional advice. Currently I use two
texture atlases - one 1024x1024 for the map tiles and one 2048x2048
for the map objects. Now I would like to create these textures
dynamically while loading the game - I want to dynamically add new
textures as needed as on very large maps 2048x2048 for the map objects
will not be enough. I also want to store animation frames in the same
texture. Is there a way besides try/except the atlas.add() for knowing
how many images will fit into my texture or for knowing if these new X
animation frames will fit? Is there a way to test this besides waiting
for an exception in batch.add() ?

Second I need some advice for my vertex lists. As I will manage a
dynamical count of them it will be possible when moving around a map
that no object for a vertex_list will be drawn which will result in
resizing it to zero - which is not allowed. I would have to insert an
invisible dummy object into this vertex list every time zero quads of
this list are to be drawn, right? Is there a more elegant way than
doing that?

Richard Jones

unread,
May 12, 2013, 7:50:35 PM5/12/13
to pyglet-users
Be sure to make the coordinates you're positioning the tiles all integers. If they're floats then you'll get some off-tile image bleed in due to the way OpenGL texturing works. Or if the tile images are all in separate textures you might use GL_CLAMP.


     Richard


On 12 May 2013 18:28, <een...@gmail.com> wrote:
Hello all!

I'm having a bit of an issue with drawing tilemap. See, I'm trying the same methods as josch to draw it, and it works pretty ok. The only thing is the tiles are not in sync (or something) and when I move the map around (with glTranslatef) I get black lines (or brown or blue, seems to depend on the tile next to it on tileset) between them. That is kinda weird. One fellow suggested indeces (batch.add_indexed()), but I dont know how to use them on this case. Not much talk about it on the internet.

Here is an example shot of the issue: http://www.eeneku.net/upload/screen_for_fryer.png
Here is the source file for that test: https://github.com/eeneku/thor/blob/master/tilemap_test.py

eeneku

--
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 pyglet-users...@googlegroups.com.
To post to this group, send email to pyglet...@googlegroups.com.
Visit this group at http://groups.google.com/group/pyglet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

een...@gmail.com

unread,
May 18, 2013, 1:53:27 AM5/18/13
to pyglet...@googlegroups.com
Hey Richard! 

Thanks for your response.

I am using integers but doesnt work. I also use one image for my tilemap test, and it worked fine if I didnt add it to atlas, but when I did the lines started to appear. They arent always there, only when I move the view to certain positions.

But I got it fixed. A friend suggested to do this:

offset = 0.5 / tileset_bin.texture_width

texture_data.extend([tile_image.tex_coords[0]+offset,
tile_image.tex_coords[1]+offset,
tile_image.tex_coords[2]+offset,
tile_image.tex_coords[3]-offset,
tile_image.tex_coords[4]+offset,
tile_image.tex_coords[5]+offset,
tile_image.tex_coords[6]-offset,
tile_image.tex_coords[7]-offset,
tile_image.tex_coords[8]+offset,
tile_image.tex_coords[9]+offset,
tile_image.tex_coords[10]-offset,
tile_image.tex_coords[11]+offset])

Adding offset to coords worked fine and lines disappeared. I dont know if this is The Solution, but it works fine and I'm cool with it.

eeneku
Reply all
Reply to author
Forward
0 new messages