def handle_collision(self, collision_list, group):
"""Given a list of sprites that collide with the sprite, alter state such as position, velocity, etc"""
# If there's only 1 block, then we're over an edge, so do nothing in that case
# and just let the sprite fall, otherwise, clamp to the top of the block
if collision_list:
if len(collision_list) > 1:
self.falling = False
self.falling_frames = 1
self.dy = 0
self.rect.bottom = collision_list[0].rect.top
elif len(collision_list) == 1:
if self.facing_left and self.rect.right > collision_list[0].rect.left:
self.falling = False
self.falling_frames = 1
self.dy = 0
self.rect.bottom = collision_list[0].rect.top
elif not self.facing_left and self.rect.left < collision_list[0].rect.right:
self.falling = False
self.falling_frames = 1
self.dy = 0
self.rect.bottom = collision_list[0].rect.top
python类sprite()的实例源码
def apply_physics(self, tile_map):
"""Gravity in this case"""
# The dy should be controlled by 'gravity' only for now - jumps will impart an
# Initial up velocity (done in the keyhandler), then gravity acts here on update.
# Without some sort of gravity approximation, sprites would move at the same speed
# while in the air and seem very light, like they're walking on the moon in low gravity
# only worse. Not a problem for a top-down 2D game :)
# If not on the ground floor, just assume we're falling (for now this will be true)
if self.rect.bottom < tile_map.player_bounds_rect.bottom and self.falling == False:
self.falling = True
self.falling_frames = 1
if self.falling:
# As long as the sprite is continually falling, the 'speed' increases each
# frame by the acceleration until some terminal speed
if self.dy < self.settings.terminal_velocity:
self.dy += self.settings.gravity
self.rect.centery += self.dy
self.falling_frames += 1
def basic_bounds_containment(self, tile_map):
"""Contains the sprite to the player bounds"""
# Bounds check on bottom edge
if self.rect.bottom > tile_map.player_bounds_rect.bottom:
self.rect.bottom = tile_map.player_bounds_rect.bottom
self.dy = 0.0
self.falling = False
# Left/Right bounds containment check
# RIGHT
if self.dx > 0:
self.rect.centerx += self.dx
if self.rect.right - self.margin_right > tile_map.player_bounds_rect.right:
self.rect.right = tile_map.player_bounds_rect.right + self.margin_right
self.dx = 0.0
if self.dx < 0:
self.rect.centerx += self.dx
if self.rect.left + self.margin_left < tile_map.player_bounds_rect.left:
self.rect.left = tile_map.player_bounds_rect.left - self.margin_left
self.dx = 0.0
def above_all(self, sprite):
if not sprite or sprite.zindex + 1 == len(self._spritelist):
return
spritelist = self._spritelist
del spritelist[sprite.zindex]
i = sprite.zindex
size = len(spritelist)
while i < size:
s = spritelist[i]
s.zindex = i
i += 1
sprite.zindex = i
spritelist.append(sprite)
# above_all()
def __init__(self):
## pygame.sprite.Sprite.__init__(self)
FRG.DirtySprite.__init__(self)
self.image = Thingy.images[0]
self.rect = self.image.get_rect()
self.rect.x = randint(0, screen_dims[0])
self.rect.y = randint(0, screen_dims[1])
#self.vel = [randint(-10, 10), randint(-10, 10)]
self.vel = [randint(-1, 1), randint(-1, 1)]
self.dirty = 2
def update(self, tile_map):
"""Updates the blob sprite's position"""
if not self.dying:
last_dx = self.dx
super().update(tile_map, tile_map.block_group)
# Blobs only stop when they hit a wall so reverse course
if last_dx != 0 and self.dx == 0:
self.facing_left = not self.facing_left
if self.facing_left:
self.dx = 1.0
else:
self.dx = -1.0
# Check if the blob is over the "exit" for the enemies, and if so, drop it down
if tile_map.drainrect.colliderect(self.rect):
self.dying = True
self.falling = True
self.falling_frames = 1
else:
if self.dy < self.settings.terminal_velocity:
self.dy += self.settings.gravity
self.rect.centery += self.dy
self.falling_frames += 1
if self.rect.top > self.screen_rect.bottom:
self.kill()
self.finish_update()
def position_digits(self):
"""Move each digit sprite based on the frame position"""
y_offset = self.rect.top + self.settings.lcd_frame_padding_vert
x_offset = self.rect.left + self.settings.lcd_frame_padding_horz
self.position_digit_pair(self.digit_M1, self.digit_M2, x_offset, y_offset)
x_offset = self.digit_M2.rect.right + self.settings.lcd_frame_digit_padding_horz_major
self.position_digit_pair(self.digit_S1, self.digit_S2, x_offset, y_offset)
x_offset = self.digit_S2.rect.right + self.settings.lcd_frame_digit_padding_horz_major
self.position_digit_pair(self.digit_h1, self.digit_h2, x_offset, y_offset)
def draw(self):
"""Draws the animated sprite's current frame at its current position on the screen"""
frame_index = self.animations[self.current_animation].get_current_frame()
self.screen.blit(self.images[frame_index], self.rect)
def __init__(self, imagepath):
pygame.sprite.DirtySprite.__init__(self)
self.image = pygame.image.load(imagepath).convert()
self.rect = self.image.get_rect()
def __init__(self, sprite):
self.sprite = sprite
self.rect = Rect(sprite.rect)
self.alpha = sprite.alpha
self.visible = sprite.visible
self.image = sprite.image
# __init__()
def changed(self):
sprite = self.sprite
return self.rect != sprite.rect or \
self.alpha != sprite.alpha or \
self.visible != sprite.visible or \
self.image != sprite.image
# changed()
def add_internal(self, sprite):
Group.add_internal(self, sprite)
sprite.zindex = len(self._spritelist)
self._spritelist.append(sprite)
if sprite.visible:
self.dirty = True
# add_internal()
def remove_internal(self, sprite):
if sprite.last_state:
self.lostsprites.append(sprite.last_state.rect)
del self._spritelist[sprite.zindex]
sprite.zindex = None
if sprite.visible:
self.dirty = True
Group.remove_internal(self, sprite)
# remove_internal()
def __init__(self):
## pygame.sprite.Sprite.__init__(self)
FRG.DirtySprite.__init__(self)
self.image = Thingy.images[0]
self.rect = self.image.get_rect()
self.rect.x = randint(0, screen_dims[0])
self.rect.y = randint(0, screen_dims[1])
#self.vel = [randint(-10, 10), randint(-10, 10)]
self.vel = [randint(-1, 1), randint(-1, 1)]
self.dirty = 2
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
self.x = 230
self.y = 700
self.screen = screen
self.image_path = './plane/hero.gif'
self.image = pygame.image.load(self.image_path).convert()
self.bullet_list = []
self.is_hit = False
self.rect = self.image.get_rect()
def __init__(self, x, y, screen):
pygame.sprite.Sprite.__init__(self)
self.x = x+40
self.y = y-20
self.screen = screen
self.image_path = './plane/bullet-1.gif'
self.image = pygame.image.load(self.image_path)
def check_bullet_alien_collisions(self):
collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)
if len(self.aliens) == 0:
print("fleet empty")
self.create_fleet()
def update_aliens(self):
for alien in self.aliens.sprites():
if alien.check_edge_hit():
self.change_alien_fleet_direction()
break
self.aliens.update()
if pygame.sprite.spritecollideany(self.ship, self.aliens):
print("ship hit")
self.ship_hit()
def random_pos(self, snake_head, snake_parts, foods):
while True:
if self.style != 'big':
self.rect.left = randint(0, self.settings.x - 1) * self.settings.len
self.rect.top = randint(0, self.settings.y - 1) * self.settings.len + self.settings.scoreboard_height
else:
self.rect.left = randint(0, self.settings.x - 4) * self.settings.len
self.rect.top = randint(0, self.settings.y - 4) * self.settings.len + self.settings.scoreboard_height
# ????????????????
if not pygame.sprite.spritecollideany(self, snake_parts)\
and not self.rect.colliderect(snake_head)\
and not pygame.sprite.spritecollideany(self, foods):
break
def update(self):
"""Update all owned objects (blocks, player, enemies, etc)"""
if self.player.at_top:
self.level_timer.stop()
# Check for a reset flag set on the player object
if self.player.won_level:
self.player.reset()
self.enemies.empty()
gf.generate_new_random_blob(self.settings, self.screen, self.settings.image_res.enemy_blob_images, self)
self.generate_platforms()
self.blob_exit.stop_gibbing()
self.level_info.increase_level()
self.settings.enemy_generation_rate -= self.settings.enemy_generation_level_rate
self.level_timer.reset()
# Update the player
self.player.update(self, self.enemies)
# Check if it's time to add a new enemy to the map
self.new_enemy_counter += 1
if self.new_enemy_counter >= self.settings.enemy_generation_rate:
self.new_enemy_counter = 0
gf.generate_new_random_blob(self.settings, self.screen, self.settings.image_res.enemy_blob_images, self)
# Update enemies that exist
for enemy in self.enemies:
enemy.update(self)
# Update the 'exit' sprite
self.blob_exit.update(self.enemies)
# Update the level info
self.level_info.update()
# Update the level timer
self.level_timer.update()
# bonuses
for bonus in self.bonuses:
bonus.update()
if not bonus.alive():
self.bonuses.remove(bonus)
def clear(self, surface, bg):
# make heavily used symbols local, avoid python performance hit
split_rects_add = _split_rects_add
spritelist = self._spritelist
spritelist_len = len(spritelist)
changed = self.lostsprites
changed_append = changed.append
for sprite in spritelist:
if not sprite.last_state_changed():
continue
state = sprite.last_state
changed_append(state.rect)
i = sprite.zindex
while i < spritelist_len:
s2 = spritelist[i]
i += 1
if s2.dirty or not s2.visible:
continue
r = state.rect.clip(s2.rect)
if r:
r2 = Rect((r.left - s2.rect.left,
r.top - s2.rect.top),
r.size)
s2.damaged_areas.append((r, r2))
s2.damaged = True
# for in spritelist
changed.sort(_cmp_area)
split_rects = []
for r in changed:
split_rects_add(split_rects, r)
surface_blit = surface.blit
dirty = []
dirty_append = dirty.append
for r in split_rects:
r = surface_blit(bg, r, r)
dirty_append(r)
for s in spritelist:
if s.dirty or s.damaged or not s.visible:
continue
state = s.last_state
r2 = r.clip(state.rect)
if r2:
r3 = Rect(r2.left - s.rect.left, r2.top - s.rect.top,
r2.width, r2.height)
surface_blit(s.image, r2, r3)
# for in spritelist
# for in split_rects
self.lostsprites = dirty
# clear()