import tkinter as tk
import random
import math
import time
from tkinter import messagebox
class ZombieGame:
def __init__(self, root):
self.root = root
self.root.title("丧尸生存游戏")
self.root.geometry("800x600")
self.root.resizable(False, False)
self.root.bind("<KeyPress>", self.on_key_press)
self.root.bind("<KeyRelease>", self.on_key_release)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
# 游戏画布
self.canvas = tk.Canvas(self.root, width=800, height=600, bg="black")
self.canvas.pack()
# 游戏状态
self.game_over = False
self.paused = False
self.score = 0
self.level = 1
self.lives = 3
self.bullets = 30
self.last_shot = 0
self.shoot_cooldown = 300 # 射击冷却时间(毫秒)
# 玩家属性
self.player_size = 20
self.player_x = 400
self.player_y = 300
self.player_speed = 5
self.player_dx = 0
self.player_dy = 0
self.player_angle = 0
# 键盘状态
self.keys = {
'w': False, 'a': False, 's': False, 'd': False,
'up': False, 'down': False, 'left': False, 'right': False,
'space': False
}
# 创建游戏对象
self.player = self.canvas.create_oval(
self.player_x - self.player_size,
self.player_y - self.player_size,
self.player_x + self.player_size,
self.player_y + self.player_size,
fill="blue"
)
# 玩家方向指示
self.direction_line = self.canvas.create_line(
self.player_x, self.player_y,
self.player_x + self.player_size * math.cos(math.radians(self.player_angle)),
self.player_y - self.player_size * math.sin(math.radians(self.player_angle)),
fill="white", width=2
)
# 游戏元素
self.zombies = []
self.bullets_list = []
self.obstacles = []
self.power_ups = []
# 生成障碍物
self.generate_obstacles(10)
# 显示游戏信息
self.score_text = self.canvas.create_text(50, 20, text="分数: 0", fill="white", anchor="w")
self.level_text = self.canvas.create_text(50, 40, text="等级: 1", fill="white", anchor="w")
self.lives_text = self.canvas.create_text(50, 60, text="生命: 3", fill="white", anchor="w")
self.bullets_text = self.canvas.create_text(50, 80, text="子弹: 30", fill="white", anchor="w")
self.status_text = self.canvas.create_text(400, 300, text="", fill="red", font=("Arial", 24))
# 开始游戏
self.spawn_zombies(3)
self.update()
def generate_obstacles(self, count):
for _ in range(count):
x = random.randint(100, 700)
y = random.randint(100, 500)
size = random.randint(30, 60)
# 确保障碍物不会生成在玩家附近
if math.sqrt((x - self.player_x) ** 2 + (y - self.player_y) ** 2) > 100:
obstacle = self.canvas.create_rectangle(
x - size, y - size, x + size, y + size,
fill="brown"
)
self.obstacles.append({
'id': obstacle,
'x': x,
'y': y,
'size': size
})
def spawn_zombies(self, count):
for _ in range(count):
# 在屏幕边缘生成丧尸
if random.random() < 0.5:
x = random.choice([-50, 850])
y = random.randint(0, 600)
else:
x = random.randint(0, 800)
y = random.choice([-50, 650])
zombie_size = random.randint(15, 25)
zombie_speed = random.uniform(1.0, 2.5 - self.level * 0.1)
if zombie_speed < 1.0:
zombie_speed = 1.0
zombie = self.canvas.create_oval(
x - zombie_size, y - zombie_size,
x + zombie_size, y + zombie_size,
fill="red"
)
self.zombies.append({
'id': zombie,
'x': x,
'y': y,
'size': zombie_size,
'speed': zombie_speed,
'health': 100
})
def update(self):
if not self.game_over and not self.paused:
# 更新玩家位置
self.update_player_position()
# 更新子弹位置
self.update_bullets()
# 更新丧尸位置
self.update_zombies()
# 检查碰撞
self.check_collisions()
# 生成补给
if random.random() < 0.005:
self.spawn_power_up()
# 检查游戏状态
if len(self.zombies) == 0:
self.level_up()
# 更新游戏信息
self.canvas.itemconfig(self.score_text, text=f"分数: {self.score}")
self.canvas.itemconfig(self.level_text, text=f"等级: {self.level}")
self.canvas.itemconfig(self.lives_text, text=f"生命: {self.lives}")
self.canvas.itemconfig(self.bullets_text, text=f"子弹: {self.bullets}")
# 显示游戏状态
if self.lives <= 0:
self.game_over = True
self.canvas.itemconfig(self.status_text, text="游戏结束!按R重新开始")
elif self.game_over:
self.canvas.itemconfig(self.status_text, text="游戏结束!按R重新开始")
elif self.paused:
self.canvas.itemconfig(self.status_text, text="游戏暂停!按P继续")
# 继续更新
self.root.after(16, self.update)
def update_player_position(self):
# 计算玩家移动方向
dx = 0
dy = 0
if self.keys['w'] or self.keys['up']:
dy -= self.player_speed
if self.keys['s'] or self.keys['down']:
dy += self.player_speed
if self.keys['a'] or self.keys['left']:
dx -= self.player_speed
if self.keys['d'] or self.keys['right']:
dx += self.player_speed
# 归一化速度向量,防止对角线移动过快
if dx != 0 or dy != 0:
length = math.sqrt(dx ** 2 + dy ** 2)
dx = dx / length * self.player_speed
dy = dy / length * self.player_speed
# 计算玩家角度
self.player_angle = math.degrees(math.atan2(-dy, dx))
# 更新玩家位置
new_x = self.player_x + dx
new_y = self.player_y + dy
# 检查边界碰撞
if new_x - self.player_size > 0 and new_x + self.player_size < 800:
self.player_x = new_x
if new_y - self.player_size > 0 and new_y + self.player_size < 600:
self.player_y = new_y
# 移动玩家图形
self.canvas.coords(
self.player,
self.player_x - self.player_size,
self.player_y - self.player_size,
self.player_x + self.player_size,
self.player_y + self.player_size
)
# 更新方向线
self.canvas.coords(
self.direction_line,
self.player_x, self.player_y,
self.player_x + self.player_size * math.cos(math.radians(self.player_angle)),
self.player_y - self.player_size * math.sin(math.radians(self.player_angle))
)
# 处理射击
current_time = time.time() * 1000
if self.keys['space'] and current_time - self.last_shot > self.shoot_cooldown and self.bullets > 0:
self.shoot()
self.last_shot = current_time
def shoot(self):
# 减少子弹数量
self.bullets -= 1
# 创建子弹
bullet_size = 5
bullet_speed = 10
# 子弹起始位置在玩家前方
bullet_x = self.player_x + self.player_size * math.cos(math.radians(self.player_angle))
bullet_y = self.player_y - self.player_size * math.sin(math.radians(self.player_angle))
bullet = self.canvas.create_oval(
bullet_x - bullet_size, bullet_y - bullet_size,
bullet_x + bullet_size, bullet_y + bullet_size,
fill="yellow"
)
self.bullets_list.append({
'id': bullet,
'x': bullet_x,
'y': bullet_y,
'size': bullet_size,
'speed': bullet_speed,
'angle': self.player_angle
})
def update_bullets(self):
bullets_to_remove = []
for bullet in self.bullets_list:
# 计算新位置
angle_radians = math.radians(bullet['angle'])
bullet['x'] += bullet['speed'] * math.cos(angle_radians)
bullet['y'] -= bullet['speed'] * math.sin(angle_radians)
# 更新子弹图形
self.canvas.coords(
bullet['id'],
bullet['x'] - bullet['size'],
bullet['y'] - bullet['size'],
bullet['x'] + bullet['size'],
bullet['y'] + bullet['size']
)
# 检查是否超出边界
if (bullet['x'] < 0 or bullet['x'] > 800 or
bullet['y'] < 0 or bullet['y'] > 600):
bullets_to_remove.append(bullet)
# 检查子弹与障碍物的碰撞
for obstacle in self.obstacles:
distance = math.sqrt(
(bullet['x'] - obstacle['x']) ** 2 +
(bullet['y'] - obstacle['y']) ** 2
)
if distance < bullet['size'] + obstacle['size']:
bullets_to_remove.append(bullet)
break
# 移除需要删除的子弹
for bullet in bullets_to_remove:
self.canvas.delete(bullet['id'])
if bullet in self.bullets_list:
self.bullets_list.remove(bullet)
def update_zombies(self):
for zombie in self.zombies:
# 计算丧尸朝向玩家的角度
dx = self.player_x - zombie['x']
dy = self.player_y - zombie['y']
angle = math.degrees(math.atan2(-dy, dx))
# 移动丧尸
speed = zombie['speed']
zombie['x'] += speed * math.cos(math.radians(angle))
zombie['y'] -= speed * math.sin(math.radians(angle))
# 更新丧尸图形
self.canvas.coords(
zombie['id'],
zombie['x'] - zombie['size'],
zombie['y'] - zombie['size'],
zombie['x'] + zombie['size'],
zombie['y'] + zombie['size']
)
def check_collisions(self):
# 检查子弹与丧尸的碰撞
bullets_to_remove = []
zombies_to_remove = []
for bullet in self.bullets_list:
for zombie in self.zombies:
distance = math.sqrt(
(bullet['x'] - zombie['x']) ** 2 +
(bullet['y'] - zombie['y']) ** 2
)
if distance < bullet['size'] + zombie['size']:
# 减少丧尸生命值
zombie['health'] -= 50
# 如果丧尸死亡,添加到移除列表
if zombie['health'] <= 0:
zombies_to_remove.append(zombie)
self.score += 10
# 添加子弹到移除列表
bullets_to_remove.append(bullet)
break
# 移除死亡的丧尸和子弹
for zombie in zombies_to_remove:
self.canvas.delete(zombie['id'])
if zombie in self.zombies:
self.zombies.remove(zombie)
for bullet in bullets_to_remove:
self.canvas.delete(bullet['id'])
if bullet in self.bullets_list:
self.bullets_list.remove(bullet)
# 检查玩家与丧尸的碰撞
for zombie in self.zombies:
distance = math.sqrt(
(self.player_x - zombie['x']) ** 2 +
(self.player_y - zombie['y']) ** 2
)
if distance < self.player_size + zombie['size']:
# 玩家受伤
self.lives -= 1
zombies_to_remove.append(zombie)
# 显示受伤效果
self.canvas.itemconfig(self.player, fill="red")
self.root.after(200, lambda: self.canvas.itemconfig(self.player, fill="blue"))
# 检查游戏是否结束
if self.lives <= 0:
self.game_over = True
# 移除与玩家碰撞的丧尸
for zombie in zombies_to_remove:
if zombie in self.zombies:
self.canvas.delete(zombie['id'])
self.zombies.remove(zombie)
# 检查玩家与补给的碰撞
power_ups_to_remove = []
for power_up in self.power_ups:
distance = math.sqrt(
(self.player_x - power_up['x']) ** 2 +
(self.player_y - power_up['y']) ** 2
)
if distance < self.player_size + power_up['size']:
# 应用补给效果
if power_up['type'] == 'health':
self.lives = min(3, self.lives + 1)
elif power_up['type'] == 'ammo':
self.bullets += 15
power_ups_to_remove.append(power_up)
# 移除被收集的补给
for power_up in power_ups_to_remove:
self.canvas.delete(power_up['id'])
if power_up in self.power_ups:
self.power_ups.remove(power_up)
def spawn_power_up(self):
# 确保补给不会生成在玩家附近
x = random.randint(100, 700)
y = random.randint(100, 500)
if math.sqrt((x - self.player_x) ** 2 + (y - self.player_y) ** 2) > 100:
power_up_type = random.choice(['health', 'ammo'])
size = 15
if power_up_type == 'health':
color = 'green'
else: # ammo
color = 'yellow'
power_up = self.canvas.create_oval(
x - size, y - size, x + size, y + size,
fill=color
)
self.power_ups.append({
'id': power_up,
'x': x,
'y': y,
'size': size,
'type': power_up_type
})
def level_up(self):
self.level += 1
self.spawn_zombies(self.level * 2)
self.bullets += 10 # 每升一级增加子弹
def on_key_press(self, event):
key = event.keysym.lower()
if key in self.keys:
self.keys[key] = True
elif key == 'r' and self.game_over:
self.restart_game()
elif key == 'p':
self.paused = not self.paused
def on_key_release(self, event):
key = event.keysym.lower()
if key in self.keys:
self.keys[key] = False
def restart_game(self):
# 清除所有游戏对象
for zombie in self.zombies:
self.canvas.delete(zombie['id'])
for bullet in self.bullets_list:
self.canvas.delete(bullet['id'])
for obstacle in self.obstacles:
self.canvas.delete(obstacle['id'])
for power_up in self.power_ups:
self.canvas.delete(power_up['id'])
# 重置游戏状态
self.game_over = False
self.score = 0
self.level = 1
self.lives = 3
self.bullets = 30
# 重置玩家位置
self.player_x = 400
self.player_y = 300
# 更新玩家图形
self.canvas.coords(
self.player,
self.player_x - self.player_size,
self.player_y - self.player_size,
self.player_x + self.player_size,
self.player_y + self.player_size
)
# 更新方向线
self.canvas.coords(
self.direction_line,
self.player_x, self.player_y,
self.player_x + self.player_size * math.cos(math.radians(self.player_angle)),
self.player_y - self.player_size * math.sin(math.radians(self.player_angle))
)
# 重新生成障碍物
self.obstacles = []
self.generate_obstacles(10)
# 生成初始丧尸
self.zombies = []
self.spawn_zombies(3)
# 清空子弹和补给
self.bullets_list = []
self.power_ups = []
# 更新游戏信息
self.canvas.itemconfig(self.score_text, text=f"分数: {self.score}")
self.canvas.itemconfig(self.level_text, text=f"等级: {self.level}")
self.canvas.itemconfig(self.lives_text, text=f"生命: {self.lives}")
self.canvas.itemconfig(self.bullets_text, text=f"子弹: {self.bullets}")
self.canvas.itemconfig(self.status_text, text="")
def on_closing(self):
if messagebox.askokcancel("退出", "确定要退出游戏吗?"):
self.root.destroy()
if __name__ == "__main__":
root = tk.Tk()
game = ZombieGame(root)
root.mainloop()
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END
暂无评论内容