[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Effecient way to 'darken' a surface?



Peter Shinners wrote:
On Tue, 2005-12-20 at 22:45 +0100, Troels Therkelsen wrote:
  
arr = surfarray.array3d(surf)
arr = maximum(zeros(arr.shape), arr - 200))
surfarray.blit_array(surf, arr)

I dunno, perhaps there just isn't a significantly faster way of doing 
this? Please prove me wrong!
    

This could be sped up a few ways. If your image uses an 8bit palette you
can quickly modify the palette colors in realtime and blit the new
background.

You can optimize the Numeric mojo a bit by not worrying about the
clamping.

def multiply(surface, value):
    "Value is 0 to 255. So 128 would be 50% darken"
    arr = pygame.surfarray.array3d(surface) * value
    arr >>= 8
    pygame.surfarray.blit_array(surface, arr)



I have gotten away with also creating all black images, setting the
alpha level and blitting. I can't guess if this would be slower of
faster than the Numeric version. If you are going to redo this many
times with the same sized images, you could reuse the "dark" Surface for
more speed.


def darken(surface, value):
    "Value is 0 to 255. So 128 would be 50% darken"
    dark = pygame.Surface(surface.get_size(), 32)
    dark.set_alpha(value, pygame.RLEACCEL)
    surface.blit(dark, (0, 0))


  
Thanks for everyone's suggestions and advices.  Ironically, I did think of the alpha blitting approach almost immediately after posting, so maybe I should've thought a little bit more about the problem before posting ;-)

For those curious about the outcome, the alpha blitting approach is about 8 times faster than the Numeric approach (using Pete's optimisations above) for my game. It's about 13 times faster than my original code.  On my 'slow' setup (1GHz linux server sending X over the network to a 2.6GHz windows box running an X emulator), this means that the delay goes from "noticable, but not unbearably so" to "unnoticable".  On my 'fast' (1.7GHz Intel M linux laptop) setup the delay wasn't really noticable in the first place.  But I always test on the slow setup, too, because that tends to reveal performance issues pretty early in the process.

My game is a level-based puzzle game and everytime you beat (or are defeated by) a level, I want the level area darkened so I can print a game over / level won notice on top of it.  However, there's a lot of other elements (score, level name, timers, etc) on the screen that I don't want touched by this darkening.  In addition, each level is not necessarily the same size.  Since I don't need this done a lot (it's an event that happens exactly once for every level) the speed of the alpha blitting is fast enough for me.

Yes, it is tile-based; however many of the tiles are animated on different timers and/or generated runtime so I don't really have a fixed colour palette for all tiles. So I thought that simply telling everything on the level to stop animating/reacting to user input and then darkening the appropriate area of the display would be the simplest approach.  My hax0r solution's lack of speed of course disappointed me, hence my original post to this list :-)

Anyway, I've ranted on for long enough.  Thanks again for the help! ;-)

/Troels Therkelsen
begin:vcard
fn:Troels Therkelsen
n:Therkelsen;Troels
org:Nitram Lexa
adr:;;Danmarksvej 5A;Kongens Lyngby;;2800;Denmark
email;internet:tt@xxxxxxxxxxxxxx
title:Programmer
tel;work:+45 70 25 24 23
tel;fax:+45 70 25 29 23
tel;home:+45 38 81 33 66
tel;cell:+45 25 39 14 69
x-mozilla-html:FALSE
url:http://www.nitramlexa.com
version:2.1
end:vcard