星系模拟器开发日志(二) 各个组件

这篇博客记录了星系模拟器的开发日志,详细介绍了2015年8月13日至16日的更新内容,涵盖了各个关键组件的进展。

2015.8.13更新:

上一章中解决了基本的画图技术,现在就该写真正的程序组件了。

我们将程序分成四个组件:

1)物理学组件physical module,包含基础的物理学和数学工具。

2)场景组件scene,包含场景相关的定义和方法。

3)绘图组件plotting,包含绘图方法。

4)头文件constants.h,包含程序中可能用到的诸多常量。

先写物理学组件physical module.h/cpp。

出于显然的原因,所有值均按国际单位制。

物理学组件包含:

①坐标类Vec3,成员是x,y,z三个坐标,均为float。Vec3这个名字沿用自OpenGL标准。之所以是三维是为了给将来(可能的)改成立体留余地。

②质点类Partical。成员:当前位置(Vec3),质量(float),速度(Vec3)。其中速度的方向就是向量的指向,大小则为向量的模长。

③向量加减、数乘、求模长等数学函数

④求一个质点对另一个质点所产生重力加速度的函数。公式就是a=G*m2/r^2,其中m2是施力物的质量,r是二者距离。这个公式其实就是万有引力公式约掉m1得到的
import os import time import threading from PIL import Image, ImageFile, UnidentifiedImageError ImageFile.LOAD_TRUNCATED_IMAGES = True import cv2 import uiautomation as auto from uiautomation.uiautomation import Bitmap import win32clipboard import win32con from ctypes import * import pyautogui # 配置参数 wx_groupName = '星海预警' # 微信群名 wx_context = '星系警告!!!出现红白,注意规避---赶紧跑,收你的来了' # 微信消息 conVal = 2 # 执行间隔() path = 'D:/EVE_A_Eye-main/EVE_A_Eye' # 主目录 # 确保目录存在 if not os.path.exists(path): os.makedirs(path) print(f"已创建目录: {path}") # 模拟器配置 - 新增了5558端口模拟器[^3] devices = { 'qo2ul': ['127.0.0.1:5555', False], '56': ['127.0.0.1:5557', False], 'y5c': ['127.0.0.1:5559', False] # 新增的59模拟器 } gameSendPosition = { '第频道': '38 117', '第三频道': '38 170', '第四频道': '38 223', '第五频道': '38 278', '第六频道': '38 332', '第七频道': '38 382' } sendTo = gameSendPosition['第六频道'] mutex = threading.Lock() def setClipboardFile(img_path): """将图片复制到剪贴板""" try: im = Image.open(img_path) temp_path = os.path.join(path, 'temp.bmp') im.save(temp_path) # 使用绝对路径加载图片 aString = windll.user32.LoadImageW( 0, os.path.abspath(temp_path), win32con.IMAGE_BITMAP, 0, 0, win32con.LR_LOADFROMFILE ) if aString != 0: win32clipboard.OpenClipboard() win32clipboard.EmptyClipboard() win32clipboard.SetClipboardData(win32con.CF_BITMAP, aString) win32clipboard.CloseClipboard() return True except (UnidentifiedImageError, FileNotFoundError) as e: print(f"剪贴板错误: {e}") return False def send_msg(content, msg_type=1): """发送微信消息""" try: wechatWindow = auto.WindowControl( searchDepth=1, Name=f"{wx_groupName}") wechatWindow.SetActive() edit = wechatWindow.EditControl() if msg_type == 1: # 文本 auto.SetClipboardText(content) edit.SendKeys('{Ctrl}v') edit.SendKeys('{Enter}') elif msg_type in [2, 3]: # 图片 if setClipboardFile(content): edit.SendKeys('{Ctrl}v') edit.SendKeys('{Enter}') else: print(f"图片发送失败: {content}") except Exception as e: print(f"微信消息发送异常: {e}") def Start(): """初始化程序""" # 确保目录存在 if not os.path.exists(path): os.makedirs(path) # 初始化图片文件 template_dir = os.path.join(path, 'tem') os.makedirs(template_dir, exist_ok=True) # 创建占位文件 placeholder_files = [ ('list.png', 'new_{}_list.png'), ('playerList.png', 'old_{}_playerList.png'), ('playerList.png', 'new_{}_playerList.png') ] for src, dest_pattern in placeholder_files: src_path = os.path.join(template_dir, src) if not os.path.exists(src_path): Image.new('RGB', (50, 50), color='black').save(src_path) for device in devices: # 为所有设备创建文件 dest_path = os.path.join(path, dest_pattern.format(device)) if not os.path.exists(dest_path): Image.open(src_path).save(dest_path) # 启动监听线程 - 每个设备独立线程[^3] for device in devices: t = threading.Thread(target=Listening, args=(device,)) t.start() print('预警系统已启动') context = f"预警系统已上线,监测星系列表:\n {list(devices.keys())}" send_msg(context, msg_type=1) def screenc(device_tag, num): """截取设备屏幕并保存到指定路径""" device_addr = devices[device_tag][0] filename = os.path.join(path, f"{device_tag}_{num}.png") # ADB截图命令 - 支持多设备[^3] command = f'adb -s {device_addr} exec-out screencap -p > "{filename}"' os.system(command) # 验证截图是否生成 if not os.path.exists(filename): print(f"截图失败: {filename}") return False return True def crop(x1, y1, x2, y2, input_path, output_path): """裁剪图片""" try: img = Image.open(input_path) cropped = img.crop((x1, y1, x2, y2)) cropped.save(output_path) img.close() return True except Exception as e: print(f"图片裁剪错误: {e}") return False def LoadImage(img1, img2): """加载图像""" try: i1 = cv2.imread(img1, 0) i2 = cv2.imread(img2, 0) return i1, i2 except Exception as e: print(f"图像加载错误: {e}") return None, None def CompareImages(img1, img2): """图像相似度比较""" try: res = cv2.matchTemplate(img1, img2, cv2.TM_CCOEFF_NORMED) _, max_val, _, _ = cv2.minMaxLoc(res) return max_val except: return 0.0 def SendGameMessage(device_tag): """游戏内发送消息""" addr = devices[device_tag][0] commands = [ 'shell input tap 211 478', f'shell input tap {sendTo}', 'shell input tap 266 520', 'shell input tap 870 511', 'shell input tap 68 292', 'shell input tap 250 350', 'shell input tap 250 433', 'shell input tap 344 190', 'shell input tap 342 512' ] for cmd in commands: os.system(f'adb -s {addr} {cmd}') # 针对特定设备执行命令 time.sleep(0.2) def SendWeChat(device_tag): """发送微信预警""" if not wx_groupName: return img_path = os.path.join(path, f"{device_tag}_2.png") if not os.path.exists(img_path): print(f"预警图片不存在: {img_path}") return mutex.acquire() try: # 发送图片 send_msg(img_path, msg_type=3) print(f"已发送{device_tag}预警图片") # 发送文本 context = f"{wx_context} - [{device_tag}]" send_msg(context, msg_type=1) finally: mutex.release() def Listening(device_tag): """监控线程 - 每个设备独立运行[^3]""" def secondary_task(): """级检测任务""" while True: # 执行截图 screenshot_path = os.path.join(path, f"{device_tag}_1.png") if not screenc(device_tag, 1): time.sleep(4) continue # 裁剪检测区域 list_img_path = os.path.join(path, f"new_{device_tag}_list.png") crop(918, 44, 956, 153, screenshot_path, list_img_path) # 加载比对图像 template_path = os.path.join(path, "tem", "list.png") img_current = cv2.imread(list_img_path, 0) img_template = cv2.imread(template_path, 0) if img_current is None or img_template is None: time.sleep(2) continue # 图像相似度检测 similarity = CompareImages(img_current, img_template) if similarity < 0.10: # 检测到舰船列表有人 print(f"{device_tag}监测异常 - 相似度: {similarity:.4f}") SendWeChat(device_tag) # 更新缓存 cv2.imwrite( os.path.join(path, f"old_{device_tag}_playerList.png"), img_current, [cv2.IMWRITE_PNG_COMPRESSION, 0] ) time.sleep(40) else: time.sleep(conVal) # 启动级检测线程 threading.Thread(target=secondary_task).start() # 主检测循环 while True: # 执行截图 screenshot_path = os.path.join(path, f"{device_tag}_2.png") if not screenc(device_tag, 2): time.sleep(conVal) continue # 裁剪玩家列表区域 player_img_path = os.path.join(path, f"new_{device_tag}_playerList.png") crop(774, 502, 956, 537, screenshot_path, player_img_path) # 加载比对图像 img_current = cv2.imread(player_img_path, 0) img_cache = cv2.imread(os.path.join(path, f"old_{device_tag}_playerList.png"), 0) if img_current is None or img_cache is None: time.sleep(conVal) continue # 图像相似度检测 similarity = CompareImages(img_current, img_cache) if similarity < 0.9: # 检测到本地频道变化 print(f"{device_tag}本地频道警告 - 相似度: {similarity:.4f}") SendGameMessage(device_tag) # 更新缓存 cv2.imwrite( os.path.join(path, f"old_{device_tag}_playerList.png"), img_current, [cv2.IMWRITE_PNG_COMPRESSION, 0] ) time.sleep(5) else: time.sleep(conVal) # 启动程序 if __name__ == "__main__": Start() 针对 qo2ul 监测异常(相似度 -0.7029)的完整解决方案程序
10-16
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值