is faster Sprites or CustomDisplayable? (very technical!)
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.
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
is faster Sprites or CustomDisplayable? (very technical!)
I'm trying to speed up the map I have in SOTW:
in practice a 10x10 grid, plus some arrows in the hotspots. The main problem is the slowness when changing maps.
I've improved by preloading the maps on startup (the values) but especially on mobile, is SUPER SLOW, like takes 3-4 seconds to change map!!!
I don't do anything special in the change map, is just a call, update the map info (array) and then back to the loop where I use call screen to show the map.
I tried using a customdisplayable with blit/render instead of a for/loop to blit the various map cells on screen, and I *think* that speed improved, at least on Desktop. On mobile, even if improves, from 4seconds to 3,5seconds is still an eternity so harder to notice
I am now wondering if I could try using the Sprites class instead? would that one be faster than the customdisplayable ? thanks
in practice a 10x10 grid, plus some arrows in the hotspots. The main problem is the slowness when changing maps.
I've improved by preloading the maps on startup (the values) but especially on mobile, is SUPER SLOW, like takes 3-4 seconds to change map!!!
I don't do anything special in the change map, is just a call, update the map info (array) and then back to the loop where I use call screen to show the map.
I tried using a customdisplayable with blit/render instead of a for/loop to blit the various map cells on screen, and I *think* that speed improved, at least on Desktop. On mobile, even if improves, from 4seconds to 3,5seconds is still an eternity so harder to notice
I am now wondering if I could try using the Sprites class instead? would that one be faster than the customdisplayable ? thanks
Re: is faster Sprites or CustomDisplayable? (very technical!
It's hard to say what's the bottleneck in your rendering without more information.
Can you post the actual code that draws the tile map?
How large are the tile images?
Can you post the actual code that draws the tile map?
How large are the tile images?
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
Well I tried with both, and CustomDisplayable seemed slightly faster, but still the game is unplayable even on a fairly new android tablet
The map is 10x10 so 100 tiles, the code is big but the core of the map:
The map is 10x10 so 100 tiles, the code is big but the core of the map:
Code: Select all
init python:
class MapDisplayable(renpy.Displayable):
def __init__(self, **properties):
renpy.Displayable.__init__(self, **properties)
# The child.
# self.child = renpy.displayable(child)
# The distance at which the child will become fully opaque, and
# where it will become fully transparent. The former must be less
# than the latter.
# self.opaque_distance = opaque_distance
# self.transparent_distance = transparent_distance
# The alpha channel of the child.
self.alpha = 1.0
# The width and height of us, and our child.
self.width = 1280
self.height = 720
def render(self, width, height, st, at):
r = renpy.Render(width, height)
ofx=0;ofy=0;sfx=578;sfy=4
for x in range(MyMapsize):
ofx=sfx;ofy=sfy
for y in range(MyMapsize):
img=("tile%s" % (MyMap[x][y]))
if Is_Night and img not in tilenotint:
try:
img=im.MatrixColor(ImageReference(img),im.matrix.tint(Ir,Ig,Ib)*im.matrix.saturation(Is)*im.matrix.brightness(Il))
except:
pass
if Is_Dusk:
try:
img=im.MatrixColor(ImageReference(img),im.matrix.tint(.9,.9,1.0)*im.matrix.saturation(.9)*im.matrix.brightness(-.1))
except:
pass
r.blit(renpy.render(ImageReference(img), width, height, st, at), (ofx,ofy))
ofy+=32;ofx+=64
sfx-=64;sfy+=32
return r
#screen ShowMap:
# add "main/mainbase.jpg"
# add MapDisplayable()
screen ShowMapHotSpots:
default mapinfo=False
default cval1=99
default cval2=99
default MTiles=False
default MArrows=True
# key "-" action MinusVar
# key "+" action PlusVar
# key "v" action ChangeVar
key "K_F2" action ToggleScreenVariable("mapinfo")
key "K_F3" action ToggleVariable("Is_Night")
# key "m" action ToggleScreenVariable("MTiles")
# key "n" action ToggleScreenVariable("MArrows")
# add "main/mainbase.jpg"
# #text ("R:%s G:%s B:%s Sat:%s Lum:%s CurVar:%s" % (Ir,Ig,Ib,Is,Il,CurVar)) outlines [(2,"#000")]
# add MapDisplayable()
if MTiles or config.developer:
#draw the map
$ofx=0;ofy=0;sfx=578;sfy=4
for x in range(MyMapsize):
$ofx=sfx;ofy=sfy
for y in range(MyMapsize):
# $img=("tile%s" % (MyMap[x][y]))
# if Is_Night and img not in tilenotint:
# python:
# try:
# img=im.MatrixColor(ImageReference(img),im.matrix.tint(Ir,Ig,Ib)*im.matrix.saturation(Is)*im.matrix.brightness(Il))
# except:
# pass
# add (img) xpos (ofx) ypos (ofy)
if mapinfo:
text ("%s,%s" % (x,y)) xpos (ofx+48) ypos (ofy+60) size 12 outlines [(1,"#000")]
text ("%s" % MyMap[x][y]) xpos (ofx+48) ypos (ofy+80) size 12 outlines [(1,"#000")]
#imagebutton idle (im.MatrixColor("cursor.png",im.matrix.opacity(0.5))) hover ("cursor.png") focus_mask True action Return() xpos (ofx) ypos (ofy)
$ofy+=32;ofx+=64
$sfx-=64;sfy+=32
if "touch" in config.variants:
button:
xfill True yfill True background None
action (SetScreenVariable("cval1",99),Hide("InfoBox"))
activate_sound None
if not temp_map:
#map stats
hbox xalign .8 ypos 10 spacing 10:
button background None xpadding 0 ypadding 0:
vbox:
add (Frame("map/quest_big.png",1,1,xmaximum=64,ymaximum=64))
text ("%s/%s" % (map_quests[cur_season],max_quests[cur_season])) size 20 outlines [(2,"#1e1a16")] font "Stoke-Regular.ttf" xcenter .5
action Show("MsgBox",msg="This is the total number of quests available in this Season. Besides the main plot quest, there are several sidequests of varying difficulty/length available. Find and solve them all to get more EXP points!",msgtitle="Total Quests")
button background None xpadding 0 ypadding 0:
vbox:
add (Frame("map/location_big.png",1,1,xmaximum=64,ymaximum=64))
text ("%s/%s" % (map_locations[cur_season],max_locations[cur_season])) size 20 outlines [(2,"#1e1a16")] font "Stoke-Regular.ttf" xcenter .5
action Show("MsgBox",msg="Each Season has a number of locations to unearth. Some are fairly obvious and visible, while others are harder to find, but could yield interesting rewards. Discover all the locations in a Season to earn bonus EXP!",msgtitle="Undiscovered Locations")
button background None xpadding 0 ypadding 0:
vbox:
add (Frame("map/fame_big.png",1,1,xmaximum=64,ymaximum=64))
#text ("%s/%s" % (map_fame[cur_season],max_fame[cur_season])) size 20 outlines [(2,"#1e1a16")] font "Stoke-Regular.ttf" xcenter .5
text ("%s") % (map_fame[cur_season]) size 20 outlines [(2,"#1e1a16")] font "Stoke-Regular.ttf" xcenter .5
action Show("MsgBox",msg="Fame indicates how much people know about you and your deeds. This value increases as you complete quests, and defeat dangerous opponents. Fame relates to this Season only, and will not carry over to the next Season. High fame will lead to discounts in shops, and other sorts of favors from people.",msgtitle="Party Fame")
if MArrows:
#draw hotspots
$ofx=0;ofy=0;sfx=580;sfy=4
for x in range(MyMapsize):
$ofx=sfx;ofy=sfy
for y in range(MyMapsize):
for mapN,mt,mx,my,type,desc,par,arrowC,fTile in maps:
if mapN==map_zone and x==mx and y==my and eval(mt):
#autofix edge movement arrows!
if arrowC=="green":
if mx==9:
$arrowC="W"
if mx==0:
$arrowC="E"
if my==9:
$arrowC="S"
if my==0:
$arrowC="N"
#if mobile
if "touch" in config.variants:
button background None bottom_padding 30 xpos (ofx+64) ypos (ofy+48) at Boing():
add ("map/%s.png" % arrowC)
action If(cval1==mx and cval2==my, (Hide("InfoBox"),Return([type,desc,par])), (Show("InfoBox",x=ofx+64,y=ofy+48,type=type,desc=desc,par=par),SetScreenVariable("cval1",mx),SetScreenVariable("cval2",my)) )
else:
button background None bottom_padding 30 xpos (ofx+64) ypos (ofy+48) at Boing():
add ("map/%s.png" % arrowC)
hovered Show("InfoBox",x=ofx+64,y=ofy+48,type=type,desc=desc,par=par)
unhovered Hide("InfoBox")#,transition=quickdissolve)
action (Hide("InfoBox"),Return([type,desc,par]))
#display party position ?
if showpartyposition and x==pax and y==pay:
add ("map/party_%s.png" % partyposname) xpos (ofx+64) ypos (ofy+48) at Rotor()
$ofy+=32;ofx+=64
$sfx-=64;sfy+=32
#Info
vbox xpos 10 ypos 0 spacing -2:
text map_name[map_zone] size (75-len(map_name[map_zone])) outlines [(2,"#1e1a16")] font "BerkshireSwash-Regular.ttf"
text ("Day %d, %s" % (CurDay,Seasons[CurSeason])) color "#DDD" size 32 outlines [(2,"#1e1a16")] font "BerkshireSwash-Regular.ttf"
if not temp_map:
text ("Days to next plot event: {color=#FF0}%02d{/color}" % Dday) size 22 outlines [(2,"#1e1a16")] font "Stoke-Regular.ttf"
if not temp_map:
#display party
hbox xpos 4 yalign 1.0 spacing 4:
$c=0
for entry in party.dragCharacters:
$img="gfx/gui/unlearnedSkill.png"
if entry.character in party.available:
if entry.character.isAlive():
$img="gfx/gui/learnedSkill.png"
else:
$img="gfx/gui/unlearnedSkill.png"
$a=1#.25
if entry.character in party.party:
$a=1
vbox:
button:
background Frame(img,8,8,tile=True)
xmaximum 96 ymaximum 90 xminimum 96 yminimum 90 xmargin 0 ymargin 0 xpadding 4 top_padding 4 bottom_padding 5
bar value (entry.character.hp) range (entry.character.getValue("HP")) style "hpbar" xalign 0.025 yalign 1.0 thumb None bar_vertical True
bar value (entry.character.sp) range (entry.character.getValue("SP")) style "spbar" xalign 1.0 yalign 1.0 thumb None bar_vertical True
$img2="gfx/portraits/p_%s.png" % entry.character.name
if entry.character.isAlive():
add (img2) xcenter .5 alpha (a) zoom .75 yalign .9
else:
add (im.Grayscale(img2)) xcenter .5 alpha (a) zoom .75 yalign .9
action (SetField(party,"gui_selected_char",entry.character),Show("Char_Screen_Main"))
frame ymaximum 24 xminimum 96 xcenter .5 ypadding 10 xpadding 15:
background Frame(img,8,8,tile=True)
text entry.character.name size 13 xcenter .5
else:
vbox:
button:
background Frame(img,8,8,tile=True)
xmaximum 96 ymaximum 90 xminimum 96 yminimum 90 xmargin 0 ymargin 0 xpadding 4 top_padding 4 bottom_padding 5
text "?" size 40 xcenter .5 ycenter .5
# bar value (entry.character.hp) range (entry.character.getValue("HP")) style "hpbar" xalign 0.025 yalign 1.0 thumb None bar_vertical True
# bar value (entry.character.sp) range (entry.character.getValue("SP")) style "spbar" xalign 1.0 yalign 1.0 thumb None bar_vertical True
frame ymaximum 24 xminimum 96 xcenter .5 ypadding 10 xpadding 15:
background Frame(img,8,8,tile=True)
text " " size 13 xcenter .5
$c+=1
if c==4:
null width 472
use OnScreen_Menu
-
- Eileen-Class Veteran
- Posts: 1258
- Joined: Fri Sep 21, 2007 7:13 am
- Projects: a battle engine
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
I would suggest not re-rendering identical tiles. Keep a dictionary of the tiles you've already rendered this redraw, keep the render and just blit it multiple times. Other than that, I'm not really sure.
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
Well the problem is that in many maps there are very different ones. They may not be 100 unique tiles, but likely 60-70.
I am also using a single texture each tileset and created images from it on init:
though I don't think that should be an issue.
I know that renpy wasn't made for such games, but would be nice if the speed in the screens could be improved. Even during the battles, it's barely playable on Android, and those are the same as Loren (apart for the higher resolution).
I am also using a single texture each tileset and created images from it on init:
Code: Select all
#define the tilesets
c=1
for name in ("snowriver","snowterrain","dungeon01","dungeon02","desert","towndesert","greenforest"):
for y in range(8):#this has to change based on the tile numbers
for x in range(8):
renpy.image("tile%d" % (c), im.Crop("map/%s.png" % name, (x*128, y*128, 128, 128)) )
I know that renpy wasn't made for such games, but would be nice if the speed in the screens could be improved. Even during the battles, it's barely playable on Android, and those are the same as Loren (apart for the higher resolution).
Re: is faster Sprites or CustomDisplayable? (very technical!
Mayheps:
- Have variations of tile images ready and preloaded into image cache
- Reduce the amount of for loops (maybe without screen language or only with screen language)
- use xrange (very marginally faster)
- Reference globals to local namespaces (also marginally faster but prolly makes sense since you're using globals a lot inside of for loops)
Don't know if any of these will be enough to improve the situation significantly, maybe someone else will have better ideas.
Edit: Missed two post while reading that code/typing this
- Have variations of tile images ready and preloaded into image cache
- Reduce the amount of for loops (maybe without screen language or only with screen language)
- use xrange (very marginally faster)
- Reference globals to local namespaces (also marginally faster but prolly makes sense since you're using globals a lot inside of for loops)
Don't know if any of these will be enough to improve the situation significantly, maybe someone else will have better ideas.
Edit: Missed two post while reading that code/typing this
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
The fact is that on desktop works fine. But on Android is really slow. I am thinking maybe is an Android-specific problem, I mean maybe there some code executes much slower.
I could play Roommates fine on my old tablet, 1Ghz single core, and that game is 1280x720 too. The old Loren was a bit slow during combats, but still playable. The really worst thing is the map, in particular changing map, takes 2-3s that might not seem much but is quite frustrating during play
Only thing I haven't tried is preloading images in the cache, I could try that indeed.
I could play Roommates fine on my old tablet, 1Ghz single core, and that game is 1280x720 too. The old Loren was a bit slow during combats, but still playable. The really worst thing is the map, in particular changing map, takes 2-3s that might not seem much but is quite frustrating during play
Only thing I haven't tried is preloading images in the cache, I could try that indeed.
Re: is faster Sprites or CustomDisplayable? (very technical!
Never messed around with Android... so there is no advice I can give here. I wrote simple code to load maps into Jake's BE from a software called Tiled to try it out once, worked really well, even on a super old laptop.jack_norton wrote:The fact is that on desktop works fine. But on Android is really slow. I am thinking maybe is an Android-specific problem, I mean maybe there some code executes much slower.
I could play Roommates fine on my old tablet, 1Ghz single core, and that game is 1280x720 too. The old Loren was a bit slow during combats, but still playable. The really worst thing is the map, in particular changing map, takes 2-3s that might not seem much but is quite frustrating during play
Only thing I haven't tried is preloading images in the cache, I could try that indeed.
Code: Select all
class TileMap(_object):
"""
Prototype to import and build of maps from Tiled.
For now using a single tileset (can be updated to using infinite amount)
"""
def __init__(self, path):
self.data = load_json(path)
# Map:
self.map = self.data["layers"][0]["data"]
self.height = self.data["layers"][0]["height"]
self.width = self.data["layers"][0]["width"]
# Tileset:
# If this works out, I'll have to account for mupliple tilesets in the future.
# self.imageheight = self.data["tilesets"]["imageheight"]
# self.imagewidth = self.data["tilesets"]["imagewidth"]
self.image = "content/gfx/tilesets/tmw_desert_spacing.png" # + self.data["tilesets"][0]["image"]
self.ts_name = self.data["tilesets"][0]["name"]
self.tileproperties = self.data["tilesets"][0]["tileproperties"]
self.col = [int(key) + 1 for key in self.tileproperties.keys()]
def get_args_for_composite(self):
"""
Returns a list of arguments to be unpacked for Composite
"""
args = list()
for y in xrange(self.height):
for x in xrange(self.width):
args.append((x*96, y*96))
args.append(self.ts_name + str(self.map[y*(self.height+(self.width-self.height)) + x]))
return args
def build_map(self):
"""
Builds the map and returns it as RenPy Image
"""
# Register the times as images first:
t = 1
# Margins + Spacing
for y in xrange(6):
for x in xrange(8):
_x = x + 1
_y = y + 1
renpy.image(self.ts_name + "%d"%t, im.Scale(im.Crop(self.image, (x*32+_x, y*32+_y, 32, 32)), 96, 96))
t += 1
# Build the map into single image and return it:
args = self.get_args_for_composite()
return LiveComposite((3840, 2400), *args)
Re: is faster Sprites or CustomDisplayable? (very technical!
Code: Select all
img=im.MatrixColor(ImageReference(img),im.matrix.tint(Ir,Ig,Ib)*im.matrix.saturation(Is)*im.matrix.brightness(Il))
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
Yes but that happens only when in the game is night time, so in my tests is never executed and is still super slow. I tried to use caching but seems it didn't improve the situation at all
Maybe the problem is python or android lib or something else. I'm doing a tower defense game with a friend coder, and using C plus his own lib I can show 500 sprites on screen at once at 26FPS on the low-end android tablet so is possible to do much better, but of course is not fair to compare a C lib with a system like renpy, but thought I could at least make it run a bit faster.
Maybe the problem is python or android lib or something else. I'm doing a tower defense game with a friend coder, and using C plus his own lib I can show 500 sprites on screen at once at 26FPS on the low-end android tablet so is possible to do much better, but of course is not fair to compare a C lib with a system like renpy, but thought I could at least make it run a bit faster.
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
Okay so an update: I tried disabling the map completely on Android, and the map change is still painful. So the slowness is somewhere else (no clue where... on desktop is instant!!) but I think is safe to say that is not a problem of graphic performance at least!
-
- Regular
- Posts: 130
- Joined: Sun Jul 26, 2009 7:07 pm
- Location: Fredericton, NB, Canada
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
I've done some experiments with my Android phone, and once I had a problem with long pauses when I was doing rollback. I eventually discovered the problem was me putting an 'import os' statement in my script, that I was using for something unrelated.
Does your game use any extra imports or libraries?
Does your game use any extra imports or libraries?
Flash To Ren'Py Exporter
See the Cookbook thread
See the Cookbook thread
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
Ah I have that import os indeed, to center the window on desktop! I'll try to remove that, thanks
- jack_norton
- Lemma-Class Veteran
- Posts: 4084
- Joined: Mon Jul 21, 2008 5:41 pm
- Completed: Too many! See my homepage
- Projects: A lot! See www.winterwolves.com
- Tumblr: winterwolvesgames
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
In case someone is curious, I solved this, the problem was in my code
I was iterating with a for cycle for a list of over 100 items, each made of 7-8 elements. Now I copy only the items for the current map which is not longer than 7-8 and is super fast
Next challenge is to speed up the battle screen but I don't know how to use a customdisplayable with buttons (or that works as button)
I was iterating with a for cycle for a list of over 100 items, each made of 7-8 elements. Now I copy only the items for the current map which is not longer than 7-8 and is super fast
Next challenge is to speed up the battle screen but I don't know how to use a customdisplayable with buttons (or that works as button)
-
- Veteran
- Posts: 448
- Joined: Wed Nov 18, 2009 11:17 am
- Completed: Loren
- Projects: PS2
- Location: Germany
- Contact:
Re: is faster Sprites or CustomDisplayable? (very technical!
You simply give them an event method.
Avatar created with this deviation by Crysa
Currently working on:
Currently working on:
- Winterwolves "Planet Stronghold 2" - RPG Framework: Phase III
Who is online
Users browsing this forum: No registered users