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

MediaPipe+OpenCV的python实现交互式贪吃蛇小游戏

1,安装依赖

pip install opencv-python mediapipe numpy

2,代码

import cv2
import numpy as np
import mediapipe as mp
import random
import mathmp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
hands = mp_hands.Hands(static_image_mode=False,max_num_hands=1,min_detection_confidence=0.7,min_tracking_confidence=0.7
)WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (0, 0, 255)
BLUE = (255, 0, 0)
YELLOW = (0, 255, 255)
PURPLE = (255, 0, 255)
ORANGE = (0, 165, 255)class TrailSnakeGame:def __init__(self):self.reset()def reset(self):self.trail = []self.trail_length = 30  self.score = 0self.food_radius = 25  self.food = self.generate_food()  self.game_over = Falseself.snake_thickness = 15self.growth_amount = 10  self.min_trail_length_for_collision = 25  self.smoothing_factor = 0.7  self.last_smoothed_pos = Nonedef generate_food(self):food = {'pos': (random.randint(60, WINDOW_WIDTH - 60),random.randint(60, WINDOW_HEIGHT - 60)),'radius': self.food_radius,  'color': RED,'points': 1}return fooddef smooth_position(self, current_pos):"""平滑处理位置坐标,减少抖动"""if self.last_smoothed_pos is None:self.last_smoothed_pos = current_posreturn current_possmoothed_x = int(self.smoothing_factor * current_pos[0] +(1 - self.smoothing_factor) * self.last_smoothed_pos[0])smoothed_y = int(self.smoothing_factor * current_pos[1] +(1 - self.smoothing_factor) * self.last_smoothed_pos[1])smoothed_pos = (smoothed_x, smoothed_y)self.last_smoothed_pos = smoothed_posreturn smoothed_posdef update_trail(self, finger_pos):if self.game_over:returnif finger_pos is None:returnsmoothed_pos = self.smooth_position(finger_pos)if len(self.trail) > 0:last_pos = self.trail[-1]distance = math.sqrt((smoothed_pos[0] - last_pos[0]) ** 2 +(smoothed_pos[1] - last_pos[1]) ** 2)if distance < 3:  returnself.trail.append(smoothed_pos)if len(self.trail) > self.trail_length:self.trail.pop(0)self.check_food_collision(smoothed_pos)if len(self.trail) > self.min_trail_length_for_collision:self.check_self_collision()def check_food_collision(self, head_pos):if len(self.trail) == 0:returnfood_x, food_y = self.food['pos']distance = math.sqrt((head_pos[0] - food_x) ** 2 + (head_pos[1] - food_y) ** 2)collision_distance = self.snake_thickness + self.food['radius'] - 8if distance < collision_distance:self.score += self.food['points']self.trail_length += self.growth_amountself.food = self.generate_food()print(f"吃到食物!+{self.food['points']}分,当前分数: {self.score}, 拖尾长度: {self.trail_length}")def check_self_collision(self):if len(self.trail) < self.min_trail_length_for_collision:returnhead_pos = self.trail[-1]skip_points = max(15, int(len(self.trail) * 0.4))  collision_detected = Falsefor i in range(len(self.trail) - skip_points):body_pos = self.trail[i]distance = math.sqrt((head_pos[0] - body_pos[0]) ** 2 +(head_pos[1] - body_pos[1]) ** 2)collision_threshold = self.snake_thickness - 5if distance < collision_threshold:collision_detected = Truebreakif collision_detected:self.game_over = Trueprint(f"游戏结束!撞到自己了,当前分数: {self.score}")def draw(self, frame, finger_pos):game_frame = np.zeros((WINDOW_HEIGHT, WINDOW_WIDTH, 4), dtype=np.uint8)game_frame[:, :, 3] = 0if len(self.trail) > 1:for i in range(1, len(self.trail)):color_ratio = i / len(self.trail)r = int(255 * (1 - color_ratio))g = int(255 * color_ratio)b = int(128 + 127 * math.sin(color_ratio * math.pi))color = (b, g, r, 255)  cv2.line(game_frame, self.trail[i - 1], self.trail[i],color, self.snake_thickness, lineType=cv2.LINE_AA)if len(self.trail) > 0:head_pos = self.trail[-1]cv2.circle(game_frame, head_pos, self.snake_thickness, (0, 255, 0, 255), -1, lineType=cv2.LINE_AA)cv2.circle(game_frame, head_pos, self.snake_thickness // 2, (255, 255, 0, 255), 2, lineType=cv2.LINE_AA)food_pos = self.food['pos']cv2.circle(game_frame, food_pos, self.food['radius'], (0, 0, 255, 255), -1, lineType=cv2.LINE_AA)highlight_pos = (food_pos[0] - self.food['radius'] // 3, food_pos[1] - self.food['radius'] // 3)cv2.circle(game_frame, highlight_pos, self.food['radius'] // 4, (255, 255, 255, 200), -1, lineType=cv2.LINE_AA)cv2.circle(game_frame, food_pos, self.food['radius'] + 2, (255, 255, 255, 255), 2, lineType=cv2.LINE_AA)game_rgb = game_frame[:, :, :3]game_alpha = game_frame[:, :, 3] / 255.0frame_height, frame_width = frame.shape[:2]game_x_start = frame_width - WINDOW_WIDTHgame_y_start = 0if (game_x_start >= 0 and game_y_start >= 0 andgame_x_start + WINDOW_WIDTH <= frame_width andgame_y_start + WINDOW_HEIGHT <= frame_height):game_region = frame[game_y_start:game_y_start + WINDOW_HEIGHT,game_x_start:game_x_start + WINDOW_WIDTH]for c in range(3):game_region[:, :, c] = (game_rgb[:, :, c] * game_alpha +game_region[:, :, c] * (1 - game_alpha))cv2.putText(frame, f"Score: {self.score}", (frame_width - WINDOW_WIDTH + 20, 40),cv2.FONT_HERSHEY_SIMPLEX, 1, WHITE, 2)cv2.putText(frame, f"Trail Length: {len(self.trail)}",(frame_width - WINDOW_WIDTH + 20, 80),cv2.FONT_HERSHEY_SIMPLEX, 0.7, WHITE, 2)cv2.putText(frame, "Move your finger to control the snake",(frame_width - WINDOW_WIDTH + 20, WINDOW_HEIGHT - 30),cv2.FONT_HERSHEY_SIMPLEX, 0.6, WHITE, 1)if self.game_over:overlay = frame.copy()cv2.rectangle(overlay,(frame_width - WINDOW_WIDTH, 0),(frame_width, WINDOW_HEIGHT),(0, 0, 0, 128), -1)cv2.addWeighted(overlay, 0.5, frame, 0.5, 0, frame)cv2.putText(frame, "GAME OVER",(frame_width - WINDOW_WIDTH // 2 - 100, WINDOW_HEIGHT // 2 - 30),cv2.FONT_HERSHEY_SIMPLEX, 1.5, RED, 3)cv2.putText(frame, f"Final Score: {self.score}",(frame_width - WINDOW_WIDTH // 2 - 80, WINDOW_HEIGHT // 2 + 20),cv2.FONT_HERSHEY_SIMPLEX, 1, WHITE, 2)cv2.putText(frame, "Press 'R' to Restart",(frame_width - WINDOW_WIDTH // 2 - 80, WINDOW_HEIGHT // 2 + 60),cv2.FONT_HERSHEY_SIMPLEX, 0.7, WHITE, 2)return framedef get_finger_position(hand_landmarks, frame_shape):"""获取食指指尖位置"""index_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]h, w = frame_shape[:2]finger_x = int(index_tip.x * w)finger_y = int(index_tip.y * h)return (finger_x, finger_y)def main():cap = cv2.VideoCapture(0)game = TrailSnakeGame()cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)print("拖尾贪吃蛇游戏开始!")print("移动手指来控制蛇的移动")print("触碰红色大圆圈来获得分数并变长")print("避免让蛇头撞到自己的身体")print("按R重新开始游戏,按Q退出")while True:ret, frame = cap.read()if not ret:print("无法读取摄像头画面")breakframe = cv2.flip(frame, 1)rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)results = hands.process(rgb_frame)finger_pos = Nonegame_finger_pos = Noneif results.multi_hand_landmarks:for hand_landmarks in results.multi_hand_landmarks:mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)finger_pos = get_finger_position(hand_landmarks, frame.shape)if finger_pos:cv2.circle(frame, finger_pos, 12, (0, 255, 0), -1, lineType=cv2.LINE_AA)cv2.circle(frame, finger_pos, 8, (255, 255, 255), 2, lineType=cv2.LINE_AA)if finger_pos:frame_height, frame_width = frame.shape[:2]game_x_start = frame_width - WINDOW_WIDTHgame_y_start = 0if (game_x_start <= finger_pos[0] < frame_width andgame_y_start <= finger_pos[1] < WINDOW_HEIGHT):game_finger_x = finger_pos[0] - game_x_startgame_finger_y = finger_pos[1] - game_y_startgame_finger_pos = (game_finger_x, game_finger_y)game.update_trail(game_finger_pos)frame = game.draw(frame, game_finger_pos)cv2.imshow('Smooth Trail Snake Game', frame)key = cv2.waitKey(1) & 0xFFif key == ord('q'):breakelif key == ord('r'):game.reset()print("游戏重新开始!")cap.release()cv2.destroyAllWindows()print("游戏结束!")if __name__ == "__main__":main()

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

相关文章:

  • 解析网站dns软件外包公司如何接单
  • 汽车排放检测的 “模块化核心”:HORIBA OBS-ONE GS Unit 气体分析单元技术解析
  • 【每天一个AI小知识】:什么是联邦学习?
  • 安卓进阶——多媒体
  • Spring Boot3零基础教程,响应式编程的模型,笔记109
  • 解读IEC 60086-4 2025
  • 学做网站论坛 可以吗360建筑工程网
  • 济南旅游团购网站建设动态电子商务网站建设报告
  • 企业做网站用dedeCMS免费吗在线资源搜索引擎
  • 什么是离子注入的注入剂量?
  • 静态网站 挂马北京网站设计的公司价格
  • 厦门建设局网站商品房免费免费网站模板
  • 怎么做谷歌这样的网站刷赞网站推广免费链接
  • 5、foc控制系统——电流环设计
  • 代码随想录打卡day25:56.合并区间
  • 【C++】C++11新特性 (上)
  • vue3+ts element-plus动态Icon图标统一注册
  • 用户组管理指令大全
  • 网站建设经费保障青海网站开发多少钱
  • 跨越协议鸿沟:RS485转ETHERCAT网关在电力电动机保护中的破局之道
  • 【开题答辩全过程】以 扶贫农产品销售平台APP为例,包含答辩的问题和答案
  • 专业做网站建设公司有哪些o2o网站建设行业现状
  • 自己做网站服务器多少钱网站域名怎么修改吗
  • 黑马JAVAWeb-05 JDBC入门-预编译SQL-Mybatis入门-Mybatis日志输出-数据库连接池-增删改查-XML映射配置
  • 济南高端网站asp.net怎样做网站登录
  • 北京平台网站建设哪家好有口碑的镇江网站优化
  • 抖音来客如何实现自动回复
  • 网站设计入门闸北品牌网站建设
  • PhotoShop网页版(在线ps)在快速修复老照片,在线修旧如新
  • 网站怎么做评估wordpress获取当前子分类