class Buff: def __init__(self, func, duration): self.func = func self.duration = duration self.timer = Timer() self.is_expired = False def start(self): self.timer = Timer() def call_func(self, player, buff): self.func(player, buff) def update(self, deltatime): t = self.timer.get_time() if t > self.duration: self.is_expired = True
class AnimatedSprite: def __init__(self, img_id, frames): self.image_id = img_id self.frequency = 100 self.bounds = (32,32) self.timer = Timer() self.current_frame = 0 self.max_frames = frames self.sprite_rec = gImages[self.image_id.value].get_rect() self.rotation = 0 self.loop_count = 0 def full_sprite_rect(self): return self.sprite_rec def sprite_rect(self): return pygame.Rect(self.sprite_rec.topleft[0],self.sprite_rec.topleft[1],self.bounds[0],self.bounds[1]) def get_center(self): return (self.sprite_rec.topleft[0] + int(self.bounds[0]/2) , self.sprite_rec.topleft[1] + int(self.bounds[1]/2)) def next_frame(self): self.current_frame += 1 self.current_frame %= self.max_frames if self.current_frame==0: self.loop_count += 1 def reset(self): self.current_frame = 0 self.loop_count = 0 self.timer.reset() def update(self, deltatime): time = self.timer.get_time() if time >= self.frequency: self.timer.mod_time(self.frequency) self.next_frame() def draw(self, screen, camera): rect = pygame.Rect((self.current_frame*self.bounds[0],0),self.bounds) spr_pos = (self.sprite_rec[0]-camera[0],self.sprite_rec[1]-camera[1],self.sprite_rec[2]-camera[0], self.sprite_rec[3]-camera[1]) screen.blit(gImages[self.image_id.value], spr_pos, rect) def move(self, displacement): self.sprite_rec = self.sprite_rec.move(displacement) def set_location(self, pos): self.sprite_rec.topleft = pos def set_rotation(self, angle): self.rotation = angle self.sprite = pygame.transform.rotate(gImages[self.image_id.value], math.degrees(angle)) def get_mask(self): m = pygame.Mask((32,32)) m.fill() return m def get_frame(self): return self.current_frame
class AnimatedSprite: def __init__(self, img_id, frames): self.image_id = img_id self.frequency = 100 self.bounds = (32, 32) self.timer = Timer() self.current_frame = 0 self.max_frames = frames self.sprite_rec = gImages[self.image_id.value].get_rect() self.rotation = 0 self.loop_count = 0 def full_sprite_rect(self): return self.sprite_rec def sprite_rect(self): return pygame.Rect(self.sprite_rec.topleft[0], self.sprite_rec.topleft[1], self.bounds[0], self.bounds[1]) def get_center(self): return (self.sprite_rec.topleft[0] + int(self.bounds[0] / 2), self.sprite_rec.topleft[1] + int(self.bounds[1] / 2)) def next_frame(self): self.current_frame += 1 self.current_frame %= self.max_frames if self.current_frame == 0: self.loop_count += 1 def reset(self): self.current_frame = 0 self.loop_count = 0 self.timer.reset() def update(self, deltatime): time = self.timer.get_time() if time >= self.frequency: self.timer.mod_time(self.frequency) self.next_frame() def draw(self, screen, camera): rect = pygame.Rect((self.current_frame * self.bounds[0], 0), self.bounds) spr_pos = (self.sprite_rec[0] - camera[0], self.sprite_rec[1] - camera[1], self.sprite_rec[2] - camera[0], self.sprite_rec[3] - camera[1]) screen.blit(gImages[self.image_id.value], spr_pos, rect) def move(self, displacement): self.sprite_rec = self.sprite_rec.move(displacement) def set_location(self, pos): self.sprite_rec.topleft = pos def set_rotation(self, angle): self.rotation = angle self.sprite = pygame.transform.rotate(gImages[self.image_id.value], math.degrees(angle)) def get_mask(self): m = pygame.Mask((32, 32)) m.fill() return m def get_frame(self): return self.current_frame
class Player: def __init__(self, pos, level): self.level = level self.size = (BLOCK_SIZE, BLOCK_SIZE) self.state = PlayerState.JUMPING self.speed = CONST_PLAYER_SPEED self.sprint_speed = CONST_PLAYER_SPRINT_SPEED self.jump_velocity = CONST_JUMP_VELOCITY self.energy_regain_rate = CONST_ENERGY_GAIN_RATE self.sprint_energy_rate = CONST_SPRINT_ENERGY_RATE self.facing = Facing.LEFT self.sprite = AnimationFSM() spr0 = AnimatedSprite(ImageEnum.PLAYER1_LEFT, 8) spr1 = AnimatedSprite(ImageEnum.PLAYER1_RIGHT, 8) spr2 = AnimatedSprite(ImageEnum.PLAYER1_JUMPLEFT, 1) spr3 = AnimatedSprite(ImageEnum.PLAYER1_JUMPRIGHT, 1) spr4 = AnimatedSprite(ImageEnum.PLAYER1_LEFT, 1) spr5 = AnimatedSprite(ImageEnum.PLAYER1_RIGHT, 1) spr6 = AnimatedSprite(ImageEnum.PLAYER1_STABLEFT, 4) spr7 = AnimatedSprite(ImageEnum.PLAYER1_STABRIGHT, 4) self.sprite.add_sprite(spr0) self.sprite.add_sprite(spr1) self.sprite.add_sprite(spr2) self.sprite.add_sprite(spr3) self.sprite.add_sprite(spr4) self.sprite.add_sprite(spr5) self.sprite.add_sprite(spr6) self.sprite.add_sprite(spr7) self.sprite.set_state(PlayerAnimState.JUMP_LEFT) self.is_sprinting = False self.moving_component = MovingComponent(self, self.level) self.moving_component.move(pos) #self.moving_component.on_collision = Player.on_collision self.equipment = [] self.equipped_weapon = -1 self.equip_component = EquipComponent(self, self.level) self.equip_component.print_attach_points() self.energy = CONST_INIT_ENERGY self.energy_timer = Timer() self.valid_blink_points = [] self.health = Health(CONST_INIT_HEALTH, 0) self.max_health = CONST_INIT_HEALTH self.max_energy = CONST_INIT_ENERGY self.buffs = [] from src.Sprite import Sprite self.dot_spr = Sprite(ImageEnum.BLINK_DOT) self.dot_spr.bounds = (0, 0, 4, 4) self.can_blink = False self.keys = [] for i in range(KeyEnum.NUM.value): self.keys.append(0) for i in range(WeaponEnum.NUM.value): self.equipment.append(None) self.blink_component = Blink_Component(player=self) def update_sprite(self): if not self.equip_component.is_attacking: if self.state == PlayerState.JUMPING: if self.moving_component.velocity[0] >= 0: self.sprite.set_state(PlayerAnimState.JUMP_RIGHT) self.facing = Facing.RIGHT else: self.sprite.set_state(PlayerAnimState.JUMP_LEFT) self.facing = Facing.LEFT else: if self.moving_component.velocity[0] > 0: self.sprite.set_state(PlayerAnimState.WALK_RIGHT) self.facing = Facing.RIGHT elif self.moving_component.velocity[0] < 0: self.sprite.set_state(PlayerAnimState.WALK_LEFT) self.facing = Facing.LEFT else: if self.facing == Facing.RIGHT: self.sprite.set_state(PlayerAnimState.RIGHT) if self.facing == Facing.LEFT: self.sprite.set_state(PlayerAnimState.LEFT) def handle_collisions(self): entities = self.level.entities lies_between = lambda x, a, b : a <= x <= b for other in entities: #assert(isinstance(other, Skeleton)) player_rect =self.sprite.sprite_rect() assert(isinstance(player_rect, pygame.Rect)) other_rect = other.sprite.sprite_rect() assert(isinstance(other_rect, pygame.Rect)) collision = {} collision["right"] = lies_between(other_rect.left, player_rect.left, player_rect.right) collision["left"] = lies_between(other_rect.right, player_rect.left, player_rect.right) if collision["left"] or collision["right"]: collision["up"] = lies_between(other_rect.bottom, player_rect.top, player_rect.bottom) collision["down"] = lies_between(other_rect.top, player_rect.top, player_rect.bottom) if collision["down"] or collision["up"]: self.on_collision(other) def update_buffs(self, deltatime): self.speed = CONST_PLAYER_SPEED self.sprint_speed = CONST_PLAYER_SPRINT_SPEED self.jump_velocity = CONST_JUMP_VELOCITY self.energy_regain_rate = CONST_ENERGY_GAIN_RATE self.sprint_energy_rate = CONST_SPRINT_ENERGY_RATE self.moving_component.gravity = CONST_GRAVITY self.moving_component.bounciness = 0 for buff in self.buffs: buff.update(deltatime) if buff.is_expired: self.buffs.remove(buff) else: buff.call_func(self, buff) def can_sprint(self): if self.energy > 0: return True else: return False def draw(self, screen, camera): self.sprite.draw(screen, camera) self.equip_component.draw_right(screen, camera) #if self.equipped_weapon is not -1: # self.weapon[self.equipped_weapon].draw(screen, camera) self.blink_component.draw(screen, camera) def handle_event(self, event): self.blink_component.handle_event(event) if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and self.state==PlayerState.GROUND: self.moving_component.velocity = (self.moving_component.velocity[0],self.moving_component.velocity[1] - self.jump_velocity) #self.state = PlayerState.JUMPING play_sound(SoundEnum.JUMP) elif event.key == pygame.K_e: i = self.equipped_weapon + 1 while i < WeaponEnum.NUM.value: if self.equipment[i] is not None: self.equipped_weapon = i self.equip_component.equip_right(self.equipment[self.equipped_weapon]) break i+=1 elif event.key == pygame.K_q: i = self.equipped_weapon - 1 while i >= 0: if self.equipment[i] is not None: self.equipped_weapon = i self.equip_component.equip_right(self.equipment[self.equipped_weapon]) break i-=1 elif event.type == pygame.MOUSEBUTTONDOWN: if self.blink_component.state != BlinkState.SHOWING_LINE: if self.equipped_weapon != -1: mpos = pygame.mouse.get_pos() target = (mpos[0]+self.level.camera_pos[0],mpos[1]+self.level.camera_pos[1]) self.equipment[self.equipped_weapon].use(target) self.equip_component.is_attacking = True elif event.type == pygame.KEYUP: if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: self.moving_component.velocity = (0, self.moving_component.velocity[1]) # def handle_event(self, event): # self.blink_component.handle_event(event) # if event.type == pygame.KEYDOWN: # if event.key == pygame.K_SPACE and self.state==PlayerState.GROUND: # self.moving_component.velocity = (self.moving_component.velocity[0],self.moving_component.velocity[1] - self.jump_velocity) # play_sound(SoundEnum.JUMP) # elif event.type == pygame.KEYUP: # if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: # self.moving_component.velocity = (0, self.moving_component.velocity[1]) def update(self, deltatime): self.blink_component.update(deltatime) #parse buffs self.update_buffs(deltatime) #detect input keys = pygame.key.get_pressed() if keys[pygame.K_a] and not keys[pygame.K_d]: if keys[SPRINT_KEY] and self.can_sprint(): self.moving_component.velocity = (-self.sprint_speed, self.moving_component.velocity[1]) self.is_sprinting = True else: self.moving_component.velocity = (-self.speed, self.moving_component.velocity[1]) self.is_sprinting = False elif keys[pygame.K_d] and not keys[pygame.K_a]: if keys[SPRINT_KEY] and self.can_sprint(): self.moving_component.velocity = (self.sprint_speed, self.moving_component.velocity[1]) self.is_sprinting = True else: self.moving_component.velocity = (self.speed, self.moving_component.velocity[1]) self.is_sprinting = False else: self.moving_component.velocity = (0, self.moving_component.velocity[1]) self.is_sprinting = False self.moving_component.update(deltatime) self.equip_component.update(deltatime) #set sprite if not self.moving_component.in_air: self.state = PlayerState.GROUND self.update_sprite() else: self.state = PlayerState.JUMPING self.update_sprite() #sprinting t = self.energy_timer.get_time() if self.is_sprinting: if t > self.sprint_energy_rate: self.energy_timer.mod_time(self.sprint_energy_rate) self.energy -= 1 if self.energy < 0: self.energy = 0 elif not keys[SPRINT_KEY]: if t > self.energy_regain_rate: self.energy_timer.mod_time(self.energy_regain_rate) self.energy += 1 if self.energy >= self.max_energy: self.energy = self.max_energy self.sprite.update(deltatime) if self.health.health > self.max_health: self.health.health = self.max_health #handle collisions self.handle_collisions() def save(self, file): file.write(str(self.moving_component.position[0])) file.write('\n') file.write(str(self.moving_component.position[1])) file.write('\n') @staticmethod def load(file, level): posx = int(file.readline()) posy = int(file.readline()) pos = (posx, posy) return (Player(pos, level)) def on_collision(self, other): if isinstance(other, Powerup): other.buff.start() self.buffs.append(other.buff) self.level.destroy_entity(other) play_sound(SoundEnum.POWERUP) if isinstance(other, Key): self.keys[other.key_type.value] += 1 self.level.destroy_entity(other) if isinstance(other, Lock): if self.keys[other.lock_type.value] > 0: self.keys[other.lock_type.value] -= 1 self.level.destroy_entity(other) play_sound(SoundEnum.UNLOCK) if isinstance(other, Ammo): if self.equipment[other.ammo_type.value] is not None: self.equipment[other.ammo_type.value].ammo += 5 self.level.destroy_entity(other) if isinstance(other, WeaponItem): print("eq") self.equipment[other.weapon_type.value] = WeaponEquipped(other.weapon_type, 5, self) if self.equip_component.right_hand is None: self.equip_component.equip_right(self.equipment[other.weapon_type.value]) self.equipped_weapon = other.weapon_type.value else: self.equipment[other.weapon_type.value].ammo += 5 self.level.destroy_entity(other)