群侠集结安卓版启动器发布
本帖最后由 lsl330 于 2025-7-10 20:27 编辑整理了一下逐梦的底层,制作了一款安卓启动器。
百度下载地址
链接: 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、将游戏画面与虚拟按钮绘制逻辑分离。虚拟按钮固定现实在屏幕的指定位置。不再受游戏画面的影响
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金庸群侠传
=LUA54
游戏简介支持使用/n做分行显示,启动器支持多引擎启动,=LUA54(可选LUA52和LUA53),必须填写正确
Q:我想打开启动器直接运行游戏,可以么?
A:本启动器支持默认启动设置,在游戏运行中,从最左侧向右滑,可弹出侧滑菜单,选择设置为默认启动,以后启动即可自动运行。取消默认启动可以以同样方式在侧滑菜单中取消
Q:如何制作数据包
A:LUA版本应该要做部分改动才能完美支持该启动器。理论上来说,底层越新,迁移越容易。制作者有兴趣可联系门客,后续或许也会写一个适配指南。
Q:本启动器有何特色
A:简单来说,就是尽可能简单的提供多平台支持,可以用同一份数据包,实现win,android,linux的游戏运行,同时提供完全一致的游戏体验(win和linux的启动文件有空再发布吧)
\n是不是好一些 scarscc 发表于 2025-7-6 10:35
\n是不是好一些
啊,无所谓了。反正都没人写
config.UI示例(config.UI需放在数据包的根目录,编码为UTF-8)
path=config.lua
prefix=CONFIG.
encode=GBK
ScreenZoomMode=
Zoom=
MusicVolume=
SoundVolume=
ButtonAlpha=
WalkSkip=
Replay=
AutoConfirm=
ScreenW
PlayName
以下是格式讲解
path为配置文件所在位置。若在根目录config.lua则填config.lua,若在script目录,则填script/config.lua。实际上,启动器仅支持从这两个位置加载配置文件
encode为文本编码,需根据LUA对应的编码填写,可填写的值为GBK、BIG5、UTF-8。若不填写,默认为UTF-8
prefix为前缀,若添加,则所有配置项前面会自动匹配该前缀。如上边的格式中,会自动匹配CONFIG.ScreenZoomMode。若不需要前缀,可以将prefix=CONFIG.整行删掉,然后这样书写CONFIG.ScreenZoomMode=
Spinner是下拉菜单[]里面的是拉下菜单的取值和对应名称
SeekBar是拖动条,[]里面的是取值范围
Switch是开关按钮,[]里面的是开关状态对应的值
TextBox为文本框,可在最后添加一个,若string不存在,填写的项将没有"",若设定为属性,填写的项将会自动加入双引号
本帖最后由 lsl330 于 2025-7-10 20:28 编辑
--新增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 gb1 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即可,省时省力
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 ==0 and RepeatState ==0 and RepeatState ==0 and RepeatState ==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 and RepeatState ~=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 = string.sub(szFullString, nFindStartIndex, string.len(szFullString))
break;
else
nSplitArray = 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.的方式运行相关模块
页:
[1]