XMWAI 0.4.1__tar.gz → 0.4.4__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.

Files changed (130) hide show
  1. {xmwai-0.4.1 → xmwai-0.4.4}/MANIFEST.in +2 -1
  2. {xmwai-0.4.1/XMWAI.egg-info → xmwai-0.4.4}/PKG-INFO +2 -1
  3. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/__init__.py +5 -3
  4. xmwai-0.4.4/XMWAI/assets/1.png +0 -0
  5. xmwai-0.4.4/XMWAI/assets/g.png +0 -0
  6. xmwai-0.4.4/XMWAI/assets/h.png +0 -0
  7. xmwai-0.4.4/XMWAI/assets/l.png +0 -0
  8. xmwai-0.4.4/XMWAI/assets/m.png +0 -0
  9. xmwai-0.4.4/XMWAI/assets/s.png +0 -0
  10. xmwai-0.4.4/XMWAI/assets/t.png +0 -0
  11. xmwai-0.4.4/XMWAI/assets//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  12. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/core.py +2 -2
  13. xmwai-0.4.4/XMWAI/gif/__init__.py +0 -0
  14. xmwai-0.4.4/XMWAI/snake_core.py +426 -0
  15. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/trial_class.py +53 -49
  16. {xmwai-0.4.1 → xmwai-0.4.4/XMWAI.egg-info}/PKG-INFO +2 -1
  17. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/SOURCES.txt +10 -0
  18. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/requires.txt +1 -0
  19. {xmwai-0.4.1 → xmwai-0.4.4}/setup.py +5 -2
  20. {xmwai-0.4.1 → xmwai-0.4.4}/LICENSE.txt +0 -0
  21. {xmwai-0.4.1 → xmwai-0.4.4}/README.md +0 -0
  22. {xmwai-0.4.1/XMWAI/file → xmwai-0.4.4/XMWAI/assets}/__init__.py +0 -0
  23. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/bomb_core.py +0 -0
  24. {xmwai-0.4.1/XMWAI/gif → xmwai-0.4.4/XMWAI/file}/__init__.py +0 -0
  25. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/file/idiom.json +0 -0
  26. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/0.gif +0 -0
  27. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/1.gif +0 -0
  28. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/10.gif +0 -0
  29. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/11.gif +0 -0
  30. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/12.gif +0 -0
  31. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/13.gif +0 -0
  32. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/14.gif +0 -0
  33. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/15.gif +0 -0
  34. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/16.gif +0 -0
  35. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/17.gif +0 -0
  36. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/18.gif +0 -0
  37. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/19.gif +0 -0
  38. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/2.gif +0 -0
  39. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/20.gif +0 -0
  40. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/21.gif +0 -0
  41. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/22.gif +0 -0
  42. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/23.gif +0 -0
  43. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/24.gif +0 -0
  44. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/25.gif +0 -0
  45. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/26.gif +0 -0
  46. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/27.gif +0 -0
  47. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/28.gif +0 -0
  48. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/29.gif +0 -0
  49. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/3.gif +0 -0
  50. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/30.gif +0 -0
  51. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/31.gif +0 -0
  52. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/32.gif +0 -0
  53. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/33.gif +0 -0
  54. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/34.gif +0 -0
  55. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/35.gif +0 -0
  56. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/36.gif +0 -0
  57. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/37.gif +0 -0
  58. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/38.gif +0 -0
  59. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/39.gif +0 -0
  60. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/4.gif +0 -0
  61. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/40.gif +0 -0
  62. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/41.gif +0 -0
  63. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/42.gif +0 -0
  64. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/43.gif +0 -0
  65. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/44.gif +0 -0
  66. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/45.gif +0 -0
  67. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/46.gif +0 -0
  68. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/47.gif +0 -0
  69. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/48.gif +0 -0
  70. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/49.gif +0 -0
  71. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/5.gif +0 -0
  72. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/50.gif +0 -0
  73. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/51.gif +0 -0
  74. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/52.gif +0 -0
  75. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/53.gif +0 -0
  76. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/54.gif +0 -0
  77. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/55.gif +0 -0
  78. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/56.gif +0 -0
  79. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/57.gif +0 -0
  80. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/58.gif +0 -0
  81. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/59.gif +0 -0
  82. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/6.gif +0 -0
  83. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/60.gif +0 -0
  84. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/61.gif +0 -0
  85. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/62.gif +0 -0
  86. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/63.gif +0 -0
  87. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/64.gif +0 -0
  88. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/65.gif +0 -0
  89. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/66.gif +0 -0
  90. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/67.gif +0 -0
  91. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/68.gif +0 -0
  92. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/69.gif +0 -0
  93. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/7.gif +0 -0
  94. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/70.gif +0 -0
  95. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/71.gif +0 -0
  96. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/72.gif +0 -0
  97. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/73.gif +0 -0
  98. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/74.gif +0 -0
  99. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/75.gif +0 -0
  100. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/76.gif +0 -0
  101. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/77.gif +0 -0
  102. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/78.gif +0 -0
  103. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/79.gif +0 -0
  104. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/8.gif +0 -0
  105. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/80.gif +0 -0
  106. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/81.gif +0 -0
  107. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/82.gif +0 -0
  108. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/83.gif +0 -0
  109. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/84.gif +0 -0
  110. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/85.gif +0 -0
  111. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/9.gif +0 -0
  112. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/idiom_core.py +0 -0
  113. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/magic_core.py +0 -0
  114. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/burger.js +0 -0
  115. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/BottomBun.png +0 -0
  116. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/TopBun.png +0 -0
  117. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/beef.png +0 -0
  118. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/bg.jpeg +0 -0
  119. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/bg.png +0 -0
  120. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/cheese.png +0 -0
  121. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/lettuce.png +0 -0
  122. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/sauce.png +0 -0
  123. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/tomato.png +0 -0
  124. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates/burger.html +0 -0
  125. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates/nutrition_pie.html +0 -0
  126. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates//345/210/233/346/204/217/350/217/234/350/260/261.html" +0 -0
  127. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/web_core.py +0 -0
  128. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/dependency_links.txt +0 -0
  129. {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/top_level.txt +0 -0
  130. {xmwai-0.4.1 → xmwai-0.4.4}/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.1
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
@@ -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, detect_windows_scale, get_file_content_as_base64_2, cartoon # 从子模块导入函数到顶层
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", "detect_windows_scale",
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
@@ -36,7 +36,7 @@ def story(role, time, address, event, key=""):
36
36
  print("秘钥错误!请重新输入!")
37
37
  return "秘钥错误!请重新输入!"
38
38
  header = {
39
- "Authorization": "AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
39
+ "Authorization": "Bearer AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
40
40
  }
41
41
  response = requests.post(url, headers=header, json=data, stream=True)
42
42
 
@@ -135,7 +135,7 @@ def reply(role, content, key=""):
135
135
  print("秘钥错误!请重新输入!")
136
136
  return "秘钥错误!请重新输入!"
137
137
  header = {
138
- "Authorization": "AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
138
+ "Authorization": "Bearer AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
139
139
  }
140
140
  response = requests.post(url, headers=header, json=data, stream=True)
141
141
 
File without changes
@@ -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
@@ -13,6 +13,9 @@ import cv2
13
13
  import numpy as np
14
14
 
15
15
  '''-----------体验课1-----------'''
16
+ import urllib.parse
17
+ import platform
18
+ from io import BytesIO
16
19
 
17
20
 
18
21
  def make(screen):
@@ -57,9 +60,8 @@ def make(screen):
57
60
  # 发送创建任务请求
58
61
  response = requests.post(create_url, headers=headers,
59
62
  data=create_payload.encode("utf-8"))
60
- response.raise_for_status() # 检查请求是否成功
63
+ response.raise_for_status()
61
64
  task_id = response.json()["data"]["task_id"]
62
- # print(f"任务已创建,ID: {task_id}")
63
65
 
64
66
  # 轮询检查任务状态
65
67
  query_payload = json.dumps({"task_id": task_id}, ensure_ascii=False)
@@ -71,16 +73,15 @@ def make(screen):
71
73
  query_url, headers=headers, data=query_payload.encode("utf-8"))
72
74
  response.raise_for_status()
73
75
  task_status = response.json()["data"]["task_status"]
74
- # print(f"任务状态: {task_status}")
75
76
 
76
77
  # 处理任务结果
77
78
  if task_status == "SUCCESS":
78
79
  picture = requests.get(response.json()[
79
- "data"]["sub_task_result_list"][0]["final_image_list"][0]["img_url"])
80
+ "data"]["sub_task_result_list"][0]["final_image_list"][0]["img_url"])
80
81
  image_data = BytesIO(picture.content)
81
82
  image = Image.open(image_data)
82
83
  image.save('image.gif')
83
- os.system("image.gif")
84
+ open_image("image.gif")
84
85
  else:
85
86
  print(f"任务失败,状态: {task_status}")
86
87
 
@@ -99,14 +100,31 @@ def get_file_content_as_base64(path, urlencoded=False):
99
100
  return content
100
101
 
101
102
 
103
+ def detect_scale():
104
+ """
105
+ 跨平台缩放比例检测
106
+ - Windows: 检测实际 DPI
107
+ - macOS/Linux: 默认返回 1.0
108
+ """
109
+ if platform.system() == "Windows":
110
+ try:
111
+ user32 = ctypes.windll.user32
112
+ user32.SetProcessDPIAware()
113
+ if hasattr(user32, 'GetDpiForSystem'):
114
+ dpi = user32.GetDpiForSystem()
115
+ return dpi / 96.0
116
+ screen_width = user32.GetSystemMetrics(0)
117
+ return screen_width / 1920.0
118
+ except Exception:
119
+ return 1.0
120
+ else:
121
+ return 1.0
122
+
123
+
102
124
  def save_pic(screen, output_file="pic.png"):
103
125
  """
104
126
  精准截取turtle绘图区域,不包含窗口边框和标题栏
105
- 专为Windows系统优化,支持高DPI缩放
106
-
107
- 参数:
108
- screen: turtle的Screen对象
109
- output_file: 输出文件名
127
+ 跨平台支持 (Windows/macOS/Linux)
110
128
  """
111
129
  canvas = screen.getcanvas()
112
130
  screen.update()
@@ -118,62 +136,48 @@ def save_pic(screen, output_file="pic.png"):
118
136
  width = canvas.winfo_width()
119
137
  height = canvas.winfo_height()
120
138
 
121
- # 检测Windows屏幕缩放比例
122
- scale_factor = detect_windows_scale()
123
- # print(f"检测到屏幕缩放比例: {scale_factor}x")
139
+ # 检测屏幕缩放比例
140
+ scale_factor = detect_scale()
124
141
 
125
- # 调整截图区域,排除窗口边框
126
- # 典型Windows窗口边框宽度约为8像素,标题栏约为30像素
127
- border_width = int(8 * scale_factor)
128
- title_height = int(30 * scale_factor)
142
+ # Windows 上要扣除边框和标题栏
143
+ border_width = int(
144
+ 8 * scale_factor) if platform.system() == "Windows" else 0
145
+ title_height = int(
146
+ 30 * scale_factor) if platform.system() == "Windows" else 0
129
147
 
130
148
  # 计算实际绘图区域
131
149
  img = ImageGrab.grab(
132
150
  bbox=(
133
- x + border_width, # 左边界,排除左侧边框
134
- y + title_height, # 上边界,排除标题栏和上边框
135
- x + width - border_width, # 右边界,排除右侧边框
136
- y + height - border_width # 下边界,排除底部边框
151
+ x + border_width,
152
+ y + title_height,
153
+ x + width - border_width,
154
+ y + height - border_width
137
155
  )
138
156
  )
139
157
 
140
- # 保存为PNG
141
158
  img.save(output_file)
142
- # print(f"已保存图形到 {output_file} (尺寸: {img.size})")
143
159
  except Exception as e:
144
160
  print(f"截图时出错: {e}")
145
- print("提示: 尝试使用save_turtle_canvas_fallback函数或手动截图")
161
+ print("提示: 可以尝试手动截图或使用其他方法")
146
162
 
147
163
 
148
- def detect_windows_scale():
164
+ def open_image(file_path):
149
165
  """
150
- 检测Windows系统的屏幕缩放比例
151
- 优先使用高精度方法,失败则降级使用兼容性方法
166
+ 跨平台打开图片
167
+ - Windows: os.startfile
168
+ - macOS: open
169
+ - Linux: xdg-open
152
170
  """
171
+ system = platform.system()
153
172
  try:
154
- # 高精度方法:获取系统DPI
155
- user32 = ctypes.windll.user32
156
- user32.SetProcessDPIAware()
157
-
158
- # 尝试获取系统DPI (Windows 8.1及以上)
159
- if hasattr(user32, 'GetDpiForSystem'):
160
- dpi = user32.GetDpiForSystem()
161
- return dpi / 96.0 # Windows标准DPI是96
162
-
163
- # 尝试获取显示器DPI (Windows 10及以上)
164
- if hasattr(user32, 'GetDpiForWindow'):
165
- root = tk.Tk()
166
- dpi = user32.GetDpiForWindow(root.winfo_id())
167
- root.destroy()
168
- return dpi / 96.0
169
-
170
- # 兼容方法:获取屏幕尺寸并与标准尺寸比较
171
- screen_width = user32.GetSystemMetrics(0)
172
- return screen_width / 1920.0 # 假设标准分辨率为1920x1080
173
+ if system == "Windows":
174
+ os.startfile(file_path)
175
+ elif system == "Darwin": # macOS
176
+ os.system(f"open {file_path}")
177
+ else: # Linux / 其他
178
+ os.system(f"xdg-open {file_path}")
173
179
  except Exception as e:
174
- print(f"检测缩放比例时出错: {e}")
175
- print("使用默认缩放比例1.0")
176
- return 1.0
180
+ print(f"打开图片失败: {e}")
177
181
 
178
182
 
179
183
  '''-----------体验课2-----------'''
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: XMWAI
3
- Version: 0.4.1
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
@@ -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
@@ -4,3 +4,4 @@ opencv-python>=3.4.18.65
4
4
  numpy>=1.26.0
5
5
  flask>=3.1.0
6
6
  pyecharts>=2.0.8
7
+ cvzone>=1.6.1
@@ -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.1", # 每次上传记得升级版本号
6
+ version="0.4.4", # 每次上传记得升级版本号
7
7
  author="pydevelopment", # 作者
8
8
  author_email="hekai@xiaoma.cn", # 邮箱
9
9
  description="Small code King AI related library", # 简短描述
@@ -22,6 +22,8 @@ setup(
22
22
  ],
23
23
  "XMWAI.gif": ["*.gif"], # gif 文件夹下的所有 GIF
24
24
  "XMWAI.file": ["*.json"], # file 文件夹下的 json
25
+ "XMWAI.assets": ["*.png"], # assets 文件夹下的 png
26
+ "XMWAI.assets": ["*.ttf"] # assets 文件夹下的 ttf
25
27
  },
26
28
  install_requires=[
27
29
  "requests>=2.32.3", # 依赖包
@@ -29,7 +31,8 @@ setup(
29
31
  "opencv-python>=3.4.18.65", # OpenCV 库
30
32
  "numpy>=1.26.0", # 数值计算库
31
33
  "flask>=3.1.0", # Web 框架
32
- "pyecharts>=2.0.8" # 图表绘制库
34
+ "pyecharts>=2.0.8", # 图表绘制库
35
+ "cvzone>=1.6.1" # 手势识别库
33
36
  ],
34
37
  classifiers=[
35
38
  "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