如何使用C#代码实现跳一跳自动跳跃(云服务器、云主机、高防IP、高防服务器、香港服务器、美国服务器,编程语言)

时间:2024-05-02 04:24:31 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

效果图

如何使用C#代码实现跳一跳自动跳跃如何使用C#代码实现跳一跳自动跳跃

因为比较急着做出成品,所以细节上没多细抠。感觉设置的跳跃速度稍快了一点,有兴趣的同学可以实测一下。也有一个因素是测试时后台程序比较多,影响了结果。
原理其实也是跟大家想的一样很简单,无非就是三个要素:距离、速度、时间。就是通过当前小蓝人脚底所在的像素坐标和目标平台中心像素的坐标计算距离,除以事先通过测试得出的速度,得出触摸屏幕时间,由程序发出“触摸”指令,实现定点跳跃。不过在做自动计算跳跃所需触摸时间之前还是要做一些准备功夫的。下面直接说一下详细的过程吧。

准备工作:

1、通过PS等工具获取①小蓝人最底下一行(作为当前位置Y坐标)和最左边一列(作为当前位置X坐标)的像素RGB,实测在本机基本都是一样的X(54,63, 102),Y(43, 43, 73)。图片左上角、右下角坐标分别为[0,0][Xmax,Ymax]。②获取小蓝人的头的宽度(所占像素点)。③获取左上角分数最底下一行的像素y坐标。

2、通过指令

adbshellinputtouchscreenswipexyxy延时(ms)

(x、y为触摸屏幕的坐标),结合photoshop测试出“跳一跳”每一条的速度。本例中测得结果约为17 / 24(pixel/ms),实际游戏中的速度略小于这个速度。大家用代码可以精确测一下,我已经没耐心了0.0。

3、电脑准备好调试环境(因为穷所以测试用的是自己的Android机,所以要准备好ADK(platform-tools/adb.exe);另外本次测试语言是C#)

4、手机开启调试模式,连接电脑,打开“跳一跳”

过程:

一、获取设备号(获取序列号,或者直接查看手机信息),指令:

adbdevices

二、截取手机当前画面到sd卡(本机存储格式为png,实测手机按键截屏为jpg(失真)),指令:

adb-s设备号shellscreencap-p/sdcard/temp.png

三、复制文件到电脑,指令:

adb-s设备号pull/sdcard/temp.png保存路径

四、删除文件,指令:

adb-s设备号shellrm/sdcard/temp.png

五、获取小蓝人脚底像素坐标和目标平台中心像素坐标,下面详细说说里面的步骤

1、通过Bitmap类读取图片,再用unsafe代码利用指针把RGB数据直接从内存拷出来存放到byte数组中(这步其实不用也可以但不知道直接通过Bitmap获取像素效率会不会很低,大家可以测了分享一下结果)
2、用两层循环y从max->0,遍历x轴像素,通过对比找出小蓝人位置,本例通过两个rgb像素的标准差不超过3作为置信偏差判断两个像素是否为同一元素。再稍微处理一下就可得出当前坐标。
3、利用上面得到的坐标P以及一开始准备工作中提到的分数底行y坐标(取大于该y作为startY即可)再进行对目标坐标的搜索:用两层循环y从startY->Py,遍历x轴像素(利用P的x坐标缩小搜索的x坐标范围:若x位于左半屏则搜索Px+40->Xmax,反之搜索0->Px-40,注:不缩小范围会出错,原因大家想想)。(这个40可取大于小蓝人头宽度一半的值即可)
4、那就用我们的勾三股四弦五定理再开根求出距离。距离除以速度得出时间。

六、发送触摸指令实现定时跳跃,指令:

adbshellinputtouchscreenswipexyxy延时(ms)

这里不得不说一下,当时找半天找不到定时触摸的指令,网上有个用6个指令组合实现定时触摸屏幕的方法,但实测无效,而且也怕指令这么多,延时还是分开控制,肯定会对跳跃结果有很大影响。后面看到一条利用swipe指令实现的评论,真是醒目。swipe虽然是滑动指令,但如果设置起止坐标都是同一个坐标不就相当于实现了定点定时触摸了吗。

七、七就是一直重复二~六的步骤就是了。

本次测试很东西都是急着做,没仔细研究,例如获取跳跃速度这个就是傻瓜式的通过手动发送跳跃指令、截图用ps手动计算出来的。大家可以用代码实现一下。希望大家指正可以改进的地方。

C#源码如下

Cmd类,实现cmd执行命令

classCmd{privateSystem.Diagnostics.Processprocess;privateboolisExecuted;//是否执行过命令privatestringcommand;//上次执行命令privateintresult;//上次执行命令结果privatestringresultContent;//上次执行命令返回结果publicCmd(){process=newSystem.Diagnostics.Process();process.StartInfo.FileName="cmd.exe";process.StartInfo.UseShellExecute=false;//是否使用操作系统shell启动process.StartInfo.RedirectStandardInput=true;//接受来自调用程序的输入信息process.StartInfo.RedirectStandardOutput=true;//由调用程序获取输出信息process.StartInfo.RedirectStandardError=true;//重定向标准错误输出process.StartInfo.CreateNoWindow=true;//不显示程序窗口isExecuted=false;}publicintExecuteCmd(stringcmd){command=cmd;try{process.Start();process.StandardInput.WriteLine(cmd+"&exit");process.StandardInput.AutoFlush=true;stringcontent=process.StandardOutput.ReadToEnd();process.WaitForExit();//等待程序执行完退出进程process.Close();result=0;resultContent=content.Split(newstring[]{"&exit"},StringSplitOptions.None)[1].Replace("\n","");}catch(Exceptionex){result=-1;resultContent=ex.Message;}if(!isExecuted)isExecuted=true;returnresult;}privateintExecuteCmd(stringadbPath,stringcmd){command=$"\"{adbPath}\"{cmd}";try{process.Start();process.StandardInput.WriteLine(command+"&exit");process.StandardInput.AutoFlush=true;stringcontent=process.StandardOutput.ReadToEnd();process.WaitForExit();//等待程序执行完退出进程process.Close();result=0;resultContent=content.Split(newstring[]{"&exit"},StringSplitOptions.None)[1].Replace("\n","");}catch(Exceptionex){result=-1;resultContent=ex.Message;}if(!isExecuted)isExecuted=true;returnresult;}publicstringGetExcResult(){if(isExecuted){if(result==0){returnresultContent;}else{return$"ExecuteFailed!Command:{command}\n{resultContent}";}}else{return"从未执行过命令";}}publicvoidDisposeProcess(){process.Dispose();}}classPixel{publicbyte[]pixel=newbyte[3];publicPixel(){}}

Pixel类,存放RGB字节

classPixel{publicbyte[]pixel=newbyte[3];publicPixel(){}}

PlayJumpJump类,实现主要分析计算和跳跃操作

classPlayJumpJump{privatestaticreadonlyintconfidenceItv=3;//两个rgb标准差小于等于3认为是同一元素privatestaticreadonlyPixelmanXRgb=newPixel{pixel=newbyte[]{54,63,102}};//小人X坐标rgbprivatestaticreadonlyPixelmanYRgb=newPixel{pixel=newbyte[]{43,43,73}};//小人Y坐标rgbprivatestaticreadonlydoublestartYPer=0.15625;//分数下一行Y为第289,取300/1920=0.15625,从下一行开始搜索目标privatestaticreadonlydoubleSpeed=17.0/24;//速度,最重要的因素,这也是约摸算出来的privatestaticreadonlystring[]TouchCoor=newstring[]{"800","1700"};//触屏位置privatestaticreadonlystringFormat="png";//本人用机子截取为png,也可不设格式(实测bitmap与pscc打开同一jpg,同一像素点rgb值不一致,怀疑是bitmap打开jpg会有失真)privatestaticreadonlystringTempDir="/sdcard/";privatestaticreadonlystringSaveDir="temp/";privatestaticreadonlystringCaptureScreen_Command=$"-s{{0}}shellscreencap-p{TempDir}{{1}}";privatestaticreadonlystringCopyFile_Command=$"-s{{0}}pull{TempDir}{{1}}\"{SaveDir}{{1}}\"";privatestaticreadonlystringRemoveFile_Command=$"-s{{0}}shellrm{TempDir}{{1}}";privatestaticreadonlystringLongPress_Command="shellinputtouchscreenswipe{0}{1}{0}{1}{2}";privateCmdmyCmd;privatestringadbCmdPrefix;privatestringresult;publicList<string>devices;publicPlayJumpJump(stringadbPath){myCmd=newCmd();adbCmdPrefix=$"\"{adbPath}\"";if(!Directory.Exists(SaveDir)){Directory.CreateDirectory(SaveDir);}}publicvoidInit(){myCmd=newCmd();}publicboolGetDevices(){devices=newList<string>();myCmd.ExecuteCmd(ReturnCommand("devices"));result=myCmd.GetExcResult();foreach(stringlineinresult.Split(newchar[]{'\n'})){if(line.Contains("device")){List<string>items=line.Split(newchar[]{'\t','\r'},StringSplitOptions.None).ToList();if(items.Count>1){devices.Add(items[items.IndexOf("device")-1]);}}}returndevices.Count>0?true:false;}publicstringCaptureScreen(){stringfileName=$"temp{DateTime.Now.ToString("HHmmssfff")}.{Format}";myCmd.ExecuteCmd(ReturnCommand(CaptureScreen_Command,newstring[]{devices[0],fileName}));myCmd.ExecuteCmd(ReturnCommand(CopyFile_Command,newstring[]{devices[0],fileName}));myCmd.ExecuteCmd(ReturnCommand(RemoveFile_Command,newstring[]{devices[0],fileName}));returnAppDomain.CurrentDomain.BaseDirectory+SaveDir+fileName;}publicstaticunsafePixel[][]GetPixelArray(stringpath){Bitmapbitmap=newBitmap(path);intdepth=Image.GetPixelFormatSize(bitmap.PixelFormat);if(depth==24){intwidth=bitmap.Width;intheight=bitmap.Height;Pixel[][]pixelArray=newPixel[height][];for(inti=0;i<pixelArray.Length;i++)pixelArray[i]=newPixel[width];Rectanglerect=newRectangle(0,0,bitmap.Width,bitmap.Height);BitmapDatabmpData=bitmap.LockBits(rect,ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);byte*ptr=(byte*)bmpData.Scan0;for(inti=0;i<pixelArray.Length;i++){for(intj=0;j<pixelArray[i].Length;j++){pixelArray[i][j]=newPixel{pixel=newbyte[]{*(ptr+2),*(ptr+1),*ptr}};ptr+=3;}ptr+=bmpData.Stride-3*bmpData.Width;//减去占位字节(可能出于性能或兼容性考虑,Stride为4的倍数)}bitmap.UnlockBits(bmpData);returnpixelArray;}elseif(depth==32){intwidth=bitmap.Width;intheight=bitmap.Height;Pixel[][]pixelArray=newPixel[height][];for(inti=0;i<pixelArray.Length;i++)pixelArray[i]=newPixel[width];Rectanglerect=newRectangle(0,0,bitmap.Width,bitmap.Height);BitmapDatabmpData=bitmap.LockBits(rect,ImageLockMode.ReadOnly,PixelFormat.Format32bppRgb);byte*ptr=(byte*)bmpData.Scan0;for(inti=0;i<pixelArray.Length;i++){for(intj=0;j<pixelArray[i].Length;j++){pixelArray[i][j]=newPixel{pixel=newbyte[]{*(ptr+2),*(ptr+1),*ptr}};ptr+=4;//每3个字节忽略1个透明度字节}}bitmap.UnlockBits(bmpData);returnpixelArray;}else{returnnull;}}publicvoidJump2Happy(){stringpicture=CaptureScreen();Pixel[][]pixelArray=GetPixelArray(picture);int[]curCoor=GetCurCoordinates(pixelArray);int[]destCoor=GetDestCoordinates(pixelArray,curCoor);doubledistance=Math.Round(Math.Sqrt(Math.Pow(Math.Abs(destCoor[0]-curCoor[0]),2)+Math.Pow(Math.Abs(destCoor[1]-curCoor[1]),2)),3);inttime=(int)(distance/Speed);Console.WriteLine($"from[{curCoor[0]},{curCoor[1]}]\tto[{destCoor[0]},{destCoor[1]}]distance≈{distance}take≈{time}ms==>>Jump");myCmd.ExecuteCmd(ReturnCommand(LongPress_Command,newstring[]{TouchCoor[0],TouchCoor[1],time.ToString()}));}publicstaticint[]GetCurCoordinates(Pixel[][]pixelArray){int[]coordinates=newint[2];List<int[]>xList=newList<int[]>();List<int[]>yList=newList<int[]>();//y从max->0,遍历x轴像素for(inti=pixelArray.Length-1;i>=0;i--){for(intj=0;j<pixelArray[i].Length;j++){if(isSameElement(pixelArray[i][j],manXRgb,confidenceItv)){xList.Add(newint[]{j,i});}}if(xList.Count>0)break;}coordinates[0]=xList.Count>0?(xList[0][0]+xList[xList.Count-1][0])/2:0;//x从0->max,遍历y轴像素for(inti=0;i<pixelArray[0].Length;i++){for(intj=pixelArray.Length-1;j>=0;j--){if(isSameElement(pixelArray[j][i],manYRgb,confidenceItv)){yList.Add(newint[]{i,j});}}if(yList.Count>0)break;}coordinates[1]=yList.Count>0?(yList[0][1]+yList[yList.Count-1][1])/2:0;returncoordinates;}publicstaticint[]GetDestCoordinates(Pixel[][]pixelArray,int[]curCoor){PixelenviRgb;//排除rgb采样PixeldestRgb=null;//采样int[]coordinates=newint[2];List<int[]>xList=newList<int[]>();List<int[]>yList=newList<int[]>();intstartY=(int)(pixelArray.Length*startYPer);intstart,end,inc;if(curCoor[0]<(pixelArray[0].Length/2)){start=curCoor[0]+40;end=pixelArray[0].Length;}else{start=0;end=curCoor[0]-40;}//y从0->max,遍历x轴像素for(inti=startY;i<pixelArray.Length;i++){enviRgb=pixelArray[i][0];for(intj=start;j<end;j++){if(!isSameElement(pixelArray[i][j],enviRgb,confidenceItv)){xList.Add(newint[]{j,i});if(destRgb==null)destRgb=pixelArray[i][j];}}if(xList.Count>0)break;}coordinates[0]=xList.Count>0?(xList[0][0]+xList[xList.Count-1][0])/2:0;//x从0->max,遍历y轴像素if(coordinates[0]<(pixelArray[0].Length/2)){start=0;end=pixelArray[0].Length-1;inc=1;}else{start=pixelArray[0].Length-1;end=0;inc=-1;}boolisFond=false;for(inti=start;i!=end;i+=inc){for(intj=startY;j<curCoor[1];j++){if(isSameElement(pixelArray[j][i],destRgb,confidenceItv)){coordinates[1]=j;isFond=true;break;}}if(isFond)break;}returncoordinates;}publicstaticboolisSameElement(Pixelpixel1,Pixelpixel2,intconfidence){returnMath.Pow(pixel1.pixel[0]-pixel2.pixel[0],2)+Math.Pow(pixel1.pixel[1]-pixel2.pixel[1],2)+Math.Pow(pixel1.pixel[2]-pixel2.pixel[2],2)<=3*Math.Pow(confidence,2);}publicstringReturnCommand(stringcommand,string[]parameter){returnadbCmdPrefix+string.Format(command,parameter);}publicstringReturnCommand(stringcommand,stringparameter){returnadbCmdPrefix+string.Format(command,parameter);}publicstringReturnCommand(stringcommand){returnadbCmdPrefix+command;}publicvoidDisposeProcess(){myCmd.DisposeProcess();myCmd=null;}

测试:

staticvoidMain(string[]args){stringadbPath="";//adb.exe路径PlayJumpJumptestPlay=newPlayJumpJump(adbPath);if(testPlay.GetDevices()){while(true){testPlay.Jump2Happy();Thread.Sleep(1200);}}testPlay.DisposeProcess();Console.ReadKey();}}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:如何使用C#代码实现跳一跳自动跳跃的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:php微信收不到post数据怎么解决下一篇:

14 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18