|
|
|
@ -19,6 +19,7 @@ class Level:
|
|
|
|
|
self.setup_ground_items()
|
|
|
|
|
self.setup_bricks_and_boxes()
|
|
|
|
|
self.setup_enemies()
|
|
|
|
|
self.setup_checkpoints()
|
|
|
|
|
|
|
|
|
|
def load_map_data(self):
|
|
|
|
|
file_name = 'level_1.json'
|
|
|
|
@ -60,24 +61,37 @@ class Level:
|
|
|
|
|
def setup_bricks_and_boxes(self):
|
|
|
|
|
self.brick_group = pygame.sprite.Group()
|
|
|
|
|
self.box_group = pygame.sprite.Group()
|
|
|
|
|
self.coin_group = pygame.sprite.Group()
|
|
|
|
|
self.powerup_group = pygame.sprite.Group()
|
|
|
|
|
|
|
|
|
|
if'brick' in self.map_data:
|
|
|
|
|
for brick_data in self.map_data['brick']: # 遍历得到x,y坐标以及type
|
|
|
|
|
x,y = brick_data['x'],brick_data['y']
|
|
|
|
|
brick_type = brick_data['type']
|
|
|
|
|
if 'brick_num' in brick_data:
|
|
|
|
|
#TODO Batch bricks
|
|
|
|
|
pass
|
|
|
|
|
if brick_type == 0:
|
|
|
|
|
if 'brick_num' in brick_data:
|
|
|
|
|
#TODO Batch bricks
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
self.brick_group.add(brick.Brick(x, y, brick_type,None))
|
|
|
|
|
elif brick_type == 1:
|
|
|
|
|
self.brick_group.add(brick.Brick(x, y, brick_type, self.coin_group))
|
|
|
|
|
else:
|
|
|
|
|
self.brick_group.add(brick.Brick(x,y,brick_type))
|
|
|
|
|
self.brick_group.add(brick.Brick(x, y, brick_type, self.powerup_group))
|
|
|
|
|
|
|
|
|
|
if 'box' in self.map_data:
|
|
|
|
|
for box_data in self.map_data['box']: # 遍历得到x,y坐标以及type
|
|
|
|
|
x, y = box_data['x'], box_data['y']
|
|
|
|
|
box_type = box_data['type']
|
|
|
|
|
self.brick_group.add(box.Box(x, y, box_type))
|
|
|
|
|
if box_type == 1:
|
|
|
|
|
self.box_group.add(box.Box(x, y, box_type, self.coin_group))
|
|
|
|
|
else:
|
|
|
|
|
self.box_group.add(box.Box(x, y, box_type,self.powerup_group))
|
|
|
|
|
|
|
|
|
|
def setup_enemies(self):
|
|
|
|
|
self.dying_group = pygame.sprite.Group()
|
|
|
|
|
self.shell_group = pygame.sprite.Group()
|
|
|
|
|
self.enemy_group = pygame.sprite.Group() # 初始化
|
|
|
|
|
self.enemy_group_dict = {}
|
|
|
|
|
for enemy_group_data in self.map_data['enemy']: # 字典存放
|
|
|
|
|
group = pygame.sprite.Group()
|
|
|
|
@ -86,6 +100,14 @@ class Level:
|
|
|
|
|
group.add(enemy.create_enemy(enemy_data)) # 调用 ce
|
|
|
|
|
self.enemy_group_dict[enemy_group_id] = group
|
|
|
|
|
|
|
|
|
|
def setup_checkpoints(self):
|
|
|
|
|
self.checkpoint_group = pygame.sprite.Group()
|
|
|
|
|
for item in self.map_data['checkpoint']:
|
|
|
|
|
x,y,w,h = item['x'],item['y'],item['width'],item['height']
|
|
|
|
|
checkpoint_type = item['type']
|
|
|
|
|
enemy_groupid = item.get('enemy_groupid')
|
|
|
|
|
self.checkpoint_group.add(stuff.Checkpoint(x,y,w,h,checkpoint_type,enemy_groupid))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update(self, surface, keys):
|
|
|
|
@ -100,13 +122,17 @@ class Level:
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
self.update_player_position()
|
|
|
|
|
self.check_checkpoints()
|
|
|
|
|
self.check_if_go_die()
|
|
|
|
|
self.update_game_window()
|
|
|
|
|
self.info.update()
|
|
|
|
|
self.brick_group.update()
|
|
|
|
|
self.box_group.update()
|
|
|
|
|
for enemy_group in self.enemy_group_dict.values():
|
|
|
|
|
enemy_group.update()
|
|
|
|
|
self.enemy_group.update(self)
|
|
|
|
|
self.dying_group.update(self)
|
|
|
|
|
self.shell_group.update(self)
|
|
|
|
|
self.coin_group.update()
|
|
|
|
|
self.box_group.update()
|
|
|
|
|
|
|
|
|
|
self.draw(surface)
|
|
|
|
|
|
|
|
|
@ -122,8 +148,11 @@ class Level:
|
|
|
|
|
self.check_x_collisions()
|
|
|
|
|
|
|
|
|
|
# y判定
|
|
|
|
|
self.player.rect.y += self.player.y_vel
|
|
|
|
|
self.check_y_collisions()
|
|
|
|
|
if not self.player.dead:
|
|
|
|
|
self.player.rect.y += self.player.y_vel
|
|
|
|
|
self.check_y_collisions()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_x_collisions(self): # x方向
|
|
|
|
|
check_group = pygame.sprite.Group(self.ground_items_group,self.brick_group,self.box_group)
|
|
|
|
@ -131,12 +160,64 @@ class Level:
|
|
|
|
|
if collided_sprite:
|
|
|
|
|
self.adjust_player_x(collided_sprite)
|
|
|
|
|
|
|
|
|
|
enemy = pygame.sprite.spritecollideany(self.player, self.enemy_group)
|
|
|
|
|
if enemy:
|
|
|
|
|
self.player.go_die()
|
|
|
|
|
|
|
|
|
|
shell = pygame.sprite.spritecollideany(self.player, self.shell_group) # 碰撞检测
|
|
|
|
|
if shell:
|
|
|
|
|
if shell.state == 'slide':
|
|
|
|
|
self.player.go_die()
|
|
|
|
|
else:
|
|
|
|
|
if self.player.rect.x < shell.rect.x: # 龟壳弹开方向以及速度
|
|
|
|
|
shell.x_vel = 10
|
|
|
|
|
shell.rect.x += 40
|
|
|
|
|
shell.direction = 1
|
|
|
|
|
else:
|
|
|
|
|
shell.x_vel = -10
|
|
|
|
|
shell.rect.x -= 40
|
|
|
|
|
shell.direction = 0
|
|
|
|
|
shell.state = 'slide'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_y_collisions(self): # y方向
|
|
|
|
|
check_group = pygame.sprite.Group(self.ground_items_group, self.brick_group,self.box_group)
|
|
|
|
|
collided_sprite = pygame.sprite.spritecollideany(self.player, check_group) # 检测碰撞
|
|
|
|
|
if collided_sprite:
|
|
|
|
|
self.adjust_player_y( collided_sprite)
|
|
|
|
|
ground_item = pygame.sprite.spritecollideany(self.player,self.ground_items_group)
|
|
|
|
|
brick = pygame.sprite.spritecollideany(self.player, self.brick_group)
|
|
|
|
|
box = pygame.sprite.spritecollideany(self.player, self.box_group)
|
|
|
|
|
enemy = pygame.sprite.spritecollideany(self.player, self.enemy_group)
|
|
|
|
|
|
|
|
|
|
if brick and box: # 判断离哪个砖块进哪个顶起
|
|
|
|
|
to_brick = abs(self.player.rect.centerx - brick.rect.centerx)
|
|
|
|
|
to_box = abs(self.player.rect.centerx - box.rect.centerx)
|
|
|
|
|
if to_brick > to_box:
|
|
|
|
|
brick = None
|
|
|
|
|
else:
|
|
|
|
|
box = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ground_item:
|
|
|
|
|
self.adjust_player_y(ground_item)
|
|
|
|
|
elif brick:
|
|
|
|
|
self.adjust_player_y(brick)
|
|
|
|
|
elif box:
|
|
|
|
|
self.adjust_player_y(box)
|
|
|
|
|
|
|
|
|
|
elif enemy:
|
|
|
|
|
self.enemy_group.remove(enemy)
|
|
|
|
|
if enemy.name == 'koopa':
|
|
|
|
|
self.shell_group.add(enemy) # 龟壳状态进龟壳组
|
|
|
|
|
else:
|
|
|
|
|
self.dying_group.add(enemy) # 由敌人组 → 死亡组
|
|
|
|
|
|
|
|
|
|
if self.player.y_vel < 0:
|
|
|
|
|
how = 'bumped'
|
|
|
|
|
else:
|
|
|
|
|
how = 'trampled'
|
|
|
|
|
self.player.state = 'jump'
|
|
|
|
|
self.player.rect.bottom = enemy.rect.top
|
|
|
|
|
self.player.y_vel = self.player.jump_vel * 0.8 # 力道
|
|
|
|
|
enemy.go_die(how)
|
|
|
|
|
|
|
|
|
|
self.check_will_fall(self.player) # 坠落检测
|
|
|
|
|
|
|
|
|
|
def adjust_player_x(self,sprite):
|
|
|
|
@ -156,11 +237,18 @@ class Level:
|
|
|
|
|
self.player.rect.top = sprite.rect.bottom
|
|
|
|
|
self.player.state = 'fall'
|
|
|
|
|
|
|
|
|
|
if sprite.name == 'box':
|
|
|
|
|
if sprite.state == 'rest':
|
|
|
|
|
sprite.go_bumped()
|
|
|
|
|
if sprite.name == 'brick':
|
|
|
|
|
if sprite.state == 'rest':
|
|
|
|
|
sprite.go_bumped()
|
|
|
|
|
|
|
|
|
|
def check_will_fall(self,sprite):
|
|
|
|
|
sprite.rect.y += 1 # 下落一个像素
|
|
|
|
|
check_group = pygame.sprite.Group(self.ground_items_group,self.brick_group,self.box_group) # 检测是否碰撞
|
|
|
|
|
collided_sprite = pygame.sprite.spritecollideany(sprite,check_group)
|
|
|
|
|
if not collided_sprite and sprite.state != 'jump' : # 如果没有或者处于跳起则不坠落
|
|
|
|
|
if not collided_sprite and sprite.state != 'jump': # 如果没有或者处于跳起则不坠落
|
|
|
|
|
sprite.state = 'fall'
|
|
|
|
|
sprite.rect.y -= 1
|
|
|
|
|
|
|
|
|
@ -175,12 +263,24 @@ class Level:
|
|
|
|
|
self.game_ground.blit(self.player.image,self.player.rect) # 将背景与人物化境
|
|
|
|
|
self.brick_group.draw(self.game_ground)
|
|
|
|
|
self.box_group.draw(self.game_ground)
|
|
|
|
|
for enemy_group in self.enemy_group_dict.values():
|
|
|
|
|
enemy_group.draw(self.game_ground)
|
|
|
|
|
self.enemy_group.draw(self.game_ground)
|
|
|
|
|
self.dying_group.draw(self.game_ground)
|
|
|
|
|
self.shell_group.draw(self.game_ground)
|
|
|
|
|
self.coin_group.draw(self.game_ground)
|
|
|
|
|
self.powerup_group.draw(self.game_ground)
|
|
|
|
|
|
|
|
|
|
surface.blit(self.game_ground,(0,0), self.game_window) # 渲染
|
|
|
|
|
self.info.draw(surface)
|
|
|
|
|
|
|
|
|
|
def check_checkpoints(self):
|
|
|
|
|
checkpoint = pygame.sprite.spritecollideany(self.player,self.checkpoint_group)
|
|
|
|
|
if checkpoint:
|
|
|
|
|
if checkpoint.checkpoint_type == 0: # checkpoint for enemy appearance # 如果检查点类型为0 释放对应敌人
|
|
|
|
|
self.enemy_group.add(self.enemy_group_dict[str(checkpoint.enemy_groupid)]) # 一旦某个点被触发就把对应敌人放入此组
|
|
|
|
|
checkpoint.kill() # 被触碰后消失
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_if_go_die(self):
|
|
|
|
|
if self.player.rect.y > C.SCREEN_H:
|
|
|
|
|
self.player.go_die() # 判断是否掉落屏幕外
|
|
|
|
|