import pygame from .. import tools,setup from .. import constants as C import json import os class Player(pygame.sprite.Sprite): def __init__(self,name): pygame.sprite.Sprite.__init__(self) self.name = name self.load_data() self.setup_states() # 状态 self.setup_velocities() # 速度 self.setup_timer() # 一系列计时器 self.load_images() # 帧造型 def load_data(self): file_name = self.name + '.json' file_path = os.path.join('source/data/player', file_name) # 拼接文件路径 with open(file_path) as f: self.player_data = json.load(f) # 打开加载文件 def setup_states(self): self.state = 'stand' # 初始状态 self.face_right = True self.dead = False self.big = False self.can_jump = True def setup_velocities(self): speed = self.player_data['speed'] # 读出速度数据 self.x_vel = 0 self.y_vel = 0 self.max_walk_vel = speed['max_walk_speed'] # 记录速度属性 v速度 a加速 t转身 self.max_run_vel = speed['max_run_speed'] self.max_y_vel = speed['max_y_velocity'] self.jump_vel = speed['jump_velocity'] self.walk_accel = speed['walk_accel'] self.run_accel = speed['run_accel'] self.turn_accel = speed['turn_accel'] self.gravity = C.GRAVITY self.anti_gravity = C.ANTI_GRAVITY self.max_y_vel = self.max_walk_vel self.x_accel = self.walk_accel def setup_timer(self): self.walking_timer = 0 self.transition_timer = 0 def load_images(self): sheet = setup.GRAPHICS['mario_bros'] frame_rects = self.player_data['image_frames'] self.right_small_normal_frames = [] self.right_big_normal_frames = [] self.right_big_fire_frames = [] self.left_small_normal_frames = [] self.left_big_normal_frames = [] self.left_big_fire_frames = [] # 底层分类 self.small_normal_frames = [self.right_small_normal_frames,self.left_small_normal_frames] self.big_normal_frames = [self.right_big_normal_frames,self.left_big_normal_frames] self.big_fire_frames = [self.right_big_fire_frames,self.left_big_fire_frames] #归纳 self.all_frames = [ self.right_small_normal_frames, self.right_big_normal_frames, self.right_big_fire_frames, self.left_small_normal_frames, self.left_big_normal_frames, self.left_big_fire_frames, # 全体集合 ] self.right_frames = self.right_small_normal_frames self.left_frames = self.left_small_normal_frames # 设置默认左右帧库 for group,group_frame_rects in frame_rects.items(): for frame_rect in group_frame_rects: right_image = tools.get_image(sheet, frame_rect['x'],frame_rect['y'], frame_rect['width'],frame_rect['height'],(0, 0, 0), C.PLAYER_MULTI) left_image = pygame.transform.flip(right_image, True, False) if group == 'right_small_normal': self.right_small_normal_frames.append(right_image) self.left_small_normal_frames.append(left_image) if group == 'right_big_normal': self.right_big_normal_frames.append(right_image) self.left_big_normal_frames.append(left_image) if group == 'right_big_fire': self.right_big_fire_frames.append(right_image) self.left_big_fire_frames.append(left_image) # 遍历 self.frame_index = 0 self.frames = self.right_frames self.image = self.frames[self.frame_index] self.rect = self.image.get_rect() def update(self,keys): self.current_time = pygame.time.get_ticks() self.handle_states(keys) def handle_states(self,keys): # 状态检测 self.can_jump_or_not(keys) if self.state == 'stand': self.stand(keys) elif self.state == 'walk': self.walk(keys) elif self.state == 'jump': self.jump(keys) elif self.state == 'fall': self.fall(keys) elif self.state == 'basketball': self.play_basketball(keys) if self.face_right: self.image = self.right_frames[self.frame_index] else: self.image = self.left_frames[self.frame_index] def can_jump_or_not(self,keys): if not keys[pygame.K_SPACE]: self.can_jump = True def stand(self,keys): self.frame_index = 0 self.x_vel = 0 self.y_vel = 0 # 初速度等都为0 if keys[pygame.K_RIGHT]: # 朝向 self.face_right = True self.state = 'walk' if keys[pygame.K_LEFT]: self.face_right = False self.state = 'walk' if keys[pygame.K_SPACE] and self.can_jump: self.state = 'jump' self.y_vel = self.jump_vel def walk(self,keys): self.current_time = pygame.time.get_ticks() if keys[pygame.K_s]: self.max_x_vel = self.max_run_vel self.x_accel = self.run_accel else: self.max_x_vel = self.max_walk_vel self.x_accel = self.walk_accel if keys[pygame.K_SPACE] and self.can_jump: self.state = 'jump' self.y_vel = self.jump_vel if self.current_time - self.walking_timer > self.calc_frame_duration(): if self.frame_index < 3: self.frame_index += 1 else: self.frame_index = 1 self.walking_timer = self.current_time if keys[pygame.K_RIGHT]: self.face_right = True if self.x_vel < 0: self.frame_index = 5 self.x_accel = self.turn_accel self.x_vel = self.calc_vel(self.x_vel,self.x_accel,self.max_x_vel,True) elif keys[pygame.K_LEFT]: self.face_right = False if self.x_vel > 0: self.frame_index = 5 self.x_accel = self.turn_accel self.x_vel = self.calc_vel(self.x_vel, self.x_accel, self.max_x_vel, False) else: if self.face_right: self.x_vel -= self.x_accel if self.x_vel < 0: self.x_vel = 0 self.state = 'stand' else: self.x_vel += self.x_accel if self.x_vel > 0: self.x_vel = 0 self.state = 'stand' def jump(self,keys): self.frame_index = 4 self.y_vel += self.anti_gravity self.can_jump = False if self.y_vel >= 0: self.state = 'fall' if keys[pygame.K_RIGHT]: self.x_vel = self.calc_vel(self.x_vel,self.x_accel,self.max_x_vel,True) elif keys[pygame.K_LEFT]: self.x_vel = self.calc_vel(self.x_vel, self.x_accel, self.max_x_vel, False) if not keys[pygame.K_SPACE]: self.state = 'fall' def fall(self,keys): self.y_vel = self.calc_vel(self.y_vel,self.gravity,self.max_y_vel) # TODO WORKAROUND if self.rect.bottom > C.GROUND_HEIGHT: self.rect.bottom = C.GROUND_HEIGHT self.y_vel = 0 self.state = 'walk' if keys[pygame.K_RIGHT]: self.x_vel = self.calc_vel(self.x_vel,self.x_accel,self.max_x_vel,True) elif keys[pygame.K_LEFT]: self.x_vel = self.calc_vel(self.x_vel, self.x_accel, self.max_x_vel, False) def play_basketball(self,keys): pass def calc_vel(self,vel,accel,max_vel,is_positive=True): # 求速度 if is_positive: return min(vel + accel, max_vel) else: return max(vel - accel, -max_vel) # 反之加负 def calc_frame_duration(self): duration = -60 / self.max_run_vel *abs(self.x_accel) + 80 return duration