mimi_rice 发表于 2015-4-2 13:12:22

【院刊】-【201504期】按键有屎以来最智能寻路系列

本帖最后由 mimi_rice 于 2015-4-2 13:14 编辑

按键有屎以来最智能寻路系列直接输入坐标即时寻路
本文由按键学院提供技术支持




{:3_59:}众所周知,自动寻路是脚本编写中非常重要的一环,如何高效并稳定的实现让脚本模拟人工操作进行智能自动寻路成为脚本编写的必修课之一,然而是通过什么让游戏角色可以自动寻路呢?小编认为百分之九十九的游戏自动寻路方式都依赖于本身的游戏地图,擅用游戏地图对我们写脚本往往有事半功倍的效果,所以本期小编打算从易到难出一个关于自动寻路系列的院刊,希望大家多多支持哈~






地图寻路方式


关于游戏的地图寻路方式,小编认为可以大致分为这几类:

1、在地图上某个位置输入坐标后点寻路,比如烈焰、赤月传说等页游
2、根据地图配合键盘移动来达到寻路方式,比如XNF、疾风之刃
3、根据地图上找Npc名称或标志物进行寻路,但是无法精确到达指定点,比如太极
4、地图上的坐标点有误差,需要换算坐标,比如神途
5、根据地图上的路径点进行寻路,比如lol
5、待定···

:P以上纯属个人看法,个人玩过的游戏及思维能力有限,有补充和其他想法的童鞋欢迎回帖说明,小编会不定时查看的,小编今天就以烈焰这款网页游戏为例,跟大家分享下第1种最简单的—直接输入坐标寻路方法
游戏地图





从图上我们就能比较直观的看出这款游戏一个大概的寻路流程
思路流程





技术难点:
1.X、Y字符不是纯色的,并且X、Y字符偏色程度也是不一样的
2.游戏输入坐标处默认会保存一个0,并且每次打开地图不会自动清空上一次输入的坐标,如何才能正确的输入寻路坐标
3.移动过程中,如何判断人物是否已经移动到了指定坐标点,开始下一步动作



绑定窗口


{:5_138:}今天我们写的脚本有用到大漠插件,并且是后台的
因为是单开脚本,并且客户区句柄隐藏的也比较深,所以用的是FindWindowSuper命令,该命令内容较多,具体说明请查看大漠接口说明

后台绑定模式:
      图色模式:dx2
      鼠标模式:windows
      键盘模式:windows

关于大漠绑定模式如何获知
请参阅相关院刊:
【院刊】-【201501期】沙盘后台绑定游戏




打开地图


为了避免地图已经打开的情况
我们要先判断地图有没有打开,没有打开的话才去按M键打开地图
因为后面我们找字的时候就是要在地图上找字,所以我们先进行找字
没找到字的情况下说明地图没打开,再按m键打开地图



大漠找字


因为要分别找X、Y、前往字符,为了降低代码重复度,
所以我们应该想到把找字做成一个带参数的函数,
参数为要找的字符、偏色、相似度,
找到X、Y字符的时候我们要进行计算,
找到后进行相应的坐标偏移才能准确点到坐标输入框,
然而找字符"前往"的话坐标不需要偏移。
所以我们在代码里要加入判断当前查找的字符是不是"前往",
如果是的话执行不一样的移动操作

相关代码Function 找字(string, color_format, sim)
    dm_ret = dm.SetExactOcr(1)//设置找字方式为精确查找,避免类似字符的干扰
    Do
      dm_ret=dm.FindStrFast(0,0,w,h,string,color_format,sim,intX,intY)
      If intX > 0 and string<>"前往"Then //找到X、Y字符的操作
            TracePrint "找到了"
Delay 100
            dm.MoveTo intX + 66, intY + 8//鼠标漂移相应坐标后点击输入框
            Delay 100
            dm.LeftClick
            Delay 100
            Call 清除坐标
            Exit Do
      Elseif intX > 0 and string="前往" Then //找到前往字符的操作
            dm.MoveTo intX , intY
            Delay 100
            dm.LeftClick
            Exit Do
      Else
            TracePrint "地图没打开,所以找不到"
            dm.KeyPress 77//按M键打开地图
      End If
      Delay 100
    Loop
End Function{:4_92:}输入坐标后点击前往后,人物就开始移动了
那怎么才能知道人物已经移动到指定点了呢?
小编认为最简便的方法就是莫过于用大漠的IsDisplayDead函数来判断了,
关于这个函数的说明与使用方法已经在之前的院刊已经重点的介绍过了,
有不懂的童鞋可以查看:【院刊】-【201503期】寻路中判断人物是否停止行走
那除了使用这个函数的方法外或者我们本身不知道有这个函数的话,是否还有其他方法呢?
答案显示是有的,小编今天就再给大家重点介绍一个识别数字后分割坐标的方法



坐标识别法





如图所示,很多游戏小地图上通常都是类似这样显示当前坐标的,而且坐标的颜色通常都是固定的,所以我们不妨分别提取出0-9的数字,以及逗号做成一个独立字库,不会使用大漠做字库的童鞋可以参考:如何利用大漠综合工具自作字库
字库做完后,我们就可以通过这个字库使用大漠插件的Ocr函数来识别这个范围的坐标值了,因为里面刚好有个逗号,我们就可以用逗号来分割出X坐标和Y坐标,通过循环一直获取坐标与我们要寻路到达的坐标作比较,由于这个游戏寻路到达坐标的时候坐标都会少1,所以我们用绝对值来对比距离差,允许些许容差

命令名称Ocr
命令功能识别屏幕范围(x1,y1,x2,y2)内符合color_format的字符串,并且相似度为sim,sim取值范围(0.1-1.0)

命令参数x1 整形数:区域的左上X坐标
y1 整形数:区域的左上Y坐标
x2 整形数:区域的右下X坐标
y2 整形数:区域的右下Y坐标
color_format 字符串:颜色格式串. RGB和HSV颜色格式都支持.
sim 双精度浮点数:相似度,取值范围0.1-1.0
返 回 值字符串:
返回识别到的字符串


相关代码 Do
      s = dm.Ocr(500, 30, w, h, "ff9912-000000", 0.9)
      If len(s) > 0 Then
            TracePrint "找到了"
            坐标 = split(s, ",")
            TracePrint cint(坐标(0))//即当前位置X坐标
            TracePrint cint(坐标(1))//即当前位置Y坐标
            If (abs(x坐标 -cint(坐标(0)))<3) and (abs(y坐标 - cint(坐标(1)))<3) Then //当前位置坐标与指定坐标的距离差的绝对值小于3则判断到达指定坐标
                Call Plugin.Msg.Tips("到达指定坐标,寻路结束")//托盘信息提示到达指定坐标
                Exit Do
                ElseCall Plugin.Msg.Tips("寻路中!!!") //托盘信息提示还未到达指定坐标
            End If
      End If
      Delay 500//每隔500毫秒检测一次,可自定义
    Loop小拓展:小编这里只是用坐标做是否寻路到达的判断,
其实通过识别游戏的当前坐标我们可以做很多其他判断和操作的,
当然这是个仁者见仁、智者见智的问题了,小编在此就不讨论了


整体代码


    Call 找字("X", "A6AB56-0C0E35", 0.9)//找地图上的X字
    dm.SendString hwnd,cstr(x坐标)//向后台窗口输入X坐标(这里要注意类型需要转换下)
    Delay 500
    Call 找字("Y", "A8AE42-0C1343", 0.9)//找地图上的Y字
    dm.SendString hwnd, cstr(y坐标)//向后台窗口输入Y坐标(这里要注意类型需要转换下)
    Delay 500
    Call 找字("前往", "f2e627-000000", 0.9)//找小地图上的前往字符
    //以下代码是每隔500毫秒,识别一下当前位置坐标与指定坐标的距离差,循环判断是否到达指定坐标
    Do
      s = dm.Ocr(500, 30, w, h, "ff9912-000000", 0.9)
      If len(s) > 0 Then
            坐标 = split(s, ",")
            TracePrint "当前角色所在x坐标为"&s
            //            TracePrint cint(坐标(0))
            //            TracePrint cint(坐标(1))
            If (abs(x坐标 - cint(坐标(0))) < 3) and (abs(y坐标 - cint(坐标(1))) < 3) Then //当前位置坐标与指定坐标的距离差的绝对值小于3则判断到达指定坐标
                dm.keypress 77//关闭地图
                Call Plugin.Msg.Tips("到达指定坐标,寻路结束并关闭地图")//托盘信息提示到达指定坐标
                Exit Do
                ElseCall Plugin.Msg.Tips("寻路中!!!") //托盘信息提示还未到达指定坐标
            End If
      End If
      Delay 500
    Loop
End Function
Function 找字(string, color_format, sim)
    dm_ret = dm.SetExactOcr(1)//设置找字方式为精确查找,避免类似字符的干扰
    Do
      dm_ret=dm.FindStrFast(0,0,w,h,string,color_format,sim,intX,intY)
      If intX > 0 and string<>"前往"Then //找到X、Y字符的操作
            TracePrint "找到地图了"
            TracePrint "x字符坐标为"&intx
            TracePrint "y字符坐标为" & inty
            Delay 100
            dm.MoveTo intX + 66, intY + 8//鼠标漂移相应坐标后点击输入框
            Delay 100
            dm.LeftClick
            Delay 100
            Call 清除坐标
            Exit Do
      Elseif intX > 0 and string="前往" Then //找到前往字符的操作
            dm.MoveTo intX , intY
            Delay 100
            dm.LeftClick
            TracePrint"点击前往按钮"
            Exit Do
      Else
            TracePrint "未找到地图,按m键打开地图"
            Delay 100
            dm.KeyPress 77//按M键打开小地图
      End If
      Delay 100
    Loop
End Function
Function 清除坐标
    For 10   //打开小地图后按10次backspace键先对原先的坐标进行清除
      dm.keypress 8
      Delay 100
    Next
    TracePrint "清空地图初始坐标"
    dm.keypress 39//按右方向键一次保证坐标不会被0影响
End Function
Function 找句柄
    For i = 0 To 20
      hwnd = dm.FindWindowSuper("MacromediaFlashPlayerActiveX",2,1,"Internet Explorer_Server",6,0) //根据俩组设置条件,获得烈焰窗口句柄
      Delay 2000
      If hwnd > 0 Then
            TracePrint hwnd
            dm_ret = dm.GetClientSize(hwnd,w,h) //获取窗口客户区大小
            TracePrint "游戏客户区宽度:" & w & ",高度:" & h
            dm_ret = dm.SetWindowState(hwnd, 1)
            Exit For
            Elseifi >= 20 ThenMsgBox"未检测到游戏窗口,请确认游戏窗口已经打开"
      End If
    Next
End Function
Function 注册大漠()
    Dim i
    //释放附件内容
    PutAttachment "D:\test", "*.*"
    Set ws = createobject("Wscript.Shell")
    For i = 0 To 20
      //注册atl跟dm插件
      ws.run("regsvr32 atl.dll -s")
      ws.run ("regsvr32 D:\test\dm.dll -s")
      Delay 200
      Set ws = nothing
      Set dm = createobject("dm.dmsoft")
      ver = dm.ver()
      //输出版本号
      If ver <> "" Then
            Exit For
      End If
    Next
    If i >= 20 Then
      TracePrint "大漠插件注册失败!"
      EndScript
    End If
    Set dm = nothing
    Delay 10
End Function
Function 大漠绑定
    For i = 0 To 20
      dm_ret = dm.BindWindowEx(hwnd, "dx2", "windows", "windows", "", 0)'绑定窗口
      Delay 500
      If dm_ret = 1 Then
            TracePrint "绑定窗口成功"
            Exit For
            Elseif i>=20 Then TracePrint "绑定失败"
      End If
    Next
End Function
Sub OnScriptExit()//解绑大漠
    dm_ret = dm.UnBindWindow()
End Sub


后记


关于初级寻路今天就介绍到这里了,欲知其他寻路方式的解决办法,请听下回分解!


谢谢大家阅读,记得给小编送支花花 !顺手点个赞

按键精灵安卓班(第一期)大肆招生啦~回实战班:回合制通用教学火热报名
招生对象:零基础用户,快速学会按键精灵安卓版
招生人数:70人
【报名时间】:3/18——4/6
【学费】:128RMB
【学习日期】:1个月(2015.4.6-2015.4.27)
【上课时间】:周1、周3、周519:30--21:30
【上课导师】:梦幻小飞侠
【实战游戏】:[天天富翁][三国之刃][梦幻西游]
本期重点:回合制游戏--神武
学习时效:终生有效
上课时间:周2、周4、周6的   20:00--22:00
导师:工程师07
技术支持:果儿(院刊编辑)
点我进入按键学院报名啦   招生细节进群咨询招生办主任:2群-372671254(优先加入)    1群-376122403


fengjikou 发表于 2015-4-2 17:04:25

强烈支持楼主ing……

yuzhibo 发表于 2015-5-3 19:58:08

就喜欢楼主这样的哈哈哈

zhangyang 发表于 2015-9-28 04:20:35

楼主很给力哈,在此代表需要的人对楼主表示无尽的感激之情
页: [1]
查看完整版本: 【院刊】-【201504期】按键有屎以来最智能寻路系列