import tkinter as tkimport randomfrom tkinter import messageboxclass TankGame: def __init__(self, root): self.root = root self.root.title("坦克大战") self.root.resizable(False, False) # 游戏配置 self.cell_size = 30 # 每个格子的大小(像素) self.map_width = 20 # 地图宽度(格子数) self.map_height = 15 # 地图高度(格子数) # 计算窗口大小 self.game_width = self.map_width * self.cell_size self.game_height = self.map_height * self.cell_size self.info_width = 200 # 设置窗口大小 self.root.geometry(f"{self.game_width + self.info_width + 40}x{self.game_height + 40}") # 游戏状态 self.player_tank = None self.enemy_tanks = [] self.bullets = [] self.walls = [] self.score = 0 self.enemy_count = 5 # 敌方坦克数量 self.game_over = False self.paused = False self.game_loop_id = None # 移动延迟(防止移动太快) self.move_delay = 0 self.enemy_move_delay = 0 # 颜色配置 self.colors = { 'bg': '#2c3e50', 'player': '#2ecc71', 'enemy': '#e74c3c', 'wall': '#95a5a6', 'bullet': '#f1c40f', 'grid': '#34495e' } # 创建界面 self.setup_ui() # 绑定键盘事件 self.bind_keys() # 开始游戏 self.start_game() # 游戏循环 self.game_loop() def setup_ui(self): """创建用户界面""" # 主框架 main_frame = tk.Frame(self.root, bg=self.colors['bg']) main_frame.pack(expand=True, fill=tk.BOTH) # 游戏画布 self.canvas = tk.Canvas( main_frame, width=self.game_width, height=self.game_height, bg=self.colors['bg'], highlightthickness=2, highlightbackground='#555' ) self.canvas.pack(side=tk.LEFT, padx=10, pady=10) # 信息面板 info_frame = tk.Frame(main_frame, width=self.info_width, bg='#34495e') info_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.BOTH) info_frame.pack_propagate(False) # 得分显示 self.score_label = tk.Label( info_frame, text=f"得分: {self.score}", font=('Arial', 18, 'bold'), bg='#34495e', fg='white' ) self.score_label.pack(pady=20) # 敌方剩余数量 self.enemy_label = tk.Label( info_frame, text=f"敌方剩余: {self.enemy_count}", font=('Arial', 14, 'bold'), bg='#34495e', fg='white' ) self.enemy_label.pack(pady=10) # 操作说明 controls_frame = tk.Frame(info_frame, bg='#34495e') controls_frame.pack(pady=20) controls = [ "操作说明:", "", "WASD 或 方向键: 移动", "J 或 空格: 射击", "", "P: 暂停", "R: 重新开始" ] for text in controls: label = tk.Label( controls_frame, text=text, font=('Arial', 10), bg='#34495e', fg='#95a5a6' ) label.pack(pady=2) def bind_keys(self): """绑定键盘事件""" # 移动控制 self.root.bind('<KeyPress-Left>', lambda e: self.move_player('left')) self.root.bind('<KeyPress-Right>', lambda e: self.move_player('right')) self.root.bind('<KeyPress-Up>', lambda e: self.move_player('up')) self.root.bind('<KeyPress-Down>', lambda e: self.move_player('down')) self.root.bind('<KeyPress-a>', lambda e: self.move_player('left')) self.root.bind('<KeyPress-d>', lambda e: self.move_player('right')) self.root.bind('<KeyPress-w>', lambda e: self.move_player('up')) self.root.bind('<KeyPress-s>', lambda e: self.move_player('down')) # 射击控制 self.root.bind('<KeyPress-space>', lambda e: self.shoot()) self.root.bind('<KeyPress-j>', lambda e: self.shoot()) self.root.bind('<KeyPress-J>', lambda e: self.shoot()) # 游戏控制 self.root.bind('<KeyPress-p>', lambda e: self.toggle_pause()) self.root.bind('<KeyPress-P>', lambda e: self.toggle_pause()) self.root.bind('<KeyPress-r>', lambda e: self.restart()) self.root.bind('<KeyPress-R>', lambda e: self.restart()) # 确保窗口获得焦点 self.root.focus_set() def start_game(self): """开始游戏""" self.create_map() self.player_tank = Tank(self.map_width // 2, self.map_height - 2, 'player', self.colors['player']) self.enemy_tanks = [] self.bullets = [] self.score = 0 self.enemy_count = 5 self.game_over = False self.paused = False self.move_delay = 0 self.enemy_move_delay = 0 # 创建敌方坦克 for i in range(self.enemy_count): while True: x = random.randint(1, self.map_width - 2) y = random.randint(1, 5) # 确保不与玩家重叠且不与其他敌方坦克重叠 overlap = False if (x, y) == (self.player_tank.x, self.player_tank.y): overlap = True for enemy in self.enemy_tanks: if enemy.x == x and enemy.y == y: overlap = True break if not overlap: enemy = Tank(x, y, 'enemy', self.colors['enemy']) self.enemy_tanks.append(enemy) break self.update_info() self.draw() def create_map(self): """创建地图(墙壁)""" self.walls = [] # 创建边界墙壁 for x in range(self.map_width): self.walls.append(Wall(x, 0)) # 上边界 self.walls.append(Wall(x, self.map_height - 1)) # 下边界 for y in range(self.map_height): self.walls.append(Wall(0, y)) # 左边界 self.walls.append(Wall(self.map_width - 1, y)) # 右边界 # 创建一些障碍物 obstacles = [ (5, 5), (6, 5), (7, 5), (12, 5), (13, 5), (14, 5), (3, 8), (4, 8), (5, 8), (6, 8), (13, 8), (14, 8), (15, 8), (16, 8), (8, 10), (9, 10), (10, 10), (11, 10), (4, 12), (5, 12), (14, 12), (15, 12) ] for x, y in obstacles: if 0 < x < self.map_width - 1 and 0 < y < self.map_height - 1: self.walls.append(Wall(x, y)) def move_player(self, direction): """移动玩家坦克(带延迟,防止移动太快)""" if self.game_over or self.paused: return # 移动延迟控制 if self.move_delay > 0: return new_x, new_y = self.player_tank.x, self.player_tank.y if direction == 'left': new_x -= 1 elif direction == 'right': new_x += 1 elif direction == 'up': new_y -= 1 elif direction == 'down': new_y += 1 # 检查碰撞 if self.can_move(new_x, new_y, self.player_tank): self.player_tank.x = new_x self.player_tank.y = new_y self.player_tank.direction = direction self.move_delay = 3 # 设置移动延迟,数值越大移动越慢 self.draw() def move_enemies(self): """移动敌方坦克(带延迟)""" if self.enemy_move_delay > 0: self.enemy_move_delay -= 1 return for enemy in self.enemy_tanks[:]: # 随机移动 directions = ['up', 'down', 'left', 'right'] move_dir = random.choice(directions) new_x, new_y = enemy.x, enemy.y if move_dir == 'left': new_x -= 1 elif move_dir == 'right': new_x += 1 elif move_dir == 'up': new_y -= 1 elif move_dir == 'down': new_y += 1 # 检查碰撞 if self.can_move(new_x, new_y, enemy): enemy.x = new_x enemy.y = new_y enemy.direction = move_dir self.enemy_move_delay = 4 # 敌方移动延迟,比玩家稍慢 def can_move(self, x, y, tank): """检查坦克是否可以移动到指定位置""" # 检查边界 if x <= 0 or x >= self.map_width - 1 or y <= 0 or y >= self.map_height - 1: return False # 检查墙壁碰撞 for wall in self.walls: if wall.x == x and wall.y == y: return False # 检查其他坦克碰撞 if tank.type == 'player': for enemy in self.enemy_tanks: if enemy.x == x and enemy.y == y: return False else: if self.player_tank.x == x and self.player_tank.y == y: return False for other in self.enemy_tanks: if other != tank and other.x == x and other.y == y: return False return True def shoot(self): """玩家射击(无冷却)""" if self.game_over or self.paused: return bullet = Bullet( self.player_tank.x, self.player_tank.y, self.player_tank.direction, 'player' ) self.bullets.append(bullet) def enemy_shoot(self, enemy): """敌方射击(无冷却)""" bullet = Bullet( enemy.x, enemy.y, enemy.direction, 'enemy' ) self.bullets.append(bullet) def update_bullets(self): """更新子弹位置和碰撞(子弹速度加快)""" for bullet in self.bullets[:]: # 子弹每次移动多格,加快速度 for _ in range(3): # 每次更新移动3格,速度是坦克的3倍 # 移动子弹 if bullet.direction == 'up': bullet.y -= 1 elif bullet.direction == 'down': bullet.y += 1 elif bullet.direction == 'left': bullet.x -= 1 elif bullet.direction == 'right': bullet.x += 1 # 检查边界 if (bullet.x <= 0 or bullet.x >= self.map_width - 1 or bullet.y <= 0 or bullet.y >= self.map_height - 1): if bullet in self.bullets: self.bullets.remove(bullet) break # 检查墙壁碰撞 hit_wall = False for wall in self.walls[:]: if wall.x == bullet.x and wall.y == bullet.y: if wall in self.walls: self.walls.remove(wall) if bullet in self.bullets: self.bullets.remove(bullet) hit_wall = True break if hit_wall: break # 检查坦克碰撞 if bullet.type == 'player': for enemy in self.enemy_tanks[:]: if enemy.x == bullet.x and enemy.y == bullet.y: if enemy in self.enemy_tanks: self.enemy_tanks.remove(enemy) if bullet in self.bullets: self.bullets.remove(bullet) self.score += 10 self.enemy_count = len(self.enemy_tanks) self.update_info() break if bullet not in self.bullets: break else: if (self.player_tank.x == bullet.x and self.player_tank.y == bullet.y): self.game_over = True if bullet in self.bullets: self.bullets.remove(bullet) return # 如果子弹已经移除,跳出循环 if bullet not in self.bullets: break def update_info(self): """更新信息显示""" self.score_label.config(text=f"得分: {self.score}") self.enemy_label.config(text=f"敌方剩余: {self.enemy_count}") # 检查胜利条件 if self.enemy_count == 0 and not self.game_over: self.game_over = True self.show_victory() def toggle_pause(self): """暂停/继续游戏""" if not self.game_over: self.paused = not self.paused self.draw() if not self.paused: self.game_loop() def restart(self): """重新开始游戏""" # 停止当前的游戏循环 if self.game_loop_id: self.root.after_cancel(self.game_loop_id) self.game_loop_id = None self.start_game() self.draw() self.game_loop() def show_game_over(self): """显示游戏结束""" self.draw() result = messagebox.askyesno("游戏结束", f"游戏结束!\n最终得分: {self.score}\n是否重新开始?") if result: self.restart() else: self.root.quit() def show_victory(self): """显示胜利""" self.draw() result = messagebox.askyesno("胜利", f"恭喜获胜!\n最终得分: {self.score}\n是否重新开始?") if result: self.restart() else: self.root.quit() def draw(self): """绘制游戏画面""" self.canvas.delete("all") # 绘制网格线 for x in range(self.map_width + 1): self.canvas.create_line( x * self.cell_size, 0, x * self.cell_size, self.game_height, fill=self.colors['grid'], width=1 ) for y in range(self.map_height + 1): self.canvas.create_line( 0, y * self.cell_size, self.game_width, y * self.cell_size, fill=self.colors['grid'], width=1 ) # 绘制墙壁 for wall in self.walls: self.canvas.create_rectangle( wall.x * self.cell_size, wall.y * self.cell_size, (wall.x + 1) * self.cell_size, (wall.y + 1) * self.cell_size, fill=self.colors['wall'], outline=self.colors['bg'], width=2 ) # 绘制玩家坦克 if self.player_tank: self.draw_tank(self.player_tank) # 绘制敌方坦克 for enemy in self.enemy_tanks: self.draw_tank(enemy) # 绘制子弹 for bullet in self.bullets: self.canvas.create_rectangle( bullet.x * self.cell_size + self.cell_size//3, bullet.y * self.cell_size + self.cell_size//3, (bullet.x + 1) * self.cell_size - self.cell_size//3, (bullet.y + 1) * self.cell_size - self.cell_size//3, fill=self.colors['bullet'], outline='' ) # 绘制游戏结束或暂停文字 if self.game_over: text = "胜利!" if self.enemy_count == 0 else "游戏结束" color = "green" if self.enemy_count == 0 else "red" self.canvas.create_text( self.game_width // 2, self.game_height // 2, text=text, font=('Arial', 30, 'bold'), fill=color ) elif self.paused: self.canvas.create_text( self.game_width // 2, self.game_height // 2, text="暂停", font=('Arial', 30, 'bold'), fill='yellow' ) def draw_tank(self, tank): """绘制坦克""" x = tank.x * self.cell_size y = tank.y * self.cell_size size = self.cell_size # 绘制坦克身体 self.canvas.create_rectangle( x + 2, y + 2, x + size - 2, y + size - 2, fill=tank.color, outline='white', width=2 ) # 绘制炮管 炮管长度 = size // 2 炮管宽度 = size // 6 if tank.direction == 'up': self.canvas.create_line( x + size//2, y + size//2, x + size//2, y - 炮管长度//2, fill='white', width=炮管宽度 ) elif tank.direction == 'down': self.canvas.create_line( x + size//2, y + size//2, x + size//2, y + size + 炮管长度//2, fill='white', width=炮管宽度 ) elif tank.direction == 'left': self.canvas.create_line( x + size//2, y + size//2, x - 炮管长度//2, y + size//2, fill='white', width=炮管宽度 ) elif tank.direction == 'right': self.canvas.create_line( x + size//2, y + size//2, x + size + 炮管长度//2, y + size//2, fill='white', width=炮管宽度 ) def game_loop(self): """游戏主循环""" if not self.game_over and not self.paused: # 更新移动延迟 if self.move_delay > 0: self.move_delay -= 1 self.move_enemies() # 敌方随机射击(无冷却,但降低概率) if self.enemy_tanks and not self.game_over: for enemy in self.enemy_tanks: if random.random() < 0.02: # 降低射击概率 self.enemy_shoot(enemy) self.update_bullets() self.draw() # 游戏循环间隔(控制整体速度) self.game_loop_id = self.root.after(100, self.game_loop) elif not self.game_over and self.paused: # 暂停时继续检查,但不更新游戏逻辑 self.game_loop_id = self.root.after(100, self.game_loop) elif self.game_over: # 游戏结束时不再循环,等待用户操作 passclass Tank: """坦克类""" def __init__(self, x, y, type, color): self.x = x self.y = y self.type = type self.direction = 'up' self.color = colorclass Wall: """墙壁类""" def __init__(self, x, y): self.x = x self.y = yclass Bullet: """子弹类""" def __init__(self, x, y, direction, type): self.x = x self.y = y self.direction = direction self.type = typedef main(): root = tk.Tk() game = TankGame(root) root.mainloop()if __name__ == "__main__": main()