first commit

main
夏铭 6 months ago
parent 4f98e3147b
commit 9b18a238e0

@ -1,13 +1,17 @@
import pygame import pygame
from .. import tools,setup from .. import tools,setup
from .. import constants as C from .. import constants as C
from .powerup import create_powerup
class Box(pygame.sprite.Sprite): class Box(pygame.sprite.Sprite):
def __init__(self, x, y,box_type): def __init__(self, x, y,box_type,group,name = 'box'):
pygame.sprite.Sprite.__init__(self) pygame.sprite.Sprite.__init__(self)
self.x = x self.x = x
self.y = y self.y = y
self.box_type = box_type self.box_type = box_type
self.group = group
self.name = name
self.frame_rects = [ self.frame_rects = [
(384,0,16,16), (384,0,16,16),
(400,0,16,16), (400,0,16,16),
@ -24,3 +28,50 @@ class Box(pygame.sprite.Sprite):
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.rect.x = self.x self.rect.x = self.x
self.rect.y = self.y # 设置坐标与图片 self.rect.y = self.y # 设置坐标与图片
self.gravity = C.GRAVITY
self.state = 'rest'
self.timer = 0
def update(self):
self.current_time = pygame.time.get_ticks()
self.handel_states()
def handel_states(self):
if self.state == 'rest':
self.rest()
elif self.state == 'bumped':
self.bumped()
elif self.state == 'open':
self.open()
def rest(self):
frame_durations = [400,100,100,50]
if self.current_time - self.timer > frame_durations[self.frame_index]:
self.frame_index = (self.frame_index + 1) % 4
self.timer = self.current_time
self.image = self.frames[self.frame_index]
def go_bumped(self):
self.y_vel = -7
self.state = 'bumped'
def bumped(self):
self.rect.y += self.y_vel
self.y_vel += self.gravity
self.frame_index = 3
self.image = self.frames[self.frame_index]
if self.rect.y > self.y + 10 : # 如果大于初始位置回弹
self.rect.y = self.y
self.state = 'open'
if self.box_type == 1:
pass
else:
self.group.add(create_powerup(self.rect.centerx,self.rect.centery,self.box_type))
def open(self):
pass

@ -1,13 +1,16 @@
import pygame import pygame
from .. import tools,setup from .. import tools,setup
from .. import constants as C from .. import constants as C
from .powerup import create_powerup
class Brick(pygame.sprite.Sprite): class Brick(pygame.sprite.Sprite):
def __init__(self, x, y,brick_type,color=None): def __init__(self, x, y,brick_type,group,color=None,name = 'brick'):
pygame.sprite.Sprite.__init__(self) pygame.sprite.Sprite.__init__(self)
self.x = x self.x = x
self.y = y self.y = y
self.type = brick_type self.brick_type = brick_type
self.group = group
self.name = name
bright_frame_rects = [(16,0,16,16),(48,0,16,16)] bright_frame_rects = [(16,0,16,16),(48,0,16,16)]
dark_frame_rects = [(16,32,16,16),(48,32,16,16)] # 抠图 dark_frame_rects = [(16,32,16,16),(48,32,16,16)] # 抠图
@ -25,3 +28,45 @@ class Brick(pygame.sprite.Sprite):
self.rect = self.image.get_rect() self.rect = self.image.get_rect()
self.rect.x = self.x self.rect.x = self.x
self.rect.y = self.y # 设置坐标与图片 self.rect.y = self.y # 设置坐标与图片
self.state = 'rest'
self.gravity = C.GRAVITY
def update(self):
self.current_time = pygame.time.get_ticks()
self.handel_states()
def handel_states(self):
if self.state == 'rest':
self.rest()
elif self.state == 'bumped':
self.bumped()
elif self.state == 'open':
self.open()
def rest(self):
pass
def go_bumped(self):
self.y_vel = -7
self.state = 'bumped'
def bumped(self):
self.rect.y += self.y_vel
self.y_vel += self.gravity
if self.rect.y > self.y + 10 : # 如果大于初始位置回弹
self.rect.y = self.y
if self.brick_type == 0:
self.state = 'rest'
elif self.brick_type == 1:
self.state = 'open'
else:
self.group.add(create_powerup(self.rect.centerx,self.rect.centery,self.brick_type))
def open(self):
self.frame_index = 1
self.image = self.frames[self.frame_index]

@ -31,6 +31,10 @@ class Enemy(pygame.sprite.Sprite):
self.rect.bottom = y_bottom self.rect.bottom = y_bottom
self.timer = 0 self.timer = 0
self.x_vel = -1 * C.ENEMY_SPEED if self.direction == 0 else C.ENEMY_SPEED
self.y_vel = 0
self.gravity = C.GRAVITY
self.state = 'walk'
def load_frames(self,frame_rects): def load_frames(self,frame_rects):
for frame_rect in frame_rects: for frame_rect in frame_rects:
@ -39,13 +43,101 @@ class Enemy(pygame.sprite.Sprite):
self.left_frames.append(left_frame) self.left_frames.append(left_frame)
self.right_frames.append(right_frame) self.right_frames.append(right_frame)
def update(self): def update(self,level):
self.current_time = pygame.time.get_ticks() self.current_time = pygame.time.get_ticks()
self.handle_states()
self.update_position(level)
def handle_states(self): # 状态检测
if self.state == 'walk':
self.walk()
elif self.state == 'fall':
self.fall()
elif self.state == 'die':
self.die()
elif self.state == 'trampled':
self.trampled()
elif self.state == 'slide':
self.slide()
if self.direction:
self.image = self.right_frames[self.frame_index]
else:
self.image = self.left_frames[self.frame_index]
def walk(self):
if self.current_time - self.timer > 125: if self.current_time - self.timer > 125:
self.frame_index = (self.frame_index + 1) % 2 self.frame_index = (self.frame_index + 1) % 2
self.image = self.frames[self.frame_index] self.image = self.frames[self.frame_index]
self.timer = self.current_time self.timer = self.current_time
def fall(self):
if self.y_vel < 10:
self.y_vel += self.gravity
def die(self):
self.rect.x += self.x_vel
self.rect.y += self.y_vel
self.y_vel += self.gravity
if self.rect.y > C.SCREEN_H:
self.kill()
def trampled(self):
pass
def slide(self):
pass
def update_position(self,level):
self.rect.x += self.x_vel
self.check_x_collisions(level)
self.rect.y += self.y_vel
if self.state != 'die':
self.check_y_collisions(level)
def check_x_collisions(self,level):
sprite = pygame.sprite.spritecollideany(self,level.ground_items_group)
if sprite:
if self.direction: # 向右
self.direction = 0
self.rect.right = sprite.rect.left
else:
self.direction = 1
self.rect.left = sprite.rect.right
self.x_vel *= -1
if self.state == 'slide':
enemy = pygame.sprite.spritecollideany(self,level.enemy_group)
if enemy:
enemy.go_die(how='slided')
level.enemy_group.remove(enemy)
level.dying_group.add(enemy)
def check_y_collisions(self,level):
check_group = pygame.sprite.Group(level.ground_items_group,level.box_group,level.brick_group)
sprite = pygame.sprite.spritecollideany(self,check_group)
if sprite:
if self.rect.top < sprite.rect.top:
self.rect.bottom = sprite.rect.top
self.y_vel = 0
self.state = 'walk'
level.check_will_fall(self)
def go_die(self,how):
self.death_timer = self.current_time
if how in ['bumped','slide']:
self.y_vel = -8
self.gravity = 0.6
self.state = 'die'
self.frame_index = 2
elif how == 'trampled':
self.state = 'trampled'
class Goomba(Enemy): class Goomba(Enemy):
def __init__(self, x, y_bottom, direction, name, color): def __init__(self, x, y_bottom, direction, name, color):
@ -59,6 +151,14 @@ class Goomba(Enemy):
Enemy.__init__(self,x,y_bottom,direction,name,frame_rects) Enemy.__init__(self,x,y_bottom,direction,name,frame_rects)
def trampled(self):
self.x_vel = 0
self.frame_index = 2
if self.death_timer == 0:
self.death_timer = self.current_time
if self.current_time - self.death_timer > 500:
self.kill()
class Koopa(Enemy): class Koopa(Enemy):
def __init__(self, x, y_bottom, direction, name, color): def __init__(self, x, y_bottom, direction, name, color):
@ -71,3 +171,11 @@ class Koopa(Enemy):
frame_rects = dark_frame_rects frame_rects = dark_frame_rects
Enemy.__init__(self,x, y_bottom, direction, name, frame_rects) Enemy.__init__(self,x, y_bottom, direction, name, frame_rects)
def trampled(self):
self.x_vel = 0
self.frame_index = 2 # 缩头乌龟
def slide(self):
pass

@ -0,0 +1,27 @@
import pygame
from .. import tools,setup
from .. import constants as C
def create_powerup(centerx,centery,type): # 根据状态出现道具
"""create powerup based on type and mario state"""
return Mushroom(centerx,centery)
class PowerUp(pygame.sprite.Sprite):
def __init__(self,centerx,rentery,frame_rects):
pygame.sprite.Sprite.__init__(self)
self.frames = []
self.frame_index = 0
for frame_rect in frame_rects:
self.frames.append(tools.get_image(setup.GRAPHICS['item_objects'],*frame_rect,(0,0,0),2.5))
self.image = self.frames[self.frame_index]
self.rect = self.image.get_rect()
self.rect.centerx = centerx
self.rect.centery = rentery
class Mushroom(PowerUp):
def __init__(self,centerx,centery):
PowerUp.__init__(self,centerx,centery,[(0,0,16,16)])

@ -9,3 +9,8 @@ class Item(pygame.sprite.Sprite):
self.rect.y = y self.rect.y = y
self.name = name self.name = name
class Checkpoint(Item):
def __init__(self,x,y,w,h,checkpoint_type,enemy_groupid=None,name='checkpoint'):
Item.__init__(self,x,y,w,h,name)
self.checkpoint_type = checkpoint_type
self.enemy_groupid = enemy_groupid

@ -6,6 +6,7 @@ BG_MULTI = 2.68
PLAYER_MULTI = 2.9 PLAYER_MULTI = 2.9
BRICK_MULTI = 2.69 BRICK_MULTI = 2.69
ENEMY_MULTI = 2.5 ENEMY_MULTI = 2.5
ENEMY_SPEED = 1
GRAVITY = 1.0 GRAVITY = 1.0
ANTI_GRAVITY = 0.3 ANTI_GRAVITY = 0.3

@ -19,6 +19,7 @@ class Level:
self.setup_ground_items() self.setup_ground_items()
self.setup_bricks_and_boxes() self.setup_bricks_and_boxes()
self.setup_enemies() self.setup_enemies()
self.setup_checkpoints()
def load_map_data(self): def load_map_data(self):
file_name = 'level_1.json' file_name = 'level_1.json'
@ -60,24 +61,37 @@ class Level:
def setup_bricks_and_boxes(self): def setup_bricks_and_boxes(self):
self.brick_group = pygame.sprite.Group() self.brick_group = pygame.sprite.Group()
self.box_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: if'brick' in self.map_data:
for brick_data in self.map_data['brick']: # 遍历得到xy坐标以及type for brick_data in self.map_data['brick']: # 遍历得到xy坐标以及type
x,y = brick_data['x'],brick_data['y'] x,y = brick_data['x'],brick_data['y']
brick_type = brick_data['type'] brick_type = brick_data['type']
if 'brick_num' in brick_data: if brick_type == 0:
#TODO Batch bricks if 'brick_num' in brick_data:
pass #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: 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: if 'box' in self.map_data:
for box_data in self.map_data['box']: # 遍历得到xy坐标以及type for box_data in self.map_data['box']: # 遍历得到xy坐标以及type
x, y = box_data['x'], box_data['y'] x, y = box_data['x'], box_data['y']
box_type = box_data['type'] 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): 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 = {} self.enemy_group_dict = {}
for enemy_group_data in self.map_data['enemy']: # 字典存放 for enemy_group_data in self.map_data['enemy']: # 字典存放
group = pygame.sprite.Group() group = pygame.sprite.Group()
@ -86,6 +100,14 @@ class Level:
group.add(enemy.create_enemy(enemy_data)) # 调用 ce group.add(enemy.create_enemy(enemy_data)) # 调用 ce
self.enemy_group_dict[enemy_group_id] = group 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): def update(self, surface, keys):
@ -100,13 +122,17 @@ class Level:
else: else:
self.update_player_position() self.update_player_position()
self.check_checkpoints()
self.check_if_go_die() self.check_if_go_die()
self.update_game_window() self.update_game_window()
self.info.update() self.info.update()
self.brick_group.update() self.brick_group.update()
self.box_group.update() self.box_group.update()
for enemy_group in self.enemy_group_dict.values(): self.enemy_group.update(self)
enemy_group.update() self.dying_group.update(self)
self.shell_group.update(self)
self.coin_group.update()
self.box_group.update()
self.draw(surface) self.draw(surface)
@ -122,8 +148,11 @@ class Level:
self.check_x_collisions() self.check_x_collisions()
# y判定 # y判定
self.player.rect.y += self.player.y_vel if not self.player.dead:
self.check_y_collisions() self.player.rect.y += self.player.y_vel
self.check_y_collisions()
def check_x_collisions(self): # x方向 def check_x_collisions(self): # x方向
check_group = pygame.sprite.Group(self.ground_items_group,self.brick_group,self.box_group) check_group = pygame.sprite.Group(self.ground_items_group,self.brick_group,self.box_group)
@ -131,12 +160,64 @@ class Level:
if collided_sprite: if collided_sprite:
self.adjust_player_x(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方向 def check_y_collisions(self): # y方向
check_group = pygame.sprite.Group(self.ground_items_group, self.brick_group,self.box_group) ground_item = pygame.sprite.spritecollideany(self.player,self.ground_items_group)
collided_sprite = pygame.sprite.spritecollideany(self.player, check_group) # 检测碰撞 brick = pygame.sprite.spritecollideany(self.player, self.brick_group)
if collided_sprite: box = pygame.sprite.spritecollideany(self.player, self.box_group)
self.adjust_player_y( collided_sprite) 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) # 坠落检测 self.check_will_fall(self.player) # 坠落检测
def adjust_player_x(self,sprite): def adjust_player_x(self,sprite):
@ -156,11 +237,18 @@ class Level:
self.player.rect.top = sprite.rect.bottom self.player.rect.top = sprite.rect.bottom
self.player.state = 'fall' 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): def check_will_fall(self,sprite):
sprite.rect.y += 1 # 下落一个像素 sprite.rect.y += 1 # 下落一个像素
check_group = pygame.sprite.Group(self.ground_items_group,self.brick_group,self.box_group) # 检测是否碰撞 check_group = pygame.sprite.Group(self.ground_items_group,self.brick_group,self.box_group) # 检测是否碰撞
collided_sprite = pygame.sprite.spritecollideany(sprite,check_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.state = 'fall'
sprite.rect.y -= 1 sprite.rect.y -= 1
@ -175,12 +263,24 @@ class Level:
self.game_ground.blit(self.player.image,self.player.rect) # 将背景与人物化境 self.game_ground.blit(self.player.image,self.player.rect) # 将背景与人物化境
self.brick_group.draw(self.game_ground) self.brick_group.draw(self.game_ground)
self.box_group.draw(self.game_ground) self.box_group.draw(self.game_ground)
for enemy_group in self.enemy_group_dict.values(): self.enemy_group.draw(self.game_ground)
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) # 渲染 surface.blit(self.game_ground,(0,0), self.game_window) # 渲染
self.info.draw(surface) 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): def check_if_go_die(self):
if self.player.rect.y > C.SCREEN_H: if self.player.rect.y > C.SCREEN_H:
self.player.go_die() # 判断是否掉落屏幕外 self.player.go_die() # 判断是否掉落屏幕外

Loading…
Cancel
Save