PyIgnition

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

gravity.py (8991B)


      1 ### EXESOFT PYIGNITION ###
      2 # Copyright David Barker 2010
      3 #
      4 # Gravity objects
      5 
      6 
      7 from math import sqrt
      8 import keyframes, interpolate, random
      9 from constants import *
     10 
     11 
     12 def RandomiseStrength(base, range):
     13 	return base + (float(random.randrange(int(-range * 100), int(range * 100))) / 100.0)
     14 
     15 
     16 class DirectedGravity:
     17 	def __init__(self, strength = 0.0, strengthrandrange = 0.0, direction = [0, 1]):
     18 		self.selected = False
     19 		self.type = "directed"
     20 		self.initstrength = strength
     21 		self.strength = strength
     22 		self.strengthrandrange = strengthrandrange
     23 		directionmag = sqrt(direction[0]**2 + direction[1]**2)
     24 		self.direction = [direction[0] / directionmag, direction[1] / directionmag]
     25 		
     26 		self.keyframes = []
     27 		self.CreateKeyframe(0, self.strength, self.strengthrandrange, self.direction)
     28 		self.curframe = 0
     29 	
     30 	def Update(self):
     31 		newvars = interpolate.InterpolateKeyframes(self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'direction_x':self.direction[0], 'direction_y':self.direction[1]}, self.keyframes)
     32 		self.initstrength = newvars['strength']
     33 		self.strengthrandrange = newvars['strengthrandrange']
     34 		self.direction = [newvars['direction_x'], newvars['direction_y']]
     35 		
     36 		if self.strengthrandrange != 0.0:
     37 			self.strength = RandomiseStrength(self.initstrength, self.strengthrandrange)
     38 		
     39 		self.curframe = self.curframe + 1
     40 	
     41 	def GetForce(self, pos):
     42 		force = [self.strength * self.direction[0], self.strength * self.direction[1]]
     43 		
     44 		return force
     45 	
     46 	def GetForceOnParticle(self, particle):
     47 		return self.GetForce(particle.pos)
     48 	
     49 	def CreateKeyframe(self, frame, strength = None, strengthrandrange = None, direction = [None, None], interpolationtype = INTERPOLATIONTYPE_LINEAR):
     50 		return keyframes.CreateKeyframe(self.keyframes, frame, {'strength':strength, 'strengthrandrange':strengthrandrange, 'direction_x':direction[0], 'direction_y':direction[1], 'interpolationtype':interpolationtype})
     51 	
     52 	def ConsolidateKeyframes(self):
     53 		keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'direction_x':self.direction[0], 'direction_y':self.direction[1]})
     54 	
     55 	def SetStrength(self, newstrength):
     56 		self.CreateKeyframe(self.curframe, strength = newstrength)
     57 	
     58 	def SetStrengthRandRange(self, newstrengthrandrange):
     59 		self.CreateKeyframe(self.curframe, strengthrandrange = newstrengthrandrange)
     60 	
     61 	def SetDirection(self, newdirection):
     62 		self.CreateKeyframe(self.curframe, direction = newdirection)
     63 
     64 
     65 class PointGravity:
     66 	def __init__(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)):
     67 		self.selected = False
     68 		self.type = "point"
     69 		self.initstrength = strength
     70 		self.strength = strength
     71 		self.strengthrandrange = strengthrandrange
     72 		self.pos = pos
     73 		
     74 		self.keyframes = []
     75 		self.CreateKeyframe(0, self.strength, self.strengthrandrange, self.pos)
     76 		self.curframe = 0
     77 	
     78 	def Update(self):			
     79 		newvars = interpolate.InterpolateKeyframes(self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]}, self.keyframes)
     80 		self.initstrength = newvars['strength']
     81 		self.strengthrandrange = newvars['strengthrandrange']
     82 		self.pos = (newvars['pos_x'], newvars['pos_y'])
     83 		
     84 		if self.strengthrandrange != 0.0:
     85 			self.strength = RandomiseStrength(self.initstrength, self.strengthrandrange)
     86 		else:
     87 			self.strength = self.initstrength
     88 		
     89 		self.curframe = self.curframe + 1
     90 	
     91 	def GetForce(self, pos):
     92 		distsquared = (pow(float(pos[0] - self.pos[0]), 2.0) + pow(float(pos[1] - self.pos[1]), 2.0))
     93 		if distsquared == 0.0:
     94 			return [0.0, 0.0]
     95 		
     96 		forcemag = (self.strength * UNIVERSAL_CONSTANT_OF_MAKE_GRAVITY_LESS_STUPIDLY_SMALL) / (distsquared)
     97 		
     98 		# Calculate normal vector from pos to the gravity point and multiply by force magnitude to find force vector
     99 		dist = sqrt(distsquared)
    100 		dx = float(self.pos[0] - pos[0]) / dist
    101 		dy = float(self.pos[1] - pos[1]) / dist
    102 		
    103 		force = [forcemag * dx, forcemag * dy]
    104 		
    105 		return force
    106 	
    107 	def GetForceOnParticle(self, particle):
    108 		return self.GetForce(particle.pos)
    109 	
    110 	def GetMaxForce(self):
    111 		return self.strength * UNIVERSAL_CONSTANT_OF_MAKE_GRAVITY_LESS_STUPIDLY_SMALL
    112 	
    113 	def CreateKeyframe(self, frame, strength = None, strengthrandrange = None, pos = (None, None), interpolationtype = INTERPOLATIONTYPE_LINEAR):
    114 		return keyframes.CreateKeyframe(self.keyframes, frame, {'strength':strength, 'strengthrandrange':strengthrandrange, 'pos_x':pos[0], 'pos_y':pos[1], 'interpolationtype':interpolationtype})
    115 	
    116 	def ConsolidateKeyframes(self):
    117 		keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]})
    118 	
    119 	def SetStrength(self, newstrength):
    120 		self.CreateKeyframe(self.curframe, strength = newstrength)
    121 	
    122 	def SetStrengthRandRange(self, newstrengthrandrange):
    123 		self.CreateKeyframe(self.curframe, strengthrandrange = newstrengthrandrange)
    124 	
    125 	def SetPos(self, newpos):
    126 		self.CreateKeyframe(self.curframe, pos = newpos)
    127 
    128 
    129 class VortexGravity(PointGravity):
    130 	def __init__(self, strength = 0.0, strengthrandrange = 0.0, pos = (0, 0)):
    131 		PointGravity.__init__(self, strength, strengthrandrange, pos)
    132 		self.type = "vortex"
    133 		
    134 		self.CreateKeyframe(0, self.strength, self.strengthrandrange, self.pos)
    135 	
    136 	def Update(self):			
    137 		newvars = interpolate.InterpolateKeyframes(self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]}, self.keyframes)
    138 		self.initstrength = newvars['strength']
    139 		self.strengthrandrange = newvars['strengthrandrange']
    140 		self.pos = (newvars['pos_x'], newvars['pos_y'])
    141 		
    142 		if self.strengthrandrange != 0.0:
    143 			self.strength = RandomiseStrength(self.initstrength, self.strengthrandrange)
    144 		else:
    145 			self.strength = self.initstrength
    146 		
    147 		self.curframe = self.curframe + 1
    148 	
    149 	def GetForce(self, pos):
    150 		try:
    151 			self.alreadyshownerror
    152 		except:
    153 			print ("WARNING: VortexGravity relies upon particle velocities as well as positions, and so its \
    154 				force can only be obtained using GetForceOnParticle([PyIgnition particle object]).".replace("\t", ""))
    155 			self.alreadyshownerror = True
    156 		
    157 		return [0.0, 0.0]
    158 	
    159 	def GetForceOnParticle(self, particle):
    160 		# This uses F = m(v^2 / r) (the formula for centripetal force on an object moving in a circle)
    161 		# to determine what force should be applied to keep an object circling the gravity. A small extra
    162 		# force (self.strength * VORTEX_ACCELERATION) is added in order to accelerate objects inward as
    163 		# well, thus creating a spiralling effect. Note that unit mass is assumed throughout.
    164 		
    165 		distvector = [self.pos[0] - particle.pos[0], self.pos[1] - particle.pos[1]]  # Vector from the particle to this gravity
    166 		try:
    167 			distmag = sqrt(float(distvector[0] ** 2) + float(distvector[1] ** 2))  # Distance from the particle to this gravity
    168 		except:
    169 			return [0.0, 0.0]  # This prevents OverflowErrors
    170 		
    171 		if distmag == 0.0:
    172 			return [0.0, 0.0]
    173 		
    174 		if distmag <= VORTEX_SWALLOWDIST:
    175 			particle.alive = False
    176 		
    177 		normal = [float(distvector[0]) / distmag, float(distvector[1]) / distmag]  # Normal from particle to this gravity
    178 		
    179 		velocitymagsquared = (particle.velocity[0] ** 2) + (particle.velocity[1] ** 2)  # Velocity magnitude squared
    180 		forcemag = (velocitymagsquared / distmag) + (self.strength * VORTEX_ACCELERATION)  # Force magnitude = (v^2 / r) + radial acceleration
    181 		
    182 		#velparmag = (particle.velocity[0] * normal[0]) + (particle.velocity[1] * normal[1])  # Magnitude of velocity parallel to normal
    183 		#velpar = [normal[0] * velparmag, normal[1] * velparmag]  # Vector of velocity parallel to normal
    184 		#velperp = [particle.velocity[0] - velpar[0], particle.velocity[1] - velpar[1]]  # Vector of velocity perpendicular to normal
    185 		#
    186 		#fnpar = [-velperp[1], velperp[0]]  # Force normal parallel to normal
    187 		#fnperp = [velpar[1], -velpar[0]]  # Force normal perpendicular to normal
    188 		#
    189 		#force = [(fnpar[0] + fnperp[0]) * forcemag, (fnpar[1] + fnperp[1]) * forcemag]
    190 		
    191 		force = [normal[0] * forcemag, normal[1] * forcemag]  # Works, but sometimes goes straight to the gravity w/ little spiraling
    192 		
    193 		return force
    194 	
    195 	def CreateKeyframe(self, frame, strength = None, strengthrandrange = None, pos = (None, None), interpolationtype = INTERPOLATIONTYPE_LINEAR):
    196 		return keyframes.CreateKeyframe(self.keyframes, frame, {'strength':strength, 'strengthrandrange':strengthrandrange, 'pos_x':pos[0], 'pos_y':pos[1], 'interpolationtype':interpolationtype})
    197 	
    198 	def ConsolidateKeyframes(self):
    199 		keyframes.ConsolidateKeyframes(self.keyframes, self.curframe, {'strength':self.initstrength, 'strengthrandrange':self.strengthrandrange, 'pos_x':self.pos[0], 'pos_y':self.pos[1]})