铁血丹心

 找回密码
 我要成为铁血侠客
搜索
查看: 578|回复: 3

[分享] 群侠集结安卓版启动器发布

[复制链接]
 楼主| 发表于 2025-7-5 10:20 | 显示全部楼层 |阅读模式

马上注册,结交更多侠友!

您需要 登录 才可以下载或查看,没有账号?我要成为铁血侠客

x
本帖最后由 lsl330 于 2025-7-10 20:26 编辑

整理了一下逐梦的底层,制作了一款安卓启动器(胡乱想了个名字,顾且叫群侠集结,图标还没来得及换,还是逐梦的图标,以后再换吧)。

百度下载地址

链接: https://pan.baidu.com/s/1ig72NiwgVtRVLHlTfTdgYQ?pwd=qe6d



演示地址:
https://www.bilibili.com/video/BV1un33zZEFC/#reply114789510546645

算是兑现了一下对自己的承诺。
虽然逐梦是闭源的,但也想为金群mod做一份贡献,后续会发布对应的windows和linux启动文件

有制作者有兴趣适配可以联系我(金书群侠传已做了基础适配,是否发布看老顾吧)

2025.7.10fix
修复一个lib.CharSet配置与老API相反的bug。重新下载即可

2025.7.9更新1.0.0版本
更新内容
1、添加可视化配置界面。需制作者自行在数据包根目录编写config.UI文件
2、添加存档下载和分享功能,存档导入功能(下载会自动下载到download文件夹)
备注:存档下载和导入功能,需要各数据包固定存档位置和存档名称
存档需放在根目录的save文件夹,以Save_%d.sav命名(%d的值为1-10)。
上述两项功能长按游戏封面,呼出菜单选择即可
3、将游戏画面与虚拟按钮绘制逻辑分离。虚拟按钮固定现实在屏幕的指定位置。不再受游戏画面的影响





【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2025-7-5 10:45 | 显示全部楼层
本帖最后由 lsl330 于 2025-7-10 08:49 编辑

Q:数据包支持的压缩包格式
A:数据包支持zip和tar.zst。若你的数据包中有中文文件名,建议使用后者(可以用peazip压缩)

Q:数据包有命名规则么
A:数据包有两种命名格式,name1-name2.zip(tar.zst)或name1-name2-name3.zip(tar.zst)
前者为本体模式,会在沙箱目录新建name2文件夹并导入(若已有name2文件夹,则不能导入)
后者为补丁模式,若沙箱目录中已有name2文件夹,则将内容导入并覆盖到name2文件夹中(若没有name2文件夹,则不能导入),name3本身无意义,仅作为是否补丁判定之用
name1为启动器中显示的名称,建议设置成中文

Q:上传的数据包如何显示封面
A:数据包根目录将cover.jpg打包进去本体数据包,导入即可看到封面

Q:info.txt是什么,如何填写
A:info.txt可以将游戏的基础信息告诉启动器,info.txt格式如下
[制作者]=河洛工作室
[游戏简介]=永恒的经典/n金庸群侠传
[LUA]=LUA54
游戏简介支持使用/n做分行显示,启动器支持多引擎启动,[LUA]=LUA54(可选LUA52和LUA53),必须填写正确

Q:我想打开启动器直接运行游戏,可以么?
A:本启动器支持默认启动设置,在游戏运行中,从最左侧向右滑,可弹出侧滑菜单,选择设置为默认启动,以后启动即可自动运行。取消默认启动可以以同样方式在侧滑菜单中取消(上述功能需授权悬浮窗权限)

Q:如何制作数据包
A:LUA版本应该要做部分改动才能完美支持该启动器。理论上来说,底层越新,迁移越容易。制作者有兴趣可联系门客,后续或许也会写一个适配指南。

Q:本启动器有何特色
A:简单来说,就是尽可能简单的提供多平台支持,可以用同一份数据包,实现win,android,linux的游戏运行,同时提供完全一致的游戏体验(win和linux的启动文件有空再发布吧)
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2025-7-9 15:40 | 显示全部楼层
本帖最后由 lsl330 于 2025-7-9 15:42 编辑


path=config.lua
prefix=CONFIG.
encode=GBK
[Spinner=缩放方式]ScreenZoomMode=[0="拉伸",1="比例",2="特殊"]
[SeekBar=缩放比例]Zoom=[100-200]
[SeekBar=音量大小]MusicVolume=[0-128]
[SeekBar=音效大小]SoundVolume=[0-128]
[SeekBar=按键透明度]ButtonAlpha=[0-255]
[SeekBar=首步延迟]WalkSkip=[100-500]
[Switch=游戏录像]Replay=[0=false,1=true]
[Switch=自动确认]AutoConfirm=[0=false,1=true]
[TextBox=游戏宽度]ScreenW
[TextBox=主角姓名]PlayName[string]


以下是格式讲解
path为配置文件所在位置。若在根目录config.lua则填config.lua,若在script目录,则填script/config.lua。实际上,启动器仅支持从这两个位置加载配置文件
encode为文本编码,需根据LUA对应的编码填写,可填写的值为GBK、BIG5、UTF-8。若不填写,默认为UTF-8
prefix为前缀,若添加,则所有配置项前面会自动匹配该前缀。如上边的格式中,会自动匹配CONFIG.ScreenZoomMode。若不需要前缀,可以将prefix=CONFIG.整行删掉,然后这样书写[Spinner=缩放方式]CONFIG.ScreenZoomMode=[0="拉伸",1="比例",2="特殊"]
Spinner是下拉菜单[]里面的是拉下菜单的取值和对应名称
SeekBar是拖动条,[]里面的是取值范围
Switch是开关按钮,[]里面的是开关状态对应的值
TextBox为文本框,可在最后添加一个[string],若string不存在,填写的项将没有"",若设定为[string]属性,填写的项将会自动加入双引号
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
 楼主| 发表于 2025-7-10 09:15 | 显示全部楼层
本帖最后由 lsl330 于 2025-7-10 20:25 编辑

--新增api
--CONFIG部分
CONFIG.SoundVolume=64 --音效大小,取值为1-128
CONFIG.MusicVolume=64 --音量大小,取值为1-128
CONFIG.GameTitle="群侠集结" --用于pc版本显示的游戏名称
CONFIG.MMapId=93; --设置大地图贴图编号,默认为0(因为不同编号往往有区别,提前定义可方便移植用)
CONFIG.SMapId=94; --设置场景贴图编号,默认为0(因为不同编号往往有区别,提前定义可方便移植用)
CONFIG.MapDId=93; --大地图事件用到的贴图编号,建议设定为和CONFIG.MMapId一致,先留个坑吧,实际上要还需要很多的修改,可以先不管,默认是不生效的
CONFIG.Operation = lib.GetOperation(); --获取操作系统类型,0-window;1-linux;2android直装;3android启动器
CONFIG.CurrentPath = lib.GetPath(1);--获取游戏目录地址,由底层统一管理
CONFIG.MouseMode=0 --可取值0,1,2(1实际上是完全禁用鼠标,没啥用),2为触控按钮模式(触屏设备可点击屏幕中上部快速切换)
if CONFIG.Operation == 2 or CONFIG.Operation == 3 then --针对不同系统按钮显示方案示例
        CONFIG.MouseMode = 2 --0为鼠标模式,2为触控模式,安卓默认启动,点击屏幕中上部可自动切换
else
        CONFIG.MouseMode = 0 --0为鼠标模式,2为触控模式,其他系统默认关闭
end
CONFIG.ButtonAlpha = 128; --按钮透明度
CONFIG.ButtonDScale = 140; --左侧按钮大小140%
CONFIG.ButtonScale = 130; --右侧按钮大小130%

CONFIG.SrcCharSet = 2--LUA源代码的字符集,你的LUA用什么编码要设置成哪种编码, 0 gb  1 big5   2 utf8
CONFIG.CharSet = 0 --游戏简繁显示0简体,1繁体,这是老API,但还是提示一下

CONFIG.ScreenZoomMode = 1 --1为等比例显示模式,0为拉伸模式,建议甚至为1,新增一个特殊缩放模式,值为2,建议搭配lib.ScreenDisplay()使用

--与cpp交互部分
local width,height=lib.ScreenDisplay() --获取屏幕宽高,此函数可以用于获取android手机的屏幕宽高,以下是简单示例

if CONFIG.ScreenZoomMode == 2 then--根据美好的地狱提议尝试的一种试验性缩放策略
            
        local width,height=lib.ScreenDisplay()
        if width / Height > CONFIG.Width / CONFIG.Height then --确定一下宽屏
                CONFIG.Width = math.modf(width*CONFIG.Height/height);--计算对应CONFIG.Height时铺满屏幕的宽度
        end
        --若这样设置,该模式下,当lib.LoadPNG的XY坐标均为-1时,图片会拉伸铺满全屏(用于大图使用),小图坐标需要自己换算调整
end

--逐梦江湖行使用的一种缩放策略
if CONFIG.Operation == 2 or CONFIG.Operation == 3 then;--安卓
        local width,height=lib.ScreenDisplay()
        local gwidth = math.modf(width*900/height);--计算对应900高时屏幕宽度
        local gheight = math.modf(height*900/width);--计算对应900高时屏幕宽度
        if gheight > gwidth then gwidth = gheight end
        if gwidth >= 2100 then
                CONFIG.Width = 2100
                CONFIG.Height = 900
        elseif gwidth >= 2000 then        
                CONFIG.Width = 2000
                CONFIG.Height = 900
        elseif gwidth >= 1900 then        
                CONFIG.Width = 1900
                CONFIG.Height = 900
        elseif gwidth >= 1800 then
                CONFIG.Width = 1800
                CONFIG.Height = 900
        else
                CONFIG.Width = 1600
                CONFIG.Height = 900
        end
end
--通过上述方式,可以获取安卓上的最佳显示比例。但强烈建议针对上述列明的比例做图像显示适配,否则毫无意义,还不如固定一个16比9的比例然后按比例显示

lib.FillColorCircle(x,y,r,color) --对x,y坐标,半径为r的圆,填充color颜色

lib.MouseState()--返回值true,false。可用于判定鼠标左键是否为按住的状态
lib.SetWeather(flag)--设置天气flag,0为晴天、1为雨天、2为雪天、3、雷、4为雷雨、5为雷雪
lib.CharSet(str,num)--主要用于转换R文件数据之用。num1为GBK转BIG5,0为BIG5转GBK,UTF8就没必要转了,R文件为UTF8时,LUA编码也设置成UTF8即可,省时省力
--之前排查发现和老API实现相反了,已经改回来。悲剧

lib.utf8gbk(str,boolean)--utf8编码和GBK编码互转
version = lib.utf8gbk(version, true)--举例,true为将version从GBK转换成UTF8,false为将UTF8转换成GBK,实际上除了特殊需求,应该已经没啥用了
lib.PlayMPEG(filename) --播放视频
lib.ExistFile(filename) --可跨平台判定文件是否存在(仅安卓直装方案需要使用,启动器貌似没啥用,还是写一下吧)
lib.SetMusicVolume(volume) --设置音量大小,取值0-128
lib.SetSoundVolume(volume) --设置音效大小,取值0-128
lib.SetZoom(num)        --实时变换贴图缩放比例
lib.MouseMode(num)        --实时切换触控状态,取值参考CONFIG.MouseMode
lib.WalkMode(num) --有效值0,1,实际上是用于触控方向按钮是否连按的判定,因最早用于走路判定,因此使用这名称,需包裹lib.GetKey()使用
--示例
local keypress, ktype, mx, my
lib.WalkMode(1)
keypress, ktype, mx, my = lib.GetKey()
if ktype < 2 then keypress = RepeatKey(keypress, CC.RepeatRate) end
lib.WalkMode(0)

--RepeatKey的实现
function RepeatKey(key,delay,flag)
        
        local firstdelay = 500
        local repeatkey = false
        
        if JY.WalkTime == 0 then
                CC.WalkTime = socket.gettime() * 1000 + firstdelay
                CC.RepeatKey = false
        else
                JY.WalkTime = socket.gettime() * 1000
        end
        
        if CC.RepeatKey and delay then
                lib.Delay(delay)
        elseif flag == 1 then
                lib.Delay(CC.Frame)
        end
        local RepeatState = {}
        for i = VK_RIGHT,VK_UP do --没表格存储按键状态,减少与C++底层的交互
                RepeatState = lib.GetKeyState(i)
        end
        
        --先检测跟上次不同的方向是否被按下
        if (JY.WalkTime == 0 or JY.WalkTime < CC.WalkTime) and firstdelay ~= 0 then
                if key==VK_UP then
                        JY.WalkTime = 0
                elseif key==VK_DOWN then
                        JY.WalkTime = 0
                elseif key==VK_LEFT then
                        JY.WalkTime = 0
                elseif key==VK_RIGHT then
                        JY.WalkTime = 0
                elseif RepeatState[VK_UP] ==0 and RepeatState[VK_DOWN] ==0 and RepeatState[VK_LEFT] ==0 and RepeatState[VK_RIGHT] ==0 then
                        JY.WalkTime = 0
                elseif JY.WalkTime < CC.WalkSkip then
                        JY.WalkTime = 1
                end
        else
                for i = VK_RIGHT,VK_UP do
                        if i ~= CC.PrevKeypress and RepeatState ~=0 then
                                key = i
                                repeatkey = true
                        end
                end
                --如果与上次不同的方向未被按下,则检测与上次相同的方向是否被按下
                if key==-1 and RepeatState[CC.PrevKeypress] and RepeatState[CC.PrevKeypress] ~=0 then
                        key = CC.PrevKeypress
                        repeatkey = true
                elseif repeatkey == false then
                        for i = VK_RIGHT,VK_UP do
                                if RepeatState ~=0 then
                                        key = i
                                        repeatkey = true
                                        break
                                end
                        end
                end
                CC.PrevKeypress = key
               
                if repeatkey == false then
                        JY.WalkTime = 0
                end
        end
        if repeatkey then CC.RepeatKey = true end
        return key
end

lib.InputText(x,y,color,size,fontname) --跨平台输入法支持
function InputText(x,y,color,size,fontname) --以下是一个实现示例
        if x == -1 or x == nil then
                x = CC.ScreenW
        end
        if y == -1 or y == nil then
                y = CC.ScreenH
        end
        if color == nil then
                color = C_WHITE
        end
        if size == nil then
                size = CC.DefaultFont
        end
        if fontname == nil then
                fontname = CC.FontName
        end        
        if CONFIG.SrcCharSet == 2 then
                return lib.InputText(x,y,color,size,fontname)
        else
                return lib.utf8gbk(lib.InputText(x,y,color,size,fontname), false) --非UTF8编码时,从UTF8转换成GBK
        end
end

lib.ButtonAlpha(128); --实时变换触控按钮透明度,取值0-255
lib.ButtonScale(140,130); --实时变换触控按钮大小,140%右侧、130%左侧
lib.ButtonMode(num); --切换按钮样式。num为0时使用XYL1R1图案,1时使用X1Y1L1R1图案,2时使用X2Y2L2R2图案
lib.OpenUrl(url) --打开网址
lib.SetCursor(num) --切换鼠标光标,0为默认光标,1为小手光标
lib.SetInt("g_DarkView", 160) --场景可使用,创造个黑暗视野。160为视野大小,可随意改动

Byte.unzip_path(zipfile, CC.SavePath..'', 'r.grp','d.grp','s.grp','tjm','e.grp','a.grp')
Byte.zipfile(zipfile, CC.SavePath..'r.grp','r.grp', CC.SavePath..'s.grp','s.grp', CC.SavePath..'d.grp','d.grp', CC.SavePath..'a.grp','a.grp', CC.SavePath..'e.grp','e.grp', CC.SavePath..'tjm','tjm')
--解压和压缩api。统一手机和安卓存档必须调整部分,以上是解压和压缩的示例。

--utf8相关api,若想将lua的编码迁移到utf8可尝试使用
lib.Utf8StringLen(str)--模拟GBK编码下的string.len(str)结果
lib.Utf8StringSub(str, start_byte, end_byte)--模拟GBK编码下的string.sub(str, start_byte, end_byte)结果
--具体使用可直接套路上述代码,批量替换将string.len(str)和string.sub(str, start_byte, end_byte)改成stringlen(str)和stringsub(str, start_byte, end_byte)
function stringlen(str)
        if CONFIG.SrcCharSet == 2 then
                return lib.Utf8StringLen(str)
        else
                return string.len(str)
        end
end

function stringsub(str, start_byte, end_byte)
        if CONFIG.SrcCharSet == 2 then
                return lib.Utf8StringSub(str, start_byte, end_byte)
        else
                return string.sub(str, start_byte, end_byte)
        end
end

--替换的同时,要注意不要替换这函数中的代码
function Split(szFullString, szSeparator)
  local nFindStartIndex = 1
  local nSplitIndex = 1
  local nSplitArray = {}
  while true do
    local nFindLastIndex = string.find(szFullString, szSeparator, nFindStartIndex)
    if not nFindLastIndex then
      nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, string.len(szFullString))
      break;
    else
            nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1)
            nFindStartIndex = nFindLastIndex + string.len(szSeparator)
            nSplitIndex = nSplitIndex + 1
          end
  end
  return nSplitIndex, nSplitArray
end


--内置的lua包含的额外模块
--本启动器内置的所有lua,均包含了lfs、socket和luasql.sqlite3模块
--lfs为文件管理模块,socket为网络模块,luasql.sqlite3为数据库模块


--luasql.sqlite3可参考如下方式导入
local luasql = require("luasql.sqlite3")
local env = luasql.sqlite3()
local conn = env:connect(filename)

--lfs和socket无需导入。
--可直接用lfs.和socket.的方式运行相关模块

【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

小黑屋|手机版|铁血丹心

GMT+8, 2025-7-12 21:35

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表