#### 一、游戏自动化脚本基础原理
在开发复古传奇自动化脚本之前,我们需要了解一些基础原理。游戏自动化脚本主要通过以下几种方式实现:
1. **键鼠模拟**:通过程序控制鼠标移动和点击,以及键盘按键
2. **图像识别**:识别游戏画面中的元素,如怪物、血条、物品等
3. **内存操作**:直接读取或修改游戏内存数据(此方法容易被检测)
4. **网络拦截**:拦截和分析游戏网络数据包(需要更高级的技术)
对于大多数玩家而言,基于键鼠模拟和图像识别的脚本是最安全和可行的选择。这种脚本通过分析游戏画面来做出决策,并通过模拟人类操作来执行这些决策。
#### 二、开发环境搭建
首先,我们需要搭建开发环境并安装必要的库:
```bash
# 安装Python 3.9或更高版本
# 安装必要的库
pip install pyautogui opencv-python numpy pillow pywin32
```
我们将使用以下库:
- **PyAutoGUI**:用于控制鼠标和键盘
- **OpenCV**:用于图像识别和处理
- **NumPy**:用于数值计算
- **Pillow**:用于图像处理
- **pywin32**:用于Windows窗口管理
#### 三、核心功能实现
下面是一个完整的复古传奇自动化脚本实现,包含了自动打怪、拾取物品、喝药和回城等核心功能:
```python
import pyautogui
import cv2
import numpy as np
import time
import win32gui
import win32con
import random
import logging
from enum import Enum
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# 游戏状态枚举
class GameState(Enum):
IDLE = 1 # 空闲状态
FIGHTING = 2 # 战斗状态
PICKING = 3 # 拾取状态
RETURNING = 4 # 回城状态
REPAIRING = 5 # 修理状态
BUYING = 6 # 购买状态
class LegendBot:
def __init__(self):
# 游戏窗口信息
self.game_title = "复古传奇"
self.game_hwnd = None
self.game_rect = None
# 游戏状态
self.current_state = GameState.IDLE
self.hp_percentage = 100
self.mp_percentage = 100
self.inventory_full = False
# 配置参数
self.config = {
"hp_threshold": 30, # 血量低于此值时喝药
"mp_threshold": 20, # 魔法值低于此值时喝蓝
"inventory_threshold": 80, # 背包满的阈值(百分比)
"fight_interval": (1.0, 2.0), # 攻击间隔(秒)
"pick_interval": 3.0, # 拾取间隔(秒)
"return_delay": 10.0, # 回城延迟(秒)
"templates_path": "templates/", # 模板图片路径
}
# 模板图片
self.templates = {
"monster": None,
"item": None,
"hp_bar": None,
"mp_bar": None,
"inventory": None,
"town_npc": None,
"repair_button": None,
"buy_button": None,
}
# 加载模板图片
self._load_templates()
def _load_templates(self):
"""加载所有模板图片"""
try:
for key in self.templates:
template_path = f"{self.config['templates_path']}{key}.png"
self.templates[key] = cv2.imread(template_path, 0)
if self.templates[key] is not None:
logger.info(f"成功加载模板: {key}")
else:
logger.warning(f"无法加载模板: {key}")
except Exception as e:
logger.error(f"加载模板时出错: {str(e)}")
def find_game_window(self):
"""查找并激活游戏窗口"""
self.game_hwnd = win32gui.FindWindow(None, self.game_title)
if not self.game_hwnd:
logger.error(f"未找到游戏窗口: {self.game_title}")
return False
# 获取窗口位置和大小
rect = win32gui.GetWindowRect(self.game_hwnd)
self.game_rect = (rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1])
logger.info(f"找到游戏窗口: 位置{self.game_rect}")
# 激活窗口
win32gui.SetForegroundWindow(self.game_hwnd)
time.sleep(0.5) # 等待窗口激活
return True
def capture_screen(self):
"""截取游戏窗口画面"""
if not self.game_rect:
return None
left, top, width, height = self.game_rect
screenshot = pyautogui.screenshot(region=(left, top, width, height))
return cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
def find_template(self, template, threshold=0.7):
"""在屏幕上查找模板"""
screen = self.capture_screen()
if screen is None:
return None
screen_gray = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
result = cv2.matchTemplate(screen_gray, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val >= threshold:
h, w = template.shape
center_x = max_loc[0] + w // 2
center_y = max_loc[1] + h // 2
return (center_x, center_y, max_val)
return None
def recognize_status(self):
"""识别游戏状态(血量、魔法值、背包等)"""
self._recognize_hp()
self._recognize_mp()
self._recognize_inventory()
def _recognize_hp(self):
"""识别当前血量"""
result = self.find_template(self.templates["hp_bar"], threshold=0.8)
if result:
x, y, confidence = result
# 这里需要根据实际游戏的血条位置和颜色进行分析
# 简化实现,实际应用中可能需要更复杂的处理
screen = self.capture_screen()
hp_region = screen[y-5:y+5, x-50:x+50]
hsv = cv2.cvtColor(hp_region, cv2.COLOR_BGR2HSV)
# 定义红色范围(血条通常是红色)
lower_red = np.array([0, 100, 100])
upper_red = np.array([10, 255, 255])
mask1 = cv2.inRange(hsv, lower_red, upper_red)
lower_red = np.array([160, 100, 100])
upper_red = np.array([180, 255, 255])
mask2 = cv2.inRange(hsv, lower_red, upper_red)
mask = mask1 + mask2
hp_percentage = (np.count_nonzero(mask) / mask.size) * 100
self.hp_percentage = hp_percentage
logger.debug(f"当前血量: {hp_percentage:.1f}%")
else:
logger.warning("无法识别血量")
def _recognize_mp(self):
"""识别当前魔法值"""
# 实现类似_recognize_hp,但针对魔法条
# 简化实现
self.mp_percentage = random.randint(1, 100)
logger.debug(f"当前魔法值: {self.mp_percentage:.1f}%")
def _recognize_inventory(self):
"""识别背包状态"""
# 实现背包状态识别
# 简化实现
self.inventory_full = random.random() > 0.7
logger.debug(f"背包状态: {'满' if self.inventory_full else '未满'}")
def click_position(self, x, y, button='left', delay=0.3):
"""点击指定位置"""
if not self.game_rect:
return
# 转换为屏幕坐标
screen_x = self.game_rect[0] + x
screen_y = self.game_rect[1] + y
# 添加随机延迟,模拟人类操作
time.sleep(random.uniform(0.1, delay))
# 移动鼠标并点击
pyautogui.moveTo(screen_x, screen_y, duration=0.2 + random.random() * 0.3)
pyautogui.click(button=button)
def attack_monster(self):
"""寻找并攻击怪物"""
result = self.find_template(self.templates["monster"])
if result:
x, y, confidence = result
logger.info(f"找到怪物,位置: ({x}, {y}), 匹配度: {confidence:.2f}")
self.click_position(x, y)
self.current_state = GameState.FIGHTING
return True
logger.info("未找到怪物")
self.current_state = GameState.IDLE
return False
def pick_items(self):
"""寻找并拾取物品"""
result = self.find_template(self.templates["item"])
if result:
x, y, confidence = result
logger.info(f"找到物品,位置: ({x}, {y}), 匹配度: {confidence:.2f}")
self.click_position(x, y)
self.current_state = GameState.PICKING
time.sleep(1.0) # 等待拾取动画
return True
logger.info("未找到物品")
return False
def use_hp_potion(self):
"""使用血药"""
logger.info("血量过低,使用血药")
pyautogui.press('f4') # 假设F4是血药快捷键
time.sleep(0.5) # 等待喝药动画
def use_mp_potion(self):
"""使用蓝药"""
logger.info("魔法值过低,使用蓝药")
pyautogui.press('f5') # 假设F5是蓝药快捷键
time.sleep(0.5) # 等待喝药动画
def return_to_town(self):
"""返回城镇"""
logger.info("准备回城")
pyautogui.press('f2') # 假设F2是回城快捷键
self.current_state = GameState.RETURNING
time.sleep(self.config["return_delay"]) # 等待回城动画
def repair_equipment(self):
"""修理装备"""
logger.info("准备修理装备")
# 寻找NPC
result = self.find_template(self.templates["town_npc"])
if result:
x, y, confidence = result
logger.info(f"找到NPC,位置: ({x}, {y}), 匹配度: {confidence:.2f}")
self.click_position(x, y)
time.sleep(1.0) # 等待对话打开
# 点击修理按钮
repair_result = self.find_template(self.templates["repair_button"])
if repair_result:
rx, ry, rconfidence = repair_result
logger.info(f"找到修理按钮,位置: ({rx}, {ry}), 匹配度: {rconfidence:.2f}")
self.click_position(rx, ry)
time.sleep(1.0) # 等待修理完成
return True
logger.warning("无法完成修理")
return False
def buy_supplies(self):
"""购买补给品"""
logger.info("准备购买补给品")
# 寻找NPC
result = self.find_template(self.templates["town_npc"])
if result:
x, y, confidence = result
logger.info(f"找到NPC,位置: ({x}, {y}), 匹配度: {confidence:.2f}")
self.click_position(x, y)
time.sleep(1.0) # 等待对话打开
# 点击购买按钮
buy_result = self.find_template(self.templates["buy_button"])
if buy_result:
bx, by, bconfidence = buy_result
logger.info(f"找到购买按钮,位置: ({bx}, {by}), 匹配度: {bconfidence:.2f}")
self.click_position(bx, by)
time.sleep(1.0) # 等待商店打开
# 购买操作...
# 这里需要根据实际游戏商店界面实现
return True
logger.warning("无法完成购买")
return False
def run_bot(self):
"""运行脚本主循环"""
if not self.find_game_window():
return
logger.info("脚本开始运行,按Ctrl+C终止")
try:
while True:
# 识别当前状态
self.recognize_status()
# 根据状态决定行动
if self.hp_percentage < self.config["hp_threshold"]:
self.use_hp_potion()
elif self.mp_percentage < self.config["mp_threshold"]:
self.use_mp_potion()
elif self.inventory_full:
self.return_to_town()
self.repair_equipment()
self.buy_supplies()
# 离开城镇返回战斗区域
# 这里需要根据实际游戏实现
time.sleep(5.0)
else:
# 正常战斗状态
if not self.attack_monster():
# 没找到怪物,尝试拾取物品
self.pick_items()
# 添加随机延迟,避免操作过于规律
delay = random.uniform(0.5, 1.5)
time.sleep(delay)
except KeyboardInterrupt:
logger.info("用户中断,脚本停止运行")
# 运行脚本
if __name__ == "__main__":
bot = LegendBot()
bot.run_bot()
```
#### 四、图像识别优化技术
为了提高脚本的稳定性和可靠性,我们可以采用以下图像识别优化技术:
1. **多尺度模板匹配**:
```python
def find_template_multi_scale(self, template, threshold=0.7, scales=[1.0, 0.9, 1.1]):
"""多尺度模板匹配"""
screen = self.capture_screen()
if screen is None:
return None
screen_gray = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
best_match = None
for scale in scales:
# 调整模板大小
resized_template = cv2.resize(template, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
if resized_template.shape[0] > screen_gray.shape[0] or resized_template.shape[1] > screen_gray.shape[1]:
continue
result = cv2.matchTemplate(screen_gray, resized_template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if max_val > threshold and (best_match is None or max_val > best_match[2]):
h, w = resized_template.shape
center_x = max_loc[0] + w // 2
center_y = max_loc[1] + h // 2
best_match = (center_x, center_y, max_val)
return best_match
```
2. **特征点匹配**:
```python
def find_template_keypoints(self, template, threshold=10):
"""使用特征点匹配"""
screen = self.capture_screen()
if screen is None:
return None
screen_gray = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
# 初始化ORB检测器
orb = cv2.ORB_create()
# 找到关键点和描述符
kp1, des1 = orb.detectAndCompute(template, None)
kp2, des2 = orb.detectAndCompute(screen_gray, None)
# 创建BFMatcher对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 匹配描述符
matches = bf.match(des1, des2)
# 按距离排序
matches = sorted(matches, key=lambda x: x.distance)
# 如果有足够的匹配点,计算中心点
if len(matches) > threshold:
points = [kp2[m.trainIdx].pt for m in matches[:threshold]]
center_x = int(sum([p[0] for p in points]) / len(points))
center_y = int(sum([p[1] for p in points]) / len(points))
return (center_x, center_y, len(matches))
return None
```
3. **图像预处理**:
```python
def preprocess_image(self, image):
"""图像预处理"""
# 高斯模糊
blurred = cv2.GaussianBlur(image, (5, 5), 0)
# 灰度转换
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
# 直方图均衡化
equalized = cv2.equalizeHist(gray)
# 边缘检测
edges = cv2.Canny(equalized, 50, 150)
return edges
```
#### 五、反检测技术
为了降低被游戏检测到的风险,我们可以采用以下反检测技术:
1. **操作随机化**:
```python
def randomized_click(self, x, y, button='left'):
"""带随机化的点击操作"""
# 随机偏移
offset_x = random.randint(-5, 5)
offset_y = random.randint(-5, 5)
# 随机移动速度
duration = random.uniform(0.2, 0.5)
# 转换为屏幕坐标
screen_x = self.game_rect[0] + x + offset_x
screen_y = self.game_rect[1] + y + offset_y
# 移动鼠标并点击
pyautogui.moveTo(screen_x, screen_y, duration=duration)
pyautogui.click(button=button)
# 随机延迟
time.sleep(random.uniform(0.3, 0.8))
```
2. **行为多样化**:
```python
def random_idle_action(self):
"""随机执行一些空闲动作,模拟人类玩家"""
if random.random() < 0.1: # 10%的概率执行空闲动作
actions = ["look_around", "check_inventory", "adjust_equipment"]
action = random.choice(actions)
if action == "look_around":
logger.info("随机环顾四周")
# 模拟鼠标移动,环顾四周
pyautogui.moveRel(random.randint(-100, 100), random.randint(-100, 100), duration=0.5)
time.sleep(random.uniform(1.0, 2.0))
elif action == "check_inventory":
logger.info("检查背包")
pyautogui.press('i') # 假设I键是背包快捷键
time.sleep(random.uniform(1.0, 2.0))
pyautogui.press('i')
elif action == "adjust_equipment":
logger.info("调整装备")
pyautogui.press('e') # 假设E键是装备快捷键
time.sleep(random.uniform(1.0, 2.0))
pyautogui.press('e')
```
3. **异常处理**:
```python
def handle_exception(self, e):
"""异常处理,模拟人类反应"""
logger.error(f"发生异常: {str(e)}")
# 模拟人类反应
pyautogui.moveRel(random.randint(-50, 50), random.randint(-50, 50), duration=0.3)
time.sleep(random.uniform(1.0, 3.0))
# 重试机制
retry_count = 0
while retry_count < 3:
try:
# 尝试恢复操作
self.find_game_window()
time.sleep(2.0)
return True
except Exception as retry_e:
logger.error(f"重试失败: {str(retry_e)}")
retry_count += 1
time.sleep(2.0)
return False
```
#### 六、脚本使用与配置指南
1. **模板图片准备**:
- 在项目目录下创建`templates`文件夹
- 截取游戏中的各种元素作为模板,包括怪物、物品、血条、NPC等
- 保存为PNG格式,确保图片清晰且背景简单
2. **配置参数调整**:
- 根据自己的游戏设置调整快捷键
- 根据角色属性调整血量、魔法值阈值
- 根据背包大小调整背包满的阈值
3. **脚本运行**:
- 确保游戏已启动并可见
- 运行脚本,它会自动找到游戏窗口
- 脚本将根据游戏状态自动执行相应操作
4. **调试与优化**:
- 使用日志信息了解脚本运行状态
- 如果识别不准确,调整模板图片或匹配阈值
- 如果操作无响应,检查游戏窗口是否被遮挡
通过以上技术和方法,你可以开发出一个功能完整、安全可靠的复古传奇自动化脚本。记住,使用脚本应遵守游戏规则,避免过度依赖,保持游戏的乐趣。
复古传奇脚本开发全解析:打造智能挂机助手
来源:
作者:
点击:

