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

Re: [pygame] sprites in arrays, instead of simple variables



Take a look at this:

#! /usr/bin/python
"""for more details on sprites and groups, see
1) http://www.pygame.org/docs/ref/sprite.html
2) http://www.pygame.org/docs/tut/SpriteIntro.html
3) http://www.sacredchao.net/~piman/writing/sprite-tutorial.shtml (
might want to read this before #2 )

example written by: ninmonkeys@xxxxxxxxx
about:
	quick demo on using sprite groups
"""
import sys, pygame, math, os, random
from pygame.locals import *

class Unit(pygame.sprite.Sprite):
	"""Your main 'unit', which is any sprite that will be drawn. Group
requires .image and .rect members.
	
	Might split this into more classes, ie: objects, and enemies. Can
place sprites into multiple groups,
	ie quoted from the tutorial:
	====
		At this point the two classes seem pretty basic. Not doing a lot
more than you can do with a simple list and your own class of game
objects. But there are some big advantages to using the Sprite and
Group together. A sprite can belong to as many groups as you want.
Remember as soon as it belongs to no groups, it will usually be
cleared up (unless you have other "non-group" references to that
object)

		The first big thing is a fast simple way to categorize sprites. For
example, say we had a pacman-like game. We could make separate groups
for the different types of objects in the game. Ghosts, Pac, and
Pellets. When pac eats a power pellet, we can change the state for all
ghost objects by effecting everything in the Ghost group. This is
quicker and simpler than looping through a list of all the game
objects and checking which ones are ghosts.

		Adding and removing groups and sprites from each other is a very
fast operation, quicker than using lists to store everything.
Therefore you can very efficiently change group memberships. Groups
can be used to work like simple attributes for each game object.
Instead of tracking some attribute like "close_to_player" for a bunch
of enemy objects, you could add them to a separate group. Then when
you need to access all the enemies that are near the player, you
already have a list of them, instead of going through a list of all
the enemies, checking for the "close_to_player" flag. Later on your
game could add multiple players, and instead of adding more
"close_to_player2", "close_to_player3" attributes, you can easily add
them to different groups for each player.

		Another important benefit of using the Sprites and Groups, the
groups cleanly handle the deleting (or killing) of game objects. In a
game where many objects are referencing other objects, sometimes
deleting an object can be the hardest part, since it can't go away
until it is not referenced by anyone. Say we have an object that is
"chasing" another object. The chaser can keep a simple Group that
references the object (or objects) it is chasing. If the object being
chased happens to be destroyed, we don't need to worry about notifying
the chaser to stop chasing. The chaser can see for itself that its
group is now empty, and perhaps find a new target.

		Again, the thing to remember is that adding and removing sprites
from groups is a very cheap/fast operation. You may be best off by
adding many groups to contain and organize your game objects. Some
could even be empty for large portions of the game, there isn't any
penalties for managing your game like this.
	====
	"""
	def __init__(self, game):
	# def __init__(self, game, loc=(0,0), color=(128,128,128) ): # could
set variables manually
		pygame.sprite.Sprite.__init__(self)				
		self.image = pygame.Surface([15,15])
		self.game = game
		
		# for now use random values
		loc = random.randint(0, self.game.width), random.randint(0,self.game.height)
		c = random.randint(0,255)
		color = (c,c,c)
	
		self.image.fill(color)
		self.rect = self.image.get_rect()
		self.rect.center  = loc # or .topleft if you prefer
		
	def update(self):
		"""movement method. should make it time-based"""
		self.rect.left += 1
		# check if is alive, and act on it.
		# or
		
		
class Game():
	"""instance of main game class. would normally be in seperate file,
	game.py, but kept here for now.
	
	methods:
		add_unit : add a random unit to the group
	
	members:
		screen : surface to blit to
		done : if true, game ends
		clock : time.Clock()
		sprites : sprite.RenderPlain()
		
	"""
		
	def __init__(self, width=800, height=600):
		"""Initialize PyGame"""		
		pygame.init()
		self.done = False
		self.width, self.height = width, height

		self.clock = pygame.time.Clock()

		self.screen = pygame.display.set_mode(( self.width, self.height ))
		pygame.display.set_caption( "sprite_groups test" )
		
		self.sprites = pygame.sprite.RenderPlain()
		# self.sprites = pygame.sprite.Group()
		
	
	def add_unit(self):
		# if args: u = Unit(self,  (100,100), (64,64,64) )
		u = Unit(self) #else no args
		self.sprites.add( u )
		
	def update(self):
		# move objects
		self.sprites.update()
		
	def draw(self):
		self.screen.fill( (0,0,0))
		
		# draw guys here	
		# for s in self.sprites: s.draw()
		self.sprites.draw(self.screen)

		pygame.display.flip()
	
	def loop(self):				
		"""main loop"""
		while not self.done:
			self.handle_events()
			self.update()
			self.draw()
			
			self.clock.tick(60)
		
		print "%s units." % ( len(self.sprites) )

	def handle_events(self):
		events = pygame.event.get()
		for event in events:
			if event.type == pygame.QUIT: sys.exit()			
			# event: keydown
			elif event.type == KEYDOWN:
				# exit on 'escape'
				if (event.key == K_ESCAPE):
					self.done = True
				elif( event.key == K_SPACE):
					self.add_unit()					

if __name__ == "__main__":
	game = Game()
	game.loop()
-- 
Jake