PyIgnition

https://github.com/animatinator/PyIgnition update for Python 3
Clone: git clone https://git.frombelow.net/PyIgnition.git
Log | Files | Refs | README

PyIgnition.py (29576B)


      1 ### EXESOFT PYIGNITION ###
      2 # Copyright David Barker 2010
      3 #
      4 # Particle effect manager
      5 
      6 
      7 import particles, gravity, obstacles, constants, sys, pygame, xml
      8 from constants import *
      9 
     10 
     11 class ParticleEffect:
     12 	def __init__(self, display, pos = (0, 0), size = (0, 0)):
     13 		self.display = display
     14 		self.pos = pos
     15 		self.size = size
     16 		
     17 		self.left = pos[0]
     18 		self.top = pos[1]
     19 		self.right = pos[0] + size[0]
     20 		self.bottom = pos[1] + size[1]
     21 		
     22 		self.particles = []
     23 		self.sources = []
     24 		self.gravities = []
     25 		self.obstacles = []
     26 	
     27 	def Update(self):
     28 		for source in self.sources:
     29 			source.Update()
     30 		
     31 		for gravity in self.gravities:
     32 			gravity.Update()
     33 		
     34 		for obstacle in self.obstacles:
     35 			obstacle.Update()
     36 
     37 		for particle in self.particles:
     38 			radius = 0.0  # Used for making sure radii don't overlap objects...
     39 			
     40 			if particle.drawtype == DRAWTYPE_CIRCLE or particle.drawtype == DRAWTYPE_BUBBLE:
     41 				radius = particle.radius * (1.0 - RADIUS_PERMITTIVITY)  # ...But only set if the particle is actually circular
     42 			
     43 			# First calculate the forces acting on the particle
     44 			totalforce = [0.0, 0.0]
     45 			
     46 			for gravity in self.gravities:
     47 				force = gravity.GetForceOnParticle(particle)
     48 				totalforce[0] += force[0]
     49 				totalforce[1] += force[1]
     50 			
     51 			for obstacle in self.obstacles:
     52 				force = obstacle.GetForce(particle.pos, particle.velocity, radius)
     53 				totalforce[0] += force[0]
     54 				totalforce[1] += force[1]
     55 			
     56 			# Apply the forces to the velocity and update the particle
     57 			particle.velocity = [particle.velocity[0] + totalforce[0], particle.velocity[1] + totalforce[1]]
     58 			
     59 			particle.Update()
     60 			
     61 			# Resolve collisions
     62 			for obstacle in self.obstacles:
     63 				if (not obstacle.OutOfRange(particle.pos)) and (obstacle.InsideObject(particle.pos, radius)):
     64 					particle.pos = obstacle.GetResolved(particle.pos, radius)
     65 		
     66 		# Delete dead particles
     67 		for particle in self.particles:
     68 			if not particle.alive:
     69 				self.particles.remove(particle)
     70 	
     71 	def Redraw(self):
     72 		for particle in self.particles:
     73 			particle.Draw(self.display)
     74 		
     75 		for obstacle in self.obstacles:
     76 			obstacle.Draw(self.display)
     77 	
     78 	def CreateSource(self, pos = (0, 0), initspeed = 0.0, initdirection = 0.0, initspeedrandrange = 0.0, initdirectionrandrange = 0.0, particlesperframe = 0, particlelife = -1, genspacing = 0, drawtype = 0, colour = (0, 0, 0), radius = 0.0, length = 0.0, imagepath = None):
     79 		newsource = particles.ParticleSource(self, pos, initspeed, initdirection, initspeedrandrange, initdirectionrandrange, particlesperframe, particlelife, genspacing, drawtype, colour, radius, length, imagepath)
     80 		self.sources.append(newsource)
     81 		return newsource  # Effectively a reference
     82 	
     83 	def CreatePointGravity(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)):
     84 		newgrav = gravity.PointGravity(strength, strengthrandrange, pos)
     85 		self.gravities.append(newgrav)
     86 		return newgrav
     87 	
     88 	def CreateDirectedGravity(self, strength = 0.0, strengthrandrange = 0.0, direction = [0, 1]):
     89 		newgrav = gravity.DirectedGravity(strength, strengthrandrange, direction)
     90 		self.gravities.append(newgrav)
     91 		return newgrav
     92 	
     93 	def CreateVortexGravity(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)):
     94 		newgrav = gravity.VortexGravity(strength, strengthrandrange, pos)
     95 		self.gravities.append(newgrav)
     96 		return newgrav
     97 	
     98 	def CreateCircle(self, pos = (0, 0), colour = (0, 0, 0), bounce = 1.0, radius = 0.0):
     99 		newcircle = obstacles.Circle(self, pos, colour, bounce, radius)
    100 		self.obstacles.append(newcircle)
    101 		return newcircle
    102 	
    103 	def CreateRectangle(self, pos = (0, 0), colour = (0, 0, 0), bounce = 1.0, width = 0.0, height = 0.0):
    104 		newrect = obstacles.Rectangle(self, pos, colour, bounce, width, height)
    105 		self.obstacles.append(newrect)
    106 		return newrect
    107 	
    108 	def CreateBoundaryLine(self, pos = (0, 0), colour = (0, 0, 0), bounce = 1.0, normal = [0, 1]):
    109 		newline = obstacles.BoundaryLine(self, pos, colour, bounce, normal)
    110 		self.obstacles.append(newline)
    111 		return newline
    112 	
    113 	def AddParticle(self, particle):
    114 		self.particles.append(particle)
    115 	
    116 	def GetDrawtypeAsString(self, drawtype):
    117 		if drawtype == DRAWTYPE_POINT:
    118 			return "point"
    119 		elif drawtype == DRAWTYPE_CIRCLE:
    120 			return "circle"
    121 		elif drawtype == DRAWTYPE_LINE:
    122 			return "line"
    123 		elif drawtype == DRAWTYPE_SCALELINE:
    124 			return "scaleline"
    125 		elif drawtype == DRAWTYPE_BUBBLE:
    126 			return "bubble"
    127 		elif drawtype == DRAWTYPE_IMAGE:
    128 			return "image"
    129 		else:
    130 			return "ERROR: Invalid drawtype"
    131 	
    132 	def GetStringAsDrawtype(self, string):
    133 		if string == "point":
    134 			return DRAWTYPE_POINT
    135 		elif string == "circle":
    136 			return DRAWTYPE_CIRCLE
    137 		elif string == "line":
    138 			return DRAWTYPE_LINE
    139 		elif string == "scaleline":
    140 			return DRAWTYPE_SCALELINE
    141 		elif string == "bubble":
    142 			return DRAWTYPE_BUBBLE
    143 		elif string == "image":
    144 			return DRAWTYPE_IMAGE
    145 		else:
    146 			return DRAWTYPE_POINT
    147 	
    148 	def GetInterpolationtypeAsString(self, interpolationtype):
    149 		if interpolationtype == INTERPOLATIONTYPE_LINEAR:
    150 			return "linear"
    151 		elif interpolationtype == INTERPOLATIONTYPE_COSINE:
    152 			return "cosine"
    153 	
    154 	def GetStringAsInterpolationtype(self, string):
    155 		if string == "linear":
    156 			return INTERPOLATIONTYPE_LINEAR
    157 		elif string == "cosine":
    158 			return INTERPOLATIONTYPE_COSINE
    159 		else:
    160 			return INTERPOLATIONTYPE_LINEAR
    161 	
    162 	def TranslatePos(self, pos):
    163 		return (pos[0] - self.pos[0], pos[1] - self.pos[1])
    164 	
    165 	def ConvertXMLTuple(self, string):
    166 		# 'string' must be of the form "(value, value, value, [...])"
    167 		bracketless = string.replace("(", "").replace(")", "")
    168 		strings = bracketless.split(", ")
    169 		finaltuple = []
    170 		for string in strings:
    171 			temp = string.split(".")
    172 			if len(temp) > 1:
    173 				finaltuple.append(float(string))
    174 			else:
    175 				finaltuple.append(int(string))
    176 		
    177 		return tuple(finaltuple)
    178 	
    179 	def SaveToFile(self, outfilename):
    180 		outfile = open(outfilename, 'w')
    181 		
    182 		outfile.write("<?xml version = \"1.0\"?>\n<?pyignition version = \"%f\"?>\n\n" % PYIGNITION_VERSION)
    183 		outfile.write("<effect>\n")
    184 		
    185 		# Write out sources
    186 		for source in self.sources:
    187 			outfile.write("\t<source>\n")
    188 			
    189 			# Write out source variables
    190 			outfile.write("\t\t<pos>(%i, %i)</pos>\n" % source.pos)
    191 			outfile.write("\t\t<initspeed>%f</initspeed>\n" % source.initspeed)
    192 			outfile.write("\t\t<initdirection>%f</initdirection>\n" % source.initdirection)
    193 			outfile.write("\t\t<initspeedrandrange>%f</initspeedrandrange>\n" % source.initspeedrandrange)
    194 			outfile.write("\t\t<initdirectionrandrange>%f</initdirectionrandrange>\n" % source.initdirectionrandrange)
    195 			outfile.write("\t\t<particlesperframe>%i</particlesperframe>\n" % source.particlesperframe)
    196 			outfile.write("\t\t<particlelife>%i</particlelife>\n" % source.particlelife)
    197 			outfile.write("\t\t<genspacing>%i</genspacing>\n" % source.genspacing)
    198 			outfile.write("\t\t<drawtype>%s</drawtype>\n" % self.GetDrawtypeAsString(source.drawtype))
    199 			outfile.write("\t\t<colour>(%i, %i, %i)</colour>\n" % source.colour)
    200 			outfile.write("\t\t<radius>%f</radius>\n" % source.radius)
    201 			outfile.write("\t\t<length>%f</length>\n" % source.length)
    202 			outfile.write("\t\t<imagepath>%s</imagepath>\n" % source.imagepath)
    203 			
    204 			# Write out source keyframes
    205 			outfile.write("\t\t<keyframes>\n")
    206 			
    207 			for keyframe in source.keyframes:
    208 				if keyframe.frame == 0:  # Don't bother writing out the first keyframe
    209 					continue
    210 				
    211 				outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame)
    212 				
    213 				# Write out keyframed variables
    214 				for variable in keyframe.variables.keys():
    215 					if variable == "interpolationtype":
    216 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable))
    217 					else:
    218 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable))
    219 				
    220 				outfile.write("\t\t\t</keyframe>\n")
    221 			
    222 			outfile.write("\t\t</keyframes>\n")
    223 			
    224 			# Write out source particle keyframes
    225 			outfile.write("\t\t<particlekeyframes>\n")
    226 			
    227 			for keyframe in source.particlekeyframes:
    228 				if keyframe.frame == 0:  # Don't bother writing out the first keyframe
    229 					continue
    230 					
    231 				outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame)
    232 				
    233 				# Write out keyframed variables
    234 				for variable in keyframe.variables.keys():
    235 					if variable == "interpolationtype":
    236 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable))
    237 					else:
    238 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable))
    239 				
    240 				outfile.write("\t\t\t</keyframe>\n")
    241 			
    242 			outfile.write("\t\t</particlekeyframes>\n")
    243 			
    244 			outfile.write("\t</source>\n\n")
    245 		
    246 		# Write out gravities
    247 		for gravity in self.gravities:
    248 			# Identify type
    249 			gtype = gravity.type
    250 			
    251 			outfile.write("\t<%sgravity>\n" % gtype)
    252 			
    253 			# Write out gravity variables
    254 			outfile.write("\t\t<strength>%f</strength>\n" % gravity.initstrength)
    255 			outfile.write("\t\t<strengthrandrange>%f</strengthrandrange>\n" % gravity.strengthrandrange)
    256 			if gtype == "directed":
    257 				outfile.write("\t\t<direction>(%f, %f)</direction>\n" % tuple(gravity.direction))
    258 			elif gtype == "point" or gtype == "vortex":
    259 				outfile.write("\t\t<pos>(%i, %i)</pos>\n" % gravity.pos)
    260 			
    261 			# Write out gravity keyframes
    262 			outfile.write("\t\t<keyframes>\n")
    263 			
    264 			for keyframe in gravity.keyframes:
    265 				if keyframe.frame == 0:  # Don't bother writing out the first keyframe
    266 					continue
    267 				
    268 				outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame)
    269 				
    270 				# Write out keyframed variables
    271 				for variable in keyframe.variables.keys():
    272 					if variable == "interpolationtype":
    273 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable))
    274 					else:
    275 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable))
    276 				
    277 				outfile.write("\t\t\t</keyframe>\n")
    278 			
    279 			outfile.write("\t\t</keyframes>\n")
    280 			
    281 			outfile.write("\t</%sgravity>\n\n" % gtype)
    282 		
    283 		# Write out obstacles
    284 		for obstacle in self.obstacles:
    285 			# Identify type
    286 			otype = obstacle.type
    287 			
    288 			outfile.write("\t<%s>\n" % otype)
    289 			
    290 			# Write out obstacle variables
    291 			outfile.write("\t\t<pos>(%i, %i)</pos>\n" % obstacle.pos)
    292 			outfile.write("\t\t<colour>(%i, %i, %i)</colour>\n" % obstacle.colour)
    293 			outfile.write("\t\t<bounce>%f</bounce>\n" % obstacle.bounce)
    294 			if otype == "circle":
    295 				outfile.write("\t\t<radius>%f</radius>\n" % obstacle.radius)
    296 			elif otype == "rectangle":
    297 				outfile.write("\t\t<width>%i</width>\n" % obstacle.width)
    298 				outfile.write("\t\t<height>%i</height>\n" % obstacle.height)
    299 			elif otype == "boundaryline":
    300 				outfile.write("\t\t<normal>(%f, %f)</normal>\n" % tuple(obstacle.normal))
    301 			
    302 			# Write out obstacle keyframes
    303 			outfile.write("\t\t<keyframes>\n")
    304 			
    305 			for keyframe in obstacle.keyframes:
    306 				if keyframe.frame == 0:  # Don't bother writing out the first keyframe
    307 					continue
    308 				
    309 				outfile.write("\t\t\t<keyframe frame = \"%i\">\n" % keyframe.frame)
    310 				
    311 				# Write out keyframed variables
    312 				for variable in keyframe.variables.keys():
    313 					if variable == "interpolationtype":
    314 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, self.GetInterpolationtypeAsString(keyframe.variables[variable]), variable))
    315 					else:
    316 						outfile.write("\t\t\t\t<%s>%s</%s>\n" % (variable, str(keyframe.variables[variable]), variable))
    317 				
    318 				outfile.write("\t\t\t</keyframe>\n")
    319 			
    320 			outfile.write("\t\t</keyframes>\n")
    321 			
    322 			outfile.write("\t</%s>\n\n" % otype)
    323 		
    324 		outfile.write("</effect>")
    325 		outfile.close()
    326 	
    327 	def LoadFromFile(self, infilename):
    328 		infile = open(infilename, "r")
    329 		
    330 		data = xml.XMLParser(infile.read()).Parse()
    331 		infile.close()
    332 		
    333 		for child in data.children:
    334 			if child.tag == "source":  # Source object
    335 				pos = (0, 0)
    336 				initspeed = 0.0
    337 				initdirection = 0.0
    338 				initspeedrandrange = 0.0
    339 				initdirectionrandrange = 0.0
    340 				particlesperframe = 0
    341 				particlelife = 0
    342 				genspacing = 0
    343 				drawtype = DRAWTYPE_POINT
    344 				colour = (0, 0, 0)
    345 				radius = 0.0
    346 				length = 0.0
    347 				imagepath = None
    348 				
    349 				keyframes = None
    350 				particlekeyframes = None
    351 				
    352 				for parameter in child.children:
    353 					if parameter.tag == "pos":
    354 						pos = self.ConvertXMLTuple(parameter.inside)
    355 					elif parameter.tag == "initspeed":
    356 						initspeed = float(parameter.inside)
    357 					elif parameter.tag == "initdirection":
    358 						initdirection = float(parameter.inside)
    359 					elif parameter.tag == "initspeedrandrange":
    360 						initspeedrandrange = float(parameter.inside)
    361 					elif parameter.tag == "initdirectionrandrange":
    362 						initdirectionrandrange = float(parameter.inside)
    363 					elif parameter.tag == "particlesperframe":
    364 						particlesperframe = int(parameter.inside)
    365 					elif parameter.tag == "particlelife":
    366 						particlelife = int(parameter.inside)
    367 					elif parameter.tag == "genspacing":
    368 						genspacing = int(parameter.inside)
    369 					elif parameter.tag == "drawtype":
    370 						drawtype = self.GetStringAsDrawtype(parameter.inside)
    371 					elif parameter.tag == "colour":
    372 						colour = self.ConvertXMLTuple(parameter.inside)
    373 					elif parameter.tag == "radius":
    374 						radius = float(parameter.inside)
    375 					elif parameter.tag == "length":
    376 						length = float(parameter.inside)
    377 					elif parameter.tag == "image":
    378 						imagepath = float(parameter.inside)
    379 					elif parameter.tag == "keyframes":
    380 						keyframes = parameter.children
    381 					elif parameter.tag == "particlekeyframes":
    382 						particlekeyframes = parameter.children
    383 				
    384 				newsource = self.CreateSource(pos, initspeed, initdirection, initspeedrandrange, initdirectionrandrange, particlesperframe, particlelife, genspacing, drawtype, colour, radius, length, imagepath)
    385 				
    386 				for keyframe in keyframes:
    387 					frame = int(keyframe.meta['frame'])
    388 					variables = {}
    389 					
    390 					for variable in keyframe.children:
    391 						if variable.tag == "pos_x" and variable.inside != "None":
    392 							variables['pos_x'] = int(variable.inside)
    393 						elif variable.tag == "pos_y" and variable.inside != "None":
    394 							variables['pos_y'] = int(variable.inside)
    395 						elif variable.tag == "initspeed" and variable.inside != "None":
    396 							variables['initspeed'] = float(variable.inside)
    397 						elif variable.tag == "initdirection" and variable.inside != "None":
    398 							variables['initdirection'] = float(variable.inside)
    399 						elif variable.tag == "initspeedrandrange" and variable.inside != "None":
    400 							variables['initspeedrandrange'] = float(variable.inside)
    401 						elif variable.tag == "initdirectionrandrange" and variable.inside != "None":
    402 							variables['initdirectionrandrange'] = float(variable.inside)
    403 						elif variable.tag == "particlesperframe" and variable.inside != "None":
    404 							variables['particlesperframe'] = int(variable.inside)
    405 						elif variable.tag == "genspacing" and variable.inside != "None":
    406 							variables['genspacing'] = int(variable.inside)
    407 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    408 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    409 						
    410 					newframe = newsource.CreateKeyframe(frame = frame)
    411 					newframe.variables = variables
    412 				
    413 				for keyframe in particlekeyframes:
    414 					frame = int(keyframe.meta['frame'])
    415 					variables = {}
    416 					
    417 					for variable in keyframe.children:
    418 						if variable.tag == "colour_r" and variable.inside != "None":
    419 							variables['colour_r'] = int(variable.inside)
    420 						elif variable.tag == "colour_g" and variable.inside != "None":
    421 							variables['colour_g'] = int(variable.inside)
    422 						elif variable.tag == "colour_b" and variable.inside != "None":
    423 							variables['colour_b'] = int(variable.inside)
    424 						elif variable.tag == "radius" and variable.inside != "None":
    425 							variables['radius'] = float(variable.inside)
    426 						elif variable.tag == "length" and variable.inside != "None":
    427 							variables['length'] = float(variable.inside)
    428 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    429 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    430 					
    431 					newframe = newsource.CreateParticleKeyframe(frame = frame)
    432 					newframe.variables = variables
    433 					newsource.PreCalculateParticles()
    434 			
    435 			elif child.tag == "directedgravity":
    436 				strength = 0.0
    437 				strengthrandrange = 0.0
    438 				direction = [0, 0]
    439 				
    440 				keyframes = None
    441 				
    442 				for parameter in child.children:
    443 					if parameter.tag == "strength":
    444 						strength = float(parameter.inside)
    445 					elif parameter.tag == "strengthrandrange":
    446 						strengthrandrange = float(parameter.inside)
    447 					elif parameter.tag == "direction":
    448 						direction = self.ConvertXMLTuple(parameter.inside)
    449 					elif parameter.tag == "keyframes":
    450 						keyframes = parameter.children
    451 				
    452 				newgrav = self.CreateDirectedGravity(strength, strengthrandrange, direction)
    453 				
    454 				for keyframe in keyframes:
    455 					frame = int(keyframe.meta['frame'])
    456 					variables = {}
    457 					
    458 					for variable in keyframe.children:
    459 						if variable.tag == "strength" and variable.inside != "None":
    460 							variables['strength'] = float(variable.inside)
    461 						elif variable.tag == "strengthrandrange" and variable.inside != "None":
    462 							variables['strengthrandrange'] = float(variable.inside)
    463 						elif  variable.tag == "direction_x" and variable.inside != "None":
    464 							variables['direction_x'] = float(variable.inside)
    465 						elif  variable.tag == "direction_y" and variable.inside != "None":
    466 							variables['direction_y'] = float(variable.inside)
    467 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    468 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    469 					
    470 					newframe = newgrav.CreateKeyframe(frame = frame)
    471 					newframe.variables = variables
    472 			
    473 			elif child.tag == "pointgravity":
    474 				strength = 0.0
    475 				strengthrandrange = 0.0
    476 				pos = (0, 0)
    477 				
    478 				keyframes = None
    479 				
    480 				for parameter in child.children:
    481 					if parameter.tag == "strength":
    482 						strength = float(parameter.inside)
    483 					elif parameter.tag == "strengthrandrange":
    484 						strengthrandrange = float(parameter.inside)
    485 					elif parameter.tag == "pos":
    486 						pos = self.ConvertXMLTuple(parameter.inside)
    487 					elif parameter.tag == "keyframes":
    488 						keyframes = parameter.children
    489 				
    490 				newgrav = self.CreatePointGravity(strength, strengthrandrange, pos)
    491 				
    492 				for keyframe in keyframes:
    493 					frame = int(keyframe.meta['frame'])
    494 					variables = {}
    495 					
    496 					for variable in keyframe.children:
    497 						if variable.tag == "strength" and variable.inside != "None":
    498 							variables['strength'] = float(variable.inside)
    499 						elif variable.tag == "strengthrandrange" and variable.inside != "None":
    500 							variables['strengthrandrange'] = float(variable.inside)
    501 						elif  variable.tag == "pos_x" and variable.inside != "None":
    502 							variables['pos_x'] = int(variable.inside)
    503 						elif  variable.tag == "pos_y" and variable.inside != "None":
    504 							variables['pos_y'] = int(variable.inside)
    505 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    506 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    507 					
    508 					newframe = newgrav.CreateKeyframe(frame = frame)
    509 					newframe.variables = variables
    510 			
    511 			elif child.tag == "vortexgravity":
    512 				strength = 0.0
    513 				strengthrandrange = 0.0
    514 				pos = (0, 0)
    515 				
    516 				keyframes = None
    517 				
    518 				for parameter in child.children:
    519 					if parameter.tag == "strength":
    520 						strength = float(parameter.inside)
    521 					elif parameter.tag == "strengthrandrange":
    522 						strengthrandrange = float(parameter.inside)
    523 					elif parameter.tag == "pos":
    524 						direction = self.ConvertXMLTuple(parameter.inside)
    525 					elif parameter.tag == "keyframes":
    526 						keyframes = parameter.children
    527 				
    528 				newgrav = self.CreateVortexGravity(strength, strengthrandrange, pos)
    529 				
    530 				for keyframe in keyframes:
    531 					frame = int(keyframe.meta['frame'])
    532 					variables = {}
    533 					
    534 					for variable in keyframe.children:
    535 						if variable.tag == "strength" and variable.inside != "None":
    536 							variables['strength'] = float(variable.inside)
    537 						elif variable.tag == "strengthrandrange" and variable.inside != "None":
    538 							variables['strengthrandrange'] = float(variable.inside)
    539 						elif  variable.tag == "pos_x" and variable.inside != "None":
    540 							variables['pos_x'] = int(variable.inside)
    541 						elif  variable.tag == "pos_y" and variable.inside != "None":
    542 							variables['pos_y'] = int(variable.inside)
    543 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    544 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    545 					
    546 					newframe = newgrav.CreateKeyframe(frame = frame)
    547 					newframe.variables = variables
    548 			
    549 			elif child.tag == "circle":
    550 				pos = (0, 0)
    551 				colour = (0, 0, 0)
    552 				bounce = 0.0
    553 				radius = 0.0
    554 				
    555 				keyframes = None
    556 				
    557 				for parameter in child.children:
    558 					if parameter.tag == "pos":
    559 						pos = self.ConvertXMLTuple(parameter.inside)
    560 					elif parameter.tag == "colour":
    561 						colour = self.ConvertXMLTuple(parameter.inside)
    562 					elif parameter.tag == "bounce":
    563 						bounce = float(parameter.inside)
    564 					elif parameter.tag == "radius":
    565 						radius = float(parameter.inside)
    566 					elif parameter.tag == "keyframes":
    567 						keyframes = parameter.children
    568 				
    569 				newobstacle = self.CreateCircle(pos, colour, bounce, radius)
    570 				
    571 				for keyframe in keyframes:
    572 					frame = int(keyframe.meta['frame'])
    573 					variables = {}
    574 					
    575 					for variable in keyframe.children:
    576 						if variable.tag == "pos_x" and variable.inside != "None":
    577 							variables['pos_x'] = int(variable.inside)
    578 						elif variable.tag == "pos_y" and variable.inside != "None":
    579 							variables['pos_y'] = int(variable.inside)
    580 						elif variable.tag == "colour_r" and variable.inside != "None":
    581 							variables['colour_r'] = int(variable.inside)
    582 						elif variable.tag == "colour_g" and variable.inside != "None":
    583 							variables['colour_g'] = int(variable.inside)
    584 						elif variable.tag == "colour_b" and variable.inside != "None":
    585 							variables['colour_b'] = int(variable.inside)
    586 						elif variable.tag == "bounce" and variable.inside != "None":
    587 							variables['bounce'] = float(variable.inside)
    588 						elif variable.tag == "radius" and variable.inside != "None":
    589 							variables['radius'] = float(variable.inside)
    590 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    591 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    592 					
    593 					newframe = newobstacle.CreateKeyframe(frame = frame)
    594 					newframe.variables = variables
    595 		
    596 			elif child.tag == "rectangle":
    597 				pos = (0, 0)
    598 				colour = (0, 0, 0)
    599 				bounce = 0.0
    600 				width = 0.0
    601 				height = 0.0
    602 				
    603 				keyframes = None
    604 				
    605 				for parameter in child.children:
    606 					if parameter.tag == "pos":
    607 						pos = self.ConvertXMLTuple(parameter.inside)
    608 					elif parameter.tag == "colour":
    609 						colour = self.ConvertXMLTuple(parameter.inside)
    610 					elif parameter.tag == "bounce":
    611 						bounce = float(parameter.inside)
    612 					elif parameter.tag == "width":
    613 						width = float(parameter.inside)
    614 					elif parameter.tag == "height":
    615 						height = float(parameter.inside)
    616 					elif parameter.tag == "keyframes":
    617 						keyframes = parameter.children
    618 				
    619 				newobstacle = self.CreateRectangle(pos, colour, bounce, width, height)
    620 				
    621 				for keyframe in keyframes:
    622 					frame = int(keyframe.meta['frame'])
    623 					variables = {}
    624 					
    625 					for variable in keyframe.children:
    626 						if variable.tag == "pos_x" and variable.inside != "None":
    627 							variables['pos_x'] = int(variable.inside)
    628 						elif variable.tag == "pos_y" and variable.inside != "None":
    629 							variables['pos_y'] = int(variable.inside)
    630 						elif variable.tag == "colour_r" and variable.inside != "None":
    631 							variables['colour_r'] = int(variable.inside)
    632 						elif variable.tag == "colour_g" and variable.inside != "None":
    633 							variables['colour_g'] = int(variable.inside)
    634 						elif variable.tag == "colour_b" and variable.inside != "None":
    635 							variables['colour_b'] = int(variable.inside)
    636 						elif variable.tag == "bounce" and variable.inside != "None":
    637 							variables['bounce'] = float(variable.inside)
    638 						elif variable.tag == "width" and variable.inside != "None":
    639 							variables['width'] = float(variable.inside)
    640 						elif variable.tag == "height" and variable.inside != "None":
    641 							variables['height'] = float(variable.inside)
    642 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    643 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    644 					
    645 					newframe = newobstacle.CreateKeyframe(frame = frame)
    646 					newframe.variables = variables
    647 		
    648 			elif child.tag == "boundaryline":
    649 				pos = (0, 0)
    650 				colour = (0, 0, 0)
    651 				bounce = 0.0
    652 				direction = [0.0, 0.0]
    653 				
    654 				keyframes = None
    655 				
    656 				for parameter in child.children:
    657 					if parameter.tag == "pos":
    658 						pos = self.ConvertXMLTuple(parameter.inside)
    659 					elif parameter.tag == "colour":
    660 						colour = self.ConvertXMLTuple(parameter.inside)
    661 					elif parameter.tag == "bounce":
    662 						bounce = float(parameter.inside)
    663 					elif parameter.tag == "normal":
    664 						normal = self.ConvertXMLTuple(parameter.inside)
    665 					elif parameter.tag == "keyframes":
    666 						keyframes = parameter.children
    667 				
    668 				newobstacle = self.CreateBoundaryLine(pos, colour, bounce, normal)
    669 				
    670 				for keyframe in keyframes:
    671 					frame = int(keyframe.meta['frame'])
    672 					variables = {}
    673 					
    674 					for variable in keyframe.children:
    675 						if variable.tag == "pos_x" and variable.inside != "None":
    676 							variables['pos_x'] = int(variable.inside)
    677 						elif variable.tag == "pos_y" and variable.inside != "None":
    678 							variables['pos_y'] = int(variable.inside)
    679 						elif variable.tag == "colour_r" and variable.inside != "None":
    680 							variables['colour_r'] = int(variable.inside)
    681 						elif variable.tag == "colour_g" and variable.inside != "None":
    682 							variables['colour_g'] = int(variable.inside)
    683 						elif variable.tag == "colour_b" and variable.inside != "None":
    684 							variables['colour_b'] = int(variable.inside)
    685 						elif variable.tag == "bounce" and variable.inside != "None":
    686 							variables['bounce'] = float(variable.inside)
    687 						elif variable.tag == "normal_x" and variable.inside != "None":
    688 							variables['normal_x'] = float(variable.inside)
    689 						elif variable.tag == "normal_y" and variable.inside != "None":
    690 							variables['normal_y'] = float(variable.inside)
    691 						elif variable.tag == "interpolationtype" and variable.inside != "None":
    692 							variables['interpolationtype'] = self.GetStringAsInterpolationtype(variable.inside)
    693 					
    694 					newframe = newobstacle.CreateKeyframe(frame = frame)
    695 					newframe.variables = variables
    696 
    697 	def PropogateCurframe(self, newframe):
    698 		for source in self.sources:
    699 			source.curframe = newframe
    700 		for gravity in self.gravities:
    701 			gravity.curframe = newframe
    702 		for obstacle in self.obstacles:
    703 			obstacle.curframe = newframe
    704 
    705 
    706 ## Begin testing code
    707 if __name__ == '__main__':
    708 	screen = pygame.display.set_mode((800, 600))
    709 	pygame.display.set_caption("PyIgnition demo")
    710 	clock = pygame.time.Clock()
    711 	test = ParticleEffect(screen, (0, 0), (800, 600))
    712 	testgrav = test.CreatePointGravity(strength = 1.0, pos = (500, 380))
    713 	testgrav.CreateKeyframe(300, strength = 10.0, pos = (0, 0))
    714 	testgrav.CreateKeyframe(450, strength = 10.0, pos = (40, 40))
    715 	testgrav.CreateKeyframe(550, strength = -2.0, pos = (600, 480))
    716 	testgrav.CreateKeyframe(600, strength = -20.0, pos = (600, 0))
    717 	testgrav.CreateKeyframe(650, strength = 1.0, pos = (500, 380))
    718 	anothertestgrav = test.CreateDirectedGravity(strength = 0.04, direction = [1, 0])
    719 	anothertestgrav.CreateKeyframe(300, strength = 1.0, direction = [-0.5, 1])
    720 	anothertestgrav.CreateKeyframe(600, strength = 1.0, direction = [1.0, -0.1])
    721 	anothertestgrav.CreateKeyframe(650, strength = 0.04, direction = [1, 0])
    722 	testsource = test.CreateSource((10, 10), initspeed = 5.0, initdirection = 2.35619449, initspeedrandrange = 2.0, initdirectionrandrange = 1.0, particlesperframe = 5, particlelife = 125, drawtype = DRAWTYPE_SCALELINE, colour = (255, 255, 255), length = 10.0)
    723 	testsource.CreateParticleKeyframe(50, colour = (0, 255, 0), length = 10.0)
    724 	testsource.CreateParticleKeyframe(75, colour = (255, 255, 0), length = 10.0)
    725 	testsource.CreateParticleKeyframe(100, colour = (0, 255, 255), length = 10.0)
    726 	testsource.CreateParticleKeyframe(125, colour = (0, 0, 0), length = 10.0)
    727 	
    728 	test.SaveToFile("PyIgnition test.ppe")
    729 	
    730 	while True:
    731 		for event in pygame.event.get():
    732 			if event.type == pygame.QUIT:
    733 				sys.exit()
    734 		
    735 		screen.fill((0, 0, 0))
    736 		test.Update()
    737 		test.Redraw()
    738 		pygame.display.update()
    739 		clock.tick(20)