Mercurial > skaapsteker
annotate skaapsteker/physics.py @ 155:b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
author | Simon Cross <hodgestar@gmail.com> |
---|---|
date | Tue, 05 Apr 2011 22:51:14 +0200 |
parents | 60138b935bc0 |
children | 0b0dbfb50e5f |
rev | line source |
---|---|
22
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
1 """Model of gravity, acceleration, velocities and collisions. |
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
2 |
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
3 Works very closely with sprites/base.py. |
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
4 """ |
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
5 |
105
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
6 import time |
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
7 |
39 | 8 import pygame |
105
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
9 import pygame.draw |
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
10 import pygame.sprite |
155
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
11 from pygame.mask import from_surface |
105
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
12 |
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
13 from . import options |
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
14 from .constants import EPSILON |
22
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
15 |
128
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
16 class Sprite(pygame.sprite.Sprite): |
22
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
17 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
18 # physics attributes |
22
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
19 mobile = True # whether the velocity may be non-zero |
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
20 gravitates = True # whether gravity applies to the sprite |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
21 terminal_velocity = (450.0, 450.0) # maximum horizontal and vertial speeds (pixels / s) |
112 | 22 bounce_factor = (0.95, 0.95) # bounce factor |
121 | 23 mass = 1.0 # used for shared collisions and applying forces |
128
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
24 friction_coeff = (0.99, 0.99) # friction factor |
39 | 25 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
26 # collision attributes |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
27 # Sprite X collides with Y iff (X.collision_layer in Y.collides_with) and X.check_collides(Y) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
28 # Collisions result in the colliding movement being partially backed out, a call to X.bounce(frac) and a call to X.collided(Y) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
29 # X.bounce(frac) is only called for the first (as determined by backing out distance) collision in a multi-collision event |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
30 collision_layer = None # never collides with anything |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
31 collides_with = set() # nothing collides with this |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
32 |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
33 # set to True to have .update() called once per tick |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
34 wants_updates = False |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
35 |
117
b361d9e17c26
Angry fruit salad debug boxes.
Jeremy Thurgood <firxen@gmail.com>
parents:
116
diff
changeset
|
36 debug_color = (240, 0, 0) |
b361d9e17c26
Angry fruit salad debug boxes.
Jeremy Thurgood <firxen@gmail.com>
parents:
116
diff
changeset
|
37 |
146 | 38 floor = False # We special case collisions with ground objects |
155
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
39 block = False |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
40 |
39 | 41 def __init__(self, *args, **kwargs): |
42 super(Sprite, self).__init__(*args, **kwargs) | |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
43 self.on_solid = False |
39 | 44 self.velocity = (0.0, 0.0) |
45 self.rect = pygame.Rect(0, 0, 10, 10) # sub-classes should override | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
46 self.collide_rect = pygame.Rect(0, 0, 10, 10) # rectangle we use for collisions |
43 | 47 self.image = pygame.Surface((10, 10)) |
48 self.image.fill((0, 0, 200)) | |
155
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
49 self._mask_cache = {} # image id -> collision bit mask |
66 | 50 |
51 def init_pos(self): | |
52 self._float_pos = self.rect.topleft | |
39 | 53 |
117
b361d9e17c26
Angry fruit salad debug boxes.
Jeremy Thurgood <firxen@gmail.com>
parents:
116
diff
changeset
|
54 def get_debug_color(self): |
b361d9e17c26
Angry fruit salad debug boxes.
Jeremy Thurgood <firxen@gmail.com>
parents:
116
diff
changeset
|
55 return self.debug_color |
b361d9e17c26
Angry fruit salad debug boxes.
Jeremy Thurgood <firxen@gmail.com>
parents:
116
diff
changeset
|
56 |
53 | 57 def draw_debug(self, surface): |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
58 pygame.draw.rect(surface, (240, 0, 0), self.collide_rect, 1) |
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
59 pygame.draw.rect(surface, self.get_debug_color(), self.collide_rect, 1) |
53 | 60 |
121 | 61 def deltaf(self, df): |
62 dv = df[0] / self.mass, df[1] / self.mass | |
63 self.deltav(dv) | |
64 | |
39 | 65 def deltav(self, dv): |
66 v_x, v_y = self.velocity | |
67 v_x, v_y = v_x + dv[0], v_y + dv[1] | |
68 | |
69 t_v = self.terminal_velocity | |
70 v_x = max(min(v_x, t_v[0]), -t_v[0]) | |
71 v_y = max(min(v_y, t_v[1]), -t_v[1]) | |
72 | |
73 self.velocity = (v_x, v_y) | |
74 | |
75 def deltap(self, dt): | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
76 old_pos = self.rect.topleft |
39 | 77 v_x, v_y = self.velocity |
66 | 78 f_x, f_y = self._float_pos |
39 | 79 d_x, d_y = v_x * dt, v_y * dt |
66 | 80 f_x, f_y = f_x + d_x, f_y + d_y |
81 self._float_pos = f_x, f_y | |
82 self.rect.topleft = int(f_x), int(f_y) | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
83 delta_pos = self.rect.left - old_pos[0], self.rect.top - old_pos[1] |
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
84 self.collide_rect.move_ip(delta_pos) |
66 | 85 |
155
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
86 def _check_mask(self): |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
87 image_id = id(self.image) |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
88 mask = self._mask_cache.get(image_id, None) |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
89 if mask is None: |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
90 mask = self._mask_cache[image_id] = from_surface(self.image) |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
91 self.mask = mask |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
92 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
93 def check_collides(self, other): |
155
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
94 # check bitmasks for collision |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
95 self._check_mask() |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
96 other._check_mask() |
b2e0f1246c38
Hook up bitmasked based collisions (mask caching may be unnecessary, please comment on whether this effects performance for you).
Simon Cross <hodgestar@gmail.com>
parents:
152
diff
changeset
|
97 return pygame.sprite.collide_mask(self, other) |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
98 |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
99 def collided(self, other): |
98 | 100 pass |
66 | 101 |
128
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
102 def apply_friction(self): |
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
103 v_x, v_y = self.velocity |
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
104 self.velocity = self.friction_coeff[0] * v_x, self.friction_coeff[1] * v_y |
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
105 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
106 def bounce(self, other, normal): |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
107 """Alter velocity after a collision. |
78
f29b7ada68c1
Fix bouncing and tweak universal constants to show it off.
Simon Cross <hodgestar@gmail.com>
parents:
68
diff
changeset
|
108 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
109 other: sprite collided with |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
110 normal: unit vector (tuple) normal to the collision |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
111 surface. |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
112 """ |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
113 v_x, v_y = self.velocity |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
114 b_x = 1.0 + self.bounce_factor[0] * other.bounce_factor[0] |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
115 b_y = 1.0 + self.bounce_factor[1] * other.bounce_factor[1] |
121 | 116 dv_x = - normal[0] * b_x * v_x |
117 dv_y = - normal[1] * b_y * v_y | |
118 | |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
119 if normal == (0, 1) and (other.floor or other.block) and v_y > 0 and self.collide_rect.top < other.collide_rect.top: |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
120 # Colliding with the ground from above is special |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
121 self.on_solid = True |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
122 dv_y = -v_y |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
123 |
121 | 124 if other.mobile: |
125 total_mass = self.mass + other.mass | |
126 f_self = self.mass / total_mass | |
127 f_other = other.mass / total_mass | |
128 | |
129 self.deltav((dv_x * f_self, dv_y * f_self)) | |
130 other.deltav((- dv_x * f_other, - dv_y * f_other)) | |
131 else: | |
132 self.deltav((dv_x, dv_y)) # oof | |
39 | 133 |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
134 def update(self): |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
135 pass # only called in wants_update = True |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
136 |
22
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
137 |
b815471d4b95
Move sprite base class into physics since they're tightly coupled.
Simon Cross <hodgestar@gmail.com>
parents:
18
diff
changeset
|
138 class World(object): |
23
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
139 |
103
aaef228b6358
Run kitsune, run! And by the running of the kitsune gravity is restored to normal.
Simon Cross <hodgestar@gmail.com>
parents:
98
diff
changeset
|
140 GRAVITY = 0.0, 9.8 * 20.0 # pixels / s^2 |
39 | 141 |
23
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
142 def __init__(self): |
57
e545236dd8f4
Change back to plain layered updater since everything is dirty all the time. Remove collision print since collisions appear to work.
Simon Cross <hodgestar@gmail.com>
parents:
53
diff
changeset
|
143 self._all = pygame.sprite.LayeredUpdates() |
23
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
144 self._mobiles = pygame.sprite.Group() |
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
145 self._gravitators = pygame.sprite.Group() |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
146 self._updaters = pygame.sprite.Group() |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
147 self._collision_groups = { None: pygame.sprite.Group() } |
39 | 148 self._last_time = None |
23
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
149 |
104
12ce1d131a72
Hack in resume game option
Neil Muller <drnlmuller@gmail.com>
parents:
103
diff
changeset
|
150 def freeze(self): |
12ce1d131a72
Hack in resume game option
Neil Muller <drnlmuller@gmail.com>
parents:
103
diff
changeset
|
151 self._last_time = None |
12ce1d131a72
Hack in resume game option
Neil Muller <drnlmuller@gmail.com>
parents:
103
diff
changeset
|
152 |
12ce1d131a72
Hack in resume game option
Neil Muller <drnlmuller@gmail.com>
parents:
103
diff
changeset
|
153 def thaw(self): |
12ce1d131a72
Hack in resume game option
Neil Muller <drnlmuller@gmail.com>
parents:
103
diff
changeset
|
154 self._last_time = time.time() |
12ce1d131a72
Hack in resume game option
Neil Muller <drnlmuller@gmail.com>
parents:
103
diff
changeset
|
155 |
23
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
156 def add(self, sprite): |
66 | 157 sprite.init_pos() |
23
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
158 self._all.add(sprite) |
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
159 if sprite.mobile: |
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
160 self._mobiles.add(sprite) |
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
161 if sprite.gravitates: |
5c9f2eeeb629
Very start of world / physics engine.
Simon Cross <hodgestar@gmail.com>
parents:
22
diff
changeset
|
162 self._gravitators.add(sprite) |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
163 if sprite.wants_updates: |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
164 self._updaters.add(sprite) |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
165 self._add_collision_group(sprite.collision_layer) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
166 for layer in sprite.collides_with: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
167 self._add_collision_group(layer) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
168 self._collision_groups[layer].add(sprite) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
169 |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
170 def _add_collision_group(self, layer): |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
171 if layer in self._collision_groups: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
172 return |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
173 self._collision_groups[layer] = pygame.sprite.Group() |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
174 |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
175 def _backout_collisions(self, sprite, others, dt): |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
176 frac, normal, idx = -1.0, None, None |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
177 v_x, v_y = sprite.velocity |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
178 abs_v_x, abs_v_y = abs(v_x), abs(v_y) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
179 |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
180 for i, other in enumerate(others): |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
181 clip = sprite.collide_rect.clip(other.collide_rect) |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
182 # TODO: avoid continual "if abs_v_? > EPSILON" |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
183 frac_x = clip.width / abs_v_x if abs_v_x > EPSILON else dt |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
184 frac_y = clip.height / abs_v_y if abs_v_y > EPSILON else dt |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
185 if frac_x > frac_y: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
186 if frac_y > frac: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
187 frac, normal, idx = frac_y, (0, 1), i |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
188 else: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
189 if frac_x > frac: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
190 frac, normal, idx = frac_x, (1, 0), i |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
191 |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
192 sprite.deltap(max(-1.1 * frac, -dt)) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
193 sprite.bounce(others[idx], normal) |
128
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
194 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
195 for other in others: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
196 sprite.collided(other) |
39 | 197 |
198 def update(self): | |
199 if self._last_time is None: | |
200 self._last_time = time.time() | |
201 return | |
202 | |
203 # find dt | |
204 now = time.time() | |
205 self._last_time, dt = now, now - self._last_time | |
206 | |
207 # gravity | |
103
aaef228b6358
Run kitsune, run! And by the running of the kitsune gravity is restored to normal.
Simon Cross <hodgestar@gmail.com>
parents:
98
diff
changeset
|
208 dv = self.GRAVITY[0] * dt, self.GRAVITY[1] * dt |
39 | 209 for sprite in self._gravitators: |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
210 if sprite.on_solid: |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
211 sprite.deltav((dv[0], 0.0)) |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
212 else: |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
213 sprite.deltav(dv) |
39 | 214 |
128
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
215 # friction |
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
216 for sprite in self._mobiles: |
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
217 sprite.apply_friction() |
36267deaccd8
Add friction. Remove old dirty sprite attributes.
Simon Cross <hodgestar@gmail.com>
parents:
122
diff
changeset
|
218 |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
219 # position update and collision check (do last) |
39 | 220 for sprite in self._mobiles: |
221 sprite.deltap(dt) | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
121
diff
changeset
|
222 sprite_collides = sprite.collide_rect.colliderect |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
223 collisions = [] |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
224 for other in self._collision_groups[sprite.collision_layer]: |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
225 if sprite_collides(other.collide_rect) \ |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
226 and sprite.check_collides(other): |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
227 collisions.append(other) |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
228 if collisions: |
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
85
diff
changeset
|
229 self._backout_collisions(sprite, collisions, dt) |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
230 contact_rect = pygame.Rect( |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
231 (sprite.collide_rect.left, sprite.collide_rect.bottom), |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
232 (sprite.collide_rect.width, 1)) |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
233 collides = contact_rect.colliderect |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
234 if sprite.on_solid: |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
235 # Check if we are still in contact with the ground |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
236 still_on_solid = False |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
237 for other in self._collision_groups[sprite.collision_layer]: |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
238 if (other.floor or other.block) and collides(other.collide_rect): |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
239 still_on_solid = True |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
240 break |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
241 sprite.on_solid = still_on_solid |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
242 else: |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
243 # Are we currently in contact with the groun |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
244 for other in self._collision_groups[sprite.collision_layer]: |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
245 if (other.floor or other.block) and collides(other.collide_rect): |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
146
diff
changeset
|
246 sprite.on_solid = True |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
247 break |
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
128
diff
changeset
|
248 |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
249 # call update methods |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
250 self._updaters.update() |
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
112
diff
changeset
|
251 |
39 | 252 def draw(self, surface): |
253 self._all.draw(surface) | |
105
c455b7925212
Global options in skaapsteker.__init__
Stefano Rivera <stefano@rivera.za.net>
parents:
104
diff
changeset
|
254 if options['debug_rects']: |
53 | 255 for sprite in self._all: |
256 sprite.draw_debug(surface) |