diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..359bb5307e8535ab7d59faf27a7377033291821e
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000000000000000000000000000000000000..11a5d8e18ab71465be9424cf930c5e792c75edb7
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+main.py
\ No newline at end of file
diff --git a/.idea/Adapted-game-snake.iml b/.idea/Adapted-game-snake.iml
new file mode 100644
index 0000000000000000000000000000000000000000..8437fe66726a74ad9e6a89ed9c73e7a4fee5e64b
--- /dev/null
+++ b/.idea/Adapted-game-snake.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
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..dc9ea4906e15825848ae951155a4381c08529eaf
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4754f78d7964e15cab9c96605b62bbc1396b4f6f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..94a25f7f4cb416c083d265558da75d457237d671
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 3e4731e6c1d0e144b8722666c489f0419e00465f..756072d733ea915714e08b19335822a008622e15 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ exe文件在SnakeQuest-exe里-运行SnakeQuest.exe就可以了
#### 作品名
蛇蛇闯关
-#### 项目简介
+#### 项目简介
**非常建议开音量玩,30左右即可**
独特的闯关模式,更加平滑的360度移动,炫酷的攻击动画,耐听又贴切的背景音乐
diff --git a/SE2101010.md b/SE2101010.md
new file mode 100644
index 0000000000000000000000000000000000000000..1a9deeeca96350663ece5eb4d3ab8b27e11ea786
Binary files /dev/null and b/SE2101010.md differ
diff --git a/__pycache__/animations.cpython-310.pyc b/__pycache__/animations.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c925710282795e5e2d47168391a345a698bb9d34
Binary files /dev/null and b/__pycache__/animations.cpython-310.pyc differ
diff --git a/__pycache__/animations.cpython-39.pyc b/__pycache__/animations.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fed9a78f3033da32ade62942ce74084593c07567
Binary files /dev/null and b/__pycache__/animations.cpython-39.pyc differ
diff --git a/__pycache__/chat.cpython-310.pyc b/__pycache__/chat.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1cd21e14b80d0a6bf397d3390e7cef2942014544
Binary files /dev/null and b/__pycache__/chat.cpython-310.pyc differ
diff --git a/__pycache__/chat.cpython-39.pyc b/__pycache__/chat.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..04da54dff01ce6d486c065eb18e74c24b7688fde
Binary files /dev/null and b/__pycache__/chat.cpython-39.pyc differ
diff --git a/__pycache__/config.cpython-310.pyc b/__pycache__/config.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f0ca8a8f547b42b8069943da384fcda44c653b27
Binary files /dev/null and b/__pycache__/config.cpython-310.pyc differ
diff --git a/__pycache__/config.cpython-39.pyc b/__pycache__/config.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0b1d4162d3d03a444681f857e2820a7c75a4f081
Binary files /dev/null and b/__pycache__/config.cpython-39.pyc differ
diff --git a/__pycache__/cycle.cpython-310.pyc b/__pycache__/cycle.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ca08a799bc04431554cf026174a4d31f6ab4ed95
Binary files /dev/null and b/__pycache__/cycle.cpython-310.pyc differ
diff --git a/__pycache__/cycle.cpython-39.pyc b/__pycache__/cycle.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f32cc6a3d536b8b6c5a4686e21e564594c91264f
Binary files /dev/null and b/__pycache__/cycle.cpython-39.pyc differ
diff --git a/__pycache__/enemy_snake.cpython-310.pyc b/__pycache__/enemy_snake.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..108bf406507bc82eb378073bd150a06c7915fd79
Binary files /dev/null and b/__pycache__/enemy_snake.cpython-310.pyc differ
diff --git a/__pycache__/enemy_snake.cpython-39.pyc b/__pycache__/enemy_snake.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..478a63535f6de67f7f15a90b97239383b6861f57
Binary files /dev/null and b/__pycache__/enemy_snake.cpython-39.pyc differ
diff --git a/__pycache__/fights.cpython-310.pyc b/__pycache__/fights.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6ceb97d7d689a7a5bbef19f3b66731f9e5df40f3
Binary files /dev/null and b/__pycache__/fights.cpython-310.pyc differ
diff --git a/__pycache__/fights.cpython-39.pyc b/__pycache__/fights.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..aa2d02653297a896ce88b39019c1799c1a34c98d
Binary files /dev/null and b/__pycache__/fights.cpython-39.pyc differ
diff --git a/__pycache__/game.cpython-310.pyc b/__pycache__/game.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..92f68563b050ace8a2347f3f8a25a5586e8979d3
Binary files /dev/null and b/__pycache__/game.cpython-310.pyc differ
diff --git a/__pycache__/game.cpython-39.pyc b/__pycache__/game.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ea070589242a2d97c81113b0535a85dcdbaf060
Binary files /dev/null and b/__pycache__/game.cpython-39.pyc differ
diff --git a/__pycache__/hud.cpython-310.pyc b/__pycache__/hud.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3dfea83fdec5958948f1fe15a50dc7242c1fd248
Binary files /dev/null and b/__pycache__/hud.cpython-310.pyc differ
diff --git a/__pycache__/hud.cpython-39.pyc b/__pycache__/hud.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..721f027800dc9939cb6e23fb3b738ef473fed014
Binary files /dev/null and b/__pycache__/hud.cpython-39.pyc differ
diff --git a/__pycache__/map.cpython-310.pyc b/__pycache__/map.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4d52144344ae8a7f0a75c826667846c8594be5ae
Binary files /dev/null and b/__pycache__/map.cpython-310.pyc differ
diff --git a/__pycache__/map.cpython-39.pyc b/__pycache__/map.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4cdd57975158b20b4fb4a77791c73f9f9d93792a
Binary files /dev/null and b/__pycache__/map.cpython-39.pyc differ
diff --git a/__pycache__/menu.cpython-310.pyc b/__pycache__/menu.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2df5936e6762188379f56c19afa827a76488c3fa
Binary files /dev/null and b/__pycache__/menu.cpython-310.pyc differ
diff --git a/__pycache__/menu.cpython-39.pyc b/__pycache__/menu.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a55a4af82f10ff9550b02c883a1d4865e9f55522
Binary files /dev/null and b/__pycache__/menu.cpython-39.pyc differ
diff --git a/__pycache__/scene.cpython-310.pyc b/__pycache__/scene.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..db823ab004f7a9cc7d0168dd796198601d3c6045
Binary files /dev/null and b/__pycache__/scene.cpython-310.pyc differ
diff --git a/__pycache__/scene.cpython-39.pyc b/__pycache__/scene.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..31e3a1009ddabad9c5932eb1a987eb717de5bc20
Binary files /dev/null and b/__pycache__/scene.cpython-39.pyc differ
diff --git a/__pycache__/snake.cpython-310.pyc b/__pycache__/snake.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..48e878005eb394954ca33bb2c2986a4ca8b7aae6
Binary files /dev/null and b/__pycache__/snake.cpython-310.pyc differ
diff --git a/__pycache__/snake.cpython-39.pyc b/__pycache__/snake.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..84af4a84e97a3e5996653144fc4d1a2e80709864
Binary files /dev/null and b/__pycache__/snake.cpython-39.pyc differ
diff --git a/config.py b/config.py
index 49e5b56696d47f3459874ec2c533f14bdf1b9279..b24ac5800df7eaaedc84763d8d4f106b65cc8b7f 100644
--- a/config.py
+++ b/config.py
@@ -6,7 +6,7 @@ from math import *
pygame.init()
# 常用环境变量,分别是鼠标角度,x位置,y位置,以及是否按下
-env = {"mouse_direction": 0, "mouse_x": 0, "mouse_y": 0, "mouse_down": False}
+env = {"mouse_direction": 0, "mouse_x": 0, "mouse_y": 0, "mouse_down": False, "key": ''}
# 屏幕长宽,初始化屏幕 , pygame.HWSURFACE | pygame.FULLSCREEN
screen_width, screen_height = 600, 400
diff --git a/enemy_snake.py b/enemy_snake.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c3cbc2dd1a99f9a90f2185f8452afc8f74b825d
--- /dev/null
+++ b/enemy_snake.py
@@ -0,0 +1,157 @@
+from animations import *
+from config import *
+
+
+class Segment:
+ """
+ 蛇的一段,中心在center,以angle角度摆放,宽度是width
+ """
+
+ def __init__(self, center, angle, width):
+ self.angle = angle + pi / 2
+ self.width = width
+ self.center = center
+ self.draw_displacement = [0, 0]
+ self.update()
+
+ # 设置宽度
+ def set_width(self, width):
+ self.width = width
+
+ # 根据角度更新蛇的绘制点
+ def update(self):
+ self.draw_displacement[0] = cos(self.angle) * self.width
+ self.draw_displacement[1] = sin(self.angle) * self.width
+
+ # 获取绘制点一
+ def get_point1(self, offset):
+ return (self.center[0] + self.draw_displacement[0] + offset[0],
+ self.center[1] + self.draw_displacement[1] + offset[1])
+
+ # 获取绘制点二
+ def get_point2(self, offset):
+ return (self.center[0] - self.draw_displacement[0] + offset[0],
+ self.center[1] - self.draw_displacement[1] + offset[1])
+
+
+class EnemySnake:
+ """
+ 贪吃蛇本体,由许多Segment构成
+ """
+
+ def __init__(self, game):
+ self.game = game
+ self.width = 10
+ self.speed = 3
+ self.segments = []
+ self.direction = 0
+ self.poly_points = []
+ self.length = 0
+ self.seg_width = []
+ self.position = [100, 10]
+ self.turn_limit = pi / 3
+ self.outofbound = False
+ self.color = (255, 0, 0)
+
+ self.dead = False
+
+ self.hit_points = []
+
+ # 设置当前蛇前进角度
+ def set_direction(self, angle):
+ d_angle = (angle - self.direction) % (2 * pi)
+ if d_angle < self.turn_limit or d_angle > 2 * pi - self.turn_limit:
+ self.direction = angle
+ else:
+ turn_amount = self.turn_limit if d_angle < pi else -self.turn_limit
+ self.direction = (self.direction + turn_amount) % (2 * pi)
+
+ # 在蛇前面加一个Segment,segment的宽由一个函数生成
+ def increase_length(self):
+ self.length += 1
+ self.seg_width.append(self.width)
+ if self.length > 1:
+ a = -(self.width / ((self.length - 1) * (self.length - 1)))
+ for i in range(self.length):
+ self.seg_width[self.length - i - 1] = a * (i * i) + self.width
+
+ # 移动蛇的位置,用于更新offset
+ def move(self, dx, dy):
+ new_x = self.position[0] + dx
+ new_y = self.position[1] + dy
+
+ # 获取游戏区域边界
+ left_bound = -150 # 左边界
+ right_bound = self.game.width - 150 # 右边界
+ top_bound = -150 # 上边界
+ bottom_bound = self.game.height - 150 # 下边界
+
+ # 检查新位置是否超出边界,并调整位置和方向
+ if new_x <= left_bound:
+ new_x = left_bound
+ self.direction = random.uniform(0, pi) # 随机选择向右的新方向
+ elif new_x >= right_bound:
+ new_x = right_bound
+ self.direction = random.uniform(pi, 2 * pi) # 随机选择向左的新方向
+
+ if new_y <= top_bound:
+ new_y = top_bound
+ self.direction = random.uniform(-pi / 2, pi / 2) # 随机选择向下的新方向
+ elif new_y >= bottom_bound:
+ new_y = bottom_bound
+ self.direction = random.uniform(pi / 2, 3 * pi / 2) # 随机选择向上的新方向
+
+ # 更新蛇的位置
+ self.position[0] = new_x
+ self.position[1] = new_y
+
+ # 如果蛇的位置被调整到边界上,将其标记为超出边界
+ self.outofbound = (new_x == left_bound or new_x == right_bound or
+ new_y == top_bound or new_y == bottom_bound)
+
+ # 让蛇长长一节
+ def grow(self):
+ self.add_head_segment()
+ self.increase_length()
+ self.add_head_segment()
+ self.increase_length()
+
+ # 添加一个头部Segment
+ def add_head_segment(self):
+ self.move(cos(self.direction) * self.speed, sin(self.direction) * self.speed)
+ self.segments.append(Segment((self.position[0], self.position[1]), self.direction, self.width))
+ self.hit_points.append((self.position[0], self.position[1]))
+
+ # 移除一个尾部Segment
+ def remove_tail_segment(self):
+ del self.segments[0]
+ del self.hit_points[0]
+
+ # 让蛇往前爬一次
+ def crawl(self):
+ self.add_head_segment()
+ self.remove_tail_segment()
+
+ # 碰撞检测
+ def collide_with(self, snake):
+ for i in range(0, len(snake.hit_points), 2):
+ if get_distance(snake.hit_points[i], self.position) < self.width:
+ self.dead = True
+ return True
+ return False # 未发生碰撞,返回 False
+
+ # 进行更新,更新Segment宽度,当前经验升级,更新血量信息,以及碰撞点与绘制点列表
+ def update(self):
+ for i, segment in enumerate(self.segments):
+ segment.set_width(self.seg_width[i])
+ segment.update()
+
+ self.poly_points = [segment.get_point1(self.game.get_offset()) for segment in self.segments]
+ self.poly_points.extend(segment.get_point2(self.game.get_offset()) for segment in reversed(self.segments))
+
+ # 使用多边形方法绘制蛇
+ def draw(self):
+ pygame.draw.polygon(screen, self.color, self.poly_points)
+ pygame.draw.circle(screen, self.color, (int(self.position[0] + self.game.get_offset()[0]),
+ int(self.position[1] + self.game.get_offset()[1])),
+ self.width + 2)
diff --git a/fights.py b/fights.py
index 90d382b22fd6dcb3c96e96daf1dc9bffdbf03daf..e778a3aba3c90cd15a1575fe7ed1468338d96932 100644
--- a/fights.py
+++ b/fights.py
@@ -237,11 +237,22 @@ class ExpBall:
self.pos = pos
self.points = points
self.cycle = Cycle(4, 6)
+ self.texture_types = ["food", "banana"]
# 绘制经验球
+# def draw(self, offset):
+# 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))
+
+# def draw(self, offset):
+# screen.blit(texture_lib["banana"], (self.pos[0] + offset[0] - 22, self.pos[1] + offset[1] - 22),)
+
def draw(self, offset):
+ print("Drawing food")
+ # 绘制"food"纹理
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))
+ pygame.Rect(0, self.cycle.get() * 45, 45, 45))
+
class OneCanon:
diff --git a/game.py b/game.py
index 53d13c6bb139255f3fd35d9ffad2eaa099081173..e5fdaffb48806641a5771c3ce72bdb53797975ea 100644
--- a/game.py
+++ b/game.py
@@ -4,6 +4,21 @@ from hud import *
from menu import *
from chat import *
from scene import *
+from enemy_snake import *
+import random
+import time
+
+
+# 生成随机方向角度
+def generate_random_angles(num_snakes):
+ angles = []
+ current_time = int(time.time() // 2)
+ for i in range(num_snakes):
+ seed = current_time + i # 为每条小蛇生成唯一的种子
+ random.seed(seed) # 设置种子
+ angle = random.uniform(0, 2 * pi) # 生成随机角度
+ angles.append(angle)
+ return angles
class Game:
@@ -11,24 +26,28 @@ class Game:
游戏主题,一共有六个阶段:主菜单,关卡选择,对话场景,关卡显示场景,关卡进行,关卡结果场景
可以根据current_level来改变当前关卡,用于继续上次游戏
"""
+
def __init__(self, current_level=0):
+ self.width=300
+ self.height=300
self.snake_move_cycle = Cycle(2, 1)
self.current_level = current_level
self.current_playing = 0
-
self.map = None
-
self.snake = None
-
+ self.snake2 = None # 玩家小蛇2
+ self.enemy = [] # 敌人小蛇
self.scene = None
-
self.info_hud = None
-
+ self.info_hud2 = None
self.menu = MainMenu()
-
self.shaking = [False, False]
self.shake_cycle = [ReCycle(15, 1), ReCycle(15, 1)]
self.shake_countdown = [0, 0]
+ self.snake_base_speed = 7
+
+ # 新属性,用于追踪暂停状态
+ self.paused = False
# 摇晃当前屏幕,特效
def shake(self, direction, dur_t):
@@ -42,16 +61,16 @@ class Game:
# 获取当前渲染offset,为了让屏幕随着蛇移动
def get_offset(self):
if self.shaking[0] and self.shaking[1]:
- return self.shake_cycle[0].get()-int(self.snake.position[0] - screen_width/2), \
- self.shake_cycle[1].get()-int(self.snake.position[1] - screen_height/2)
+ return self.shake_cycle[0].get() - int(self.snake.position[0] - screen_width / 2), \
+ self.shake_cycle[1].get() - int(self.snake.position[1] - screen_height / 2)
elif self.shaking[0]:
- return self.shake_cycle[0].get()-int(self.snake.position[0] - screen_width/2), \
- -int(self.snake.position[1] - screen_height/2)
+ return self.shake_cycle[0].get() - int(self.snake.position[0] - screen_width / 2), \
+ -int(self.snake.position[1] - screen_height / 2)
elif self.shaking[1]:
- return -int(self.snake.position[0] - screen_width/2), \
- self.shake_cycle[1].get()-int(self.snake.position[1] - screen_height/2)
- return -int(self.snake.position[0] - screen_width/2), \
- -int(self.snake.position[1] - screen_height/2)
+ return -int(self.snake.position[0] - screen_width / 2), \
+ self.shake_cycle[1].get() - int(self.snake.position[1] - screen_height / 2)
+ return -int(self.snake.position[0] - screen_width / 2), \
+ -int(self.snake.position[1] - screen_height / 2)
# 开始一个场景
def start_scene(self, scene):
@@ -61,9 +80,25 @@ class Game:
def start(self, level=7):
self.menu = None
self.snake = Snake(self)
+ # 生成玩家小蛇2
+ self.snake2 = Snake(self)
+ self.snake2.color = (191, 213, 255)
+ self.snake2.common_color = (191, 213, 255)
+ for i in range(5):
+ # 生成5条敌人小蛇
+ self.enemy.append(EnemySnake(self))
for _ in range(5):
self.snake.grow()
+ self.snake2.grow()
+ # 生成敌人小蛇
+ for i in range(len(self.enemy)):
+ self.enemy[i].grow()
+
self.info_hud = InfoBar(self.snake)
+ self.info_hud2 = InfoBar(self.snake2)
+ self.info_hud2.level_pos = (30, 50)
+ self.info_hud2.exp_bar = (6, 10)
+ self.info_hud2.hp_bar = (150, 300)
if level == 1:
self.map = Level1(self)
elif level == 2:
@@ -81,8 +116,14 @@ class Game:
elif level == 8:
self.map = Level8(self)
self.map.set_snake(self.snake)
+ # 设置玩家小蛇2
+ self.map.set_snake2(self.snake2)
self.update()
- self.start_scene(TalkScene("snake_1", "snake_2", level_chats[level-1]))
+ # 设置和更新敌人小蛇
+ self.map.set_enemy(self.enemy)
+ for i in range(5):
+ self.enemy[i].update()
+ self.start_scene(TalkScene("snake_1", "snake_2", level_chats[level - 1]))
bgs[3].play_non_stop()
# 绘制当前状态,菜单优先,其次场景,最后是游戏本身
@@ -92,9 +133,17 @@ class Game:
elif not self.scene:
self.map.draw_background(self.get_offset())
self.snake.draw()
+
+ # 画出玩家小蛇2
+ self.snake2.draw()
+
+ # 画出敌人小蛇
+ for i in range(5):
+ self.enemy[i].draw()
self.map.draw(self.get_offset())
self.info_hud.draw()
+ self.info_hud2.draw()
else:
if self.scene.name == "text" or self.scene.name == "level":
self.map.draw(self.get_offset())
@@ -102,12 +151,17 @@ class Game:
# 触发成员的键盘鼠标事件,并且根据返回的值来更新自己的状态
def handle_event(self, event):
+ if event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_t:
+ # 切换暂停状态
+ self.paused = not self.paused
+
if self.menu:
result = self.menu.handle_event(event)
if result != -1:
if result >= 0:
self.current_playing = result
- self.start(result+1)
+ self.start(result + 1)
else:
if result == -3:
self.menu = LevelSelect(self.current_level)
@@ -117,43 +171,117 @@ class Game:
elif not self.scene:
pass
else:
- self.scene.handle_event(event)
+ if not self.paused:
+ self.scene.handle_event(event)
+
+ if self.snake:
+ if event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_LSHIFT:
+ self.snake.speed = 5 * self.snake_base_speed
+ if event.key == pygame.K_q:
+ self.snake.hp = 100
+ elif event.type == pygame.KEYUP:
+ if event.key == pygame.K_LSHIFT:
+ self.snake.speed = self.snake_base_speed
+
+ if event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_ESCAPE:
+ self.snake_move_cycle = Cycle(2, 1)
+ self.current_playing = 0
+ self.map = None
+ self.snake = None
+ self.scene = None
+ self.info_hud = None
+ self.info_hud2 = None
+ self.menu = MainMenu()
+ self.shaking = [False, False]
+ self.shake_cycle = [ReCycle(15, 1), ReCycle(15, 1)]
+ self.shake_countdown = [0, 0]
+ self.snake_base_speed = 7
# 更新当前状态,菜单优先,其次场景,最后是游戏本身。同时处理屏幕摇晃,根据结束场景开始游戏或者开始另外一个场景。
def update(self):
if not self.scene and self.menu:
self.menu.update()
elif not self.scene:
- self.snake.set_direction(env["mouse_direction"])
- self.map.update()
-
- if self.snake_move_cycle.get() == 0:
- self.snake.crawl()
- self.snake.update()
-
- self.info_hud.update()
- if self.map.is_dead():
- self.menu = LevelSelect(self.current_level)
- self.scene = TextScene("lose_text")
- 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")
- elif self.map.is_passed():
- self.menu = LevelSelect(self.current_level)
- self.scene = TextScene("win_text")
+ if not self.paused:
+ self.snake.set_direction(env["mouse_direction"])
+
+ # 玩家小蛇2设置方向
+ if env["key"] == 'w':
+ self.snake2.direction = 3 * pi / 2
+ elif env["key"] == 'd':
+ self.snake2.direction = 0
+ elif env["key"] == 's':
+ self.snake2.direction = pi / 2
+ elif env["key"] == 'a':
+ self.snake2.direction = pi
+
+ # 为敌人小蛇设置方向,方向由generate_random_angles函数随机生成
+ for i in range(5):
+ self.enemy[i].set_direction(generate_random_angles(len(self.enemy))[i])
+ self.map.update()
+
+ if self.snake_move_cycle.get() == 0:
+ self.snake.crawl()
+ # 移动玩家小蛇2
+ self.snake2.crawl()
+ self.snake.update()
+ # 更新玩家小蛇2
+ self.snake2.update()
+
+ # 让敌人小蛇移动
+ for i in range(len(self.enemy)):
+ if self.snake_move_cycle.get() == 0:
+ self.enemy[i].crawl()
+ self.enemy[i].update()
+
+ self.info_hud.update()
+ self.info_hud2.update()
+ if self.map.is_dead2() != 3:
+ self.menu = LevelSelect(self.current_level)
+ if self.map.is_dead2() == 1:
+ self.scene = TextScene("player2_win")
+ else:
+ self.scene = TextScene("player1_win")
+ elif self.map.is_passed2() != 3 and self.current_level == self.current_playing:
+ self.current_level += 1
+ self.menu = LevelSelect(self.current_level)
+ if self.map.is_passed2() == 1:
+ self.scene = TextScene("player1_win")
+ else:
+ self.scene = TextScene("player2_win")
+ # self.scene = TextScene("win_text")
+ elif self.map.is_passed2() != 3:
+ self.menu = LevelSelect(self.current_level)
+ if self.map.is_passed2() == 1:
+ self.scene = TextScene("player1_win")
+ else:
+ self.scene = TextScene("player2_win")
+ # if self.map.is_dead():
+ # self.menu = LevelSelect(self.current_level)
+ # self.scene = TextScene("lose_text")
+ # 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")
+ # elif self.map.is_passed():
+ # self.menu = LevelSelect(self.current_level)
+ # self.scene = TextScene("win_text")
+
else:
- self.scene.update()
- if self.scene.is_ended():
- if self.scene.name == "chat":
- m = random.randint(0, 1)
- if m == 0:
- bgs[1].play_non_stop()
+ if not self.paused:
+ self.scene.update()
+ if self.scene.is_ended():
+ if self.scene.name == "chat":
+ m = random.randint(0, 1)
+ if m == 0:
+ bgs[1].play_non_stop()
+ else:
+ bgs[2].play_non_stop()
+ self.scene = LevelNum(self.current_playing + 1)
else:
- bgs[2].play_non_stop()
- self.scene = LevelNum(self.current_playing+1)
- else:
- self.scene = None
+ self.scene = None
if self.shaking[0]:
self.shake_countdown[0] -= 1
@@ -163,3 +291,4 @@ class Game:
self.shake_countdown[1] -= 1
if self.shake_countdown[1] <= 0:
self.shaking[1] = False
+
diff --git a/hud.py b/hud.py
index 14ae4ba7b3f1a15dd396a9cbc330672cf1f3808f..c19b831d330bc1da60b326c1a7bf482dd2a1c034 100644
--- a/hud.py
+++ b/hud.py
@@ -8,7 +8,10 @@ class InfoBar:
def __init__(self, snake):
self.snake = snake
self.hp_lag = 300
-
+ # 设置UI位置
+ self.level_pos = (30, 15)
+ self.exp_bar = (6, 50)
+ self.hp_bar = (150, 370)
self.level_text = None
self.update()
@@ -19,13 +22,12 @@ class InfoBar:
self.hp_lag -= 2
else:
self.hp_lag = self.snake.hp*3
-
# 将当前数值绘制出来
def draw(self):
- screen.blit(self.level_text, (30, 15))
- screen.blit(texture_lib["exp_bar"], (6, 50), pygame.Rect(0, 10, self.snake.current_exp, 10))
- screen.blit(texture_lib["exp_bar"], (6, 50), pygame.Rect(0, 0, 100, 10))
- screen.fill(-1, pygame.Rect(150, 370, self.hp_lag, 20))
- screen.blit(texture_lib["hp_bar"], (150, 370),
+ screen.blit(self.level_text, self.level_pos)
+ screen.blit(texture_lib["exp_bar"], self.exp_bar, pygame.Rect(0, 10, self.snake.current_exp, 10))
+ screen.blit(texture_lib["exp_bar"], self.exp_bar, pygame.Rect(0, 0, 100, 10))
+ screen.fill(-1, pygame.Rect(self.hp_bar[0], self.hp_bar[1], self.hp_lag, 20))
+ screen.blit(texture_lib["hp_bar"], self.hp_bar,
pygame.Rect(300 - self.snake.hp * 3, 20, self.snake.hp * 3, 20))
- screen.blit(texture_lib["hp_bar"], (150, 370), pygame.Rect(0, 0, 300, 20))
+ screen.blit(texture_lib["hp_bar"], self.hp_bar, pygame.Rect(0, 0, 300, 20))
diff --git a/main.py b/main.py
index f16bfc0946275f8a373674e9a7e4ec4b085043f7..07d31f3f42e5f7f80c0e3ecda3b99a24bf535dc2 100644
--- a/main.py
+++ b/main.py
@@ -23,6 +23,18 @@ while True:
f.close()
pygame.quit()
sys.exit()
+
+ # 键盘事件,更新小蛇移动方向
+ if event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_w:
+ env["key"] = 'w'
+ elif event.key == pygame.K_d:
+ env["key"] = 'd'
+ elif event.key == pygame.K_s:
+ env["key"] = 's'
+ elif event.key == pygame.K_a:
+ env["key"] = 'a'
+
# 鼠标事件,更新环境变量
if event.type == pygame.MOUSEMOTION:
env["mouse_x"] = pygame.mouse.get_pos()[0]
diff --git a/map.py b/map.py
index 3c7c79f0034b74f967d1811f25da4667deae2c63..2521577efcd0e6d36dd30cfd64e047d37a41db05 100644
--- a/map.py
+++ b/map.py
@@ -5,6 +5,7 @@ class Level:
"""
关卡父类
"""
+
def __init__(self):
pass
@@ -18,6 +19,7 @@ class Map(Level):
地图,存储数据有所有攻击,经验球,动画以及物品(大炮,激光炮等)
per_exp为每个经验球的经验,food_count是场上经验球数量,pass_level是过关等级
"""
+
def __init__(self, game):
Level.__init__(self)
self.game = game
@@ -25,6 +27,8 @@ class Map(Level):
self.exp_balls = []
self.deme = [300, 300]
self.snake = None
+ self.snake2 = None # 玩家小蛇2
+ self.enemy = [] # 敌人小蛇
self.attacks = []
self.food_count = 5
self.per_exp = 10
@@ -34,10 +38,23 @@ class Map(Level):
self.animations = []
+ self.exp_balls = []
+ self.exp_balls_count = 0
+ if random.random() > 0.98:
+ self.hp_balls_count = random.randint(1, 3)
+
# 判断当前蛇是否死亡
def is_dead(self):
return self.snake.hp < 0
+ # 判断是否有玩家死亡
+ def is_dead2(self):
+ if self.snake.hp < 0:
+ return 1
+ elif self.snake2.hp < 0:
+ return 2
+ return 3
+
# 绘制四周边框,是动画
def draw_boarder(self, offset):
c = self.boarder_cycle.get()
@@ -94,6 +111,14 @@ class Map(Level):
def set_snake(self, snake):
self.snake = snake
+ # 设置玩家小蛇2
+ def set_snake2(self, snake):
+ self.snake2 = snake
+
+ # 设置敌人小蛇
+ def set_enemy(self, enemy):
+ self.enemy = enemy
+
# 绘制背景底色
def draw_background(self, offset):
pygame.draw.rect(screen, (70, 70, 70),
@@ -102,51 +127,72 @@ 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))
+ # 小蛇2危险状态
+ if self.snake2.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 get_distance(self.snake2.position, self.exp_balls[i].pos) < 20:
+ self.snake2.current_exp += self.exp_balls[i].points
+ ses[2].play_once()
+ del self.exp_balls[i]
+ # 敌人小蛇碰撞检测
+ for i in range(len(self.enemy) - 1, -1, -1):
+ if self.enemy[i].collide_with(self.snake):
+ self.snake.hp -= 2
+ if self.enemy[i].collide_with(self.snake2):
+ self.snake2.hp -= 2
+ #玩家小蛇一与玩家小蛇二碰撞检测
+ for i in range(len(self.enemy) - 1, -1, -1):
+ if self.snake.collide_with(self.snake2):
+ self.snake.hp -= 0.01
+ self.snake2.hp-=0.01
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]
@@ -163,17 +209,33 @@ class Map(Level):
else:
self.snake.outofbound = False
+ if (self.snake2.position[0] < -self.deme[0] or
+ self.snake2.position[0] > self.deme[0] or
+ self.snake2.position[1] < -self.deme[1] or
+ self.snake2.position[1] > self.deme[1]):
+ self.snake2.outofbound = True
+ else:
+ self.snake2.outofbound = False
+
class Level1(Map):
"""
第一关,场地为200,200
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 200
self.deme[1] = 200
self.pass_level = 3
+ def is_passed2(self):
+ if self.snake.level >= self.pass_level:
+ return 1
+ if self.snake2.level >= self.pass_level:
+ return 2
+ return 3
+
# 同父类
def is_passed(self):
if self.snake.level >= self.pass_level:
@@ -189,6 +251,7 @@ class Level2(Map):
"""
第二关,有两个大炮
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 250
@@ -209,10 +272,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 +283,7 @@ class Level3(Map):
"""
第三关,一个十字激光
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 300
@@ -247,6 +311,7 @@ class Level4(Map):
"""
第四关,一个移动激光
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 350
@@ -297,6 +362,7 @@ class Level5(Map):
"""
第五关,有一个旋转激光
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 400
@@ -323,6 +389,7 @@ class Level6(Map):
"""
第六关,有一个巨型激光
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 300
@@ -366,6 +433,7 @@ class Level7(Map):
"""
第七关,有四条随机横向或者竖向的激光
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 400
@@ -394,13 +462,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 +491,7 @@ class Level8(Map):
"""
第八关,每吃一个果子升一级,可以(基本上)无限玩下去
"""
+
def __init__(self, game):
Map.__init__(self, game)
self.deme[0] = 400
diff --git a/scene.py b/scene.py
index 02cc592e0871e7d089a1d6493fe2228b4e1a4412..9d85269a1a9dfeee70f946e495178d209bba44ce 100644
--- a/scene.py
+++ b/scene.py
@@ -108,6 +108,14 @@ class TalkScene:
# 处理鼠标点击事件,左击可快速跳过对话
def handle_event(self, event):
+ if event.type == pygame.KEYUP and event.key == pygame.K_SPACE:
+ # 通过清空对话列表来跳过所有剩余对话
+ self.chats = []
+ # 如果当前存在对话框,标记为结束以继续下一个场景
+ if self.current_chat:
+ self.current_chat.dead = True
+ ses[7].play_once()
+
if self.current_chat:
if event.type == pygame.MOUSEBUTTONUP:
if self.current_chat.stage == 1:
@@ -123,7 +131,7 @@ class TalkScene:
if not self.chats and (not self.current_chat or self.current_chat.dead):
self.stage_tick = 0
self.stage += 1
- elif self.current_chat.dead:
+ elif self.current_chat and self.current_chat.dead:
self.next_chat()
else:
self.stage_tick += 1
@@ -135,18 +143,22 @@ class TalkScene:
def draw(self):
if self.stage == 0:
if self.stage_tick < 25:
- screen.blit(texture_lib[self.c1], (self.stage_tick * 12 - 300, 250))
+ x1 = self.stage_tick * 12 - 300
+ x2 = 600 - (self.stage_tick - 25) * 12
else:
- screen.blit(texture_lib[self.c1], (0, 250))
- screen.blit(texture_lib[self.c2], (600 - (self.stage_tick - 25) * 12, 250))
-
+ x1 = 0
+ x2 = 600
+ screen.blit(texture_lib[self.c1], (x1, 250))
+ screen.blit(texture_lib[self.c2], (x2, 250))
elif self.stage == 1:
self.current_chat.draw()
screen.blit(texture_lib[self.c1], (0, 250))
screen.blit(texture_lib[self.c2], (300, 250))
elif self.stage == 2:
- screen.blit(texture_lib[self.c1], (-self.stage_tick * 13, 250))
- screen.blit(texture_lib[self.c2], (300 + self.stage_tick * 13, 250))
+ x1 = -self.stage_tick * 13
+ x2 = 300 + self.stage_tick * 13
+ screen.blit(texture_lib[self.c1], (x1, 250))
+ screen.blit(texture_lib[self.c2], (x2, 250))
else:
screen.blit(texture_lib[self.c1], (0, 250))
screen.blit(texture_lib[self.c2], (300, 250))
diff --git a/screenshots/enemy_snake.png b/screenshots/enemy_snake.png
new file mode 100644
index 0000000000000000000000000000000000000000..fe6fca18a6281515e3fe247e0f7eb3a6d780694c
Binary files /dev/null and b/screenshots/enemy_snake.png differ
diff --git a/screenshots/twoplayers.png b/screenshots/twoplayers.png
new file mode 100644
index 0000000000000000000000000000000000000000..5f67352f956f232689a60de19405dae4877dfb80
Binary files /dev/null and b/screenshots/twoplayers.png differ
diff --git a/snake.py b/snake.py
index bd9f421f76f321e09ec136ef3c8fd0809cd07c6d..c56e850f551b96a118fcc48b4f7cfda939b029f2 100644
--- a/snake.py
+++ b/snake.py
@@ -49,6 +49,7 @@ class Snake:
self.turn_limit = pi/3
self.outofbound = False
self.color = (255, 255, 255)
+ self.common_color = (255, 255, 255)
self.level = 1
self.current_exp = 0
@@ -107,15 +108,12 @@ class Snake:
# 进行更新,更新Segment宽度,当前经验升级,更新血量信息,以及碰撞点与绘制点列表
def update(self):
- for i in range(self.length):
- self.segments[i].set_width(self.seg_width[i])
- self.segments[i].update()
+ for segment, width in zip(self.segments, self.seg_width):
+ segment.set_width(width)
+ segment.update()
- del self.poly_points[:]
- for seg in self.segments:
- self.poly_points.append(seg.get_point1(self.game.get_offset()))
- for i in range(self.length - 1, -1, -1):
- self.poly_points.append(self.segments[i].get_point2(self.game.get_offset()))
+ self.poly_points = [seg.get_point1(self.game.get_offset()) for seg in self.segments]
+ self.poly_points.extend(seg.get_point2(self.game.get_offset()) for seg in reversed(self.segments))
if self.current_exp > 100:
ses[4].play_once()
@@ -134,9 +132,15 @@ class Snake:
if self.pre_hp > self.hp:
self.color = (255, 100, 100)
else:
- self.color = (255, 255, 255)
+ self.color = self.common_color
self.pre_hp = self.hp
-
+ #不同玩家小蛇碰撞检测
+ def collide_with(self, snake):
+ for i in range(0, len(snake.hit_points), 2):
+ if get_distance(snake.hit_points[i], self.position) < self.width:
+ self.dead = True
+ return True
+ return False # 未发生碰撞,返回 False
# 使用多边形方法绘制蛇
def draw(self):
pygame.draw.polygon(screen, self.color, self.poly_points)
diff --git a/texture/banana.png b/texture/banana.png
new file mode 100644
index 0000000000000000000000000000000000000000..c222b7a94abfae120da78bbf7e0eb1bc8eba32a0
Binary files /dev/null and b/texture/banana.png differ
diff --git a/texture/player1_win.png b/texture/player1_win.png
new file mode 100644
index 0000000000000000000000000000000000000000..64f8d818150923f71e3bc532c06154738be66aa5
Binary files /dev/null and b/texture/player1_win.png differ
diff --git a/texture/player2_win.png b/texture/player2_win.png
new file mode 100644
index 0000000000000000000000000000000000000000..2f7cc5701ced6471231961832f252d6cc189a853
Binary files /dev/null and b/texture/player2_win.png differ
diff --git a/~$2101010.md b/~$2101010.md
new file mode 100644
index 0000000000000000000000000000000000000000..83b2c3a4b3bf39d5351e03ca18ff2f0967d140c0
Binary files /dev/null and b/~$2101010.md differ