Mercurial > skaapsteker
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: |