def update (self) : assert (self._cooldown_frames_left >= 0) if self._cooldown_frames_left > 0 : self._cooldown_frames_left -= 1 Weapon.update (self)
def update(self, *args): Weapon.update(self, *args) if self.cooldown > 0: self.cooldown -= 1 return self.cooldown = 5 if self.engaged: bp = self.pos bv = (self.target_pos - bp).normal * 1400 if bv.x != 0 or bv.y != 0: self.fire_sound.play() bullet.pool.fire(bp.x, bp.y, bv.x, bv.y)
class EnemyShip(Movable): def __init__(self, pos, screen, size, level): super().__init__(pos, screen, size) self.name = "enemyShip" self.level = level self.image = pygame.image.load("pics/enemy_ship.png") self.cropped_rects = util.cropped_image_rects(40, 36, 8) self.frames_per_image = 4 #TODO adjust self.cur_image_frames = 0 self.cur_image_index = 0 #worth 250 points self.points = 250 self.targets = [level.comets, level.smilies, level.ships_group ] #TODO so far enemyShips do not have friendly fire #TODO: balance hp, speed, and sound here self.weapon = Weapon(self, (9, 9), 120, 2.0, 13, "pics/enemy_bullet.png", self.targets, "TODO:soundfile") def update_impl(self): #not needed self.weapon.update( ) #this just decreases cooldown and kills old bullets #TODO I need to acquire targets from self.targets and shoot at them, also move around (also target != self) #use the self.weapon.shoot(), adjust the self.v_facing for that! #TODO kinda completely redo the movement here since it's weird def blitme_impl(self): self.weapon.blitme() #drawing projectiles before, so ship is on top if self.cur_image_frames >= self.frames_per_image: self.cur_image_index = (self.cur_image_index + 1) % len( self.cropped_rects) self.cur_image_frames = 0 self.screen.blit(self.image, self.rect, self.cropped_rects[self.cur_image_index]) self.cur_image_frames += 1 def killme_impl(self, v_killer=None, killer=None): self.kill()
class Ship: def __init__(self, app): self.screen = app.screen self.screen_rect = app.screen.get_rect() self.image = pygame.image.load("assets/images/dark_ship.png") self.rect = self.image.get_rect() self.rect.midbottom = self.screen_rect.midbottom self.speed = 0.15 self.acceleration = 0.05 self.x = float(self.rect.x) self.move_right = False self.move_left = False self.shoot_delay = 1000 self.last = pygame.time.get_ticks() self.weapon = Weapon() def draw(self): self.weapon.draw(self.screen) self.screen.blit(self.image, self.rect) def update(self): if self.move_right and self.rect.x + self.rect.width - 15 < self.screen_rect.width: print(self.speed) self.x += self.speed elif self.move_left and self.rect.x + 15 > 0: print(self.speed) self.x -= self.speed else: self.speed = 4 self.rect.x = self.x self.weapon.update() def shoot(self): now = pygame.time.get_ticks() if now - self.last > self.shoot_delay: self.last = now self.weapon.shoot(self.rect.x + 25, self.rect.y) def check_collision(self, object1, object2): if(object1.rect.x < object2.rect.x + object2.rect.width and object1.rect.x + object1.rect.width > object2.rect.x and object1.rect.y < object2.rect.y + object2.rect.height and object1.rect.y + object1.rect.height> object2.rect.y): return True
def update(self, *args): Weapon.update(self, *args) # if self.cooldown > 0: # self.cooldown -= 1 # return self.cooldown = 1 if self.engaged: bv = (self.target_pos - self.pos).normal * 2000 bp = self.pos if bv.x != 0 or bv.y != 0: self.fire_sound.play() # jitter bv.x += random.randrange(-100,100) bv.y += random.randrange(-100,100) bullet.pool.fire(bp.x, bp.y, bv.x, bv.y)
def update(self, *args): Weapon.update(self, *args) # if self.cooldown > 0: # self.cooldown -= 1 # return self.cooldown = 1 if self.engaged: bv = (self.target_pos - self.pos).normal * 2000 bp = self.pos if bv.x != 0 or bv.y != 0: self.fire_sound.play() # jitter bv.x += random.randrange(-100, 100) bv.y += random.randrange(-100, 100) bullet.pool.fire(bp.x, bp.y, bv.x, bv.y)
def update(self, *args): Weapon.update(self, *args) if self.cooldown > 0: self.cooldown -= 1 return self.cooldown = 5 if self.engaged: bv = (self.target_pos - self.pos).normal * 1400 bv2 = bv.rotated(8) bv3 = bv.rotated(-8) bp = self.pos if bv.x != 0 or bv.y != 0: self.fire_sound.play() bullet.pool.fire(bp.x, bp.y, bv.x, bv.y) bullet.pool.fire(bp.x, bp.y, bv2.x, bv2.y) bullet.pool.fire(bp.x, bp.y, bv3.x, bv3.y)
class Player(pygame.sprite.Sprite): def __init__(self, image_name='player.png'): super(Player, self).__init__() self.image = pygame.image.load(IMAGES_PATH + image_name) self.rect = self.image.get_rect() self.weapon = Weapon() self.moving_left = False self.moving_right = False self.lives = STARTING_LIVES self.set_position() self.is_alive = True def shoot(self): if self.weapon.is_active: return self.weapon = Weapon(self.rect.centerx, self.rect.top) self.weapon.is_active = True def update(self): if self.moving_left and self.rect.left >= 0: self.rect = self.rect.move(-PLAYER_SPEED, 0) if self.moving_right and self.rect.right <= WINDOWWIDTH: self.rect = self.rect.move(PLAYER_SPEED, 0) if self.weapon.is_active: self.weapon.update() def set_position(self, x=WINDOWWIDTH / 2, y=WINDOWHEIGHT): self.rect.centerx, self.rect.bottom = x, y self.weapon.is_active = False def reload(self): self.weapon.is_active = False def stop_moving(self): self.moving_left = self.moving_right = False def position(self): return self.rect.centerx def can_shoot(self): return not self.weapon.is_active
class Ship(Movable): """The player controlled ship""" def __init__(self, pos, screen, size, props, player_number, level): super().__init__(pos, screen, size) self.name = "player_ship#" + str(player_number) #TODO: balance these! self.f_drag = 0.995 self.base_speed = 4.5 self.base_thrust = 1.3 self.base_rot = 3.8 self.base_bullet_speed = 6.4 self.base_shield = 1.0 self.base_disruptor = 1.0 self.base_hyperspace = 1.0 self.props = props self.player_number = player_number self.level = level #TODO the values are unchecked image_name = "pics/" + props.color + ".png" self.image = pygame.image.load(image_name) #TODO: subject to change! #bools for moving by input self.b_rotating_right = False self.b_rotating_left = False self.b_thrusting = False self.b_is_shooting = False self.b_using_special = False self.targets = [level.comets, level.smilies, level.enemy_ships] #TODO: balance hp and size, speed, image and sound here self.weapon = Weapon(self, (5, 5), 120, 2.0, 13, "pics/bullet_dummy.png", self.targets, "TODO:soundfile") self.lives = 5 #constant from the original, very first spawn reduces this to 4, 0 lives is still alive self.spawn_cooldown = 180 #TODO balance me, display? self.cur_spawn_cooldown = 0 #TODO change? #pls just call this once.. def enable_friendly_fire(self, player_ships): self.targets.append(player_ships) self.weapon.targets.append(player_ships) #need to update there as well def blitme_impl(self): """drawing the current ship ()and it's bullets via the weapon)""" self.weapon.blitme() #drawing projectiles before, so ship is on top angle = math.degrees( math.acos(np.dot(np.array([0.0, -1.0]), self.v_facing))) if self.v_facing[0] > 0: angle = -angle rotated_img_rect = util.rot_center(self.image, self.rect, angle) self.screen.blit(rotated_img_rect[0], rotated_img_rect[1]) #TODO: add color from properties def update_impl(self): """updating the weapon and the thrust/rotation of the ship based on pressed keys and velocity""" self.weapon.update() if not self.hidden: if self.b_rotating_left and self.b_rotating_right: pass #both cancel each other out, but this should not really happen elif self.b_rotating_left: angle = self.base_rot * self.props.f_rot_speed self.v_facing = util.rotate_v(self.v_facing, -angle, True) #notice the '-' for rotating the other way elif self.b_rotating_right: angle = self.base_rot * self.props.f_rot_speed self.v_facing = util.rotate_v(self.v_facing, angle, True) if self.b_thrusting: #TODO: check and balance this added_thrust = self.v_facing * self.props.f_thrust * self.base_thrust #print("added thrust: " + str(added_thrust)) self.v_moving += added_thrust current_speed = util.mag_v(self.v_moving) max_speed = self.base_speed * self.props.f_max_speed if current_speed > max_speed: self.v_moving = (self.v_moving / current_speed) * max_speed else: #TODO I need to factor in hyperspace once I implement it HERE (hyperspace needs hidden = True for no collide) if self.lives >= 0: if self.cur_spawn_cooldown > 0: self.cur_spawn_cooldown -= 1 else: if self.spawn_location_is_free(): self.v_facing = np.array( [0.0, -1.0]) # everything starts facing upwards self.v_moving = np.array( [0.0, 0.0]) # everything starts by not moving self.spawn() else: print("You are dead, please implement this!") #TODO do this def spawn_location_is_free(self): return True #TODO implement this def killme_impl(self, v_killer=None, killer=None): self.lives -= 1 self.cur_spawn_cooldown = self.spawn_cooldown
class Hero(Player): def __init__(self, game_settings, screen, hero, weapon): path = '../resources/' + hero + '/' + hero + '_m' self.name = hero super().__init__(game_settings, screen, path) self.rect.centerx = self.screen_rect.centerx / 3 self.rect.bottom = self.screen_rect.bottom - game_settings.floor self.center = float(self.rect.centerx) self.hit_sound = pygame.mixer.Sound( '../resources/heroes/sword_stab-18.wav') self.swing_sound = pygame.mixer.Sound( '../resources/heroes/sword_swing-18.wav') self.hit = 0 self.hp = self.baseHp = self.mana = self.baseMana = 0 # Sets character hp/mana/weapon through dictionaries in settings for char in game_settings.characters: if hero == char['NAME']: self.hp = self.baseHp = char['HP'] if weapon in char["WEAPONS"]: self.weapon = Weapon(screen, game_settings, self.rect, weapon) else: self.weapon = Weapon(screen, game_settings, self.rect, char['WEAPONS'][0]) if hero not in [char['NAME'] for char in game_settings.characters]: self.name = hero = game_settings.characters[0]['NAME'] self.hp = self.baseHp = game_settings.characters[0]['HP'] self.weapon = Weapon(screen, game_settings, self.rect, game_settings.characters[0]['WEAPONS'][0]) self.npc = False self.ui = UI(screen, game_settings) def left(self): super().left() self.weapon.face_left() def right(self): super().right() self.weapon.face_right() def use_weapon(self): self.weapon.using = True if not self.weapon.collision: self.swing_sound.play(0, 2000, 1000) def check_collision(self, sprite): if pygame.sprite.collide_mask(self.weapon, sprite): self.collision = True self.weapon.collision = True self.hit %= 5 if self.weapon.using and self.hit == 1: self.hit_sound.play(0, 2000, 1000) sprite.hp -= self.weapon.damage if sprite.hp < 0: sprite.hp = 0 self.hit += 1 else: self.weapon.collision = False def update(self): super().update() self.weapon.update(self.rect, self.rect.centery, self.facing_right) def blitme(self): self.ui.blitme((self.hp / self.baseHp)) self.weapon.blitme() super().blitme()
class Hero(): def __init__(self, screen, map_, settings): self.screen = screen self.map = map_ self.settings = settings self.enemy_bullet_image = pygame.image.load('images/laser/bg_bullet.png') self.blood_image = pygame.image.load('images/heart.ico') self.magic_image = pygame.image.load('images/blue_heart.png') self.blood_rect = self.blood_image.get_rect() self.magic_rect = self.magic_image.get_rect() self.magic_rect.top += 50 #加载动画 self.frame_order = 0 #正播放的帧序号 self.frame_size = 5 #代表一个图片要放的帧数目 self.basic_frame_size = 5 #基本帧数目 self.jump_frame_size = [2,2,2,2,5,5,2,5, 5,10,15,25,2,2,2,2,2,] #用于调节跳跃动作的帧数目 # [0,1,2,3,4,5,6,7, 8, 9, 0, 1, 2,3,4,5,6,] self.image_order = 0 #正播放的图片序号 self.move_size = [6, 12, 6] #移动图片的总数目 6,12,6 self.attack_size = [11, 8, 0] # 11, 11, 11 self.jump_size = 17 # 17, 17, 17 self.jump_attack_size = [17, 17, 0] #17, 17, 17 self.fire_magic_size = [8, 8, 0] self.hurt_size = 4 # 4, 4, 4 self.squat_move_size = 10 self.squat_attack_size = 9 self.weapon_size = self.settings.hero_weapon_size #images[direction][weapon]代表一个图片或图片文件夹或空 self.stay_images = {} self.move_images = {} self.attack_images = {} self.jump_images = {} self.jump_attack_images = {} self.fire_magic_images = {} self.hurt_images = {} self.frame_num = 0 #代表人物图片的外框的数量,等同于图片数量 # self.squat_images = {} # self.squat_attack_images = {} # self.squat_move_images = {} self.image_to_frame = {} self.load_images() # for i in range(len(self.image_to_frame[self.jump_attack_images[1][0][9]].frame)): # print(i, self.image_to_frame[self.jump_attack_images[1][0][9]].frame[i]) # 初始化人物 self.weapon = self.settings.hero_weapon["fist"] self.status = self.settings.hero_status["stay"] self.direction = self.settings.hero_direction["right"] self.image = self.stay_images[self.direction][self.weapon] self.rect = self.image.get_rect() self.rect.centerx = self.settings.hero_init_centerx self.x = self.settings.left_border + self.rect.centerx #在整个地图中的位置 self.rect.bottom = self.map.gety(self.rect.centerx) self.moving_left = False self.moving_right = False self.getting_hurt = False self.attacking = False self.fire_magicing = False self.jumping = False self.squating = False self.falling = False self.weapon_attacks = Weapon(self.screen, self.settings) self.weapon_en = { self.settings.hero_weapon["fist"] : True, self.settings.hero_weapon["sword"] : False, self.settings.hero_weapon["gun"] : False, } self.blood = 0 self.magic = self.settings.hero_init_magic self.magic_level = 0 self.magic_cd_time = 300 self.money = 999 self.jump_en = 1 # 1代表可以跳跃 self.shoot_cd = 0 # 射击冷却时间,0时才能进行射击 self.magic_cd = 0 # 技能冷却时间 self.blood_cd = 200 # 暴血状态,非0时代表无敌 self.speedy = 8 self.speedx = 4 self.velocityx = 0 self.velocityy = -self.speedy def start(self): self.weapon = self.settings.hero_weapon["fist"] self.status = self.settings.hero_status["stay"] self.direction = self.settings.hero_direction["right"] self.image = self.stay_images[self.direction][self.weapon] self.rect = self.image.get_rect() self.rect.centerx = self.settings.hero_init_centerx self.x = self.settings.left_border + self.rect.centerx #在整个地图中的位置 self.rect.bottom = self.map.gety(self.rect.centerx) self.blood = self.settings.hero_init_blood self.magic = self.settings.hero_init_magic self.jump_en = 1 # 1代表可以跳跃 self.shoot_cd = 0 # 射击冷却时间,0时才能进行射击 self.magic_cd = 0 # 技能冷却时间 self.blood_cd = 200 # 暴血状态,非0时代表无敌 self.speedy = 8 self.speedx = 4 self.velocityx = 0 self.velocityy = -self.speedy def restart(self, x): self.x = x self.settings.left_border = max(int(self.x - 50), 0) # self.bottom = self. def update_status(self): #根据旧状态即status的值继续状态;或者根据按键(即or后面)更改状态.更新image #可以改变方向的只有 移动键和受伤 self.frame_size = self.basic_frame_size if self.status == self.settings.hero_status["hurt"]: #受伤的优先级最高, 要更新图形 self.hurt_image() elif self.status == self.settings.hero_status["fire_magic"]: self.fire_magic_image() elif self.status == self.settings.hero_status["attack"] : #攻击动画 self.attack_image() elif self.status == self.settings.hero_status["jump_attack"] : #跳起攻击动画 self.jump_attack_image() elif self.status == self.settings.hero_status["squat_attack"] : #下蹲攻击动画 self.squat_attack_image() elif self.fire_magicing == True and self.magic_cd == 0 \ and self.weapon != self.settings.hero_weapon["gun"]: self.image_order = 0 self.frame_order = 0 self.status = self.settings.hero_status["fire_magic"] elif self.attacking and self.weapon != self.settings.hero_weapon["gun"]: #当按下攻击键时,进入攻击状态 if self.status == self.settings.hero_status["jump"] : self.status = self.settings.hero_status["jump_attack"] elif self.status == self.settings.hero_status["squat"]: self.frame_order = 0 self.image_order = 0 self.status = self.settings.hero_status["squat_attack"] else : self.frame_order = 0 self.image_order = 0 self.status = self.settings.hero_status["attack"] elif self.status == self.settings.hero_status["jump"] : # 跳起 self.jump_image() # elif self.status == self.settings.hero_status["squat_move"]: # #蹲着移动 # self.squat_move() # elif self.squating : # #下蹲键, 按着蹲下键时,无法跳跃,即按跳起键无效。当此时有移动按键时,将变成蹲着移动 # self.status = self.settings.hero_status["squat"] # self.squat_image() elif self.jumping : #跳跃键 self.image_order = 0 self.status = self.settings.hero_status["jump"] elif self.status == self.settings.hero_status["move"] : # 最后是移动 self.move_image() elif self.moving_left != self.moving_right : # 进入移动状态 self.status = self.settings.hero_status["move"] if self.moving_left == True: self.direction = self.settings.hero_direction["left"] elif self.moving_right == True: self.direction = self.settings.hero_direction["right"] else : #self.status == self.settings.hero_status["stay"] # 静止状态 self.status = self.settings.hero_status["stay"] self.image_order = 0 self.frame_order = 0 self.velocityx = 0 self.velocityy = self.speedy self.stay_image() #重置 if self.status != self.settings.hero_status["hurt"]: if self.weapon == self.settings.hero_weapon["gun"] and self.attacking: #gun无攻击状态 # self.attacking = False self.shoot_bullet() if self.shoot_cd > 0: self.shoot_cd -= 1 if self.blood_cd > 0: self.blood_cd -= 1 if self.magic_cd > 0: self.magic_cd -= 1 if self.weapon != self.settings.hero_weapon["gun"]: self.attacking = False self.jumping = False self.fire_magicing = False def get_hurt(self, direction): # 发生碰撞时,调用的接口函数, # 更新人物方向,设置人物状态,direction表示攻击的来源方向 # 若人物已经受伤,不再受伤 if self.status != self.settings.hero_status["hurt"] and self.blood_cd == 0: self.direction = direction self.status = self.settings.hero_status["hurt"] self.image_order = 0 self.frame_order = 0 self.blood_cd = 200 self.blood -= 1 if self.blood <= 0 : pass #播放动画 def hurt_image(self): #受伤动画,播完动画则结束受伤状态 self.velocityx = - self.direction * self.speedx self.velocityy = self.speedy self.change_image(self.hurt_images[self.direction][self.weapon][self.image_order]) self.display_frame(self.hurt_size) def attack_image(self): #攻击动画 self.velocityx = 0 self.velocityy = self.speedy self.change_image(self.attack_images[self.direction][self.weapon][self.image_order]) self.display_frame(self.attack_size[self.weapon]) def jump_attack_image(self): #跳起时进行攻击 # 调节帧数目 self.frame_size = self.jump_frame_size[self.image_order] if self.moving_left == True and self.moving_right == False: self.velocityx = -self.speedx elif self.moving_left == False and self.moving_right == True: self.velocityx = self.speedx else : self.velocityx = 0 if self.image_order < 6 : self.velocityx = 0 elif self.image_order >= 6 and self.image_order <= 7: self.velocityy = -self.speedy elif self.image_order >= 8 and self.image_order <= 10: self.velocityy = -self.speedy elif self.image_order == 11: self.velocityy = self.speedy else : self.velocityy = self.speedy self.change_image(self.jump_attack_images[self.direction][self.weapon][self.image_order]) self.display_frame(self.jump_attack_size[self.weapon]) def jump_image(self): #跳跃动画 #self.velocityx 随移动键改变 self.frame_size = self.jump_frame_size[self.image_order] if self.moving_left == True and self.moving_right == False: self.direction = self.settings.hero_direction["left"] self.velocityx = -self.speedx elif self.moving_left == False and self.moving_right == True: self.direction = self.settings.hero_direction["right"] self.velocityx = self.speedx else : self.velocityx = 0 # 调节帧数目 if self.image_order < 6 : self.velocityx = 0 elif self.image_order >= 6 and self.image_order <= 7: self.velocityy = -self.speedy elif self.image_order >= 8 and self.image_order <= 10: self.velocityy = -self.speedy elif self.image_order == 11: self.velocityy = self.speedy else : self.velocityy = self.speedy self.change_image(self.jump_images[self.direction][self.weapon][self.image_order]) self.display_frame(self.jump_size) def fire_magic_image(self): self.velocityx = 0 self.velocityy = self.speedy self.change_image(self.fire_magic_images[self.direction][self.weapon][self.image_order]) self.display_frame(self.fire_magic_size[self.weapon]) def move_image(self): #移动动画, 如果是状态发生改变 if self.direction == self.settings.hero_direction["left"] and \ self.moving_left == True and self.moving_right == False : self.velocityx = self.speedx * self.direction elif self.direction == self.settings.hero_direction["right"] and \ self.moving_right == True and self.moving_left == False : self.velocityx = self.speedx * self.direction else : self.velocityx = 0 self.velocityy = self.speedy #动画未播放完整,继续动画 self.change_image(self.move_images[self.direction][self.weapon][self.image_order]) self.display_frame(self.move_size[self.weapon]) def stay_image(self): self.change_image(self.stay_images[self.direction][self.weapon]) # def squat_image(self): # #下蹲动画,有方向时变成滚动了 # if self.moving_left != self.moving_right : # self.status = self.settings.hero_status["squat_move"] # if self.moving_left == True: # self.direction = self.settings.hero_direction["left"] # elif self.moving_right == True: # self.direction = self.settings.hero_direction["right"] # self.change_image(self.squat_right_image) # def squat_move(self): # self.velocityx = 2 * self.speedx * self.direction # self.velocityy = -self.speedy # self.change_image(self.squat_move_images[self.direction][self.weapon][self.image_order]) # self.display_frame(self.squat_move_size) # def squat_attack_image(self): # self.change_image(self.squat_attack_images[self.direction][self.weapon][self.image_order]) # self.display_frame(self.squat_attack_size) # def update_pos(self): # self.update_herox() # self.update_heroy() # def update_herox(self): # if self.map.gety(self.x + self.velocityx * 2) < self.rect.bottom : # self.velocityx = 0 # if (self.x > self.settings.left_border and self.x < self.settings.left_border + self.settings.screen_width) \ # or (self.x <= self.settings.left_border and self.velocityx > 0)\ # or (self.velocityx < 0 and self.x >= self.settings.left_border + self.settings.screen_width): # self.x += self.velocityx # if self.settings.map_lock or \ # (self.velocityx > 0 and self.rect.right < self.settings.screen_width/2) or \ # (self.velocityx < 0 and self.rect.left > self.settings.screen_width/10): # self.rect.centerx += self.velocityx # self.map.update(self.velocityx, self.rect) def update_herox_v2(self): if self.map.gety(self.x + self.velocityx * 2) < self.rect.bottom : self.velocityx = 0 if (self.rect.centerx > 0 + self.speedx and self.rect.centerx < self.settings.screen_width - self.speedx) \ or (self.rect.centerx <= self.speedx and self.velocityx > 0) \ or (self.rect.centerx >= self.settings.screen_width - self.speedx and self.velocityx < 0): self.x += self.velocityx def update_centerx(self): self.rect.centerx = self.x - self.settings.left_border def update_heroy(self, x): #跳起与坠落 self.rect.bottom += self.velocityy if self.rect.bottom > self.map.gety(self.x): self.rect.bottom = self.map.gety(self.x) if self.rect.bottom == self.settings.BOTTOM_NUM: if self.blood_cd == 0: self.blood -= 1 # 重新定位 if self.blood > 0: self.restart(x) else : pass #游戏结束 # self.x = 50 #print(self.x, self.rect.bottom, self.map.gety(self.x)) def check_collision(self, monster_list, tool_list): #碰撞检测, 碰撞到地图, 道具, 拳头攻击到敌人, 敌人攻击 #遇到不同颜色,先检查道具,看对应的位置的颜色是否一样,一样则是接触到了道具 #再检测是不是正在进行拳头攻击,是的话,某些位置不会成为攻击矩形 #否则受到攻击 frame = self.image_to_frame[self.image] del_tool_list = [] #接触到的道具, 要在最后删除 for y in range(frame.frame_rect["top"], frame.frame_rect["bottom"]): for direction, xs in frame.frame[y].items() : for x in xs : pos = (self.rect.left + x, self.rect.top + y) if pos[0] < 0 or pos[0] >= self.settings.screen_width or \ pos[1] < 0 or pos[1] >= self.settings.screen_height : continue color = self.screen.get_at(pos) if color != self.settings.hero_boot_color: #先检测碰撞对象 touch_object = self.touch_object(pos, color, monster_list, tool_list, del_tool_list) #检测碰撞对象 if touch_object == "food" : #道具名称 self.blood += 1 self.blood_en = 50 elif touch_object == "sword" : self.weapon_en["sword"] = True elif touch_object == "gun" : self.weapon_en["gun"] = True elif touch_object == "bullet" : self.get_hurt(self.settings.hero_direction[direction]) elif touch_object == "enemy" : # 碰撞到敌人 if self.weapon == self.settings.hero_weapon["fist"] \ and self.status == self.settings.hero_status["attack"] \ and self.image_order >= 5 and self.image_order <= 7 \ and self.direction == self.settings.hero_direction[direction] and \ y >= 44 and y <= 59: #特殊情况 拳头部分 pass elif self.weapon == self.settings.hero_weapon["fist"] and \ self.status == self.settings.hero_status["jump_attack"] and \ self.image_order >= 9 and self.image_order <= 12 and \ self.direction == self.settings.hero_direction[direction] and \ y >= 97 and y <= 112: pass else : # print(x, y, self.image_order, self.status) # print(pos, pos[0]+self.settings.left_border, self.map.gety(pos[0]+self.settings.left_border)) # print(self.x, self.rect.bottom, self.map.gety(self.x)) self.get_hurt(self.settings.hero_direction[direction]) for i in del_tool_list: tool_list.pop(i) def touch_object(self, pos, color, monster_list, tool_list, del_tool_list): # 判断接触到了什么 ? 道具, 地图, 技能, 子弹, 敌人 (x, y) = pos #检测碰撞到血槽和蓝 if y < 50 and x < self.blood * 50 : return "blood" elif y < 100 and x < 50: return "blue" #检测道具 for i in range(len(tool_list)) : if x >= tool_list[i].rect.left and x < tool_list[i].rect.right \ and y >= tool_list[i].rect.top and y < tool_list[i].rect.bottom : if i in del_tool_list : return "nothing" elif i not in del_tool_list \ and color == tool_list[i].bg_image.get_at((x - tool_list[i].rect.left, y - tool_list[i].rect.top)): name = tool_list[i].name del_tool_list.append(i) return name # 检测地图 if color == self.settings.map_color: # 当这个坐标在地图以下时,就是接触到地图了,有可能是一条垂直线 # for distance in range(-2, 3): # if self.map.gety(self.settings.left_border + x + distance) <= y : # return "map" if self.map.gety(self.settings.left_border + x - 1) <= y \ or self.map.gety(self.settings.left_border + x) <= y \ or self.map.gety(self.settings.left_border + x + 1) <= y : return "map" # 检测自己的魔法 if self.weapon_attacks.fist_magic_firing == True : if x >= self.weapon_attacks.fist_magic_rect.left and x < self.weapon_attacks.fist_magic_rect.right and \ y >= self.weapon_attacks.fist_magic_rect.top and y < self.weapon_attacks.fist_magic_rect.bottom : magic_pos = (x - self.weapon_attacks.fist_magic_rect.left, y - self.weapon_attacks.fist_magic_rect.top) if color == self.weapon_attacks.fist_magic_images[self.weapon_attacks.image_order].get_at(magic_pos): return "magic" elif self.weapon_attacks.sword_magic_firing == True : if x >= self.weapon_attacks.sword_magic_rect.left and x < self.weapon_attacks.sword_magic_rect.right and \ y >= self.weapon_attacks.sword_magic_rect.top and y < self.weapon_attacks.sword_magic_rect.bottom : magic_pos = (x - self.weapon_attacks.sword_magic_rect.left, y - self.weapon_attacks.fist_magic_rect.top) if color == self.weapon_attacks.sword_magic_images[self.weapon_attacks.image_order].get_at(magic_pos): return "magic" # 检测敌人子弹 for monster in monster_list : if type(monster) == MonsterPlane and monster.bullet_list: is_bullet = False for i in range(len(monster.bullet_list)): # 如果和英雄碰撞,加入删除列表 if monster.bullet_alive_list[i]: if x >= monster.bullet_rect_list[i].left and x < monster.bullet_rect_list[i].right and \ y >= monster.bullet_rect_list[i].top and y < monster.bullet_rect_list[i].bottom : bullet_pos = (x - monster.bullet_rect_list[i].left, y - monster.bullet_rect_list[i].top) if color == self.enemy_bullet_image.get_at(bullet_pos): is_bullet = True monster.bullet_alive_list[i] = False if is_bullet: return "bullet" # 碰撞到敌人身体 return "enemy" def update_weapon_attack(self): self.weapon_attacks.update(self.magic_level) # 初始化各种攻击范围. 技能,普通攻击,跳跃攻击. (均可分为拳头和剑两种武器) if self.status == self.settings.hero_status["fire_magic"]: if self.weapon == self.settings.hero_weapon["fist"] \ and self.image_order == self.fire_magic_size[self.weapon] - 2 \ and self.frame_order == 0 and self.magic_cd == 0 : play_short_music("music/m3.wav") # 播放音效 self.magic -= 1 # 扣一点蓝 self.magic_cd = self.magic_cd_time # 冷却时间为300帧 self.weapon_attacks.image_order = 0 # 技能开始播放的帧序号 self.weapon_attacks.fist_magic_playing = True # 设置技能动画播放为True self.weapon_attacks.fist_magic_firing = True # 设置技能伤害为True,命中或过时后为失效 if self.direction == self.settings.hero_direction["left"] : # 设置技能动画位置 self.weapon_attacks.fist_magic_rect.right = self.rect.left - 100 elif self.direction == self.settings.hero_direction["right"] : self.weapon_attacks.fist_magic_rect.left = self.rect.right + 100 self.weapon_attacks.fist_magic_centerx = self.settings.left_border + self.weapon_attacks.fist_magic_rect.centerx self.weapon_attacks.fist_magic_rect.bottom = self.map.gety(self.weapon_attacks.fist_magic_centerx) if self.weapon_attacks.fist_magic_rect.bottom > self.settings.screen_height: self.weapon_attacks.fist_magic_rect.bottom = self.settings.screen_height # 初始化攻击范围 self.weapon_attacks.fist_magic.height = 1 # 初始化技能伤害范围, 随动画图片变化 self.weapon_attacks.fist_magic.width = 1 self.weapon_attacks.fist_magic.centerx = self.weapon_attacks.fist_magic_rect.centerx elif self.weapon == self.settings.hero_weapon["sword"] \ and self.image_order == self.fire_magic_size[self.weapon] - 2 \ and self.frame_order == 0 and self.magic_cd == 0: play_short_music("music/m4.wav") self.magic -= 1 self.magic_cd = self.magic_cd_time self.weapon_attacks.image_order = 0 self.weapon_attacks.sword_magic_playing = True self.weapon_attacks.sword_magic_firing = True if self.direction == self.settings.hero_direction["left"] : self.weapon_attacks.sword_magic_rect.right = self.rect.left elif self.direction == self.settings.hero_direction["right"] : self.weapon_attacks.sword_magic_rect.left = self.rect.right self.weapon_attacks.sword_magic_centerx = self.settings.left_border + self.weapon_attacks.sword_magic_rect.centerx self.weapon_attacks.sword_magic_rect.centery = self.rect.top + 60 self.weapon_attacks.sword_magic.height = 80 self.weapon_attacks.sword_magic.width = 100 self.weapon_attacks.sword_magic.center = self.weapon_attacks.sword_magic_rect.center elif self.status == self.settings.hero_status["attack"]: self.weapon_attacks.fist.width = 130 self.weapon_attacks.fist.height = 16 self.weapon_attacks.fist.top = self.rect.top + 44 if self.direction == self.settings.hero_direction["left"] : self.weapon_attacks.fist.right = self.rect.centerx elif self.direction == self.settings.hero_direction["right"] : self.weapon_attacks.fist.left = self.rect.centerx self.weapon_attacks.sword["centerx"] = self.rect.centerx + 60 * self.direction self.weapon_attacks.sword["centery"] = self.rect.bottom - 150 self.weapon_attacks.sword["radius"] = 85 self.weapon_attacks.sword["direction"] = self.direction if self.weapon == self.settings.hero_weapon["fist"] and self.image_order >= 5 and self.image_order <= 6: if self.frame_order == 0 and self.image_order == 5 : # 初始化攻击, 命中后失效 self.weapon_attacks.fist_attacking = True self.weapon_attacks.sword_attacking = False elif self.weapon == self.settings.hero_weapon["sword"] and self.image_order >= 1 and self.image_order <= 5: if self.frame_order == 0 and self.image_order == 1: self.weapon_attacks.fist_attacking = False self.weapon_attacks.sword_attacking = True else : self.weapon_attacks.fist_attacking = False self.weapon_attacks.sword_attacking = False elif self.status == self.settings.hero_status["jump_attack"]: self.weapon_attacks.fist.width = 110 self.weapon_attacks.fist.height = 16 self.weapon_attacks.fist.top = self.rect.top + 97 if self.direction == self.settings.hero_direction["left"]: self.weapon_attacks.fist.right = self.rect.centerx elif self.direction == self.settings.hero_direction["right"]: self.weapon_attacks.fist.left = self.rect.centerx self.weapon_attacks.sword["centerx"] = self.rect.centerx + 70 * self.direction self.weapon_attacks.sword["centery"] = self.rect.bottom - 90 self.weapon_attacks.sword["radius"] = 85 self.weapon_attacks.sword["direction"] = self.direction if self.weapon == self.settings.hero_weapon["fist"] and self.image_order >= 9 and self.image_order <= 11: if self.frame_order == 0 and self.image_order == 9 : self.weapon_attacks.fist_attacking = True self.weapon_attacks.sword_attacking = False elif self.weapon == self.settings.hero_weapon["sword"] and self.image_order >= 8 and self.image_order <= 12: if self.frame_order == 0 and self.image_order == 8 : self.weapon_attacks.fist_attacking = False self.weapon_attacks.sword_attacking = True else : self.weapon_attacks.fist_attacking = False self.weapon_attacks.sword_attacking = False else : self.weapon_attacks.fist_attacking = False self.weapon_attacks.sword_attacking = False # def update(self, monster_list, tool_list): # self.check_collision(monster_list, tool_list) # self.update_status() # self.update_pos() # self.update_weapon_attack() def update1_v2(self, monster_list, tool_list): self.check_collision(monster_list, tool_list) self.update_status() self.update_herox_v2() def update2_v2(self, x): # 用于保证人物坐标和地图坐标同步 self.update_centerx() self.update_heroy(x) self.update_weapon_attack() def change_weapon(self, weapon_order): #更换武器,保证更换武器后不会有动作冲突 if self.weapon_en[weapon_order] == True: self.weapon = weapon_order # self.weapon = (self.weapon + 1) % self.weapon_size # while self.weapon_en[self.weapon] == False : # self.weapon = (self.weapon + 1) % self.weapon_size if self.status == self.settings.hero_status["move"] and self.image_order >= 6: self.image_order -= 6 if self.status == self.settings.hero_status["fire_magic"] : self.status = self.settings.hero_status["stay"] if self.weapon == self.settings.hero_weapon["gun"]: #持枪时无攻击状态 if self.status == self.settings.hero_status["attack"] : self.status = self.settings.hero_status["stay"] elif self.status == self.settings.hero_status["jump_attack"]: self.status = self.settings.hero_status["jump"] if self.status == self.settings.hero_status["attack"] and self.image_order >= 8: self.image_order = 7 def shoot_bullet(self): #发射子弹 if self.shoot_cd > 0: #无法发射子弹 return if self.direction == self.settings.hero_direction["right"]: bullet_velocity = self.speedx * 2 bullet_pos = [] bullet_pos.append(self.rect.right + 3*self.speedx) elif self.direction == self.settings.hero_direction["left"]: bullet_velocity = -self.speedx * 2 bullet_pos = [] bullet_pos.append(self.rect.left - 5*self.speedx) else : return if self.status == self.settings.hero_status["stay"]: #不同状态中,枪的纵坐标不同 bullet_pos.append(self.rect.bottom - 167) elif self.status == self.settings.hero_status["move"]: bullet_pos.append(self.rect.bottom - 175) elif self.status == self.settings.hero_status["jump"]: bullet_pos.append(self.rect.top + 40) else : return new_bullet = Bullet(self.screen, self.settings, bullet_pos, bullet_velocity) self.weapon_attacks.bullets.append(new_bullet) self.shoot_cd = 50 def display_frame(self, image_size): #播放帧 self.frame_order += 1 if self.frame_order >= self.frame_size: #切换图片 self.frame_order = 0 self.image_order += 1 if self.image_order >= image_size: self.image_order = 0 if self.squating: self.status = self.settings.hero_status["squat"] else: self.status = self.settings.hero_status["stay"] def change_image(self, image): #确保切换图片后,位置没有变 rect_centerx = self.rect.centerx rect_bottom = self.rect.bottom rect_top = self.rect.top self.image = image self.rect = self.image.get_rect() self.rect.centerx = rect_centerx self.rect.bottom = rect_bottom if self.status == self.settings.hero_status["jump"] or self.status == self.settings.hero_status["jump_attack"]: if self.image_order == 7: self.rect.top = rect_top # if self.rect.bottom > self.settings.screen_height + 300: # self.rect.bottom = self.settings.screen_height + 300 def blitme(self): # 绘制图片到屏幕 if self.blood_cd % 10 < 5 : self.screen.blit(self.image, self.rect) self.weapon_attacks.blitme() # 绘制血条,技能冷却时间 for i in range(self.blood): self.blood_rect.left = i * 50 self.screen.blit(self.blood_image, self.blood_rect) if self.magic_cd == 0: # pygame.draw.circle(Surface, color, pos , raduis, width) pygame.draw.circle(self.screen, (30,30,205, 105), (25, 75), 25) else : # pygame.draw.arc(Surface, color, Rect, start_angle, stop_angle, width=1) -> Rect pygame.draw.arc(self.screen, (0,0,255), (0,50,50,50), 0, ((self.magic_cd)/180)*math.pi, 20) def load_image_file(self, direction, weapon, images, images_path, images_size): #加载图片文件夹 images[self.settings.hero_direction[direction]].append([]) for i in range(0, images_size): num = str(i) if images_size >= 10 and i < 10: num = '0' + str(i) png_image_path = 'images/' + str(weapon) + '_' + direction + '_' + images_path + '/' + images_path + num + '.png' image = pygame.image.load(png_image_path) # image = image.convert_alpha() # 想要修改透明度,必须改变图片通道 # transparent(image) # 背景透明化 # pygame.image.save(image, png_image_path) # # self.image_to_frame[image] = Frame(image, self.settings) # 描绘人物外框,并对人物图片进行修改 # pygame.image.save(image, png_image_path) # 保存图片 # frame = Frame(image, self.settings) # frame_path = "frames/frame/"+str(self.frame_num) + ".txt" frame_rect_path = "frames/frame_rect/" + str(self.frame_num) + ".txt" self.frame_num += 1 # with open(frame_path,'w') as file_obj: # 将人物外框事先保存在json文件中 # file_obj.write(json.dumps(frame.frame)) # 这样就不用每次开启的时候都要描绘外框 # with open(frame_rect_path,'w') as file_obj: # 减少开启的时间 # file_obj.write(json.dumps(frame.frame_rect)) # with open(frame_path,'r') as file_obj: frame_frame = json.loads(file_obj.read()) with open(frame_rect_path,'r') as file_obj: frame_frame_rect = json.loads(file_obj.read()) self.image_to_frame[image] = Frame(image, self.settings, True, frame_frame, frame_frame_rect) images[self.settings.hero_direction[direction]][weapon].append(image) def load_images(self): #加载图片,图片人物框架 for direction in self.settings.hero_direction.keys() : self.stay_images[self.settings.hero_direction[direction]] = [] self.move_images[self.settings.hero_direction[direction]] = [] self.attack_images[self.settings.hero_direction[direction]] = [] self.jump_images[self.settings.hero_direction[direction]] = [] self.jump_attack_images[self.settings.hero_direction[direction]] = [] self.fire_magic_images[self.settings.hero_direction[direction]] = [] self.hurt_images[self.settings.hero_direction[direction]] = [] for weapon in range(0, self.weapon_size): png_image_path = 'images/' + str(weapon) + '_' + direction + '_stay.png' image = pygame.image.load(png_image_path) # image = image.convert_alpha() # # transparent(image) # 背景透明化 # pygame.image.save(image, png_image_path) # # self.image_to_frame[image] = Frame(image, self.settings) # 描绘人物外框 # pygame.image.save(image, png_image_path) # 保存图片 # frame = Frame(image, self.settings) # frame_path = "frames/frame/"+str(self.frame_num) + ".txt" frame_rect_path = "frames/frame_rect/" + str(self.frame_num) + ".txt" self.frame_num += 1 # with open(frame_path,'w') as file_obj: # 将人物外框事先保存在json文件中 # file_obj.write(json.dumps(frame.frame)) # 这样就不用每次开启的时候都要描绘外框 # with open(frame_rect_path,'w') as file_obj: # 减少开启的时间 # file_obj.write(json.dumps(frame.frame_rect)) with open(frame_path,'r') as file_obj: frame_frame = json.loads(file_obj.read()) with open(frame_rect_path,'r') as file_obj: frame_frame_rect = json.loads(file_obj.read()) self.image_to_frame[image] = Frame(image, self.settings, True, frame_frame, frame_frame_rect) self.stay_images[self.settings.hero_direction[direction]].append(image) self.load_image_file(direction, weapon, self.move_images, 'move_images', self.move_size[weapon]) self.load_image_file(direction, weapon, self.attack_images, 'attack_images', self.attack_size[weapon]) self.load_image_file(direction, weapon, self.jump_images, 'jump_images', self.jump_size) self.load_image_file(direction, weapon, self.jump_attack_images, 'jump_attack_images', self.jump_attack_size[weapon]) self.load_image_file(direction, weapon, self.fire_magic_images, 'fire_magic_images', self.fire_magic_size[weapon]) self.load_image_file(direction, weapon, self.hurt_images, 'hurt_images', self.hurt_size)
def update (self) : if self._has_been_launched : Projectile.update (self) else : Weapon.update (self)