Mercurial > skaapsteker
changeset 122:51bcc909873d
Saner, buggier collision rectangles
author | Neil Muller <drnlmuller@gmail.com> |
---|---|
date | Mon, 04 Apr 2011 22:39:42 +0200 |
parents | 5f5e43391395 |
children | 592477d8b09b |
files | skaapsteker/physics.py skaapsteker/sprites/base.py skaapsteker/sprites/player.py |
diffstat | 3 files changed, 29 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/skaapsteker/physics.py Mon Apr 04 22:37:59 2011 +0200 +++ b/skaapsteker/physics.py Mon Apr 04 22:39:42 2011 +0200 @@ -37,6 +37,7 @@ super(Sprite, self).__init__(*args, **kwargs) self.velocity = (0.0, 0.0) self.rect = pygame.Rect(0, 0, 10, 10) # sub-classes should override + self.collide_rect = pygame.Rect(0, 0, 10, 10) # rectangle we use for collisions self.image = pygame.Surface((10, 10)) self.image.fill((0, 0, 200)) self.visible = 1 @@ -50,7 +51,8 @@ return self.debug_color def draw_debug(self, surface): - pygame.draw.rect(surface, self.get_debug_color(), self.rect, 1) + pygame.draw.rect(surface, (240, 0, 0), self.collide_rect, 1) + pygame.draw.rect(surface, self.get_debug_color(), self.collide_rect, 1) def deltaf(self, df): dv = df[0] / self.mass, df[1] / self.mass @@ -67,12 +69,15 @@ self.velocity = (v_x, v_y) def deltap(self, dt): + old_pos = self.rect.topleft v_x, v_y = self.velocity f_x, f_y = self._float_pos d_x, d_y = v_x * dt, v_y * dt f_x, f_y = f_x + d_x, f_y + d_y self._float_pos = f_x, f_y self.rect.topleft = int(f_x), int(f_y) + delta_pos = self.rect.left - old_pos[0], self.rect.top - old_pos[1] + self.collide_rect.move_ip(delta_pos) def check_collides(self, other): return True # default to relying purefly on collision_layer and collides_with @@ -145,12 +150,12 @@ self._collision_groups[layer] = pygame.sprite.Group() def _backout_collisions(self, sprite, others, dt): - frac, normal, idx = 0.0, None, None + frac, normal, idx = -1.0, None, None v_x, v_y = sprite.velocity abs_v_x, abs_v_y = abs(v_x), abs(v_y) for i, other in enumerate(others): - clip = sprite.rect.clip(other.rect) + clip = sprite.collide_rect.clip(other.collide_rect) # TODO: avoid continual "if abs_v_? > EPSILON" frac_x = clip.width / abs_v_x if abs_v_x > EPSILON else dt frac_y = clip.height / abs_v_y if abs_v_y > EPSILON else dt @@ -183,7 +188,7 @@ # position update and collision check (do last) for sprite in self._mobiles: sprite.deltap(dt) - sprite_collides = sprite.rect.colliderect + sprite_collides = sprite.collide_rect.colliderect collisions = [] for other in self._collision_groups[sprite.collision_layer]: if sprite_collides(other) and sprite.check_collides(other):
--- a/skaapsteker/sprites/base.py Mon Apr 04 22:37:59 2011 +0200 +++ b/skaapsteker/sprites/base.py Mon Apr 04 22:39:42 2011 +0200 @@ -27,6 +27,7 @@ self.image = data.load_image('sprites/' + self.image_file) self.starting_tile_pos = pos self.rect = self.image.get_rect(topleft=(pos[0]*TILE_SIZE[0], pos[1]*TILE_SIZE[1])) + self.collide_rect = self.image.get_rect(topleft=(pos[0]*TILE_SIZE[0], pos[1]*TILE_SIZE[1])) self._layer = Layers.PLAYER self.setup(**opts) @@ -57,7 +58,11 @@ Sprite.__init__(self) self.tile_pos = pos self.image = image - self.rect = Rect((pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1]), TILE_SIZE) + self.collide_rect = self.image.get_bounding_rect(1) + self.rect = self.image.get_rect() + self.rect_offset = self.collide_rect.left - self.rect.left, self.rect.top - self.rect.top + self.collide_rect.topleft = pos[0] * TILE_SIZE[0] + self.rect_offset[0], pos[1] * TILE_SIZE[1] + self.rect_offset[1] + self.rect.topleft = pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1] def get_debug_color(self): if self.floor or self.block:
--- a/skaapsteker/sprites/player.py Mon Apr 04 22:37:59 2011 +0200 +++ b/skaapsteker/sprites/player.py Mon Apr 04 22:39:42 2011 +0200 @@ -18,6 +18,7 @@ def __init__(self): Sprite.__init__(self) self.image = None + self.rect = None self._image_dict = {} self._animation_frame = 0.0 # State flags and such @@ -37,7 +38,17 @@ images = self._image_dict[key] if self._animation_frame >= len(images): self._animation_frame = 0.0 + if self.rect: + cur_pos = self.rect.topleft + else: + cur_pos = (0, 0) self.image = images[int(self._animation_frame)] + self.rect = self.image.get_rect() + self.collide_rect = self.image.get_bounding_rect(1) + self.rect_offset = self.collide_rect.left - self.rect.left, self.collide_rect.top - self.rect.top + self.rect.topleft = cur_pos + self.collide_rect.topleft = cur_pos[0] + self.rect_offset[0], cur_pos[1] + self.rect_offset[1] + def update(self): v_x, v_y = self.velocity @@ -51,10 +62,11 @@ def set_facing(self, new_facing): self.facing = new_facing + def set_pos(self, pos): self.starting_tile_pos = pos - self.rect = self.image.get_rect(topleft=(pos[0]*TILE_SIZE[0], pos[1]*TILE_SIZE[1])) - self.rect.inflate_ip(-10, -10) + self.collide_rect.topleft = pos[0] * TILE_SIZE[0] + self.rect_offset[0], pos[1] * TILE_SIZE[1] + self.rect_offset[1] + self.rect.topleft = pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1] def action_left(self): if self.facing != 'left':