mimi_rice 发表于 2015-4-9 15:39:19

按键有屎以来最智能寻路系列之二


按键有屎以来最智能寻路系列之二换算地图坐标寻路法
本文由按键学院提供技术支持



{:4_111:}上周跟大家介绍了关于游戏地图的寻路方式,也以烈焰游戏无题材向大家分享了下最简单的寻路方法—直接输入坐标寻路法(没看过的童鞋可以参考:按键有屎以来最智能寻路系列),看过之后,想必大家对游戏的寻路方式有了一定的认知,小编今天再跟大家分享下进阶版的寻路方法,即换算地图坐标寻路法




换算地图坐标寻路法



{:4_92:}神马叫换算游戏坐标寻路法呢?顾名思义就是游戏地图上显示的坐标跟我们屏幕实际坐标不一致,需要通过相应关系的换算才能算出地图坐标相对于屏幕实际坐标的偏移量,然后鼠标相对偏移量点击地图某位置后即可自动进行寻路,听到这里估计大家还是不大懂,没关系,下面小编就以神途游戏为例子,跟大家深度解析下
                                                                                                             游戏地图






图上左上角红色的点0,0为游戏地图的起始坐标,右下角红色的点为游戏地图的终点坐标830,690,但是实际上我们用qq截图功能对地图区域进行截图会发现该地图图片的实际大小大概只有660*415像素,除了游戏初始(0,0)坐标跟实际鼠标偏移坐标一致外,其他游戏地图坐标跟实际鼠标偏移坐标都是不一致的再进一步来讲就是相对于游戏地图初始点坐标(0,0)来讲游戏坐标(830,690)=实际鼠标偏移坐标(660,412)
那根据这个关系我们怎么进行坐标换算呢

坐标换算



该游戏地图的大小都是660*412像素(实际是600*375,上传到论坛变大了,为了方便对照,我们就以上面的图片为例),那比如我们当前人物如上图所示坐标是(258,266),游戏地图最大坐标是(830,690),那么相对于游戏地图起始坐标(0,0)点来讲,我们人物角色当前的所在位置(也就是地图上橘黄色的点的中心位置)就应该等于:
实际偏移X坐标=int(660/830*258)=205实际偏移Y坐标=int(412/690*266)=159{:4_115:}到底对不对呢,我们不妨用大漠综合工具的浮动抓图功能截取上面的图片来验证看看:


有图有真相,事实证明小编的计算是正确的

思路流程







技术难点:
1.地图名不一样所对应的地图最大X、Y坐标都不一样
2.如何确定地图初始点(0,0)位置,然后进行坐标换算后偏移
3.移动过程中,如何判断人物是否已经移动到了指定坐标点,开始下一步动作



绑定窗口



{:5_138:}今天我们写的脚本有用到大漠插件,并且是后台的

因为是单开脚本,顶层窗口句柄就是游戏所对应的客户区句柄,所有用的是大漠的findwindow命令,查找符合类名或者标题名的顶层    可见窗口

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

关于大漠绑定模式如何获知
请参阅相关院刊:
**** Hidden Message *****

判断地图名



游戏左下角会显示地图名及坐标,由于游戏不同的地图对应的游戏最大X坐标、Y坐标都是不一样的,所以我们要先识别当前的地图名,然后根据识别到的地图名对最大X坐标、Y坐标进行相应赋值,由于左下角会显示地图名和坐标,相互之间有时会有影响,所以做了俩个字库(坐标字库、地图名字库),分开调用

打开地图



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


确定地图初始点坐标



找地图上的"复活区"字,找到后就会得到该字左上角第一点坐标(IntX,IntY)然后通过大漠工具精确抓图获取到地图初始点位置(0,0)相对于"复活区"    偏移的坐标

地图起始点X坐标=IntX-154地图起始点Y坐标=IntY+31

判断寻路是否到达



这个在上一期的寻路院刊已经介绍过了,这边就不重复说明了,具体请查看院刊:按键有屎以来最智能寻路系列

整体代码




Call 注册大漠()
Set dm = createobject("dm.dmsoft")//创建大漠对象
Call 找句柄()
Delay 100
Call 大漠绑定()
dm_ret = dm.SetPath("D:\test")//设置全局路径
dm_ret = dm.SetDict(0, "神途地图名字库.txt")//设置字库为地图名字库为0号字库
dm_ret = dm.SetExactOcr(1)//设置找字方式为精确查找,避免类似字符的干扰
//地图起始点X坐标=找"复活区"字-155
//地图起始点Y坐标=找"复活区"字+31
Delay 1000
Call 寻路(360, 360)
Function 寻路(X坐标, Y坐标)
    Call 识别当前地图名//主要作用在于给当前地图最大X、Y坐标赋值
    dm_ret = dm.SetDict(1, "神途坐标字库.txt")//设置坐标字库为1号字库
    dm_ret = dm.UseDict(1)//使用1号字库来找字
    Call 找字
    Delay 1000
    x =int(600/地图最大X坐标*X坐标)
    y =int(375/地图最大Y坐标*Y坐标)
    TracePrint x
    TracePrint y
    dm.MoveTo intX-154+x,intY+31+y//相对于地图起始点坐标进行换算后的鼠标偏移点击
    Delay 1000
    dm.leftclick
    Do
      s = dm.Ocr(77,746,133,764, "ffffff-000000", 0.9)
      If len(s) > 0 Then
            坐标 = split(s, ":")//分割游戏左下角显示的x、y坐标
            TracePrint "当前角色所在坐标为"&s
            //            TracePrint cint(坐标(0))
            //            TracePrint cint(坐标(1))
            If (abs(x坐标 - cint(坐标(0))) < 3) and (abs(y坐标 - cint(坐标(1))) < 3) Then //当前位置坐标与指定坐标的距离差的绝对值小于3则判断到达指定坐标
                dm.keypress 9////按tab关闭地图
                Call Plugin.Msg.Tips("到达指定坐标,寻路结束并关闭地图")//托盘信息提示到达指定坐标
                Exit Do
                ElseCall Plugin.Msg.Tips("寻路中!!!当前角色所在坐标为"&s) //托盘信息提示还未到达指定坐标
            End If
      End If
      Delay 500
    Loop
End Function
Function 找字
    Do
      dm_ret = dm.FindStrFast(0, 0, w, h, "复活区", "ffe34a-000000", 0.9, intX, intY)
      If intX >= 0 and intY >= 0 Then
            TracePrint intX
            TracePrint intY
            Exit Do
      Else
            dm.keypress 9//按tab打开地图
      End If
      Delay 2000
    loop
End Function
Function 识别当前地图名
    Do
      s = dm.Ocr(4,728,200,768, "ffffff-000000", 0.8)//识别当前地图名
      If len(s) > 0 Then
            TracePrint s
            Select Case s
            Case "土城"//地图名是"土城"则对当前地图最大坐标赋值
                TracePrint "当前角色在土城"
                地图最大X坐标=830
                地图最大Y坐标 = 690
            Case "客栈一楼"//地图名是"客栈一楼"则对当前地图最大坐标赋值
                地图最大X坐标=27
                地图最大Y坐标 = 31
                //          Case 其他···
            End Select
            Exit Do
      End If
      Delay 1000
    Loop
End Function
Function 找句柄
    For i = 0 To 20
      hwnd = dm.FindWindow("GAME","神途")
      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







**** Hidden Message *****

f186111 发表于 2015-4-29 15:12:09

我只是看看这个是什么

Alliance 发表于 2015-6-11 14:55:23

寻路?nav导航网格寻路算法 有比这更智能的?

赵叔叔 发表于 2015-6-11 15:04:12

支持楼主,绝对顶你...谢谢!

ffx530 发表于 2015-6-13 22:34:15

很高兴看的这个帖子,支持一下!

wjj197981 发表于 2015-10-15 21:13:26

来学习一下

zmggee 发表于 2015-11-7 01:51:37

难得给力的好帖子,顶楼主。

死理性流氓 发表于 2016-1-20 05:50:49

来看看来看看来看看

yxw6388 发表于 2016-1-22 19:05:20

看看 适不适合3D网游

caolei 发表于 2016-4-6 14:31:47

支持楼主,感谢楼主的分享,好贴必须学习!
页: [1] 2 3 4 5
查看完整版本: 按键有屎以来最智能寻路系列之二