Compare commits

...

250 Commits

Author SHA1 Message Date
MrZ626
29002f8465 版本推进 2021-12-30 18:53:40 +08:00
MrZ626
1c5b7f1f9c 整理代码
调整中文tip
2021-12-30 18:35:54 +08:00
MrZ626
05921c2c53 更新一些日语翻译 2021-12-30 18:21:32 +08:00
MrZ626
5615037fd5 MES改回根据屏幕比例绘制 2021-12-29 00:03:38 +08:00
MrZ626
786490c654 调整一个人物词条细节 2021-12-28 22:38:09 +08:00
MrZ626
e6dc60afed 整理代码 2021-12-28 17:46:33 +08:00
MrZ626
939b32129d 框架新增setDebugInfo方法,原来的左下角debug信息可外部自定义 2021-12-28 17:43:17 +08:00
MrZ626
0ce3c7f9bc 缩短miya语音包欢迎语音 2021-12-28 17:42:35 +08:00
MrZ626
388a9fe418 微调音乐室交互 2021-12-28 14:59:16 +08:00
MrZ626
75e44da055 修复bgm资源管理问题导致的一些音频bug close #557 2021-12-28 14:59:06 +08:00
MrZ626
6aedeff515 重新编辑+裁剪部分音效 2021-12-28 14:47:59 +08:00
MrZ626
1bf6b887df 微调中文tip 2021-12-28 13:38:14 +08:00
MrZ626
fde80893ef 修改时间字符串使用的字符 2021-12-28 13:37:08 +08:00
MrZ626
b1fb9cc9f9 更新win和linux的图标 2021-12-28 12:04:37 +08:00
MrZ626
ceafcccc3b 修正开局倒计时问题 2021-12-28 12:01:57 +08:00
MrZ626
ac41690e76 修正staff菜单按键小问题 2021-12-28 12:01:52 +08:00
MrZ626
b941399aa8 微调主菜单按钮移动速度 2021-12-28 11:55:31 +08:00
MrZ626
97eb434d5f 添加一个赞助者 2021-12-28 11:54:06 +08:00
MrZ626
ea76b618a7 更新日语文本(by sakurw) 2021-12-28 11:53:32 +08:00
MrZ626
89595aa0d8 更新mac用图标 2021-12-28 11:42:22 +08:00
MrZ626
df28ca4cc1 补充一些日语文本
Co-authored-by: C₂₉H₂₅N₃O₅ <cgu52@wisc.edu>
2021-12-28 11:36:42 +08:00
MrZ626
7ca83597c4 修改更新历史 2021-12-27 19:51:35 +08:00
MrZ626
459d1e4c64 移除yygq语言
新增日语(by sakurw,不完整,待后续补充)
staff列表重做

Co-authored-by: C₂₉H₂₅N₃O₅ <cgu52@wisc.edu>
2021-12-27 19:34:14 +08:00
C₂₉H₂₅N₃O₅
683d73b04c 大改staff名单 (#565)
* 大改staff名单
2021-12-27 14:54:52 +08:00
NOT_A_ROBOT
0e838f08a6 Update issue templates (#568)
* Update bluescreen crash report template

* Update normal bug report template

* Update feature request template
2021-12-27 14:54:16 +08:00
MrZ626
f8f115de10 更新字体 2021-12-27 14:19:39 +08:00
MrZ626
b07c4dc53a 优化滑条控件和列表框控件 2021-12-26 02:57:57 +08:00
NOT_A_ROBOT
6eeddba773 Remove dictionary and legal page conflict (#563)
Dictionary: "A 🤔 game developed using LÖVE."
Legal page: "TECHMINO is not a fan game of Tetris."

This commit edits the dictionary to follow the legal page into:
"A block stacker game developed using LÖVE."
2021-12-25 19:24:51 +08:00
MrZ626
0cfe4df468 新BGM:lounge(暂未使用, by Hailey (cudsys) & MrZ) 2021-12-24 18:50:30 +08:00
MrZ626
eb5c3c3be5 版本推进 2021-12-24 00:08:46 +08:00
MrZ626
a5b9206694 修正联网对战结算的l'pm公式算的其实是lpm 2021-12-24 00:06:43 +08:00
MrZ626
375e67bdc4 微调框架坐标系相关细节 2021-12-24 00:06:40 +08:00
MrZ626
724a576aa3 跟进框架更新 2021-12-23 21:03:11 +08:00
MrZ626
ed47dcb90c 框架新增onResize 2021-12-23 21:03:05 +08:00
MrZ626
64b08a5a4d 修复录像界面导入导出按钮隐藏状态错误 2021-12-23 14:00:30 +08:00
MrZ626
baed0153a2 两个节日主题颜色浅一些 2021-12-23 13:48:39 +08:00
MrZ626
46d95b33e4 播放立体声音效限制输入值范围 2021-12-23 13:19:01 +08:00
MrZ626
200d270fee 框架会给场景提供触摸id 2021-12-22 21:22:19 +08:00
MrZ626
a8628275a0 大量指数接近动画改为基于时间而不是帧 2021-12-22 02:19:42 +08:00
MrZ626
20a1d2bcc1 修正框架主循环刷新率控制 2021-12-21 23:35:32 +08:00
MrZ626
b887a1f096 版本推进 2021-12-21 23:24:01 +08:00
MrZ626
9bf0e9f28d 调整一行hpc判定为“消除后最高行是垃圾行”,避免自定义场地的空气行争议 2021-12-21 23:18:49 +08:00
MrZ626
dfc724767b 调整帧率控制算法 2021-12-21 10:23:16 +08:00
MrZ626
f0e66e9dc5 框架添加设置最大帧率的入口 2021-12-21 00:16:29 +08:00
MrZ626
0932335f0b 微调游戏设置菜单 2021-12-20 23:21:02 +08:00
MrZ626
a9b39e396a BGM.play新增预加载参数 2021-12-20 16:01:19 +08:00
MrZ626
2e0ceaae72 math扩展库新增interval方法 2021-12-20 16:01:19 +08:00
MrZ626
04f38d2eb6 微调新模式pr的小问题 2021-12-20 14:55:42 +08:00
MrZ626
fc1ed4dff6 修正英文词典小问题 2021-12-20 14:52:40 +08:00
NOT_A_ROBOT
f8935d3dd7 Add Master Instinct mode (#545)
* Add Inverse Invisible mode

A mode where the locked pieces doesn't become invisible, but your active piece does.

[NOTE: I haven't added the mode to the map yet because the mode selection screen is changing]

* Renamed to Master Instinct
2021-12-20 14:51:30 +08:00
user670
a86228677f Update dict_en.lua (#556)
- Un-confused the support entries. Patreon processing fee assumes your account uses the 5% tier.
- TGM games are arcade games, NOT Windows games, despite their now most common versions found in China are Windows ports.
2021-12-20 14:47:45 +08:00
MrZ626
79df9f7876 前两个tsd模式有很小的重力 2021-12-19 20:22:02 +08:00
MrZ626
12ea2d76be 修正profile模块小问题 2021-12-19 17:06:44 +08:00
MrZ626
485bd72241 重构bgm模块 2021-12-19 16:29:50 +08:00
MrZ626
7240275075 修复一个bgm模块小问题 2021-12-19 15:26:16 +08:00
MrZ626
29ef9b8d15 ai种子会根据id变化 2021-12-19 00:59:01 +08:00
MrZ626
97f4795d4e 修正一处框架修改没改完导致地图报错 2021-12-19 00:50:42 +08:00
MrZ626
226e45b24d 整理代码 2021-12-18 16:08:45 +08:00
MrZ626
d6ab7e72b2 调整某个无关紧要的小东西 2021-12-18 01:15:04 +08:00
MrZ626
168f44b8b3 修正一处框架方法名修改没改完 2021-12-18 00:37:32 +08:00
MrZ626
b73f646a4c 作者要求mono语音包暂时消失一段时间 2021-12-18 00:25:05 +08:00
MrZ626
36cefcc000 太空背景支持任意帧率 2021-12-17 21:57:33 +08:00
MrZ626
f901c25c87 修正一些地方move音效没改touch 2021-12-17 21:12:50 +08:00
MrZ626
6d8478b029 string扩展模块新增一个按字符数读+截取的方法 2021-12-17 13:54:27 +08:00
MrZ626
9bcb040019 bgm模块新增isPlaying方法 2021-12-16 17:47:57 +08:00
MrZ626
d977087fc0 调整上一个pr的小问题 2021-12-16 14:35:57 +08:00
C₂₉H₂₅N₃O₅
1a330771d7 大改词典 (#553)
* 大修中文词典

`dict_zh`:
* 术语和专有名词大小写修正
* 日期格式标准化
* 增加评论注释
* 增加更多关键词索引
* 删除重复内容
* 英文使用半角标点
* 修改一些写错的名词
* 修改一个链接

* Updated `dict_en`

`dict_en`
* Added more search indexes
* Added many contents from `dict_zh`, especially the games
* Changed some URL links (from the teatube version to the original websites, if possible)
* Corrected the names of the wrongly-spelled proper nouns
* Rearranged the order of some entries
2021-12-16 13:48:02 +08:00
MrZ626
9c8c9f2106 涉及框架的设置项统一应用,不再细分时机
修改errData的获得方式
WIDGET新增setOnChange方法,不再依赖THEME
2021-12-16 12:39:42 +08:00
MrZ626
8e075adf8f 新增一个简易秒表小程序 2021-12-16 02:58:36 +08:00
MrZ626
60f2a0e647 更新ios无法自动退出的界面细节 2021-12-16 02:37:25 +08:00
MrZ626
2b80f72c6b 移除框架内几处对SETTING的依赖 2021-12-16 02:31:53 +08:00
MrZ626
3dda0254a8 调整中文词典的游戏介绍词条及顺序
Co-authored-by: C₂₉H₂₅N₃O₅ <cgu52@wisc.edu>
2021-12-16 00:22:32 +08:00
MrZ626
054a52a445 版本推进 2021-12-15 14:28:44 +08:00
MrZ626
85242d808b 修复语言文件小问题 2021-12-15 14:28:05 +08:00
MrZ626
57241677a9 修复混战 2021-12-15 14:26:40 +08:00
MrZ626
6ccdee2a53 bgm模块新增瞬间开/关功能
字符串扩展模块不再直接修改全局的string,需要外部自己补充
2021-12-15 11:28:25 +08:00
MrFaq2018
a3d2b7b7f3 Update lang_es.lua (#552) 2021-12-14 12:41:45 +08:00
MrZ626
b7b28b4ae3 修复经典模式h和u难度没有干旱计数器 close #546 2021-12-13 03:52:19 +08:00
MrZ626
30748200dd 修复自定义场地界面按超过第三个的鼠标键会报错 2021-12-11 19:38:24 +08:00
MrZ626
5c7082e886 修复不能deepdrop 2021-12-10 12:50:57 +08:00
MrZ626
9a3c889a9d 修改词典和tip 2021-12-10 09:31:07 +08:00
MrZ626
b432fdf90a 部分语言的模式说明添加换行 2021-12-09 19:43:36 +08:00
MrZ626
df089a2f04 框架新增1*1空白画布变量PAPER 2021-12-09 17:26:02 +08:00
user670
6600713f4b Update lang_en.lua (#540) 2021-12-09 16:04:24 +08:00
NOT_A_ROBOT
96dad762b2 Update lang_en.lua (#544)
BiRS now allows you to spin the O1 piece.
2021-12-09 16:03:57 +08:00
MrZ626
fa64c868b9 调整一些tip 2021-12-09 15:21:51 +08:00
MrZ626
97e7b019dd TRS的N/H块补充一个踢墙 2021-12-09 03:21:28 +08:00
MrZ626
1826ca6f2f fix 2021-12-09 01:03:27 +08:00
MrZ626
db490a6c6c FILE.load新增-lua方式(直接运行,无环境限制) 2021-12-09 01:01:24 +08:00
MrZ626
421fdef4f9 调整两个群友词条的关键词 2021-12-09 01:00:40 +08:00
MrZ626
d717ce842d 调整tip 2021-12-08 09:19:58 +08:00
MrZ626
f13c9792af 调整把按键添加到录像的时机
修复触发了自动保存的最后一个按键本身不会保存到录像里
2021-12-08 08:40:24 +08:00
MrZ626
41e7b8e0f4 版本推进 2021-12-07 22:43:53 +08:00
MrZ626
4bd723a7ee 整理代码 2021-12-07 22:43:48 +08:00
MrZ626
66d5bd5490 更多场景的大标题添加最大显示长度 2021-12-07 22:40:16 +08:00
MrZ626
351d0258b2 再优化miya立绘 2021-12-07 22:40:16 +08:00
NOT_A_ROBOT
26fb9a7052 Add Strategy+ (#539) 2021-12-07 22:39:00 +08:00
MrZ626
307fd637fa 换新miya立绘
给不同立绘添加不同点击动画
2021-12-07 20:25:14 +08:00
MrZ626
93fb716f89 fix 2021-12-07 17:10:02 +08:00
MrZ626
7b41551e2d xitonglai 2021-12-07 16:57:47 +08:00
MrZ626
4806af5f7d 重做关于页面,赞助二维码搬家 2021-12-07 16:00:52 +08:00
MrZ626
85cb55cdd0 文本控件也支持设置最大宽度了 2021-12-07 15:51:19 +08:00
MrZ626
27a9697e47 修改scene模块,支持在切换场景的时候传参了 2021-12-07 15:04:27 +08:00
MrZ626
7d230cc3b0 修正印尼语按钮文本错误 close #536 2021-12-07 14:33:04 +08:00
MrZ626
0db2fffad1 版本推进 2021-12-07 01:43:17 +08:00
MrZ626
2a3296a0e8 调整pixel皮肤,修改x块的默认色为黄色 2021-12-07 01:26:46 +08:00
MrZ626
941b875afa 再微调语言设置界面
整理代码
2021-12-07 01:05:46 +08:00
MrZ626
99155bb9cf 更新macOS安装包用图
Co-authored-by: C₂₉H₂₅N₃O₅ <cgu52@wisc.edu>
2021-12-07 01:00:22 +08:00
MrZ626
0701dd2ad3 新皮肤:pixel(by C₂₉H₂₅N₃O₅) 2021-12-07 00:59:19 +08:00
MrZ626
5570c19e1f 调整颜色表
调整语言选择菜单
整理代码
2021-12-07 00:59:19 +08:00
NOT_A_ROBOT
a728c91476 Add Indonesian Translation (#535)
- Added Indonesian language file
- Added Indonesian button in language select menu
- Added Indonesian variant of the word "language" on the language select menu
- Added credit to me for translating (applies to all languages)
2021-12-07 00:00:51 +08:00
MrZ626
6a43481067 优化小程序triple体验 2021-12-06 22:42:49 +08:00
MrZ626
29a049fe4e 版本推进 2021-12-06 22:20:59 +08:00
MrZ626
b5a9c8e1bb 修正一处手柄事件可能爆炸 2021-12-06 21:17:30 +08:00
MrZ626
bb9a35c161 修复云存档/读档的一处小问题 2021-12-06 21:11:54 +08:00
MrZ626
b25a345b42 更换click音效,音乐室播放按钮声音调整 2021-12-06 20:33:41 +08:00
MrZ626
b22b0e0194 修正文件加载模块参数识别的小问题 2021-12-06 19:52:00 +08:00
MrZ626
55cf95f218 修正策略堆叠模式评级标准不当 2021-12-06 19:24:24 +08:00
MrZ626
225ddbcfac 调整几个tip 2021-12-06 16:43:46 +08:00
MrZ626
9377090c7c 【bug风险较大,需要测试】解耦玩家代码中的部分混战模式代码 2021-12-06 16:00:46 +08:00
MrZ626
ed002ec2e1 略微降低master-h模式骨块出现后的难度 2021-12-06 13:49:51 +08:00
MrZ626
e33036d9ec 调整几个词条的关键词 2021-12-06 12:46:17 +08:00
MrZ626
ef03e7c009 layout菜单名改为style 2021-12-06 12:46:11 +08:00
MrZ626
aef4220ac0 修复自定义场地16号颜色的方块名位置显示错误
优化皮肤设置页面交互效果
2021-12-06 03:25:39 +08:00
MrZ626
46223e38cd STRING模块新增一个简易摘要算法,未来保护用户密码明文可能用到 2021-12-06 03:18:41 +08:00
MrZ626
4bafa4bffe 版本推进 2021-12-05 22:01:16 +08:00
MrZ626
2b3dd877dd 修正100攻击竞速模式没有重力 2021-12-05 18:13:47 +08:00
MrZ626
0553e5c45e 调整中文tip 2021-12-05 18:11:12 +08:00
MrZ626
4d93374cf6 微调暂停界面和语言选择界面 2021-12-05 00:54:42 +08:00
MrZ626
4e421bf9ba 微调一些场景细节 2021-12-04 22:29:38 +08:00
user670
8b2a9d7c01 Update lang_en.lua (#534) 2021-12-04 22:17:43 +08:00
C₂₉H₂₅N₃O₅
5a3244d345 更改语言选择界面布局 (#532)
* 再更改语言选择布局
2021-12-04 19:56:24 +08:00
MrZ626
f1b9d0c5e4 新增返回按钮音效 2021-12-03 17:15:32 +08:00
MrZ626
6493e0e623 创建button和key控件时的sound参数可以指定音效名了 2021-12-03 16:45:37 +08:00
MrZ626
e71ba17f9f 微调一个中文词典词条 2021-12-03 11:57:21 +08:00
MrZ626
e656363e20 录像回放菜单对键盘支持更好 2021-12-03 11:23:44 +08:00
MrZ626
0826a748ae 版本推进 2021-12-03 11:04:51 +08:00
MrZ626
a595fe99ef 大规模整理中文tip 2021-12-03 10:50:05 +08:00
MrZ626
9dbc7942e3 调整语言菜单标题 2021-12-03 10:49:57 +08:00
C₂₉H₂₅N₃O₅
845d8ae32e 字体增加谚文/语言滚动菜单丰富 (#530)
* 字体支持谚文显示

* 语言选择界面滚动菜单增加一堆语言
2021-12-03 08:26:09 +08:00
MrZ626
5c524e138c 语言选择菜单会轮流显示不同语言的“语言” 2021-12-02 22:06:06 +08:00
MrZ626
86d9265ff9 修复最后一个hold的死锁问题 close #528 2021-12-02 18:42:03 +08:00
MrZ626
6994a5d6d3 调整tip 2021-12-02 18:16:59 +08:00
MrZ626
e6213b00c1 修复无尽挖掘规则包会对非指定背景做不好的事情 close #525 2021-12-02 14:07:52 +08:00
MrZ626
43e2caa30e 修正进入登录场景时本地没保存过账户信息文件时会弹出文件读取错误 2021-12-02 10:04:38 +08:00
MrZ626
97ca245dfc 修复放录像的时候虚拟按键不会自己动 2021-12-02 08:58:35 +08:00
MrZ626
36de1c0751 版本推进 2021-12-02 01:40:01 +08:00
MrZ626
704341fd15 修正软降在sddas/sdarr很小的时候行为不正确 2021-12-02 01:33:50 +08:00
MrZ626
22b61bc9c3 修正暂停界面数据显示条件为>=180帧而不是>180帧
key控件微调
2021-12-02 00:30:21 +08:00
MrZ626
f4cbbc0a2a 修复cc看不到初始场地 2021-12-01 22:15:54 +08:00
MrZ626
dc99187b9d 修改三个音效名称 2021-12-01 22:03:22 +08:00
MrZ626
915598dec4 整理代码,SFX模块load时会提示缺失多少音效 2021-12-01 19:23:39 +08:00
MrZ626
e7b4518d73 【警告:需要测试】
调整玩家能hold/移动/旋转方块的条件
修复cc复活后小bug
整理代码
2021-12-01 15:46:12 +08:00
NOT_A_ROBOT
9603a78e87 Halved field height for Big mode (#520)
* Halved field height for big mode

Co-authored-by: MrZ_26 <1046101471@qq.com>
2021-12-01 09:29:57 +08:00
MrZ626
bd90e051d4 版本推进 2021-12-01 02:41:18 +08:00
MrZ626
26e66b313f 继续收拾各种ui相关
空心控件统一加上灰色背景方便观察
按钮样式调整
2021-12-01 02:40:11 +08:00
MrZ626
c534bbd12a 微调马拉松和混战的速度曲线 2021-12-01 00:39:21 +08:00
NOT_A_ROBOT
83b5e217e5 Add Big Mode (#515)
I even halved the gravity :)
2021-12-01 00:10:00 +08:00
MrZ626
c0adf5bf0b COLOR模块新增三个半透明灰色并大量应用
微调颜色V和lV的hue值
2021-11-30 23:36:04 +08:00
MrZ626
4ff737a4ac 减小语音随机偏差范围 2021-11-30 23:20:59 +08:00
MrZ626
5af0706c09 普通消1不再有single语音 2021-11-30 22:52:27 +08:00
MrZ626
4ccee0f1de 修改小程序trp的next生成 2021-11-30 22:31:46 +08:00
MrZ626
9b752d540e 修正慢速下落有拖影不好看
测试代码忘删
2021-11-30 22:24:58 +08:00
MrZ626
e860c7b7ec 大改重力和软降的结算逻辑,两个值接近的时候不会看起来不自然了 close #438 2021-11-30 19:40:53 +08:00
C29H25N3O5
8a1fd9531f 修复NH块搞反的问题 2021-11-30 15:54:54 +08:00
C29H25N3O5
5fd6e0ee99 再更新虚拟按键贴图, 使用Plex字体 2021-11-30 15:54:52 +08:00
MrZ626
53b2b81fe0 再新增几个tip 2021-11-30 14:51:04 +08:00
MrZ626
6ccc811b46 微调tip 2021-11-30 12:56:32 +08:00
MrZ626
962a61567a OS X系统名称字符串强制改为macOS close #513 2021-11-30 12:25:59 +08:00
MrZ626
58f05e1cec 控制台sudo命令改名su 2021-11-30 12:22:14 +08:00
MrZ626
6b426790c7 调整小程序triple 2021-11-30 11:49:48 +08:00
MrZ626
d4fc578673 词典添加穿透词条 2021-11-30 11:17:17 +08:00
MrZ626
51b567b8db app -list输出美化 2021-11-30 03:53:22 +08:00
MrZ626
07b47dee3f 版本推进 2021-11-30 01:50:13 +08:00
MrZ626
4431a906b9 整理代码 2021-11-30 01:44:21 +08:00
NOT_A_ROBOT
2bb6852e3e Added multiple bg and bgm to Strategy Mode (#506)
(excluding strategy_e for the bgm)
2021-11-30 01:42:39 +08:00
user670
1948ed3e16 Update gameTables.lua (#508)
On an XBox controller, B is on the right and A is on the bottom (unlike a Nintendo controller), and it makes more sense to default B to rotate right and A to rotate left.
2021-11-30 01:42:02 +08:00
MrZ626
81b5ccae30 修复检测第一次启动失败 2021-11-30 01:40:53 +08:00
MrZ626
5543ff0d29 新小程序:Triple 2021-11-30 01:40:49 +08:00
MrZ626
cd567e9e98 删除添加作者qq按钮 2021-11-30 01:40:01 +08:00
MrZ626
5d86925a8a 大多数菜单的二次确认统一用tryXXX管理 2021-11-30 01:40:01 +08:00
MrZ626
e3db564a4b 整理代码,返回需要二次确认的小程序统一用一个函数 2021-11-30 01:40:01 +08:00
MrZ626
a4293624ab 微调wine颜色 2021-11-29 22:24:17 +08:00
MrZ626
367e2dc81a 新增几个tip 2021-11-29 21:32:09 +08:00
MrZ626
9ec33c6eef 修改BGM: sugar fairy的作者标注 2021-11-29 21:32:08 +08:00
MrZ626
9c9b8d36f2 小程序mem平衡调整 2021-11-29 21:32:08 +08:00
MrZ626
4fc6f335c7 新增小程序:Memorize 2021-11-29 15:40:55 +08:00
MrZ626
d2f4123d08 修改两个有数字键盘的小程序的退格键图标 2021-11-29 15:40:40 +08:00
MrZ626
b29d352a1b 把主菜单快捷键加回来 2021-11-29 12:57:17 +08:00
MrZ626
cd5a71cd12 更新赞助名单 2021-11-29 12:49:58 +08:00
MrZ626
cdd68e985d 修正键位设置菜单里mac的del键符号错误 2021-11-29 11:15:24 +08:00
MrZ626
8cf4d4280c 修正Ospin变O后操作序列不清空
Ospin变远端朝下JL时允许水平可移动
2021-11-29 11:11:54 +08:00
C29H25N3O5
cd29bf8702 调整字体
* Monospaced字体简中字库使用大陆标准字形, 日语部分仍然使用日语字形
* 调整自定义图标手柄和键盘部分的文字字体
* 修复proportional字体a的变音符没对齐的问题
* 修复Monospaced字体ij连字的问题
* 修复Monospaced字体slash还用的是plex字体的问题
2021-11-28 18:24:11 -06:00
MrZ626
13d98be051 版本推进 2021-11-29 04:23:05 +08:00
MrZ626
a350ff3182 微调背景模块,自定义模式设置背景的时候访问不到特殊背景了 2021-11-29 04:22:08 +08:00
MrZ626
e0360cc7eb 修正一处模块更新错误(傻了) 2021-11-29 03:57:18 +08:00
MrZ626
4249a29b63 继续优化键位设置菜单 2021-11-29 03:38:05 +08:00
MrZ626
43b2a0a8c8 优化键位设置菜单各种键的显示 2021-11-29 03:27:57 +08:00
MrZ626
6d6584f99e 修改按钮音效,给复选框和选择器添加新音效 2021-11-29 02:48:41 +08:00
MrZ626
077c651226 微调键位设置菜单 2021-11-29 01:16:22 +08:00
MrZ626
3fc872aa76 微调几个隐藏模式入口点击范围 2021-11-28 22:39:49 +08:00
MrZ626
cb0b347a38 更新赞助名单 2021-11-28 22:21:10 +08:00
MrZ626
d08967c688 整理词典 2021-11-28 22:02:39 +08:00
MrZ626
3666c0caa9 修复更换自定义背景图片时没有更新尺寸 2021-11-28 20:52:12 +08:00
MrZ626
4ef179fccb 控制台场景向全局环境添加一个输出到控制台的函数 close #499 2021-11-28 19:51:46 +08:00
MrZ626
861f9b3caa 继续完善手柄控制 2021-11-28 19:40:26 +08:00
MrZ626
05292df456 模式地图上读取手柄按键时不再报错 2021-11-28 17:43:36 +08:00
MrZ626
9fed692223 控制台help命令输出美化 close #502 2021-11-28 16:53:24 +08:00
MrZ626
b1c04c1fea 修复自定义模式用按钮开始游戏会报错 2021-11-28 16:21:27 +08:00
MrZ626
bc9adc2cd3 调整扳机键的默认触发阈值 2021-11-28 16:16:44 +08:00
MrZ626
cdf149afca 略微优化自定义背景绘制性能 2021-11-28 05:20:29 +08:00
MrZ626
73145b4e5e 自定义背景拖入无法识别的格式时会提示 2021-11-28 05:20:18 +08:00
MrZ626
f8b9f30fd6 修改框架的光标默认位置 2021-11-28 05:02:29 +08:00
MrZ626
e6bc567b12 两种按钮上的文本也会挤压绘制了
优化控件绘制性能
修正两个背景设置按钮位置错误
调整之前忘了同步的语言
2021-11-28 04:56:55 +08:00
MrZ626
fe004a72f0 版本推进 2021-11-28 04:17:44 +08:00
MrZ626
0433fd3d9d 三个高难隐形使用不同模式图标 close #493 2021-11-28 04:10:42 +08:00
MrZ626
1c18060570 尝试修复地图菜单读取手柄摇杆位置错误 2021-11-28 04:06:37 +08:00
MrZ626
be54c0e641 关闭背景时亮度可调
新增自定义图片背景功能(可调透明度,目前仅电脑可用)
2021-11-28 03:56:53 +08:00
MrZ626
0be2eb9107 修正一处可能未改回材质缩放模式 2021-11-28 03:30:34 +08:00
MrZ626
4859faf1e7 创建控件允许留空code域,什么都不会发生 2021-11-28 02:03:52 +08:00
MrZ626
c25d40c67d 启动加载数据文件时允许不存在,不会提醒 close #495 2021-11-28 01:59:24 +08:00
MrZ626
b6c37a5c9f 框架keyDown事件机制微调,重构框架主循环和控件相关代码
可以用键盘和手柄控制光标(手柄不完善)
整理代码和部分语言文件细节
2021-11-27 23:16:21 +08:00
MrZ626
f6b4c1b109 整理代码,表示键盘按键的字符串使用单引号 2021-11-27 19:01:32 +08:00
MrZ626
841faeede4 版本推进 2021-11-27 14:33:38 +08:00
MrZ626
e61b9b23a0 修复右侧c/s/a+方向键不能触发控件功能 close #492 2021-11-27 14:33:36 +08:00
MrZ626
72a826ef0a 微调报错界面,日志使用等宽字体 2021-11-27 14:25:13 +08:00
MrZ626
f070b8f295 修正svg标题的小问题 2021-11-27 14:20:05 +08:00
MrZ626
1646b75520 修正TRS的v块1<->2比0<->3少一个踢墙 2021-11-27 14:20:05 +08:00
C29H25N3O5
241617e31a 微调字体
* Monospaced的CJK字体也调整为思源
* 改动几个新元素汉字
* 精简Monospaced字符集
2021-11-26 22:58:40 -06:00
MrZ626
5de2893e07 帮0.17前的版本自动调大1帧的das打断,尝试维持手感 2021-11-27 05:52:35 +08:00
MrZ626
030e894040 theme移出框架,大改通常bgm的配置 2021-11-27 05:35:55 +08:00
MrZ626
e7b9a4ba87 添加DRS_weak旋转系统 close #441 2021-11-27 05:09:02 +08:00
MrZ626
617bae67c6 修正matt的一些翻译修改和控制台代码 2021-11-27 04:47:48 +08:00
MattMayuga
64d2d08820 Update English translation (#487)
* Update readme.md

* Update lang_en.lua

* Update app_console.lua

* Update error.lua

* Add warnings and extended time to 10s for resetall

When you use the resetall command, you will now get a message that there is no way to recover the saved data when it is deleted.
2021-11-27 04:28:08 +08:00
NOT_A_ROBOT
037b33c99a Update theme list (#489) 2021-11-27 04:26:40 +08:00
MrZ626
afa69ce9a4 版本推进 2021-11-27 04:24:41 +08:00
MrZ626
3226c0c831 重构字体模块,支持多字体
控制台应用等宽字体
2021-11-27 04:24:40 +08:00
MrZ626
4e759cad4c ultra模式重开时会重新播放bgm 2021-11-27 02:05:48 +08:00
MrZ626
291795928d 更多的设置修改的时候会触发警告 2021-11-26 21:52:10 +08:00
MrZ626
a1315e7f7f 修复一处遗留逻辑hold和序列生成相关的错误 2021-11-26 21:24:34 +08:00
MrZ626
657bc2b4e0 修正加载文件的时候会因为没有应用语言没法弹出消息而报错 2021-11-26 14:15:42 +08:00
MrZ626
d8b12fc55d 版本推进 2021-11-26 01:48:23 +08:00
MrZ626
6d11367ea4 新BGM:malate(暂未使用) 2021-11-26 01:47:14 +08:00
MrZ626
eb9e741b4f 关于界面的对称40行入口换成堆积模式 2021-11-26 00:59:23 +08:00
MrZ626
c47546d501 微调一些玩家动作逻辑
修复零ARE+非零lineARE的时候ihs失效
2021-11-26 00:55:29 +08:00
MrZ626
11aa178fc1 ultra模式计时器样式改为数字 2021-11-25 19:58:22 +08:00
MrZ626
f3a88ef269 游戏内再次封装saveFile和loadFile函数
原本的FILE模块更独立,不基于全局text变量和报错信息而是直接报错
2021-11-25 17:38:09 +08:00
MrZ626
720dc2131f 字符串扩展模块给默认string库补充两个方法repD和sArg 2021-11-25 17:37:46 +08:00
MrZ626
701ef17ae1 大爆炸改名清版竞速 2021-11-25 14:03:36 +08:00
MrZ626
1a689a5f07 修正当前方块显示条件 2021-11-25 09:57:45 +08:00
239 changed files with 8115 additions and 4255 deletions

View File

@@ -1,8 +1,8 @@
---
name: Bug report (bluescreen crash) Bug报告 (蓝屏报错)
about: Create a report of problems which made the crash with a bluescreen
about: Create a bug report which causes a bluescreen crash
---
Screenshot with crash information (*Image(s) Here*):
If you can reproduce it, write the steps here. If you can't, try to describe the exactly time the game crash, like pressing which key or which button (*Details Here*)
If you can reproduce it, write the steps here. If you can't, try to describe what causes the game to crash, like pressing a key/button (*Details Here*)

View File

@@ -1,8 +1,8 @@
---
name: Bug report (unintended behaviors) Bug报告 (奇怪的现象)
about: Create a report of unintended behaviors
about: Create bug report that causes unintended behaviors
---
Screenshot with unintended behaviors (*Image(s) Here*):
If you can reproduce it, write the steps here. If you can't, try to describe the exactly time the game crash, like pressing which key or which button (*Details Here*):
If you can reproduce it, write the steps here. If you can't, try to describe what causes the unintended behavior, like pressing a key/button (*Details Here*):

View File

@@ -2,3 +2,7 @@
name: Feature Request 添加新功能
about: Suggest an idea that may improve Techmino 提一些有意思的新想法,让Techmino越来越好!
---
### What feature do you want to suggest to the game?

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -4,8 +4,9 @@ local BGs={
}
local BGlist={'none'}
local BG={
cur='none',
default='none',
locked=false,
cur='none',
init=false,
resize=false,
update=NULL,
@@ -14,6 +15,8 @@ local BG={
discard=NULL,
}
function BG.lock()BG.locked=true end
function BG.unlock()BG.locked=false end
function BG.add(name,bg)
BGs[name]=bg
BGlist[#BGlist+1]=name
@@ -21,6 +24,9 @@ end
function BG.getList()
return BGlist
end
function BG.remList(name)
table.remove(BGlist,TABLE.find(BGlist,name))
end
function BG.send(...)
if BG.event then
BG.event(...)
@@ -29,20 +35,20 @@ end
function BG.setDefault(bg)
BG.default=bg
end
function BG.set(background)
background=background or BG.default
if not BGs[background]or not SETTING.bg then return end
if background~=BG.cur then
function BG.set(name)
name=name or BG.default
if not BGs[name]or BG.locked then return end
if name~=BG.cur then
BG.discard()
BG.cur=background
background=BGs[background]
BG.cur=name
local bg=BGs[name]
BG.init= background.init or NULL
BG.resize= background.resize or NULL
BG.update= background.update or NULL
BG.draw= background.draw or NULL
BG.event= background.event or NULL
BG.discard=background.discard or NULL
BG.init= bg.init or NULL
BG.resize= bg.resize or NULL
BG.update= bg.update or NULL
BG.draw= bg.draw or NULL
BG.event= bg.event or NULL
BG.discard=bg.discard or NULL
BG.init()
end
return true

View File

@@ -1,44 +1,17 @@
local lastLoaded={}
local maxLoadedCount=3
local nameList={}
local SourceObjList={}
local volume=1
local BGM={
default=false,
getList=function()error("Cannot getList before initialize!")end,
getCount=function()return 0 end,
play=NULL,
stop=NULL,
onChange=NULL,
--nowPlay=[str:playing ID]
--playing=[src:playing SRC]
--lastPlayed=[str:lastPlayed ID]
}
local function task_fadeOut(src)
while true do
coroutine.yield()
local v=src:getVolume()-.025*volume
src:setVolume(v>0 and v or 0)
if v<=0 then
src:pause()
return true
end
end
end
local function task_fadeIn(src)
while true do
coroutine.yield()
local v=volume
v=math.min(v,src:getVolume()+.025*v)
src:setVolume(v)
if v>=volume then
return true
end
end
end
local function check_curFadeOut(task,code,src)
return task.code==code and task.args[1]==src
end
local function _tryReleaseSources()
local n=#lastLoaded
while #lastLoaded>maxLoadedCount do
@@ -53,6 +26,27 @@ local function _tryReleaseSources()
end
end
end
local function _addFile(name,path)
if not SourceObjList[name]then
table.insert(nameList,name)
SourceObjList[name]={path=path,source=false}
end
end
function BGM.getList()return nameList end
function BGM.getCount()return #nameList end
function BGM.load(name,path)
if type(name)=='table'then
for k,v in next,name do
_addFile(k,v)
end
else
_addFile(name,path)
end
table.sort(nameList)
LOG(BGM.getCount().." BGM files added")
end
function BGM.setDefault(bgm)
BGM.default=bgm
end
@@ -75,85 +69,114 @@ function BGM.setVol(v)
end
end
end
function BGM.init(list)
BGM.init=nil
local simpList={}
for _,v in next,list do
table.insert(simpList,v.name)
SourceObjList[v.name]={path=v.path,source=false}
end
table.sort(simpList)
function BGM.getList()return simpList end
local count=#simpList
LOG(count.." BGM files added")
function BGM.getCount()return count end
local function _tryLoad(name)
if SourceObjList[name]then
if SourceObjList[name].source then
return true
elseif love.filesystem.getInfo(SourceObjList[name].path)then
SourceObjList[name].source=love.audio.newSource(SourceObjList[name].path,'stream')
SourceObjList[name].source:setLooping(true)
SourceObjList[name].source:setVolume(0)
table.insert(lastLoaded,1,name)
_tryReleaseSources()
return true
else
LOG("No BGM: "..SourceObjList[name],5)
end
elseif name then
LOG("No BGM: "..name,5)
local function task_fadeOut(src)
while true do
coroutine.yield()
local v=src:getVolume()-volume/40
src:setVolume(v>0 and v or 0)
if v<=0 then
src:stop()
return true
end
end
function BGM.play(name)
name=name or BGM.default
if not _tryLoad(name)then return end
if volume==0 then
end
local function task_fadeIn(src)
while true do
coroutine.yield()
local v=volume
v=math.min(v,src:getVolume()+v/40)
src:setVolume(v)
if v>=volume then
return true
end
end
end
local function check_curFadeOut(task,code,src)
return task.code==code and task.args[1]==src
end
local function _tryLoad(name)
if SourceObjList[name]then
if SourceObjList[name].source then
return true
elseif love.filesystem.getInfo(SourceObjList[name].path)then
SourceObjList[name].source=love.audio.newSource(SourceObjList[name].path,'stream')
SourceObjList[name].source:setVolume(0)
table.insert(lastLoaded,1,name)
_tryReleaseSources()
return true
else
LOG("No BGM: "..SourceObjList[name],5)
end
elseif name then
LOG("No BGM: "..name,5)
end
end
function BGM.play(name,args)
name=name or BGM.default
args=args or""
if not _tryLoad(name)or args:sArg('-preLoad')then return end
if volume==0 then
BGM.nowPlay=name
BGM.playing=SourceObjList[name].source
return true
end
if name and SourceObjList[name].source then
if BGM.nowPlay~=name then
if BGM.nowPlay then
if not args:sArg('-sdout')then
TASK.new(task_fadeOut,BGM.playing)
else
BGM.playing:pause()
end
end
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source)
TASK.removeTask_code(task_fadeIn)
BGM.nowPlay=name
BGM.playing=SourceObjList[name].source
return true
end
if name and SourceObjList[name].source then
if BGM.nowPlay~=name then
if BGM.nowPlay then
TASK.new(task_fadeOut,BGM.playing)
end
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source)
TASK.removeTask_code(task_fadeIn)
TASK.new(task_fadeIn,SourceObjList[name].source)
BGM.nowPlay=name
BGM.playing=SourceObjList[name].source
BGM.lastPlayed=BGM.nowPlay
BGM.playing:seek(0)
if not args:sArg('-sdin')then
BGM.playing:setVolume(0)
TASK.new(task_fadeIn,BGM.playing)
else
BGM.playing:setVolume(volume)
BGM.playing:play()
BGM.onChange(name)
end
return true
end
end
function BGM.seek(t)
if BGM.playing then
BGM.playing:seek(t)
end
end
function BGM.continue()
if BGM.lastPlayed then
BGM.nowPlay,BGM.playing=BGM.lastPlayed,SourceObjList[BGM.lastPlayed].source
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[BGM.nowPlay].source)
TASK.removeTask_code(task_fadeIn)
TASK.new(task_fadeIn,BGM.playing)
SourceObjList[name].source:setLooping(not args:sArg('-noloop'))
BGM.lastPlayed=BGM.nowPlay
BGM.playing:play()
BGM.onChange(name)
end
return true
end
function BGM.stop()
end
function BGM.seek(t)
if BGM.playing then
BGM.playing:seek(t)
end
end
function BGM.isPlaying()
return BGM.playing and BGM.playing:isPlaying()
end
function BGM.continue()
if BGM.lastPlayed then
BGM.nowPlay,BGM.playing=BGM.lastPlayed,SourceObjList[BGM.lastPlayed].source
TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[BGM.nowPlay].source)
TASK.removeTask_code(task_fadeIn)
TASK.new(task_fadeIn,BGM.playing)
BGM.playing:play()
end
end
function BGM.stop(args)
args=args or""
TASK.removeTask_code(task_fadeIn)
if not args:sArg('-s')then
if BGM.nowPlay then
TASK.new(task_fadeOut,BGM.playing)
end
BGM.nowPlay,BGM.playing=nil
elseif BGM.playing then
BGM.playing:pause()
end
BGM.nowPlay,BGM.playing=nil
end
return BGM

View File

@@ -1,5 +1,5 @@
local abs=math.abs
local function hsv(h,s,v,a)
local function hsv(h,s,v,a)--Color type, Color amount, Light
if s<=0 then return v,v,v,a end
h=h*6
local c=v*s
@@ -19,33 +19,33 @@ local COLOR={
red= {hsv(0.00, 0.89, 0.91)},
fire= {hsv(0.04, 0.93, 0.94)},
orange= {hsv(0.09, 0.99, 0.96)},
yellow= {hsv(0.16, 0.82, 0.90)},
lime= {hsv(0.18, 0.89, 0.88)},
jade= {hsv(0.23, 1.00, 0.82)},
yellow= {hsv(0.15, 0.82, 0.90)},
lime= {hsv(0.20, 0.89, 0.88)},
jade= {hsv(0.25, 1.00, 0.82)},
green= {hsv(0.33, 1.00, 0.81)},
aqua= {hsv(0.48, 1.00, 0.74)},
aqua= {hsv(0.47, 1.00, 0.76)},
cyan= {hsv(0.53, 1.00, 0.88)},
navy= {hsv(0.56, 1.00, 1.00)},
sea= {hsv(0.61, 1.00, 1.00)},
blue= {hsv(0.64, 1.00, 0.95)},
violet= {hsv(0.73, 1.00, 0.91)},
violet= {hsv(0.74, 1.00, 0.91)},
purple= {hsv(0.80, 1.00, 0.81)},
magenta= {hsv(0.86, 1.00, 0.78)},
wine= {hsv(0.94, 0.96, 0.91)},
wine= {hsv(0.92, 0.98, 0.91)},
lRed= {hsv(0.00, 0.38, 0.93)},
lFire= {hsv(0.04, 0.45, 0.91)},
lOrange= {hsv(0.10, 0.53, 0.92)},
lYellow= {hsv(0.15, 0.61, 0.95)},
lLime= {hsv(0.19, 0.66, 0.92)},
lJade= {hsv(0.24, 0.56, 0.90)},
lYellow= {hsv(0.14, 0.61, 0.95)},
lLime= {hsv(0.20, 0.66, 0.92)},
lJade= {hsv(0.26, 0.56, 0.90)},
lGreen= {hsv(0.34, 0.49, 0.89)},
lAqua= {hsv(0.49, 0.59, 0.85)},
lAqua= {hsv(0.47, 0.59, 0.86)},
lCyan= {hsv(0.51, 0.77, 0.88)},
lNavy= {hsv(0.54, 0.80, 0.95)},
lSea= {hsv(0.56, 0.72, 0.97)},
lSea= {hsv(0.57, 0.72, 0.97)},
lBlue= {hsv(0.64, 0.44, 0.96)},
lViolet= {hsv(0.73, 0.47, 0.95)},
lViolet= {hsv(0.72, 0.47, 0.95)},
lPurple= {hsv(0.80, 0.62, 0.89)},
lMagenta= {hsv(0.86, 0.61, 0.89)},
lWine= {hsv(0.93, 0.57, 0.92)},
@@ -53,13 +53,13 @@ local COLOR={
dRed= {hsv(0.00, 0.80, 0.48)},
dFire= {hsv(0.04, 0.80, 0.34)},
dOrange= {hsv(0.07, 0.80, 0.39)},
dYellow= {hsv(0.11, 0.80, 0.37)},
dLime= {hsv(0.17, 0.80, 0.26)},
dJade= {hsv(0.31, 0.80, 0.27)},
dYellow= {hsv(0.12, 0.80, 0.37)},
dLime= {hsv(0.20, 0.80, 0.26)},
dJade= {hsv(0.29, 0.80, 0.27)},
dGreen= {hsv(0.33, 0.80, 0.26)},
dAqua= {hsv(0.47, 0.80, 0.23)},
dAqua= {hsv(0.46, 0.80, 0.24)},
dCyan= {hsv(0.50, 0.80, 0.30)},
dNavy= {hsv(0.59, 0.80, 0.42)},
dNavy= {hsv(0.58, 0.80, 0.42)},
dSea= {hsv(0.64, 0.80, 0.40)},
dBlue= {hsv(0.67, 0.80, 0.34)},
dViolet= {hsv(0.71, 0.80, 0.35)},
@@ -72,12 +72,17 @@ local COLOR={
gray= {hsv(0.02, 0.05, 0.65)},
lGray= {hsv(0.02, 0.06, 0.86)},
white= {hsv(0.01, 0.02, 0.99)},
xGray= {hsv(0.00, 0.00, 0.35,.8)},
lxGray= {hsv(0.00, 0.00, 0.62,.8)},
dxGray= {hsv(0.00, 0.00, 0.16,.8)},
}
for k,v in next,{
R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine',
lR='lRed',lF='lFire',lO='lOrange',lY='lYellow',lL='lLime',lJ='lJade',lG='lGreen',lA='lAqua',lC='lCyan',lN='lNavy',lS='lSea',lB='lBlue',lV='lViolet',lP='lPurple',lM='lMagenta',lW='lWine',
dR='dRed',dF='dFire',dO='dOrange',dY='dYellow',dL='dLime',dJ='dJade',dG='dGreen',dA='dAqua',dC='dCyan',dN='dNavy',dS='dSea',dB='dBlue',dV='dViolet',dP='dPurple',dM='dMagenta',dW='dWine',
D='black',dH='dGray',H='gray',lH='lGray',Z='white',
X='xGray',lX='lxGray',dX='dxGray',
--Remain letter: EIKQTUX
}do
COLOR[k]=COLOR[v]

View File

@@ -1,66 +1,76 @@
local fs=love.filesystem
local FILE={}
function FILE.load(name,mode)
function FILE.load(name,args)
if not args then args=''end
if fs.getInfo(name)then
local F=fs.newFile(name)
if F:open'r'then
local s=F:read()
F:close()
if mode=='luaon'or not mode and s:sub(1,6)=="return{"then
s=loadstring(s)
if s then
setfenv(s,{})
return s()
end
elseif mode=='json'or not mode and s:sub(1,1)=="["and s:sub(-1)=="]"or s:sub(1,1)=="{"and s:sub(-1)=="}"then
local res=JSON.decode(s)
if res then
return res
end
elseif mode=='string'or not mode then
return s
assert(F:open'r','open error')
local s=F:read()F:close()
local mode=
STRING.sArg(args,'-luaon')and'luaon'or
STRING.sArg(args,'-lua')and'lua'or
STRING.sArg(args,'-json')and'json'or
STRING.sArg(args,'-string')and'string'or
s:sub(1,6)=='return{'and'luaon'or
(s:sub(1,1)=='['and s:sub(-1)==']'or s:sub(1,1)=='{'and s:sub(-1)=='}')and'json'or
'string'
if mode=='luaon'then
local func,err_mes=loadstring(s)
if func then
setfenv(func,{})
local res=func()
return assert(res,'decode error')
else
MES.new("No file loading mode called "..tostring(mode))
error('decode error: '..err_mes)
end
elseif mode=='lua'then
local func,err_mes=loadstring(s)
if func then
local res=func()
return assert(res,'run error')
else
error('compile error: '..err_mes)
end
elseif mode=='json'then
local res=JSON.decode(s)
if res then
return res
end
error('decode error')
elseif mode=='string'then
return s
else
MES.new('error',name.." "..text.loadError)
error('unknown mode')
end
else
error('no file')
end
end
function FILE.save(data,name,mode)
if not mode then mode=""end
function FILE.save(data,name,args)
if not args then args=''end
if STRING.sArg(args,'-d')and fs.getInfo(name)then
error('duplicate')
end
if type(data)=='table'then
if mode:find'l'then
if STRING.sArg(args,'-luaon')then
data=TABLE.dump(data)
if not data then
MES.new('error',name.." "..text.saveError.."dump error")
return
error('encode error')
end
else
data=JSON.encode(data)
if not data then
MES.new('error',name.." "..text.saveError.."json error")
return
error('encode error')
end
end
else
data=tostring(data)
end
if mode:find'd'and fs.getInfo(name)then
MES.new('error',text.saveError_duplicate)
return
end
local F=fs.newFile(name)
F:open'w'
local success,mes=F:write(data)
F:flush()F:close()
if success then
return true
else
MES.new('error',text.saveError..(mes or"unknown error"))
MES.traceback()
end
assert(F:open('w'),'open error')
F:write(data)F:flush()F:close()
end
function FILE.clear(path)
if fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory'then

View File

@@ -1,67 +1,60 @@
local gc=love.graphics
local set=gc.setFont
local fontCache={}
local currentFontSize
local fontFiles,fontCache={},{}
local defaultFont,defaultFallBack
local curFont=false--Current using font object
local FONT={}
function FONT.set(s)
if s~=currentFontSize then
if not fontCache[s]then
fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2)
end
set(fontCache[s])
currentFontSize=s
end
end
function FONT.get(s)
function FONT.setDefault(name)defaultFont=name end
function FONT.setFallback(name)defaultFallBack=name end
function FONT.rawget(s)
if not fontCache[s]then
fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2)
end
return fontCache[s]
end
function FONT.reset()
for s in next,fontCache do
fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2)
end
function FONT.rawset(s)
set(fontCache[s]or FONT.rawget(s))
end
function FONT.load(mainFont,secFont)
assert(love.filesystem.getInfo(mainFont),"Font file '"..mainFont.."' not exist!")
mainFont=love.filesystem.newFile(mainFont)
if secFont and love.filesystem.getInfo(secFont)then
secFont=love.filesystem.newFile(secFont)
else
secFont=false
end
function FONT.set(s)
if s~=currentFontSize then
if not fontCache[s]then
fontCache[s]=gc.setNewFont(mainFont,s,'light',gc.getDPIScale()*SCR.k*2)
if secFont then
fontCache[s]:setFallbacks(gc.setNewFont(secFont,s,'light',gc.getDPIScale()*SCR.k*2))
end
end
set(fontCache[s])
currentFontSize=s
end
end
function FONT.get(s)
if not fontCache[s]then
fontCache[s]=gc.setNewFont(mainFont,s,'light',gc.getDPIScale()*SCR.k*2)
if secFont then
fontCache[s]:setFallbacks(gc.setNewFont(secFont,s,'light',gc.getDPIScale()*SCR.k*2))
end
end
return fontCache[s]
end
function FONT.reset()
for s in next,fontCache do
fontCache[s]=gc.setNewFont(mainFont,s,'light',gc.getDPIScale()*SCR.k*2)
if secFont then
fontCache[s]:setFallbacks(gc.setNewFont(secFont,s,'light',gc.getDPIScale()*SCR.k*2))
end
end
function FONT.load(fonts)
for name,path in next,fonts do
assert(love.filesystem.getInfo(path),STRING.repD("Font file $1($2) not exist!",name,path))
fontFiles[name]=love.filesystem.newFile(path)
fontCache[name]={}
end
FONT.reset()
end
function FONT.get(size,name)
if not name then name=defaultFont end
local f=fontCache[name][size]
if not f then
f=gc.setNewFont(fontFiles[name],size,'light',gc.getDPIScale()*SCR.k*2)
if defaultFallBack and name~=defaultFallBack then
f:setFallbacks(FONT.get(size,defaultFallBack))
end
fontCache[name][size]=f
end
return f
end
function FONT.set(size,name)
if not name then name=defaultFont end
local f=fontCache[name][size]
if f~=curFont then
curFont=f or FONT.get(size,name)
set(curFont)
end
end
function FONT.reset()
for name,cache in next,fontCache do
if type(cache)=='table'then
for size in next,cache do
cache[size]=FONT.get(size,name)
end
else
fontCache[name]=FONT.rawget(name)
end
end
end
return FONT

View File

@@ -95,6 +95,7 @@ do--function GC.DO(L)
setLJ="setLineJoin",
print="print",
rawFT=function(...)FONT.rawset(...)end,
setFT=function(...)FONT.set(...)end,
mText=GC.mStr,
mDraw=GC.draw,

View File

@@ -2,7 +2,6 @@ local IMG={}
function IMG.init(list)
IMG.init=nil
local null=love.graphics.newCanvas(1,1)
setmetatable(IMG,{__index=function(self,name)
if type(list[name])=='table'then
self[name]={}
@@ -13,7 +12,7 @@ function IMG.init(list)
self[name]=love.graphics.newImage(list[name])
else
LOG("No IMG: "..name)
self[name]=null
self[name]=PAPER
end
return self[name]
end})

View File

@@ -1,4 +1,4 @@
NONE={}function NULL()end
NONE={}function NULL()end PAPER=love.graphics.newCanvas(1,1)
EDITING=""
LOADED=false
@@ -37,7 +37,6 @@ REQUIRE= require'Zframework.require'
TASK= require'Zframework.task'
WS= require'Zframework.websocket'
LANG= require'Zframework.languages'
THEME= require'Zframework.theme'
--Love-based modules (basic)
FILE= require'Zframework.file'
@@ -61,6 +60,7 @@ BGM= require'Zframework.bgm'
VOC= require'Zframework.voice'
local ms,kb=love.mouse,love.keyboard
local KBisDown=kb.isDown
local gc=love.graphics
local gc_push,gc_pop,gc_clear,gc_discard=gc.push,gc.pop,gc.clear,gc.discard
@@ -72,11 +72,24 @@ local WIDGET,SCR,SCN=WIDGET,SCR,SCN
local xOy=SCR.xOy
local ITP=xOy.inverseTransformPoint
local mx,my,mouseShow=-20,-20,false
local max,min=math.max,math.min
local devMode
local mx,my,mouseShow,cursorSpd=640,360,false,0
local jsState={}--map, joystickID->axisStates: {axisName->axisVal}
local errData={}--list, each error create {mes={errMes strings},scene=sceneNameStr}
local devMode
local function drawCursor(_,x,y)
gc_setColor(1,1,1)
gc_setLineWidth(2)
gc_circle(ms.isDown(1)and'fill'or'line',x,y,6)
end
local showPowerInfo=true
local showClickFX=true
local discardCanvas=false
local frameMul=100
local sleepInterval=1/60
local onQuit=NULL
local batteryImg=GC.DO{31,20,
{'fRect',1,0,26,2},
@@ -94,17 +107,16 @@ local function updatePowerInfo()
gc_clear(0,0,0,.25)
if state~='unknown'then
gc_setLineWidth(4)
local charging=state=='charging'
if state=='nobattery'then
gc_setColor(1,1,1)
gc_setLineWidth(2)
gc_line(74,SCR.safeX+5,100,22)
gc_line(74,5,100,22)
elseif pow then
if charging then gc_setColor(0,1,0)
elseif pow>50 then gc_setColor(1,1,1)
elseif pow>26 then gc_setColor(1,1,0)
elseif pow==26 then gc_setColor(.5,0,1)
else gc_setColor(1,0,0)
if state=='charging'then gc_setColor(0,1,0)
elseif pow>50 then gc_setColor(1,1,1)
elseif pow>26 then gc_setColor(1,1,0)
elseif pow==26 then gc_setColor(.5,0,1)
else gc_setColor(1,0,0)
end
gc.rectangle('fill',76,6,pow*.22,14)
if pow<100 then
@@ -127,36 +139,81 @@ local function updatePowerInfo()
end
-------------------------------------------------------------
local lastX,lastY=0,0--Last click pos
local function _updateMousePos(x,y,dx,dy)
if SCN.swapping then return end
dx,dy=dx/SCR.k,dy/SCR.k
if SCN.mouseMove then SCN.mouseMove(x,y,dx,dy)end
if ms.isDown(1)then
WIDGET.drag(x,y,dx,dy)
else
WIDGET.cursorMove(x,y)
end
end
local function _triggerMouseDown(x,y,k)
if devMode==1 then
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
x,y,
x-lastX,y-lastY,
math.floor(x/10)*10,math.floor(y/10)*10,
math.floor((x-lastX)/10)*10,math.floor((y-lastY)/10)*10
))
end
if SCN.swapping then return end
if SCN.mouseDown then SCN.mouseDown(x,y,k)end
WIDGET.press(x,y,k)
lastX,lastY=x,y
if showClickFX then SYSFX.newTap(3,x,y)end
end
local function mouse_update(dt)
if not KBisDown('lctrl','rctrl')and KBisDown('up','down','left','right')then
local dx,dy=0,0
if KBisDown('up')then dy=dy-cursorSpd end
if KBisDown('down')then dy=dy+cursorSpd end
if KBisDown('left')then dx=dx-cursorSpd end
if KBisDown('right')then dx=dx+cursorSpd end
mx=max(min(mx+dx,1280),0)
my=max(min(my+dy,720),0)
if my==0 or my==720 then
WIDGET.sel=false
WIDGET.drag(0,0,0,-dy)
end
_updateMousePos(mx,my,dx,dy)
cursorSpd=min(cursorSpd+dt*26,12.6)
else
cursorSpd=6
end
end
local function gp_update(js,dt)
local sx,sy=js._jsObj:getGamepadAxis('leftx'),js._jsObj:getGamepadAxis('lefty')
if math.abs(sx)>.1 or math.abs(sy)>.1 then
local dx,dy=0,0
if sy<-.1 then dy=dy+2*sy*cursorSpd end
if sy>.1 then dy=dy+2*sy*cursorSpd end
if sx<-.1 then dx=dx+2*sx*cursorSpd end
if sx>.1 then dx=dx+2*sx*cursorSpd end
mx=max(min(mx+dx,1280),0)
my=max(min(my+dy,720),0)
if my==0 or my==720 then
WIDGET.sel=false
WIDGET.drag(0,0,0,-dy)
end
_updateMousePos(mx,my,dx,dy)
cursorSpd=min(cursorSpd+dt*26,12.6)
else
cursorSpd=6
end
end
function love.mousepressed(x,y,k,touch)
if touch then return end
mouseShow=true
mx,my=ITP(xOy,x,y)
if devMode==1 then
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
mx,my,
mx-lastX,my-lastY,
math.floor(mx/10)*10,math.floor(my/10)*10,
math.floor((mx-lastX)/10)*10,math.floor((my-lastY)/10)*10
))
end
if SCN.swapping then return end
if SCN.mouseDown then SCN.mouseDown(mx,my,k)end
WIDGET.press(mx,my,k)
lastX,lastY=mx,my
if SETTING.clickFX then SYSFX.newTap(3,mx,my)end
_triggerMouseDown(mx,my,k)
end
function love.mousemoved(x,y,dx,dy,touch)
if touch then return end
mouseShow=true
mx,my=ITP(xOy,x,y)
if SCN.swapping then return end
dx,dy=dx/SCR.k,dy/SCR.k
if SCN.mouseMove then SCN.mouseMove(mx,my,dx,dy)end
if ms.isDown(1)then
WIDGET.drag(mx,my,dx/SCR.k,dy/SCR.k)
else
WIDGET.cursorMove(mx,my)
end
_updateMousePos(mx,my,dx,dy)
end
function love.mousereleased(x,y,k,touch)
if touch or SCN.swapping then return end
@@ -191,13 +248,13 @@ function love.touchpressed(id,x,y)
x,y=ITP(xOy,x,y)
lastX,lastY=x,y
WIDGET.cursorMove(x,y)
if SCN.touchDown then SCN.touchDown(x,y)end
if SCN.touchDown then SCN.touchDown(x,y,id)end
if kb.hasTextInput()then kb.setTextInput(false)end
end
function love.touchmoved(_,x,y,dx,dy)
function love.touchmoved(id,x,y,dx,dy)
if SCN.swapping then return end
x,y=ITP(xOy,x,y)
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k,id)end
WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k)
end
function love.touchreleased(id,x,y)
@@ -210,40 +267,40 @@ function love.touchreleased(id,x,y)
WIDGET.unFocus()
SCN.mainTouchID=false
end
if SCN.touchUp then SCN.touchUp(x,y)end
if SCN.touchUp then SCN.touchUp(x,y,id)end
if(x-lastX)^2+(y-lastY)^2<62 then
if SCN.touchClick then SCN.touchClick(x,y)end
if SETTING.clickFX then SYSFX.newTap(3,x,y)end
if showClickFX then SYSFX.newTap(3,x,y)end
end
end
local fnKey={NULL,NULL,NULL,NULL,NULL,NULL,NULL}
local function noDevkeyPressed(key)
if key=="f1"then fnKey[1]()
elseif key=="f2"then fnKey[2]()
elseif key=="f3"then fnKey[3]()
elseif key=="f4"then fnKey[4]()
elseif key=="f5"then fnKey[5]()
elseif key=="f6"then fnKey[6]()
elseif key=="f7"then fnKey[7]()
elseif key=="f8"then devMode=nil MES.new('info',"DEBUG OFF",.2)
elseif key=="f9"then devMode=1 MES.new('info',"DEBUG 1")
elseif key=="f10"then devMode=2 MES.new('info',"DEBUG 2")
elseif key=="f11"then devMode=3 MES.new('info',"DEBUG 3")
elseif key=="f12"then devMode=4 MES.new('info',"DEBUG 4")
if key=='f1'then fnKey[1]()
elseif key=='f2'then fnKey[2]()
elseif key=='f3'then fnKey[3]()
elseif key=='f4'then fnKey[4]()
elseif key=='f5'then fnKey[5]()
elseif key=='f6'then fnKey[6]()
elseif key=='f7'then fnKey[7]()
elseif key=='f8'then devMode=nil MES.new('info',"DEBUG OFF",.2)
elseif key=='f9'then devMode=1 MES.new('info',"DEBUG 1")
elseif key=='f10'then devMode=2 MES.new('info',"DEBUG 2")
elseif key=='f11'then devMode=3 MES.new('info',"DEBUG 3")
elseif key=='f12'then devMode=4 MES.new('info',"DEBUG 4")
elseif devMode==2 then
local W=WIDGET.sel
if W then
if key=="left"then W.x=W.x-10
elseif key=="right"then W.x=W.x+10
elseif key=="up"then W.y=W.y-10
elseif key=="down"then W.y=W.y+10
elseif key==","then W.w=W.w-10
elseif key=="."then W.w=W.w+10
elseif key=="/"then W.h=W.h-10
elseif key=="'"then W.h=W.h+10
elseif key=="["then W.font=W.font-5
elseif key=="]"then W.font=W.font+5
if key=='left'then W.x=W.x-10
elseif key=='right'then W.x=W.x+10
elseif key=='up'then W.y=W.y-10
elseif key=='down'then W.y=W.y+10
elseif key==','then W.w=W.w-10
elseif key=='.'then W.w=W.w+10
elseif key=='/'then W.h=W.h-10
elseif key=='\''then W.h=W.h+10
elseif key=='['then W.font=W.font-5
elseif key==']'then W.font=W.font+5
else return true
end
else
@@ -257,22 +314,34 @@ function love.keypressed(key,_,isRep)
mouseShow=false
if devMode and not noDevkeyPressed(key)then
return
elseif key=="f8"then
elseif key=='f8'then
devMode=1
MES.new('info',"DEBUG ON",.2)
elseif key=="f11"then
elseif key=='f11'then
SETTING.fullscreen=not SETTING.fullscreen
applyFullscreen()
applySettings()
saveSettings()
elseif not SCN.swapping then
if SCN.keyDown then
if EDITING==""then
SCN.keyDown(key,isRep)
if EDITING==""and(not SCN.keyDown or SCN.keyDown(key,isRep))then
local W=WIDGET.sel
if key=='escape'and not isRep then
SCN.back()
elseif key=='up'or key=='down'or key=='left'or key=='right'then
mouseShow=true
if KBisDown('lctrl','rctrl')then
if W and W.arrowKey then W:arrowKey(key)end
end
elseif key=='space'or key=='return'then
mouseShow=true
if not isRep then
if showClickFX then SYSFX.newTap(3,mx,my)end
_triggerMouseDown(mx,my,1)
end
else
if W and W.keypress then
W:keypress(key)
end
end
elseif key=="escape"and not isRep then
SCN.back()
else
WIDGET.keyPressed(key,isRep)
end
end
end
@@ -308,35 +377,38 @@ local dPadToKey={
back='escape',
}
function love.joystickadded(JS)
jsState[JS:getID()]={
_loveJSObj=JS,
table.insert(jsState,{
_id=JS:getID(),
_jsObj=JS,
leftx=0,lefty=0,
rightx=0,righty=0,
triggerleft=0,triggerright=0
}
})
MES.new('info',"Joystick added")
end
function love.joystickremoved(JS)
local js=jsState[JS:getID()]
if js then
for i=1,#gamePadKeys do
if JS:isGamepadDown(gamePadKeys[i])then
love.gamepadreleased(JS,gamePadKeys[i])
for i=1,#jsState do
if jsState[i]._jsObj==JS then
for j=1,#gamePadKeys do
if JS:isGamepadDown(gamePadKeys[j])then
love.gamepadreleased(JS,gamePadKeys[j])
end
end
love.gamepadaxis(JS,'leftx',0)
love.gamepadaxis(JS,'lefty',0)
love.gamepadaxis(JS,'rightx',0)
love.gamepadaxis(JS,'righty',0)
love.gamepadaxis(JS,'triggerleft',-1)
love.gamepadaxis(JS,'triggerright',-1)
MES.new('info',"Joystick removed")
table.remove(jsState,i)
break
end
love.gamepadaxis(JS,'leftx',0)
love.gamepadaxis(JS,'lefty',0)
love.gamepadaxis(JS,'rightx',0)
love.gamepadaxis(JS,'righty',0)
love.gamepadaxis(JS,'triggerleft',-1)
love.gamepadaxis(JS,'triggerright',-1)
jsState[JS:getID()]=nil
MES.new('info',"Joystick removed")
end
end
function love.gamepadaxis(JS,axis,val)
local js=jsState[JS:getID()]
if js then
if jsState[1]and JS==jsState[1]._jsObj then
local js=jsState[1]
if axis=='leftx'or axis=='lefty'or axis=='rightx'or axis=='righty'then
local newVal=--range: [0,1]
val>.4 and 1 or
@@ -356,7 +428,7 @@ function love.gamepadaxis(JS,axis,val)
js[axis]=newVal
end
elseif axis=='triggerleft'or axis=='triggerright'then
local newVal=val>-.3 and 1 or 0--range: [-1,1]
local newVal=val>.3 and 1 or 0--range: [0,1]
if newVal~=js[axis]then
if newVal==1 then
love.gamepadpressed(JS,jsAxisEventName[axis])
@@ -368,13 +440,36 @@ function love.gamepadaxis(JS,axis,val)
end
end
end
function love.gamepadpressed(_,i)
function love.gamepadpressed(_,key)
mouseShow=false
if SCN.swapping then return end
if SCN.gamepadDown then SCN.gamepadDown(i)
elseif SCN.keyDown then SCN.keyDown(dPadToKey[i]or i)
elseif i=="back"then SCN.back()
else WIDGET.gamepadPressed(dPadToKey[i]or i)
if not SCN.swapping then
local cursorCtrl
if SCN.gamepadDown then
cursorCtrl=SCN.gamepadDown(key)
elseif SCN.keyDown then
cursorCtrl=SCN.keyDown(dPadToKey[key]or key)
else
cursorCtrl=true
end
if cursorCtrl then
key=dPadToKey[key]or key
mouseShow=true
local W=WIDGET.sel
if key=='back'then
SCN.back()
elseif key=='up'or key=='down'or key=='left'or key=='right'then
mouseShow=true
if W and W.arrowKey then W:arrowKey(key)end
elseif key=='return'then
mouseShow=true
if showClickFX then SYSFX.newTap(3,mx,my)end
_triggerMouseDown(mx,my,1)
else
if W and W.keypress then
W:keypress(key)
end
end
end
end
end
function love.gamepadreleased(_,i)
@@ -396,14 +491,16 @@ function love.lowmemory()
MES.new('check',"[auto GC] low MEM 设备内存过低")
end
end
local onResize=NULL
function love.resize(w,h)
if SCR.w==w and SCR.h==h then return end
SCR.resize(w,h)
if BG.resize then BG.resize(w,h)end
if SCN.resize then SCN.resize(w,h)end
WIDGET.resize(w,h)
FONT.reset()
SHADER.warning:send('w',w*SCR.dpi)
onResize(w,h)
end
local onFocus=NULL
@@ -514,7 +611,7 @@ local devColor={
}
local WS=WS
local WSnames={'app','user','play','stream','chat','manage'}
local wsBottomImage do
local wsImg={}do
local L={78,18,
{'clear',1,1,1,0},
{'setCL',1,1,1,.3},
@@ -524,32 +621,27 @@ local wsBottomImage do
table.insert(L,{'setCL',1,1,1,i*.005})
table.insert(L,{'fRect',i,0,1,18})
end
wsBottomImage=GC.DO(L)
wsImg.bottom=GC.DO(L)
wsImg.dead=GC.DO{20,20,
{'rawFT',20},
{'setCL',1,.3,.3},
{'mText',"X",11,-1},
}
wsImg.connecting=GC.DO{20,20,
{'rawFT',20},
{'setLW',3},
{'mText',"C",11,-1},
}
wsImg.running=GC.DO{20,20,
{'rawFT',20},
{'setCL',.5,1,0},
{'mText',"R",11,-1},
}
end
local ws_deadImg=GC.DO{20,20,
{'setFT',20},
{'setCL',1,.3,.3},
{'mText',"X",11,-1},
}
local ws_connectingImg=GC.DO{20,20,
{'setFT',20},
{'setLW',3},
{'mText',"C",11,-1},
}
local ws_runningImg=GC.DO{20,20,
{'setFT',20},
{'setCL',.5,1,0},
{'mText',"R",11,-1},
}
local function drawCursor(_,x,y)
gc_setColor(1,1,1)
gc_setLineWidth(2)
gc_circle(ms.isDown(1)and'fill'or'line',x,y,6)
end
local function showPowerInfo()return true end
local onQuit=NULL
local debugInfos={
{"Cache",gcinfo},
}
function love.run()
local love=love
@@ -560,12 +652,11 @@ function love.run()
local TASK_update=TASK.update
local SYSFX_update,SYSFX_draw=SYSFX.update,SYSFX.draw
local WIDGET_update,WIDGET_draw=WIDGET.update,WIDGET.draw
local STEP,WAIT=love.timer.step,love.timer.sleep
local FPS,MINI=love.timer.getFPS,love.window.isMinimized
local PUMP,POLL=love.event.pump,love.event.poll
local timer,SETTING,VERSION=love.timer.getTime,SETTING,VERSION
local timer,VERSION=love.timer.getTime,VERSION
local frameTimeList={}
local lastFrame=timer()
@@ -599,6 +690,8 @@ function love.run()
--UPDATE
STEP()
if mouseShow then mouse_update(dt)end
if next(jsState)then gp_update(jsState[1],dt)end
VOC.update()
BG.update(dt)
TEXT_update(dt)
@@ -612,11 +705,10 @@ function love.run()
--DRAW
if not MINI()then
FCT=FCT+SETTING.frameMul
FCT=FCT+frameMul
if FCT>=100 then
FCT=FCT-100
local safeX=SCR.safeX
gc_replaceTransform(SCR.origin)
gc_setColor(1,1,1)
BG.draw()
@@ -627,16 +719,14 @@ function love.run()
TEXT_draw()
--Draw cursor
if mouseShow then
drawCursor(time,mx,my)
end
if mouseShow then drawCursor(time,mx,my)end
gc_replaceTransform(SCR.xOy_ul)
MES_draw()
gc_replaceTransform(SCR.origin)
--Draw power info.
if showPowerInfo()then
if showPowerInfo then
gc_setColor(1,1,1)
gc_draw(infoCanvas,safeX,0,0,SCR.k)
gc_draw(infoCanvas,SCR.safeX,0,0,SCR.k)
end
--Draw scene swapping animation
@@ -647,10 +737,12 @@ function love.run()
end
gc_replaceTransform(SCR.xOy_d)
--Draw Version string
gc_setColor(.8,.8,.8,.4)
gc_setColor(.9,.9,.9,.42)
FONT.set(20)
mStr(VERSION.string,0,-30)
gc_replaceTransform(SCR.xOy_dl)
local safeX=SCR.safeX/SCR.k
--Draw FPS
FONT.set(15)
gc_setColor(1,1,1)
@@ -658,11 +750,14 @@ function love.run()
--Debug info.
if devMode then
--Left-down infos
--Debug infos at left-down
gc_setColor(devColor[devMode])
gc_print("MEM "..gcinfo(),safeX+5,-40)
gc_print("Tasks "..TASK.getCount(),safeX+5,-60)
gc_print("Voices "..VOC.getQueueCount(),safeX+5,-80)
--Text infos
for i=1,#debugInfos do
gc_print(debugInfos[i][1],safeX+5,-20-20*i)
gc_print(debugInfos[i][2](),safeX+62.6,-20-20*i)
end
--Update & draw frame time
table.insert(frameTimeList,1,dt)table.remove(frameTimeList,126)
@@ -690,14 +785,14 @@ function love.run()
for i=1,6 do
local status=WS.status(WSnames[i])
gc_setColor(1,1,1)
gc.draw(wsBottomImage,-79,20*i-139)
gc.draw(wsImg.bottom,-79,20*i-139)
if status=='dead'then
gc_draw(ws_deadImg,-20,20*i-140)
gc_draw(wsImg.dead,-20,20*i-140)
elseif status=='connecting'then
gc_setColor(1,1,1,.5+.3*math.sin(time*6.26))
gc_draw(ws_connectingImg,-20,20*i-140)
gc_draw(wsImg.connecting,-20,20*i-140)
elseif status=='running'then
gc_draw(ws_runningImg,-20,20*i-140)
gc_draw(wsImg.running,-20,20*i-140)
end
local t1,t2,t3=WS.getTimers(WSnames[i])
gc_setColor(.9,.9,.9,t1)gc.rectangle('fill',-60,20*i-122,-16,-16)
@@ -708,13 +803,13 @@ function love.run()
gc_present()
--SPEED UPUPUP!
if SETTING.cleanCanvas then gc_discard()end
if discardCanvas then gc_discard()end
end
end
--Fresh power info.
if time-lastFreshPow>2.6 then
if showPowerInfo()then
if showPowerInfo then
updatePowerInfo()
lastFreshPow=time
end
@@ -732,31 +827,59 @@ function love.run()
end
end
--Keep 60fps
_=timer()-lastFrame
if _<.0162 then WAIT(.0162-_)end
while timer()-lastFrame<1/60 do end
if _<sleepInterval*.9626 then WAIT(sleepInterval*.9626-_)end
while timer()-lastFrame<sleepInterval do end
end
end
local Z={}
Z.js=jsState
Z.errData=errData
function Z.getJsState()return jsState end
function Z.getErr(i)
if i=='#'then
return errData[#errData]
elseif i then
return errData[i]
else
return errData
end
end
function Z.setIfPowerInfo(func)showPowerInfo=func end
function Z.setPowerInfo(bool)showPowerInfo=bool end
function Z.setCleanCanvas(bool)discardCanvas=bool end
function Z.setFrameMul(n)frameMul=n end
function Z.setMaxFPS(fps)sleepInterval=1/fps end
function Z.setClickFX(bool)showClickFX=bool end
--[Warning] Color and line width is uncertain value, set it in the function.
function Z.setCursor(func)drawCursor=func end
--Change F1~F7 events of devmode (F8 mode)
function Z.setOnFnKeys(list)
assert(type(list)=='table')
for i=1,7 do fnKey[i]=type(list[i])=='function'and list[i]or NULL end
assert(type(list)=='table',"Z.setOnFnKeys(list): list must be a table")
for i=1,7 do fnKey[i]=assert(type(list[i])=='function'and list[i])end
end
function Z.setOnFocus(func)onFocus=type(func)=='function'and func or NULL end
function Z.setDebugInfo(list)
assert(type(list)=='table',"Z.setDebugInfo(list): list must be a table")
for i=1,#list do
assert(type(list[i][1])=='string',"Z.setDebugInfo(list): list[i][1] must be a string")
assert(type(list[i][2])=='function',"Z.setDebugInfo(list): list[i][2] must be a function")
end
debugInfos=list
end
function Z.setOnQuit(func)onQuit=type(func)=='function'and func or NULL end
function Z.setOnFocus(func)
onFocus=assert(type(func)=='function'and func,"Z.setOnFocus(func): func must be a function")
end
function Z.setOnResize(func)
onResize=assert(type(func)=='function'and func,"Z.setOnResize(func): func must be a function")
end
function Z.setOnQuit(func)
onQuit=assert(type(func)=='function'and func,"Z.setOnQuit(func): func must be a function")
end
return Z

View File

@@ -20,4 +20,18 @@ function MATH.coin(a,b)
end
end
function MATH.interval(v,low,high)
if v<=low then
return low
elseif v>=high then
return high
else
return v
end
end
function MATH.expApproach(a,b,k)
return b+(a-b)*2.718281828459045^-k
end
return MATH

View File

@@ -140,11 +140,11 @@ function profile.switch()
switch=not switch
if not switch then
profile.stop()
love.system.setClipboardText(PROFILE.report())
PROFILE.reset()
love.system.setClipboardText(profile.report())
profile.reset()
return false
else
PROFILE.start()
profile.start()
return true
end
end

View File

@@ -15,6 +15,8 @@ local SCN={
draw=false, --Swap draw func
},
stack={},--Scene stack
prev=false,
args={},--Arguments from previous scene
scenes=scenes,
@@ -52,14 +54,15 @@ function SCN.swapUpdate(dt)
S.time=S.time-dt
if S.time<S.changeTime and S.time+dt>=S.changeTime then
--Scene swapped this frame
SCN.init(S.tar,SCN.cur)
SCN.prev=SCN.cur
SCN.init(S.tar)
SCN.mainTouchID=nil
end
if S.time<0 then
SCN.swapping=false
end
end
function SCN.init(s,org)
function SCN.init(s)
love.keyboard.setTextInput(false)
local S=scenes[s]
@@ -89,7 +92,7 @@ function SCN.init(s,org)
SCN.update=S.update
SCN.draw=S.draw
if S.sceneInit then
S.sceneInit(org)
S.sceneInit()
end
end
function SCN.push(tar,style)
@@ -165,11 +168,12 @@ local swap={
end
},
}--Scene swapping animations
function SCN.swapTo(tar,style)--Parallel scene swapping, cannot back
function SCN.swapTo(tar,style,...)--Parallel scene swapping, cannot back
if scenes[tar]then
if not SCN.swapping and tar~=SCN.cur then
style=style or'fade'
SCN.swapping=true
SCN.args={...}
local S=SCN.stat
S.tar,S.style=tar,style
S.time=swap[style].duration
@@ -180,15 +184,15 @@ function SCN.swapTo(tar,style)--Parallel scene swapping, cannot back
MES.new('warn',"No Scene: "..tar)
end
end
function SCN.go(tar,style)--Normal scene swapping, can back
function SCN.go(tar,style,...)--Normal scene swapping, can back
if scenes[tar]then
SCN.push()
SCN.swapTo(tar,style)
SCN.swapTo(tar,style,...)
else
MES.new('warn',"No Scene: "..tar)
end
end
function SCN.back()
function SCN.back(...)
if SCN.swapping then return end
--Leave scene
@@ -199,7 +203,7 @@ function SCN.back()
--Poll&Back to previous Scene
local m=#SCN.stack
if m>0 then
SCN.swapTo(SCN.stack[m-1],SCN.stack[m])
SCN.swapTo(SCN.stack[m-1],SCN.stack[m],...)
SCN.stack[m],SCN.stack[m-1]=nil
end
end

View File

@@ -1,5 +1,6 @@
local type,rem=type,table.remove
local int,rnd=math.floor,math.random
local interval=MATH.interval
local sfxList={}
local packSetting={}
@@ -42,16 +43,28 @@ function SFX.init(list)
end
function SFX.load(path)
local c=0
local missing=0
for i=1,#sfxList do
local fullPath=path..sfxList[i]..'.ogg'
if love.filesystem.getInfo(fullPath)then
if Sources[sfxList[i]]then
for j=1,#Sources[sfxList[i]]do
Sources[sfxList[i]][j]:release()
end
end
Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')}
c=c+1
else
LOG("No SFX: "..sfxList[i]..'.ogg',.1)
missing=missing+1
end
end
LOG(c.."/"..#sfxList.." SFX files loaded")
LOG(missing.." SFX files missing")
if missing>0 then
MES.new('info',missing.." SFX files missing")
end
collectgarbage()
end
function SFX.loadSample(pack)
assert(type(pack)=='table',"Usage: SFX.loadsample([table])")
@@ -128,7 +141,7 @@ local function _play(name,vol,pos,pitch)
S=S[n]--AU_SRC
if S:getChannelCount()==1 then
if pos then
pos=pos*stereo
pos=interval(pos,-1,1)*stereo
S:setPosition(pos,1-pos^2,0)
else
S:setPosition(0,0,0)

View File

@@ -2,9 +2,25 @@ local data=love.data
local STRING={}
local assert,tostring,tonumber=assert,tostring,tonumber
local int,format=math.floor,string.format
local find,sub,upper=string.find,string.sub,string.upper
local find,sub,gsub,upper=string.find,string.sub,string.gsub,string.upper
local char,byte=string.char,string.byte
--"Replace dollars", replace all $n with ...
function STRING.repD(str,...)
local l={...}
for i=#l,1,-1 do
str=gsub(str,'$'..i,l[i])
end
return str
end
--"Scan arg", scan if str has the arg (format of str is like "-json -q", arg is like "-q")
function STRING.sArg(str,switch)
if find(str.." ",switch.." ")then
return true
end
end
do--function STRING.shiftChar(c)
local shiftMap={
['1']='!',['2']='@',['3']='#',['4']='$',['5']='%',
@@ -61,11 +77,11 @@ end
function STRING.time(t)
if t<60 then
return format("%.3f\"",t)
return format("%.3f",t)
elseif t<3600 then
return format("%d'%05.2f\"",int(t/60),int(t%60*100)/100)
return format("%d%05.2f",int(t/60),int(t%60*100)/100)
else
return format("%d:%.2d'%05.2f\"",int(t/3600),int(t/60%60),int(t%60*100)/100)
return format("%d:%.2d%05.2f",int(t/3600),int(t/60%60),int(t%60*100)/100)
end
end
@@ -153,6 +169,25 @@ function STRING.vcsDecrypt(text,key)
end
return result..buffer
end
function STRING.digezt(text)--Not powerful hash, just protect the original text
local out={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
local seed=26
for i=1,#text do
local c=byte(text,i)
seed=(seed+c)%26
c=c+seed
local pos=c*i%16
local step=(c+i)%4+1
local times=2+(c%6)
for _=1,times do
out[pos+1]=(out[pos+1]+c)%256
pos=(pos+step)%16
end
end
local result=""
for i=1,16 do result=result..char(out[i])end
return result
end
function STRING.readLine(str)
local p=str:find("\n")
@@ -162,6 +197,9 @@ function STRING.readLine(str)
return str,""
end
end
function STRING.readChars(str,n)
return sub(str,1,n),sub(str,n+1)
end
function STRING.packBin(s)
return data.encode('string','base64',data.compress('string','zlib',s))

View File

@@ -9,11 +9,11 @@ return function(y,key1,key2)
trigDist=min(trigDist,0)-(-y)^1.2
end
while trigDist>=1 do
love.keypressed(key1 or"up")
love.keypressed(key1 or'up')
trigDist=trigDist-1
end
while trigDist<=-1 do
love.keypressed(key2 or"down")
love.keypressed(key2 or'down')
trigDist=trigDist+1
end
end

View File

@@ -13,13 +13,13 @@ local kb=love.keyboard
local timer=love.timer.getTime
local next=next
local int,ceil,abs=math.floor,math.ceil,math.abs
local int,ceil=math.floor,math.ceil
local max,min=math.max,math.min
local sub,ins,rem=string.sub,table.insert,table.remove
local mDraw,mDraw_X,mDraw_Y=GC.draw,GC.simpX,GC.simpY
local xOy=SCR.xOy
local FONT=FONT
local mStr=GC.mStr
local approach=MATH.expApproach
local downArrowIcon=GC.DO{40,25,{'fPoly',0,0,20,25,40,0}}
local upArrowIcon=GC.DO{40,25,{'fPoly',0,25,20,0,40,25}}
@@ -29,7 +29,7 @@ local clearIcon=GC.DO{40,40,
{'fRect',11,14,18,21},
}
local sureIcon=GC.DO{40,40,
{'setFT',35},
{'rawFT',35},
{'mText',"?",20,0},
}
local smallerThen=GC.DO{20,20,
@@ -46,7 +46,12 @@ local function _rectangleStencil()
gc.rectangle('fill',1,1,STW-2,STH-2)
end
local onChange=NULL
local WIDGET={}
function WIDGET.setOnChange(func)onChange=assert(type(func)=='function'and func,"WIDGET.setOnChange(func): func must be a function")end
local widgetMetatable={
__tostring=function(self)
return self:getInfo()
@@ -73,24 +78,28 @@ function text:draw()
if self.alpha>0 then
local c=self.color
gc_setColor(c[1],c[2],c[3],self.alpha)
local w=self.obj:getWidth()
local k=min(self.lim/self.obj:getWidth(),1)
if self.align=='M'then
mDraw_X(self.obj,self.x,self.y)
gc_draw(self.obj,self.x,self.y,nil,k,1,w*.5,0)
elseif self.align=='L'then
gc_draw(self.obj,self.x,self.y)
gc_draw(self.obj,self.x,self.y,nil,k,1)
elseif self.align=='R'then
gc_draw(self.obj,self.x-self.obj:getWidth(),self.y)
gc_draw(self.obj,self.x,self.y,nil,k,1,w,0)
end
end
end
function WIDGET.newText(D)--name,x,y[,fText][,color][,font=30][,align='M'][,hideF][,hide]
function WIDGET.newText(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,align='M'][,hideF][,hide]
local _={
name= D.name or"_",
x= D.x,
y= D.y,
lim= D.lim or 1e99,
fText=D.fText,
color=D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30,
fType=D.fType,
align=D.align or'M',
hideF=D.hideF,
}
@@ -139,7 +148,7 @@ function button:reset()
end
function button:setObject(obj)
if type(obj)=='string'or type(obj)=='number'then
self.obj=gc.newText(FONT.get(self.font),obj)
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
elseif obj then
self.obj=obj
end
@@ -148,9 +157,9 @@ function button:isAbove(x,y)
local ATV=self.ATV
return
x>self.x-ATV and
y>self.y-ATV and
y>self.y and
x<self.x+self.w+2*ATV and
y<self.y+self.h+2*ATV
y<self.y+self.h
end
function button:getCenter()
return self.x+self.w*.5,self.y+self.h*.5
@@ -171,45 +180,49 @@ function button:draw()
--Button
gc_setColor(.15+r*.7,.15+g*.7,.15+b*.7,.9)
gc_rectangle('fill',x-ATV,y-ATV,w+2*ATV,h+2*ATV,3)
gc_rectangle('fill',x-ATV,y,w+2*ATV,h,4)
gc_setLineWidth(2)
gc_setColor(.3+r*.7,.3+g*.7,.3+b*.7)
gc_rectangle('line',x-ATV,y,w+2*ATV,h,5)
if ATV>0 then
gc_setLineWidth(2)
gc_setColor(.97,.97,.97,ATV*.125)
gc_rectangle('line',x-ATV+2,y-ATV+2,w+2*ATV-4,h+2*ATV-4,3)
gc_rectangle('line',x-ATV,y,w+2*ATV,h,3)
end
--Drawable
local obj=self.obj
local y0=y+h*.5-ATV*.5
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
local y0=y+h*.5
gc_setColor(1,1,1,.2+ATV*.05)
if self.align=='M'then
local x0=x+w*.5
mDraw(obj,x0-1,y0-1)
mDraw(obj,x0-1,y0+1)
mDraw(obj,x0+1,y0-1)
mDraw(obj,x0+1,y0+1)
local kx=obj:type()=='Text'and min(w/ox/2,1)or 1
gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy)
gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy)
gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy)
gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy)
gc_setColor(r*.55,g*.55,b*.55)
mDraw(obj,x0,y0)
gc_draw(obj,x0,y0,nil,kx,1,ox,oy)
elseif self.align=='L'then
local edge=self.edge
mDraw_Y(obj,x+edge-1,y0-1)
mDraw_Y(obj,x+edge-1,y0+1)
mDraw_Y(obj,x+edge+1,y0-1)
mDraw_Y(obj,x+edge+1,y0+1)
gc_draw(obj,x+edge-1,y0-1-oy)
gc_draw(obj,x+edge-1,y0+1-oy)
gc_draw(obj,x+edge+1,y0-1-oy)
gc_draw(obj,x+edge+1,y0+1-oy)
gc_setColor(r*.55,g*.55,b*.55)
mDraw_Y(obj,x+edge,y0)
gc_draw(obj,x+edge,y0-oy)
elseif self.align=='R'then
local x0=x+w-self.edge-obj:getWidth()
mDraw_Y(obj,x0-1,y0-1)
mDraw_Y(obj,x0-1,y0+1)
mDraw_Y(obj,x0+1,y0-1)
mDraw_Y(obj,x0+1,y0+1)
local x0=x+w-self.edge-ox*2
gc_draw(obj,x0-1,y0-1-oy)
gc_draw(obj,x0-1,y0+1-oy)
gc_draw(obj,x0+1,y0-1-oy)
gc_draw(obj,x0+1,y0+1-oy)
gc_setColor(r*.55,g*.55,b*.55)
mDraw_Y(obj,x0,y0)
gc_draw(obj,x0,y0-oy)
end
end
function button:getInfo()
return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font)
return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType)
end
function button:press(_,_,k)
self.code(k)
@@ -217,15 +230,15 @@ function button:press(_,_,k)
SYSFX.newRectRipple(
6,
self.x-ATV,
self.y-ATV-WIDGET.scrollPos,
self.y-WIDGET.scrollPos,
self.w+2*ATV,
self.h+2*ATV
self.h
)
if self.sound then
SFX.play('button')
SFX.play(self.sound)
end
end
function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,sound=true][,align='M'][,edge=0],code[,hideF][,hide]
function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,fType][,sound][,align='M'][,edge=0][,code][,hideF][,hide]
if not D.h then D.h=D.w end
local _={
name= D.name or"_",
@@ -246,13 +259,21 @@ function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,sound=tr
fText=D.fText,
color=D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30,
fType=D.fType,
align=D.align or'M',
edge= D.edge or 0,
sound=D.sound~=false,
code= D.code,
code= D.code or NULL,
hideF=D.hideF,
hide= D.hide,
}
if D.sound==false then
_.sound=false
elseif type(D.sound)=='string'then
_.sound=D.sound
else
_.sound='button'
end
for k,v in next,button do _[k]=v end
setmetatable(_,widgetMetatable)
return _
@@ -268,7 +289,7 @@ function key:reset()
end
function key:setObject(obj)
if type(obj)=='string'or type(obj)=='number'then
self.obj=gc.newText(FONT.get(self.font),obj)
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
elseif obj then
self.obj=obj
end
@@ -298,48 +319,54 @@ function key:draw()
local align=self.align
local r,g,b=c[1],c[2],c[3]
--Frame
if not self.noFrame then
gc_setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7)
gc_setLineWidth(2)
gc_rectangle('line',x,y,w,h,3)
end
--Fill
if self.fShade then
gc_setColor(r,g,b,ATV*.25)
if align=='M'then
mDraw(self.fShade,x+w*.5,y+h*.5)
gc_draw(self.fShade,x+w*.5-self.fShade:getWidth()*.5,y+h*.5-self.fShade:getHeight()*.5)
elseif align=='L'then
mDraw_Y(self.fShade,x+self.edge,y+h*.5)
gc_draw(self.fShade,x+self.edge,y+h*.5-self.fShade:getHeight()*.5)
elseif align=='R'then
mDraw_Y(self.fShade,x+w-self.edge-self.fShade:getWidth(),y+h*.5)
gc_draw(self.fShade,x+w-self.edge-self.fShade:getWidth(),y+h*.5-self.fShade:getHeight()*.5)
end
else
--Background
gc_setColor(0,0,0,.3)
gc_rectangle('fill',x,y,w,h,4)
--Frame
gc_setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7)
gc_setLineWidth(2)
gc_rectangle('line',x,y,w,h,3)
--Shade
gc_setColor(1,1,1,ATV*.05)
gc_rectangle('fill',x,y,w,h,3)
end
--Drawable
local obj=self.obj
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
gc_setColor(r,g,b)
if align=='M'then
mDraw(self.obj,x+w*.5,y+h*.5)
local kx=obj:type()=='Text'and min(w/ox/2,1)or 1
gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy)
elseif align=='L'then
mDraw_Y(self.obj,x+self.edge,y+h*.5)
gc_draw(obj,x+self.edge,y-oy+h*.5)
elseif align=='R'then
mDraw_Y(self.obj,x+w-self.edge-self.obj:getWidth(),y+h*.5)
gc_draw(obj,x+w-self.edge-ox*2,y-oy+h*.5)
end
end
function key:getInfo()
return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font)
return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType)
end
function key:press(_,_,k)
self.code(k)
if self.sound then
SFX.play('key')
SFX.play(self.sound)
end
end
function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,noFrame][,color][,font=30][,sound=true][,align='M'][,edge=0],code[,hideF][,hide]
function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,color][,font=30][,fType][,sound][,align='M'][,edge=0][,code][,hideF][,hide]
if not D.h then D.h=D.w end
local _={
name= D.name or"_",
@@ -359,16 +386,22 @@ function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,noFrame][,color][,fo
fText= D.fText,
fShade= D.fShade,
noFrame=D.noFrame,
color= D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30,
sound= D.sound~=false,
fType= D.fType,
align= D.align or'M',
edge= D.edge or 0,
code= D.code,
code= D.code or NULL,
hideF= D.hideF,
hide= D.hide,
}
if D.sound==false then
_.sound=false
elseif type(D.sound)=='string'then
_.sound=D.sound
else
_.sound='key'
end
for k,v in next,key do _[k]=v end
setmetatable(_,widgetMetatable)
return _
@@ -408,6 +441,10 @@ function switch:draw()
local x,y=self.x,self.y
local ATV=self.ATV
--Background
gc_setColor(0,0,0,.3)
gc_rectangle('fill',x,y-25,50,50,4)
--Frame
gc_setLineWidth(2)
gc_setColor(1,1,1,.6+ATV*.1)
@@ -430,15 +467,15 @@ function switch:draw()
gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5)
end
function switch:getInfo()
return("x=%d,y=%d,font=%d"):format(self.x,self.y,self.font)
return("x=%d,y=%d,font=%d"):format(self.x,self.y,self.font,self.fType)
end
function switch:press()
self.code()
if self.sound then
SFX.play('touch')
SFX.play(self.disp()and'check'or'uncheck')
end
end
function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,sound=true][,disp],code[,hideF][,hide]
function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,sound=true][,disp][,code][,hideF][,hide]
local _={
name= D.name or"_",
@@ -453,9 +490,10 @@ function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,sound=tr
fText=D.fText,
color=D.color and(COLOR[D.color]or D.color)or COLOR.Z,
font= D.font or 30,
fType=D.fType,
sound=D.sound~=false,
disp= D.disp,
code= D.code,
code= D.code or NULL,
hideF=D.hideF,
hide= D.hide,
}
@@ -491,7 +529,7 @@ function slider:isAbove(x,y)
return x>self.x-10 and x<self.x+self.w+10 and y>self.y-25 and y<self.y+25
end
function slider:getCenter()
return self.x+self.w*(self.pos/self.unit),self.y
return self.x+self.w*((self.pos-self.rangeL)/(self.rangeR-self.rangeL)),self.y
end
function slider:update(dt)
local ATV=self.ATV
@@ -505,7 +543,7 @@ function slider:update(dt)
if ATV>0 then self.ATV=max(ATV-dt*30,0)end
end
if not self.hide then
self.pos=self.pos*.7+self.disp()*.3
self.pos=approach(self.pos,self.disp(),dt*26)
end
end
function slider:draw()
@@ -518,8 +556,8 @@ function slider:draw()
--Units
if not self.smooth then
gc_setLineWidth(2)
for p=0,self.unit do
local X=x+(x2-x)*p/self.unit
for p=self.rangeL,self.rangeR,self.unit do
local X=x+(x2-x)*(p-self.rangeL)/(self.rangeR-self.rangeL)
gc_line(X,y+7,X,y-7)
end
end
@@ -529,7 +567,7 @@ function slider:draw()
gc_line(x,y,x2,y)
--Block
local cx=x+(x2-x)*self.pos/self.unit
local cx=x+(x2-x)*(self.pos-self.rangeL)/(self.rangeR-self.rangeL)
local bx,by,bw,bh=cx-10-ATV*.5,y-16-ATV,20+ATV,32+2*ATV
gc_setColor(.8,.8,.8)
gc_rectangle('fill',bx,by,bw,bh,3)
@@ -564,13 +602,16 @@ end
function slider:drag(x)
if not x then return end
x=x-self.x
local p=self.disp()
local P=x<0 and 0 or x>self.w and self.unit or x/self.w*self.unit
if not self.smooth then
P=int(P+.5)
local newPos=MATH.interval(x/self.w,0,1)
local newVal
if not self.unit then
newVal=(1-newPos)*self.rangeL+newPos*self.rangeR
else
newVal=newPos*(self.rangeR-self.rangeL)
newVal=self.rangeL+newVal-newVal%self.unit
end
if p~=P then
self.code(P)
if newVal~=self.disp()then
self.code(newVal)
end
if self.change and timer()-self.lastTime>.5 then
self.lastTime=timer()
@@ -583,8 +624,8 @@ function slider:release(x)
end
function slider:scroll(n)
local p=self.disp()
local u=self.smooth and .01 or 1
local P=n==-1 and max(p-u,0)or min(p+u,self.unit)
local u=self.unit or .01
local P=MATH.interval(p+u*n,self.rangeL,self.rangeR)
if p==P or not P then return end
self.code(P)
if self.change and timer()-self.lastTime>.18 then
@@ -593,9 +634,15 @@ function slider:scroll(n)
end
end
function slider:arrowKey(k)
self:scroll((k=="left"or k=="up")and -1 or 1)
self:scroll((k=='left'or k=='up')and -1 or 1)
end
function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,unit][,smooth][,font=30][,change],disp[,show],code,hide
function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,axis][,smooth][,font=30][,fType][,change],disp[,show][,code],hide
if not D.axis then
D.axis={0,1,false}
D.smooth=true
elseif not D.axis[3]then
D.smooth=true
end
local _={
name= D.name or"_",
@@ -614,32 +661,30 @@ function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,unit][,smooth][,
fText= D.fText,
color= D.color and(COLOR[D.color]or D.color)or COLOR.Z,
unit= D.unit or 1,
smooth=false,
rangeL=D.axis[1],
rangeR=D.axis[2],
unit= D.axis[3],
smooth=D.smooth,
font= D.font or 30,
fType= D.fType,
change=D.change,
disp= D.disp,
code= D.code,
code= D.code or NULL,
hideF= D.hideF,
hide= D.hide,
show= false,
}
if D.smooth~=nil then
_.smooth=D.smooth
else
_.smooth=_.unit<=1
end
if D.show then
if type(D.show)=='function'then
_.show=D.show
else
_.show=sliderShowFunc[D.show]
end
elseif D.show~=false then
if _.unit<=1 then
_.show=sliderShowFunc.percent
else
elseif D.show~=false then--Use default if nil
if _.unit and _.unit%1==0 then
_.show=sliderShowFunc.int
else
_.show=sliderShowFunc.percent
end
end
for k,v in next,slider do _[k]=v end
@@ -691,6 +736,10 @@ function selector:draw()
local w=self.w
local ATV=self.ATV
--Background
gc_setColor(0,0,0,.3)
gc_rectangle('fill',x,y,w,60,4)
--Frame
gc_setColor(1,1,1,.6+ATV*.1)
gc_setLineWidth(2)
@@ -744,7 +793,7 @@ function selector:press(x)
self.select=s
self.selText=self.list[s]
if self.sound then
SFX.play('prerotate')
SFX.play('selector')
end
end
end
@@ -764,14 +813,14 @@ function selector:scroll(n)
self.select=s
self.selText=self.list[s]
if self.sound then
SFX.play('prerotate')
SFX.play('selector')
end
end
function selector:arrowKey(k)
self:scroll((k=="left"or k=="up")and -1 or 1)
self:scroll((k=='left'or k=='up')and -1 or 1)
end
function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp,code,hide
function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp[,code],hide
local _={
name= D.name or"_",
@@ -793,7 +842,7 @@ function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,dis
font= 30,
list= D.list,
disp= D.disp,
code= D.code,
code= D.code or NULL,
hideF=D.hideF,
hide= D.hide,
}
@@ -854,18 +903,24 @@ function inputBox:draw()
local x,y,w,h=self.x,self.y,self.w,self.h
local ATV=self.ATV
gc_setColor(1,1,1,ATV*.08)
gc_rectangle('fill',x,y,w,h,3)
--Background
gc_setColor(0,0,0,.4)
gc_rectangle('fill',x,y,w,h,4)
--Highlight
gc_setColor(1,1,1,ATV*.08*(math.sin(TIME()*4.2)*.2+.8))
gc_rectangle('fill',x,y,w,h,4)
--Frame
gc_setColor(1,1,1)
gc_setLineWidth(3)
gc_rectangle('line',x,y,w,h,3)
--Drawable
local f=self.font
FONT.set(f)
FONT.set(f,self.fType)
if self.obj then
mDraw_Y(self.obj,x-12-self.obj:getWidth(),y+h*.5)
gc_draw(self.obj,x-12-self.obj:getWidth(),y+h*.5-self.obj:getHeight()*.5)
end
if self.secret then
y=y+h*.5-f*.2
@@ -892,21 +947,21 @@ end
function inputBox:keypress(k)
local t=self.value
if #t>0 and EDITING==""then
if k=="backspace"then
if k=='backspace'then
local p=#t
while t:byte(p)>=128 and t:byte(p)<192 do
p=p-1
end
t=sub(t,1,p-1)
SFX.play('lock')
elseif k=="delete"then
elseif k=='delete'then
t=""
SFX.play('hold')
end
self.value=t
end
end
function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,secret][,regex][,limit],hide
function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,fType][,secret][,regex][,limit],hide
local _={
name= D.name or"_",
@@ -922,6 +977,7 @@ function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,secret][,regex][,limit
},
font= D.font or int(D.h/7-1)*5,
fType= D.fType,
secret=D.secret==true,
regex= D.regex,
limit= D.limit,
@@ -999,9 +1055,9 @@ function textBox:scroll(dir)
self:drag(nil,nil,nil,-dir*self.lineH)
end
function textBox:arrowKey(k)
if k=="up"then
if k=='up'then
self:scroll(-1)
elseif k=="down"then
elseif k=='down'then
self:scroll(-1)
end
end
@@ -1013,8 +1069,8 @@ function textBox:draw()
local lineH=self.lineH
--Background
gc_setColor(0,0,0,.4)
gc_rectangle('fill',x,y,w,h,3)
gc_setColor(0,0,0,.3)
gc_rectangle('fill',x,y,w,h,4)
--Frame
gc_setLineWidth(2)
@@ -1022,7 +1078,7 @@ function textBox:draw()
gc_rectangle('line',x,y,w,h,3)
--Texts
FONT.set(self.font)
FONT.set(self.font,self.fType)
gc_push('transform')
gc_translate(x,y)
@@ -1054,7 +1110,7 @@ end
function textBox:getInfo()
return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h)
end
function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,lineH][,fix],hide
function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,fType][,lineH][,fix],hide
local _={
name= D.name or"_",
@@ -1076,6 +1132,7 @@ function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,lineH][,fix],hide
h= D.h,
font= D.font or 30,
fType=D.fType,
fix= D.fix,
texts={},
hideF=D.hideF,
@@ -1153,7 +1210,7 @@ function listBox:press(x,y)
if self.list[y]then
if self.selected~=y then
self.selected=y
SFX.play('click',.4)
SFX.play('selector',.8,0,12)
end
end
end
@@ -1176,6 +1233,14 @@ function listBox:arrowKey(dir)
end
end
end
function listBox:select(i)
self.selected=i
if self.selected<int(self.scrollPos/self.lineH)+2 then
self:drag(nil,nil,nil,1e99)
elseif self.selected>int(self.scrollPos/self.lineH)+self.capacity-1 then
self:drag(nil,nil,nil,-1e99)
end
end
function listBox:draw()
local x,y,w,h=self.x,self.y,self.w,self.h
local list=self.list
@@ -1186,6 +1251,10 @@ function listBox:draw()
gc_push('transform')
gc_translate(x,y)
--Background
gc_setColor(0,0,0,.4)
gc_rectangle('fill',0,0,w,h,4)
--Frame
gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z)
gc_setLineWidth(2)
@@ -1214,7 +1283,7 @@ end
function listBox:getInfo()
return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h)
end
function WIDGET.newListBox(D)--name,x,y,w,h,lineH[,hideF][,hide][,drawF]
function WIDGET.newListBox(D)--name,x,y,w,h,lineH,drawF[,hideF][,hide]
local _={
name= D.name or"_",
@@ -1271,16 +1340,7 @@ function WIDGET.setWidgetList(list)
for i=1,#list do
list[i]:reset()
end
if SCN.cur~='custom_field'then
local colorList=THEME.getThemeColor()
if not colorList then return end
local rnd=math.random
for _,W in next,list do
if W.color and not W.fText then
W.color=colorList[rnd(#colorList)]
end
end
end
onChange()
end
end
function WIDGET.setScrollHeight(height)
@@ -1373,59 +1433,6 @@ function WIDGET.release(x,y)
W:release(x,y+WIDGET.scrollPos)
end
end
function WIDGET.keyPressed(k,isRep)
local W=WIDGET.sel
if k=="space"or k=="return"then
if not isRep then
WIDGET.press()
end
elseif k=="up"or k=="down"or k=="left"or k=="right"then
if kb.isDown("lshift","lalt","lctrl")then
--Control some widgets with arrowkeys when hold shift/ctrl/alt
if W and W.arrowKey then W:arrowKey(k)end
else
if not W then
for _,w in next,WIDGET.active do
if not w.hide and w.isAbove then
WIDGET.focus(w)
return
end
end
elseif W.getCenter then
local WX,WY=W:getCenter()
local dir=(k=="right"or k=="down")and 1 or -1
local tar
local minDist=1e99
local swap_xy=k=="up"or k=="down"
if swap_xy then WX,WY=WY,WX end--note that we do not swap them back later
for _,W1 in ipairs(WIDGET.active)do
if W~=W1 and W1.resCtr and not W1.hide then
local L=W1.resCtr
for j=1,#L,2 do
local x,y=L[j],L[j+1]
if swap_xy then x,y=y,x end--note that we do not swap them back later
local dist=(x-WX)*dir
if dist>10 then
dist=dist+abs(y-WY)*6.26
if dist<minDist then
minDist=dist
tar=W1
end
end
end
end
end
if tar then
WIDGET.focus(tar)
end
end
end
else
if W and W.keypress then
W:keypress(k)
end
end
end
function WIDGET.textinput(texts)
local W=WIDGET.sel
if W and W.type=='inputBox'then
@@ -1433,41 +1440,10 @@ function WIDGET.textinput(texts)
WIDGET.sel.value=WIDGET.sel.value..texts
SFX.play('touch')
else
SFX.play('finesseError',.3)
SFX.play('drop_cancel')
end
end
end
local keyMirror={
dpup="up",
dpdown="down",
dpleft="left",
dpright="right",
start="return",
back="escape",
}
function WIDGET.gamepadPressed(i)
if i=="start"then
WIDGET.press()
elseif i=="a"or i=="b"then
local W=WIDGET.sel
if W then
if W.type=='button'or W.type=='key'then
WIDGET.press()
elseif W.type=='slider'then
local p=W.disp()
local P=i=="left"and(p>0 and p-1)or p<W.unit and p+1
if p==P or not P then return end
W.code(P)
if W.change and timer()-W.lastTime>.18 then
W.lastTime=timer()
W.change()
end
end
end
elseif i=="dpup"or i=="dpdown"or i=="dpleft"or i=="dpright"then
WIDGET.keyPressed(keyMirror[i])
end
end
function WIDGET.update(dt)
for _,W in next,WIDGET.active do

117
main.lua
View File

@@ -23,14 +23,14 @@ local fs=love.filesystem
VERSION=require"version"
TIME=love.timer.getTime
YIELD=coroutine.yield
SYSTEM=love.system.getOS()
FNSF=SYSTEM:find'\79\83'--What does FNSF stand for? IDK so don't ask me lol
SYSTEM=love.system.getOS()if SYSTEM=='OS X'then SYSTEM='macOS'end
FNNS=SYSTEM:find'\79\83'--What does FNSF stand for? IDK so don't ask me lol
MOBILE=SYSTEM=='Android'or SYSTEM=='iOS'
SAVEDIR=fs.getSaveDirectory()
--Global Vars & Settings
SFXPACKS={'chiptune'}
VOCPACKS={'miya','mono','xiaoya','miku'}
VOCPACKS={'miya',--[['mono',]]'xiaoya','miku'}
FIRSTLAUNCH=false
DAILYLAUNCH=false
@@ -50,11 +50,30 @@ local _LOADTIME_=TIME()
--Load modules
Z=require'Zframework'
FONT.load('parts/fonts/proportional.ttf')
FONT.load{
norm='parts/fonts/proportional.ttf',
mono='parts/fonts/monospaced.ttf',
}
FONT.setDefault('norm')
FONT.setFallback('norm')
SCR.setSize(1280,720)--Initialize Screen size
BGM.setMaxSources(5)
BGM.setChange(function(name)MES.new('music',text.nowPlaying..name,5)end)
VOC.setDiversion(1)
VOC.setDiversion(.62)
WIDGET.setOnChange(function()
if SCN.cur~='custom_field'then
local colorList=THEME.getThemeColor()
if not colorList then return end
local rnd=math.random
for _,W in next,SCN.scenes[SCN.cur].widgetList do
if W.color then
W.color=colorList[rnd(#colorList)]
end
end
end
end)
table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_))
@@ -65,6 +84,9 @@ mStr=GC.mStr
mText=GC.simpX
mDraw=GC.draw
Snd=SFX.playSample
string.repD=STRING.repD
string.sArg=STRING.sArg
string.split=STRING.split
--Delete all naked files (from too old version)
FILE.clear('')
@@ -93,6 +115,7 @@ for _,v in next,fs.getDirectoryItems('parts/shaders')do
end
end
THEME= require'parts.theme'
LINE= require'parts.line'
DATA= require'parts.data'
@@ -109,16 +132,13 @@ MODES= require'parts.modes'
setmetatable(TEXTURE,{__index=function(self,k)
MES.new('warn',"No texture called: "..k)
self[k]=love.graphics.newCanvas(1,1)
self[k]=PAPER
return self[k]
end})
table.insert(_LOADTIMELIST_,("Load Parts: %.3fs"):format(TIME()-_LOADTIME_))
--Init Zframework
Z.setIfPowerInfo(function()
return SETTING.powerInfo and LOADED
end)
do--Z.setCursor
local normImg=GC.DO{16,16,
{'fCirc',8,8,4},
@@ -164,6 +184,15 @@ Z.setOnFnKeys({
function()for k,v in next,_G do print(k,v)end end,
function()if love['_openConsole']then love['_openConsole']()end end,
})
Z.setDebugInfo{
{"Cache",gcinfo},
{"Tasks",TASK.getCount},
{"Voices",VOC.getQueueCount},
{"Audios",love.audio.getSourceCount},
}
Z.setOnResize(function(w,_)
SHADER.warning:send('w',w*SCR.dpi)
end)
do--Z.setOnFocus
local function task_autoSoundOff()
while true do
@@ -205,15 +234,15 @@ end
Z.setOnQuit(destroyPlayers)
--Load settings and statistics
TABLE.cover (FILE.load('conf/user')or{},USER)
TABLE.cover (FILE.load('conf/unlock')or{},RANKS)
TABLE.update(FILE.load('conf/settings')or{},SETTING)
TABLE.coverR(FILE.load('conf/data')or{},STAT)
TABLE.cover (FILE.load('conf/key')or{},KEY_MAP)
TABLE.cover (FILE.load('conf/virtualkey')or{},VK_ORG)
TABLE.cover (loadFile('conf/user','-canSkip')or{},USER)
TABLE.cover (loadFile('conf/unlock','-canSkip')or{},RANKS)
TABLE.update(loadFile('conf/settings','-canSkip')or{},SETTING)
TABLE.coverR(loadFile('conf/data','-canSkip')or{},STAT)
TABLE.cover (loadFile('conf/key','-canSkip')or{},KEY_MAP)
TABLE.cover (loadFile('conf/virtualkey','-json -canSkip')or{},VK_ORG)
--Initialize fields, sequence, missions, gameEnv for cutsom game
local fieldData=FILE.load('conf/customBoards','string')
local fieldData=loadFile('conf/customBoards','-string -canSkip')
if fieldData then
fieldData=STRING.split(fieldData,"!")
for i=1,#fieldData do
@@ -222,15 +251,15 @@ if fieldData then
else
FIELD[1]=DATA.newBoard()
end
local sequenceData=FILE.load('conf/customSequence','string')
local sequenceData=loadFile('conf/customSequence','-string -canSkip')
if sequenceData then
DATA.pasteSequence(sequenceData)
end
local missionData=FILE.load('conf/customMissions','string')
local missionData=loadFile('conf/customMissions','-string -canSkip')
if missionData then
DATA.pasteMission(missionData)
end
local customData=FILE.load('conf/customEnv')
local customData=loadFile('conf/customEnv','-canSkip')
if customData and customData['version']==VERSION.code then
TABLE.complete(customData,CUSTOMENV)
end
@@ -249,13 +278,15 @@ IMG.init{
pay1='media/image/mess/pay1.png',
pay2='media/image/mess/pay2.png',
miyaCH='media/image/characters/miya.png',
miyaF1='media/image/characters/miya_f1.png',
miyaF2='media/image/characters/miya_f2.png',
miyaF3='media/image/characters/miya_f3.png',
miyaF4='media/image/characters/miya_f4.png',
miyaCH1='media/image/characters/miya1.png',
miyaCH2='media/image/characters/miya2.png',
miyaCH3='media/image/characters/miya3.png',
miyaCH4='media/image/characters/miya4.png',
miyaHeart='media/image/characters/miya_heart.png',
miyaGlow='media/image/characters/miya_glow.png',
monoCH='media/image/characters/mono.png',
xiaoyaCH='media/image/characters/xiaoya.png',
xiaoyaOmino='media/image/characters/xiaoya_Omino.png',
mikuCH='media/image/characters/miku.png',
electric='media/image/characters/electric.png',
hbm='media/image/characters/hbm.png',
@@ -272,7 +303,7 @@ IMG.init{
SKIN.load{
{name="crystal_scf",path='media/image/skin/crystal_scf.png'},
{name="matte_mrz",path='media/image/skin/matte_mrz.png'},
{name="shiny_cho",path='media/image/skin/shiny_cho.png'},
{name="shiny_chno",path='media/image/skin/shiny_chno.png'},
{name="contrast_mrz",path='media/image/skin/contrast_mrz.png'},
{name="polkadots_scf",path='media/image/skin/polkadots_scf.png'},
{name="toy_scf",path='media/image/skin/toy_scf.png'},
@@ -295,6 +326,7 @@ SKIN.load{
{name="classic",path='media/image/skin/classic_unknown.png'},
{name="ball_shaw",path='media/image/skin/ball_shaw.png'},
{name="retro_notypey",path='media/image/skin/retro_notypey.png'},
{name="pixel_chno",path='media/image/skin/pixel_chno.png'},
{name="textbone_mrz",path='media/image/skin/textbone_mrz.png'},
{name="coloredbone_mrz",path='media/image/skin/coloredbone_mrz.png'},
{name="wtf",path='media/image/skin/wtf_mrz.png'},
@@ -310,11 +342,11 @@ SFX.init((function()--[Warning] Not loading files here, just get the list of sou
end
return L
end)())
BGM.init((function()
BGM.load((function()
local L={}
for _,v in next,fs.getDirectoryItems('media/music')do
if isSafeFile('media/music/'..v,"Dangerous file : %SAVE%/media/music/"..v)then
table.insert(L,{name=v:sub(1,-5),path='media/music/'..v})
L[v:sub(1,-5)]='media/music/'..v
end
end
return L
@@ -333,14 +365,15 @@ VOC.init{
LANG.init('zh',
{
zh=require'parts.language.lang_zh',
zh_full=require'parts.language.lang_zh_full',
zh_trad=require'parts.language.lang_zh_trad',
zh_full=require'parts.language.lang_zh_full',
en=require'parts.language.lang_en',
fr=require'parts.language.lang_fr',
es=require'parts.language.lang_es',
pt=require'parts.language.lang_pt',
id=require'parts.language.lang_id',
ja=require'parts.language.lang_ja',
zh_grass=require'parts.language.lang_zh_grass',
zh_yygq=require'parts.language.lang_yygq',
symbol=require'parts.language.lang_symbol',
--1. Add language file to LANG folder;
--2. Require it;
@@ -373,6 +406,7 @@ for _,v in next,fs.getDirectoryItems('parts/backgrounds')do
BG.add(name,require('parts.backgrounds.'..name))
end
end
BG.remList('none')BG.remList('gray')BG.remList('custom')
--Load scene files from SOURCE ONLY
for _,v in next,fs.getDirectoryItems('parts/scenes')do
if isSafeFile('parts/scenes/'..v)then
@@ -407,7 +441,6 @@ do
local needSave
if not fs.getInfo('conf/data')then
FIRSTLAUNCH=true
needSave=true
end
if type(STAT.version)~='number'then
@@ -439,7 +472,6 @@ do
if RANKS.tsd_u then
RANKS.tsd_u=0
end
needSave=true
end
if STAT.version==1601 then
RANKS.round_e=nil
@@ -453,6 +485,13 @@ do
fs.remove('record/round_l.rec')
fs.remove('record/round_u.rec')
end
if STAT.version<1700 and SETTING.dascut<5 then
SETTING.dascut=SETTING.dascut+1
needSave=true
end
if SETTING.vocPack=='mono'then
SETTING.vocPack='miya'
end
if RANKS.stack_e then
RANKS.stack_e=nil
RANKS.stack_h=nil
@@ -477,6 +516,10 @@ do
fs.remove('record/rhythm_h.rec')
fs.remove('record/rhythm_u.rec')
end
if RANKS.bigbang then
RANKS.clearRush,RANKS.bigbang=RANKS.bigbang
fs.remove('record/bigbang.rec')
end
if STAT.version~=VERSION.code then
for k,v in next,MODE_UPDATE_MAP do
if RANKS[k]then
@@ -504,6 +547,9 @@ do
if type(SETTING.skinSet)=='number'then SETTING.skinSet='crystal_scf'end
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then SETTING.frameMul=100 end
if SETTING.cv then SETTING.vocPack,SETTING.cv=SETTING.cv end
if type(SETTING.bg)~='string'then SETTING.bg='on'end
if SETTING.skin[18]==10 then SETTING.skin[18]=4 end
if SETTING.reTime>3 or SETTING.reTime<.5 then SETTING.reTime=2 end
if RANKS.infinite then RANKS.infinite=0 end
if RANKS.infinite_dig then RANKS.infinite_dig=0 end
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
@@ -543,7 +589,8 @@ do
end
end
--First start for phones
--First start
FIRSTLAUNCH=STAT.run==0
if FIRSTLAUNCH and MOBILE then
SETTING.VKSwitch=true
SETTING.powerInfo=true
@@ -551,7 +598,7 @@ if FIRSTLAUNCH and MOBILE then
end
--Apply system setting
applyAllSettings()
applySettings()
--Load replays
for _,fileName in next,fs.getDirectoryItems('replay')do
@@ -629,9 +676,9 @@ if TABLE.find(arg,'--test')then
TASK.new(function()
while true do
YIELD()
if Z.errData[1]then break end
if Z.getErr(1)then break end
end
LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(Z.errData[1].mes,"\n").."\27[91m\nAborting\27[0m")
LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(Z.getErr(1).mes,"\n").."\27[91m\nAborting\27[0m")
TEST.yieldN(60)
love.event.quit(1)
end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 41 KiB

BIN
media/music/lounge.ogg Normal file

Binary file not shown.

BIN
media/music/malate.ogg Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -97,12 +97,12 @@ do
{131,2,2, 0, 0,0},{131,2,2,-1,-1,0},{131,2,2,-1, 0,0},--S
{131,1,2,-1, 0,0},{131,1,2, 0,-1,0},{131,1,2, 0, 0,0},--Z(misOrder)
{313,2,2, 0, 0,0},{313,2,2,-1,-1,0},{313,2,2,-1, 0,0},--S(misOrder)
{331,3,2, 0,-1,0},--J(farDown)
{113,4,2,-1,-1,0},--L(farDown)
{331,3,2, 0,-1,1},--J(farDown)
{113,4,2,-1,-1,1},--L(farDown)
{113,3,2,-1,-1,0},{113,3,0, 0, 0,0},--J
{331,4,2, 0,-1,0},{331,4,0,-1, 0,0},--L
{222,7,2,-1, 0,2},{222,7,2,-2, 0,2},{222,7,2, 0, 0,2},--I
{222,7,0,-1, 1,1},{222,7,0,-2, 1,1},{222,7,0, 0, 1,1},--I(high)
{222,7,2,-1, 0,2},{222,7,2,-2, 0,2},{222,7,2, 0, 0,2},--I(low)
{121,6,0, 1,-1,2},{112,6,0, 2,-1,2},{122,6,0, 1,-2,2},--O
{323,6,0,-1,-1,2},{332,6,0,-2,-1,2},{322,6,0,-1,-2,2},--O
}--{keys, ID, dir, dx, dy, freeLevel (0=immovable, 1=U/D-immovable, 2=free)}
@@ -204,6 +204,7 @@ do
P.spinLast=2
P.stat.rotate=P.stat.rotate+1
P:freshBlock('move')
C.spinSeq=nil
return
end
end
@@ -304,8 +305,8 @@ do
[10]={'+0+0','+0+1','+1+0','+0-2','+1-2'},
[03]={'+0+0','+0-1','+0+1','+0+2'},
[30]={'+0+0','+0-1','+0+1','+0-2'},
[12]={'+0+0','+0-1','+0+1'},
[21]={'+0+0','+0-1','+0-2'},
[12]={'+0+0','+0-1','+0+1','+0+2'},
[21]={'+0+0','+0-1','+0-2','+0-2'},
[32]={'+0+0','+1+0','-1+0'},
[23]={'+0+0','-1+0','+1+0'},
[02]={'+0+0','-1+1','+1-1'},
@@ -375,8 +376,8 @@ do
},--R
false,--Y
{
[01]={'+0+0','-1+0','-1+1','+0+1','+1+0','-1+2','-2+0','+0-2'},
[10]={'+0+0','+1+0','-1+0','+0-1','+1-1','+1-2','+2+0','+0+2'},
[01]={'+0+0','-1+0','-1+1','+0+1','+1+0','+1+1','-1+2','-2+0','+0-2'},
[10]={'+0+0','+1+0','-1+0','+0-1','-1-1','+1-1','+1-2','+2+0','+0+2'},
[03]={'+0+0','-1+0','+1-1','+0-2','+0-3','+1+0','+1-2','+1-3','+0+1','-1+1'},
[30]={'+0+0','-1+0','+1-1','+1-2','+1+0','+0-2','+1-3','-1+2','+0+3','-1+3'},
[12]={'+0+0','-1+0','+1-1','-1-1','+1-2','+1+0','+0-2','+1-3','-1+2','+0+3','-1+3'},
@@ -761,6 +762,68 @@ do
ARS_Z.kickTable[25]=upSet
end
local DRS_weak
do
local centerPos=TABLE.copy(defaultCenterPos)
centerPos[1]={[0]={1,1},{1,0},{1,1},{1,1}}--Z
centerPos[2]={[0]={1,1},{1,0},{1,1},{1,1}}--S
centerPos[3]={[0]={1,1},{1,0},{1,1},{1,1}}--L
centerPos[4]={[0]={1,1},{1,0},{1,1},{1,1}}--J
centerPos[5]={[0]={1,1},{1,0},{1,1},{1,1}}--T
centerPos[7]={[0]={.5,1.5},{1.5,-.5},{.5,1.5},{1.5,.5}}--I
centerPos[10]={[0]={1,1},{1,0},{1,1},{1,0}}--P
centerPos[11]={[0]={1,1},{1,1},{1,1},{1,1}}--Q
centerPos[15]={[0]={1,1},{1,0},{1,1},{1,1}}--U
centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}--V
centerPos[19]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--J5
centerPos[20]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--L5
centerPos[21]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--R
centerPos[22]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--Y
centerPos[23]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--N
centerPos[24]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--H
centerPos[26]={[0]={0,1},{0,0},{0,1},{0,0}}--I3
centerPos[28]={[0]={0,1},{0,0},{0,1},{0,0}}--I2
local L={'+0+0','-1+0','+1+0','+0-1','-1-1','+1-1'}
local R={'+0+0','+1+0','-1+0','+0-1','+1-1','-1-1'}
local Z={
[01]=R,[10]=L,[03]=L,[30]=R,
[12]=R,[21]=L,[32]=L,[23]=R,
[02]=R,[20]=L,[13]=L,[31]=R,
}
local S=_reflect(Z)
DRS_weak={
centerTex=GC.DO{10,10,
{'setLW',2},
{'dRect',1,1,8,8},
{'fRect',3,3,4,4},
},
centerPos=centerPos,
kickTable={
Z,S,--Z,S
Z,S,--J,L
Z,--T
noKickSet,--O
Z,--I
Z,S,--Z5,S5
Z,S,--P,Q
Z,S,--F,E
Z,Z,Z,Z,--T5,U,V,W
noKickSet,--X
Z,S,--J5,L5
Z,S,--R,Y
Z,S,--N,H
Z,--I5
Z,Z,--I3,C
Z,Z,--I2,O1
}
}
end
local ASC
do
local L={'+0+0','+1+0','+0-1','+1-1','+0-2','+1-2','+2+0','+2-1','+2-2','-1+0','-1-1','+0+1','+1+1','+2+1','-1-2','-2+0','+0+2','+1+2','+2+2','-2-1','-2-2'}
@@ -934,6 +997,7 @@ local RSlist={
SRS_X=SRS_X,
BiRS=BiRS,
ARS_Z=ARS_Z,
DRS_weak=DRS_weak,
ASC=ASC,
ASC_plus=ASC_plus,
C2=C2,

View File

@@ -0,0 +1,31 @@
--Secret custom background
local gc_clear,gc_setColor=love.graphics.clear,love.graphics.setColor
local back={}
local image=false
local alpha=.26
local mx,my,k
function back.init()
back.resize()
end
function back.resize()
mx,my=SCR.w*.5,SCR.h*.5
if image then
k=math.max(SCR.w/image:getWidth(),SCR.h/image:getHeight())
end
end
function back.draw()
gc_clear(.1,.1,.1)
if image then
gc_setColor(1,1,1,alpha)
mDraw(image,mx,my,nil,k)
end
end
function back.event(a,img)
if a then alpha=a end
if img then image=img end
back.resize()
end
return back

View File

@@ -0,0 +1,11 @@
--Customizable grey background
local gc=love.graphics
local back={}
local brightness=.26
function back.draw()
gc.clear(brightness,brightness,brightness)
end
function back.event(b)
brightness=b
end
return back

View File

@@ -22,12 +22,12 @@ function back.resize(w,h)
S[i+4]=(rnd()-.5)*.01*s--Vy
end
end
function back.update()
function back.update(dt)
local S=stars
--Star moving
for i=1,1260,5 do
S[i+1]=(S[i+1]+S[i+3])%W
S[i+2]=(S[i+2]+S[i+4])%H
S[i+1]=(S[i+1]+S[i+3]*dt*60)%W
S[i+2]=(S[i+2]+S[i+4]*dt*60)%H
end
end
function back.draw()

View File

@@ -25,8 +25,8 @@ function bot_cc:revive()
self.P:loadAI(self.data)
end
function bot_cc:pushNewNext(id)
self.ccBot:addNext(rem(self.nexts,1))
ins(self.nexts,id)
self.ccBot:addNext(rem(self.bufferedNexts,1))
ins(self.bufferedNexts,id)
end
function bot_cc:thread()
local P,keys=self.P,self.keys

View File

@@ -12,7 +12,7 @@ local baseBot={
function baseBot.update(bot)
local P=bot.P
local keys=bot.keys
if P.control and P.waiting==0 then
if P.control and P.cur then
bot.delay=bot.delay-1
if not keys[1]then
if bot.runningThread then
@@ -85,7 +85,7 @@ function BOT.new(P,data)
if data.type=="CC"then
P:setRS('SRS')
bot.keys={}
bot.nexts={}
bot.bufferedNexts={}
bot.delay=data.delay
bot.delay0=data.delay
if P.gameEnv.holdCount>1 then
@@ -109,20 +109,25 @@ function BOT.new(P,data)
return
self.ccBot[k]and function(_,...)self.ccBot[k](self.ccBot,...)end or
cc_lua[k]and function(_,...)cc_lua[k](self,...)end or
baseBot[k]and baseBot[k]or
error("No actions called "..k)
assert(baseBot[k],"No CC action called "..k)
end})
for i,B in next,P.nextQueue do
if i<=data.next then
local pushed=0
if P.cur then
bot:addNext(P.cur.id)
pushed=pushed+1
end
for _,B in next,P.nextQueue do
if pushed<=data.next then
bot:addNext(B.id)
pushed=pushed+1
else
ins(bot.nexts,B.id)
ins(bot.bufferedNexts,B.id)
end
end
bot.runningThread=coroutine.wrap(cc_lua.thread)
bot.runningThread(bot)
elseif data.type=="9S"or true then--9s or else
else--if data.type=="9S"then--9s or else
TABLE.cover(baseBot,bot)
TABLE.cover(require"parts.bot.bot_9s",bot)
P:setRS('TRS')

View File

@@ -0,0 +1,18 @@
return{
hook_drop=function(P)
if P.lastPiece.row>0 then
for _=1,#P.clearedRow do
local h=#P.field
P.field[h+1]=LINE.new(20)
P.visTime[h+1]=LINE.new(20)
for i=3,7 do P.field[h+1][i]=0 end
end
if P.combo>P.modeData.maxCombo then
P.modeData.maxCombo=P.combo
end
if P.stat.row>=200 then
P:win('finish')
end
end
end
}

39
parts/eventsets/big_h.lua Normal file
View File

@@ -0,0 +1,39 @@
return
{
drop=1,
wait=8,
fall=20,
fieldH=10,
mesDisp=function(P)
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
PLY.draw.drawTargetLine(P,200-P.stat.row)
end,
task=function(P)
local F=P.field
for i=1,24 do
F[i]=LINE.new(20)
P.visTime[i]=LINE.new(20)
for x=3,7 do F[i][x]=0 end
end
P.modeData.target=50
end,
hook_drop=function(P)
if P.stat.row>=P.modeData.target then
if P.modeData.target==50 then
P.gameEnv.drop=.5
P.modeData.target=100
SFX.play('reach')
elseif P.modeData.target==100 then
P.gameEnv.drop=.25
P.modeData.target=150
SFX.play('reach')
elseif P.modeData.target==150 then
P:set20G(true)
P.modeData.target=200
SFX.play('reach')
else
P:win('finish')
end
end
end
}

Some files were not shown because too many files have changed in this diff Show More