XMWAI 0.4.2__tar.gz → 0.4.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of XMWAI might be problematic. Click here for more details.
- {xmwai-0.4.2 → xmwai-0.4.5}/MANIFEST.in +2 -1
- {xmwai-0.4.2/XMWAI.egg-info → xmwai-0.4.5}/PKG-INFO +2 -1
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/__init__.py +5 -3
- xmwai-0.4.5/XMWAI/assets/1.png +0 -0
- xmwai-0.4.5/XMWAI/assets/g.png +0 -0
- xmwai-0.4.5/XMWAI/assets/h.png +0 -0
- xmwai-0.4.5/XMWAI/assets/l.png +0 -0
- xmwai-0.4.5/XMWAI/assets/m.png +0 -0
- xmwai-0.4.5/XMWAI/assets/s.png +0 -0
- xmwai-0.4.5/XMWAI/assets/t.png +0 -0
- xmwai-0.4.5/XMWAI/assets//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
- xmwai-0.4.5/XMWAI/gif/__init__.py +0 -0
- xmwai-0.4.5/XMWAI/snake_core.py +389 -0
- {xmwai-0.4.2 → xmwai-0.4.5/XMWAI.egg-info}/PKG-INFO +2 -1
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI.egg-info/SOURCES.txt +10 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI.egg-info/requires.txt +1 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/setup.py +4 -2
- {xmwai-0.4.2 → xmwai-0.4.5}/LICENSE.txt +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/README.md +0 -0
- {xmwai-0.4.2/XMWAI/file → xmwai-0.4.5/XMWAI/assets}/__init__.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/bomb_core.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/core.py +0 -0
- {xmwai-0.4.2/XMWAI/gif → xmwai-0.4.5/XMWAI/file}/__init__.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/file/idiom.json +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/0.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/1.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/10.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/11.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/12.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/13.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/14.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/15.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/16.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/17.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/18.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/19.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/2.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/20.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/21.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/22.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/23.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/24.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/25.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/26.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/27.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/28.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/29.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/3.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/30.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/31.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/32.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/33.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/34.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/35.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/36.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/37.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/38.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/39.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/4.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/40.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/41.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/42.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/43.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/44.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/45.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/46.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/47.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/48.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/49.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/5.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/50.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/51.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/52.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/53.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/54.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/55.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/56.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/57.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/58.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/59.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/6.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/60.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/61.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/62.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/63.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/64.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/65.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/66.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/67.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/68.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/69.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/7.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/70.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/71.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/72.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/73.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/74.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/75.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/76.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/77.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/78.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/79.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/8.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/80.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/81.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/82.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/83.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/84.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/85.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/gif/9.gif +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/idiom_core.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/magic_core.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/burger.js +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/BottomBun.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/TopBun.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/beef.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/bg.jpeg +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/bg.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/cheese.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/lettuce.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/sauce.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/static/images/tomato.png +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/templates/burger.html +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/templates/nutrition_pie.html +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/templates//345/210/233/346/204/217/350/217/234/350/260/261.html" +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/trial_class.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/web_core.py +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI.egg-info/dependency_links.txt +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/XMWAI.egg-info/top_level.txt +0 -0
- {xmwai-0.4.2 → xmwai-0.4.5}/setup.cfg +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
recursive-include XMWAI/gif *
|
|
2
2
|
recursive-include XMWAI/file *.json
|
|
3
3
|
recursive-include XMWAI/templates *.html
|
|
4
|
-
recursive-include XMWAI/static *.js *.css *.png *.jpg *.gif *.jpeg
|
|
4
|
+
recursive-include XMWAI/static *.js *.css *.png *.jpg *.gif *.jpeg
|
|
5
|
+
recursive-include XMWAI/assets *
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: XMWAI
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Small code King AI related library
|
|
5
5
|
Home-page: https://github.com/Tonykai88/XMWAI.git
|
|
6
6
|
Author: pydevelopment
|
|
@@ -17,6 +17,7 @@ Requires-Dist: opencv-python>=3.4.18.65
|
|
|
17
17
|
Requires-Dist: numpy>=1.26.0
|
|
18
18
|
Requires-Dist: flask>=3.1.0
|
|
19
19
|
Requires-Dist: pyecharts>=2.0.8
|
|
20
|
+
Requires-Dist: cvzone>=1.6.1
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: author-email
|
|
22
23
|
Dynamic: classifier
|
|
@@ -2,10 +2,12 @@ from .core import story, photo, reply, poem, crack, show # 从子模块导入
|
|
|
2
2
|
from .magic_core import birthday # 从子模块导入函数到顶层
|
|
3
3
|
from .bomb_core import bomb # 从子模块导入函数到顶层
|
|
4
4
|
from .idiom_core import idiom, searchIdiom, get_json_path # 从子模块导入函数到顶层
|
|
5
|
-
from .trial_class import make, get_file_content_as_base64, save_pic,
|
|
5
|
+
from .trial_class import make, get_file_content_as_base64, save_pic, detect_scale, open_image, get_file_content_as_base64_2, cartoon # 从子模块导入函数到顶层
|
|
6
6
|
from .web_core import burger, cookbook # 从子模块导入函数到顶层
|
|
7
|
+
from .snake_core import SnakeGame
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
__all__ = ["story", "photo", "reply", "poem", 'birthday', 'bomb',
|
|
9
11
|
"idiom", "searchIdiom", "get_json_path", "crack", "show",
|
|
10
|
-
"make", "get_file_content_as_base64", "save_pic", "
|
|
11
|
-
"get_file_content_as_base64_2", "cartoon", "burger", "cookbook"] # 可选:明确导出的内容
|
|
12
|
+
"make", "get_file_content_as_base64", "save_pic", "detect_scale", "open_image",
|
|
13
|
+
"get_file_content_as_base64_2", "cartoon", "burger", "cookbook", "SnakeGame"] # 可选:明确导出的内容
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
import math
|
|
3
|
+
import random
|
|
4
|
+
import cvzone
|
|
5
|
+
import numpy as np
|
|
6
|
+
from cvzone.HandTrackingModule import HandDetector
|
|
7
|
+
from PIL import ImageFont, ImageDraw, Image
|
|
8
|
+
import os
|
|
9
|
+
import time
|
|
10
|
+
import importlib.resources as pkg_resources
|
|
11
|
+
|
|
12
|
+
# 引入包内资源
|
|
13
|
+
import XMWAI.assets as assets
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_asset_path(filename: str) -> str:
|
|
17
|
+
"""获取包内资源的路径"""
|
|
18
|
+
with pkg_resources.path(assets, filename) as p:
|
|
19
|
+
return str(p)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SnakeGame:
|
|
23
|
+
def __init__(self, width=720, height=720, snakeInitLength=150, snakeGrowth=50,
|
|
24
|
+
snakeLineWidth=10, snakeHeadSize=15, foodPaths=None, foodNames=None, foodScores=None,
|
|
25
|
+
obstaclePaths=None, fontPath=None):
|
|
26
|
+
|
|
27
|
+
self.resolution = (width, height)
|
|
28
|
+
self.snakeInitLength = snakeInitLength
|
|
29
|
+
self._snakeGrowth = snakeGrowth
|
|
30
|
+
self._snakeHeadSize = snakeHeadSize
|
|
31
|
+
self._foodScores = foodScores if foodScores is not None else [3, 2, 1]
|
|
32
|
+
self.snakeLineWidth = snakeLineWidth
|
|
33
|
+
|
|
34
|
+
# 字体路径(默认取包内字体)
|
|
35
|
+
self.fontPath = fontPath or get_asset_path("微软雅黑.ttf")
|
|
36
|
+
|
|
37
|
+
# 默认资源路径
|
|
38
|
+
if foodPaths is None:
|
|
39
|
+
foodPaths = [get_asset_path("h.png"),
|
|
40
|
+
get_asset_path("s.png"),
|
|
41
|
+
get_asset_path("t.png")]
|
|
42
|
+
if foodNames is None:
|
|
43
|
+
foodNames = ["汉堡", "薯条", "甜甜圈"]
|
|
44
|
+
if obstaclePaths is None:
|
|
45
|
+
obstaclePaths = [get_asset_path("g.png"),
|
|
46
|
+
get_asset_path("l.png"),
|
|
47
|
+
get_asset_path("m.png")]
|
|
48
|
+
|
|
49
|
+
self.foodPaths = foodPaths
|
|
50
|
+
self.foodNames = foodNames
|
|
51
|
+
self.obstaclePaths = obstaclePaths
|
|
52
|
+
|
|
53
|
+
self.cap = None
|
|
54
|
+
self.detector = None
|
|
55
|
+
self.snake = None
|
|
56
|
+
self.foodManager = None
|
|
57
|
+
self.obstacleManager = None
|
|
58
|
+
self.img = None
|
|
59
|
+
self.overlayTexts = []
|
|
60
|
+
|
|
61
|
+
self.timer = 30
|
|
62
|
+
self.start_time = None
|
|
63
|
+
|
|
64
|
+
self._init_game_objects()
|
|
65
|
+
self.open_window()
|
|
66
|
+
|
|
67
|
+
# ----------- 属性自动同步 -----------
|
|
68
|
+
@property
|
|
69
|
+
def snakeHeadSize(self):
|
|
70
|
+
return self._snakeHeadSize
|
|
71
|
+
|
|
72
|
+
@snakeHeadSize.setter
|
|
73
|
+
def snakeHeadSize(self, value):
|
|
74
|
+
self._snakeHeadSize = value
|
|
75
|
+
if self.snake:
|
|
76
|
+
self.snake.headSize = value
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def foodScores(self):
|
|
80
|
+
return self._foodScores
|
|
81
|
+
|
|
82
|
+
@foodScores.setter
|
|
83
|
+
def foodScores(self, scores):
|
|
84
|
+
self._foodScores = scores
|
|
85
|
+
if self.foodManager:
|
|
86
|
+
self.foodManager.foodScores = scores
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def snakeGrowth(self):
|
|
90
|
+
return self._snakeGrowth
|
|
91
|
+
|
|
92
|
+
@snakeGrowth.setter
|
|
93
|
+
def snakeGrowth(self, value):
|
|
94
|
+
self._snakeGrowth = value
|
|
95
|
+
|
|
96
|
+
# ---------------- 工具函数 ----------------
|
|
97
|
+
def _putChineseText(self, img, text, pos, fontSize=40, color=(0, 0, 255)):
|
|
98
|
+
img_pil = Image.fromarray(img)
|
|
99
|
+
draw = ImageDraw.Draw(img_pil)
|
|
100
|
+
try:
|
|
101
|
+
font = ImageFont.truetype(self.fontPath, fontSize)
|
|
102
|
+
except OSError:
|
|
103
|
+
font = ImageFont.load_default()
|
|
104
|
+
draw.text(pos, text, font=font, fill=color)
|
|
105
|
+
return np.array(img_pil)
|
|
106
|
+
|
|
107
|
+
def _init_game_objects(self):
|
|
108
|
+
self.snake = self.Snake(color=(0, 0, 255), initLength=self.snakeInitLength,
|
|
109
|
+
lineWidth=self.snakeLineWidth, headSize=self._snakeHeadSize)
|
|
110
|
+
self.foodManager = self.FoodManager(
|
|
111
|
+
self.foodPaths, self.foodNames, self._foodScores)
|
|
112
|
+
self.obstacleManager = self.ObstacleManager(self.obstaclePaths)
|
|
113
|
+
self.obstacleManager.randomObstacles()
|
|
114
|
+
|
|
115
|
+
def _render_frame(self, show_food=True, show_obstacle=True):
|
|
116
|
+
success, self.img = self.cap.read()
|
|
117
|
+
if not success:
|
|
118
|
+
return
|
|
119
|
+
self.img = cv2.flip(self.img, 1)
|
|
120
|
+
hands, self.img = self.detector.findHands(self.img, flipType=False)
|
|
121
|
+
player_head = tuple(hands[0]['lmList'][8][0:2]) if hands else None
|
|
122
|
+
|
|
123
|
+
if not self.snake.gameOver and player_head:
|
|
124
|
+
self.snake.update(self.img, player_head, self.obstacleManager)
|
|
125
|
+
|
|
126
|
+
if not self.snake.gameOver and player_head and show_food:
|
|
127
|
+
cx, cy = player_head
|
|
128
|
+
rx, ry = self.foodManager.foodPoint
|
|
129
|
+
w, h = self.foodManager.wFood, self.foodManager.hFood
|
|
130
|
+
if rx - w//2 <= cx <= rx + w//2 and ry - h//2 <= cy <= ry + h//2:
|
|
131
|
+
self.snake.score += self.foodManager.foodScores[self.foodManager.foodIndex]
|
|
132
|
+
self.snake.allowedLength += self._snakeGrowth
|
|
133
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
134
|
+
|
|
135
|
+
if show_obstacle:
|
|
136
|
+
self.img = self.obstacleManager.draw(self.img)
|
|
137
|
+
self.obstacleManager.moveObstacles(
|
|
138
|
+
self.resolution[0], self.resolution[1])
|
|
139
|
+
|
|
140
|
+
if show_food:
|
|
141
|
+
self.img = self.foodManager.draw(self.img)
|
|
142
|
+
|
|
143
|
+
# ---------------- 对外接口 ----------------
|
|
144
|
+
def open_window(self):
|
|
145
|
+
self.cap = cv2.VideoCapture(0)
|
|
146
|
+
self.cap.set(3, self.resolution[0])
|
|
147
|
+
self.cap.set(4, self.resolution[1])
|
|
148
|
+
self.detector = HandDetector(detectionCon=0.7, maxHands=1)
|
|
149
|
+
success, self.img = self.cap.read()
|
|
150
|
+
if not success:
|
|
151
|
+
print("摄像头打开失败")
|
|
152
|
+
return
|
|
153
|
+
self.img = cv2.flip(self.img, 1)
|
|
154
|
+
cv2.imshow("AI Snake", self.img)
|
|
155
|
+
cv2.waitKey(1)
|
|
156
|
+
|
|
157
|
+
def reset_game(self):
|
|
158
|
+
self.snake.reset()
|
|
159
|
+
self.snake.headSize = self._snakeHeadSize
|
|
160
|
+
self.obstacleManager.randomObstacles()
|
|
161
|
+
self.foodManager.foodScores = self._foodScores
|
|
162
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
163
|
+
self.start_time = time.time()
|
|
164
|
+
self.timer = 30
|
|
165
|
+
if self.cap is None or not self.cap.isOpened():
|
|
166
|
+
self.open_window()
|
|
167
|
+
|
|
168
|
+
def gameover(self, path=None, size=(100, 100)):
|
|
169
|
+
if path is None:
|
|
170
|
+
path = get_asset_path("1.png")
|
|
171
|
+
|
|
172
|
+
if os.path.exists(path):
|
|
173
|
+
gameover_img = cv2.imread(path)
|
|
174
|
+
gameover_img = cv2.resize(gameover_img, self.resolution)
|
|
175
|
+
else:
|
|
176
|
+
gameover_img = np.zeros(
|
|
177
|
+
(self.resolution[1], self.resolution[0], 3), np.uint8)
|
|
178
|
+
cv2.putText(gameover_img, "Game Over Image Missing!", (50, 100),
|
|
179
|
+
cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 3)
|
|
180
|
+
|
|
181
|
+
gameover_img = self._putChineseText(
|
|
182
|
+
gameover_img, f"最终分数:{self.snake.score}", size, 40, (68, 84, 106))
|
|
183
|
+
|
|
184
|
+
while True:
|
|
185
|
+
cv2.imshow("AI Snake", gameover_img)
|
|
186
|
+
key = cv2.waitKey(0) & 0xFF
|
|
187
|
+
if key == ord('r'): # 重启游戏
|
|
188
|
+
self.reset_game()
|
|
189
|
+
self.start()
|
|
190
|
+
break
|
|
191
|
+
elif key == ord('q'): # 退出游戏
|
|
192
|
+
if self.cap is not None:
|
|
193
|
+
self.cap.release()
|
|
194
|
+
cv2.destroyAllWindows()
|
|
195
|
+
break
|
|
196
|
+
|
|
197
|
+
def start(self):
|
|
198
|
+
if self.cap is None or not self.cap.isOpened():
|
|
199
|
+
self.open_window()
|
|
200
|
+
self.start_time = time.time()
|
|
201
|
+
self.timer = 30
|
|
202
|
+
|
|
203
|
+
while True:
|
|
204
|
+
if self.snake.gameOver or self.timer == 0:
|
|
205
|
+
self.gameover()
|
|
206
|
+
break
|
|
207
|
+
|
|
208
|
+
self._render_frame(show_food=True, show_obstacle=True)
|
|
209
|
+
elapsed = int(time.time() - self.start_time)
|
|
210
|
+
self.timer = max(0, 30 - elapsed)
|
|
211
|
+
|
|
212
|
+
self.overlayTexts = [
|
|
213
|
+
(f'玩家分数:{self.snake.score}', (50, 50), 30, (255, 0, 255)),
|
|
214
|
+
(f'倒计时:{self.timer} 秒', (50, 120), 30, (255, 0, 255))
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
if self.img is not None:
|
|
218
|
+
img_copy = self.img.copy()
|
|
219
|
+
for txt, pos, size, color in self.overlayTexts:
|
|
220
|
+
img_copy = self._putChineseText(
|
|
221
|
+
img_copy, txt, pos, size, color)
|
|
222
|
+
cv2.imshow("AI Snake", img_copy)
|
|
223
|
+
|
|
224
|
+
key = cv2.waitKey(1)
|
|
225
|
+
if key == ord('r'):
|
|
226
|
+
self.reset_game()
|
|
227
|
+
elif key == ord('q'):
|
|
228
|
+
if self.cap is not None:
|
|
229
|
+
self.cap.release()
|
|
230
|
+
cv2.destroyAllWindows()
|
|
231
|
+
break
|
|
232
|
+
|
|
233
|
+
# ---------------- 内部类:蛇 ----------------
|
|
234
|
+
class Snake:
|
|
235
|
+
def __init__(self, color, initLength=150, lineWidth=10, headSize=15):
|
|
236
|
+
self.points = []
|
|
237
|
+
self.currentLength = 0
|
|
238
|
+
self.allowedLength = initLength
|
|
239
|
+
self.previousHead = None
|
|
240
|
+
self.score = 0
|
|
241
|
+
self.color = color
|
|
242
|
+
self.gameOver = False
|
|
243
|
+
self.lineWidth = lineWidth
|
|
244
|
+
self.headSize = headSize
|
|
245
|
+
|
|
246
|
+
def reset(self):
|
|
247
|
+
self.points = []
|
|
248
|
+
self.currentLength = 0
|
|
249
|
+
self.allowedLength = 150
|
|
250
|
+
self.previousHead = None
|
|
251
|
+
self.score = 0
|
|
252
|
+
self.gameOver = False
|
|
253
|
+
|
|
254
|
+
def update(self, imgMain, currentHead, obstacleManager=None):
|
|
255
|
+
if self.gameOver:
|
|
256
|
+
return
|
|
257
|
+
cx, cy = currentHead
|
|
258
|
+
if cx is None or cy is None:
|
|
259
|
+
return
|
|
260
|
+
if self.previousHead is None:
|
|
261
|
+
self.previousHead = (cx, cy)
|
|
262
|
+
px, py = self.previousHead
|
|
263
|
+
|
|
264
|
+
alpha = 0.7
|
|
265
|
+
cx = int(px * (1 - alpha) + cx * alpha)
|
|
266
|
+
cy = int(py * (1 - alpha) + cy * alpha)
|
|
267
|
+
|
|
268
|
+
maxStep = 50
|
|
269
|
+
dx = cx - px
|
|
270
|
+
dy = cy - py
|
|
271
|
+
distance = math.hypot(dx, dy)
|
|
272
|
+
if distance > maxStep:
|
|
273
|
+
steps = int(distance / maxStep)
|
|
274
|
+
for i in range(1, steps + 1):
|
|
275
|
+
ix = int(px + dx * i / steps)
|
|
276
|
+
iy = int(py + dy * i / steps)
|
|
277
|
+
self.points.append((ix, iy))
|
|
278
|
+
self.currentLength += maxStep
|
|
279
|
+
else:
|
|
280
|
+
self.points.append((cx, cy))
|
|
281
|
+
self.currentLength += distance
|
|
282
|
+
|
|
283
|
+
self.previousHead = (cx, cy)
|
|
284
|
+
|
|
285
|
+
while self.currentLength > self.allowedLength:
|
|
286
|
+
if len(self.points) > 1:
|
|
287
|
+
removed_dx = self.points[1][0] - self.points[0][0]
|
|
288
|
+
removed_dy = self.points[1][1] - self.points[0][1]
|
|
289
|
+
removed_dist = math.hypot(removed_dx, removed_dy)
|
|
290
|
+
self.currentLength -= removed_dist
|
|
291
|
+
self.points.pop(0)
|
|
292
|
+
|
|
293
|
+
for i in range(1, len(self.points)):
|
|
294
|
+
cv2.line(
|
|
295
|
+
imgMain, self.points[i-1], self.points[i], self.color, self.lineWidth)
|
|
296
|
+
|
|
297
|
+
snakeHeadColor = (random.randint(0, 255), random.randint(
|
|
298
|
+
0, 255), random.randint(0, 255))
|
|
299
|
+
cv2.circle(imgMain, (cx, cy), self.headSize,
|
|
300
|
+
snakeHeadColor, cv2.FILLED)
|
|
301
|
+
|
|
302
|
+
h, w, _ = imgMain.shape
|
|
303
|
+
margin = 5
|
|
304
|
+
if cx <= margin or cx >= w - margin or cy <= margin or cy >= h - margin:
|
|
305
|
+
self.gameOver = True
|
|
306
|
+
|
|
307
|
+
if obstacleManager:
|
|
308
|
+
for ox, oy, ow, oh, *_ in obstacleManager.obstacles:
|
|
309
|
+
if ox <= cx <= ox + ow and oy <= cy <= oy + oh:
|
|
310
|
+
self.gameOver = True
|
|
311
|
+
|
|
312
|
+
# ---------------- 内部类:食物 ----------------
|
|
313
|
+
class FoodManager:
|
|
314
|
+
def __init__(self, foodPaths, foodNames, foodScores):
|
|
315
|
+
self.foodImages = []
|
|
316
|
+
for path in foodPaths:
|
|
317
|
+
if os.path.exists(path):
|
|
318
|
+
self.foodImages.append(
|
|
319
|
+
cv2.imread(path, cv2.IMREAD_UNCHANGED))
|
|
320
|
+
else:
|
|
321
|
+
self.foodImages.append(np.zeros((50, 50, 4), np.uint8))
|
|
322
|
+
self.foodNames = foodNames
|
|
323
|
+
self.foodScores = foodScores
|
|
324
|
+
self.foodIndex = 0
|
|
325
|
+
self.hFood, self.wFood = 0, 0
|
|
326
|
+
self.foodPoint = 0, 0
|
|
327
|
+
self.randomFoodLocation()
|
|
328
|
+
|
|
329
|
+
def randomFoodLocation(self, obstacleManager=None):
|
|
330
|
+
max_attempts = 100
|
|
331
|
+
for _ in range(max_attempts):
|
|
332
|
+
self.foodPoint = random.randint(
|
|
333
|
+
50, 670), random.randint(50, 670)
|
|
334
|
+
self.foodIndex = random.randint(0, len(self.foodImages)-1)
|
|
335
|
+
self.hFood, self.wFood, _ = self.foodImages[self.foodIndex].shape
|
|
336
|
+
if obstacleManager:
|
|
337
|
+
overlap = False
|
|
338
|
+
for ox, oy, ow, oh, *_ in obstacleManager.obstacles:
|
|
339
|
+
if ox < self.foodPoint[0] < ox + ow and oy < self.foodPoint[1] < oy + oh:
|
|
340
|
+
overlap = True
|
|
341
|
+
break
|
|
342
|
+
if not overlap:
|
|
343
|
+
return
|
|
344
|
+
return
|
|
345
|
+
|
|
346
|
+
def draw(self, imgMain):
|
|
347
|
+
rx, ry = self.foodPoint
|
|
348
|
+
imgMain = cvzone.overlayPNG(imgMain, self.foodImages[self.foodIndex],
|
|
349
|
+
(rx - self.wFood//2, ry - self.hFood//2))
|
|
350
|
+
return imgMain
|
|
351
|
+
|
|
352
|
+
# ---------------- 内部类:障碍 ----------------
|
|
353
|
+
class ObstacleManager:
|
|
354
|
+
def __init__(self, obstaclePaths):
|
|
355
|
+
self.obstacleImages = []
|
|
356
|
+
for path in obstaclePaths:
|
|
357
|
+
if os.path.exists(path):
|
|
358
|
+
self.obstacleImages.append(
|
|
359
|
+
cv2.imread(path, cv2.IMREAD_UNCHANGED))
|
|
360
|
+
else:
|
|
361
|
+
self.obstacleImages.append(np.zeros((50, 50, 4), np.uint8))
|
|
362
|
+
self.obstacles = []
|
|
363
|
+
|
|
364
|
+
def randomObstacles(self):
|
|
365
|
+
self.obstacles.clear()
|
|
366
|
+
for img in self.obstacleImages:
|
|
367
|
+
h, w, _ = img.shape
|
|
368
|
+
x = random.randint(150, 600)
|
|
369
|
+
y = random.randint(50, 600)
|
|
370
|
+
dx = random.choice([-5, 5])
|
|
371
|
+
dy = random.choice([-5, 5])
|
|
372
|
+
self.obstacles.append([x, y, w, h, dx, dy, img])
|
|
373
|
+
|
|
374
|
+
def moveObstacles(self, wMax, hMax):
|
|
375
|
+
for obs in self.obstacles:
|
|
376
|
+
x, y, ow, oh, dx, dy, img = obs
|
|
377
|
+
x += dx
|
|
378
|
+
y += dy
|
|
379
|
+
if x <= 0 or x + ow >= wMax:
|
|
380
|
+
dx *= -1
|
|
381
|
+
if y <= 0 or y + oh >= hMax:
|
|
382
|
+
dy *= -1
|
|
383
|
+
obs[0], obs[1], obs[4], obs[5] = x, y, dx, dy
|
|
384
|
+
|
|
385
|
+
def draw(self, imgMain):
|
|
386
|
+
for obs in self.obstacles:
|
|
387
|
+
x, y, w, h, dx, dy, img = obs
|
|
388
|
+
imgMain = cvzone.overlayPNG(imgMain, img, (int(x), int(y)))
|
|
389
|
+
return imgMain
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: XMWAI
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Small code King AI related library
|
|
5
5
|
Home-page: https://github.com/Tonykai88/XMWAI.git
|
|
6
6
|
Author: pydevelopment
|
|
@@ -17,6 +17,7 @@ Requires-Dist: opencv-python>=3.4.18.65
|
|
|
17
17
|
Requires-Dist: numpy>=1.26.0
|
|
18
18
|
Requires-Dist: flask>=3.1.0
|
|
19
19
|
Requires-Dist: pyecharts>=2.0.8
|
|
20
|
+
Requires-Dist: cvzone>=1.6.1
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: author-email
|
|
22
23
|
Dynamic: classifier
|
|
@@ -7,6 +7,7 @@ XMWAI/bomb_core.py
|
|
|
7
7
|
XMWAI/core.py
|
|
8
8
|
XMWAI/idiom_core.py
|
|
9
9
|
XMWAI/magic_core.py
|
|
10
|
+
XMWAI/snake_core.py
|
|
10
11
|
XMWAI/trial_class.py
|
|
11
12
|
XMWAI/web_core.py
|
|
12
13
|
XMWAI.egg-info/PKG-INFO
|
|
@@ -14,6 +15,15 @@ XMWAI.egg-info/SOURCES.txt
|
|
|
14
15
|
XMWAI.egg-info/dependency_links.txt
|
|
15
16
|
XMWAI.egg-info/requires.txt
|
|
16
17
|
XMWAI.egg-info/top_level.txt
|
|
18
|
+
XMWAI/assets/1.png
|
|
19
|
+
XMWAI/assets/__init__.py
|
|
20
|
+
XMWAI/assets/g.png
|
|
21
|
+
XMWAI/assets/h.png
|
|
22
|
+
XMWAI/assets/l.png
|
|
23
|
+
XMWAI/assets/m.png
|
|
24
|
+
XMWAI/assets/s.png
|
|
25
|
+
XMWAI/assets/t.png
|
|
26
|
+
XMWAI/assets/微软雅黑.ttf
|
|
17
27
|
XMWAI/file/__init__.py
|
|
18
28
|
XMWAI/file/idiom.json
|
|
19
29
|
XMWAI/gif/0.gif
|
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name="XMWAI", # 包名(pip install XMWAI)
|
|
6
|
-
version="0.4.
|
|
6
|
+
version="0.4.5", # 每次上传记得升级版本号
|
|
7
7
|
author="pydevelopment", # 作者
|
|
8
8
|
author_email="hekai@xiaoma.cn", # 邮箱
|
|
9
9
|
description="Small code King AI related library", # 简短描述
|
|
@@ -22,6 +22,7 @@ setup(
|
|
|
22
22
|
],
|
|
23
23
|
"XMWAI.gif": ["*.gif"], # gif 文件夹下的所有 GIF
|
|
24
24
|
"XMWAI.file": ["*.json"], # file 文件夹下的 json
|
|
25
|
+
"XMWAI.assets": ["*.png", "*.ttf"], # 图片和字体
|
|
25
26
|
},
|
|
26
27
|
install_requires=[
|
|
27
28
|
"requests>=2.32.3", # 依赖包
|
|
@@ -29,7 +30,8 @@ setup(
|
|
|
29
30
|
"opencv-python>=3.4.18.65", # OpenCV 库
|
|
30
31
|
"numpy>=1.26.0", # 数值计算库
|
|
31
32
|
"flask>=3.1.0", # Web 框架
|
|
32
|
-
"pyecharts>=2.0.8" # 图表绘制库
|
|
33
|
+
"pyecharts>=2.0.8", # 图表绘制库
|
|
34
|
+
"cvzone>=1.6.1" # 手势识别库
|
|
33
35
|
],
|
|
34
36
|
classifiers=[
|
|
35
37
|
"Programming Language :: Python :: 3",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xmwai-0.4.2 → xmwai-0.4.5}/XMWAI/templates//345/210/233/346/204/217/350/217/234/350/260/261.html"
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|