diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..35410cacdc5e87f985c93a96520f5e11a5c822e4 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000000000000000000000000000000..64daf1693b3bc4927c3201b21c769ef0a7ddff82 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..bf2fd389f37daa1e5abfcca9b6d38dcfc8823dd6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a1ed0ee04cb081217c2cee6b78d5e8b7c50ee26 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/snake.iml b/.idea/snake.iml new file mode 100644 index 0000000000000000000000000000000000000000..8e5446ac9594d6e198c2a2923123566d13b94bf9 --- /dev/null +++ b/.idea/snake.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/fights.py b/fights.py index 90d382b22fd6dcb3c96e96daf1dc9bffdbf03daf..12eb1c6df7e49560025076861fac8a42a464a789 100644 --- a/fights.py +++ b/fights.py @@ -1,3 +1,5 @@ +import time + from animations import * from cycle import * @@ -6,6 +8,7 @@ class Obstacles: """ 所有可以伤害到玩家的物品的父类 """ + def __init__(self, map_in): self.map = map_in self.damage = 0 @@ -32,6 +35,7 @@ class Beam(Obstacles): 激光对象,在map_in里pos位置添加一个width宽度length长度color颜色damage伤害的激光, 改激光的朝向是direction,在发射前又pre_t帧的前摇,动画时间为last_t * 2 """ + def __init__(self, map_in, pos, length, direction, width=30, pre_t=100, last_t=6, color=(242, 245, 66), damage=20): Obstacles.__init__(self, map_in) self.damage = damage @@ -55,18 +59,18 @@ class Beam(Obstacles): # 同父类 def collide_with(self, snake): if self.direction == "v": - for i in range(0, len(snake.hit_points)-2, 2): - if not(self.pos[0] - self.width/2 > max(snake.hit_points[i][0], snake.hit_points[i+2][0]) or - self.pos[0] + self.width/2 < min(snake.hit_points[i][0], snake.hit_points[i+2][0])): + for i in range(0, len(snake.hit_points) - 2, 2): + if not (self.pos[0] - self.width / 2 > max(snake.hit_points[i][0], snake.hit_points[i + 2][0]) or + self.pos[0] + self.width / 2 < min(snake.hit_points[i][0], snake.hit_points[i + 2][0])): self.map.animations.append(ParticleExplode(snake.hit_points[i])) self.map.animations.append(ParticleExplode(snake.hit_points[i + 2])) ses[3].play_once() return True elif self.direction == "h": - for i in range(0, len(snake.hit_points)-2, 2): - if not (self.pos[1] - self.width/2 > max(snake.hit_points[i][1], snake.hit_points[i + 2][1]) or - self.pos[1] + self.width/2 < min(snake.hit_points[i][1], snake.hit_points[i + 2][1])): + for i in range(0, len(snake.hit_points) - 2, 2): + if not (self.pos[1] - self.width / 2 > max(snake.hit_points[i][1], snake.hit_points[i + 2][1]) or + self.pos[1] + self.width / 2 < min(snake.hit_points[i][1], snake.hit_points[i + 2][1])): self.map.animations.append(ParticleExplode(snake.hit_points[i])) self.map.animations.append(ParticleExplode(snake.hit_points[i + 2])) ses[3].play_once() @@ -79,7 +83,7 @@ class Beam(Obstacles): if self.width < 100: ses[6].play_once() - if self.tick > self.pre_t + self.last_t*2: + if self.tick > self.pre_t + self.last_t * 2: self.dead = True else: self.tick += 1 @@ -100,17 +104,18 @@ class Beam(Obstacles): (self.point1[0] + offset[0], self.point1[1] + offset[1]), (self.point2[0] + offset[0], self.point2[1] + offset[1]), int(self.speed * (self.tick - self.pre_t))) - elif self.tick < self.pre_t + self.last_t*2: + elif self.tick < self.pre_t + self.last_t * 2: pygame.draw.line(screen, self.color, (self.point1[0] + offset[0], self.point1[1] + offset[1]), (self.point2[0] + offset[0], self.point2[1] + offset[1]), - int(self.speed * (self.pre_t + self.last_t*2 - self.tick))) + int(self.speed * (self.pre_t + self.last_t * 2 - self.tick))) class LastBeam(Obstacles): """ 移动激光,同激光,object_t为跟随移动的目标 """ + def __init__(self, map_in, pos, height, orientation, object_t, width=30, pre_t=100, dur_t=60, last_t=6, color=(242, 245, 66), damage=20): Obstacles.__init__(self, map_in) @@ -139,18 +144,18 @@ class LastBeam(Obstacles): # 同父类 def collide_with(self, snake): if self.orientation == "v": - for i in range(0, len(snake.hit_points)-2, 2): - if not(self.pos[0] - self.width/2 > max(snake.hit_points[i][0], snake.hit_points[i+2][0]) or - self.pos[0] + self.width/2 < min(snake.hit_points[i][0], snake.hit_points[i+2][0])): + for i in range(0, len(snake.hit_points) - 2, 2): + if not (self.pos[0] - self.width / 2 > max(snake.hit_points[i][0], snake.hit_points[i + 2][0]) or + self.pos[0] + self.width / 2 < min(snake.hit_points[i][0], snake.hit_points[i + 2][0])): self.map.animations.append(ParticleExplode(snake.hit_points[i])) self.map.animations.append(ParticleExplode(snake.hit_points[i + 2])) ses[3].play_once() return True elif self.orientation == "h": - for i in range(0, len(snake.hit_points)-2, 2): - if not (self.pos[1] - self.width/2 > max(snake.hit_points[i][1], snake.hit_points[i + 2][1]) or - self.pos[1] + self.width/2 < min(snake.hit_points[i][1], snake.hit_points[i + 2][1])): + for i in range(0, len(snake.hit_points) - 2, 2): + if not (self.pos[1] - self.width / 2 > max(snake.hit_points[i][1], snake.hit_points[i + 2][1]) or + self.pos[1] + self.width / 2 < min(snake.hit_points[i][1], snake.hit_points[i + 2][1])): self.map.animations.append(ParticleExplode(snake.hit_points[i])) self.map.animations.append(ParticleExplode(snake.hit_points[i + 2])) ses[3].play_once() @@ -183,11 +188,11 @@ class LastBeam(Obstacles): (self.point1[0] + offset[0], self.point1[1] + offset[1]), (self.point2[0] + offset[0], self.point2[1] + offset[1]), self.width) - elif self.tick < self.pre_t + self.last_t*2 + self.dur_t: + elif self.tick < self.pre_t + self.last_t * 2 + self.dur_t: pygame.draw.line(screen, self.color, (self.point1[0] + offset[0], self.point1[1] + offset[1]), (self.point2[0] + offset[0], self.point2[1] + offset[1]), - int(self.speed * (self.pre_t + self.last_t*2 + self.dur_t - self.tick))) + int(self.speed * (self.pre_t + self.last_t * 2 + self.dur_t - self.tick))) else: self.dead = True @@ -197,6 +202,7 @@ class Bullet(Obstacles): 子弹,在map_in的x,y位置生成一个damage伤害半径radius的子弹,以vx,vy的速度移动,若one_time为True 则在碰撞后删除自己。 """ + def __init__(self, map_in, damage, radius, x, y, vx, vy, one_time=True): Obstacles.__init__(self, map_in) self.damage = damage @@ -233,21 +239,27 @@ class ExpBall: """ 在pos位置经验为points的经验球 """ + def __init__(self, pos, points=10): self.pos = pos - self.points = points + self.points = random.randint(5,15) #设置水果为随机经验值 self.cycle = Cycle(4, 6) + self.end_time = time.time() + 20 + self.state = random.randint(0,1) #表示2种水果 # 绘制经验球 def draw(self, offset): - screen.blit(texture_lib["food"], (self.pos[0] + offset[0] - 22, self.pos[1] + offset[1] - 22), + if self.state == 0: + screen.blit(texture_lib["food"], (self.pos[0] + offset[0] - 22, self.pos[1] + offset[1] - 22), pygame.Rect(0, self.cycle.get()*45, 45, 45)) - + elif self.state == 1: + screen.blit(texture_lib["banana"], (self.pos[0] + offset[0] - 22, self.pos[1] + offset[1] - 22)) class OneCanon: """ 发射Bullet的大炮 """ + def __init__(self, pos): self.cast = False self.attacking = False @@ -276,7 +288,7 @@ class OneCanon: # 绘制大炮 def draw(self, offset): if self.attacking: - screen.blit(texture_lib["one_cannon"], (self.pos[0]+offset[0], self.pos[1]+offset[1]), + screen.blit(texture_lib["one_cannon"], (self.pos[0] + offset[0], self.pos[1] + offset[1]), pygame.Rect(0, self.attack_ani_cycle.get() * 80, 80, 80)) else: screen.blit(texture_lib["one_cannon"], (self.pos[0] + offset[0], self.pos[1] + offset[1]), @@ -287,6 +299,7 @@ class CrossCanon: """ 十字激光发射器 """ + def __init__(self, pos): self.cast = False self.attacking = False @@ -315,7 +328,7 @@ class CrossCanon: # 绘制激光炮 def draw(self, offset): if self.attacking: - screen.blit(texture_lib["cross_cannon"], (self.pos[0]+offset[0], self.pos[1]+offset[1]), + screen.blit(texture_lib["cross_cannon"], (self.pos[0] + offset[0], self.pos[1] + offset[1]), pygame.Rect(0, self.attack_ani_cycle.get() * 80, 80, 80)) else: screen.blit(texture_lib["cross_cannon"], (self.pos[0] + offset[0], self.pos[1] + offset[1]), @@ -327,6 +340,7 @@ class MovingBeamCannon: 移动激光炮,在map_in的pos位置绘制一个高度为height朝向orientation,向着 direction移动length距离的移动激光炮,前摇为cd """ + def __init__(self, map_in, pos, orientation, direction, length, height, cd=60): self.orientation = orientation self.height = height @@ -345,7 +359,7 @@ class MovingBeamCannon: self.end_tick = cd self.dying = False self.beam = LastBeam(map_in, self.pos, self.height, self.orientation, self, - pre_t=cd-20, last_t=20, dur_t=self.length/self.speed) + pre_t=cd - 20, last_t=20, dur_t=self.length / self.speed) # 获取该激光炮的激光 def get_beam(self): @@ -408,11 +422,12 @@ class CenterSlice(Obstacles): 中心十字旋转,boxed目前没用因为没时间做,本来打算是激光四周是方形的 伤害为damage,以speed速度在map_in旋转,中心是0,0 """ + def __init__(self, map_in, damage, speed, boxed): Obstacles.__init__(self, map_in) self.boxed = boxed self.damage = damage - self.radius = boxed*1.414 + self.radius = boxed * 1.414 self.angle = 0.0 self.speed = speed @@ -453,10 +468,39 @@ class CenterSlice(Obstacles): def collide_with(self, snake): for i in range(0, len(snake.hit_points), 2): for i2 in range(4): - diff = self.angle + (i2*pi/2) - get_angle(snake.hit_points[i][0], snake.hit_points[i][1]) + diff = self.angle + (i2 * pi / 2) - get_angle(snake.hit_points[i][0], snake.hit_points[i][1]) while diff > pi: diff -= pi * 2 if -self.shade < diff < self.shade: self.map.animations.append(ParticleExplode(snake.hit_points[i])) return True return False + +class Barrier(Obstacles): + """ + 在pos位置伤害为damage的障碍 + """ + + def __init__(self,map_in,x,y): + Obstacles.__init__(self, map_in) + self.pos = [x,y] + self.damage = 10 + self.radius = 15 + self.dead = False + self.attack = True + self.bounded = False + self.dead_on_collide = True + + # 绘制障碍 + def draw(self, offset): + screen.blit(texture_lib["barrier"], (self.pos[0] + offset[0] - 20, self.pos[1] + offset[1] - 20)) + + def collide_with(self, snake): + for i in range(0, len(snake.hit_points), 2): + if get_distance(snake.hit_points[i], self.pos) < snake.width + self.radius - 3: + if self.dead_on_collide: + self.dead = True + self.map.animations.append(ParticleExplode(snake.hit_points[i])) + ses[3].play_once() + return True + return False \ No newline at end of file diff --git a/game.py b/game.py index 53d13c6bb139255f3fd35d9ffad2eaa099081173..817f32fcb7b78949f28959c4a1c3ad97dfbc489c 100644 --- a/game.py +++ b/game.py @@ -138,10 +138,20 @@ class Game: elif self.map.is_passed() and self.current_level == self.current_playing: self.current_level += 1 self.menu = LevelSelect(self.current_level) - self.scene = TextScene("win_text") + if self.snake.hp <= 33: + self.scene = TextScene("win_text1") + elif self.snake.hp <= 66: + self.scene = TextScene("win_text2") + else: + self.scene = TextScene("win_text3") elif self.map.is_passed(): self.menu = LevelSelect(self.current_level) - self.scene = TextScene("win_text") + if self.snake.hp <= 33: + self.scene = TextScene("win_text1") + elif self.snake.hp <= 66: + self.scene = TextScene("win_text2") + else: + self.scene = TextScene("win_text3") else: self.scene.update() if self.scene.is_ended(): diff --git a/map.py b/map.py index 3c7c79f0034b74f967d1811f25da4667deae2c63..4034ef1796f725dbcd849472fd89a5e8d2a1ff11 100644 --- a/map.py +++ b/map.py @@ -5,6 +5,7 @@ class Level: """ 关卡父类 """ + def __init__(self): pass @@ -16,8 +17,9 @@ class Level: class Map(Level): """ 地图,存储数据有所有攻击,经验球,动画以及物品(大炮,激光炮等) - per_exp为每个经验球的经验,food_count是场上经验球数量,pass_level是过关等级 + per_exp为每个经验球的经验,food_count是场上经验球数量,pass_level是过关等级,barrior_count是障碍的数量 """ + def __init__(self, game): Level.__init__(self) self.game = game @@ -27,12 +29,12 @@ class Map(Level): self.snake = None self.attacks = [] self.food_count = 5 - self.per_exp = 10 + self.barrior_count = 5 + self.per_exp = random.randint(5, 11) self.pass_level = 1 - self.boarder_cycle = ReCycle(6, 1) - self.animations = [] + self.robots = [] # 判断当前蛇是否死亡 def is_dead(self): @@ -102,51 +104,56 @@ class Map(Level): # 绘制地图上的所有物件 def draw(self, offset): - for i in range(len(self.exp_balls)-1, -1, -1): + for i in range(len(self.exp_balls) - 1, -1, -1): self.exp_balls[i].draw(offset) for i in range(len(self.attacks) - 1, -1, -1): self.attacks[i].draw(offset) for i in range(len(self.objects) - 1, -1, -1): self.objects[i].draw(offset) - for i in range(len(self.animations)-1, -1, -1): + for i in range(len(self.animations) - 1, -1, -1): self.animations[i].draw(offset) if self.snake.outofbound: screen.blit(texture_lib["danger"], (0, 0)) self.draw_boarder(offset) - pass_render = chat_font.render("Target:"+str(self.pass_level), False, (255, 255, 255)) + pass_render = chat_font.render("Target:" + str(self.pass_level), False, (255, 255, 255)) screen.blit(pass_render, (450, 30)) # 更新地图上的所有物品,若有物品为dead则删除物品,同时判断攻击tick,以及经验球与蛇的碰撞 def update(self): - for i in range(len(self.exp_balls)-1, -1, -1): + for i in range(len(self.exp_balls) - 1, -1, -1): if get_distance(self.snake.position, self.exp_balls[i].pos) < 20: self.snake.current_exp += self.exp_balls[i].points ses[2].play_once() del self.exp_balls[i] + # 判断经验球的死亡时间 + for i in range(len(self.exp_balls) - 1, -1, -1): + if self.exp_balls[i].end_time < time.time(): + del self.exp_balls[i] + for i in range(len(self.animations) - 1, -1, -1): if self.animations[i].dead: del self.animations[i] else: self.animations[i].update() - for i in range(len(self.attacks)-1, -1, -1): + for i in range(len(self.attacks) - 1, -1, -1): self.attacks[i].update() if self.attacks[i].attack: if self.attacks[i].collide_with(self.snake): self.snake.hp -= self.attacks[i].damage if self.attacks[i].bounded: if self.attacks[i].pos[0] > self.deme[0] or \ - self.attacks[i].pos[0] < -self.deme[0] or \ - self.attacks[i].pos[1] > self.deme[1] or \ - self.attacks[i].pos[1] < -self.deme[1]: + self.attacks[i].pos[0] < -self.deme[0] or \ + self.attacks[i].pos[1] > self.deme[1] or \ + self.attacks[i].pos[1] < -self.deme[1]: self.attacks[i].dead = True if self.attacks[i].dead: del self.attacks[i] - for i in range(len(self.objects)-1, -1, -1): + for i in range(len(self.objects) - 1, -1, -1): self.objects[i].update() if self.objects[i].dead: del self.objects[i] @@ -154,7 +161,6 @@ class Map(Level): if len(self.exp_balls) < self.food_count: self.exp_balls.append(ExpBall((random.randint(-self.deme[0], self.deme[0]), random.randint(-self.deme[1], self.deme[1])), self.per_exp)) - if (self.snake.position[0] < -self.deme[0] or self.snake.position[0] > self.deme[0] or self.snake.position[1] < -self.deme[1] or @@ -168,6 +174,7 @@ class Level1(Map): """ 第一关,场地为200,200 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 200 @@ -181,14 +188,20 @@ class Level1(Map): return False # 同父类 + # 添加障碍物,数量为5个 def update(self): Map.update(self) + if len(self.attacks) <= 5: + self.attacks.append(Barrier(self, random.randint(-self.deme[0], self.deme[0]), + random.randint(-self.deme[1], self.deme[1]))) + ses[5].play_once() class Level2(Map): """ 第二关,有两个大炮 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 250 @@ -209,10 +222,10 @@ class Level2(Map): def update(self): Map.update(self) if self.objects[0].cast: - self.add_bullet((self.objects[0].pos[0]+70, self.objects[0].pos[1]+40), (5, 0), 15, 10) + self.add_bullet((self.objects[0].pos[0] + 70, self.objects[0].pos[1] + 40), (5, 0), 15, 10) ses[5].play_once() if self.objects[1].cast: - self.add_bullet((self.objects[1].pos[0]+70, self.objects[1].pos[1]+40), (5, 0), 15, 10) + self.add_bullet((self.objects[1].pos[0] + 70, self.objects[1].pos[1] + 40), (5, 0), 15, 10) ses[5].play_once() @@ -220,6 +233,7 @@ class Level3(Map): """ 第三关,一个十字激光 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 300 @@ -247,6 +261,7 @@ class Level4(Map): """ 第四关,一个移动激光 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 350 @@ -297,6 +312,7 @@ class Level5(Map): """ 第五关,有一个旋转激光 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 400 @@ -323,6 +339,7 @@ class Level6(Map): """ 第六关,有一个巨型激光 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 300 @@ -366,6 +383,7 @@ class Level7(Map): """ 第七关,有四条随机横向或者竖向的激光 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 400 @@ -394,13 +412,13 @@ class Level7(Map): if self.attack_tick == self.attack_speed: self.attacks.append(Beam(self, self.current_wave[0], 800, self.current_wave[4], pre_t=80, width=50, damage=20)) - elif self.attack_tick == self.attack_speed*2: + elif self.attack_tick == self.attack_speed * 2: self.attacks.append(Beam(self, self.current_wave[1], 800, self.current_wave[4], pre_t=80, width=50, damage=20)) - elif self.attack_tick == self.attack_speed*3: + elif self.attack_tick == self.attack_speed * 3: self.attacks.append(Beam(self, self.current_wave[2], 800, self.current_wave[4], pre_t=80, width=50, damage=20)) - elif self.attack_tick == self.attack_speed*4: + elif self.attack_tick == self.attack_speed * 4: self.attacks.append(Beam(self, self.current_wave[3], 800, self.current_wave[4], pre_t=80, width=50, damage=20)) elif self.attack_tick > self.attack_speed * 4: @@ -423,6 +441,7 @@ class Level8(Map): """ 第八关,每吃一个果子升一级,可以(基本上)无限玩下去 """ + def __init__(self, game): Map.__init__(self, game) self.deme[0] = 400 diff --git a/snake.py b/snake.py index bd9f421f76f321e09ec136ef3c8fd0809cd07c6d..c4aa24561f26c8ca8d059b8fa6dcdbd44fe19974 100644 --- a/snake.py +++ b/snake.py @@ -120,6 +120,7 @@ class Snake: if self.current_exp > 100: ses[4].play_once() self.level += 1 + self.hp += 10 # 升级可以回血 self.grow() self.current_exp = 0 for point in self.hit_points: diff --git a/texture/banana.png b/texture/banana.png new file mode 100644 index 0000000000000000000000000000000000000000..084de1983ac99a7deebcb1c78e83221631876401 Binary files /dev/null and b/texture/banana.png differ diff --git a/texture/barrier.png b/texture/barrier.png new file mode 100644 index 0000000000000000000000000000000000000000..d0d1a3fe9dedf1aead484580cac5c72ffc050067 Binary files /dev/null and b/texture/barrier.png differ diff --git a/texture/orange.png b/texture/orange.png new file mode 100644 index 0000000000000000000000000000000000000000..f0c1a1466f44cd39cce97dff077e9bf1fc6d5639 Binary files /dev/null and b/texture/orange.png differ diff --git a/texture/win_text1.png b/texture/win_text1.png new file mode 100644 index 0000000000000000000000000000000000000000..a6f4dbf1da23ca93fc94ba5813e9bf36b45d32ab Binary files /dev/null and b/texture/win_text1.png differ diff --git a/texture/win_text2.png b/texture/win_text2.png new file mode 100644 index 0000000000000000000000000000000000000000..17c3c9bba52922a05cfba998dbca9b5d1f05375a Binary files /dev/null and b/texture/win_text2.png differ diff --git a/texture/win_text3.png b/texture/win_text3.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3548a4a4147907c747d2c344d11631a7280652 Binary files /dev/null and b/texture/win_text3.png differ