XMWAI 0.4.2__py3-none-any.whl → 0.4.4__py3-none-any.whl
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/__init__.py +5 -3
- XMWAI/assets/1.png +0 -0
- XMWAI/assets/__init__.py +0 -0
- XMWAI/assets/g.png +0 -0
- XMWAI/assets/h.png +0 -0
- XMWAI/assets/l.png +0 -0
- XMWAI/assets/m.png +0 -0
- XMWAI/assets/s.png +0 -0
- XMWAI/assets/t.png +0 -0
- XMWAI/assets//321/205/342/225/233/320/276/321/210/342/225/234/320/277/321/211/320/253/320/225/321/211/342/225/227/320/241.ttf +0 -0
- XMWAI/snake_core.py +426 -0
- {xmwai-0.4.2.dist-info → xmwai-0.4.4.dist-info}/METADATA +2 -1
- {xmwai-0.4.2.dist-info → xmwai-0.4.4.dist-info}/RECORD +16 -6
- {xmwai-0.4.2.dist-info → xmwai-0.4.4.dist-info}/WHEEL +0 -0
- {xmwai-0.4.2.dist-info → xmwai-0.4.4.dist-info}/licenses/LICENSE.txt +0 -0
- {xmwai-0.4.2.dist-info → xmwai-0.4.4.dist-info}/top_level.txt +0 -0
XMWAI/__init__.py
CHANGED
|
@@ -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"] # 可选:明确导出的内容
|
XMWAI/assets/1.png
ADDED
|
Binary file
|
XMWAI/assets/__init__.py
ADDED
|
File without changes
|
XMWAI/assets/g.png
ADDED
|
Binary file
|
XMWAI/assets/h.png
ADDED
|
Binary file
|
XMWAI/assets/l.png
ADDED
|
Binary file
|
XMWAI/assets/m.png
ADDED
|
Binary file
|
XMWAI/assets/s.png
ADDED
|
Binary file
|
XMWAI/assets/t.png
ADDED
|
Binary file
|
|
Binary file
|
XMWAI/snake_core.py
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
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
|
+
import XMWAI.assets # 引入资源目录
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# ---------- 工具函数:从 assets 读取资源 ----------
|
|
15
|
+
def get_asset_path(filename: str) -> str:
|
|
16
|
+
"""
|
|
17
|
+
获取包内资源的绝对路径 (兼容 pip 安装后的情况)
|
|
18
|
+
"""
|
|
19
|
+
with pkg_resources.path(XMWAI.assets, filename) as p:
|
|
20
|
+
return str(p)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SnakeGame:
|
|
24
|
+
def __init__(self, width=720, height=720, snakeInitLength=150, snakeGrowth=50,
|
|
25
|
+
snakeLineWidth=10, snakeHeadSize=15, foodPaths=None, foodNames=None, foodScores=None,
|
|
26
|
+
obstaclePaths=None, fontPath=None):
|
|
27
|
+
|
|
28
|
+
self.resolution = (width, height)
|
|
29
|
+
self.snakeInitLength = snakeInitLength
|
|
30
|
+
self._snakeGrowth = snakeGrowth
|
|
31
|
+
self._snakeHeadSize = snakeHeadSize
|
|
32
|
+
self._foodScores = foodScores if foodScores is not None else [3, 2, 1]
|
|
33
|
+
self.snakeLineWidth = snakeLineWidth
|
|
34
|
+
|
|
35
|
+
# 默认资源路径
|
|
36
|
+
if foodPaths is None:
|
|
37
|
+
foodPaths = [get_asset_path("h.png"),
|
|
38
|
+
get_asset_path("s.png"),
|
|
39
|
+
get_asset_path("t.png")]
|
|
40
|
+
if foodNames is None:
|
|
41
|
+
foodNames = ["汉堡", "薯条", "甜甜圈"]
|
|
42
|
+
if obstaclePaths is None:
|
|
43
|
+
obstaclePaths = [get_asset_path("g.png"),
|
|
44
|
+
get_asset_path("l.png"),
|
|
45
|
+
get_asset_path("m.png")]
|
|
46
|
+
if fontPath is None:
|
|
47
|
+
fontPath = get_asset_path("微软雅黑.ttf")
|
|
48
|
+
|
|
49
|
+
self.foodPaths = foodPaths
|
|
50
|
+
self.foodNames = foodNames
|
|
51
|
+
self.obstaclePaths = obstaclePaths
|
|
52
|
+
self.fontPath = fontPath
|
|
53
|
+
|
|
54
|
+
self.cap = None
|
|
55
|
+
self.detector = None
|
|
56
|
+
self.snake = None
|
|
57
|
+
self.foodManager = None
|
|
58
|
+
self.obstacleManager = None
|
|
59
|
+
self.img = None
|
|
60
|
+
self.overlayTexts = []
|
|
61
|
+
|
|
62
|
+
self.timer = 30
|
|
63
|
+
self.start_time = None
|
|
64
|
+
|
|
65
|
+
self._init_game_objects()
|
|
66
|
+
self.open_window()
|
|
67
|
+
|
|
68
|
+
# ----------- 属性自动同步 -----------
|
|
69
|
+
@property
|
|
70
|
+
def snakeHeadSize(self):
|
|
71
|
+
return self._snakeHeadSize
|
|
72
|
+
|
|
73
|
+
@snakeHeadSize.setter
|
|
74
|
+
def snakeHeadSize(self, value):
|
|
75
|
+
self._snakeHeadSize = value
|
|
76
|
+
if self.snake:
|
|
77
|
+
self.snake.headSize = value
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def foodScores(self):
|
|
81
|
+
return self._foodScores
|
|
82
|
+
|
|
83
|
+
@foodScores.setter
|
|
84
|
+
def foodScores(self, scores):
|
|
85
|
+
self._foodScores = scores
|
|
86
|
+
if self.foodManager:
|
|
87
|
+
self.foodManager.foodScores = scores
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def snakeGrowth(self):
|
|
91
|
+
return self._snakeGrowth
|
|
92
|
+
|
|
93
|
+
@snakeGrowth.setter
|
|
94
|
+
def snakeGrowth(self, value):
|
|
95
|
+
self._snakeGrowth = value
|
|
96
|
+
|
|
97
|
+
# ---------------- 工具函数 ----------------
|
|
98
|
+
def _putChineseText(self, img, text, pos, fontSize=40, color=(0, 0, 255)):
|
|
99
|
+
img_pil = Image.fromarray(img)
|
|
100
|
+
draw = ImageDraw.Draw(img_pil)
|
|
101
|
+
try:
|
|
102
|
+
font = ImageFont.truetype(self.fontPath, fontSize)
|
|
103
|
+
except OSError:
|
|
104
|
+
font = ImageFont.load_default()
|
|
105
|
+
draw.text(pos, text, font=font, fill=color)
|
|
106
|
+
return np.array(img_pil)
|
|
107
|
+
|
|
108
|
+
def _init_game_objects(self):
|
|
109
|
+
self.snake = self.Snake(color=(0, 0, 255), initLength=self.snakeInitLength,
|
|
110
|
+
lineWidth=self.snakeLineWidth, headSize=self._snakeHeadSize)
|
|
111
|
+
self.foodManager = self.FoodManager(
|
|
112
|
+
self.foodPaths, self.foodNames, self._foodScores)
|
|
113
|
+
self.obstacleManager = self.ObstacleManager(self.obstaclePaths)
|
|
114
|
+
self.obstacleManager.randomObstacles()
|
|
115
|
+
|
|
116
|
+
def _render_frame(self, show_food=True, show_obstacle=True):
|
|
117
|
+
success, self.img = self.cap.read()
|
|
118
|
+
if not success:
|
|
119
|
+
return
|
|
120
|
+
self.img = cv2.flip(self.img, 1)
|
|
121
|
+
hands, self.img = self.detector.findHands(self.img, flipType=False)
|
|
122
|
+
player_head = tuple(hands[0]['lmList'][8][0:2]) if hands else None
|
|
123
|
+
|
|
124
|
+
if not self.snake.gameOver and player_head:
|
|
125
|
+
self.snake.update(self.img, player_head, self.obstacleManager)
|
|
126
|
+
|
|
127
|
+
if not self.snake.gameOver and player_head and show_food:
|
|
128
|
+
cx, cy = player_head
|
|
129
|
+
rx, ry = self.foodManager.foodPoint
|
|
130
|
+
w, h = self.foodManager.wFood, self.foodManager.hFood
|
|
131
|
+
if rx - w//2 <= cx <= rx + w//2 and ry - h//2 <= cy <= ry + h//2:
|
|
132
|
+
self.snake.score += self.foodManager.foodScores[self.foodManager.foodIndex]
|
|
133
|
+
self.snake.allowedLength += self._snakeGrowth
|
|
134
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
135
|
+
|
|
136
|
+
if show_obstacle:
|
|
137
|
+
self.img = self.obstacleManager.draw(self.img)
|
|
138
|
+
self.obstacleManager.moveObstacles(
|
|
139
|
+
self.resolution[0], self.resolution[1])
|
|
140
|
+
|
|
141
|
+
if show_food:
|
|
142
|
+
self.img = self.foodManager.draw(self.img)
|
|
143
|
+
|
|
144
|
+
# ---------------- 对外接口 ----------------
|
|
145
|
+
def open_window(self):
|
|
146
|
+
self.cap = cv2.VideoCapture(0)
|
|
147
|
+
self.cap.set(3, self.resolution[0])
|
|
148
|
+
self.cap.set(4, self.resolution[1])
|
|
149
|
+
self.detector = HandDetector(detectionCon=0.7, maxHands=1)
|
|
150
|
+
success, self.img = self.cap.read()
|
|
151
|
+
if not success:
|
|
152
|
+
print("摄像头打开失败")
|
|
153
|
+
return
|
|
154
|
+
self.img = cv2.flip(self.img, 1)
|
|
155
|
+
cv2.imshow("AI Snake", self.img)
|
|
156
|
+
cv2.waitKey(1)
|
|
157
|
+
|
|
158
|
+
def hand(self):
|
|
159
|
+
if self.cap is None:
|
|
160
|
+
print("请先调用 open_window()")
|
|
161
|
+
return
|
|
162
|
+
if self.detector is None:
|
|
163
|
+
self.detector = HandDetector(detectionCon=0.8, maxHands=1)
|
|
164
|
+
while True:
|
|
165
|
+
success, self.img = self.cap.read()
|
|
166
|
+
if not success:
|
|
167
|
+
break
|
|
168
|
+
self.img = cv2.flip(self.img, 1)
|
|
169
|
+
hands, self.img = self.detector.findHands(self.img, flipType=False)
|
|
170
|
+
cv2.imshow("AI Snake", self.img)
|
|
171
|
+
key = cv2.waitKey(1) & 0xFF
|
|
172
|
+
if hands or key == ord('q'):
|
|
173
|
+
break
|
|
174
|
+
|
|
175
|
+
def display(self):
|
|
176
|
+
if self.img is None:
|
|
177
|
+
self._render_frame(show_food=False)
|
|
178
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
179
|
+
self._render_frame(show_food=True)
|
|
180
|
+
self.overlayTexts = [
|
|
181
|
+
(f'玩家分数:{self.snake.score}', (50, 50), 30, (255, 0, 255)),
|
|
182
|
+
(f'倒计时:{self.timer} 秒', (50, 120), 30, (255, 0, 255))
|
|
183
|
+
]
|
|
184
|
+
img_copy = self.img.copy()
|
|
185
|
+
for txt, pos, size, color in self.overlayTexts:
|
|
186
|
+
img_copy = self._putChineseText(img_copy, txt, pos, size, color)
|
|
187
|
+
cv2.imshow("AI Snake", img_copy)
|
|
188
|
+
cv2.waitKey(1)
|
|
189
|
+
|
|
190
|
+
# ---------------- 重置游戏 ----------------
|
|
191
|
+
def reset_game(self):
|
|
192
|
+
self.snake.reset()
|
|
193
|
+
self.snake.headSize = self._snakeHeadSize
|
|
194
|
+
self.obstacleManager.randomObstacles()
|
|
195
|
+
self.foodManager.foodScores = self._foodScores
|
|
196
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
197
|
+
self.start_time = time.time()
|
|
198
|
+
self.timer = 30
|
|
199
|
+
if self.cap is None or not self.cap.isOpened():
|
|
200
|
+
self.open_window()
|
|
201
|
+
|
|
202
|
+
# ---------------- 游戏结束 ----------------
|
|
203
|
+
def gameover(self, path=None, size=(100, 100)):
|
|
204
|
+
if path is None:
|
|
205
|
+
path = get_asset_path("1.png")
|
|
206
|
+
|
|
207
|
+
if os.path.exists(path):
|
|
208
|
+
gameover_img = cv2.imread(path)
|
|
209
|
+
gameover_img = cv2.resize(gameover_img, self.resolution)
|
|
210
|
+
else:
|
|
211
|
+
gameover_img = np.zeros(
|
|
212
|
+
(self.resolution[1], self.resolution[0], 3), np.uint8)
|
|
213
|
+
cv2.putText(gameover_img, "Game Over Image Missing!", (50, 100),
|
|
214
|
+
cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 3)
|
|
215
|
+
|
|
216
|
+
gameover_img = self._putChineseText(
|
|
217
|
+
gameover_img, f"最终分数:{self.snake.score}", size, 40, (68, 84, 106))
|
|
218
|
+
|
|
219
|
+
while True:
|
|
220
|
+
cv2.imshow("AI Snake", gameover_img)
|
|
221
|
+
key = cv2.waitKey(0) & 0xFF
|
|
222
|
+
if key == ord('r'): # 重启游戏
|
|
223
|
+
self.reset_game()
|
|
224
|
+
self.start()
|
|
225
|
+
break
|
|
226
|
+
elif key == ord('q'): # 退出游戏
|
|
227
|
+
if self.cap is not None:
|
|
228
|
+
self.cap.release()
|
|
229
|
+
cv2.destroyAllWindows()
|
|
230
|
+
break
|
|
231
|
+
|
|
232
|
+
# ---------------- 游戏主循环 ----------------
|
|
233
|
+
def start(self):
|
|
234
|
+
if self.cap is None or not self.cap.isOpened():
|
|
235
|
+
self.open_window()
|
|
236
|
+
self.start_time = time.time()
|
|
237
|
+
self.timer = 30
|
|
238
|
+
|
|
239
|
+
while True:
|
|
240
|
+
if self.snake.gameOver or self.timer == 0:
|
|
241
|
+
# 游戏结束,进入 gameover 界面
|
|
242
|
+
self.gameover()
|
|
243
|
+
break
|
|
244
|
+
|
|
245
|
+
self._render_frame(show_food=True, show_obstacle=True)
|
|
246
|
+
elapsed = int(time.time() - self.start_time)
|
|
247
|
+
self.timer = max(0, 30 - elapsed)
|
|
248
|
+
|
|
249
|
+
self.overlayTexts = [
|
|
250
|
+
(f'玩家分数:{self.snake.score}', (50, 50), 30, (255, 0, 255)),
|
|
251
|
+
(f'倒计时:{self.timer} 秒', (50, 120), 30, (255, 0, 255))
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
if self.img is not None:
|
|
255
|
+
img_copy = self.img.copy()
|
|
256
|
+
for txt, pos, size, color in self.overlayTexts:
|
|
257
|
+
img_copy = self._putChineseText(
|
|
258
|
+
img_copy, txt, pos, size, color)
|
|
259
|
+
cv2.imshow("AI Snake", img_copy)
|
|
260
|
+
|
|
261
|
+
key = cv2.waitKey(1)
|
|
262
|
+
if key == ord('r'): # 游戏中途重置
|
|
263
|
+
self.reset_game()
|
|
264
|
+
elif key == ord('q'):
|
|
265
|
+
if self.cap is not None:
|
|
266
|
+
self.cap.release()
|
|
267
|
+
cv2.destroyAllWindows()
|
|
268
|
+
break
|
|
269
|
+
|
|
270
|
+
# ---------------- 内部类:蛇 ----------------
|
|
271
|
+
class Snake:
|
|
272
|
+
def __init__(self, color, initLength=150, lineWidth=10, headSize=15):
|
|
273
|
+
self.points = []
|
|
274
|
+
self.currentLength = 0
|
|
275
|
+
self.allowedLength = initLength
|
|
276
|
+
self.previousHead = None
|
|
277
|
+
self.score = 0
|
|
278
|
+
self.color = color
|
|
279
|
+
self.gameOver = False
|
|
280
|
+
self.lineWidth = lineWidth
|
|
281
|
+
self.headSize = headSize
|
|
282
|
+
|
|
283
|
+
def reset(self):
|
|
284
|
+
self.points = []
|
|
285
|
+
self.currentLength = 0
|
|
286
|
+
self.allowedLength = 150
|
|
287
|
+
self.previousHead = None
|
|
288
|
+
self.score = 0
|
|
289
|
+
self.gameOver = False
|
|
290
|
+
|
|
291
|
+
def update(self, imgMain, currentHead, obstacleManager=None):
|
|
292
|
+
if self.gameOver:
|
|
293
|
+
return
|
|
294
|
+
cx, cy = currentHead
|
|
295
|
+
if cx is None or cy is None:
|
|
296
|
+
return
|
|
297
|
+
if self.previousHead is None:
|
|
298
|
+
self.previousHead = (cx, cy)
|
|
299
|
+
px, py = self.previousHead
|
|
300
|
+
|
|
301
|
+
alpha = 0.7
|
|
302
|
+
cx = int(px * (1 - alpha) + cx * alpha)
|
|
303
|
+
cy = int(py * (1 - alpha) + cy * alpha)
|
|
304
|
+
|
|
305
|
+
maxStep = 50
|
|
306
|
+
dx = cx - px
|
|
307
|
+
dy = cy - py
|
|
308
|
+
distance = math.hypot(dx, dy)
|
|
309
|
+
if distance > maxStep:
|
|
310
|
+
steps = int(distance / maxStep)
|
|
311
|
+
for i in range(1, steps + 1):
|
|
312
|
+
ix = int(px + dx * i / steps)
|
|
313
|
+
iy = int(py + dy * i / steps)
|
|
314
|
+
self.points.append((ix, iy))
|
|
315
|
+
self.currentLength += maxStep
|
|
316
|
+
else:
|
|
317
|
+
self.points.append((cx, cy))
|
|
318
|
+
self.currentLength += distance
|
|
319
|
+
|
|
320
|
+
self.previousHead = (cx, cy)
|
|
321
|
+
|
|
322
|
+
while self.currentLength > self.allowedLength:
|
|
323
|
+
if len(self.points) > 1:
|
|
324
|
+
removed_dx = self.points[1][0] - self.points[0][0]
|
|
325
|
+
removed_dy = self.points[1][1] - self.points[0][1]
|
|
326
|
+
removed_dist = math.hypot(removed_dx, removed_dy)
|
|
327
|
+
self.currentLength -= removed_dist
|
|
328
|
+
self.points.pop(0)
|
|
329
|
+
|
|
330
|
+
for i in range(1, len(self.points)):
|
|
331
|
+
cv2.line(
|
|
332
|
+
imgMain, self.points[i-1], self.points[i], self.color, self.lineWidth)
|
|
333
|
+
|
|
334
|
+
snakeHeadColor = (random.randint(0, 255), random.randint(
|
|
335
|
+
0, 255), random.randint(0, 255))
|
|
336
|
+
cv2.circle(imgMain, (cx, cy), self.headSize,
|
|
337
|
+
snakeHeadColor, cv2.FILLED)
|
|
338
|
+
|
|
339
|
+
h, w, _ = imgMain.shape
|
|
340
|
+
margin = 5
|
|
341
|
+
if cx <= margin or cx >= w - margin or cy <= margin or cy >= h - margin:
|
|
342
|
+
self.gameOver = True
|
|
343
|
+
|
|
344
|
+
if obstacleManager:
|
|
345
|
+
for ox, oy, ow, oh, *_ in obstacleManager.obstacles:
|
|
346
|
+
if ox <= cx <= ox + ow and oy <= cy <= oy + oh:
|
|
347
|
+
self.gameOver = True
|
|
348
|
+
|
|
349
|
+
# ---------------- 内部类:食物 ----------------
|
|
350
|
+
class FoodManager:
|
|
351
|
+
def __init__(self, foodPaths, foodNames, foodScores):
|
|
352
|
+
self.foodImages = []
|
|
353
|
+
for path in foodPaths:
|
|
354
|
+
if os.path.exists(path):
|
|
355
|
+
self.foodImages.append(
|
|
356
|
+
cv2.imread(path, cv2.IMREAD_UNCHANGED))
|
|
357
|
+
else:
|
|
358
|
+
self.foodImages.append(np.zeros((50, 50, 4), np.uint8))
|
|
359
|
+
self.foodNames = foodNames
|
|
360
|
+
self.foodScores = foodScores
|
|
361
|
+
self.foodIndex = 0
|
|
362
|
+
self.hFood, self.wFood = 0, 0
|
|
363
|
+
self.foodPoint = 0, 0
|
|
364
|
+
self.randomFoodLocation()
|
|
365
|
+
|
|
366
|
+
def randomFoodLocation(self, obstacleManager=None):
|
|
367
|
+
max_attempts = 100
|
|
368
|
+
for _ in range(max_attempts):
|
|
369
|
+
self.foodPoint = random.randint(
|
|
370
|
+
50, 1230), random.randint(50, 670)
|
|
371
|
+
self.foodIndex = random.randint(0, len(self.foodImages)-1)
|
|
372
|
+
self.hFood, self.wFood, _ = self.foodImages[self.foodIndex].shape
|
|
373
|
+
if obstacleManager:
|
|
374
|
+
overlap = False
|
|
375
|
+
for ox, oy, ow, oh, *_ in obstacleManager.obstacles:
|
|
376
|
+
if ox < self.foodPoint[0] < ox + ow and oy < self.foodPoint[1] < oy + oh:
|
|
377
|
+
overlap = True
|
|
378
|
+
break
|
|
379
|
+
if not overlap:
|
|
380
|
+
return
|
|
381
|
+
return
|
|
382
|
+
|
|
383
|
+
def draw(self, imgMain):
|
|
384
|
+
rx, ry = self.foodPoint
|
|
385
|
+
imgMain = cvzone.overlayPNG(imgMain, self.foodImages[self.foodIndex],
|
|
386
|
+
(rx - self.wFood//2, ry - self.hFood//2))
|
|
387
|
+
return imgMain
|
|
388
|
+
|
|
389
|
+
# ---------------- 内部类:障碍 ----------------
|
|
390
|
+
class ObstacleManager:
|
|
391
|
+
def __init__(self, obstaclePaths):
|
|
392
|
+
self.obstacleImages = []
|
|
393
|
+
for path in obstaclePaths:
|
|
394
|
+
if os.path.exists(path):
|
|
395
|
+
self.obstacleImages.append(
|
|
396
|
+
cv2.imread(path, cv2.IMREAD_UNCHANGED))
|
|
397
|
+
else:
|
|
398
|
+
self.obstacleImages.append(np.zeros((50, 50, 4), np.uint8))
|
|
399
|
+
self.obstacles = []
|
|
400
|
+
|
|
401
|
+
def randomObstacles(self):
|
|
402
|
+
self.obstacles.clear()
|
|
403
|
+
for img in self.obstacleImages:
|
|
404
|
+
h, w, _ = img.shape
|
|
405
|
+
x = random.randint(150, 1230)
|
|
406
|
+
y = random.randint(50, 670)
|
|
407
|
+
dx = random.choice([-5, 5])
|
|
408
|
+
dy = random.choice([-5, 5])
|
|
409
|
+
self.obstacles.append([x, y, w, h, dx, dy, img])
|
|
410
|
+
|
|
411
|
+
def moveObstacles(self, wMax, hMax):
|
|
412
|
+
for obs in self.obstacles:
|
|
413
|
+
x, y, ow, oh, dx, dy, img = obs
|
|
414
|
+
x += dx
|
|
415
|
+
y += dy
|
|
416
|
+
if x <= 0 or x + ow >= wMax:
|
|
417
|
+
dx *= -1
|
|
418
|
+
if y <= 0 or y + oh >= hMax:
|
|
419
|
+
dy *= -1
|
|
420
|
+
obs[0], obs[1], obs[4], obs[5] = x, y, dx, dy
|
|
421
|
+
|
|
422
|
+
def draw(self, imgMain):
|
|
423
|
+
for obs in self.obstacles:
|
|
424
|
+
x, y, w, h, dx, dy, img = obs
|
|
425
|
+
imgMain = cvzone.overlayPNG(imgMain, img, (int(x), int(y)))
|
|
426
|
+
return imgMain
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: XMWAI
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
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
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
XMWAI/__init__.py,sha256
|
|
1
|
+
XMWAI/__init__.py,sha256=RFHMM1PF3ELvHSMeKe2G2E0astGPum2ezuf8Hjw4D6g,968
|
|
2
2
|
XMWAI/bomb_core.py,sha256=h2ZPH3SuoG2L_XOf1dcK8p3lhw5QzhneWl2yMLj1RiU,1819
|
|
3
3
|
XMWAI/core.py,sha256=rOXj7FnewSdnzBcFLjpnBtrOTCsvMfiycIcdPDagxho,10012
|
|
4
4
|
XMWAI/idiom_core.py,sha256=yU-VHhqqoutVm6GVikcjL3m9yuB1hUsFBpPYvwY4n5g,1689
|
|
5
5
|
XMWAI/magic_core.py,sha256=Ms4b12PJ8rjsmceg1VUqWCWx2ebvdhLp4sIF6K_Vaok,3491
|
|
6
|
+
XMWAI/snake_core.py,sha256=oa0pGvcomna_oXknVa5PasbRw0ILEdThfNExJjRbz8w,16418
|
|
6
7
|
XMWAI/trial_class.py,sha256=fPsl7BZvhzch2FOIG4azr999kjtoly53Acm3LqL8f98,9724
|
|
7
8
|
XMWAI/web_core.py,sha256=7awPg1kYW3lYrbgylqJvUF3g050bn6H21PgmQ7Kv1wA,10927
|
|
9
|
+
XMWAI/assets/1.png,sha256=eEuKH_M_q3tc_O2bYnuLOsRP-NlJHIbNg0pgrKXEEjw,139720
|
|
10
|
+
XMWAI/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
XMWAI/assets/g.png,sha256=hr9hlKJ7y95X-g6-tllrzDNgL1WQkbq5cA5L4jASEAM,11686
|
|
12
|
+
XMWAI/assets/h.png,sha256=qO-kJJOPA8qUth5rqLeOVa_6_n7tU-ABQ14O0EW_YCE,14929
|
|
13
|
+
XMWAI/assets/l.png,sha256=Urm6LxH33HID6ZZbs2oMViUk4GiZ3upLPdsrNU8FlP0,9921
|
|
14
|
+
XMWAI/assets/m.png,sha256=4tl9Rb2JoMD7XLMj3w8jg-92y6D7O-1u0sZCYEoeUtk,10303
|
|
15
|
+
XMWAI/assets/s.png,sha256=v_qmHGmSPhG838vXQdUR2ZX_Z5KLI8T46kaR4P_ktUg,15120
|
|
16
|
+
XMWAI/assets/t.png,sha256=GebzA2UWhXn4u62UeuUjitdpwnJvnxfZ2z_4MFlxvm8,12838
|
|
17
|
+
XMWAI/assets/微软雅黑.ttf,sha256=dpc4EmGE1ojdwHjfIwTdr3olyEDAk3FwyreQSC9AdQ8,15043584
|
|
8
18
|
XMWAI/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
19
|
XMWAI/file/idiom.json,sha256=HUtPRUzhxBbWoasjadbmbA_5ngQ5AXLu9weQSZ4hzhk,10319857
|
|
10
20
|
XMWAI/gif/0.gif,sha256=LGpAReVTyZEb1J-bWYTpxxHbIxmLJ-3wA0lw4cBqdsY,303
|
|
@@ -107,8 +117,8 @@ XMWAI/static/images/tomato.png,sha256=FEOEAOdUhW_BDFgTpxOkYc0I5Iu29_gtHb3RIPEej0
|
|
|
107
117
|
XMWAI/templates/burger.html,sha256=vDnxpSW8phetyScySsalScZnFKl3LNpy5lJjKxGXgbI,3320
|
|
108
118
|
XMWAI/templates/nutrition_pie.html,sha256=yJVXI28i-UfvF0xOXGSNLMb8oCJNhh2J3zoRDr5_7DM,5567
|
|
109
119
|
XMWAI/templates/创意菜谱.html,sha256=RcDgH58QLyUJ9A59wobu3wvchGBY1snVsXcZQZam5M0,4805
|
|
110
|
-
xmwai-0.4.
|
|
111
|
-
xmwai-0.4.
|
|
112
|
-
xmwai-0.4.
|
|
113
|
-
xmwai-0.4.
|
|
114
|
-
xmwai-0.4.
|
|
120
|
+
xmwai-0.4.4.dist-info/licenses/LICENSE.txt,sha256=bcaIQMrIhdQ3O-PoZlexjmW6h-wLGvHxh5Oksl4ohtc,1066
|
|
121
|
+
xmwai-0.4.4.dist-info/METADATA,sha256=Qsm0Z6Kkd35aNmUsTNNp4AmIrlIAPYVxnJP8VPiPLs0,1227
|
|
122
|
+
xmwai-0.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
123
|
+
xmwai-0.4.4.dist-info/top_level.txt,sha256=yvGcDI-sggK5jqd9wz0saipZvk3oIE3hNGHlqUjxf0c,6
|
|
124
|
+
xmwai-0.4.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|