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

Re: [pygame] Using Numeric & Surfarray with alpha values



>>> 200 * (50/100)
0
>>> 200 * 50/100
100
>>> 200 * (50/100.)
100.0


Make an array of lifetime, and an array of decay with the same sized
types compared to the alpha array.


Note that:
>>> 200 * 50
10000

You see that 10000 would overflow the 8bit of the alpha.  The alphas
maximum value is 255.

There is also a precion problem with the other part.
>>> 50 / 100
0
>>> 50 / 100.
0.5

If you use floats then, you need to cast to int.  Which can be slow
unless you use a fast-yet-inacurate float->int cast.

So...

You could instead use divides.

Because 200 * 0.5 is the same as 200 / 2

Divides are slow, however if you use divides you may be able to use
less memory, which may therefore be faster.  As you don't need to have
a big enough type to store eg. 200 * 50
-> 10000 like above.  You can also avoid float->int casts.


Use *= or /= instead of * or /, so that no temporary arrays are
allocated.  a = a * b will allocate a new array.  Whereas a *= b
reuses the old memory.


If the life, and decay don't change much, make an intermediate array. 
Which I am assuming because mostly this is what happens.  Your
particles may be different though.


decay_life_array = decay_array / life_array

loop:
    alpha_array /= decay_life_array





Here is the lifetime of a particle using your way.

>>> 200 * 50/100
100
>>> 100 * 50/100
50
>>> 50 * 50/100
25
>>> 25 * 50/100
12
>>> 12 * 50/100
6
>>> 6 * 50/100
3
>>> 3 * 50/100
1
>>> 1 * 50/100
0
>>> 0 * 50/100
0




>>> 200 / (100 / 50)
100
>>> 100 / (100 / 50)
50
>>> 50 / (100 / 50)
25
>>> 25 / (100 / 50)
12
>>> 12 / (100 / 50)
6
>>> 6 / (100 / 50)
3
>>> 3 / (100 / 50)
1
>>> 1 / (100 / 50)
0
>>> 0 / (100 / 50)
0



An here is what would happen if you use floats.
>>> 200 / (100 / 50.)
100.0
>>> 100 / (100 / 50.)
50.0
>>> 50 / (100 / 50.)
25.0
>>> 25 / (100 / 50.)
12.5
>>> 12.5 / (100 / 50.)
6.25
>>> 6.25 / (100 / 50.)
3.125
>>> 3.125 / (100 / 50.)
1.5625
>>> 1.5625 / (100 / 50.)
0.78125
>>> 0.78125 / (100 / 50.)
0.390625
>>> 0.390625 / (100 / 50.)
0.1953125



Hopefully I haven't made any mistakes and wasted your time ;)

Cheers,


On 11/27/05, Mike Rotondo <mr001m@xxxxxxxxxxxxxxxxxx> wrote:
> We are writing a 2D particle engine and we would like to render each
> particle with gradually decreasing alpha values. However, our original
> image for the particles has per-pixel alpha, so we can't use set-alpha.
> So, we are going to have to modify each pixel's alpha value ith Numeric,
> it seems.
>
> We have a value for the time left for the particle to live, named
> lifetime, and a value for how long it will live, named decay. The value
> (lifetime/decay) is the percent of the original alpha value we want to
> render each pixel with. So, if a pixel in the original image has alpha
> 200, and a particular particle has lifetime 50 and decay 100, we would
> want to render that pixel in that particle with an alpha of 200 *
> (50/100) = 100.
>
> We are trying to do this with numeric & surfarray, but are having
> trouble with array types. The best we've been able to do is to create a
> list comprehension which does the job:
>
> [[pixel and (pixel * particle.life / particle.decay) for pixl in row]
> for row in array]
>
> This uses short circuit evaluation and the fact that booleans return the
> last object they looked at to return either the pixel's alpha value if
> it is 0, or the pixel's alpha value times our percentage if it is not 0.
>
> array is pygame.surfarray.array_alpha(original_image)
>
> SO, my question is: What is the best way to translate the above list
> comprehension into Numeric, so as to speed it up?
>
> Thanks,
> Mike Rotondo
>