最近刷了一段时间提灯与地下城这个游戏,太肝了[吐舌],毛都干没了,于是想制作一个替我刷图的脚本,说干就干,总结下思路。
总思路是 识别当前地图 --> 与地图中可以交互的点交互 --->识别当前地图。
当然这种是比较简单的思路,后期可以拓展。
准备
思路是使用opencv识别人物,道具和怪物等元素,但是考虑到怪物种类不一而足,素材收集也非一日之功,于是转换思路,从小地图入手,小地图的图标是种类固定的,像这样:
buff
怪物
出口
青蛙
宝石
金币
这里注意,采集到的图标需要和手机或者模拟器的图标一一对应。小地图的图片可以通过adb screencap命令获取或者minicap也是可以的。
首先观察小地图的长框可以发现是275 x 275,进一步观察可以发现分为11*11的格子,然而上面两格比较容易匹配出错,所以我们可以用一个11x9的整数数组来表示地图分布:
地图等分
func GetDevidedCentralPoint(piecesX ,piecesY int,src gocv.Mat)[][]int{
//formed up a vector of (11-2)*11
//use line to devide the map picture into 9x11 pieces
width:=src.Cols()
height:=src.Rows()
lgr.Debug("width:%v height:%v",width,height)
WPP:=width/piecesY
HPP:=height/piecesX
res:=make([][]int,piecesX)
green := color.RGBA{0, 255, 0, 0}
for i:=0;i<piecesX;i++{
resInY:=make([]int,piecesY)
for j:=0;j<piecesY;j++{
Img,err:=src.ToImage()
if err!=nil{
lgr.Debug("Transform to image failed,err:",err)
}else{
colour:=Img.At(WPP*j+WPP/2,HPP*i+HPP/2)
pt:=image.Point{WPP*j+WPP/2,HPP*i+HPP/2}
str:=fmt.Sprintf("%v",j)
gocv.PutText(&src,str,pt,gocv.FontHersheySimplex,0.5,green,1)
r,g,b,_:=colour.RGBA()
if (uint8(r)>20 && uint8(g)>20 && uint8(b)>20){
//lgr.Debug("current point(%v,[%d,%v,%v]) color is : %v",pt,uint8(r),uint8(g),uint8(b),colour)
//gocv.Circle(&src,pt,2,green,1)
resInY[j]=1
}else{
resInY[j]=0
}
}
}
res[i]=resInY
}
return res
}
然后再分别匹配上面收集的图标,匹配到就将地图数组中对应的位置改为相应的数字,定义如下:
/*-1 for store, 0 for unknow status, 1 for path, 2 for hero,3 for exit,4 for gold,5 for pet ,6 for enermys ,7 for iron box,8 for red box,9 for buff , 13 for frog,-2 for goldbox,-3 for temple, */
const heroImg= "./asset/hero.jpg"
const enermyImg= "./asset/enermy.jpg"
const exitImg= "./asset/exit.jpg"
const goldImg= "./asset/gold.jpg"
const gemImg= "./asset/gem.jpg"
const redboxImg= "./asset/redbox.jpg"
const templeImg= "./asset/temple.jpg"
const IronboxImg= "./asset/Ironbox.jpg"
const buffImg= "./asset/buff.jpg"
const petImg= "./asset/pet.jpg"
const pet1Img= "./asset/pet1.jpg"
const pet2Img= "./asset/pet2.jpg"
const pet3Img= "./asset/pet3.jpg"
const frogImg= "./asset/frog.jpg"
const selectorImg= "./asset/selector.jpg"
const storeImg= "./asset/store.jpg"
const goldboxImg= "./asset/goldbox.jpg"
const canceImg= "./asset/cancel.jpg"
const piecesX=9
const piecesY=11
然后,将采集到的地图元素与当前地图一一匹配,使用的方法是之前提过的gocv.MatchTemplate()方法,然后使用gocv.MinMaxLoc()得到可信度和对应的坐标,代码如下:
func MatchTarget(imgTempl,imgSrc ,imgSrc1 gocv.Mat,type_ int ,res [][]int){
result:=gocv.NewMat()
defer result.Close()
m :=gocv.NewMat()
blue := color.RGBA{0, 0, 255, 0}
gocv.MatchTemplate(imgTempl,imgSrc,&result,gocv.TmCcoeffNormed,m)
//gocv.MatchTemplate(imgTempl,imgSrc,&result,1,m)
m.Close()
minValue,maxConfidence,_,maxLoc :=gocv.MinMaxLoc(result)
if maxConfidence < 0.9 {
lgr.Debug("Max confidence of %f is too low. MatchTemplate could not find template in scene.", maxConfidence)
return
}
width:=imgSrc.Cols()
height:=imgSrc.Rows()
WPP:=width/piecesY
HPP:=height/piecesX
for {
//lgr.Debug("The most possible location is : %v,value is : %v",maxLoc,maxConfidence)
rect:=image.Rect(maxLoc.X,maxLoc.Y,maxLoc.X+imgTempl.Cols(),maxLoc.Y+imgTempl.Rows())
indx:=(maxLoc.X+imgTempl.Cols()/2)/WPP
indy:=(maxLoc.Y+imgTempl.Rows()/2)/HPP
pt:=image.Pt(indy,indx)
lgr.Debug("x:%v ,y:%v %v,type:%v",indy,indx,maxLoc,type_)
if type_==2{
HeroPosition=pt
}
res[indy][indx]=type_
if type_==3{
ExitPosition=pt
Dtm:=time.Since(starttime)
wtm:=time.Duration(10)*time.Minute
kc:=40
if killedCnt<kc&&Dtm<wtm&&!IsFirstFloor{
res[indy][indx]=0
}
}
if type_==-1{
IsFirstFloor=true
}
gocv.Rectangle(&imgSrc1, rect, blue, 1)
//lgr.Debug("outer result adress:%v",result)
maxLoc,maxConfidence=GetNextMaxLoc(result,maxLoc,minValue,imgTempl.Cols(),imgTempl.Rows())
if maxConfidence<0.9{
break
}
}
}
func GetNextMaxLoc(result gocv.Mat,maxLoc image.Point,minValue float32,templateW,templateH int)(image.Point,float32){
startX:=maxLoc.X-templateW
startY:=maxLoc.Y-templateH
endX :=maxLoc.X + templateW
endY :=maxLoc.Y + templateH
//lgr.Debug("Inner result adress:%v",result)
if startX<0 || startY <0 {
startX = 0
startY = 0
}
if endX >result.Cols()-1 || endY > result.Rows()-1{
endX=result.Cols()-1
endY=result.Rows()-1
}
for y:=startY;y<endY;y++{
for x:=startX;x<endX;x++{
//ret:=result.GetFloatAt(y,x)
//lgr.Debug("Get point (%v,%v) to %v",x,y,ret)
result.SetFloatAt(y,x,minValue)
//ret:=result.GetFloatAt(y,x)
//lgr.Debug("set point (%v,%v) to %v",x,y,ret)
}
}
_,maxConfidence,_,maxLoc :=gocv.MinMaxLoc(result)
lgr.Debug("the point %v is max confidence point %v",maxLoc,maxConfidence)
return maxLoc,maxConfidence
}
对每一个地图元素,调用MatchTarget 方法来刷新当前地图数组[][]rest,最后就得到了当前的地图元素。
然后就是寻路的算法,我自己使用的是A*算法,大家有兴趣的可以自己去实现一下.
最后附上脚本运行的录屏。
提灯与地下城2023年11月3日密令介绍
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么11月3日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城11月3日密令一览,希望对大家有所帮助。提灯与地下城11月3日密令是什么一、最新密令今日密令:进口枫糖浆上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击上方标注
2023-11-03提灯与地下城最佳宠物搭配(提灯与地下城宠物技能书怎么搭配)
开荒过渡流提灯与地下城是一款地下城探险rouguelike游戏,这个游戏中,有宠物系统,宠物的作用是很大的,那么,玩家如何选择宠物?宠物怎么搭配?提灯与地下城中宠物是我们的主要氪金和投
2022-06-01提灯与地下城2023年9月25日密令一览
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么9月25日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城9月25日密令一览,希望对大家有所帮助。提灯与地下城9月25日密令是什么一、最新密令今日密令:奇妙怪味豆上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击上方标注
2023-09-25提灯与地下城2023年8月23日密令一览
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么8月23日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城8月23日密令一览,希望对大家有所帮助。提灯与地下城8月23日密令是什么一、最新密令今日密令:红糖糍粑上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击上方标注位置
2023-08-23提灯与地下城2023年9月28日密令一览
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么9月28日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城9月28日密令一览,希望对大家有所帮助。提灯与地下城9月28日密令是什么一、最新密令今日密令:巧克力雪糕上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击上方标注
2023-09-28提灯与地下城12月12日密令是什么(提灯与地下城2023年12月12日密令介绍)
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么12月12日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城12月12日密令一览,希望对大家有所帮助。提灯与地下城12月12日密令是什么一、最新密令今日密令:零脂肪薏米糕
2023-12-12提灯与地下城11月22日密令是什么(提灯与地下城2023年11月22日密令介绍)
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么11月22日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城11月22日密令一览,希望对大家有所帮助。提灯与地下城11月22日密令是什么一、最新密令今日密令:香辣猪肉干上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击上
2023-11-22提灯与地下城2023年9月27日密令一览
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么9月27日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城9月27日密令一览,希望对大家有所帮助。提灯与地下城9月27日密令是什么一、最新密令今日密令:葡萄干上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击上方标注位置
2023-09-27提灯与地下城12月14日密令是什么(提灯与地下城2023年12月14日密令介绍)
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么12月14日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城12月14日密令一览,希望对大家有所帮助。提灯与地下城12月14日密令是什么一、最新密令今日密令:蔓越莓雪花酥
2023-12-14提灯与地下城11月14日密令是什么(提灯与地下城2023年11月14日密令介绍)
在提灯与地下城中,输入密令可以获得许多丰富的奖励。那么11月14日提灯与地下城有什么新的密令呢?接下来小编为大家带来提灯与地下城11月14日密令一览,希望对大家有所帮助。提灯与地下城11月14日密令是什么一、最新密令今日密令:海苔吐司面包上面红字就是密令了,快去兑换吧。提灯与地下城的密令更新时间是不定的。通常是周更,节假日除外。二、密令大全实时更新密令大全三、密令兑换流程首先进入游戏主界面,点击
2023-11-15