Mercurial > skaapsteker
annotate skaapsteker/sprites/player.py @ 167:f7fb2ee24c70
Twiddle player animation behaviour
author | Neil Muller <drnlmuller@gmail.com> |
---|---|
date | Wed, 06 Apr 2011 00:03:03 +0200 |
parents | d44a66ca3fd9 |
children | bf144d817113 |
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 |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
25 self._recent_collisions = [] |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
26 self._last_time = time.time() |
90 | 27 # State flags and such |
28 self.running = False | |
29 self.jumping = False | |
30 self.flying = False | |
31 self._load_images() | |
32 # We muck with these in load for convience, so ensure they're right | |
33 self.tails = 0 | |
34 self.set_facing('left') | |
35 self.set_image() | |
36 self.set_pos((0, 0)) | |
37 self._layer = Layers.PLAYER | |
38 | |
39 def set_image(self): | |
40 key = self._make_key() | |
120 | 41 images = self._image_dict[key] |
42 if self._animation_frame >= len(images): | |
43 self._animation_frame = 0.0 | |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
44 if self.rect: |
151
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
45 cur_pos = self.collide_rect.midbottom |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
46 else: |
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
47 cur_pos = (0, 0) |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
48 cand_image = images[int(self._animation_frame)] |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
49 cand_collide_rect = cand_image.get_bounding_rect(1) |
151
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
50 cand_collide_rect.midbottom = cur_pos |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
51 if cand_collide_rect.collidelist(self._recent_collisions) != -1 \ |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
52 and self.collide_rect.collidelist(self._recent_collisions) == -1: |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
53 # We introduce a new collision, so don't update the image |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
54 return |
120 | 55 self.image = images[int(self._animation_frame)] |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
56 self.collide_rect = self.image.get_bounding_rect(1) |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
57 self.rect = self.image.get_rect() |
151
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
58 self.rect_offset = self.rect.centerx - self.collide_rect.centerx, self.rect.bottom - self.collide_rect.bottom |
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
59 self.collide_rect.midbottom = cur_pos |
06be025c821c
Use midbottom, rather than bottomleft, when changing fox frames
Neil Muller <drnlmuller@gmail.com>
parents:
149
diff
changeset
|
60 self.rect.midbottom = cur_pos[0] + self.rect_offset[0], cur_pos[1] + self.rect_offset[1] |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
122
diff
changeset
|
61 self.init_pos() |
90 | 62 |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
115
diff
changeset
|
63 def update(self): |
120 | 64 v_x, v_y = self.velocity |
167
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
65 # 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
|
66 old_frame = self._animation_frame |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
67 self._animation_frame += abs(v_x) / 300 |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
68 time_diff = time.time() - self._last_time |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
69 if int(self._animation_frame) - int(old_frame) > 0: |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
70 # Check time diff |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
71 if time_diff < 0.07: |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
72 # Delay animation frame jump |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
73 self._animation_frame -= abs(v_x) / 300 |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
74 else: |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
75 self._last_time = time.time() |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
76 elif time_diff > 0.15: |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
77 # Force animation frame jump |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
78 self._animation_frame = old_frame + 1 |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
79 self._last_time = time.time() |
f7fb2ee24c70
Twiddle player animation behaviour
Neil Muller <drnlmuller@gmail.com>
parents:
160
diff
changeset
|
80 if abs(v_x) < 80: |
148
0474df61d5b1
Clamp very slow horizontal motion
Neil Muller <drnlmuller@gmail.com>
parents:
147
diff
changeset
|
81 # 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
|
82 self.velocity = (0, v_y) |
160 | 83 self.running = not self.on_solid # if you're not on something you can't stand |
120 | 84 else: |
85 self.running = True | |
86 self.set_image() | |
116
69a97094417a
Hook up per-tick sprite animations.
Simon Cross <hodgestar@gmail.com>
parents:
115
diff
changeset
|
87 |
90 | 88 def set_facing(self, new_facing): |
89 self.facing = new_facing | |
90 | |
149
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
91 def collided(self, other): |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
92 self._recent_collisions.append(other.collide_rect) |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
93 while len(self._recent_collisions) > 10: |
5b4d73d301a1
Don't change image if it will introduce new collisions
Neil Muller <drnlmuller@gmail.com>
parents:
148
diff
changeset
|
94 self._recent_collisions.pop(0) |
122
51bcc909873d
Saner, buggier collision rectangles
Neil Muller <drnlmuller@gmail.com>
parents:
120
diff
changeset
|
95 |
90 | 96 def set_pos(self, pos): |
97 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
|
98 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
|
99 self.collide_rect.midbottom = pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1] |
90 | 100 |
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
|
101 def action_left(self): |
115 | 102 if self.facing != 'left': |
103 self.facing = 'left' | |
104 self.set_image() | |
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
|
105 self.deltav((-100.0, 0.0)) |
90 | 106 |
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
|
107 def action_right(self): |
115 | 108 if self.facing != 'right': |
109 self.facing = 'right' | |
110 self.set_image() | |
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
|
111 self.deltav((100.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
|
112 |
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
|
113 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
|
114 if self.on_solid: |
144
6b488e1351a5
Buggy ground implementation. Make the world less bouncy
Neil Muller <drnlmuller@gmail.com>
parents:
122
diff
changeset
|
115 self.deltav((0.0, -350.0)) |
152
60138b935bc0
Make enemies block by default, so we can jump off them
Neil Muller <drnlmuller@gmail.com>
parents:
151
diff
changeset
|
116 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
|
117 |
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
|
118 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
|
119 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
|
120 |
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
|
121 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
|
122 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
|
123 |
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
|
124 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
|
125 print "F2" |
90 | 126 |
127 def _get_action(self): | |
128 if self.running: | |
129 return 'running' | |
130 if self.jumping: | |
131 return 'jumpin' | |
132 return 'standing' | |
133 | |
134 def _make_key(self, action=None): | |
135 if action is None: | |
136 action = self._get_action() | |
137 tails = self.tails | |
138 if self.tails >= 4: | |
139 tails = 4 | |
140 elif self.tails >= 2: | |
141 tails = 2 | |
142 return '%s %s %d' % (action, self.facing, tails) | |
143 | |
144 def _load_images(self): | |
158 | 145 for action in ['standing', 'running', 'jumping', 'attacking']: |
90 | 146 for tails in [0, 1, 2, 4]: |
147 self.tails = tails | |
148 directory = os.path.join('sprites', | |
149 'kitsune_%s' % action, | |
150 'kitsune_%s_%dtail' % (action, tails)) | |
151 for facing in ['left', 'right']: | |
152 self.facing = facing | |
153 key = self._make_key(action) | |
154 self._image_dict[key] = [] | |
155 for image_file in get_files(directory): | |
156 if image_file.startswith('.'): | |
157 # Skip extra junk for now | |
158 continue | |
159 image = load_image(os.path.join(directory, image_file)) | |
160 if facing == 'right': | |
161 image = pygame.transform.flip(image, True, False) | |
162 self._image_dict[key].append(image) |