微信跳一跳脚本制作思路

一、由来及游戏介绍

前段时间微信小游戏“跳一跳”火遍朋友圈,尤其深得妹子喜爱,刷分上榜排名攀比顺袭,昨天一兄弟跟我说想刷刷分,一听是要用来撩妹,@!#¥……%@(省略一万字),准备着手做个脚本,我只能帮你这么多了。

写完把测试效果发朋友圈直接炸了很多小伙伴来问怎么做的,于是写一份简单的开发思路给大家参考。

游戏是一款玩法很简单的小游戏,玩家需要目测两个物体之间的距离,然后根据距离和手感控制点击屏幕的时间长度,小人就会跳动相对应的距离,每次准确跳上物体即可得分,跳在正中心得奖励分,掉下去游戏即结束。

二、手工玩耍

先手动试玩几波,得分2位数结束。(图片随便截的,其实笔者自己玩也能几百分啦,并不是手残党)

这里写图片描述

三、观察总结

在游戏过程中,通过仔细体验+观察不难发现

  1. 小人的跳跃方向只有两种情况,这就给我提供了解决方案的思路
    • 当小人在屏幕左下角时,它是朝着右上角跳跃的
    • 当小人在屏幕右下角时,它是朝着左上角跳跃的
      这里写图片描述
  2. 小人的跳跃距离与按下屏幕时间的长短有着某种函数关系
四、理清解决方案思路

很明显如果我们要设计脚本,那么要解决这几个问题

  1. 通过图像分析找到小人在屏幕中的位置(在屏幕中的坐标)
  2. 通过图像分析找到下一个物体的中心(小人要跳到目标坐标)
  3. 算出小人要跳的距离,并找出距离与按压屏幕时长的函数关系,并根据按压时长,调用底层模拟触屏接口(其他办法都可以)实现屏幕延时点击,使小人准确跳到目标位置
五、逐步实现

首先说明一下笔者的开发环境

  1. 硬件
    • PC(windows 7 -64)
    • 小米5s(Android 7.0)
  2. 软件
    • 叉叉开发IED for windows
    • 叉叉开发助手 for android
    • Photoshop cc
    • Markman
  3. 编程语言
    • Lua
1.通过图像分析找到小人在屏幕中的位置(在屏幕中的坐标)

通过观察不难发现小人的颜色是固定的,静止状态时的形状也是固定的,那么好办了,如图所示,使用IED的抓图工具选取小人的十个点作为找色(找色就是读取屏幕中某个点的颜色,并做进一步判断和处理,具体读者可以去叉叉开发者平台自行学习)位置,其中箭头所指向的点即为小人起点坐标
这里写图片描述
使用叉叉API提供的findcolors接口,传入这十个点的颜色坐标,如果手机屏幕中出现这10个点,即判定找到了小人所在位置,并且箭头所指点的左边即为小人所在坐标中心,保存为position

//函数功能为获取小人中心位置
function getPos()
    local pX,pY
    //findcolors里的参数是IDE抓图工具生成的十个点以及其颜色参数
    pos= findColors({0, 0, 1079, 1919},"0|0|0x383862,-36|-2|0x2d2d4b,30|-2|0x383654,-25|-99|0x3a3d55,15|-99|0x8277a3,-31|-163|0x373842,21|-163|0x595280",95, 0, 0, 0)
    if #pos ~= 0 then
        if pos[1].x<540 then
            //tag为小人所在屏幕位置的左右标记
            tag = 0
        else
            tag = 1
        end
        pX = pos[1].x
        pY = pos[1].y
    else    
        pX = 0
        pY = 0
        tag = 0
    end
    sysLog("Pos: "..pX.." "..pY.." "..tag)
    return pX,pY,tag
end
2.通过图像分析找到下一个物体的中心(目标坐标)

说实话笔者在解决这个问题的时候,所花的时间是整个脚本开发时间的4/5,因为游戏背景色会随时变化,目标物体形状,颜色,大小都不固定,脚本语言里又难以集成大规模底层C语言算法去做图形识别,所以尝试了无数错误思路,最后花了半天时间才总结出一个并不完美但是还算可行的方案,介绍如下

仔细发现,小人要跳的目标位置要么在西偏北30°,要么在东偏北30°方向(图三只是选了两条验证猜想的计算数据,其实笔者做了很多数据分析)
这里写图片描述
这里写图片描述
这里写图片描述

得到这个结论之后,现在以小人在右下角为例,我们可以先通过小人起点坐标,然后根据偏移角度30°,计算出屏幕在此沿线上最边界坐标如下图
这里写图片描述
得到坐标之后,我们首先获取此点的像素RGB颜色假设为bgcolor,紧接着循环找色,使坐标沿着沿线右下角方向移动,不断获取像素点颜色,并判断获取的颜色与bgcolor是否相同,如果相同则说明此点位置仍是背景,直到获取第一个与背景色不相同的点的坐标,假设为farpos,即为沿线上目标物体与小人距离最远点的坐标如下图紫色标注
这里写图片描述
这里我们通过判断bgcolor与循环当前获取的color是否相等来判断当前所在位置是否为仍未背景,有些读者可能要说,背景色从左到右并不是纯色,而是渐变色,这样用相等判断会不会出问题。这里不用担心,叉叉API中有提供模糊比色接口,也就是判断两个颜色的相似度,设置90%相似即可

//获取farpos
function getFarP()
    local tempX,tempY
    //开发运行环境的分辨率为1080*1920,所以根据X轴中点540来判断左右,这些细节优化读者可根据自己的经验自行处理
    if posX<540 then  //这里也可以用上一步的tag来判断
        //计算出沿线屏幕边界的temppos
        tempX = 1079
        tempY = posY-(tempX-posX)/1.7320508075
        bgcolor = getColor(tempX,tempY)
        bgcolor = string.format("%#x",bgcolor.."")..""
        while true do
            flag = findColors({tempX-2, tempY, tempX, tempY+2}, "0|0|"..bgcolor..",-1|1|"..bgcolor,90, 0, 0, 0)
            if #flag~=0 then 
                tempX = tempX-1
                tempY = posY-(tempX-posX)/1.7320508075
            else 

                break
            end
        end
    else 
        //计算出沿线屏幕边界的temppos
        tempX = 1
        tempY = posY-(posX-tempX+1)/1.7320508075
        bgcolor = getColor(tempX,tempY)
        bgcolor = string.format("%#x",bgcolor.."")..""
        while true do
            flag = findColors({tempX, tempY, tempX+1, tempY+1}, "0|0|"..bgcolor..",-1|1|"..bgcolor,90, 0, 0, 0)
            if #flag~=0 then 
                tempX=tempX+1
                tempY = posY-(posX-tempX+1)/1.7320508075
            else 
                break
            end
        end
    end
    sysLog("Far : "..tempX.." "..tempY)
    return tempX,tempY
end

接下来我们要保存刚刚找到的坐标点的颜色,假设为obgcolor(即沿线上目标物体的上平面颜色),根据相同的原理,我们先计算出小人中心位置position与刚刚得到的farpos的中点坐标,记为temppos,如下图绿色标注。接着从temppos从右下往左上找,找到第一个与obgcolor同色点的坐标记为nearpos,即为沿线上目标物体与小人距离最近点的坐标如下图蓝色标注
这里写图片描述

//获取nearpos
function getNearP(color,midX,midY,farX,farY,tag)
    //需要说明的是这里有可能由于两个物块离太近导致找不到近点坐标,所以用一个success标记一下,细节优化读者自行测试,判断,总结
    local success = 0
    x = midX
    y = midY
    while y>(farY+20) do
        tcolor = getColor(x,y)
        if tcolor== color then
            success = 1
            break
        else
            if tag==0 then
                x = x+1
                y = midY-(x-midX)/1.7320508075
            else
                x = x-1
                y = midY-(midX-x)/1.7320508075
            end
        end
    end
    if success==0 then
        x = (farX+midX)/2
        y = (farY+midY)/2
    end
    sysLog("Near : "..x.." "..y)
    return x,y

end

到此我相信大家能很容易的计算出despos了,就是紫色标注的坐标与蓝色标注的坐标的中点

3.算出小人要跳的距离,并找出距离与按压屏幕时长的函数关系
//dist为距离 函数功能为根据距离计算时长并长按屏幕
function tap(dist) 
//此段注释的为笔者刚开始测试的函数关系
--  if dist >= 700 then
        k = 1.25
--  elseif dist >= 650 and dist < 700 then
--      k = 1.3
--  elseif dist >= 600 and dist < 650 then
--      k = 1.335
--  elseif dist >= 550 and dist < 600 then
--      k = 1.335
--  elseif dist >= 500 and dist < 550 then
--      k = 1.32
--  elseif dist >= 450 and dist < 500 then
--      k = 1.32
--  elseif dist >= 400 and dist < 450 then
--      k = 1.31
--  elseif dist >= 350 and dist < 400 then
--      k = 1.31
--  elseif dist >= 300 and dist < 350 then
--      k = 1.31
--  elseif dist >= 250 and dist < 300 then
--      k = 1.31
--  elseif dist >= 200 and dist < 250 then
--      k = 1.31
--  elseif dist >= 150 and dist < 200 then
--      k = 1.31
--  elseif dist >=100 and dist < 150 then
--      k = 1.25
--  elseif dist >= 50 and dist < 100 then
--      k = 1.2
--  else 
--      k = 1.15
--  end

//后来干脆直接分段了 这样更准确
    local k = 50
    if dist >= 700 then
        k = 1000 + dist - 700
    elseif dist >= 650 and dist < 700 then
        k = 900 + dist - 650
    elseif dist >= 600 and dist < 650 then
        k = 825 + dist - 600
    elseif dist >= 550 and dist < 600 then
        k = 750 + dist - 550
    elseif dist >= 500 and dist < 550 then
        k = 675 + dist - 500
    elseif dist >= 450 and dist < 500 then
        k = 625 + dist - 450
    elseif dist >= 400 and dist < 450 then
        k = 550 + dist - 400
    elseif dist >= 350 and dist < 400 then
        k = 475 + dist - 350
    elseif dist >= 300 and dist < 350 then
        k = 425 + dist - 300
    elseif dist >= 250 and dist < 300 then
        k = 375 + dist - 250
    elseif dist >= 200 and dist < 250 then
        k = 275 + dist - 200
    elseif dist >= 150 and dist < 200 then
        k = 225 + dist - 150
    elseif dist >= 100 and dist < 150 then
        k = 150 + dist - 100
    elseif dist >= 50 and dist < 100 then
        k = 50 + dist - 50
    else 
        k = 25 + dist
    end
    //随机生成点击位置 主要用于防检测
    pos_x = 540+math.random(-200,200)     
    pos_y = 1200+math.random(-200,200)
    sysLog("dist: "..dist)
    sysLog("lag_time: "..k)
    touchDown(1, pos_x, pos_y)
    mSleep(k)
    touchUp(1, pos_x, pos_y)  
end
六、简单效果展示

这里写图片描述
这里写图片描述
有读者可能会问你那4个红点怎么来的,那个绿色预判小人操作这么骚又是怎么来的,这个很简单,先用ps弄一张png, 得到了despos之后,用叉叉API里提供的图形绘制接口showHUD即可,还可以做得更精细,这里笔者为了节省时间,大概意思了一下。

总之设计花了一天,开发测试和dbug花了半天,文章写了2小时,希望对大家的学习有帮助,

转载恳请注明
错误恳请指正。

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值