Mercurial > skaapsteker
annotate skaapsteker/sprites/player.py @ 187:92ab784ecf5a
Repel fx from longstanding collisions
author | Neil Muller <drnlmuller@gmail.com> |
---|---|
date | Wed, 06 Apr 2011 20:50:00 +0200 |
parents | 88a78fb9fa82 |
children | 30a5f7cf670a |
rev | line source |
---|---|
90 | 1 """Class for dealing with the player""" |
2 | |
3 import pygame.transform | |
4 import os | |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
5 import time |
90 | 6 |
100
3eafceff6293
Have monsters also collide with players as an interim solution while I relax, eat dinner and think about the best way to use the new collision layers.
Simon Cross <hodgestar@gmail.com>
parents:
97
diff
changeset
|
7 from skaapsteker.sprites.base import TILE_SIZE, PC_LAYER, MONSTER_LAYER |
90 | 8 from skaapsteker.physics import Sprite |
9 from skaapsteker.constants import Layers | |
10 from skaapsteker.data import get_files, load_image | |
11 | |
12 | |
13 class Player(Sprite): | |
14 | |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
90
diff
changeset
|
15 collision_layer = PC_LAYER |
100
3eafceff6293
Have monsters also collide with players as an interim solution while I relax, eat dinner and think about the best way to use the new collision layers.
Simon Cross <hodgestar@gmail.com>
parents:
97
diff
changeset
|
16 collides_with = set([MONSTER_LAYER]) |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
115
diff
changeset
|
17 wants_updates = True |
97
a1d95c6152a0
Shiny new collision detection. Read code for usage information.
Simon Cross <hodgestar@gmail.com>
parents:
90
diff
changeset
|
18 |
90 | 19 def __init__(self): |
20 Sprite.__init__(self) | |
21 self.image = None | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
22 self.rect = None |
90 | 23 self._image_dict = {} |
120 | 24 self._animation_frame = 0.0 |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
25 self._last_time = time.time() |
90 | 26 # State flags and such |
27 self.running = False | |
28 self.jumping = False | |
29 self.flying = False | |
30 self._load_images() | |
31 # We muck with these in load for convience, so ensure they're right | |
32 self.tails = 0 | |
33 self.set_facing('left') | |
34 self.set_image() | |
35 self.set_pos((0, 0)) | |
187
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
36 self._collisions_seen = 0 |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
37 self._last_collide = [] |
90 | 38 self._layer = Layers.PLAYER |
39 | |
40 def set_image(self): | |
41 key = self._make_key() | |
120 | 42 images = self._image_dict[key] |
43 if self._animation_frame >= len(images): | |
44 self._animation_frame = 0.0 | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
45 if self.rect: |
151
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
46 cur_pos = self.collide_rect.midbottom |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
47 else: |
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
48 cur_pos = (0, 0) |
172
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
49 |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
50 # TODO: can save a lot of calculation here by caching collision rects |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
51 cand_image = images[int(self._animation_frame)] |
172
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
52 cand_collide_rect = cand_image.get_bounding_rect(1).inflate(-2,-2) |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
53 cand_rect = cand_image.get_rect() |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
54 cand_rect_offset = cand_rect.centerx - cand_collide_rect.centerx, cand_rect.bottom - cand_collide_rect.bottom |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
55 cand_rect.midbottom = cur_pos[0] + cand_rect_offset[0], cur_pos[1] + cand_rect_offset[1] |
151
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
56 cand_collide_rect.midbottom = cur_pos |
172
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
57 if not self.check_collide_rect(cand_collide_rect, cand_rect, cand_image): |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
58 return |
172
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
59 |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
60 self.image = cand_image |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
61 self.collide_rect = cand_collide_rect |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
62 self.rect = cand_rect |
bf144d817113
if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
Simon Cross <hodgestar@gmail.com>
parents:
167
diff
changeset
|
63 self.rect_offset = cand_rect_offset |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
122
diff
changeset
|
64 self.init_pos() |
90 | 65 |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
115
diff
changeset
|
66 def update(self): |
120 | 67 v_x, v_y = self.velocity |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
68 # Never animate slower than !7 fps, never faster than ~15 fps |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
69 old_frame = self._animation_frame |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
70 self._animation_frame += abs(v_x) / 300 |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
71 time_diff = time.time() - self._last_time |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
72 if int(self._animation_frame) - int(old_frame) > 0: |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
73 # Check time diff |
177
88a78fb9fa82
Tweak some constants to make player motion more comfortable.
Jeremy Thurgood <firxen@gmail.com>
parents:
176
diff
changeset
|
74 if time_diff < 0.10: |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
75 # Delay animation frame jump |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
76 self._animation_frame -= abs(v_x) / 300 |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
77 else: |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
78 self._last_time = time.time() |
177
88a78fb9fa82
Tweak some constants to make player motion more comfortable.
Jeremy Thurgood <firxen@gmail.com>
parents:
176
diff
changeset
|
79 elif time_diff > 0.20: |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
80 # Force animation frame jump |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
81 self._animation_frame = old_frame + 1 |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
82 self._last_time = time.time() |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
83 if abs(v_x) < 80: |
148
0474df61d5b1
Clamp very slow horizontal motion
Neil Muller <drnlmuller@gmail.com>
parents:
147
diff
changeset
|
84 # Clamp when we're not moving at least 5 pixel / s |
0474df61d5b1
Clamp very slow horizontal motion
Neil Muller <drnlmuller@gmail.com>
parents:
147
diff
changeset
|
85 self.velocity = (0, v_y) |
160 | 86 self.running = not self.on_solid # if you're not on something you can't stand |
120 | 87 else: |
176
57a78f19c673
Hack player.py to have platformer physics
Neil Muller <drnlmuller@gmail.com>
parents:
172
diff
changeset
|
88 self.velocity = (0, v_y) # Standard platformer physics |
120 | 89 self.running = True |
90 self.set_image() | |
187
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
91 if self._collisions_seen > 2 * len(self._last_collide): |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
92 print 'Trying to move' |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
93 # Can we find a position "nearby" that reduces the collision |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
94 # surface |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
95 best_move = (0, 0) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
96 clip_area = 0 |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
97 for rect in self._last_collide: |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
98 clip = rect.collide_rect.clip(self.collide_rect) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
99 clip_area += clip.width * clip.height |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
100 min_area = clip_area |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
101 for attempt in [(0, 2), (2, 0), (-2, 0), (2, 2), (-2, 2)]: |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
102 clip_area = 0 |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
103 for rect in self._last_collide: |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
104 cand_rect = self.collide_rect.move(attempt) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
105 clip = rect.collide_rect.clip(cand_rect) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
106 clip_area += clip.width * clip.height |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
107 if clip_area < min_area: |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
108 min_area = clip_area |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
109 best_move = attempt |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
110 print best_move, min_area, self.velocity |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
111 self.collide_rect.move_ip(best_move) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
112 self.rect.move_ip(best_move) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
113 self.init_pos() |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
114 self._last_collide = [] |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
115 self._collisions_seen = 0 |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
115
diff
changeset
|
116 |
90 | 117 def set_facing(self, new_facing): |
118 self.facing = new_facing | |
119 | |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
120 def collided(self, other): |
187
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
121 if other not in self._last_collide: |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
122 self._last_collide.append(other) |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
123 self._collide_pos = self.collide_rect.midbottom |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
124 self._collisions_seen = 0 |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
125 else: |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
126 self._collisions_seen += 1 |
92ab784ecf5a
Repel fx from longstanding collisions
Neil Muller <drnlmuller@gmail.com>
parents:
177
diff
changeset
|
127 |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
128 |
90 | 129 def set_pos(self, pos): |
130 self.starting_tile_pos = pos | |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
151
diff
changeset
|
131 self.rect.midbottom = pos[0] * TILE_SIZE[0] + self.rect_offset[0], pos[1] * TILE_SIZE[1] + self.rect_offset[1] |
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
151
diff
changeset
|
132 self.collide_rect.midbottom = pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1] |
90 | 133 |
102
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
134 def action_left(self): |
115 | 135 if self.facing != 'left': |
136 self.facing = 'left' | |
137 self.set_image() | |
177
88a78fb9fa82
Tweak some constants to make player motion more comfortable.
Jeremy Thurgood <firxen@gmail.com>
parents:
176
diff
changeset
|
138 self.deltav((-450.0, 0.0)) |
90 | 139 |
102
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
140 def action_right(self): |
115 | 141 if self.facing != 'right': |
142 self.facing = 'right' | |
143 self.set_image() | |
177
88a78fb9fa82
Tweak some constants to make player motion more comfortable.
Jeremy Thurgood <firxen@gmail.com>
parents:
176
diff
changeset
|
144 self.deltav((450.0, 0.0)) |
102
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
145 |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
146 def action_up(self): |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
151
diff
changeset
|
147 if self.on_solid: |
177
88a78fb9fa82
Tweak some constants to make player motion more comfortable.
Jeremy Thurgood <firxen@gmail.com>
parents:
176
diff
changeset
|
148 self.deltav((0.0, -self.terminal_velocity[1])) |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
151
diff
changeset
|
149 self.on_solid = False |
102
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
150 |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
151 def action_down(self): |
103
aaef228b6358
Run kitsune, run! And by the running of the kitsune gravity is restored to normal.
Simon Cross <hodgestar@gmail.com>
parents:
102
diff
changeset
|
152 self.deltav((0.0, 100.0)) |
102
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
153 |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
154 def action_fire1(self): |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
155 print "F1" |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
156 |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
157 def action_fire2(self): |
2e913a89e69d
Link up key presses to calls to action functions on player and to quitting level.
Simon Cross <hodgestar@gmail.com>
parents:
100
diff
changeset
|
158 print "F2" |
90 | 159 |
160 def _get_action(self): | |
161 if self.running: | |
162 return 'running' | |
163 if self.jumping: | |
164 return 'jumpin' | |
165 return 'standing' | |
166 | |
167 def _make_key(self, action=None): | |
168 if action is None: | |
169 action = self._get_action() | |
170 tails = self.tails | |
171 if self.tails >= 4: | |
172 tails = 4 | |
173 elif self.tails >= 2: | |
174 tails = 2 | |
175 return '%s %s %d' % (action, self.facing, tails) | |
176 | |
177 def _load_images(self): | |
158 | 178 for action in ['standing', 'running', 'jumping', 'attacking']: |
90 | 179 for tails in [0, 1, 2, 4]: |
180 self.tails = tails | |
181 directory = os.path.join('sprites', | |
182 'kitsune_%s' % action, | |
183 'kitsune_%s_%dtail' % (action, tails)) | |
184 for facing in ['left', 'right']: | |
185 self.facing = facing | |
186 key = self._make_key(action) | |
187 self._image_dict[key] = [] | |
188 for image_file in get_files(directory): | |
189 if image_file.startswith('.'): | |
190 # Skip extra junk for now | |
191 continue | |
192 image = load_image(os.path.join(directory, image_file)) | |
193 if facing == 'right': | |
194 image = pygame.transform.flip(image, True, False) | |
195 self._image_dict[key].append(image) |