# HG changeset patch # User Neil Muller # Date 1302011173 -7200 # Node ID 6b488e1351a559e373749bb5713dfa4a0789a16a # Parent d10b841c452e4998381b537e7a97f183b8941072 Buggy ground implementation. Make the world less bouncy diff -r d10b841c452e -r 6b488e1351a5 skaapsteker/physics.py --- a/skaapsteker/physics.py Tue Apr 05 15:00:31 2011 +0200 +++ b/skaapsteker/physics.py Tue Apr 05 15:46:13 2011 +0200 @@ -17,7 +17,7 @@ # physics attributes mobile = True # whether the velocity may be non-zero gravitates = True # whether gravity applies to the sprite - terminal_velocity = (300.0, 300.0) # maximum horizontal and vertial speeds (pixels / s) + terminal_velocity = (450.0, 450.0) # maximum horizontal and vertial speeds (pixels / s) bounce_factor = (0.95, 0.95) # bounce factor mass = 1.0 # used for shared collisions and applying forces friction_coeff = (0.99, 0.99) # friction factor @@ -34,8 +34,11 @@ debug_color = (240, 0, 0) + is_ground = False # We special case collisions with ground objects + def __init__(self, *args, **kwargs): super(Sprite, self).__init__(*args, **kwargs) + self.on_ground = False 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 @@ -100,6 +103,11 @@ dv_x = - normal[0] * b_x * v_x dv_y = - normal[1] * b_y * v_y + if normal == (0, 1) and other.is_ground and v_y > 0 and self.collide_rect.top < other.collide_rect.top: + # Colliding with the ground from above is special + self.on_ground = True + dv_y = -v_y + if other.mobile: total_mass = self.mass + other.mass f_self = self.mass / total_mass @@ -186,7 +194,10 @@ # gravity dv = self.GRAVITY[0] * dt, self.GRAVITY[1] * dt for sprite in self._gravitators: - sprite.deltav(dv) + if sprite.on_ground: + sprite.deltav((dv[0], 0.0)) + else: + sprite.deltav(dv) # friction for sprite in self._mobiles: @@ -198,10 +209,32 @@ 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): + if sprite_collides(other.collide_rect) \ + and sprite.check_collides(other): collisions.append(other) if collisions: self._backout_collisions(sprite, collisions, dt) + if sprite.on_ground: + # Check if we are still in contact with the ground + contact_rect = sprite.collide_rect.move((0, 1)) + collides = contact_rect.colliderect + still_on_ground = False + for other in self._collision_groups[sprite.collision_layer]: + if other.is_ground and collides(other.collide_rect): + still_on_ground = True + break + sprite.on_ground = still_on_ground + else: + # Are we currently in contact with the groun + contact_rect = pygame.Rect( + (sprite.collide_rect.left, sprite.collide_rect.bottom -1), + (sprite.collide_rect.width, 1)) + collides = contact_rect.colliderect + for other in self._collision_groups[sprite.collision_layer]: + if other.is_ground and collides(other.collide_rect): + sprite.on_ground = True + break + # call update methods self._updaters.update() diff -r d10b841c452e -r 6b488e1351a5 skaapsteker/sprites/base.py --- a/skaapsteker/sprites/base.py Tue Apr 05 15:00:31 2011 +0200 +++ b/skaapsteker/sprites/base.py Tue Apr 05 15:46:13 2011 +0200 @@ -71,6 +71,8 @@ mobile = False gravitates = False collides_with = set([PC_LAYER, MONSTER_LAYER]) + is_ground = True + bounce_factor = (0.0, 0.0) def __init__(self, pos, image): Sprite.__init__(self) diff -r d10b841c452e -r 6b488e1351a5 skaapsteker/sprites/player.py --- a/skaapsteker/sprites/player.py Tue Apr 05 15:00:31 2011 +0200 +++ b/skaapsteker/sprites/player.py Tue Apr 05 15:46:13 2011 +0200 @@ -39,16 +39,16 @@ if self._animation_frame >= len(images): self._animation_frame = 0.0 if self.rect: - cur_pos = self.rect.topleft + cur_pos = self.collide_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] - + self.rect_offset = self.rect.left - self.collide_rect.left, self.rect.top - self.collide_rect.top + self.collide_rect.topleft = cur_pos + self.rect.topleft = cur_pos[0] + self.rect_offset[0], cur_pos[1] + self.rect_offset[1] + self.init_pos() def update(self): v_x, v_y = self.velocity @@ -65,8 +65,8 @@ def set_pos(self, pos): self.starting_tile_pos = pos - 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] + self.rect.topleft = pos[0] * TILE_SIZE[0] + self.rect_offset[0], pos[1] * TILE_SIZE[1] + self.rect_offset[1] + self.collide_rect.topleft = pos[0] * TILE_SIZE[0], pos[1] * TILE_SIZE[1] def action_left(self): if self.facing != 'left': @@ -81,7 +81,9 @@ self.deltav((100.0, 0.0)) def action_up(self): - self.deltav((0.0, -100.0)) + if self.on_ground: + self.deltav((0.0, -350.0)) + self.on_ground = False def action_down(self): self.deltav((0.0, 100.0))