精华内容
下载资源
问答
  • 自己写的手机游戏脚本

    千次阅读 多人点赞 2020-03-09 11:46:27
    由于过年时间特殊情况,在家特别无聊,就了一个手机游戏脚本 脚本所属游戏-战舰少女 功能很简单 ● 自动刷活动材料 ● 自动收获远征奖励 ● 自动出征升级 ● 自动分解船只 但是毕竟只是自己用的,选地图功能没有...

    由于过年时间特殊情况,在家特别无聊,就写了一个手机游戏的脚本
    脚本所属游戏-战舰少女
    功能很简单
    ● 自动刷活动材料
    ● 自动收获远征奖励
    ● 自动出征升级
    ● 自动分解船只
    但是毕竟只是自己用的,选地图功能没有写,如果要用的话,还是需要自己先选好图,然后打开脚本。
    逻辑有很多地方也需要改善。姑且这算是个砖吧,我也算是抛砖引玉,后续如果有哪位大神有兴趣的话,可以自己完善代码(别自己脸上贴金了,大佬哪会看上我这种代码啊 #手动捂脸)。
    另外 func的那个是自己写的 文字识别功能,识别率不高就不贴上来了。功能就是根据坐标截取某一部分图片识别中间的文字,返回是识别到的文字。
    注:本人第一次写手机游戏脚本,希望各位大神多提意见。
    注2:里面的坐标是我一个一个试出来的。如果哪位大神有比较有效的方法获取坐标,也请不吝赐教,在下不胜感激。

    import os
    from time import sleep
    import uiautomator2 as um
    from PIL import Image, ImageFilter, ImageOps
    from pytesseract import image_to_string
    
    from func import get_text
    
    
    class JianShao:
        def __init__(self):
            self.d = um.connect('127.0.0.1:62001')
            self.s_size = self.d.window_size()
            self.title = ('', '第一章', '第二章', '第三章', '第四章', '第五章', '第六章', '第七章', '第八章')
            self.is_food = 0  # 是否补给
            # self.is_fix = 0 # 是否修理
            self.is_resolve = 0  # 是否分解
            # self.d.window_size
    
        def start_app(self):
            '''登录游戏'''
            self.d.app_start('com.huanmeng.zhanjian2', 'org.cocos2dx.cpp.AppActivity')
            sleep(5)
            '''进入游戏页面'''
            while 1:
                self.click_grid(0.884, 0.871)
                sleep(2)
                if not self.text_in_screen(self.get_grid(0.818, 0.822, 0.946, 0.891), '进入游戏', 0):
                    break
    
        def click_grid(self, x, y):
            """按指定的坐标点击屏幕"""
            self.d.click(int(self.s_size[1] * x), int(self.s_size[0] * y))
    
        def get_grid(self, x, y, x1, y1):
            """返回矩形位置"""
            return(self.s_size[1] * x, self.s_size[0] * y, self.s_size[1] * x1, self.s_size[0] * y1)
        
        def text_in_screen(self, grid, n_text, radius=1, lang='chi_sim'):
            """ 判断文字在不在图片里
            grid: 截取的图片坐标(左上角x, 左上角y, 右下角x, 右下角y)
            radius: 高斯卷积核参数 为数字
            lang: 识别语言 'chi_sim', 'eng'
            n_text: 需要判断的文字
            """
            pic = self.d.screenshot()
            text = get_text(pic, grid, radius, lang)
            if n_text in text:
                return 1
            return 0
    
        def return_main(self):
            print('返回主界面')
            if not self.text_in_screen(self.get_grid(0.686, 0.924, 0.728, 0.96), '任务', radius=0.5):
                while True:
                    self.click_grid(0.023, 0.041)
                    sleep(0.5)
                    if self.text_in_screen(self.get_grid(0.686, 0.924, 0.728, 0.96), '任务', radius=0.5):
                        self.click_grid(0.876, 0.22)
                        break
            self.click_grid(0.876, 0.22)
    
        def entry_map(self):
            """从主界面进入到地图界面"""
            print('点击出征')
            # punts_num = 0
            # 演习     radius=0   (1280*0.28, 720*0.022, 1280*0.34, 720*0.072)
            grid = self.get_grid(0.28, 0.022, 0.34, 0.072)
            while True:
                # 点击出征
                self.click_grid(0.946, 0.946)
                sleep(1)
                if self.text_in_screen(grid, '演习', 0):
                    print('进到地图界面')
                    break
    
        def expedition(self):
            '''获取远征奖励'''
            pic = self.d.screenshot()
            for i in range(4):
                end_time = get_text(pic, self.get_grid(0.84, 0.16+i/5, 0.97, 0.23+i/5), 0, 'eng')
                if end_time == '00:00:00':
                    self.click_grid(0.9, 0.27+i/5)
                    sleep(1.5)
                    self.click_grid(0.4, 0.63)  # 和分解船只确定在一个地方
                    sleep(1.5)
                    print('点击确认')
                    self.click_grid(0.4, 0.63)
                    sleep(0.5)
    
        def army_ride(self, num, fix=0):
            """出征前准备 到补给完
            num: 队伍编号 int 1,2,3,4
            fix: 是否需要修理 0表示不修理 功能没写   换船功能也没写
            """
            # if self.is_resolve >= 13:
            #     print('需要分解船只')
            #     self.resolve()
            #     # 进入地图
            #     self.entry_map()
            if self.is_resolve >=30:
                self.return_main()
                self.entry_map()
                self.is_resolve = 0
            # 判断是否在远征界面 
            while self.text_in_screen(self.get_grid(0.255, 0.26, 0.311, 0.315), f'奖励', 0):
                print('收获远征奖励')
                self.expedition()
                self.return_main()
                self.entry_map()
            # 判断有没有在队伍选择界面
            while 1:
                # 开始出征  radius=2   (1280*0.817, 720*0.887, 1280*0.932, 720*0.95)
                self.click_grid(0.638, 0.832)
                sleep(0.5)
                if self.text_in_screen(self.get_grid(0.817, 0.887, 0.932, 0.95), '开始出征', 2):
                    break
            # 选择队伍
            army = ('', (0.1, 0.16), (0.23, 0.16), (0.36, 0.16), (0.48, 0.16))
            print(f'选择第{num}队')
            self.click_grid(*army[num])
            sleep(0.3)
            if self.is_food:
                self.click_grid(0.3, 0.79)
                sleep(0.3)
                print('点击补给')
                self.click_grid(0.85, 0.68)
                self.is_food = 0
                sleep(0.3)
    
        def go_on_ride(self):
            print('开始出征')
            while 1:
                self.click_grid(0.86, 0.881)
                sleep(0.5)
                if self.text_in_screen(self.get_grid(0.85, 0.9, 0.96, 0.96), '开始战斗'):
                    print('遇到敌军')
                    break
                print('没有遇到敌军')
    
        def get_back(self, title):
            """没有需要战斗的敌军,点击撤退
            title: 正在战斗的章节 int 1, 2, 3, 4, 5, 6, 7, 8
            """
            while 1:
                self.click_grid(0.68, 0.953)
                sleep(1)
                if self.text_in_screen(self.get_grid(0.035, 0.5, 0.113, 0.555), self.title[title], 0):
                    break
    
        def fight_night(self, title, night=0, go_on=0):
            """ 结束战斗
            title: 正在战斗的章数 int 1,2,3,4,5,6,7,8
            night: 是否夜战 0不夜战
            go_on: 前进/回港  0回港
            """
            while 1:
                sleep(1.5)
                pic = self.d.screenshot()
                # pic.show()
                text1 = get_text(pic, self.get_grid(0.41, 0.025, 0.595, 0.125), 1.4)
                text2 = get_text(pic, self.get_grid(0.625, 0.625, 0.685, 0.685))
                if '战斗结果' in text1:
                    print('战斗结束')
                    break
                # 放弃  radius=1   (1280*0.63, 720*0.63, 1280*0.68, 720*0.68)
                if '放弃' in text2:
                    if night:
                        print('进入夜战')
                        while 1:
                            self.click_grid(0.35, 0.66)
                            sleep(3)
                            if self.text_in_screen(self.get_grid(0.41, 0.025, 0.595, 0.125), '战斗结果', 1.4):
                                print('战斗结束')
                                break
                            print('战斗未结束')
                    else:
                        print('战斗结束, 不夜战')
                        while 1:
                            self.click_grid(0.65, 0.66)
                            sleep(1.2)
                            if self.text_in_screen(self.get_grid(0.41, 0.025, 0.595, 0.125), '战斗结果', 1.4):
                                break
                    break
                print('战斗未结束')
            while True:
                self.click_grid(0.65, 0.65)
                sleep(0.8)
                if self.text_in_screen(self.get_grid(0.035, 0.5, 0.113, 0.555), self.title[title], 0):
                    print('返回到队伍界面')
                    break
    
        def resolve(self):
            """分解船只,完成之后进入主界面"""
            print('准备分解战舰')
            self.return_main()
            while 1:
                self.click_grid(0.035, 0.9)
                sleep(0.5)
                print('点击建造(主页)')
                self.click_grid(0.035, 0.4)
                sleep(1)
                if self.text_in_screen(self.get_grid(0.28, 0.015, 0.338, 0.09), '解体'):
                    print('点击解体')
                    break
                print('未进入到建造界面')
                self.click_grid(0.5, 0.99)
                sleep(0.5)
            while 1:
                self.click_grid(0.3, 0.05)
                sleep(0.3)
                if self.text_in_screen(self.get_grid(0.825, 0.205, 0.96, 0.266), '解体获得资源'):
                    print('点击添加')
                    break
            while 1:
                self.click_grid(0.07, 0.35)
                sleep(0.5)
                if self.text_in_screen(self.get_grid(0.862, 0.02, 0.955, 0.072), '选择舰船'):
                    print('开始添加')
                    break
            ship_list = [(0.2, 0.3), (0.3, 0.3), (0.4, 0.3), (0.53, 0.3),(0.64, 0.3),(0.75, 0.3),
                         (0.08, 0.7), (0.2, 0.7), (0.3, 0.7), (0.4, 0.7), (0.53, 0.7),(0.64, 0.7),(0.75, 0.7)]
            for i in ship_list:
                self.click_grid(i[0], i[1])
            print('点击确定')
            while 1:
                self.click_grid(0.9, 0.9)
                sleep(0.5)
                if self.text_in_screen(self.get_grid(0.825, 0.205, 0.96, 0.266), '解体获得资源'):
                    print('卸下装备')
                    break
            self.click_grid(0.84, 0.66)
            print('确定解体')
            self.click_grid(0.9, 0.9)
            sleep(0.3)
            if self.text_in_screen(self.get_grid(0.353, 0.6, 0.416, 0.665), '确认', radius=2.5):
                self.click_grid(0.4, 0.64)
                sleep(0.3)
            self.is_resolve = 0
            self.return_main()
    
        def get_punts(self):
            '''2-1刷战利品'''
            self.entry_map()
            print('2-1')
            while 1:
                # print(f'刷到{punts_num}个材料')
                # 战斗前准备 选队-补给-出征-遇到敌军
                self.army_ride(2)
                self.go_on_ride()
                if not self.text_in_screen(self.get_grid(0.018, 0.442, 0.063, 0.495), '补给', 0):
                    print('没有补给')
                    self.get_back(2)
                else:
                    print('准备战斗')
                    while True:
                        self.click_grid(0.898, 0.928)
                        sleep(0.4)
                        # 选择阵型  radius=1   (1280*0.88, 720*0.06, 1280*0.995, 720*0.118)
                        if self.text_in_screen(self.get_grid(0.88, 0.06, 0.995, 0.118), '选择阵型'):
                            break
                    print('选择复纵队')
                    self.click_grid(0.836, 0.405)
                    self.is_food = 1
                    self.is_resolve += 1
                    sleep(0.5)
                    self.click_grid(0.922, 0.43)
                    sleep(40)
                    self.fight_night(2)
    
        def fishing(self):
            '''8-1炸鱼'''
            self.entry_map()
            # 进入8-1
            print('8-1')
            while 1:
                # 战斗前准备 选队-补给-出征-遇到敌军
                self.army_ride(4)
                self.go_on_ride()
                # (1280*0.03, 720*0.08, 1280*0.21, 720*0.17)
                if not self.text_in_screen(self.get_grid(0.03, 0.08, 0.21, 0.17), '复纵阵', radius=0):
                    print('准备战斗')
                    while True:
                        self.click_grid(0.898, 0.928)
                        sleep(0.4)
                        # 选择阵型  radius=1   (1280*0.88, 720*0.06, 1280*0.995, 720*0.118)
                        if self.text_in_screen(self.get_grid(0.88, 0.06, 0.995, 0.118), '选择阵型'):
                            break
                    print('选择单横队')
                    self.is_food = 1
                    self.click_grid(0.928, 0.939)
                    sleep(0.5)
                    self.click_grid(0.898, 0.928)
                    sleep(15)
                    # 进入夜战,回港,返回第八章界面
                    self.fight_night(8, 1, 0)
                    self.is_resolve += 1
                else:
                    print('敌方重巡, 撤退')
                    self.get_back(8)
        
        def map_8_2(self):
            # 战前点击(选择战况)(0.828, 0.192, 0.918, 0.24) 火力万岁  点击(0.2, 0.65)
            # 遇到敌人  梯形队 (0.782, 0.74)
            # 不夜战
            self.entry_map()
            print('8-2')
            while 1:
                self.army_ride(3)
                print('开始出征')
                while 1:
                    self.click_grid(0.86, 0.95)
                    sleep(1)
                    if self.text_in_screen(self.get_grid(0.828, 0.192, 0.918, 0.24), '火力万岁', 0):
                        print('遇到敌军')
                        while 1:
                            self.click_grid(0.2, 0.65)
                            sleep(1.2)
                            if self.text_in_screen(self.get_grid(0.85, 0.9, 0.96, 0.96), '开始战斗'):
                                print('准备战斗')
                                break
                        break
                    print('没有遇到敌军')
                while 1:
                    self.click_grid(0.898, 0.928)
                    sleep(0.4)
                    # 选择阵型  radius=1   (1280*0.88, 720*0.06, 1280*0.995, 720*0.118)
                    if self.text_in_screen(self.get_grid(0.88, 0.06, 0.995, 0.118), '选择阵型'):
                        print('选择梯形队')
                        break
                while 1:
                    self.click_grid(0.92, 0.76)
                    sleep(2)
                    if not self.text_in_screen(self.get_grid(0.88, 0.06, 0.995, 0.118), '选择阵型'):
                        break
                
                self.is_food = 1
                sleep(10)
                self.fight_night(8, 0, 0)
                self.is_resolve += 1
    
    
    展开全文
  • 写脚本用SciTE

    2013-08-26 16:08:02
    写脚本用SciTE 游戏脚本编辑。dat
  • 一个用lua游戏脚本实例

    热门讨论 2010-04-19 13:28:03
    一个用lua游戏脚本实例,是word格式的,值得一看,通过这个例子你可以了解到游戏中的脚本是怎么
  • 收藏!一篇教会你90%的shell脚本

    万次阅读 多人点赞 2019-09-06 18:18:36
    还不会shell脚本?这篇文章教会你90%的shell脚本

    在公司项目的开发过程中,需要编写shell脚本去处理一个业务,在编写过程中发现自身对shell脚本的知识不够完善,顾整理一下,本文章主要内容来自菜鸟教程 , 也添加了一些知识点

    看完这边文章应该就可以独立完成大部分脚本得编写

    shell脚本?

    在说什么是shell脚本之前,先说说什么是shell。

    shell是外壳的意思,就是操作系统的外壳。我们可以通过shell命令来操作和控制操作系统,比如Linux中的Shell命令就包括ls、cd、pwd等等。总结来说,Shell是一个命令解释器,它通过接受用户输入的Shell命令来启动、暂停、停止程序的运行或对计算机进行控制。

    shell 是一个应用程序,它连接了用户和 Linux 内核,让用户能够更加高效、安全、低成本地使用 Linux 内核,这就是 Shell 的本质。

    shell 本身并不是内核的一部分,它只是站在内核的基础上编写的一个应用程序。

    那么什么是shell脚本呢?

    shell脚本就是由Shell命令组成的执行文件,将一些命令整合到一个文件中,进行处理业务逻辑,脚本不用编译即可运行。它通过解释器解释运行,所以速度相对来说比较慢。

    shell脚本中最重要的就是对shell命令的使用与组合,再使用shell脚本支持的一些语言特性,完成想要的功能。

    微信扫下述二维码关注公众号,回复“源码”,即可免费获取“经典飞机大战源码 + 经典像素鸟游戏源码 + 人事管理系统源码 ”!
    匠心Java*

    注释

    “# ”开头的就是注释,被编译器忽略

    • 单行注释: #
    • 多行注释: :<<EOF … EOF 或者 :<<! … ! (:<< 标识多行注释开始,并指定一个标识符作为开始结束的标志)

    变量

    变量类型
    运行shell时,会同时存在三种变量:

    1. 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
    2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
    3. shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    变量操作

    • 创建普通变量: name=“test” (=两边不可有空格)
    • 创建只可函数体中使用的局部变量: local name=“test” (使用local修饰的变量在函数体外无法访问,并且local只能在函数体内使用)
    • 使用变量: echo $name 或者 echo ${name} (推荐使用大括号版)
    • 变量重新赋值: name=“new_test” (将原值覆盖)
    • 只读变量: name=“only_read” -> readonly name (使用readonly标识后的变量,不可被修改)
    • 删除变量: unset name; (删除之后不可访问,删除不掉只读变量)

    字符串变量
    1)单引号

    • 单引号变量var='test' ,只能原样输出,变量无效
    • 单引号中不能出现一个单独的单引号,转义也不可以

    2)双引号

    • 双引号变量var="my name is ${name}",变量有效
    • 可出现转义符

    3)拼接字符串

    • 中间无任何+,之类的字符
    • name=“this is”" my name"; name=“this is my name”; name=“this” is “my name” 等效
    • name=‘this is’’ my nam’; name=‘this is my name’; name=‘this’ is ‘my name’ 等效

    4)获取字符串长度

    • 在${}中使用“#”获取长度
    • name=“test”;
    • echo ${#name}; # 输出为4

    5)提取子字符串

    • 1:4 从第2个开始 往后截取4个字符
    • ::4 从第一个字符开始 往后截取4个字符
    • name=“this is my name”;
    • echo ${name:1:4} #输出 his
    • echo ${name::4} #输出 this

    数组

    bash只支持一维数组,不支持多维数组

    • 定义数组:array_name=(li wang xiang zhang) (小括号做边界、使用空格分离)
    • 单独定义数组的元素: array_para[0]=“w”; array_para[3]=“s” (定义时下标不连续也可以)
    • 赋值数组元素:array_name[0]=“zhao”;
    • 获取数组元素:
      • array_name[0]=“li”
      • array_name[3]=“zhang”
      • echo ${array_name[0]} # 输出"li"
      • echo ${array_name[1]} # 输出" "
      • echo ${array_name[3]} # 输出"zhang"
      • echo ${array_name[@]} # 输出"li zhang" 输出数组所有元素,没有元素的下标省略
    • 取得元素个数:${#array_name[@]} 或者 ${#array_name[*]}
    • 取得单个元素长度:${#array_name[1]}

    参数传递

    • 获取参数值:
      • $0 : 固定,代表执行的文件名
      • $1 : 代表传入的第1个参数
      • $n : 代表传入的第n个参数
    • $#:参数个数
    • $*: 以一个单字符串显示所有向脚本传递的参数。如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数
    • $@:与$*相同,但是使用时加引号,并在引号中返回每个参数。
    • $$:脚本运行的当前进程号
    • $!:后台运行的最后一个进程的ID
    • $?: 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
    • $* 与 $@ 区别
      • 相同点:都是引用所有参数。
      • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。

    运算符

    算数运算

    • + 、-、*、\ : 乘号前必须加\进行转义才可以进行乘法运算
    • 加法运算
      • val=`expr 2 + 2` (使用linux命令expr进行辅助运算)
      • val=$[2+2] (4个空格不是必要的,不同于条件判断)
      • val=$((2+2))

    数字关系运算符
    关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
    下面假定变量 a 为 10,变量 b 为 20

    • -eq :检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
    • -ne: 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
    • -gt: 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
    • -lt : 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
    • -ge: 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
    • -le : 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

    字符串运算符
    下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:

    • = :检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
    • != :检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
    • -z :检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
    • -n :检测字符串长度是否为0,不为0返回 true。 [ -n “$a” ] 返回 true。
    • $ :检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

    布尔运算符
    下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

    • ! :非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
    • -o :或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
    • -a :与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

    逻辑运算符
    以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

    • && :逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
    • || :逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

    文件运算符

    • -b file :检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
    • -c file :检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
    • -d file :检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
    • -f file :检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
    • -g file :检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
    • -k file :检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
    • -p file :检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
    • -u file :检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
    • -r file :检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
    • -w file :检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
    • -x file :检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
    • -s file :检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
    • -e file :检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

    执行相关

    命令替换
    命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
    执行命令:

    1. `ls /etc` : 反引号 (所有的unix系统都支持)
    2. $(ls /etc) : $+() (部分unix系统不支持)
      多个嵌套使用时,从内向外执行

    for file in \s /etc\ 或 for file in $(ls /etc) 循环中使用
    `dirname $0` 获取脚本文件所在的目录
    path=$(cd `dirname $0`;pwd) : 获取脚本当前所在目录,并且执行cd命令到达该目录,使用pwd获取路径并赋值到path变量

    算术运算

    1. $[ ] : 加减乘除,不必添加空格
    2. $(( )) :加减乘除等,不必添加空格

    逻辑判断

    1. [ ] : 中括号旁边和运算符两边必须添加空格 (可以使用,不推荐)
    2. [[ ]]:中括号旁边和运算符两边必须添加空格 (字符串验证时,推荐使用)
    3. (()) : 中括号旁边和运算符两边必须添加空格 (数字验证时,推荐使用)
    4. [[]] 和 (()) 分别是[ ]的针对数学比较表达式和字符串表达式的加强版。
    5. 使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
      [[ ]]中增加模式匹配特效;
      (( ))不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了以下符号
      在这里插入图片描述

    输出

    echo
    仅用于字符串的输出,没有使用printf作为输出的移植性好,建议使用printf

    printf

    printf 不会像 echo 自动添加换行符,我们可以手动添加 \n
    无大括号,直接以空格分隔

    • 格式:printf format-string [arguments...] 其中(format-string: 格式控制字符串、arguments: 参数列表)
    • 案例:printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
    • %s %c %d %f 都是格式替代符
      • d:Decimal 十进制整数 对应位置参数必须是十进制整数,否则报错!
      • s:String 字符串 对应位置参数必须是字符串或者字符型 否则报错
      • c:Char 字符 对应位置参数必须是字符串或者字符型 否则报错
      • f:Float 浮点 对应位置参数必须是数字型 否则报错
    • %-10s : 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
    • %-4.2f :指格式化为小数,宽度为4个字符,其中.2指保留2位小数。
    • 转义符:
      • \a :警告字符,通常为ASCII的BEL字符
      • \b :后退
      • \c :抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
      • \f :换页(formfeed)
      • \n :换行
      • \r :回车(Carriage return)
      • \t :水平制表符
      • \v :垂直制表符
      • \ :一个字面上的反斜杠字符
      • \ddd :表示1到3位数八进制值的字符。仅在格式字符串中有效
      • \0ddd :表示1到3位的八进制值字符

    流程控制

    和Java、PHP等语言不一样,sh的流程控制不可为空,即if或者else的大括号中无任何语句
    if else

    • if
    if condition
    then
        command1 
        command2
        ...
        commandN 
    fi
    
    • if else
    if condition
    then
        command1 
        command2
        ...
        commandN
    else
        command
    fi
    
    • if else-if else
    if condition1
    then
        command1
    elif condition2 
    then 
        command2
    else
        commandN
    fi
    

    for

    for var in item1 item2 ... itemN
    do
        command1
        command2
        ...
        commandN
    done
    

    while

    • while condition
    while condition
    do
        command
    done
    
    • while 无限循环
    while :
    do
        command
    done
    

    until
    until 循环执行一系列命令直至条件为 true 时停止。
    until 循环与 while 循环在处理方式上刚好相反。

    until condition
    do
        command
    done
    

    case
    Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
    case需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break,其中“;;”不是跳出循环,是不在去匹配下面的模式
    case语句格式如下:

    casein
      模式1)
        command1
        command2
        ...
        commandN
        ;;
      模式2)
        command1
        command2
        ...
        commandN
        ;;
    esac
    

    跳出循环

    1. break :跳出总循环
    2. continue:跳出当前循环,继续下一次循环

    定义函数

    可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。

    • 函数定义
    [ function ] funname()
    {
        action;
        [return int;]
    }
    
    • 参数传递
      • 调用函数: fun_name 2 3 4
      • 函数中使用:和shell取用函数相同 $n $# $* $? 或者加上{}
    funWithParam(){
        echo "第一个参数为 $1 !"
        echo "第二个参数为 $2 !"
        echo "第十个参数为 $10 !"
        echo "第十个参数为 ${10} !"
        echo "第十一个参数为 ${11} !"
        echo "参数总数有 $# 个!"
        echo "作为一个字符串输出所有参数 $* !"}
    funWithParam 1 2 3 4 5 6 7 8 9 34 73
    echo $?  \# 判断执行是否成功
    
    • 函数返回值
      • return字样可存在也可不存在
      • return 只能为 return [0-255],此处的返回可作为函数执行的状态,通过$?获取的便是这个返回值
      • 如果不加return , 则默认最后一条语句的执行状态所为函数执行状态的返回值,如果最后一条语句执行成功,则$?为0,否则不为0
    • 使用函数返回值(Janusgraph图数据库官方启动服务脚本片段)
      • return返回的数字,只是作为函数执行状态的返回值,也就是接下来$?获取的值
      • 对于类似于下面的BIN=\abs_path``语句,获取的是函数体内所有的echo、printf输出组合成的一个字符串
    abs_path() {
        SOURCE="${BASH_SOURCE[0]}"
        while [ -h "$SOURCE" ]; do
            DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
            SOURCE="$(readlink "$SOURCE")"
            [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
        done
        echo "test"  
        echo "$( cd -P "$( dirname "$SOURCE" )" && pwd )"  
        # 此函数的两个echo输出会组合成一个字符串作为下述BIN的值
    }
    
    BIN=`abs_path` # BIN赋值函数返回值,如果没有return,则函数中所有的echo、printf输出组合成一个字符串传入BIN
    path=${BIN}/nodetool # 可直接使用
    

    输入输出重定向

    一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

    • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
    • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
    • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

    默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
    如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

    输入重定向

    1. bash.sh < file : 将脚本的输入重定向到file,由file提供参数

    输出重定向

    1. bash.sh > file : 将脚本的输出数据重定向到file中,覆盖数据
    2. bash.sh >> file : 将脚本的输出数据重定向到file中,追加数据
    3. command >> file 2>&1 : 将 stdout 和 stderr 合并后重定向到 file

    读取外部输入

    命令:read arg (脚本读取外部输入并赋值到变量上)
    在shell脚本执行到上述命令时,停止脚本执行并等待外部输入,将外部输入赋值到arg变量上,继续执行脚本

    文件引用

    引用其他的文件之后,可以使用其变量、函数等等,相当于将引用的文件包含进了当前文件
    两种方式:

    1. . file_path\file_name
    2. source file_path\file_name

    颜色标识

    printf  "\033[32m SUCCESS: yay \033[0m\n";
    printf  "\033[33m WARNING: hmm \033[0m\n";
    printf  "\033[31m ERROR: fubar \033[0m\n";
    

    输出结果:
    在这里插入图片描述

    长句换行

    在shell中为避免一个语句过长,可以使用“\”进行换行
    使用“\”换行,在脚本执行过程中还是当做一行一个语句执行,不同于enter直接换行

    注意:\ 前添加一个空格 。 \ 后无空格直接换行。

     /mysql/bin/mysql \
      -h test_host  -P 000 \
      -u test_user -ptest_password ;
    

    shell操作mysql

    下面案例为登录mysql,并选择操作数据库,之后进行导入数据

     /mysql/mysql/bin/mysql \
      -h test_host  -P 000 \
      -u test_user -ptest_password \
      -e"use test_database; source data_faile; " # -e 代表执行sql语句
    

    -u 用户名
    -p 用户密码
    -h 服务器ip地址
    -D 连接的数据库
    -N 不输出列信息
    -B 使用tab键 代替 分隔符
    -e 执行的SQL语句

    退出脚本

    命令:exit

    在退出脚本时使用不同的错误码,这样可以根据错误码来判断发生了什么错误。

    在绝大多数 shell 脚本中,exit 0 表示执行成功,exit 1 表示发生错误。
    对错误与错误码进行一对一的映射,这样有助于脚本调试。

    命令:set -e 或者 set +e
    set -e表示从当前位置开始,如果出现任何错误都将触发exit。相反,set +e表示不管出现任何错误继续执行脚本。

    如果脚本是有状态的(每个后续步骤都依赖前一个步骤),那么请使用set -e,在脚本出现错误时立即退出脚本。
    如果要求所有命令都要执行完(很少会这样),那么就使用set +e。

    shell脚本调试

    检查是否有语法错误-n
    bash -n script_name.sh
    使用下面的命令来执行并调试 Shell 脚本-x
    bash -x script_name.sh
    调试count_odd_number.sh 程序案例:

    #!/usr/bin.env bash
    
    # 用于计算数组中奇数的和
    # @author liyangyang
    # @time 2019/09/17
    
    sum=0
    for num in 1 2 3 4;do
        re=${num}%2
        if (( ${re} == 1 ));then
            sum=$[${sum}+${num}]
        fi
    done
    echo ${sum}
    
    1. 首先检查有无语法错误:
      bash -n count_odd_number.sh
    2. 没有输出,说明没有错误,开始实际调试:
      bash -x count_odd_number.sh
    3. 调试结果如下:
    + sum=0
    + for num in 1 2 3 4
    + re=1%2
    + ((  1%2 == 1  ))
    + sum=1
    + for num in 1 2 3 4
    + re=2%2
    + ((  2%2 == 1  ))
    + for num in 1 2 3 4
    + re=3%2
    + ((  3%2 == 1  ))
    + sum=4
    + for num in 1 2 3 4
    + re=4%2
    + ((  4%2 == 1  ))
    + echo 4
    4
    

    其中的输出显示了程序执行的每一步,通过观察程序执行的步骤是否满足预期从而达到调试的效果
    带有 + 表示的是 Shell 调试器的输出,不带 + 表示程序的输出。

    案例:

    这是es(ElasticSearch)官方启动服务的脚本,看可不可以理解吧~

    #!/usr/bin/env bash
    
    # CONTROLLING STARTUP:
    #
    # This script relies on a few environment variables to determine startup
    # behavior, those variables are:
    #
    #   ES_PATH_CONF -- Path to config directory
    #   ES_JAVA_OPTS -- External Java Opts on top of the defaults set
    #
    # Optionally, exact memory values can be set using the `ES_JAVA_OPTS`. Note that
    # the Xms and Xmx lines in the JVM options file must be commented out. Example
    # values are "512m", and "10g".
    #
    #   ES_JAVA_OPTS="-Xms8g -Xmx8g" ./bin/elasticsearch
    
    source "`dirname "$0"`"/elasticsearch-env
    
    parse_jvm_options() {
      if [ -f "$1" ]; then
        echo "`grep "^-" "$1" | tr '\n' ' '`"
      fi
    }
    
    ES_JVM_OPTIONS="$ES_PATH_CONF"/jvm.options
    
    ES_JAVA_OPTS="`parse_jvm_options "$ES_JVM_OPTIONS"` $ES_JAVA_OPTS"
    
    # manual parsing to find out, if process should be detached
    if ! echo $* | grep -E '(^-d |-d$| -d |--daemonize$|--daemonize )' > /dev/null; then
      exec \
        "$JAVA" \
        $ES_JAVA_OPTS \
        -Des.path.home="$ES_HOME" \
        -Des.path.conf="$ES_PATH_CONF" \
        -cp "$ES_CLASSPATH" \
        org.elasticsearch.bootstrap.Elasticsearch \
        "$@"
    else
      exec \
        "$JAVA" \
        $ES_JAVA_OPTS \
        -Des.path.home="$ES_HOME" \
        -Des.path.conf="$ES_PATH_CONF" \
        -cp "$ES_CLASSPATH" \
        org.elasticsearch.bootstrap.Elasticsearch \
        "$@" \
        <&- &
      retval=$?
      pid=$!
      [ $retval -eq 0 ] || exit $retval
      if [ ! -z "$ES_STARTUP_SLEEP_TIME" ]; then
        sleep $ES_STARTUP_SLEEP_TIME
      fi
      if ! ps -p $pid > /dev/null ; then
        exit 1
      fi
      exit 0
    fi
    
    exit $?
    

    推荐阅读:
    Git-【技术干货】工作中Git的使用实践
    Git - 使用git不知道内部实现机制怎么行

    如果转载此博文,请附上本文链接,谢谢合作~ :https://blog.csdn.net/CSDN___LYY/article/details/100584638

    如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!谢谢大家~

    在这里插入图片描述

    展开全文
  • 如何用python写游戏脚本

    千次阅读 2020-08-17 13:43:08
    前言 最近在玩儿公主连结,之前也玩儿过阴阳师这样的游戏,这样的游戏都会有个初始号这样的东西,或者说是可以肝的东西。 很多人学习python,不知道从何学起。 很多人学习python,掌握...游戏脚本其实并不高深,最简

    前言

    最近在玩儿公主连结,之前也玩儿过阴阳师这样的游戏,这样的游戏都会有个初始号这样的东西,或者说是可以肝的东西。

    很多人学习python,不知道从何学起。
    很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
    很多已经做案例的人,却不知道如何去学习更加高深的知识。
    那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
    QQ群:101677771

    当然,作为一名程序员,肝这种东西完全可以用写代码的方式帮我们自动完成。游戏脚本其实并不高深,最简单的体验方法就是下载一个Airtest了,直接截几个图片,写几层代码,就可以按照自己的逻辑玩儿游戏了。

    当然,本篇文章不是要讲Airtest这个怎么用,而是用原始的python+opencv来实现上面的操作。

    这两天我写了一个公主连结刷初始号的程序,也不能算写游戏脚本的老手,这篇文章主要是分享一些基础的技术和使用上的心得吧。

    准备工作

    首先,我们要完成以下准备。

    • 安卓设备 一个:模拟器或者真机都可以。
    • 安装 ADB ,并添加到系统的 PATH 里:adb是用来
    • 安装 tesseract-ocr ,并添加到系统的 PATH 里:帮助我们实现简单的字符识别
    • 安装 python3.7 以上的版本

    这里adb和tesseract我放在百度网盘里了,里面顺便放了一个录制的效果视频。

    链接: pan.baidu.com/s/1edTPu2o7… 提取码:33aw

    python库安装

    pip install pillow pytesseract opencv-python
    复制代码

    除此以外,如果有需要可以安装 uiautomator2 ,这篇文章就不涉及这块知识了。

    使用 adb 获取安卓设备

    这里我们主要是涉及到单个安卓设备的ADB连接操作,首先我们打开模拟器。

    然后我们调用 adb devices 来获取当前的安卓设备,我这里是一个模拟器。

    接下来可以调用 adb shell 测试一下是否能进入到安卓设备的shell环境下,确认可以输入 exit 退出即可。

    如果有的时候进不了shell,可以先调用一下 adb kill-server ,然后再调用 adb devices 。

    可能常用的ADB Shell命令

    接下来是一些ADB的命令操作。通过adb命令,我们可以用python来操作的安卓设备。

    屏幕截图

    最常见的操作就是截图了,先调用 screencap 截图放到安卓设备里,然后再把截图下拉到电脑。

    def take_screenshot():
        os.system("adb shell screencap -p /data/screenshot.png")
        os.system("adb pull /data/screenshot.png ./tmp.png")
    复制代码

    下拉文件

    下拉文件就是刚刚那个 adb pull 了,以公主连结为例,以下代码可以导出账号信息的xml,以后通过xml就可以登录了。

    os.system(f"adb pull /data/data/tw.sonet.princessconnect/shared_prefs/tw.sonet.princessconnect.v2.playerprefs.xml ./user_info.xml")
    复制代码

    上传文件

    有了下拉自然就有上传了,通过 adb push 即可完成。以公主连结为例,以下代码可以完成账号的切换。

    # 切换账号1
    os.system("adb push ./user_info1.xml /data/data/tw.sonet.princessconnect/shared_prefs/tw.sonet.princessconnect.v2.playerprefs.xml")
    
    # 切换账号2
    os.system("adb push ./user_info2.xml /data/data/tw.sonet.princessconnect/shared_prefs/tw.sonet.princessconnect.v2.playerprefs.xml")
    复制代码

    点击屏幕某个位置

    def adb_click(center, offset=(0, 0)):
        (x, y) = center
        x += offset[0]
        y += offset[1]
        os.system(f"adb shell input tap {x} {y}")
    复制代码

    输入文字

    text = "YourPassword"
    os.system(f"adb shell input text {text}")
    复制代码

    删除字符

    有的时候输入框会有输入的缓存,我们需要删除字符。

    # 删除10个字符
    for i in range(10):
        os.system("adb shell input keyevent 67")
    复制代码

    查询当前运行的包名和Activity

    通过以下代码,可以查询当前运行的程序的Activity,也可以顺便查包名。

    adb shell dumpsys activity activities
    复制代码

    停止某个应用

    有时候会需要停止某个应用,需要提供应用的包名。

    adb shell am force-stop tw.sonet.princessconnect
    复制代码

    开启某个应用

    开启某个应用需要提供包名以及Activity。

    adb shell am start -W -n tw.sonet.princessconnect/jp.co.cygames.activity.OverrideUnityActivity
    复制代码

    图像操作

    对于图像的操作第一就是图像查找了,比如说像Airtest提供的这种,无非就是判断某个图像在不在截屏中,在的话在什么位置。

    除此之外还需要一些抠图,比如说我们想获取 账号的id , 账号的等级 ,需要截取出一部分图片然后进行OCR操作。

    图像查找

    图像查找其实就是先拿到两张图片,然后调用 cv2.matchTemplate 方法来查找是否存在以及位置,这里匹配是一个相对模糊的匹配,会有一个相似度的概率,最高是1。我们设定一个阈值来判断模板是否在截屏里即可。

    这里截屏如下,文件名为 tmp.png :

    模板如下:

    代码如下:

    import cv2
    
    def image_to_position(screen, template):
        image_x, image_y = template.shape[:2]
        result = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
        print("prob:", max_val)
        if max_val > 0.98:
            global center
            center = (max_loc[0] + image_y / 2, max_loc[1] + image_x / 2)
            return center
        else:
            return False
    
    if __name__ == "__main__":
        screen = cv2.imread('tmp.png')
        template =  cv2.imread('Xuandan.png')
        print(image_to_position(screen, template))
    复制代码

    运行上述代码后,可以看到模板匹配出来的概率为 0.9977 ,位置为(1165, 693),对于一张图片,左上角为原点,因为我的分辨率是1280 * 720,那么右下角的坐标就是(1280, 720)。可以看到我们这个选单其实就是刚好在右下角的位置。

     

    如何快速裁剪模板?(win10)

    游戏脚本其实并不是代码很难写,而是需要截很多的图,这些图要保证分辨率和原始一样。我发现在win10如果用画图打开图片

    可以保证使用QQ截屏出来的分辨率,和图片本身的分辨率一样。

    这个时候直接用qq截屏出来的模板即可直接用于识别。

    图像裁剪

    接下来就是有时候需要裁剪一些图像了,当然我们的模板图片也可以通过裁剪图片的方式得到,这样的模板图片是最准的。

    裁剪其实就是需要裁剪的位置,以及需要的高度和宽度,说白了就是一篇长方形的区域,下面的代码使用PIL库实现。

    from PIL import Image
    
    def crop_screenshot(img_file, pos_x, pos_y, width, height, out_file):
        img = Image.open(img_file)
        region = (pos_x, pos_y, pos_x + width, pos_y + height)
        cropImg = img.crop(region)
        cropImg.save(out_file)
        print("exported:", out_file)
    
    if __name__ == "__main__":
        crop_screenshot("tmp.png", 817,556, 190, 24, "test_id.png")
    
    复制代码

    上面的代码以截取玩家的id为例。

    运行代码后,得到截图如下:

    简单的OCR

    得到了以上的图片信息后就是进行OCR了,也就是光学字符识别。这里代码非常简单,只要调用API即可。

    from PIL import Image
    import pytesseract
    
    image = Image.open('test_id.png')
    content = pytesseract.image_to_string(image)   # 识别图片
    print(content)
    
    复制代码

    不过需要注意的一点就是pytesseract识别出来的结果会有空格符,换行符这样的符号,真正要用的时候进行一些字符的过滤即可。

    The End

    这篇文章到这里就结束了,主要还是介绍一些ADB以及图像相关的基础操作,有些内容比如说多开和uiautomator2因为我暂时没用到所以就没写,百度一下应该也不是很难。代码写的比较丑还没完善好,就先不放了。

    展开全文
  • 用Shell游戏客户端更新脚本

    千次阅读 2012-02-28 23:10:17
    因此应测试要求,了个脚本, 每次只检出更新部分。其实只是利用了svn的update命令。 脚本实现功能: 1、如果首次使用该脚本,在制定目录中创建一个用于保存版本的文件。然后检出项目。 2、如果不是首次...

    之前我们更新客户端的方法是,一个脚本,把svn的客户端版本检出来。但是每次都重复检出。

    由于现在客户端已经有800+M,每次检出基本都需要等待5分钟左右。因此应测试要求,写了个脚本,

    每次只检出更新部分。其实只是利用了svn的update命令。


    脚本实现功能:

    1、如果首次使用该脚本,在制定目录中创建一个用于保存版本的文件。然后检出项目。

    2、如果不是首次使用,那么更新步骤1检出的项目。然后修改步骤1的版本号(递增),将版本号写入加载flash的jsp配置中。

    其中还涉及一些对额外情况的处理,比如如果检出的目标位置已经存在同名文件,那么打包备份这个文件,然后再继续执行正常操作等细微逻辑。


    刚看Shell不久,也只是利用零散时间看的。写的不好,欢迎提出。


    #!/bin/sh
    
    ##########################################
    # 客户端版本更新系统
    ##########################################
    
    
    # CLIENT_INIT_VERSION 客户端新版本,默认是0
    # CLIENT_OLD_VERSION  客户端旧版本(存放在VERSION_FILE指定的文件中),当没有时取CLIENT_INIT_VERSION
    # CLIENT_NEW_VERSION  客户端新版本,默认是CLIENT_OLD_VERSION+1
    # VERSION_FILE        存放上次版本的文件
    CLIENT_INIT_VERSION='0'
    CLIENT_OLD_VERSION='0'
    CLIENT_NEW_VERSION=''
    VERSION_FILE='client_version.txt'
    
    # CLIENT_BASE_PATH    放置前端的目录
    # VERSION_CONFIG_FILE 服务器前端版本配置文件
    # SVN_PATH            前端SVN地址
    CLIENT_BASE_PATH='/data/ylzj_test/img/'
    VERSION_CONFIG_FILE='/data/ylzj_test/sljweb/version.jsp'
    SVN_PATH='http://192.168.14.138:8080/svn/slj_release/ylzj'
    
    CLIENT_NEW_PATH=''
    CLIENT_OLD_PATH=''
    
    #更新是否成功
    IF_SUCC=''
    
    initVersionFileIfNoExist(){
        if [ -f $VERSION_FILE ];then
            echo '[INFO] Welcome to use Client Update System.'
        else
            echo '[INFO] Welcome to use Client Update System.'
            echo $CLIENT_INIT_VERSION > $VERSION_FILE
            if [ -f $VERSION_FILE ];then
                echo '[SUCC] CREATE VERSION FILE '$VERSION_FILE
            else
                echo '[FAIL] CREATE VERSION FILE '$VERSION_FILE
            fi
        fi
    }
    
    initClientNewVersion(){
        CLIENT_OLD_VERSION=$(cat $VERSION_FILE)
        echo "[INFO] The old client version is : "$CLIENT_OLD_VERSION
        CLIENT_NEW_VERSION=$(expr $(cat $VERSION_FILE) + 1)
        echo '[INFO] The new client version is : '$CLIENT_NEW_VERSION
        CLIENT_NEW_PATH=$CLIENT_BASE_PATH$CLIENT_NEW_VERSION
        CLIENT_OLD_PATH=$CLIENT_BASE_PATH$CLIENT_OLD_VERSION
    }
    
    checkIfFileExistAndDoSomething(){
            tmpvar=$1
            subpath=${tmpvar%/*}
            existFile=${tmpvar##*/}
            TMP_BACKUP_FLASH_TAR=''
                    if [ -f $1 -o -d $1 ];then
                            echo '[WARN] Flash dir '$1' has exists, it will be tar and backup.'
                            TMP_BACKUP_FLASH_TAR=$existFile'.tar'
                cd $subpath
                            echo '[INFO] Archieving '$existFile' to '$TMP_BACKUP_FLASH_TAR
                            tar -zcvf $TMP_BACKUP_FLASH_TAR $existFile
                            echo '[INFO] Removing dir '$existFile
                            rm -rf $existFile
                cd -
                    fi
            unset tmpvar
            unset subpath
            unset existFile
                    unset TMP_BACKUP_FLASH_TAR
    }
    
    prepareClientDir(){
        checkIfFileExistAndDoSomething $CLIENT_NEW_PATH
        if [ $CLIENT_INIT_VERSION -eq $CLIENT_OLD_VERSION ];then
            #第一次使用
            #创建目录
            echo '[INFO] First create the flash dir '$CLIENT_NEW_PATH
            mkdir -p $CLIENT_NEW_PATH
        else
            #非第一次使用,修改flash名字
            echo '[INFO] Copying '$CLIENT_OLD_PATH' to '$CLIENT_NEW_PATH
            mv $CLIENT_OLD_PATH $CLIENT_NEW_PATH
        fi
        if [ -d $CLIENT_NEW_PATH ];then
            IF_SUCC='TRUE'
        fi
    }
    
    storeThisVersionIfSucc(){
        if [ -n $IF_SUCC ]; then
            echo $CLIENT_NEW_VERSION > $VERSION_FILE
            echo "<%String version = \"$CLIENT_NEW_VERSION\";%>" > $VERSION_CONFIG_FILE
        fi
    }
    
    createClient(){
        echo '[INFO] Checking out flash version...'
        svn co $SVN_PATH $CLIENT_NEW_PATH --username=bqli --password=123456
        echo '[INFO] Checking out has finished.'
    }
    
    updateClient(){
        echo '[INFO] Updating flash version...'
        svn update $CLIENT_NEW_PATH
        echo '[INFO] Updating has finished.'
    }
    
    createOrUpdateClient(){
        if [ $CLIENT_INIT_VERSION -eq $CLIENT_OLD_VERSION ];then
            createClient
        else
            updateClient
        fi
    }
    
    echoStartInfo(){
        echo '#################################################'
        echo '# 欢迎使用客户端版本更新系统V1.0'
        echo '#################################################'
    }
    
    echoEndInfo(){
        echo '[SUCC] Finished.'
    }
    
    clear
    echoStartInfo
    initVersionFileIfNoExist
    initClientNewVersion
    prepareClientDir
    createOrUpdateClient
    storeThisVersionIfSucc
    echoEndInfo


    展开全文
  • 这篇文章MOMO主要想大家说明一下我在Unity3D游戏开发中是如何写游戏脚本的,...这篇文章的目的是哪些已经上手Unity3D游戏引擎的朋友学会如何更好的写游戏脚本,当然本文这紧紧是我这么多年对游戏开发的认知,你
  • 脚本游戏2048

    2018-07-31 20:31:06
    大神的2048小游戏,很适合程序员用来装逼(咳咳,研究)
  • 用Python一个游戏脚本,你会吗?

    千次阅读 2020-05-06 15:12:30
    听说pywin32写脚本还不错 pywin32主要代码 我以楚留香的电脑版为例,记录脚本的编写之路吧。 因为主要游戏都在windows跑,没什么好说的,第一步应该是获取窗口句柄。 在按键精灵帮助下,我们知道了游戏窗口句柄的...
  • 游戏架构脚本该如何来

    千次阅读 2015-07-29 18:00:06
    这篇文章的目的是哪些已经上手Unity3D游戏引擎的朋友学会如何更好的写游戏脚本,当然本文这紧紧是我这么多年对游戏开发的认知,你也可以有你自己的看法。首先我们看看游戏主要是由哪几部分组成的,如下图所示,...
  • 游戏脚本其实并不高深,最简单的体验方法就是下载一个Airtest了,直接截几个图片,几层代码,就可以按照自己的逻辑玩儿游戏了。当然,本篇文章不是要讲Airtest这个怎么用,而是用原始的python+opencv来实...
  • 游戏脚本源码

    2019-05-16 18:11:27
    这个源码跟大模一样 非常好用 可以直接编译为dll 接口文件方便易语言调用
  • 开始着手用Python一个游戏脚本(一)

    万次阅读 多人点赞 2019-06-04 15:26:04
    学习python有一段时间了,由于python语言的强大和简洁,是一个不错的脚本语言,就准备做个游戏脚本练练手。 这次以热门手游楚留香作为练手的目标啦
  • 安卓游戏脚本 - 叉叉助手

    万次阅读 2017-08-20 23:19:05
    打开电脑编译器 选择运行 会你输入 一个地址 注意 和安卓编译器在同一个局域网 输入安卓编译器的地址 选择链接 链接成功即可 开发手机软件 下面有一个我录制的小视频  链接:http://pan.baidu.com
  • 该程序是基于07年底的一个J2ME小游戏 俄罗斯方块,将全部逻辑绘制都放到LUA脚本里来做,J2ME方面仅作一个绘制库来使用!
  • 用已掌握的知识已经用"autopy"的功能了一个鼠标自动点击排队的脚本,但是我想这个脚本不用在窗口最前端显示也能运行,就是最小化了也能继续在后台继续工作,可是不了解Python的强大功能,下面是代码,有些是在...
  • js连连看是javascript的一个小游戏,此文件提供了javascript源码,可供下载者自行修改,有想学习javascript的可以参考一下
  • FreeSwitch 用Lua脚本写个小游戏

    千次阅读 2019-03-17 23:25:40
    编写一个特别简单脑残的小游戏,算是记录一下在FreeSwitch通话时,如何记录用户的按键信息的一个小例子。 2. 效果展示 用户连接FreeSwitch并拨打 1236 后,接通后可以听到背景音乐,然后按键,可以在FreeSwitch...
  • 下面飞云脚本圈子(http://www.feiyunjs.com)把自己所知道的脚本开发语言列举一下。 如果有遗留,欢迎在文章下方评论留言。 按键精灵(手机版) 按键精灵采用MQ语言,MQ是按键精灵针对旗下移动产品而设计的全新脚本...
  • 新手写脚本注意

    千次阅读 2011-12-01 15:55:35
    新人写脚本一定要注意许多地方,否则会出现外挂就可以刷装备的问题出现了 脚本一开始的[@main]是一个主题,脚本一开始运行的时候首先进行读取的就是这个 一般格式如下 [@main] #if ;#if是检查的意思 checkgold...
  • 那么这周我就篇文章从游戏脚本聊起,分析一下游戏脚本因何出现,而Mono又能提供怎样的脚本基础。最后会通过模拟Unity3D游戏引擎中的脚本功能,将Mono运行时嵌入到一个非托管(C/C++)程序中,实现脚本语言和“引擎...
  • 用shell脚本写一个猜数游戏 最近用shell的一个猜数游戏,包括4个不同难度,脚本如下: #作者:p_小王 echo '欢迎来到猜数游戏!' while true do read -p '开始/退出(y/n):' x #提示用户输入 if [ -z $x ] #...
  • dnf游戏脚本

    2012-04-19 12:34:00
    自己写的一些脚本,有召唤自动刷祭坛、死亡迷惘。自动招怪、后台邮件、自动分解等。绝对无毒,大家可以看源码:http://www.doc88.com/p-173100005968.html
  • Unity3D 游戏架构脚本该如何来

    千次阅读 2015-07-16 10:18:46
    这篇文章的目的是哪些已经上手Unity3D游戏引擎的朋友学会如何更好的写游戏脚本,当然本文这紧紧是我这么多年对游戏开发的认知,你也可以有你自己的看法。首先我们看看游戏主要是由哪几部分组成的,如下图所示,...
  • 使用 C# 写脚本的优势和方法

    千次阅读 2020-05-04 16:02:01
    现在是 2020 现在的 C# 默认在 dotnet 的支持下,可以作为脚本使用,本文将告诉大家使用 C# 写脚本的优势和方法 优势 优势如下: 基于 dotnet 的 C# 有整个 dotnet 的基础库和通过 NuGet 带来的海量的第三方库,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 83,886
精华内容 33,554
关键字:

如何写脚本让游戏自己