当前位置: 首页 > news >正文

python使用Pygame库实现避障小人行走游戏

python使用Pygame库实现避障小人行走游戏

能避开障碍物行走的小人:

一个小人在画布上随机移动;

玩家可以绘制障碍物,小人会自动避开;

玩家可以使用橡皮擦擦除障碍物。

点击“走”按钮开始小人物移动;

点击“停”按钮停止小人物移动;

可以使用速度滑块调整小人物移动速度。

点击"画笔"按钮后,在游戏区域按住鼠标左键并拖动绘制障碍物。

点击"橡皮"按钮后,在游戏区域按住鼠标左键并拖动清除障碍物。

点击"重玩"按钮重置游戏。

这个游戏html版本,可见:

https://blog.csdn.net/cnds123/article/details/148573128

关于Python中的pygame游戏模块的介绍,可参见 https://blog.csdn.net/cnds123/article/details/119514520

游戏截图:

游戏源码如下:

import pygame
import sys
import math
import random# 初始化pygame
pygame.init()# 屏幕设置
WIDTH, HEIGHT = 1100, 700  # 增加宽度以容纳说明区域
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Avoidance Character Game")# 设置中文字体
try:# 尝试使用系统中文字体font = pygame.font.SysFont('simhei', 24)  # 黑体title_font = pygame.font.SysFont('simhei', 30)small_font = pygame.font.SysFont('simhei', 18)
except:# 如果系统字体不可用,使用默认字体font = pygame.font.Font(None, 24)title_font = pygame.font.Font(None, 30)small_font = pygame.font.Font(None, 18)# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (52, 152, 219)
RED = (231, 76, 60)
GREEN = (46, 204, 113)
LIGHT_BLUE = (173, 216, 230)
PINK = (255, 159, 243)
GRAY = (200, 200, 200)
BG_COLOR = (240, 240, 240)
DARK_BLUE = (74, 105, 189)
LIGHT_GRAY = (241, 242, 246)# 游戏区域定义 - 放在左侧
GAME_AREA_WIDTH = 700
GAME_AREA = pygame.Rect(20, 150, GAME_AREA_WIDTH, HEIGHT - 200)# 说明区域 - 放在右侧
INSTRUCTION_AREA = pygame.Rect(GAME_AREA.right + 20, 150, WIDTH - GAME_AREA.right - 40, HEIGHT - 200)# 游戏状态
class GameState:def __init__(self):self.is_moving = Falseself.speed = 2self.tool = "brush"  # "brush" 或 "eraser"self.is_drawing = Falseself.step = 0# 障碍物表面self.obstacle_surface = pygame.Surface((GAME_AREA_WIDTH, GAME_AREA.height), pygame.SRCALPHA)self.obstacle_surface.fill((0, 0, 0, 0))  # 透明背景# 小人属性 - 初始位置在游戏区域内self.character = {"x": random.randint(GAME_AREA.left + 50, GAME_AREA.right - 50),"y": random.randint(GAME_AREA.top + 50, GAME_AREA.bottom - 50),"direction": random.uniform(0, 2 * math.pi),"size": 30}# 创建游戏状态
game_state = GameState()# 按钮类
class Button:def __init__(self, x, y, width, height, text, color, hover_color):self.rect = pygame.Rect(x, y, width, height)self.text = textself.color = colorself.hover_color = hover_colorself.is_hovered = Falsedef draw(self, surface):color = self.hover_color if self.is_hovered else self.colorpygame.draw.rect(surface, color, self.rect, border_radius=25)pygame.draw.rect(surface, BLACK, self.rect, 2, border_radius=25)text_surface = font.render(self.text, True, WHITE)text_rect = text_surface.get_rect(center=self.rect.center)surface.blit(text_surface, text_rect)def check_hover(self, pos):self.is_hovered = self.rect.collidepoint(pos)def is_clicked(self, pos, event):if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:return self.rect.collidepoint(pos)return False# 创建按钮
start_btn = Button(50, 50, 100, 50, "走", GREEN, (39, 174, 96))
stop_btn = Button(170, 50, 100, 50, "停", RED, (192, 57, 43))
brush_btn = Button(290, 50, 100, 50, "画笔", BLUE, (41, 128, 185))
eraser_btn = Button(410, 50, 100, 50, "橡皮", LIGHT_BLUE, (93, 173, 226))
reset_btn = Button(530, 50, 100, 50, "重玩", (155, 89, 182), (142, 68, 173))buttons = [start_btn, stop_btn, brush_btn, eraser_btn, reset_btn]# 滑块类
class Slider:def __init__(self, x, y, width, height, min_val, max_val, initial_val):self.rect = pygame.Rect(x, y, width, height)self.min_val = min_valself.max_val = max_valself.value = initial_valself.dragging = Falseself.knob_radius = 15def draw(self, surface):# 绘制滑轨pygame.draw.rect(surface, (211, 211, 211), self.rect, border_radius=10)# 计算滑块位置knob_x = self.rect.x + (self.value - self.min_val) / (self.max_val - self.min_val) * self.rect.width# 绘制滑块pygame.draw.circle(surface, BLUE, (int(knob_x), self.rect.centery), self.knob_radius)# 显示数值text = font.render(f"移动速度: {int(self.value)}", True, BLACK)surface.blit(text, (self.rect.x, self.rect.y - 30))def handle_event(self, event):if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:mouse_pos = pygame.mouse.get_pos()knob_x = self.rect.x + (self.value - self.min_val) / (self.max_val - self.min_val) * self.rect.widthknob_rect = pygame.Rect(knob_x - self.knob_radius, self.rect.centery - self.knob_radius, self.knob_radius * 2, self.knob_radius * 2)if knob_rect.collidepoint(mouse_pos):self.dragging = Trueelif event.type == pygame.MOUSEBUTTONUP and event.button == 1:self.dragging = Falseelif event.type == pygame.MOUSEMOTION and self.dragging:mouse_x = pygame.mouse.get_pos()[0]# 限制在滑轨范围内mouse_x = max(self.rect.x, min(mouse_x, self.rect.x + self.rect.width))# 计算新值self.value = self.min_val + (mouse_x - self.rect.x) / self.rect.width * (self.max_val - self.min_val)self.value = int(self.value)# 创建滑块
speed_slider = Slider(650, 65, 200, 10, 1, 10, 2)# 绘制网格背景
def draw_grid():grid_size = 30for x in range(GAME_AREA.left, GAME_AREA.right, grid_size):pygame.draw.line(screen, GRAY, (x, GAME_AREA.top), (x, GAME_AREA.bottom), 1)for y in range(GAME_AREA.top, GAME_AREA.bottom, grid_size):pygame.draw.line(screen, GRAY, (GAME_AREA.left, y), (GAME_AREA.right, y), 1)# 绘制小人
def draw_character():char = game_state.characterx, y = char["x"], char["y"]size = char["size"]# 身体pygame.draw.circle(screen, BLUE, (int(x), int(y)), size // 3)# 头部pygame.draw.circle(screen, PINK, (int(x), int(y - size // 2)), size // 3)# 腿leg_angle = math.sin(game_state.step * 0.1) * math.pi / 6 if game_state.is_moving else 0pygame.draw.line(screen, BLUE, (x - 5, y + size // 4), (x - 10 * math.cos(leg_angle), y + size // 1.2 * math.sin(leg_angle)), 4)pygame.draw.line(screen, BLUE, (x + 5, y + size // 4), (x + 10 * math.cos(-leg_angle), y + size // 1.2 * math.sin(-leg_angle)), 4)# 眼睛pygame.draw.circle(screen, BLACK, (int(x - 4), int(y - size // 2 - 2)), 2)pygame.draw.circle(screen, BLACK, (int(x + 4), int(y - size // 2 - 2)), 2)# 嘴巴pygame.draw.arc(screen, BLACK, (x - 3, y - size // 2, 6, 6), 0, math.pi, 2)# 检测碰撞
def check_collision():char = game_state.charactersize = char["size"]# 创建一个小矩形区域来检测碰撞rect = pygame.Rect(char["x"] - size // 2, char["y"] - size // 2, size, size)# 检查这个区域内是否有非透明像素for x in range(int(rect.left), int(rect.right)):for y in range(int(rect.top), int(rect.bottom)):if GAME_AREA.left <= x < GAME_AREA.right and GAME_AREA.top <= y < GAME_AREA.bottom:# 获取像素的alpha值(需要调整坐标,因为障碍物表面只包含游戏区域)rel_x = x - GAME_AREA.leftrel_y = y - GAME_AREA.topalpha = game_state.obstacle_surface.get_at((rel_x, rel_y))[3]if alpha > 128:  # 如果遇到非透明像素return Truereturn False# 移动小人
def move_character():if not game_state.is_moving:returnchar = game_state.characterold_x, old_y = char["x"], char["y"]# 计算新位置char["x"] += math.cos(char["direction"]) * game_state.speedchar["y"] += math.sin(char["direction"]) * game_state.speed# 边界检测 - 限制在游戏区域内if char["x"] < GAME_AREA.left + char["size"] / 2:char["x"] = GAME_AREA.left + char["size"] / 2char["direction"] = math.pi - char["direction"]elif char["x"] > GAME_AREA.right - char["size"] / 2:char["x"] = GAME_AREA.right - char["size"] / 2char["direction"] = math.pi - char["direction"]if char["y"] < GAME_AREA.top + char["size"] / 2:char["y"] = GAME_AREA.top + char["size"] / 2char["direction"] = -char["direction"]elif char["y"] > GAME_AREA.bottom - char["size"] / 2:char["y"] = GAME_AREA.bottom - char["size"] / 2char["direction"] = -char["direction"]# 碰撞检测if check_collision():# 恢复位置char["x"], char["y"] = old_x, old_y# 改变方向char["direction"] = random.uniform(0, 2 * math.pi)# 随机改变方向(小概率)if random.random() < 0.02:char["direction"] += (random.random() - 0.5) * math.pi / 2# 增加步数game_state.step += 1# 重置游戏
def reset_game():game_state.is_moving = Falsegame_state.speed = 2game_state.tool = "brush"game_state.step = 0game_state.character["x"] = random.randint(GAME_AREA.left + 50, GAME_AREA.right - 50)game_state.character["y"] = random.randint(GAME_AREA.top + 50, GAME_AREA.bottom - 50)game_state.character["direction"] = random.uniform(0, 2 * math.pi)game_state.obstacle_surface.fill((0, 0, 0, 0))  # 清除障碍物speed_slider.value = 2# 绘制状态信息
def draw_status():status = "行走中" if game_state.is_moving else "停止"text = font.render(f"当前状态: {status} | 速度: {game_state.speed}", True, BLACK)screen.blit(text, (WIDTH // 2 - 100, HEIGHT - 40))# 绘制游戏说明 - 在右侧独立区域显示
def draw_instructions():# 绘制说明区域背景pygame.draw.rect(screen, LIGHT_GRAY, INSTRUCTION_AREA, border_radius=10)pygame.draw.rect(screen, DARK_BLUE, INSTRUCTION_AREA, 2, border_radius=10)instructions = ["游戏说明:","• 点击'走'按钮开始小人物移动","• 点击'停'按钮停止小人物移动", "• 使用速度滑块调整小人物移动速度","• 点击'画笔'按钮后,在游戏区域按住","  鼠标左键并拖动绘制障碍物","• 点击'橡皮'按钮后,在游戏区域按住","  鼠标左键并拖动清除障碍物","• 点击'重玩'按钮重置游戏","","当前工具: " + ("画笔" if game_state.tool == "brush" else "橡皮")]# 在说明区域内显示start_x = INSTRUCTION_AREA.x + 15start_y = INSTRUCTION_AREA.y + 15line_height = 25for i, line in enumerate(instructions):text = small_font.render(line, True, BLACK)screen.blit(text, (start_x, start_y + i * line_height))# 绘制标题
def draw_title():title_text = title_font.render("行走的小人会自动避开您绘制的障碍物", True, WHITE)title_rect = title_text.get_rect(center=(WIDTH // 2, 20))# 绘制标题背景pygame.draw.rect(screen, DARK_BLUE, (0, 0, WIDTH, 50))screen.blit(title_text, title_rect)# 主游戏循环
clock = pygame.time.Clock()
last_pos = Nonerunning = True
while running:mouse_pos = pygame.mouse.get_pos()for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 处理按钮点击for button in buttons:button.check_hover(mouse_pos)if button.is_clicked(mouse_pos, event):if button == start_btn:game_state.is_moving = Trueelif button == stop_btn:game_state.is_moving = Falseelif button == brush_btn:game_state.tool = "brush"elif button == eraser_btn:game_state.tool = "eraser"elif button == reset_btn:reset_game()# 处理滑块speed_slider.handle_event(event)game_state.speed = speed_slider.value# 处理绘制/擦除if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:# 检查是否在游戏区域内if GAME_AREA.collidepoint(mouse_pos):game_state.is_drawing = Truelast_pos = mouse_posif game_state.tool == "brush":# 转换为障碍物表面的相对坐标rel_pos = (mouse_pos[0] - GAME_AREA.left, mouse_pos[1] - GAME_AREA.top)pygame.draw.circle(game_state.obstacle_surface, BLUE, rel_pos, 2)elif game_state.tool == "eraser":rel_pos = (mouse_pos[0] - GAME_AREA.left, mouse_pos[1] - GAME_AREA.top)pygame.draw.circle(game_state.obstacle_surface, (0, 0, 0, 0), rel_pos, 10)elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:game_state.is_drawing = Falselast_pos = Noneelif event.type == pygame.MOUSEMOTION and game_state.is_drawing:# 检查是否在游戏区域内if GAME_AREA.collidepoint(mouse_pos):if last_pos:if game_state.tool == "brush":rel_last = (last_pos[0] - GAME_AREA.left, last_pos[1] - GAME_AREA.top)rel_current = (mouse_pos[0] - GAME_AREA.left, mouse_pos[1] - GAME_AREA.top)pygame.draw.line(game_state.obstacle_surface, BLUE, rel_last, rel_current, 4)elif game_state.tool == "eraser":rel_last = (last_pos[0] - GAME_AREA.left, last_pos[1] - GAME_AREA.top)rel_current = (mouse_pos[0] - GAME_AREA.left, mouse_pos[1] - GAME_AREA.top)pygame.draw.line(game_state.obstacle_surface, (0, 0, 0, 0), rel_last, rel_current, 20)last_pos = mouse_pos# 更新游戏状态move_character()# 绘制screen.fill(BG_COLOR)# 绘制标题draw_title()# 绘制游戏区域pygame.draw.rect(screen, WHITE, GAME_AREA)pygame.draw.rect(screen, DARK_BLUE, GAME_AREA, 3)# 绘制网格draw_grid()# 绘制障碍物(需要调整位置到游戏区域)screen.blit(game_state.obstacle_surface, (GAME_AREA.left, GAME_AREA.top))# 绘制小人draw_character()# 绘制UI元素for button in buttons:button.draw(screen)speed_slider.draw(screen)draw_status()draw_instructions()  # 在右侧独立区域显示pygame.display.flip()clock.tick(60)pygame.quit()
sys.exit()

http://www.dtcms.com/a/545809.html

相关文章:

  • 安徽网站建站系统平台百度竞价排名事件分析
  • 餐馆网站怎么做微信开放平台网站应用
  • Docker篇2-用python运行项目和docker运行冲突问题
  • Linux SDIO驱动框架深度解析与技术实践
  • 被禁止访问网站怎么办网站建设怎么支付款项
  • 公司有网站有什么好处东莞网页设计制作公司
  • 做外贸 网站网易免费企业邮箱登录入口
  • 自己怎么做网站免费的做网站用discuz还是wp
  • windows系统连接docker desktop启动的mysql
  • 个人信息网站汾阳网站建设
  • 惠州市两学一做网站网站建设归工商局管还是工信局管
  • 仓储服务 东莞网站建设 技术支持做网站报价单
  • 自助建站信息网中国做二手房最大的网站有哪些
  • 四川省安监站网址团员关系没转就作废吗
  • 【零基础学MySQL】第二章:SQL类型
  • 程序员做网站给女朋友帝国后台网站如何设置自动刷新首
  • 仓颉语言变量声明与赋值深度解析
  • 宁波网站建设与推广方案安徽元鼎建设公司网站
  • Spring AI Alibaba 【三】
  • C++继承机制:面向对象编程的基石
  • 公司网站设计很好的怎么看一个网站是什么时候做的
  • pc不同网段间的通信过程
  • 成功移植游戏《四叶苜蓿》第二章——支持Linux和龙芯
  • 移动网站开发百科评价校园网站建设范例
  • 网站建设 别墅国家信用信息公示系统查询入口
  • 实验室安全教育与管理平台学习记录(二)化学类安全2
  • 武功县住房与城乡建设局网站太阳能建设网站
  • SAP-ABAP:SAP ABAP中的数学艺术:掌握向上取整与向下取整实例详解
  • OpenEuler中mysql这是在执行 MySQL 密码重置操作时出现的 “找不到mysqld_safe命令” 的错误场景。
  • GXDE 25.1 发布:系统优化若干