How to load a tilesheet?
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
How to load a tilesheet?
I have a tilesheet that has 16x16 grids that define 256 different types of terrain. How can I render the individual terrains through blit()? I see that renpy has renpy.load_image(), but I'm unsure how to get renpy to then only render clips of the image. Most examples I've seen usually load individual images and the blits that, but I need to use a tilesheet (a single image).
- nyaatrap
- Crawling Chaos
- Posts: 1824
- Joined: Mon Feb 13, 2012 5:37 am
- Location: Kimashi Tower, Japan
- Contact:
Re: How to load a tilesheet?
Do you really need to use blit? I think just crop final images by transform is more efficient. If you want to crop user defined displayable, use render.subsurface.
This is my personal experience, but blitting is slow operation. I think sending raw image to GPU directly, then show cropped image by transform is faster.
This is my personal experience, but blitting is slow operation. I think sending raw image to GPU directly, then show cropped image by transform is faster.
- Divona
- Miko-Class Veteran
- Posts: 678
- Joined: Sun Jun 05, 2016 8:29 pm
- Completed: The Falconers: Moonlight
- Organization: Bionic Penguin
- itch: bionicpenguin
- Contact:
Re: How to load a tilesheet?
"im.Crop()" should do it. Here is the link to documentation: https://www.renpy.org/doc/html/displaya ... ml#im.Crop
You could make a method that pick out those tile from the tileset like this:
Then display them in "screen":
"tile(0, 0)" will get 16x16 tile from top left of the tileset.
"tile(1, 0)" will get the next 16x16 tile to the right of the tile above.
"tile(0, 1)" will get the 16x16 tile block below the top left tile.
Use them with list to store the map data.
You could make a method that pick out those tile from the tileset like this:
Code: Select all
init python:
def tile(x, y):
global tile_size
tile_size = 16
return im.Crop("spritesheet.png", (tile_size * x, tile_size * y, tile_size, tile_size))
Code: Select all
screen gamemap():
for y in xrange(10):
for x in xrange(10):
add tile(0, 0):
xpos tile_size * x
ypos tile_size * y
"tile(1, 0)" will get the next 16x16 tile to the right of the tile above.
"tile(0, 1)" will get the 16x16 tile block below the top left tile.
Use them with list to store the map data.
- nyaatrap
- Crawling Chaos
- Posts: 1824
- Joined: Mon Feb 13, 2012 5:37 am
- Location: Kimashi Tower, Japan
- Contact:
Re: How to load a tilesheet?
Divona wrote:"im.Crop()" should do it.
I don't suggest to use it because this operation is slow and it's only useful for fixed results that will be never changed.
When image cropping is changed by time, use LiveCrop or transform crop which is far faster operation.
(Honestly, I never think im.Crop is useful - it's obsoleted function.
Edit: I was wrong. I remember useful case. Some image modification only accept direct images or im.modified images, but not Transform nor LiveSomthing.)
Last edited by nyaatrap on Sun Dec 18, 2016 11:49 pm, edited 1 time in total.
Re: How to load a tilesheet?
@nyaatrap Can you give a code sample? I don't quite understand how I just started learning renpy today, so I didn't know blit was slow.
In other engines, normally I would do something like build a quad, load the image as texture, then clip it and apply to the quad. Divona's way of doing it sounds like a familiar pattern, but if it's slow it would be great to know what the best way to do it in renpy would be.
Also, I found an old code sample from you: viewtopic.php?f=51&t=35608
It looks like you're blitting there, but how would you alternatively send "raw image to GPU directly, then show cropped image by transform", without blitting?
In other engines, normally I would do something like build a quad, load the image as texture, then clip it and apply to the quad. Divona's way of doing it sounds like a familiar pattern, but if it's slow it would be great to know what the best way to do it in renpy would be.
Also, I found an old code sample from you: viewtopic.php?f=51&t=35608
It looks like you're blitting there, but how would you alternatively send "raw image to GPU directly, then show cropped image by transform", without blitting?
- nyaatrap
- Crawling Chaos
- Posts: 1824
- Joined: Mon Feb 13, 2012 5:37 am
- Location: Kimashi Tower, Japan
- Contact:
Re: How to load a tilesheet?
Rewrite im.Crop to LiveCrop in the above code. Because im.Crop loads a spritesheet every time when it find new tile, but LiveCrop loads only once.bats wrote:Divona's way of doing it sounds like a familiar pattern, but if it's slow it would be great to know what the best way to do it in renpy would be.
I mean, simplilyAlso, I found an old code sample from you: viewtopic.php?f=51&t=35608
It looks like you're blitting there, but how would you alternatively send "raw image to GPU directly, then show cropped image by transform", without blitting?
Code: Select all
show image: crop x, y
Re: How to load a tilesheet?
Hm, okay I tried to update @Divona code with @nyaatrap suggestions:
Am I missing something, because I ran a test and @Divona's code (using im.Crop()) seems to load 1-2 secs faster than the above. It renders 100x100 just to test for speed (real game will do culling).
Code: Select all
label start:
show screen doit
e "rendered"
init python:
def tile(x, y):
return LiveCrop((32*x, 32*y, 32, 32), "test.png" )
screen doit():
for y in xrange(100):
for x in xrange(100):
add tile(0,0):
xpos 32 * x
ypos 32 * y
- nyaatrap
- Crawling Chaos
- Posts: 1824
- Joined: Mon Feb 13, 2012 5:37 am
- Location: Kimashi Tower, Japan
- Contact:
Re: How to load a tilesheet?
Im.Crop loads png file then create cache from it, then use this cache. Cache is multiplied if it crops many, but one small portion is small.
LiveCrop don't create cache, but use png image directly.
Come to think of it, it hard to conclude which is lighter or faster. For example, if you use all tiles or changing them by time, LiveCrop is better. If a few or static, im.Crop.
Edit: After some test, in a case when same cropped image are reused many, im.Crop is better. Sorry for confusion.
LiveCrop don't create cache, but use png image directly.
Come to think of it, it hard to conclude which is lighter or faster. For example, if you use all tiles or changing them by time, LiveCrop is better. If a few or static, im.Crop.
Edit: After some test, in a case when same cropped image are reused many, im.Crop is better. Sorry for confusion.
- nyaatrap
- Crawling Chaos
- Posts: 1824
- Joined: Mon Feb 13, 2012 5:37 am
- Location: Kimashi Tower, Japan
- Contact:
Re: How to load a tilesheet?
BTW, screen statement 'add' is the main reason why it's slow. If you want to raise performance, try my Tilemap so you could use only one add rather than (add image)*100.
Who is online
Users browsing this forum: Ahrefs [Bot], Majestic-12 [Bot]