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

Re: [pygame] Frantic (again)



Yes, this is definitely a memory vs. CPU tradeoff, and I chose CPU.  Of
course, I naively load everything at startup time, which I believe is
the real cause of the memory/loading problems, but I will fix that soon. 

BTW, I could use the method you describe below for the starship (and
save about 400 Kb of memory), because it's a static image that's rotated
in the plane of the screen.  However, the enemies and powerups either
rotate around the y-axis (perpendicular to the screen), have other
animations like blinking lights or fading skins, or both.   No other way
to manage those but to pre-render and point to the correct frame.   Then
you have the explosions, the true memory hogs.   I might have to rethink
those, or at least trim the frame length.   They do look good, though.

Thanks,

Dave

On Tue, 20 Jun 2006 20:55:12 -0500, "Luke Paireepinart"
<rabidpoobear@xxxxxxxxx> said:
> The enemies are rotated as in their sprite has multiple images that 
> represent different physical views of the same 3d object.
> I meant rotated as in the pygame surface itself is transformed.  for 
> example, when you hold down "left" during the game and the ship spins 
> around.
> I was wondering if you stored each of the ship's rotations (facing up, 
> facing left, facing right, facing 45 degrees, 30 degrees, and so on)
> for each of the frames of your sprite.
> Say this array is an image (imagine :P)
> [1,2,3,4,5,6,7,8,9,10]
> now say I rotate it 3 elements to the right.
> [8,9,10,1,2,3,4,5,6,7]
> now I know how to rotate the image in this way (just shift the elements 
> over a couple of places and put the elements that fall off the edge back 
> to the other side.)
> So there is no reason for me to store every single iteration of this 
> rotation,
> [[1,2,3,4,5,6,7,8,9,10],[10,1,2,3,4,5,6,7,8,9],[9,10,1,2,3,4,5,6,7,8],[8,9,10,1,2,3,4,5,6,7] 
> ....... ]  all in memory
> because I can just store the source array [1,2,3,4,5,6,7,8,9,10] and 
> manipulate it later if I need to rotate it by
> doing
> for x in range(len(array) % rotationamount):
>     tmp = array.pop(len(array)-1)
>     array = [tmp]+array
> 
> and by this method I will save 10x the memory and I'll just have to use 
> a little CPU power to rotate the array whenever I need a rotated version.
> 
> Now say instead of my array of numbers I have an image.
> let's say it's a starship.
>  >>> starship = pygame.image.load("images/starship.png").convert_alpha()
> It's not an animated sprite, it's just a single frame for this example.
> now one  may be tempted to say
> 
> starshiprotation = []
> for degrees in range(360):
>     starshiprotation.append(pygame.transform.rotate(starship,degrees))
> 
> Now this kicks ass for efficiency later on.  one can just say...
> screen.blit(starshiprotation[270],(0,0))
> to display a starship that's facing left, and the only time-delay is 
> (ignoring things like the lookup that occurs when you use a "." and such)
> 1. retrieve (reference to) image from starshiprotation array -> should 
> be negligible
> 2. pass the (reference of the) image to the screen.blit() function -> 
> should be negligible as well
> 3. wait for pygame to blit the image to the screen. -> depends on 
> resolution, image alpha, blah blah... takes a while.
> So the only thing we're waiting on is the blit function.  This is good 
> and fast.
> 
> However, what you have to remember is that
> 1. now we're taking up 360x as much memory as just holding the single
> image,
> 2. we have to wait a long time while python number-crunches those images 
> and rotates each of them.
> 
> The alternative to this is to say...
> screen.blit(pygame.transform.rotate(starship,270),(0,0))
> to have an image facing left.
> 
> The disadvantages of this are
> 1. Each time we need to display this image  we have to wait for the 
> rotation to occur.
> 
> The advantages are
> 1. Only need to allocate enough memory to hold the single starship image.
> 2. No overhead in the beginning generating the rotated array.
> 
> To soften the blow of the disadvantage, having to rotate the image each 
> time we need to blit it,
> we can just whip up a simple class to take care of it for us!
> 
> class StarShip(object):
>     def __init__(self,imgpath):
>        self.original = pygame.image.load(self.imgpath)
>        self.currentdegrees = 0
>        self.starship = self.original
> 
>     def rotate(self,degrees):
>        if degrees == self.currentdegrees:
>           return self.starship
>        self.starship = pygame.transform.rotate((self.starship,degrees))
>        self.currentdegrees = degrees
>        return self.starship
> 
> #StarshipTest.py
> --- import modules, initialize them, get screen surface.
> ship = StarShip("images/starship.png")
> 
> rotations = [0,45,45,45,45,90,180,270]
> for x in rotations:
>     screen.blit(ship.rotate(x),(x,x))
>     pygame.display.update()
> 
> during the calls to ship.rotate() where the previous value is used 
> (during the repeated 45 degree rotations)
> no cpu overhead will happen for the rotation (other than calling 
> functions, returning references, negligible things)
> As an added bonus, the ship will move diagonally down the screen!
> Anyway, as you can see, rotating images only when they're necessary is 
> much more memory- and loading-time efficient.
> So My original question was which of these ways you were doing it.
> 
> I hope that I didn't blabber on too much about stuff you already knew 
> and that
> my explanations were clear.
> > Anyway, I think I fixed the loading bug with the very latest release.
> >   
> Cool.  That's good.
> > [snip] Felt it would be too easy.
> I see your point.  The ship has much more maneuverability seeing as it 
> can stop on a dime more or less, so some added restrictions
> should be placed to keep it from being too easy.
> 
> > If it completely flops, I'll release the source :)
> >   
> I hope I don't see the source then! :)
> > Thanks for the feedback, Luke.
> >   
> Anytime :D
> > Dave
> >   
> Luke