[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