首页 >>  正文

c+while循环

来源:baiyundou.net   日期:2024-07-17

作者:五月雨雪

前言

我以前写过类似功能的脚本,可以使一个键发挥多个键的功能,但是代码较为琐碎,拓展功能时较为麻烦,所以这次趁着有空重新整理一下,分享给有需要的朋友。

效果

相信很多朋友都玩过moba类的游戏,这类游戏中大部分都集成有快速发信号的功能,即按下一个预设键后不要松开,拖动鼠标到四个不同的方向就可以发送四种对应的信号,比如援助、坚守、危险等。这种转盘形式的信号系统简单直观,熟悉之后下意识即可完成操作,而这也正是本篇文章中脚本的灵感来源。

启用脚本后按下预设键位不要松开,此时保持不动、向上、向下、向左或向右移动鼠标后松开预设键即可触发五种不同的功能。搭配ctrlctrl+alt可以再分别拓展五种功能,总计15种不同的功能。理论上配合各种修饰键的组合可以实现更多的功能,但是我个人认为没有必要,一是记不住,二是可能产生键位冲突。

实现

编辑键位

确保自己的鼠标上有至少一个不用的按键,在对应的配置中将该键位禁用。此处也可以不禁用,但是后续在修改脚本模板时需要将鼠标原地不动对应的功能留空。

修改脚本

首先给出一个脚本模板:

-- 转盘移动方向判定的最小鼠标位移\nlocal TURNTABLE_MIN_DISTANCE = 20\n-- 修饰键状态查询时间间隔\nlocal TURNTABLE_MODIFIER_HEARTBEAT = 10\n-- 转盘两次触发最小时间间隔\nlocal TURNTABLE_MIN_INTERVAL = 50\n\nlocal turntableLastTriggerTime = GetRunningTime()\n\nlocal funcs = {\n    function()\n        OutputLogMessage("test")\n    end,\n    "test",\n    function()\n        OutputLogMessage("test")\n    end,\n}\nfuncs[6] = "test2"\nfuncs[15] = "test3"\n\nEnablePrimaryMouseButtonEvents(true)\n\nfunction OnEvent(event, arg)\n    if (event == "MOUSE_BUTTON_PRESSED" = 7) then\n        x1, y1 = GetMousePosition()\n        -- OutputLogMessage("Mouse pressed at %d, %dn", x1, y1)\n    end\n    if (event == "MOUSE_BUTTON_RELEASED" = 7) then\n        x2, y2 = GetMousePosition()\n        -- OutputLogMessage("Mouse released at %d, %dn", x2, y2)\n        Turntable(x1, y1, x2, y2, funcs)\n    end\nend\n\nfunction Turntable(x1, y1, x2, y2, funcs)\n    -- 核验转盘上次触发时间\n    if (GetRunningTime() - turntableLastTriggerTime < TURNTABLE_MIN_INTERVAL) then\n        return\n    end\n    -- 定义局部变量\n    local dx, dy, direction, func\n    -- 计算鼠标指针位移\n    dx = x2 - x1\n    dy = y2 - y1\n    -- 鼠标移动方向,1-5分别对应原地、上、下、左、右\n    direction = 1\n    if (math.abs(dx) < math.abs(dy)  -TURNTABLE_MIN_DISTANCE) then\n        direction = 2\n    elseif (math.abs(dx) < math.abs(dy)  TURNTABLE_MIN_DISTANCE) then\n        direction = 3\n    elseif (math.abs(dx) > math.abs(dy)  -TURNTABLE_MIN_DISTANCE) then\n        direction = 4\n    elseif (math.abs(dx) > math.abs(dy)  TURNTABLE_MIN_DISTANCE) then\n        direction = 5\n    end\n    -- 根据按住修饰键的不同修改direction的数值,将按键功能由5拓展为15\n    if IsModifierPressed("ctrl")  direction + 10\n     elseif IsModifierPressed("ctrl") then\n        direction = direction + 5\n    end\n    -- 轮询修饰键状态,所有修饰键松开后开始执行对应功能\n    while (IsModifierPressed("ctrl")  funcs[direction]\n    -- OutputLogMessage(direction)\n    if (type(func) == "function") then\n        func()\n    elseif (type(func) == "string") then\n        PlayMacro(func)\n    end\n    -- 更新上次触发时间\n    turntableLastTriggerTime = GetRunningTime()\nend\n\n

具体需要修改的部分见下图:

代码解读

本部分内容可以跳过,只是记录一下写代码时的思路和解决方法,对于有兴趣自己编写罗技Lua脚本的朋友可以随便看看。

罗技的G HUB驱动虽然支持Lua脚本,但是这么多年过去了也没啥突破,还是一个半成品,各种问题很多。

首先要吐槽的一点就是字符串不支持中文,所有定义到变量中的字符串都会被识别为“?”,这一点可以通过sting.byte函数来验证。这就直接导致我想要将中文转为unicode编码通过WinCompose软件直接输出到文本编辑器中的计划破灭。虽然罗技驱动中通过编写宏的方式也可以直接输出中文字符,但是这就少了在代码中即时生成字符串的灵活性。而且实测该种方法输出的字符在WPS软件中会出现未知错误,输出的字符串皆为第一个字符的重复。

罗技的脚本是单线程运行的,希望各位在编写脚本时牢记心头。其实之前看到过一篇文章,该作者自己写了一个包实现了并行的效果,但我没仔细研究,一是懒,二是觉得真没必要,写个鼠标脚本不必如此深入。单线程带来的最大问题就是Sleep函数以及while循环要慎用。以我上面的代码为例,我为了防止按下修饰键对转盘功能的影响,将功能响应放在了松开所有修饰键后。这样设计主要是考虑到如下场景:将按下ctrl并按住转盘键向上滑动的功能设置为按一下S,如果没有上面的设计,就会变为ctrl+S这一保存的快捷键。这样设计的初衷是好的,但是会带来一个问题,那就是如果我在按住ctrl后多次按下转盘键,就会因为代码中轮询修饰键状态而使所有的按键事件卡在一起结算。换个说法,第一次转盘键松开后进入while循环,之后的每次按键都会等待该while循环结束后再依次执行,表现出来的效果就是只有第一次按键执行了正确的功能,后面的每一次按键功能都会变为funcs[1]。为了解决这一弊端,我不得不又引入了执行间隔,也就是转盘键在触发一次后必须等待固定时间间隔后才能再次触发。上面两个操作会带来一个弊端,就是按下修饰键后无法在不松开修饰键的情况下触发多个不同的功能,不过为了兼容性我觉得这点代价还是可以接受的。如果没有键位冲突的顾虑可以自行将模板中对应的两部分代码删除。

应用

游戏发言

仅需一个键就可以在游戏中实现快速喷人沟通的所有语句。玩外服时可以将一些类似good try、we can win、have fun的短句绑定在转盘键上,瞬间化身社交达人,带领团队走向胜利。

文档编辑

类似ctrl+Cctrl+Vctrl+Actrl+Z等常用快捷键。

后记

本篇文章并不是针对一无所知的小白编写的,所有只是简单写了下关键步骤,如果看不太懂的话可以先看看我前两篇文章,里面配图多一些,可能好懂一点。实在看不明白又有强烈使用需求的朋友可以留言或者私信我,如果你的需求很有意思或者使用场景很经典的话,我可能会以你的需求额外写一篇文章。

阅读更多鼠标精彩内容,可前往什么值得买查看

","gnid":"9646d48aabc197f7e","img_data":[{"flag":2,"img":[{"desc":"","height":"512","title":"","url":"https://p0.ssl.img.360kuai.com/t01056c10676873007e.jpg","width":"512"},{"desc":"","height":"755","title":"","url":"https://p0.ssl.img.360kuai.com/t01115e848892b683d4.jpg","width":"600"}]}],"original":0,"pat":"art_src_1,fts0,sts0","powerby":"hbase","pub_time":1689664265000,"pure":"","rawurl":"http://zm.news.so.com/fb62036638323307d7a6823ad1670c8c","redirect":0,"rptid":"19d5c5ee5802d4e4","rss_ext":[],"s":"t","src":"什么值得买","tag":[{"clk":"kdigital_1:罗技","k":"罗技","u":""}],"title":"罗技鼠标lua脚本 篇二:罗技鼠标lua脚本-以转盘形式拓展单键实现15个功能

伏霄肯1843C语言 while循环
郭星庭17745067521 ______ scanf的返回值:返回被成功输入的变量的数量. 这里返回1,表示num已被成功赋值. 所以采用while就是用于判断这个输入是否正确的.

伏霄肯1843C语言中while语句和do while语句具体是如何循环的? -
郭星庭17745067521 ______ while 是先判断后执行,如果第一次判断条件就为假,则一次都不执行. do-while 是先执行后判断,无论如何至少执行一次. while语句的格式: while(条件) { 循环体 } do-while语句的格式: do { 循环体 } while(条件); 注意do-while语句最...

伏霄肯1843c++循环语句 -
郭星庭17745067521 ______ 什么叫能循环?你是说让全部语句循环?while(1) //while语句就是括号内条件满足,就一直循环.{ int a,b,c; scanf("%d%d",&a,&b); c=a+b; printf("c=%d\n",c); } int a,b,c; for(int i=0;i<3;i++) //也是循环语句.i的条件满足就循环. { scanf("%d%d",&a,&b); c=a+b; printf("c=%d\n",c); } }

伏霄肯1843在C语言中用while循环.while(y>x) y+=1,x+=1,z+=1;和while(y>x)y+=1,x+=1;z+=1;后面那个主要多个; -
郭星庭17745067521 ______ 这两个while循环不一样,前面的while循环相当于 while(y>x) { y+=1; x+=1; z+=1; } 后面的while循环相当于 while(y>x) { y+=1; x+=1; } z+=1; 希望能帮到你!!!

伏霄肯1843while循环怎么理解 (C语言问题) -
郭星庭17745067521 ______ 我的理解应该是你没给变量赋初值,回车之后没输入的变量是随机值,可能会导致出错.如果想要输入回车的,可以加判断条件,就是说,while语句里面先让用户输入一个,然后判断输入是否是你指定的结束符,如果不是就继续让用户输入,如果是结束符,比如说'$',则退出循环,继续进行

伏霄肯1843C语言 while语句 -
郭星庭17745067521 ______ 我觉的这里while(key == 0);的作用是让程序停在这里,等待key != 0 满足后继续往下执行.如果这里key对应外面的按键,并且key == 0 表示按键被按下,则外面的while(1) 循环是用来检测按键是否被按下,当检测到按键被按下,即if(key == 0)成...

伏霄肯1843c语言WHILE语句 -
郭星庭17745067521 ______ 弟; 2,永远为真,所以执行了无数次,k=2是一个赋值表达式: while是判断括号内部执行的语句的真假 1,应该上面的程序无数次,下面的一次吧 原理如下,k==2是一个判断式,由于k只有在第一次的时候是2

伏霄肯1843c语言while循环的问题 -
郭星庭17745067521 ______ while循环是对while括号后面的表达式进行真假的判断,,比如你用的a,C语言中有这样的规定,如果a=0;那么a 表达的就是假,如果a不为0,那么他表示的是真,因此,上面的循环,只要a不等于0,那么循环就一直进行 刚开始学的时候,我一...

伏霄肯1843C语言用WHILE循环编九九乘法表 -
郭星庭17745067521 ______ #include <stdio.h> void main() { int x = 1, y = 1; while (x <= 9) { y = 1; while (y <= x) { printf("%d*%d=%d\t", y , x, x * y); y++; } printf("\n"); x++; } } /* 这个就是传说中的嵌套循环. 针对外面的循环,每循环依次输出换行. 对于里边的循环是输出等式. 可以说这是一个很不错的程序. */

伏霄肯1843C语言while含while语句 -
郭星庭17745067521 ______ 当i == 0 第一次外循环: j一直++ 直到 j==5 ,推出了内循环 .在这个过程中也输出了你说的输出.. 当 i== 1 时 ,第二次外循环, j 还是 == 5 ,因为没有改变, 所以内循环没有执行, 当 i 的其他的数时同样道理. .所以出现了你说的问题.. 在外循环将j 初始化就可以了.

(编辑:自媒体)
关于我们 | 客户服务 | 服务条款 | 联系我们 | 免责声明 | 网站地图 @ 白云都 2024