comparison skaapsteker/physics.py @ 66:12ec95a2e8ea

Bouncing.
author Simon Cross <hodgestar@gmail.com>
date Sun, 03 Apr 2011 22:56:47 +0200
parents 1be1ca704346
children 60aa6c3eb96f
comparison
equal deleted inserted replaced
65:bcf3d0b2a6d8 66:12ec95a2e8ea
5 5
6 import pygame.sprite 6 import pygame.sprite
7 import pygame.draw 7 import pygame.draw
8 import pygame 8 import pygame
9 import time 9 import time
10 from constants import DEBUG, Layers 10 from constants import DEBUG, EPSILON
11 11
12 class Sprite(pygame.sprite.DirtySprite): 12 class Sprite(pygame.sprite.DirtySprite):
13 13
14 mobile = True # whether the velocity may be non-zero 14 mobile = True # whether the velocity may be non-zero
15 gravitates = True # whether gravity applies to the sprite 15 gravitates = True # whether gravity applies to the sprite
23 self.image = pygame.Surface((10, 10)) 23 self.image = pygame.Surface((10, 10))
24 self.image.fill((0, 0, 200)) 24 self.image.fill((0, 0, 200))
25 self.visible = 1 25 self.visible = 1
26 self.dirty = 1 26 self.dirty = 1
27 self.blendmode = 0 27 self.blendmode = 0
28 self._layer = Layers.BACKGROUND 28
29 def init_pos(self):
30 self._float_pos = self.rect.topleft
29 31
30 def draw_debug(self, surface): 32 def draw_debug(self, surface):
31 pygame.draw.rect(surface, (240, 0, 0), self.rect, 1) 33 pygame.draw.rect(surface, (240, 0, 0), self.rect, 1)
32 34
33 def deltav(self, dv): 35 def deltav(self, dv):
40 42
41 self.velocity = (v_x, v_y) 43 self.velocity = (v_x, v_y)
42 44
43 def deltap(self, dt): 45 def deltap(self, dt):
44 v_x, v_y = self.velocity 46 v_x, v_y = self.velocity
47 f_x, f_y = self._float_pos
45 d_x, d_y = v_x * dt, v_y * dt 48 d_x, d_y = v_x * dt, v_y * dt
46 self.rect.move_ip(d_x, d_y) 49 f_x, f_y = f_x + d_x, f_y + d_y
50 self._float_pos = f_x, f_y
51 self.rect.topleft = int(f_x), int(f_y)
52
53 def collide(self, other):
54 print "Collided:", self, other
55
56 def collide_immobile(self, immobile):
57 print "Collided with immobile:", self, immobile
58 v_x, v_y = self.velocity
59 clip = self.rect.clip(immobile.rect)
60 frac_x = clip.width / abs(v_x) if abs(v_x) > EPSILON else 0.0
61 frac_y = clip.height / abs(v_y) if abs(v_y) > EPSILON else 0.0
62 frac = max(frac_x, frac_y)
63 self.velocity = (-v_x, -v_y)
64 self.deltap(frac)
47 65
48 66
49 class World(object): 67 class World(object):
50 68
51 GRAVITY = 9.8 # m/s^2 69 GRAVITY = 9.8 # m/s^2
52 70
53 def __init__(self): 71 def __init__(self):
54 self._all = pygame.sprite.LayeredUpdates() 72 self._all = pygame.sprite.LayeredUpdates()
55 self._mobiles = pygame.sprite.Group() 73 self._mobiles = pygame.sprite.Group()
74 self._immobiles = pygame.sprite.Group()
56 self._gravitators = pygame.sprite.Group() 75 self._gravitators = pygame.sprite.Group()
57 self._last_time = None 76 self._last_time = None
58 77
59 def add(self, sprite): 78 def add(self, sprite):
79 sprite.init_pos()
60 self._all.add(sprite) 80 self._all.add(sprite)
61 if sprite.mobile: 81 if sprite.mobile:
62 self._mobiles.add(sprite) 82 self._mobiles.add(sprite)
83 else:
84 self._immobiles.add(sprite)
63 if sprite.gravitates: 85 if sprite.gravitates:
64 self._gravitators.add(sprite) 86 self._gravitators.add(sprite)
65 87
66 def update(self): 88 def update(self):
67 if self._last_time is None: 89 if self._last_time is None:
80 # position update (do last) 102 # position update (do last)
81 for sprite in self._mobiles: 103 for sprite in self._mobiles:
82 sprite.deltap(dt) 104 sprite.deltap(dt)
83 105
84 # check for collisions 106 # check for collisions
85 for sprite1, sprites in pygame.sprite.groupcollide(self._mobiles, self._all, False, False).iteritems(): 107 collisions = []
86 for sprite2 in sprites: 108 collide = collisions.append
87 if sprite1 is sprite2: 109 for sprite1 in self._mobiles.sprites():
88 continue 110 spritecollide = sprite1.rect.colliderect
111 for sprite2 in self._mobiles.sprites():
112 if id(sprite1) < id(sprite2) and spritecollide(sprite2):
113 collide((sprite1, sprite2))
114 for sprite2 in self._immobiles.sprites():
115 if spritecollide(sprite2):
116 collide((sprite1, sprite2))
117 self.dispatch_collisions(collisions)
118
119 def dispatch_collisions(self, collisions):
120 for s1, s2 in collisions:
121 if not s2.mobile:
122 s1.collide_immobile(s2)
123 else:
124 s1.collide(s2)
89 125
90 def draw(self, surface): 126 def draw(self, surface):
91 self._all.draw(surface) 127 self._all.draw(surface)
92 if DEBUG: 128 if DEBUG:
93 for sprite in self._all: 129 for sprite in self._all: