Compare commits

..

78 Commits

Author SHA1 Message Date
MrZ626
fa0dc1f946 更新版本号,修改更新历史 2021-05-20 22:45:01 +08:00
MrZ626
8f860b21a8 优化开局倒计时画面效果 2021-05-20 22:12:10 +08:00
MrZ626
2a5105a49e 整理老旧自定义-消除模式代码,修复左侧消息显示问题 2021-05-20 22:09:24 +08:00
MrZ626
0fa9f85a8d 优化spike指示器绘制代码 2021-05-20 20:56:59 +08:00
MrZ626
202117a60e 垃圾行缓冲警告添加震动效果 2021-05-20 20:12:22 +08:00
MrZ626
35c7935f9c spike指示器显示优化 2021-05-20 15:48:28 +08:00
MrZ626
d953d623a2 微调联网房间内准备前ui,修改键盘准备/观战快捷键 2021-05-20 14:35:55 +08:00
MrZ626
4ddccd7211 混战模式和联网对战允许开局跳块 2021-05-20 14:21:11 +08:00
MrZ626
4a2d13c6d7 允许开局跳过若干next时,倒计时数字颜色和动画样式略有不同 2021-05-20 14:21:09 +08:00
MrZ626
c92b4c1863 修复手机端词典里的官网链接点不开 2021-05-20 13:34:15 +08:00
MrZ626
fb736c5a7a 调整模块加载顺序,修复一处cc库相关的报错 2021-05-20 13:29:18 +08:00
MrZ626
9046a0a7c8 整理版本更新代码,临时改成每次启动刷新所有lib文件 2021-05-20 12:27:08 +08:00
MrZ626
4173441d3c 修改更新历史 2021-05-20 00:24:48 +08:00
MrZ626
b5c3af05d8 整理代码 2021-05-20 00:04:12 +08:00
MrZ626
6fa9aa30fa 新增虚拟按键样式设置 2021-05-20 00:02:37 +08:00
MrZ626
41ce44fc0e 修复手机端文本框响应逻辑错误 2021-05-19 21:32:47 +08:00
MrZ626
59848cd559 尝试修复手机端文本框响应逻辑错误 2021-05-19 18:12:09 +08:00
MrZ626
092c944d27 整理代码 2021-05-19 18:12:09 +08:00
MrZ626
8ec051f523 添加一些tip 2021-05-19 16:15:56 +08:00
MrZ626
22cc708a65 赞助名单添加一位 2021-05-19 16:15:56 +08:00
MrZ626
4e577a01ae 删除一处测试代码,更新版本号,修改更新历史 2021-05-19 02:12:24 +08:00
MrZ626
5b43ff8c45 联网推进(观战功能测试) 2021-05-19 02:08:29 +08:00
MrZ626
d07075ca9c 联网推进(微调房间内交互,观战模式不再尝试发送录像流) 2021-05-18 17:39:00 +08:00
MrZ626
cd49507a2b 联网推进(增加观战相关代码) 2021-05-18 17:16:58 +08:00
MrZ626
00464f1e80 整理代码 2021-05-18 15:44:01 +08:00
MrZ626
6ec902e618 适当上移next和hold栏 2021-05-18 11:52:06 +08:00
MrZ626
30e276b132 新的对战房间数据结构,整理相关内容 2021-05-18 03:13:53 +08:00
MrZ626
b8597d1518 适配新版玩家连接状态修改方式 2021-05-18 01:45:28 +08:00
MrZ626
5543f29e4f 跟进更新历史 2021-05-18 01:12:40 +08:00
MrZ626
dc67239382 词典添加spike词条 2021-05-18 01:12:25 +08:00
MrZ626
2a571bbb97 网战录像流强行将每段数据长度补足到3的倍数保证base64后的数据不会被等号填充 2021-05-18 01:04:13 +08:00
MrZ626
2824bef04a 网战不再生成没连接成功的玩家对象 2021-05-18 00:59:41 +08:00
MrZ626
8fc7ebdab7 移除next和hold栏上的文本 2021-05-17 22:32:59 +08:00
MrZ626
793d6780f3 更新虚拟按键样式,略微优化性能 2021-05-17 22:32:59 +08:00
MrZ626
605561148b 修复未登录时游戏启动就进登录菜单 2021-05-17 22:29:56 +08:00
MrZ626
54daef0cd9 修复控件系统inputBox焦点问题 2021-05-17 22:29:56 +08:00
MrZ626
ac0ff16537 版本信息添加short字段,上报房间版本格式从code改为short,微调房间列表界面ui 2021-05-17 22:29:56 +08:00
MrZ626
e44053446a 更新ws连接服务器用的域名 2021-05-17 22:29:56 +08:00
MrZ626
d4fb606c72 再更新新房间列表ui 2021-05-17 15:15:12 +08:00
MrZ626
4cfdd4e58b 修复ws状态指示器在屏幕尺寸不标准时显示位置错误 2021-05-17 14:57:53 +08:00
MrZ626
3b82a144ea 升级本地和服务器提供的房间数据格式(警告:和旧版本不兼容),修复“游戏中”标记会被带到别的房间 2021-05-17 01:02:04 +08:00
MrZ626
2f06c1b476 前推版本适配代码,更新版本号 2021-05-16 21:35:22 +08:00
MrZ626
25b6b2c5ba 修改更新日志 2021-05-16 21:29:35 +08:00
MrZ626
9948505145 微调spike的画面效果 2021-05-16 21:26:23 +08:00
MrZ626
9d8feab2cc 添加spike计数器开关,调整画面设置界面布局 2021-05-16 20:56:13 +08:00
MrZ626
bcb5d3eba4 新增spike计数器 2021-05-16 20:29:01 +08:00
MrZ626
d7a10c00ed 再优化一点玩家绘制性能,整理代码 2021-05-16 19:10:03 +08:00
MrZ626
d2593cfb81 整理初始化空玩家代码 2021-05-16 16:32:08 +08:00
MrZ626
8101cf89f8 修复命令行空白输入报错
closes #63
2021-05-16 14:15:14 +08:00
MrZ626
8636c6dcd5 重新启用margin time,但基于帧而不是时间 2021-05-16 14:09:06 +08:00
MrZ626
b9c5599f95 修复对战房间内按钮会触发聊天框 2021-05-16 03:16:07 +08:00
MrZ626
93f854e6e4 简化/混淆水印代码 2021-05-16 03:07:25 +08:00
MrZ626
ffc09b0801 房间内文本框操作更自然 2021-05-16 02:55:25 +08:00
MrZ626
d246064ded 新增几个灰色tip 2021-05-16 01:59:35 +08:00
MrZ626
468f264545 整理代码,修改更新日志 2021-05-15 23:50:44 +08:00
MrZ626
9bec223b09 升级控件模块,封装focus相关的几个静态方法 2021-05-15 23:32:14 +08:00
MrZ626
4606bb4d01 调整进入联网游戏菜单的音效播放时机 2021-05-15 23:31:44 +08:00
MrZ626
c8405c8924 词典添加游戏官网 2021-05-15 20:58:09 +08:00
MrZ626
95a33c0e6c 主菜单按钮行为更容易理解,添加连接音效和连接成功音效 2021-05-15 20:17:31 +08:00
MrZ626
ed2ad35dde 修改默认空用户名,修复结算时显示胜利者可能报错 2021-05-15 17:57:30 +08:00
MrZ626
234ae08c76 微调双语tips 2021-05-15 17:57:16 +08:00
MrZ626
d21506b8d7 微调房间内玩家对象的绘制 2021-05-15 17:57:09 +08:00
MrZ626
1fa7bf9c27 修复房间内玩家连接状态相关代码一处概率报错 2021-05-14 22:23:05 +08:00
MrZ626
b50e01e4cf 修改更新历史,更新版本号 2021-05-14 22:23:05 +08:00
MrZ626
7abf9b0d0c 增加自定义游戏锁延刷新次数挡位 2021-05-14 22:23:04 +08:00
MrZ626
504c6f46c3 新增无尽pc挑战模式,微调其他pc模式的数据展示 2021-05-14 22:23:04 +08:00
MrZ626
78b1dcc949 减少生存模式最高两个难度的锁延刷新次数 2021-05-14 20:40:13 +08:00
MrZ626
9b0c859593 把三个设置项改成默认开启 2021-05-14 20:22:57 +08:00
MrZ626
c9a3075d0a 修复联网房间内潜在的报错可能 2021-05-14 20:20:54 +08:00
MrZ626
953b17ee88 textBox控件在隐藏时也会自动滚动 2021-05-14 20:20:54 +08:00
MrZ626
95bc979da7 主菜单点联网游戏按钮尝试连接时会有文字提示,房间内可以显示其他玩家的ws(stream)连接状态 2021-05-14 20:20:54 +08:00
MrZ626
622b1a5e25 主菜单点击联网游戏按钮尝试连接时会有文字提示 2021-05-14 18:58:44 +08:00
MrZ626
0c66ca1bdc 调整干旱2模式的标题 2021-05-14 16:25:42 +08:00
MrZ626
67323c4d93 yygq语言的tips改为深灰色移入普通语言 2021-05-14 16:25:42 +08:00
MrZ626
e2b0069947 调整统计文件保存时机,左上角不再弹出保存成功提醒 2021-05-14 12:11:56 +08:00
MrZ626
5697a201ef 简化LOG.print的功能和使用 2021-05-14 11:35:34 +08:00
MrZ626
c6115e3417 修复聊天窗带空格的消息会被截断 2021-05-14 10:29:52 +08:00
MrZ626
0ad122ce01 string扩展模块新增trim方法 2021-05-14 10:23:16 +08:00
79 changed files with 1118 additions and 747 deletions

View File

@@ -50,7 +50,7 @@ function BGM.init(list)
Sources[list[i]]:setLooping(true)
Sources[list[i]]:setVolume(0)
else
LOG.print("No BGM file: "..list[i],5,COLOR.O)
LOG.print("No BGM file: "..list[i],5,'warn')
end
if not skip and i~=count then
coroutine.yield()

View File

@@ -21,7 +21,7 @@ function FILE.load(name)
return s
end
end
LOG.print(name.." "..text.loadError,COLOR.R)
LOG.print(name.." "..text.loadError,'error')
end
end
function FILE.save(data,name,mode)
@@ -50,7 +50,7 @@ function FILE.save(data,name,mode)
F:flush()F:close()
if success then
if not mode:find'q'then
LOG.print(text.saveDone,COLOR.G)
LOG.print(text.saveDone,'message')
end
else
LOG.print(text.saveError..(mes or"unknown error"),'error')

View File

@@ -160,6 +160,7 @@ function love.touchpressed(id,x,y)
if SCN.swapping then return end
if not touching then
touching=id
WIDGET.unFocus(true)
love.touchmoved(id,x,y,0,0)
end
x,y=xOy:inverseTransformPoint(x,y)
@@ -172,14 +173,10 @@ function love.touchmoved(_,x,y,dx,dy)
x,y=xOy:inverseTransformPoint(x,y)
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end
if WIDGET.sel then
if touching then
WIDGET.drag(x,y,dx,dy)
end
if touching then WIDGET.drag(x,y,dx,dy)end
else
WIDGET.cursorMove(x,y)
if not WIDGET.sel then
touching=false
end
if not WIDGET.sel then touching=false end
end
end
function love.touchreleased(id,x,y)
@@ -188,10 +185,9 @@ function love.touchreleased(id,x,y)
if id==touching then
WIDGET.press(x,y,1)
WIDGET.release(x,y)
WIDGET.cursorMove(x,y)
WIDGET.unFocus()
touching=false
if WIDGET.sel and not WIDGET.sel.keepFocus then
WIDGET.sel=false
end
end
if SCN.touchUp then SCN.touchUp(x,y)end
if(x-lastX)^2+(y-lastY)^2<62 then
@@ -204,7 +200,7 @@ local function noDevkeyPressed(key)
if key=="f1"then
PROFILE.switch()
elseif key=="f2"then
LOG.print(("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s"):format(SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num))
LOG.print(("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s"):format(SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num),'message')
elseif key=="f3"then
for _=1,8 do
local P=PLY_ALIVE[rnd(#PLY_ALIVE)]
@@ -214,18 +210,18 @@ local function noDevkeyPressed(key)
end
end
elseif key=="f4"then if not kb.isDown("lalt","ralt")then LOG.copy()end
elseif key=="f5"then if WIDGET.sel then print(WIDGET.sel)end
elseif key=="f5"then print(WIDGET.isFocus()or"no widget selected")
elseif key=="f6"then for k,v in next,_G do print(k,v)end
elseif key=="f7"then if love._openConsole then love._openConsole()end
elseif key=="f8"then devMode=nil LOG.print("DEBUG OFF",COLOR.Y)
elseif key=="f9"then devMode=1 LOG.print("DEBUG 1",COLOR.Y)
elseif key=="f10"then devMode=2 LOG.print("DEBUG 2",COLOR.Y)
elseif key=="f11"then devMode=3 LOG.print("DEBUG 3",COLOR.Y)
elseif key=="f12"then devMode=4 LOG.print("DEBUG 4",COLOR.Y)
elseif key=="f8"then devMode=nil LOG.print("DEBUG OFF")
elseif key=="f9"then devMode=1 LOG.print("DEBUG 1")
elseif key=="f10"then devMode=2 LOG.print("DEBUG 2")
elseif key=="f11"then devMode=3 LOG.print("DEBUG 3")
elseif key=="f12"then devMode=4 LOG.print("DEBUG 4")
elseif key=="\\"then _G["\100\114\97\119\70\87\77"]=NULL
elseif devMode==2 then
if WIDGET.sel then
local W=WIDGET.sel
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
@@ -251,7 +247,7 @@ function love.keypressed(key)
return
elseif key=="f8"then
devMode=1
LOG.print("DEBUG ON",COLOR.Y)
LOG.print("DEBUG ON")
elseif key=="f11"then
switchFullscreen()
elseif not SCN.swapping then
@@ -278,12 +274,13 @@ end
function love.joystickadded(JS)
ins(joysticks,JS)
LOG.print("Joystick added",'message')
end
function love.joystickremoved(JS)
local i=TABLE.find(joysticks,JS)
if i then
rem(joysticks,i)
LOG.print("Joystick removed",COLOR.Y)
LOG.print("Joystick removed",'message')
end
end
local keyMirror={
@@ -463,11 +460,11 @@ local devColor={
local WS=WS
local WSnames={'app','user','play','stream','chat'}
local WScolor={
{1,.5,.5,.7},
{1,.8,.3,.7},
{1,1,.4,.7},
{.4,1,.7,.7},
{.5,.8,1,.7},
{1,.6,.6,.7},
{1,.8,.4,.7},
{1,1,.5,.7},
{.5,1,.8,.7},
{.6,.9,1,.7},
}
local ws_deadImg=DOGC{20,20,
{'setFT',20},
@@ -625,26 +622,26 @@ function love.run()
--Websocket status
gc_push('transform')
gc.translate(SCR.w,SCR.h-100)
gc.translate(SCR.w,SCR.h)
gc.scale(SCR.k)
for i=1,5 do
local status=WS.status(WSnames[i])
gc_setColor(WScolor[i])
gc_rectangle('fill',0,20*i,-80,-20)
gc_rectangle('fill',0,20*i-100,-80,-20)
if status=='dead'then
gc_setColor(1,1,1)
gc_draw(ws_deadImg,-20,20*i-20)
gc_draw(ws_deadImg,-20,20*i-120)
elseif status=='connecting'then
gc_setColor(1,1,1,.5+.3*sin(time*6.26))
gc_draw(ws_connectingImg,-20,20*i-20)
gc_draw(ws_connectingImg,-20,20*i-120)
elseif status=='running'then
gc_setColor(1,1,1)
gc_draw(ws_runningImg,-20,20*i-20)
gc_draw(ws_runningImg,-20,20*i-120)
end
local t1,t2,t3=WS.getTimers(WSnames[i])
gc_setColor(1,1,1,t1)gc_rectangle('fill',-60,20*i,-20,-20)
gc_setColor(0,1,0,t2)gc_rectangle('fill',-40,20*i,-20,-20)
gc_setColor(1,0,0,t3)gc_rectangle('fill',-20,20*i,-20,-20)
gc_setColor(1,1,1,t1)gc_rectangle('fill',-60,20*i-100,-20,-20)
gc_setColor(0,1,0,t2)gc_rectangle('fill',-40,20*i-100,-20,-20)
gc_setColor(1,0,0,t3)gc_rectangle('fill',-20,20*i-100,-20,-20)
end
gc_pop()

View File

@@ -4,43 +4,38 @@ return function(name,libName)
if r1 and r2 then
return r2
else
LOG.print("Cannot load "..name..": "..(r2 or r3),'warn',COLOR.R)
LOG.print("Cannot load "..name..": "..(r2 or r3),'warn')
end
elseif SYSTEM=="Android"then
local fs=love.filesystem
local platform={'arm64-v8a','armeabi-v7a'}
local libFunc=package.loadlib(SAVEDIR.."/lib/"..libName.Android,libName.libFunc)
if libFunc then
LOG.print(name.." lib loaded",'warn',COLOR.G)
else
for i=1,#platform do
local soFile=fs.read('data',"libAndroid/"..platform[i].."/"..libName.Android)
if soFile then
local success,message=fs.write("lib/"..libName.Android,soFile)
if success then
libFunc,message=package.loadlib(SAVEDIR.."/lib/"..libName.Android,libName.libFunc)
if libFunc then
LOG.print(name.." lib loaded",'warn',COLOR.G)
break
else
LOG.print("Cannot load "..name..": "..message,'warn',COLOR.R)
end
for i=1,#platform do
local soFile,_,_,mes1=fs.read('data',"libAndroid/"..platform[i].."/"..libName.Android)
if soFile then
local success,mes2=fs.write("lib/"..libName.Android,soFile)
if success then
libFunc,mes2=package.loadlib(SAVEDIR.."/lib/"..libName.Android,libName.libFunc)
if libFunc then
LOG.print(name.." lib loaded",'message')
break
else
LOG.print("Write "..name.."-"..platform[i].." to saving failed: "..message,'warn',COLOR.R)
LOG.print("Cannot load "..name..": "..mes2,'error')
end
else
LOG.print("Read "..name.."-"..platform[i].." failed",'warn',COLOR.R)
LOG.print(("Write %s-%s to saving failed: %s"):format(name,platform[i],mes2),'error')
end
else
LOG.print(("Read %s-%s to saving failed: %s"):format(name,platform[i],mes1),'error')
end
if not libFunc then
LOG.print("Cannot load "..name,'warn',COLOR.R)
return
end
end
if not libFunc then
LOG.print("Cannot load "..name,'error')
return
end
return libFunc()
else
LOG.print("No "..name.." for "..SYSTEM,'warn',COLOR.R)
LOG.print("No "..name.." for "..SYSTEM,'error')
return
end
return true

View File

@@ -35,36 +35,26 @@ function LOG.draw()
end
end
end
function LOG.print(text,T,C)--text,type/time/color,color
local time
local his
if T=='warn'then
C=C or COLOR.Y
his=true
time=180
function LOG.print(text,T)--text,type/time/color,color
local color=COLOR.Z
local time,his
if T=='message'then
color=COLOR.N
his,time=true,180
elseif T=='warn'then
color=COLOR.Y
his,time=true,180
elseif T=='error'then
C=C or COLOR.R
his=true
time=210
elseif T=='message'then
C=C or COLOR.N
his=true
color=COLOR.R
his,time=true,210
elseif type(T)=='number'then
C=C or COLOR.Z
time=T
elseif type(T)=='table'then
C=T
elseif not C then
C=COLOR.Z
end
if his then
ins(debugMesHistory,SCN.cur..": "..tostring(text))
end
ins(debugMesList,{text=tostring(text),r=C[1],g=C[2],b=C[3],blink=30,time=time or 120})
if his then ins(debugMesHistory,SCN.cur..": "..tostring(text))end
ins(debugMesList,{text=tostring(text),r=color[1],g=color[2],b=color[3],blink=30,time=time or 120})
end
function LOG.copy()
local str=table.concat(debugMesHistory,"\n")
love.system.setClipboardText(str)
LOG.print("Log copied",COLOR.B)
love.system.setClipboardText(table.concat(debugMesHistory,"\n"))
LOG.print("Log copied",'message')
end
return LOG

View File

@@ -141,10 +141,10 @@ function profile.switch()
profile.stop()
love.system.setClipboardText(PROFILE.report())
PROFILE.reset()
LOG.print("profile report copied!")
LOG.print("profile report copied!",'message')
else
PROFILE.start()
LOG.print("profile start!")
LOG.print("profile start!",'message')
end
switch=not switch
end

View File

@@ -17,7 +17,7 @@ function SFX.init(list)
if love.filesystem.getInfo(N)then
Sources[list[i]]={love.audio.newSource(N,'static')}
else
LOG.print("No SFX file: "..N,5,COLOR.O)
LOG.print("No SFX file: "..N,5)
end
if not skip and i~=count then
coroutine.yield()

View File

@@ -16,6 +16,12 @@ do--function STRING.shiftChar(c)
end
end
function STRING.trim(str)
if not str:find("%S")then return""end
str=str:sub((str:find("%S"))):reverse()
return str:sub((str:find("%S"))):reverse()
end
function STRING.split(s,sep,regex)
local L={}
local p1,p2=1--start,target

View File

@@ -48,15 +48,15 @@ function THEME.set(theme)
elseif theme=='xmas'then
BG.setDefault('snow')
BGM.setDefault('xmas')
LOG.print("==============",COLOR.R)
LOG.print("Merry Christmas!",COLOR.Z)
LOG.print("==============",COLOR.R)
LOG.print("==============")
LOG.print("Merry Christmas!")
LOG.print("==============")
elseif theme=='sprfes'then
BG.setDefault('firework')
BGM.setDefault("spring festival")
LOG.print(" ★☆☆★",COLOR.R)
LOG.print("新年快乐!",COLOR.Z)
LOG.print(" ★☆☆★",COLOR.R)
LOG.print(" ★☆☆★")
LOG.print("新年快乐!")
LOG.print(" ★☆☆★")
elseif theme=='zday1'then
BG.setDefault('lanterns')
BGM.setDefault("empty")

View File

@@ -45,7 +45,7 @@ function VOC.init(list)
if n==1 then
if not loadVoiceFile(list[i],list[i])then
LOG.print("No VOICE file: "..list[i],5,COLOR.O)
LOG.print("No VOICE file: "..list[i],5)
end
end
if not Source[list[i]][1]then Source[list[i]]=nil end

View File

@@ -1,8 +1,7 @@
-- local host="127.0.0.1"
-- local host="192.168.114.102"
-- local host="krakens.tpddns.cn"
-- local host="hdustea.3322.org"
local host="game.techmino.org"
local host="krakens.tpddns.cn"
-- local host="game.techmino.org"
local port="10026"
local path="/tech/socket/v1"

View File

@@ -1,12 +1,11 @@
local kb=love.keyboard
local gc=love.graphics
local kb,gc=love.keyboard,love.graphics
local next=next
local int,abs=math.floor,math.abs
local max,min=math.max,math.min
local sub=string.sub
local ins=table.insert
local setFont,mStr=setFont,mStr
local mDraw_X,mDraw_Y=ADRAW.simpX,ADRAW.simpY
local sub,ins=string.sub,table.insert
local getFont,setFont,mStr=getFont,setFont,mStr
local mDraw,mDraw_X,mDraw_Y=ADRAW.draw,ADRAW.simpX,ADRAW.simpY
local clearIcon=DOGC{40,40,
{'setLW',6},
@@ -519,7 +518,7 @@ function slider:drag(x)
if p~=P then
self.code(P)
end
if self.change and TIME()-self.lastTime>.18 then
if self.change and TIME()-self.lastTime>.26 then
self.lastTime=TIME()
self.change()
end
@@ -896,7 +895,7 @@ function textBox:update()
end
function textBox:push(t)
ins(self.texts,t)
if self.scrollPos==#self.texts-1 and not self.hide then
if self.scrollPos==#self.texts-1 then
self.scrollPos=#self.texts
else
self.new=true
@@ -1035,7 +1034,7 @@ WIDGET.indexMeta={
end
}
function WIDGET.set(list)
WIDGET.sel=false
WIDGET.unFocus()
WIDGET.active=list or NONE
--Reset all widgets
@@ -1072,23 +1071,42 @@ function WIDGET.setLang(widgetText)
end
end
end
function WIDGET.isFocus(W)
return W==nil and WIDGET.sel or WIDGET.sel==W
end
function WIDGET.focus(W)
if WIDGET.sel==W then return end
if WIDGET.sel and WIDGET.sel.type=='inputBox'then kb.setTextInput(false)end
WIDGET.sel=W
if W and W.type=='inputBox'then
local _,y1=SCR.xOy:transformPoint(0,W.y+W.h)
kb.setTextInput(true,0,y1,1,1)
end
end
function WIDGET.unFocus(force)
local W=WIDGET.sel
if W and(force or not W.keepFocus)then
if W.type=='inputBox'then kb.setTextInput(false)end
WIDGET.sel=false
end
end
function WIDGET.cursorMove(x,y)
for _,W in next,WIDGET.active do
if not W.hide and W.resCtr and W:isAbove(x,y)then
WIDGET.sel=W
WIDGET.focus(W)
return
end
end
if WIDGET.sel and not WIDGET.sel.keepFocus then
WIDGET.sel=false
WIDGET.unFocus()
end
end
function WIDGET.press(x,y,k)
local W=WIDGET.sel
if not W then return end
W:press(x,y,k)
if W.hide then WIDGET.sel=false end
if W.hide then WIDGET.unFocus()end
end
function WIDGET.drag(x,y,dx,dy)
local W=WIDGET.sel
@@ -1096,7 +1114,7 @@ function WIDGET.drag(x,y,dx,dy)
if W.type=='slider'or W.type=='textBox'then
W:drag(x,y,dx,dy)
elseif not W:isAbove(x,y)then
WIDGET.sel=false
WIDGET.unFocus(true)
end
end
function WIDGET.release(x,y)
@@ -1107,25 +1125,24 @@ function WIDGET.release(x,y)
end
end
function WIDGET.keyPressed(k)
local W=WIDGET.sel
if k=="space"or k=="return"then
WIDGET.press()
elseif kb.isDown("lshift","lalt","lctrl")and(k=="left"or k=="right")then
--When hold [↑], control slider with left/right
local W=WIDGET.sel
if W and W.type=='slider'or W.type=='selector'then
W:arrowKey(k=="left")
end
elseif k=="up"or k=="down"or k=="left"or k=="right"then
if not WIDGET.sel then
for _,W in next,WIDGET.active do
if not W.hide and W.isAbove then
WIDGET.sel=W
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
return
end
local W=WIDGET.sel
if not W.getCenter then return end
local WX,WY=W:getCenter()
local dir=(k=="right"or k=="down")and 1 or -1
@@ -1151,10 +1168,9 @@ function WIDGET.keyPressed(k)
end
end
if tar then
WIDGET.sel=tar
WIDGET.focus(tar)
end
else
local W=WIDGET.sel
if W and W.type=='inputBox'then
W:keypress(k)
end
@@ -1205,12 +1221,7 @@ end
function WIDGET.update()
for _,W in next,WIDGET.active do
if W.hideF then
local h=W.hideF()
if h~=W.hide then
W.hide=h
end
end
if W.hideF then W.hide=W.hideF()end
if W.update then W:update()end
end
end

View File

@@ -1,7 +1,8 @@
VERSION={
code=1407,
string="Alpha V0.14.7",
name="烈日 Burn",
code=1501,
short="V0.15.1",
string="Alpha V0.15.1",
name="耀斑 Flare",
}
function love.conf(t)
t.identity='Techmino'--Saving folder

View File

@@ -82,10 +82,10 @@ SKIN= require"parts.skin"
USERS= require"parts.users"
NET= require"parts.net"
VK= require"parts.virtualKey"
PLY= require"parts.player"
netPLY= require"parts.netPlayer"
AIFUNC= require"parts.ai"
AIBUILDER= require"parts.AITemplate"
PLY= require"parts.player"
netPLY= require"parts.netPlayer"
MODES= require"parts.modes"
--Initialize field[1]
@@ -167,7 +167,7 @@ SFX.init((function()
if fs.getRealDirectory("media/SFX/"..v)~=SAVEDIR then
table.insert(L,v:sub(1,-5))
else
LOG.print("Dangerous file : %SAVE%/media/SFX/"..v)
LOG.print("Dangerous file : %SAVE%/media/SFX/"..v,'warn')
end
end
return L
@@ -178,7 +178,7 @@ BGM.init((function()
if fs.getRealDirectory("media/BGM/"..v)~=SAVEDIR then
table.insert(L,v:sub(1,-5))
else
LOG.print("Dangerous file : %SAVE%/media/BGM/"..v)
LOG.print("Dangerous file : %SAVE%/media/BGM/"..v,'warn')
end
end
return L
@@ -236,18 +236,16 @@ for _,v in next,fs.getDirectoryItems("parts/scenes")do
LANG.addScene(sceneName)
end
end
LANG.set(SETTING.lang)
--Update data
do
local needSave
local autoRestart
local needSave,autoRestart
if type(STAT.version)~='number'then
STAT.version=0
needSave=true
end
if STAT.version<1300 then
if STAT.version<1302 then
STAT.frame=math.floor(STAT.time*60)
STAT.lastPlay='sprint_10l'
RANKS.sprintFix=nil
@@ -256,38 +254,30 @@ do
for _,name in next,fs.getDirectoryItems("replay")do
fs.remove("replay/"..name)
end
end
if STAT.version<1302 then
if RANKS.pctrain_n then RANKS.pctrain_n=0 end
if RANKS.pctrain_l then RANKS.pctrain_l=0 end
fs.remove("conf/settings")
needSave=true
autoRestart=true
end
if STAT.version<1400 then
if STAT.version<1405 then
fs.remove("conf/user")
fs.remove("conf/key")
needSave=true
autoRestart=true
end
if STAT.version<1405 then
fs.remove("conf/user")
autoRestart=true
end
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then
SETTING.frameMul=100
end
SETTING.appLock=nil
for _,v in next,VK_org do v.color=nil end
if STAT.version~=VERSION.code then
STAT.version=VERSION.code
CLEAR("lib")
needSave=true
autoRestart=true
end
if not SETTING.VKSkin then SETTING.VKSkin=1 end
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then
SETTING.frameMul=100
end
SETTING.appLock=nil
for _,v in next,VK_org do v.color=nil end
if RANKS.GM then RANKS.GM=0 end
if RANKS.infinite then RANKS.infinite=6 end
if RANKS.infinite_dig then RANKS.infinite_dig=6 end
@@ -326,4 +316,7 @@ do
if autoRestart then
love.event.quit('restart')
end
end
end
LANG.set(SETTING.lang)
VK.setShape(SETTING.VKSkin)

BIN
media/SFX/connect.ogg Normal file

Binary file not shown.

BIN
media/SFX/connected.ogg Normal file

Binary file not shown.

View File

@@ -4,6 +4,8 @@ local int=math.floor
local char,byte=string.char,string.byte
local ins=table.insert
local BAG,FIELD,MISSION,CUSTOMENV,GAME=BAG,FIELD,MISSION,CUSTOMENV,GAME
local DATA={}
--Sep symbol: 33 (!)
--Safe char: 34~126
@@ -14,7 +16,6 @@ local DATA={}
Example: "abcdefg" is [SZJLTOI], "a^aDb)" is [Z*63,Z*37,S*10]
]]
function DATA.copySequence()
local BAG=BAG
local str=""
local count=1
@@ -111,24 +112,22 @@ function DATA.pasteBoard(str,page)--Paste [str] data to [page] board
if not page then page=1 end
if not FIELD[page]then FIELD[page]=DATA.newBoard()end
local F=FIELD[page]
local _,__
--Decode
if not str:find("%S")then return end
str=str:sub((str:find("%S"))):reverse()
str=str:sub((str:find("%S"))):reverse()
_,str=pcall(data.decode,'string','base64',str)
if not _ then return end
_,str=pcall(data.decompress,'string','zlib',str)
if not _ then return end
local res
str=STRING.trim(str)
res,str=pcall(data.decode,'string','base64',str)
if not res then return end
res,str=pcall(data.decompress,'string','zlib',str)
if not res then return end
local fX,fY=1,1--*ptr for Field(r*10+(c-1))
local p=1
while true do
_=byte(str,p)--1byte
local b=byte(str,p)--1byte
--Str end
if not _ then
if not b then
if fX~=1 then
return
else
@@ -136,11 +135,11 @@ function DATA.pasteBoard(str,page)--Paste [str] data to [page] board
end
end
__=_%32-1--Block id
if __>26 then return end--Illegal blockid
_=int(_/32)--Mode id
local id=b%32-1--Block id
if id>26 then return end--Illegal blockid
b=int(b/32)--Mode id
F[fY][fX]=__
F[fY][fX]=id
if fX<10 then
fX=fX+1
else
@@ -178,7 +177,6 @@ end
]]
function DATA.copyMission()
local _
local MISSION=MISSION
local str=""
local count=1
@@ -364,7 +362,7 @@ do--function DATA.saveRecording()
--Filtering modes that cannot be saved
for _,v in next,noRecList do
if GAME.curModeName:find(v)then
LOG.print("Cannot save recording of this mode now!",COLOR.N)
LOG.print("Cannot save recording of this mode now!",'warn')
return
end
end
@@ -388,7 +386,7 @@ do--function DATA.saveRecording()
FILE.save(REPLAY,'conf/replay')
return true
else
LOG.print("Save failed: File already exists")
LOG.print("Save failed: File already exists",'error')
end
end
end

View File

@@ -1,4 +1,3 @@
local kb=love.keyboard
local gc=love.graphics
local gc_push,gc_pop=gc.push,gc.pop
local gc_origin,gc_translate=gc.origin,gc.translate
@@ -11,8 +10,8 @@ local ins,rem=table.insert,table.remove
local SETTING,GAME,SCR=SETTING,GAME,SCR
--System
function enableTextInput()if not MOBILE then kb.setTextInput(true)end end
function switchFullscreen()
SETTING.fullscreen=not SETTING.fullscreen
love.window.setFullscreen(SETTING.fullscreen)
@@ -245,7 +244,6 @@ function loadGame(M,ifQuickPlay,ifNet)--Load a mode and go to game scene
end
function gameOver()--Save record
if GAME.replaying then return end
FILE.save(STAT,'conf/data')
local M=GAME.curMode
local R=M.getRank
if R then
@@ -434,9 +432,10 @@ do--function resetGameData(args)
end
function resetGameData(args,seed)
if not args then args=""end
if PLAYERS[1]and not GAME.replaying and(PLAYERS[1].frameRun>400 or GAME.result)then
if PLAYERS[1]and not GAME.replaying and(PLAYERS[1].frameRun>300 or GAME.result)then
mergeStat(STAT,PLAYERS[1].stat)
STAT.todayTime=STAT.todayTime+PLAYERS[1].stat.time
FILE.save(STAT,'conf/data','q')
end
GAME.result=false
@@ -545,36 +544,6 @@ end
--Game draw
do--function drawFWM()
local m={
string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
string.char(65,117,116,104,111,114,58,32,77,114,90,95,50,54,10,82,101,99,111,114,100,105,110,103,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,105,115,10,119,97,116,101,114,109,97,114,107,32,97,114,101,32,117,110,97,117,116,104,111,114,105,122,101,100),
string.char(67,114,195,169,97,116,101,117,114,32,100,117,32,106,101,117,58,32,77,114,90,95,50,54,10,69,110,114,101,103,105,115,116,114,101,109,101,110,116,32,110,111,110,32,97,117,116,111,114,105,115,195,169,10,99,111,110,116,101,110,97,110,116,32,99,101,32,102,105,108,105,103,114,97,110,101),
string.char(65,117,116,111,114,58,32,77,114,90,95,50,54,10,71,114,97,98,97,99,105,195,179,110,32,110,111,32,97,117,116,111,114,105,122,97,100,97,32,113,117,101,10,99,111,110,116,105,101,110,101,32,101,115,116,97,32,109,97,114,99,97,32,100,101,32,97,103,117,97),
string.char(65,117,116,111,114,32,100,111,32,106,111,103,111,58,32,77,114,90,95,50,54,10,71,114,97,118,97,195,167,195,181,101,115,32,99,111,110,116,101,110,100,111,32,101,115,116,97,32,77,97,114,99,97,10,100,101,32,195,161,103,117,97,32,110,195,163,111,32,115,195,163,111,32,97,117,116,111,114,105,122,97,100,97,115),
string.char(65,117,116,104,111,114,58,32,77,114,90,95,50,54,10,82,101,99,111,114,100,105,110,103,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,105,115,10,119,97,116,101,114,109,97,114,107,32,97,114,101,32,117,110,97,117,116,104,111,114,105,122,101,100),
}
--你竟然找到了这里!那么在动手之前读读下面这些吧。
--【魔幻错别字躲关键字搜索警告,看得懂就行】
--千万不要为了在网络公共场合发视屏或者直播需要而擅自删除这部分代码!
--录制视屏上传到公共场合(包括但不限于任何视屏平台/论坛/好几十个人及以上的非方块社区/群等)很可能会对Techmino未来的发展有负面影响
--如果被TTC发现随时可能被他们用DMCA从法律层面强迫停止开发到时候谁都没得玩。这是真的已经有几个方块这么死了…
--氵印限制还可以减少低质量视屏泛滥,也能减轻过多不是真的感兴趣路人玩家入坑可能带来的压力
--想发视屏的话请先向作者申请,描述录制的大致内容,同意了才可以去关闭氵印
--等Techmino发展到一定程度之后会解除这个限制
--最后,别把藏在这里的东西截图/复制出去哦~
--感谢您对Techmino的支持!!!
local sin=math.sin
local setFont,TIME,mStr=setFont,TIME,mStr
function drawFWM()
local t=TIME()
setFont(25)
gc.setColor(1,1,1,.2+.1*(sin(3*t)+sin(2.6*t)))
mStr(m[_G["\83\69\84\84\73\78\71"]["\108\97\110\103"]or m[1]],240,60+26*sin(t))
end
end
do--function drawSelfProfile()
local name
local textObject,scaleK,width,offY
@@ -608,7 +577,7 @@ do--function drawSelfProfile()
gc_pop()
end
end
do
do--function drawOnlinePlayerCount()
function drawOnlinePlayerCount()
setFont(20)
gc_setColor(1,1,1)
@@ -629,6 +598,20 @@ do--function drawWarning()
end
end
end
do--function drawSystemInfo(
--你竟然找到了这里!那么在动手之前读读下面这些吧。
--【魔幻错别字躲关键字搜索警告,看得懂就行】
--千万不要为了在网络公共场合发视屏或者直播需要而擅自删除这部分代码!
--录制视屏上传到公共场合(包括但不限于任何视屏平台/论坛/好几十个人及以上的非方块社区/群等)很可能会对Techmino未来的发展有负面影响
--如果被TTC发现随时可能被他们用DMCA从法律层面强迫停止开发到时候谁都没得玩。这是真的已经有几个方块这么死了…
--氵印限制还可以减少低质量视屏泛滥,也能减轻过多不是真的感兴趣路人玩家入坑可能带来的压力
--想发视屏的话请先向作者申请,描述录制的大致内容,同意了才可以去关闭氵印
--等Techmino发展到一定程度之后会解除这个限制
--最后,别把藏在这里的东西截图/复制出去哦~
--感谢您对Techmino的支持!!!
loadstring(love.data.decode('string','base64',"CWxvY2FsIGc9bG92ZS5ncmFwaGljcztsb2NhbCB4LHMsVCxkLGM9Zy5uZXdUZXh0KGdldEZvbnQoMjUpKSxtYXRoLnNpbixUSU1FLGcuZHJhdyxnLnNldENvbG9yO3g6c2V0ZigiQXV0aOS9nOiAhTpNclpfMjZcbkFscGhh5YaF5rWL56aB5q2i5b2V5bGPL+ebtOaSrVxuTm8gcmVjb3JkaW5nL3N0cmVhbWluZyIsMzAwLCdjZW50ZXInKWZ1bmN0aW9uIGRyYXdGV00oKWxvY2FsIHQ9VCgpYygxLDEsMSwuMTYrLjA2KihzKDMuNTUqdCkrcygyLjYqdCkpKWQoeCwzMCw3Mys1MypzKHQqLjI2KSllbmQK"))()
end
--Widget function shortcuts

View File

@@ -281,14 +281,15 @@ SETTING={--Settings
text=true,
score=true,
warn=true,
bufferWarn=false,
highCam=false,
nextPos=false,
bufferWarn=true,
showSpike=true,
highCam=true,
nextPos=true,
fullscreen=true,
bg=true,
powerInfo=false,
clickFX=true,
warn=true,
--Sound
sfx=1,
@@ -304,6 +305,7 @@ SETTING={--Settings
VKSFX=.2,--SFX volume
VKVIB=0,--VIB
VKSwitch=false,--If disp
VKSkin=1,--If disp
VKTrack=false,--If tracked
VKDodge=false,--If dodge
VKTchW=.3,--Touch-Pos Weight

View File

@@ -6,6 +6,12 @@ return{
"help",
"This translation of the TetroDictionary is provided by me, User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text."
},
{"Official website",
"official website homepage",
"help",
"Official website of Techmino!\nYou can modify your profile on it",
"http://home.techmino.org",
},
{"To New Players",
"guide newbie noob",
"help",
@@ -377,7 +383,6 @@ return{
"term",
"Special T-Spin techniques that exploit the T piece's kicks and T-Spin detections.\nThey might worth different values in different games (some games consider them Minis), and hardly have real value in combat due to their relatively complex setup.",
},
{"Modern Stack-game",
"modern",
"term",
@@ -438,6 +443,11 @@ return{
"term",
"Known in Japan as REN.\nConsecutive line clears make up combos. The second line clear in the combo is 1 combo, and the third line clear is 2 combo, and so on.\nUnlike Back to Back, placing a piece that does not clear a line will break the combo.",
},
{"Spike",
"spike",
"term",
"",--TODO:"爆发攻击\n指短时间内打出大量的攻击本游戏和TETR.IO中有spike计数器可以看到自己短时间内打出了多少攻击。\n注意网络卡顿导致的累计攻击瞬间释放不算spike。",
},
{"Side well",
"sidewell",
"term",

View File

@@ -7,6 +7,12 @@ return{
"致想深入玩下去的新人:\n\t两大根本原则:\n\t\t1.选手感好的版本(Techmino/Tetr.io/Jstris/TOP/Tetr.js),别用编程练习渣版本\n\t\t2.踏实打好基础(预判next稳定消四等)别总想着炫酷T旋对未来发展没好处\n\t两大主要技巧:\n\t\t1.熟悉初始位置以及到各个位置的初始操作\n\t\t2.提前计算好下一块能放哪\n(推荐阅读专栏)一位块圈dalao给新人的话\n\n[点击右下角按钮打开链接]",
"https://bilibili.com/read/cv2352939",
},
{"游戏官网",
"official website homepage guanwang",
"help",
"Techmino的官网!\n可以在上面修改头像和个人信息",
"http://home.techmino.org",
},
{"Tetris Wiki",
"tetris wiki",
"help",
@@ -363,7 +369,7 @@ return{
"Techmino Rotation System\nTechmino独有的旋转系统基于SRS设计修补了一些常见SZ卡死的地形增加了不少实用踢墙每个五连块也基本按照SRS的spin逻辑单独设计了踢墙表。",
},
--术语(游戏内名词)
--术语(其他)
{"B2B",
"大满贯 b2b btb backtoback",
"term",
@@ -379,8 +385,6 @@ return{
"term",
"一种特殊T2的名字不同的游戏内的攻击可能不一样没有特殊价值可以不详细了解。",
},
--术语(其他)
{"现代方块",
"现代方块 modern xiandaikuai",
"term",
@@ -441,6 +445,11 @@ return{
"term",
"从第二次消除起叫1ren/combo打出的攻击根据游戏设计的不同也不同",
},
{"Spike",
"spike baofa xingbao",
"term",
"爆发攻击\n指短时间内打出大量的攻击本游戏和TETR.IO中有spike计数器可以看到自己短时间内打出了多少攻击。\n注意网络卡顿导致的累计攻击瞬间释放不算spike。",
},
{"Side",
"连击 ·side",
"term",
@@ -810,27 +819,27 @@ return{
{"重置设置",
"reset setting chongzhi qingkong shezhi",
"command",
"前往控制台输入\"rm conf/setting\"并回车\n需要重启游戏生效,若反悔,进入设置菜单再退出即可恢复文件",
"前往控制台输入\"rm conf/setting\"并回车\n需要重启游戏生效若反悔进入设置菜单再退出即可恢复文件",
},
{"重置统计数据",
"reset statistic data chongzhi tongji shuju",
"command",
"前往控制台输入\"rm conf/data\"并回车\n需要重启游戏生效,若反悔,玩一局并触发结算即可恢复文件",
"前往控制台输入\"rm conf/data\"并回车\n需要重启游戏生效若反悔玩一局并触发结算即可恢复文件",
},
{"重置解锁状态",
"reset unlock chongzhi qingkong jiesuo",
"command",
"前往控制台输入\"rm conf/unlock\"并回车\n需要重启游戏生效,若反悔,刷新任意一个模式在地图上的状态即可恢复文件",
"前往控制台输入\"rm conf/unlock\"并回车\n需要重启游戏生效若反悔刷新任意一个模式在地图上的状态即可恢复文件",
},
{"重置本地排行榜",
"reset chongzhi paihangbang",
"command",
"前往控制台输入\"rm -s record\"并回车\n需要重启游戏生效,若反悔,玩一局并更新模式排行榜即可恢复对应模式的单个排行榜文件",
"前往控制台输入\"rm -s record\"并回车\n需要重启游戏生效若反悔玩一局并更新模式排行榜即可恢复对应模式的单个排行榜文件",
},
{"删除键位",
"reset virtualkey",
"command",
"前往控制台输入\"rm conf/键位文件\"并回车\n键盘是key,虚拟按键是virtualkey,虚拟按键预设是vkSave1(2)\n前两者重启生效,若反悔,进入对应的设置菜单再返回即可恢复文件",
"前往控制台输入\"rm conf/键位文件\"并回车\n键盘是key虚拟按键是virtualkey虚拟按键预设是vkSave1(2)\n前两者重启生效若反悔进入对应的设置菜单再返回即可恢复文件",
},
{"删除录像",
"reset replay luxiang",

View File

@@ -17,7 +17,6 @@ return{
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash"},
mini="Mini",b2b="B2B ",b3b="B2B2B ",
PC="Perfect Clear",HPC="Hemi-Perfect Clear",
hold="HOLD",next="NEXT",
replaying="[Replay]",
stage="Stage $1",
@@ -78,7 +77,6 @@ return{
getVersionFail="Update detection failed",
oldVersion="Version $1 is now available!",
needUpdate="Newer version required!",
noInternet="Not connected to the network",
notFinished="Coming soon!",
jsonError="JSON error",
@@ -93,6 +91,8 @@ return{
loginFailed="Failed to log in.",
accessSuccessed="Access Granted.",
accessFailed="Access Denied.",
wsConnecting="Websocket: Connecting",
wsSuccessed="WebSocket: Connected.",
wsFailed="WebSocket: Connection Failed.",
wsClose="WebSocket Closed: ",
@@ -105,9 +105,11 @@ return{
started="Playing",
joinRoom="has joined the room.",
leaveRoom="has left the room.",
ready="READY",
set="SET",
ready="Ready",
connStream="Connecting",
waitStream="Waiting",
champion="$1 won",
spectating="Spectating",
chatRemain="Online",
chatStart="------Beginning of log------",
chatHistory="------New messages below------",
@@ -265,6 +267,7 @@ return{
},
net_game={
ready="Ready",
spectate="Spectate",
cancel="Cancel",
},
setting_game={
@@ -309,8 +312,8 @@ return{
text="Line Clear Pop-up",
score="Score Pop-up",
warn="Danger Alert",
bufferWarn="Buffer Alert",
showSpike="Spike Counter",
highCam="Screen Scrolling",
nextPos="Next Preview",
@@ -318,6 +321,7 @@ return{
power="Power Info",
clickFX="Click FX",
bg="Background",
warn="Danger Alert",
clean="Fast Draw",
},
setting_sound={
@@ -385,6 +389,7 @@ return{
save2="Save2",
load2="Load2",
size="Size",
shape="Shape",
},
setting_touchSwitch={
b1= "Move Left:", b2="Move Right:", b3="Rotate Right:", b4="Rotate Left:",
@@ -694,7 +699,7 @@ return{
['dig_400l']= {"Dig", "400L", "Dig 400 garbage lines."},
['dig_1000l']= {"Dig", "1000L", "Dig 1000 garbage lines."},
['drought_n']= {"Drought", "100L", "There are no I-pieces."},
['drought_l']= {"Drought", "100L", "W T F"},
['drought_l']= {"Drought+", "100L", "W T F"},
['marathon_n']= {"Marathon", "NORMAL", "200-line marathon with accelerating speed."},
['marathon_h']= {"Marathon", "HARD", "200-line high-speed marathon."},
['solo_e']= {"Battle", "EASY", "Defeat the AI!"},
@@ -747,6 +752,7 @@ return{
['pc_n']= {"PC Challenge", "NORMAL", "Get PCs within 100 lines!"},
['pc_h']= {"PC Challenge", "HARD", "Get PCs within 100 lines!"},
['pc_l']= {"PC Challenge", "LUNATIC", "Get PCs within 100 lines!"},
['pc_inf']= {"Infinite PC Challenge","", "Get PCs as much as you can"},
['tech_n']= {"Tech", "NORMAL", "Try to keep the\nBack-to-Back chain!"},
['tech_n_plus']= {"Tech", "NORMAL+", "Spins & PCs only."},
['tech_h']= {"Tech", "HARD", "Try to keep the\nBack-to-Back chain!"},
@@ -789,6 +795,7 @@ return{
"40-line Sprint WR: 15.654s by VinceHD",
"6next 1hold!",
"6next 6hold?!",
"Achievement system coming soon!",
"ALL SPIN!",
"Am G F G",
"B2B2B???",
@@ -809,15 +816,14 @@ return{
"Got any suggestions? Post them in our Discord!",
"Headphones recommended for a better experience.",
"Hello world!",
"if a==true",
"I3 and L3 are the only two unique triminoes.",
"if a==true",
"Increase your frame rate for a better experience.",
"Initial [insert action] system can save you.",
"Is B2B2B2B possible?",
"It's possible to finish 40L without left/right button.",
"It's really loading! Not just a cutscene!",
"Join our discord!",
"l-=-1",
"Let the bass kick!",
"LrL RlR LLr RRl RRR LLL FFF RfR RRf rFF",
"Lua No.1",
@@ -828,12 +834,14 @@ return{
"O-Spin Triple!",
"OHHHHHHHHHHHHHH",
"Online mode is planned - please be patient.",
"Playing good takes some time!",
"Play single-handedly!",
"Playing good takes some time!",
"Powered by Love2D",
"Powered by Un..Love2D",
"pps-0.01",
"REGRET!!",
"Secret number: 626",
"Server down randomly",
"Some requirements to achieve rank S are intentionally set to be difficult for even the best players.",
"Soon, you'll be able to play against friends and foes all over the world.",
"Split clear coming soon!",
@@ -845,6 +853,7 @@ return{
"There are three hidden modes in the game.",
"There is a total of 18 different pentominoes.",
"There is a total of 7 different tetrominoes.",
"Try multi-hold!",
"Try using two rotate buttons. All three is better.",
"Warning: Programmer Art",
"What about 20 PCs?",
@@ -862,11 +871,12 @@ return{
{C.C,"Also try 15puzzle!"},
{C.C,"Also try Minecraft!"},
{C.C,"Also try Minesweeper!"},
{C.C,"Also try Orzmic!"},
{C.C,"Also try osu!"},
{C.C,"Also try Phigros!"},
{C.C,"Also try Rubic's cube!"},
{C.C,"Also try Terraria!"},
{C.C,"Also try VVVVVVV!"},
{C.C,"Also try VVVVVV!"},
{C.F,"Also try Cultris II!"},
{C.F,"Also try Jstris"},
{C.F,"Also try NullpoMino!"},

View File

@@ -16,7 +16,6 @@ return{
clear={"Simple","Double","Triple","Techrash","Pentacrash","Hexacrash"},
mini="Mini",b2b="B2B ",b3b="B2B2B ",
PC="Perfect Clear",HPC="Clear",
hold="RESERVE",next="SUIVANT",
replaying="[Replay]",
stage="Etape $1",
@@ -78,7 +77,6 @@ return{
getVersionFail="Echec d'obtention de la dernière version",
oldVersion="La version $1 est disponible !",
-- needUpdate="Newer version required!",
-- noInternet="Not connected to the network",
-- notFinished="Coming soon!",
jsonError="Erreur json",
@@ -93,6 +91,8 @@ return{
loginFailed="Erreur de connexion",
accessSuccessed="Autorisé avec succès !",
accessFailed="Autorisation échouée",
-- wsConnecting="Websocket: Connecting",
wsSuccessed="WebSocket: connecté",
wsFailed="WebSocket: connection échouée",
-- wsClose="WebSocket Closed: ",
@@ -106,8 +106,10 @@ return{
joinRoom="a rejoint le salon.",
leaveRoom="a quitté le salon.",
-- ready="READY",
-- set="SET",
-- connStream="CONNECTING",
-- waitStream="WAITING",
champion="$1 a gagné",
-- spectating="Spectating",
chatRemain="En ligne : ",
chatStart="--------Début des logs--------",
chatHistory="-Nouveaux messages en dessous-",
@@ -235,6 +237,7 @@ return{
},
net_game={
-- ready="Ready",
-- spectate="Spectate",
-- cancel="Cancel",
},
setting_game={
@@ -281,7 +284,6 @@ return{
text="Texte d'action",
score="Pop-up de score",
warn="Alerte de danger",
-- bufferWarn="Buffer Alert",
highCam="Vue d'oiseau",
@@ -290,6 +292,7 @@ return{
power="Infos d'alimentation",
-- clickFX="Click FX",
bg="Arrière-plan",
warn="Alerte de danger",
-- clean="Fast Draw",
},
setting_sound={
@@ -355,6 +358,7 @@ return{
-- save2="Save2",
-- load2="Load2",
size="Taille",
-- shape="Shape",
},
setting_touchSwitch={
b1= "Déplacement vers la gauche :",b2="Déplacement vers la droite:",
@@ -605,7 +609,7 @@ return{
['dig_400l']= {"Dig", "400L", "Creusez 400 lines"},
['dig_1000l']= {"Dig", "1000L", "Creusez 1000 lines"},
['drought_n']= {"Drought", "100L", "Pas de pièce I !"},
['drought_l']= {"Drought", "100L", "WTF ??!!"},
['drought_l']= {"Drought+", "100L", "WTF ??!!"},
['marathon_n']= {"Marathon", "NORMAL", "Marathon de 200 lignes."},
['marathon_h']= {"Marathon", "DIFFICILE", "Marathon de 200 lignes à très haute vitesse"},
['solo_e']= {"Battle", "FACILE", "Battez l'IA !"},
@@ -658,6 +662,7 @@ return{
['pc_n']= {"PC Challenge", "NORMAL", "Obtenez un PC dans les prochaines 100 lignes !"},
['pc_h']= {"PC Challenge", "DIFFICILE", "Obtenez un PC dans les prochaines 100 lignes !"},
['pc_l']= {"PC Challenge", "LUNATIQUE", "Obtenez un PC dans les prochaines 100 lignes !"},
['pc_inf']= {"Infinite PC Challenge","", "Get PCs as much as you can"},--TODO
['tech_n']= {"Tech", "NORMAL", "Gardez le B2B !"},
['tech_n_plus']= {"Tech", "NORMAL+", "Spin & PC uniquement"},
['tech_h']= {"Tech", "DIFFICILE", "Gardez le B2B !"},

View File

@@ -17,7 +17,6 @@ return{
clear={"Single","Double","Triple","Techrash","Pentacrash","Hexacrash"},
mini="Mini",b2b="B2B ",b3b="B2B2B ",
PC="Perfect Clear",HPC="Clear",
hold="HOLD",next="NEXT",
replaying="[Replay]",
stage="Fase $1",
@@ -78,7 +77,6 @@ return{
getVersionFail="Falha ao detectar uma versão nova",
oldVersion="Versão $1 esta disponível agora!",
-- needUpdate="Newer version required!",
-- noInternet="Not connected to the network",
-- notFinished="Coming soon!",
jsonError="Json error",
@@ -93,6 +91,8 @@ return{
loginFailed="Falha na autenticação",
accessSuccessed="Autorizado com sucesso!",
accessFailed="Falha na autorização",
-- wsConnecting="Websocket: Connecting",
wsSuccessed="WebSocket: conectado",
wsFailed="WebSocket: falha na conexão",
wsClose="WebSocket closed: ",
@@ -106,7 +106,8 @@ return{
joinRoom="Entrou a sala.",
leaveRoom="Saiu da sala.",
-- ready="READY",
-- set="SET",
-- connStream="CONNECTING",
-- waitStream="WAITING",
-- champion="$1 won",
chatRemain="Online",
chatStart="------Começo do log------",
@@ -265,6 +266,7 @@ return{
},
net_game={
-- ready="Ready",
-- spectate="Spectate",
-- cancel="Cancel",
},
setting_game={
@@ -309,8 +311,8 @@ return{
text="Texto de ação",
score="Pop-up de pontos",
warn="Alerta de perigo",
-- bufferWarn="Buffer Alert",
-- showSpike="Spike Counter",
highCam="Vista Olho-de-pássaro",
nextPos="Próxima Pos.",
@@ -318,6 +320,7 @@ return{
power="Informação bateria",
-- clickFX="Click FX",
bg="Fundo",
warn="Alerta de perigo",
-- clean="Fast Draw",
},
setting_sound={
@@ -385,6 +388,7 @@ return{
-- save2="Save2",
-- load2="Load2",
size="Tamanho",
-- shape="Shape",
},
setting_touchSwitch={
b1= "Esquerda:", b2="Direita:", b3="Giro Dir.:", b4="Giro Esq.:",
@@ -690,7 +694,7 @@ return{
['dig_400l']= {"Cave", "400L", "Cave 400 linhas de lixo."},
['dig_1000l']= {"Cave", "1000L", "Cave 1000 linhas de lixo."},
['drought_n']= {"Drought", "100L", "Sem peça I !"},
['drought_l']= {"Drought", "100L", "WTF"},
['drought_l']= {"Drought+", "100L", "WTF"},
['marathon_n']= {"Maratona", "NORMAL", "200-line Maratona com velocidade aumentando."},
['marathon_h']= {"Maratona", "DIFÍCIL", "200-line Maratona com velocidade alta."},
['solo_e']= {"Batalha", "FÁCIL", "Derrote a inteligência!"},
@@ -743,6 +747,7 @@ return{
['pc_n']= {"Desafio PC", "NORMAL", "Obtenha PCs em 100 linhas!"},
['pc_h']= {"Desafio PC", "DIFÍCIL", "Obtenha PCs em 100 linhas!"},
['pc_l']= {"Desafio PC", "LUNÁTICO", "Obteha PCs em 100 linhas!"},
['pc_inf']= {"Infinite PC Challenge","", "Get PCs as much as you can"},--TODO
['tech_n']= {"Tech", "NORMAL", "Não quebre o B2B!"},
['tech_n_plus']= {"Tech", "NORMAL+", "Apenas spins e PC"},
['tech_h']= {"Tech", "HARD", "Keep the B2B chain!"},

View File

@@ -16,7 +16,6 @@ return{
clear={"Single","Doble","Triple","Techrash","Pentacrash","Hexacrash"},
mini="Mini",b2b="B2B ",b3b="B2B2B ",
PC="Perfect Clear",HPC="Half Clear",
hold="Reserva",next="Sig.",
replaying="[Repetición]",
stage="Nivel $1",
@@ -78,7 +77,6 @@ return{
getVersionFail="Error al buscar nuevas versiones.",
oldVersion="¡Está disponible la nueva versión $1!",
needUpdate="¡Nueva versión requerida!",
-- noInternet="Not connected to the network",
notFinished="Próximamente",
jsonError="Error en Json",
@@ -93,6 +91,8 @@ return{
loginFailed="Error al ingresar",
accessSuccessed="¡Autorizado exitoso!",
accessFailed="Error al autorizar",
-- wsConnecting="Websocket: Connecting",
wsSuccessed="WebSocket: conectado",
wsFailed="WebSocket: conexión fallida",
wsClose="WebSocket cerrado: ",
@@ -106,8 +106,10 @@ return{
joinRoom="entró a la sala.",
leaveRoom="salió de la sala.",
-- ready="READY",
-- set="SET",
-- connStream="CONNECTING",
-- waitStream="WAITING",
champion="$1 ganó!",
-- spectating="Spectating",
chatRemain="Usuarios en línea: ",
chatStart="------Comienzo del historial------",
chatHistory="------Nuevos mensajes------",
@@ -242,6 +244,7 @@ return{
},
net_game={
ready="Estoy Listo",
-- spectate="Spectate",
-- cancel="Cancel",
},
setting_game={
@@ -286,8 +289,8 @@ return{
text="Texto de Acciones",
score="Puntaje en Pantalla",
warn="Alerta de Peligro",
-- bufferWarn="Buffer Alert",
-- showSpike="Spike Counter",
highCam="Cám. Vista Aérea",
nextPos="Ver Spawn de Pza. Sig.",
@@ -295,6 +298,7 @@ return{
power="Inf. de Batería",
-- clickFX="Click FX",
bg="Fondo",
warn="Alerta de Peligro",
clean="Fast Draw",
},
setting_sound={
@@ -358,6 +362,7 @@ return{
-- save2="Save2",
-- load2="Load2",
size="Tamaño",
-- shape="Shape",
},
setting_touchSwitch={
b1= "Mover Izq.:",b2="Mover Der.:",b3="Rotar Der.:",b4="Rotar Izq.:",
@@ -603,7 +608,7 @@ return{
['dig_400l']= {"Queso", "400L", "Limpia 400 líneas de queso."},
['dig_1000l']= {"Queso", "1000L", "Limpia 1000 líneas de queso."},
['drought_n']= {"Sequía", "100L", "¡Sin piezas I!"},
['drought_l']= {"Sequía", "100L", "Guat de foc..."},
['drought_l']= {"Sequía+", "100L", "Guat de foc..."},
['marathon_n']= {"Maratón", "Normal", "Maratón de 200 líneas con velocidad en aumento."},
['marathon_h']= {"Maratón", "Difícil", "Maratón de 200 líneas a velocidad máxima."},
['solo_e']= {"VS.", "Fácil", "¡Derrota a la CPU!"},
@@ -655,6 +660,7 @@ return{
['pc_n']= {"Desafío de PCs", "Normal", "¡Consigue los PCs que puedas en 100 líneas!"},
['pc_h']= {"Desafío de PCs", "Difícil", "¡Consigue los PCs que puedas en 100 líneas!"},
['pc_l']= {"Desafío de PCs", "Lunático", "¡Consigue los PCs que puedas en 100 líneas!"},
['pc_inf']= {"Infinite PC Challenge","", "Get PCs as much as you can"},--TODO
['tech_n']= {"Tech", "Normal", "¡Mantén el B2B!"},
['tech_n_plus']= {"Tech", "Normal+", "¡Sólo se permiten Spins y PCs!"},
['tech_h']= {"Tech", "Difícil", "¡Mantén el B2B!"},

View File

@@ -12,7 +12,6 @@ return{
clear={"1","2","3","4","5","6"},
mini="v",b2b="^ ",b3b="^^ ",
PC="#<>#",HPC="<>",
hold="[ ]",next="",
replaying="[R]",
stage="::$1::",
@@ -168,8 +167,8 @@ return{
text="ABC",
score="+123",
warn="!↑↑↑!",
-- bufferWarn="Buffer Alert",
bufferWarn="^+",
showSpike="→→+",
highCam="↑__↑",
nextPos="???←",
@@ -177,6 +176,7 @@ return{
power="+.",
clickFX="_.~",
bg="__?__",
warn="!↑↑↑!",
clean="[]→→O",
},
setting_sound={
@@ -241,6 +241,7 @@ return{
save2=">2",
load2="2>",
size="←→",
shape="@?",
},
setting_touchSwitch={
b1="←:", b2="→:", b3="R→:", b4="←R:",

View File

@@ -47,6 +47,7 @@ return{
createRoomSuccessed="创好了",
started="开了",
champion="神仙是 $1",
spectating="看戏中",
stat={
"开了几次:",
@@ -83,9 +84,8 @@ return{
text="招式名",
score="跳分",
warn="要死",
bufferWarn="离死差多远",
highCam="拉镜",
warn="要死",
},
setting_sound={
title="改声音",
@@ -204,7 +204,7 @@ return{
['dig_400l']= {"挖掘", "400L", "挖400行"},
['dig_1000l']= {"挖掘", "1000L", "挖1000行"},
['drought_n']= {"干旱", "100L", "放轻松,简单得很"},
['drought_l']= {"干旱", "100L", "有趣的要来了"},
['drought_l']= {"干旱+", "100L", "有趣的要来了"},
['marathon_n']= {"马拉松", "普通", "休闲模式"},
['marathon_h']= {"马拉松", "困难", "休闲模式"},
['solo_e']= {"单挑", "简单", "鲨AI"},
@@ -257,6 +257,7 @@ return{
['pc_n']= {"全清挑战", "普通", "100行内刷PC"},
['pc_h']= {"全清挑战", "困难", "100行内刷PC"},
['pc_l']= {"全清挑战", "疯狂", "100行内刷PC"},
['pc_inf']= {"无尽全清挑战", "", "你这水平还是先别玩了"},
['tech_n']= {"科研", "普通", "禁止断B2B"},
['tech_n_plus']= {"科研", "普通+", "仅允许spin与PC"},
['tech_h']= {"科研", "困难", "禁止断B2B"},
@@ -275,44 +276,11 @@ return{
['zen']= {"", "200", "不限时200行"},
['ultra']= {"限时打分", "挑战", "2分钟刷分"},
['infinite']= {"无尽", "", "真的有人会玩这个?"},
['infinite_dig']= {"无尽:挖掘", "", "闲得慌的话来挖"},
['infinite_dig']= {"无尽:挖掘", "", "闲得慌来挖"},
['sprintFix']= {"竞速", "无移动"},
['sprintLock']= {"竞速", "无旋转"},
['marathon_bfmax']= {"马拉松", "极限"},
['custom_clear']= {"自定义", "普通"},
['custom_puzzle']= {"自定义", "拼图"},
},
getTip={refuseCopy=true,
"100apm?你倒是不用开局定式连续打几把",
"10连pc不是随手?",
"20G很难?是个人都能玩吧。",
"20TSD不难吧。",
"3pps不是人均水平?",
"40行还要40多秒,就这?",
"别会个c4w就以为自己多强,这是基本功罢了。",
"别人只用一只手都能玩,你呢?",
"不会吧不会吧,真的还有人不能随手Tspin?",
"除了雨宫太阳你还认识谁?Jonas知道吗?Ajanba听过吗?",
"还搁这玩手机呢,作业做完了?",
"极限20G不是随手通?",
"叫你多练就多练,想着几天变神仙,当自己是谁?",
"先练基础不听,现在速度没有,Tspin完地形一塌糊涂,开心吗?",
"经典块跟现代块是两个游戏,别拿多少年前水平秀优越,请从头练起。",
"卖弱不是谦虚,请看场合。",
"卖弱是要遭报应的",
"满口PCDT信天翁,还会点别的么?",
"没那水平别天天整什么花里胡哨的,人玩几年你想几天赶上?",
"全隐40行全消四很难吗??",
"少玩点,多眨眨眼,不听瞎了别怪我没提醒你",
"设置都看过一遍了吗?明明都有还嫌功能少,谁的问题?",
"谁说一定要强的人才叫卖弱?不是最菜就一定在有人眼中是卖弱",
"双旋和极简尽早学起来…懒得学以后亏的是自己",
"天天催更催更,你咋不来帮忙开发啊,真以为作者很强催催啥都有?",
"天天卖弱,你一定把把150apm吧?",
"问怎么练就好好问,别就一句话怎么变强,鬼知道你现在什么水平",
"一口一个wtcl还不赶紧去练,你是不思进取还是不想好好说话?",
"隐形很难?上电视那个水平一般都打成那样,属实自己不行看不起别人",
"隐形哪难了,你练了吗?没练几个小时在这里说难是嫌葡萄酸?",
"这不是休闲游戏…别怪关卡要求太高,就是你菜,请多练。",
},
}

View File

@@ -17,7 +17,6 @@ return{
clear={"single","double","triple","Techrash","Pentcrash","Hexcrash"},
mini="Mini",b2b="B2B ",b3b="B2B2B ",
PC="Perfect Clear",HPC="Half Clear",
hold="暂存",next="下一个",
replaying="[回放]",
stage="关卡 $1",
@@ -78,7 +77,6 @@ return{
getVersionFail="检测新版本失败",
oldVersion="最新版本$1可以下载了!",
needUpdate="请更新游戏!",
noInternet="还未连接到网络",
notFinished="暂未完成,敬请期待!",
jsonError="json错误",
@@ -93,6 +91,8 @@ return{
loginFailed="登录失败",
accessSuccessed="身份验证成功",
accessFailed="身份验证失败",
wsConnecting="正在连接WS",
wsSuccessed="WS连接成功",
wsFailed="WS连接失败",
wsClose="WS被断开: ",
@@ -106,8 +106,10 @@ return{
joinRoom="进入房间",
leaveRoom="离开房间",
ready="各就各位!",
set="预备!",
connStream="正在连接",
waitStream="等待其他人连接",
champion="$1 获胜",
spectating="观战中",
chatRemain="人数:",
chatStart="------消息的开头------",
chatHistory="------以上是历史消息------",
@@ -265,6 +267,7 @@ return{
},
net_game={
ready="准备",
spectate="观战",
cancel="取消",
},
setting_game={
@@ -309,8 +312,8 @@ return{
text="消行文本",
score="分数动画",
warn="死亡预警",
bufferWarn="缓冲预警",
showSpike="爆发累计",
highCam="超屏视野",
nextPos="生成预览",
@@ -318,6 +321,7 @@ return{
power="电量显示",
clickFX="点按特效",
bg="背景",
warn="死亡预警",
clean="绘制优化",
},
setting_sound={
@@ -384,6 +388,7 @@ return{
save2="保存2",
load2="读取2",
size="大小",
shape="形状",
},
setting_touchSwitch={
b1= "左移:", b2="右移:", b3="顺时针旋转:", b4="逆时针旋转:",
@@ -695,7 +700,7 @@ return{
['dig_400l']= {"挖掘", "400L", "挖掘400行"},
['dig_1000l']= {"挖掘", "1000L", "挖掘1000行"},
['drought_n']= {"干旱", "100L", "你I没了"},
['drought_l']= {"干旱", "100L", "后 妈 发 牌"},
['drought_l']= {"干旱+", "100L", "后 妈 发 牌"},
['marathon_n']= {"马拉松", "普通", "200行加速马拉松"},
['marathon_h']= {"马拉松", "困难", "200行高速马拉松"},
['solo_e']= {"单挑", "简单", "打败AI"},
@@ -748,6 +753,7 @@ return{
['pc_n']= {"全清挑战", "普通", "100行内刷PC"},
['pc_h']= {"全清挑战", "困难", "100行内刷PC"},
['pc_l']= {"全清挑战", "疯狂", "100行内刷PC"},
['pc_inf']= {"无尽全清挑战", "", "你能连续做多少PC?"},
['tech_n']= {"科研", "普通", "禁止断B2B"},
['tech_n_plus']= {"科研", "普通+", "仅允许spin与PC"},
['tech_h']= {"科研", "困难", "禁止断B2B"},
@@ -803,19 +809,18 @@ return{
"3next 1hold?",
"40行世界纪录:15.654s by VinceHD",
"6236326236327175",
"626in1",
"6next 1hold!",
"6next 6hold?!",
"7宽三SZ架空捐了解一下",
"9999in1",
"按钮风格进化史",
"把手机调到特殊的日期也许会发生什么",
"报时机器人:新的一天开始了",
"背景影响游玩?可以去设置关闭",
"本游戏不是产品,是作品(至少目前是…)",
"本游戏不是产品,是作品(至少目前是,嗯…)",
"本游戏的一部分内容是国际合作的!",
"本游戏的B2B是气槽机制,和传统的开关机制不一样哦",
"本游戏可不是休闲游戏。",
"本游戏内置了几个休(ying)闲(he)小游戏哦~入口就藏在这个菜单",
"本游戏内置了几个休(ying)闲(he)小游戏哦~",
"本游戏在设计的时候受到了大量其他块游甚至一些音游的启发",
"必须要软降才能到达的位置都会判定为极简操作",
"别看攻击效率不高,其实消四还是很强的",
@@ -828,7 +833,7 @@ return{
"彩色消除即将到来!",
"草(日本语)",
"成就系统在做了!",
"触发游戏报错后日志文件会越来越大(不过顶多几K)",
"触发游戏报错后日志文件会越来越大(不过顶多几K)",
"触摸板打osu也很好!",
"凑数tip什么时候能站起来!",
"打好块跟学习一样没有捷径,多练。",
@@ -840,7 +845,6 @@ return{
"低帧率会降低游戏体验",
"点击添加标题",
"点击添加副标题",
"点击退出按钮会有极小概率会…",
"电脑游玩自带按键显示~",
"对编程有真·兴趣推荐Lua,安装无脑 语法简单 执行速度快 远离枯燥学校编程(雾",
"对战游戏不是单机游戏,所以timing在对战里也非常重要!",
@@ -857,6 +861,7 @@ return{
"感觉自己速度到上限了?试着把das调低一点",
"感谢群友帮忙想tip",
"感谢Orzmic为这个tip显示框提出意见",
"感谢Phigros提供部分tip模板(",
"刚接触方块的话多玩玩就行,40行两分钟以外没啥好针对性练习的",
"刚开始练全隐形可以尽量堆平,留一列消四",
"隔断消除即将到来!",
@@ -865,7 +870,6 @@ return{
"更小的DAS和ARR拥有更高的操作上限(能控制得了的话)",
"更新内容在游戏里和群公告都有写!",
"攻击生效速度(从快到慢):消二/三,消四,spin,高连击",
"官网在做了",
"还能写些什么tip呢",
"好像还没人能用脚打块打到一定水平",
"好像可以把手机倒过来打场地旋转180...那还是不建议违反规则",
@@ -897,6 +901,7 @@ return{
"你可以从统计页面打开游戏存档目录",
"你们考虑过Z酱的感受吗?没有!你们只考虑你自己。",
"你说彩蛋?嗯…算是有,可以找找",
"你有一个好",
"你知道吗:看主页机器人玩可能比较费电",
"你知道吗:全程不使用任何旋转键完成40行模式是有可能的",
"你知道吗:全程不使用左右移动键完成40行模式是有可能的",
@@ -952,6 +957,8 @@ return{
"音乐使用beepbox制作",
"音游方块是一家(暴论",
"游戏使用love2d引擎制作",
"游戏使用un...love2d引擎制作",
"游戏也是一种艺术形式",
"游戏中左下角三个信息分别是分数/时间/极简连击数",
"有建议的话可以把信息反馈给作者~",
"有三个隐藏模式不能从地图进入,到处找找看吧",
@@ -962,10 +969,11 @@ return{
"众所周知俄罗斯方块是经典编程练手游戏(?",
"注意到方块\"旋转\"的时候到底发生了些什么吗?",
"自定义场地可以画图实现逐页演示",
"总共有300条tip哦",
"总共有将近400条tip哦",
"作者40行sub26了",
"作者电脑上装了10个方块",
"作者浏览器收藏夹里有6个方块",
"做,做碌鸠啊做,打块先啦!",
"做点击特效的时候真没想抄Phigros!想法另有出处,做完了才突然发现好像(",
"ALLSPIN!",
"Am G F G",
@@ -1010,6 +1018,7 @@ return{
"sin2α=2SαCα",
"sofunhowtoget",
"Staff名单里飘过的是赞助榜单,喜欢本游戏的话可以给我们打赞助支持开发哦~",
"STSD必死",
"SΔABC=√(h(h-a)(h-b)(h-c)), h=(a+b+c)/2",
"Techmino = Technique + tetromino",
"Techmino 好玩!",
@@ -1063,19 +1072,13 @@ return{
{C.G,"快捷键: Ctrl+W=关闭当前标签页"},
{C.G,"快捷键: shift+del=永久删除文件 (技术人员别杠)"},
{C.G,"GREEN"},
{C.H,"感谢Phigros提供部分tip模板("},
{C.H,"暂定段位:9"},
{C.H,"REGRET!!"},
{C.J,"JADE"},
{C.L,"LIME"},
{C.lC,"26连T2来一个?"},
{C.lC,"Xspin",C.Z,"是啥"},
{C.lH,"腱鞘炎警告"},
{C.lH,"没学过编曲,音乐都是自己瞎写的,觉得不好听就去设置关了吧"},
{C.lH,"秘密数字:626"},
{C.lH,"你有一个好"},
{C.lH,"STSD必死"},
{C.lH,"Techmino没有抽卡没有氪金,太良心了"},
{C.lP,"秘密数字:626"},
{C.lP,"Naki",C.Z," 可爱!"},
{C.lR,"Z ",C.lG,"S ",C.lS,"J ",C.lO,"L ",C.lP,"T ",C.lY,"O ",C.lC,"I"},
{C.lS,"茶娘",C.Z," 可爱!"},
@@ -1116,5 +1119,49 @@ return{
{C.Z,"效率药水",C.H," 效率提升 (8:00)"},
{C.Z,"协调药水",C.H," MD减少 II(1:30)"},
-- "Z酱 可爱!",
{C.dH,"100apm?你倒是不用开局定式连续打几把"},
{C.dH,"10连pc不是随手?"},
{C.dH,"20G很难?是个人练练都能玩吧。"},
{C.dH,"20TSD不是轻松?"},
{C.dH,"3pps不是人均水平?"},
{C.dH,"40行还要40多秒,就这?"},
{C.dH,"别动不动大惊小怪,就你没见过"},
{C.dH,"别会个c4w就以为自己多强,基本功之一罢了。"},
{C.dH,"别人用跳舞毯打得都比你好"},
{C.dH,"别人只用一只手都能玩,你呢?"},
{C.dH,"除了雨宫太阳你还认识谁?Jonas知道吗?Ajanba听过吗?"},
{C.dH,"单旋没前途的,别玩了"},
{C.dH,"还搁这玩手机呢,作业做完了?"},
{C.dH,"激烈的竞争不应当充斥整个游戏"},
{C.dH,"极限20G不是随手通?"},
{C.dH,"腱鞘炎警告"},
{C.dH,"叫你多练就多练,想着几天变神仙,当自己是谁?"},
{C.dH,"经典块的水也很深,不要小看经典块玩家"},
{C.dH,"经典块跟现代块是两个游戏,别拿多少年前水平秀优越,请从头练起。"},
{C.dH,"经典块和渣方块是两个概念"},
{C.dH,"觉得Techmino好玩是你的幸运,不是你有优越感的理由"},
{C.dH,"卖弱不是谦虚,请看场合。"},
{C.dH,"卖弱是要遭报应的"},
{C.dH,"满口PCDT信天翁,还会点别的么?"},
{C.dH,"没那水平别天天整什么花里胡哨的,人家玩了几年你想几天赶上?"},
{C.dH,"没学过编曲,音乐都是自己瞎写的,觉得不好听就去设置关了吧"},
{C.dH,"你不会以为S和Z只有两个方向吧"},
{C.dH,"请自己先搞搞清楚再去教别人"},
{C.dH,"全隐40行全消四很难吗??"},
{C.dH,"少玩点游戏,多注意眨眼和休息,瞎了别怪我没提醒你"},
{C.dH,"设置都看过一遍了吗?明明都有还在那嫌弃,谁的问题?"},
{C.dH,"谁说一定要强的人才叫卖弱?不是最菜就一定在有人眼中是卖弱"},
{C.dH,"双旋和极简尽早学起来…懒得学以后亏的是自己"},
{C.dH,"天天催更催更,你咋不来帮忙开发啊,真以为作者很强催啥都能有?"},
{C.dH,"天天卖弱,你一定把把150apm吧?"},
{C.dH,"问怎么练就好好问,别就一句话怎么变强,鬼知道你现在什么水平"},
{C.dH,"先练基础不听,现在速度没有,Tspin完地形一塌糊涂,开心吗?"},
{C.dH,"一口一个wtcl还不赶紧去练,你是不思进取还是不想好好说话?"},
{C.dH,"隐形很难?上电视那个水平一般都打成那样,属实自己不行看不起别人"},
{C.dH,"隐形哪难了,你练了吗?没专门练几个小时就说难也太没耐心了吧"},
{C.dH,"有问题建议先找找是不是自己的问题,那么多人怎么就你事多?"},
{C.dH,"这不是休闲游戏…别怪关卡要求太高,就是你菜,请多练。"},
{C.dH,"这年头不会双旋还敢跟人打对战?"},
{C.dH,"Techmino没有抽卡没有氪金没有逼肝,良不良心自己没点数?"},
}
}

View File

@@ -153,7 +153,7 @@ return{
['dig_400l']= {"挖掘", "400L", "挖掘400行"},
['dig_1000l']= {"挖掘", "1000L", "挖掘1000行"},
['drought_n']= {"干旱", "100行", "你I没了"},
['drought_l']= {"干旱", "100行", "后 妈 发 牌"},
['drought_l']= {"干旱+", "100行", "后 妈 发 牌"},
['marathon_n']= {"马拉松", "普通", "200行加速马拉松"},
['marathon_h']= {"马拉松", "困难", "200行高速马拉松"},
['solo_e']= {"单挑", "简单", "打败机器人"},
@@ -206,6 +206,7 @@ return{
['pc_n']= {"全清挑战", "普通", "100行内刷全清"},
['pc_h']= {"全清挑战", "困难", "100行内刷全清"},
['pc_l']= {"全清挑战", "疯狂", "100行内刷全清"},
['pc_inf']= {"无尽全清挑战", "", "你能连续做多少PC?"},
['tech_n']= {"科研", "普通", "禁止断B2B"},
['tech_n_plus']= {"科研", "普通+", "仅允许回旋与全清"},
['tech_h']= {"科研", "困难", "禁止断B2B"},

View File

@@ -161,7 +161,6 @@ do--drawableText
anykey=T(40),
replaying=T(20),
next=T(40),hold=T(40),
win=T(120),lose=T(120),
finish=T(120),
gamewin=T(100),gameover=T(100),pause=T(120),

View File

@@ -77,12 +77,13 @@ return{
{name='c4wtrain_n', x=700, y=-400, size=40,shape=1,icon="pc",unlock={'c4wtrain_l'}},
{name='c4wtrain_l', x=900, y=-400, size=40,shape=1,icon="pc"},
{name='pctrain_n', x=700, y=-220, size=40,shape=1,icon="pc", unlock={'pctrain_l','pc_n'}},
{name='pctrain_l', x=900, y=-220, size=40,shape=1,icon="pc"},
{name='pctrain_n', x=700, y=-250, size=40,shape=1,icon="pc", unlock={'pctrain_l','pc_n'}},
{name='pctrain_l', x=900, y=-250, size=40,shape=1,icon="pc"},
{name='pc_n', x=800, y=-100, size=40,shape=1,icon="pc", unlock={'pc_h'}},
{name='pc_h', x=1000, y=-100, size=40,shape=3,icon="pc", unlock={'pc_l'}},
{name='pc_l', x=1200, y=-100, size=40,shape=2,icon="pc"},
{name='pc_n', x=800, y=-110, size=40,shape=1,icon="pc", unlock={'pc_h'}},
{name='pc_h', x=950, y=-110, size=40,shape=3,icon="pc", unlock={'pc_l','pc_inf'}},
{name='pc_l', x=1100, y=-110, size=40,shape=3,icon="pc"},
{name='pc_inf', x=1100, y=-250, size=40,shape=2,icon="pc"},
{name='tech_n', x=400, y=-150, size=40,shape=1,icon="tech", unlock={'tech_n_plus','tech_h','tech_finesse'}},
{name='tech_n_plus', x=600, y=160, size=40,shape=3,icon="tech", unlock={'tsd_e','backfire_n'}},

View File

@@ -16,7 +16,7 @@ return{
load=function()
PLY.newPlayer(1)
if SETTING.sfx_spawn==0 then
LOG.print(text.switchSpawnSFX,COLOR.Y)
LOG.print(text.switchSpawnSFX,'warn')
end
end,
mesDisp=function(P)

View File

@@ -64,10 +64,8 @@ return{
local AItype=ENV.opponent:sub(1,2)
local AIlevel=tonumber(ENV.opponent:sub(-1))
if AItype=='9S'then
ENV.target=nil
PLY.newAIPlayer(2,AIBUILDER('9S',2*AIlevel))
elseif AItype=='CC'then
ENV.target=nil
PLY.newAIPlayer(2,AIBUILDER('CC',2*AIlevel-1,math.floor(AIlevel*.5+1),true,20000+5000*AIlevel))
end
@@ -77,12 +75,7 @@ return{
end,
mesDisp=function(P)
setFont(55)
if P.modeData.target>1e10 then
mStr(P.stat.row,69,225)
mText(drawableText.line,69,290)
else
local R=P.modeData.target-P.stat.row
mStr(R>=0 and R or 0,69,240)
end
mStr(P.stat.row,69,225)
mText(drawableText.line,69,290)
end,
}

View File

@@ -1,3 +1,4 @@
local yield=YIELD
return{
color=COLOR.white,
env={
@@ -5,14 +6,27 @@ return{
freshLimit=15,
pushSpeed=5,
garbageSpeed=2,
initSkip=true,
allowMod=false,
task=function(P)
local S=P.stat
while true do yield()if S.frame>90*60 then P.strength=1;P:setFrameColor(1)break end end
while true do yield()if S.frame>135*60 then P.strength=2;P:setFrameColor(2)break end end
while true do yield()if S.frame>180*60 then P.strength=3;P:setFrameColor(3)break end end
while true do yield()if S.frame>260*60 then P.strength=4;P:setFrameColor(4)break end end
end,
bgm={'battle','cruelty','distortion','far','final','hope','magicblock','new era','push','race','rockblock','secret7th','secret8th','shining terminal','storm','super7th','warped','waterfall'},
},
load=function()
PLY.newPlayer(1)
PLAYERS[1].sid=netPLY.getSID(USER.uid)
local N=2
for i=2,netPLY.getCount()do
PLY.newRemotePlayer(i,false,netPLY.rawgetPLY(i))
local p=netPLY.rawgetPLY(i)
if p.connected then
PLY.newRemotePlayer(N,false,p)
N=N+1
end
end
end,
}

View File

@@ -15,11 +15,11 @@ return{
mesDisp=function(P)
setFont(45)
local R=100-P.stat.row
mStr(R>=0 and R or 0,69,250)
mStr(R>=0 and R or 0,69,220)
setFont(75)
mStr(P.stat.pc,69,350)
mText(drawableText.pc,69,432)
setFont(70)
mStr(P.stat.pc,69,300)
mText(drawableText.pc,69,380)
end,
score=function(P)return{P.stat.pc,P.stat.time}end,
scoreDisp=function(D)return D[1].." PCs "..STRING.time(D[2])end,

46
parts/modes/pc_inf.lua Normal file
View File

@@ -0,0 +1,46 @@
return{
color=COLOR.red,
env={
drop=20,lock=60,
fall=10,
dropPiece=function(P)
if P.lastPiece.pc then
P.gameEnv.heightLimit=4
if P.stat.pc%10==0 then
P.gameEnv.drop=math.max(P.gameEnv.drop-1,1)
end
else
P.gameEnv.heightLimit=P.gameEnv.heightLimit-P.lastPiece.row
end
if #P.field>P.gameEnv.heightLimit then
P:lose()
end
end,
freshLimit=8,
heightLimit=4,
ospin=false,
bg='rgb',bgm='truth',
},
pauseLimit=true,
load=function()
PLY.newPlayer(1)
end,
mesDisp=function(P)
setFont(70)
mStr(P.stat.pc,69,300)
mText(drawableText.pc,69,380)
end,
score=function(P)return{P.stat.pc,P.stat.time}end,
scoreDisp=function(D)return D[1].." PCs "..STRING.time(D[2])end,
comp=function(a,b)return a[1]>b[1]or a[1]==b[1]and a[2]<b[2]end,
getRank=function(P)
local L=P.stat.pc
return
L>=100 and 5 or
L>=70 and 4 or
L>=40 and 3 or
L>=20 and 2 or
L>=10 and 1 or
L>=5 and 0
end,
}

View File

@@ -15,11 +15,11 @@ return{
mesDisp=function(P)
setFont(45)
local R=100-P.stat.row
mStr(R>=0 and R or 0,69,250)
mStr(R>=0 and R or 0,69,220)
setFont(75)
mStr(P.stat.pc,69,350)
mText(drawableText.pc,69,432)
setFont(70)
mStr(P.stat.pc,69,300)
mText(drawableText.pc,69,380)
end,
score=function(P)return{P.stat.pc,P.stat.time}end,
scoreDisp=function(D)return D[1].." PCs "..STRING.time(D[2])end,

View File

@@ -13,11 +13,11 @@ return{
mesDisp=function(P)
setFont(45)
local R=100-P.stat.row
mStr(R>=0 and R or 0,69,250)
mStr(R>=0 and R or 0,69,220)
setFont(75)
mStr(P.stat.pc,69,350)
mText(drawableText.pc,69,432)
setFont(70)
mStr(P.stat.pc,69,300)
mText(drawableText.pc,69,380)
end,
score=function(P)return{P.stat.pc,P.stat.time}end,
scoreDisp=function(D)return D[1].." PCs "..STRING.time(D[2])end,

View File

@@ -63,9 +63,9 @@ return{
check(PLAYERS[1])
end,
mesDisp=function(P)
setFont(75)
mStr(P.stat.pc,69,330)
mText(drawableText.pc,69,412)
setFont(70)
mStr(P.stat.pc,69,300)
mText(drawableText.pc,69,380)
end,
score=function(P)return{P.stat.pc,P.stat.time}end,
scoreDisp=function(D)return D[1].." PCs "..STRING.time(D[2])end,

View File

@@ -54,9 +54,9 @@ return{
check(PLAYERS[1])
end,
mesDisp=function(P)
setFont(75)
mStr(P.stat.pc,69,330)
mText(drawableText.pc,69,412)
setFont(70)
mStr(P.stat.pc,69,300)
mText(drawableText.pc,69,380)
end,
score=function(P)return{P.stat.pc,P.stat.time}end,
scoreDisp=function(D)return D[1].." PCs "..STRING.time(D[2])end,

View File

@@ -2,7 +2,7 @@ return{
color=COLOR.magenta,
env={
drop=30,lock=60,
freshLimit=10,
freshLimit=5,
task=function(P)
while true do
YIELD()

View File

@@ -2,7 +2,7 @@ return{
color=COLOR.red,
env={
drop=30,lock=60,
freshLimit=10,
freshLimit=5,
task=function(P)
while true do
YIELD()

View File

@@ -23,6 +23,7 @@ return{
garbageSpeed=.3,
pushSpeed=2,
freshLimit=15,
initSkip=true,
bg='rainbow',bgm='sugar fairy',
},
load=function()

View File

@@ -23,6 +23,7 @@ return{
garbageSpeed=.3,
pushSpeed=2,
freshLimit=15,
initSkip=true,
bg='rainbow',bgm='rockblock',
},
load=function()

View File

@@ -23,6 +23,7 @@ return{
garbageSpeed=.3,
pushSpeed=2,
freshLimit=15,
initSkip=true,
bg='rainbow',bgm='magicblock',
},
load=function()

View File

@@ -23,6 +23,7 @@ return{
garbageSpeed=.3,
pushSpeed=2,
freshLimit=15,
initSkip=true,
bg='rainbow',bgm='sugar fairy',
},
load=function()

View File

@@ -23,6 +23,7 @@ return{
garbageSpeed=.3,
pushSpeed=2,
freshLimit=15,
initSkip=true,
bg='rainbow',bgm='rockblock',
},
load=function()

View File

@@ -23,6 +23,7 @@ return{
garbageSpeed=.3,
pushSpeed=2,
freshLimit=15,
initSkip=true,
bg='rainbow',bgm='magicblock',
},
load=function()

View File

@@ -8,20 +8,26 @@ local NET={
connected=false,
allow_online=false,
accessToken=false,
roomList={},
roomInfo={
-- rid=false,
name=false,
-- type=false,
private=false,
-- count=false,
roomList={},--Local roomlist, updated frequently
roomState={--A copy of room structure on server
roomInfo={
name=false,
type=false,
version=false,
},
roomData={},
count=false,
capacity=false,
private=false,
start=false,
},
spectate=false,--If player is spectating
streamRoomID=false,
seed=false,
allReady=false,
connectingStream=false,
streamRoomID=false,
serverGaming=false,
waitingStream=false,
UserCount="_",
PlayCount="_",
@@ -129,11 +135,11 @@ function NET.wsconn_play()
end
function NET.wsconn_stream()
if NET.lock('wsc_stream',5)then
NET.serverGaming=true
NET.roomState.start=true
WS.connect('stream','/stream',JSON.encode{
uid=USER.uid,
accessToken=NET.accessToken,
rid=NET.streamRoomID,
srid=NET.streamRoomID,
})
TASK.new(NET.updateWS_stream)
end
@@ -144,7 +150,7 @@ function NET.wsclose_app()WS.close('app')end
function NET.wsclose_user()WS.close('user')end
function NET.wsclose_play()WS.close('play')end
function NET.wsclose_stream()
NET.serverGaming=false
NET.roomState.start=false
WS.close('stream')
end
@@ -161,6 +167,18 @@ function NET.register(username,email,password)
})
end
end
function NET.tryLogin(ifAuto)
if NET.allow_online then
if WS.status('user')=='running'then
NET.getAccessToken()
elseif not ifAuto then
SCN.go('login')
end
else
TEXT.show(text.needUpdate,640,450,60,'flicker')
SFX.play('finesseError')
end
end
function NET.pong(wsName,message)
WS.send(wsName,type(message)=='string'and message or"",'pong')
end
@@ -203,17 +221,20 @@ function NET.fetchRoom()
end
function NET.createRoom(roomName,capacity,roomType,password)
if NET.lock('enterRoom',1.26)then
NET.roomInfo.name=roomName
NET.roomInfo.type=roomType
NET.roomInfo.private=not not password
NET.roomInfo.capacity=capacity
NET.roomState.private=not not password
NET.roomState.capacity=capacity
WS.send('play',JSON.encode{
action=1,
data={
name=roomName,
capacity=capacity,
roomData={type=roomType},
password=password,
roomInfo={
name=roomName,
type=roomType,
version=VERSION.short,
},
roomData={_=0},
config=dumpBasicConfig(),
}
})
@@ -222,11 +243,6 @@ end
function NET.enterRoom(room,password)
if NET.lock('enterRoom',1.26)then
SFX.play('reach',.6)
NET.roomInfo.name=room.name
NET.roomInfo.type=room.type
NET.roomInfo.private=not not password
NET.roomInfo.capacity=room.capacity
NET.roomInfo.start=room.start
WS.send('play',JSON.encode{
action=2,
data={
@@ -253,9 +269,9 @@ end
function NET.changeConfig()
WS.send('play','{"action":5,"data":'..JSON.encode({config=dumpBasicConfig()})..'}')
end
function NET.signal_ready(ready)
if NET.lock('ready',3)and not NET.serverGaming then
WS.send('play','{"action":6,"data":{"ready":'..tostring(ready)..'}}')
function NET.signal_joinMode(ready)
if NET.lock('ready',3)and not NET.roomState.start then
WS.send('play','{"action":6,"data":'..JSON.encode{mode=ready}..'}')
end
end
function NET.signal_die()
@@ -295,24 +311,27 @@ function NET.updateWS_app()
NET.allow_online=true
if USER.authToken then
NET.wsconn_user_token(USER.uid,USER.authToken)
elseif SCN.cur=='main'then
SCN.go('login')
end
end
if VERSION.code<res.newestCode then
LOG.print(text.oldVersion:gsub("$1",res.newestName),180,COLOR.N)
LOG.print(text.oldVersion:gsub("$1",res.newestName),180,'message')
end
LOG.print(res.notice,300,COLOR.N)
LOG.print(res.notice,300,'message')
NET.tryLogin(true)
elseif res.action==0 then--Get new version info
--?
elseif res.action==1 then--Get notice
--?
elseif res.action==2 then--Register
if res.type=='Self'or res.type=='Server'then
LOG.print(res.data.message,300,COLOR.N)
LOG.print(res.data.message,300,'message')
if SCN.cur=='register'then
SCN.back()
end
else
LOG.print(res.reason or"Registration failed",300,COLOR.N)
LOG.print(res.reason or"Registration failed",300,'message')
end
NET.unlock('register')
elseif res.action==3 then--Get player counts
@@ -351,14 +370,14 @@ function NET.updateWS_user()
FILE.save(USER,'conf/user','q')
if SCN.cur=='login'then SCN.back()end
end
LOG.print(text.loginSuccessed)
LOG.print(text.loginSuccessed,'message')
--Get self infos
NET.getUserInfo(USER.uid)
NET.unlock('wsc_user')
elseif res.action==0 then--Get accessToken
NET.accessToken=res.accessToken
LOG.print(text.accessSuccessed)
LOG.print(text.accessSuccessed,'message')
NET.wsconn_play()
elseif res.action==1 then--Get userInfo
USERS.updateUserData(res.data)
@@ -391,6 +410,7 @@ function NET.updateWS_play()
SCN.go('net_menu')
NET.unlock('wsc_play')
NET.unlock('access_and_login')
SFX.play('connected')
elseif res.action==0 then--Fetch rooms
NET.roomList=res.roomList
NET.unlock('fetchRoom')
@@ -406,20 +426,38 @@ function NET.updateWS_play()
uid=p.uid,
username=p.username,
sid=p.sid,
ready=p.ready,
mode=p.mode,
config=p.config,
}
end
end
--TODO: d.roomData (json)
NET.roomState.roomInfo=d.roomInfo
NET.roomState.roomData=d.roomData
NET.roomState.count=d.count
NET.roomState.capacity=d.capacity
NET.roomState.private=d.private
NET.roomState.start=d.start
NET.allReady=false
NET.connectingStream=false
NET.waitingStream=false
NET.spectate=false
NET.streamRoomID=false
loadGame('netBattle',true,true)
if d.srid then
NET.spectate=true
NET.streamRoomID=d.srid
NET.connectingStream=true
end
else
--Load other players
netPLY.add{
uid=d.uid,
username=d.username,
sid=d.sid,
ready=d.ready,
mode=d.mode,
config=d.config,
}
if SCN.socketRead then SCN.socketRead('join',d)end
@@ -441,20 +479,21 @@ function NET.updateWS_play()
if SCN.socketRead then SCN.socketRead('talk',d)end
elseif res.action==5 then--Player change settings
netPLY.setConf(d.uid,d.config)
elseif res.action==6 then--One ready
netPLY.setReady(d.uid,d.ready)
elseif res.action==6 then--Player change join mode
netPLY.setJoinMode(d.uid,d.mode)
elseif res.action==7 then--All Ready
SFX.play('reach',.6)
NET.allReady=true
elseif res.action==8 then--Set
NET.streamRoomID=d.rid
NET.streamRoomID=d.srid
NET.allReady=false
NET.connectingStream=true
NET.wsconn_stream()
elseif res.action==9 then--Game finished
NET.wsclose_stream()
NET.roomState.start=false
NET.spectate=false
if SCN.socketRead then SCN.socketRead('finish',d)end
NET.roomInfo.start=false
NET.wsclose_stream()
end
else
WS.alert('play')
@@ -482,14 +521,39 @@ function NET.updateWS_stream()
local d=res.data
if res.type=='Connect'then
NET.unlock('wsc_stream')
elseif res.action==0 then--Game start
NET.connectingStream=false
if SCN.socketRead then SCN.socketRead('go',d)end
NET.roomInfo.start=true
elseif res.action==0 then--Game start
NET.waitingStream=false
SCN.socketRead('go')
elseif res.action==1 then--Game finished
--?
elseif res.action==2 then--Player join
--?
if res.type=='Self'then
NET.seed=d.seed
NET.spectate=d.spectate
netPLY.setConnect(d.uid)
for _,p in next,d.connected do
if not p.spectate then
netPLY.setConnect(p.uid)
end
end
if d.spectate then
if d.start then
SCN.socketRead('go')
for _,v in next,d.history or{}do
SCN.socketRead('stream',v)
end
end
else
NET.waitingStream=true
end
else
if d.spectate then
netPLY.setJoinMode(d.uid,2)
else
netPLY.setConnect(d.uid)
end
end
elseif res.action==3 then--Player leave
--?
elseif res.action==4 then--Player died

View File

@@ -87,6 +87,8 @@ end
function netPLY.clear()for _=1,netPLY.getCount()do rem(PLY)end end
function netPLY.add(p)
p.mode=0
p.connected=false
ins(PLY,p.uid==USER.uid and 1 or #PLY+1,p)
local a=rnd()*6.2832
p.x,p.y,p.w,p.h=640+2600*cos(a),360+2600*sin(a),47,47
@@ -98,24 +100,23 @@ end
function netPLY.getCount()return #PLY end
function netPLY.rawgetPLY(i)return PLY[i]end
function netPLY.getUsername(uid)return getPLY(uid).username end
function netPLY.getSID(uid)return getPLY(uid).sid end
function netPLY.getSelfReady()return PLY[1].ready end
function netPLY.getSelfJoinMode()return PLY[1].mode end
function netPLY.getSelfReady()return PLY[1].mode>0 end
function netPLY.setPlayerObj(ply,p)ply.p=p end
function netPLY.setConf(uid,config)getPLY(uid).config=config end
function netPLY.setReady(uid,ready)
function netPLY.setJoinMode(uid,ready)
for i,p in next,PLY do
if p.uid==uid then
if p.ready~=ready then
p.ready=ready
if not ready then NET.allReady=false end
if p.mode~=ready then
p.mode=ready
if ready==0 then NET.allReady=false end
SFX.play('spin_0',.6)
if i==1 then
NET.unlock('ready')
elseif not PLY[1].ready then
elseif PLY[1].mode==0 then
for j=2,#PLY do
if not PLY[j].ready then
if PLY[j].mode==0 then
return
end
end
@@ -126,9 +127,11 @@ function netPLY.setReady(uid,ready)
end
end
end
function netPLY.resetReady()
function netPLY.setConnect(uid)getPLY(uid).connected=true end
function netPLY.resetState()
for i=1,#PLY do
PLY[i].ready=false
PLY[i].mode=0
PLY[i].connected=false
end
end
@@ -165,7 +168,11 @@ function netPLY.draw()
local p=PLY[i]
gc.translate(p.x,p.y)
--Rectangle
gc.setColor(COLOR[p.ready and'G'or'Z'])
gc.setColor(COLOR[
p.mode==0 and'Z'or
p.mode==1 and(p.connected and"N"or"G")or
p.mode==2 and(p.connected and"Y"or"F")
])
gc.setLineWidth(2)
gc.rectangle('line',0,0,p.w,p.h)
@@ -185,8 +192,8 @@ function netPLY.draw()
gc.print("#"..p.uid,50,-5)
gc.print(p.username,210,-5)
else
setFont(159)
gc.print("#"..p.uid,p.h,-2)
setFont(15)
gc.print("#"..p.uid,46,-1)
setFont(30)
gc.print(p.username,p.h,8)
end

View File

@@ -111,6 +111,11 @@ return{
font=65,
color=C.rainbow_dark,
},
{
name="亮君吧",
font=65,
color=C.rainbow_dark,
},
{
name="八零哥",

View File

@@ -1,6 +1,6 @@
local gc=love.graphics
local gc_push,gc_pop,gc_clear,gc_origin=gc.push,gc.pop,gc.clear,gc.origin
local gc_translate,gc_scale,gc_rotate=gc.translate,gc.scale,gc.rotate
local gc_translate,gc_scale,gc_rotate,gc_shear=gc.translate,gc.scale,gc.rotate,gc.shear
local gc_setCanvas,gc_setShader=gc.setCanvas,gc.setShader
local gc_draw,gc_line,gc_rectangle=gc.draw,gc.line,gc.rectangle
local gc_print,gc_printf=gc.print,gc.printf
@@ -9,7 +9,7 @@ local gc_stencil,gc_setStencilTest=gc.stencil,gc.setStencilTest
local int,ceil,rnd=math.floor,math.ceil,math.random
local max,min,sin,modf=math.max,math.min,math.sin,math.modf
local setFont,mDraw,mStr,mText=setFont,mDraw,mStr,mText
local setFont,mDraw,mStr=setFont,mDraw,mStr
local SKIN,TEXTURE,IMG=SKIN,TEXTURE,IMG
local TEXT,COLOR,GAME,TIME=TEXT,COLOR,GAME,TIME
local shader_alpha,shader_lighter=SHADER.alpha,SHADER.lighter
@@ -50,6 +50,12 @@ local spinCenterImg=DOGC{9,9,
{'setCL',1,1,1},
{'fRect',3,3,3,3},
}
local playerBoarders=DOGC{334,614,
{'setLW',2},
{'dRect',16,1,302,612},
{'dRect',318,9,15,604},
{'dRect',1,9,15,604},
}
local gridLines do
local L={300,640,{'setLW',2}}
for x=1,9 do table.insert(L,{'line',30*x,0,30*x,640})end
@@ -249,13 +255,6 @@ local function drawNextPreview(P,B)
end
end end
end
local function drawBoarders(P)
gc_setLineWidth(2)
gc_setColor(P.frameColor)
gc_rectangle('line',-1,-11,302,612)--Bis Boarder
gc_rectangle('line',301,-3,15,604)
gc_rectangle('line',-16,-3,15,604)--B2b bar boarder
end
local function drawBuffer(P)
local h=0
for i=1,#P.atkBuffer do
@@ -294,9 +293,15 @@ local function drawBuffer(P)
gc_push('transform')
gc_translate(300,max(0,600-30*sum))
gc_scale(min(.2+sum/50,1))
setFont(100)
gc_setColor(1,.2+min(sum*.02,.8)*(.5+.5*sin(TIME()*min(sum,32))),.2,min(sum/30,.8))
gc_printf(int(P.atkBufferSum1),-300,-20,292,'right')
setFont(100)
if sum>20 then
local d=P.atkBufferSum-sum
if d>.5 then
gc_translate(d^.5*(rnd()-.5)*15,d^.5*(rnd()-.5)*15)
end
end
gc_printf(int(sum),-300,-20,292,'right')
gc_pop()
end
end
@@ -312,14 +317,14 @@ local function drawB2Bbar(P)
gc_rectangle('fill',-15,b<40 and 568.5 or 118.5,13,3)
end
end
local function drawLDI(P)--Lock Delay Indicator
if P.gameEnv.easyFresh then
local function drawLDI(P,ENV)--Lock Delay Indicator
if ENV.easyFresh then
gc_setColor(1,1,1)
else
gc_setColor(1,.26,.26)
end
if P.lockDelay>=0 then
gc_rectangle('fill',0,602,300*P.lockDelay/P.gameEnv.lock,6)--Lock delay indicator
gc_rectangle('fill',0,602,300*P.lockDelay/ENV.lock,6)--Lock delay indicator
end
if P.freshTime>0 then
LDmarks:setDrawRange(1,min(P.freshTime,15))
@@ -333,11 +338,10 @@ local function drawHold(P)
local holdQueue=P.holdQueue
local N=ENV.holdCount*72
gc_push('transform')
gc_translate(-140,36)
gc_translate(-140,20)
gc_setColor(0,0,0,.4)gc_rectangle('fill',0,0,124,N+8)
gc_setColor(1,1,1)gc_rectangle('line',0,0,124,N+8)
if P.holdTime==0 then gc_setColor(.6,.4,.4)end
mText(drawableText.hold,62,-51)
gc_setColor(1,1,1)
if #holdQueue<ENV.holdCount and P.nextQueue[1]then
@@ -441,13 +445,25 @@ local function drawMission(P)
end
end
end
local function drawStartCounter(count)
gc_setColor(1,1,1)
local function drawStartCounter(P)
local count=179-P.frameRun
gc_push('transform')
gc_translate(305,220)
if count%60>45 then gc_scale(1+(count%60-45)^2*.01,1)end
setFont(95)
mStr(int(count/60+1),0,0)
gc_translate(300,300)
local num=int(count/60+1)
local d=count%60-45
if num==3 then
gc_setColor(.7,.9,1)
if d>0 then gc_scale(1+d^2*.01,1)end
elseif num==2 then
gc_setColor(1,.95,.7)
if d>0 then gc_shear(-(d/15)^2,0)end
elseif num==1 then
gc_setColor(1,.8,.8)
if d>0 then gc_rotate(d^2*.00355)end
end
setFont(100)
mStr(num,0,-70)
--P.gameEnv.initSkip
gc_pop()
end
@@ -455,11 +471,10 @@ local draw={}
function draw.drawNext_norm(P)
local ENV=P.gameEnv
local texture=SKIN.curText
gc_translate(316,36)
gc_translate(316,20)
local N=ENV.nextCount*72
gc_setColor(0,0,0,.4)gc_rectangle('fill',0,0,124,N+8)
gc_setColor(1,1,1)gc_rectangle('line',0,0,124,N+8)
mText(drawableText.next,62,-51)
N=1
gc_push('transform')
gc_translate(62,40)
@@ -484,16 +499,15 @@ function draw.drawNext_norm(P)
gc_rectangle('fill',2,72*i+3,120,2)
end
end
gc_translate(-316,-36)
gc_translate(-316,-20)
end
function draw.drawNext_hidden(P)
local ENV=P.gameEnv
local texture=SKIN.curText
gc_translate(316,36)
gc_translate(316,20)
local N=ENV.nextCount*72
gc_setColor(.5,0,0,.4)gc_rectangle('fill',0,0,124,N+8)
gc_setColor(1,1,1)gc_rectangle('line',0,0,124,N+8)
mText(drawableText.next,62,-51)
N=min(ENV.nextStartPos,P.pieceCount+1)
gc_push('transform')
gc_translate(62,40)
@@ -519,7 +533,7 @@ function draw.drawNext_hidden(P)
gc_rectangle('fill',2,72*i+3,120,2)
end
end
gc_translate(-316,-36)
gc_translate(-316,-20)
end
draw.applyFieldOffset=applyFieldOffset
@@ -636,12 +650,16 @@ function draw.norm(P)
gc_pop()
gc_setStencilTest()
drawBoarders(P)
gc_setLineWidth(2)
P:drawNext()
drawHold(P)
drawBuffer(P)
drawB2Bbar(P)
drawLDI(P)
drawHold(P)
P:drawNext()
drawLDI(P,ENV)
--Draw boarders
gc_setColor(P.frameColor)
gc.draw(playerBoarders,-17,-12)
--Draw target selecting pad
if GAME.modeEnv.royaleMode then
@@ -656,6 +674,8 @@ function draw.norm(P)
gc_printf(text.atkModeName[i],RCPB[2*i-1]-4,RCPB[2*i]+4,200,"center",nil,.5)
end
end
--Board cover
if ENV.hideBoard then
gc_stencil(hideBoardStencil[ENV.hideBoard],'replace',1)
gc_setStencilTest('equal',1)
@@ -666,13 +686,28 @@ function draw.norm(P)
end
gc_setStencilTest()
end
--Spike
local sp,spt=P.spike,P.spikeTime
if ENV.showSpike and spt>0 and sp>=10 then
local rg=10/sp
gc_setColor(rg,rg,1,min(spt/30,.8))
local x,y=150,100
if spt>85 then
local d=2*(spt-85)*min(sp/50,1)
x,y=x+(rnd()-.5)*d,y+(rnd()-.5)*d
end
mDraw(P.spikeText,x,y,nil,min(.3+(sp/26)*.4+spt/100*.3,1))
end
--Bonus texts
TEXT.draw(P.bonus)
--Display Ys
-- gc_setLineWidth(6)
-- if P.curY then gc_setColor(COLOR.R)gc_line(0,611-P.curY*30,300,610-P.curY*30)end
-- if P.ghoY then gc_setColor(COLOR.G)gc_line(0,615-P.ghoY*30,300,615-P.ghoY*30)end
-- if P.minY then gc_setColor(COLOR.B)gc_line(0,619-P.minY*30,300,620-P.minY*30)end
-- if P.curY then gc_setColor(COLOR.R) gc_line(0,611-P.curY*30,300,610-P.curY*30)end
-- if P.ghoY then gc_setColor(COLOR.G) gc_line(0,615-P.ghoY*30,300,615-P.ghoY*30)end
-- if P.minY then gc_setColor(COLOR.B) gc_line(0,619-P.minY*30,300,620-P.minY*30)end
-- gc_line(0,600-P.garbageBeneath*30,300,600-P.garbageBeneath*30)
gc_pop()
@@ -705,7 +740,7 @@ function draw.norm(P)
if P.life>0 then drawLife(P.life)end
drawMission(P)
if P.frameRun<180 then drawStartCounter(179-P.frameRun)end
if P.frameRun<180 then drawStartCounter(P)end
gc_pop()
end
function draw.small(P)

View File

@@ -22,6 +22,8 @@ return{
bufferWarn=false,
highCam=false,
nextPos=false,
showSpike=false,
hideBoard=false,
flipBoard=false,

View File

@@ -79,6 +79,7 @@ local function newEmptyPlayer(id,mini)
--Inherit functions of Player class
for k,v in next,Player do P[k]=v end
--Set key/timer event
if P.id==1 and GAME.recording then
P.pressKey=pressKey_Rec
P.releaseKey=releaseKey_Rec
@@ -88,6 +89,7 @@ local function newEmptyPlayer(id,mini)
end
P.update=ply_update.alive
--Field position
P.fieldOff={--Shake FX
x=0,y=0,
vx=0,vy=0,
@@ -101,8 +103,8 @@ local function newEmptyPlayer(id,mini)
-- P.centerX,P.centerY=...
-- P.absFieldX,P.absFieldY=...
--If draw in small mode
P.mini=mini
--Minimode
P.miniMode=mini
if mini then
P.canvas=love.graphics.newCanvas(60,120)
P.frameWait=rnd(26,62)
@@ -111,60 +113,87 @@ local function newEmptyPlayer(id,mini)
P.draw=ply_draw.norm
end
--States
P.type='none'
P.sound=false
P.alive=true
P.control=false
P.timing=false
P.result=false--String: 'finish'|'win'|'lose'
P.stat=getNewStatTable()
P.modeData=setmetatable({},modeDataMeta)--Data use by mode
P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end
P.clearingRow,P.clearedRow={},{}--Clearing animation height,cleared row mark
P.dropFX,P.moveFX,P.lockFX,P.clearFX={},{},{},{}
P.tasks={}
P.bonus={}--Texts
--Times
P.frameRun=GAME.frameStart--Frame run, mainly for replay
P.endCounter=0--Used after gameover
P.keyTime={}for i=1,10 do P.keyTime[i]=-1e99 end P.keySpeed=0
P.dropTime={}for i=1,10 do P.dropTime[i]=-1e99 end P.dropSpeed=0
--Randomizers
P.seqRND=love.math.newRandomGenerator(GAME.seed)
P.atkRND=love.math.newRandomGenerator(GAME.seed)
P.holeRND=love.math.newRandomGenerator(GAME.seed)
P.aiRND=love.math.newRandomGenerator(GAME.seed)
P.frameRun=GAME.frameStart
P.alive=true
P.control=false
P.timing=false
P.stat=getNewStatTable()
P.modeData=setmetatable({},modeDataMeta)--Data use by mode
P.keyTime={}P.keySpeed=0
P.dropTime={}P.dropSpeed=0
for i=1,10 do P.keyTime[i]=-1e99 end
for i=1,10 do P.dropTime[i]=-1e99 end
--Field-related
P.field,P.visTime={},{}
P.atkBuffer={}
P.atkBufferSum=0
P.atkBufferSum1=0
P.keepVisible=true
P.showTime=false
P.garbageBeneath=0
P.fieldBeneath=0
P.fieldUp=0
--Royale-related
--Attack-related
P.atkBuffer={}
P.atkBufferSum,P.atkBufferSum1=0,0
P.spike,P.spikeTime=0,0
P.spikeText=love.graphics.newText(getFont(100))
--Attacker-related
P.badge,P.strength=0,0
P.atkMode,P.swappingAtkMode=1,20
P.atker,P.atking,P.lastRecv={}
--Network-related
--User-related
P.username=""
P.uid=false
P.sid=false
P.dropDelay,P.lockDelay=0,0
P.showTime=false
P.keepVisible=true
--Block states
--[[
P.cur={
id=shapeID,
bk=matrix[2],
sc=table[2],
dir=direction,
name=nameID
color=colorID,
}
P.curX,P.curY,P.ghoY,P.minY=0,0,0,0--x,y,ghostY
P.cur={
id=shapeID,
bk=matrix[2],
sc=table[2],
dir=direction,
name=nameID
color=colorID,
}
P.newNext=false--Warped coroutine to get new next, loaded in applyGameEnv()
]]
-- P.curX,P.curY,P.ghoY,P.minY=0,0,0,0--x,y,ghostY
P.holdQueue={}
P.holdTime=0
P.nextQueue={}
P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging
P.dropDelay,P.lockDelay=0,0
P.waiting,P.falling=-1,-1
P.freshTime=0
P.spinLast=false
P.spinSeq=0--For Ospin, each digit mean a spin
P.ctrlCount=0--Key press time, for finesse check
--Game states
P.combo=0
P.b2b,P.b2b1=0,0--B2B point & Displayed B2B point
P.score1=0--Displayed score
P.pieceCount=0--Count pieces from next, for drawing bagline
P.finesseCombo,P.finesseComboTime=0,0
P.nextQueue={}
P.holdQueue={}
P.holdTime=0
P.lastPiece={
id=0,name=0,--block id/name
@@ -179,34 +208,6 @@ local function newEmptyPlayer(id,mini)
pc=false,hpc=false,--if pc/hpc
special=false,--if special clear (spin, >=4, pc)
}
P.spinSeq=0--For Ospin, each digit mean a spin
P.ctrlCount=0--Key press time, for finesse check
P.pieceCount=0--Count pieces from next, for drawing bagline
P.type='none'
P.sound=false
-- P.newNext=false--Warped coroutine to get new next, loaded in applyGameEnv()
P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end
P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging
P.waiting,P.falling=-1,-1
P.clearingRow,P.clearedRow={},{}--Clearing animation height,cleared row mark
P.combo,P.b2b=0,0
P.finesseCombo=0
P.garbageBeneath=0
P.fieldBeneath=0
P.fieldUp=0
P.score1,P.b2b1=0,0
P.finesseComboTime=0
P.dropFX,P.moveFX,P.lockFX,P.clearFX={},{},{},{}
P.tasks={}--Tasks
P.bonus={}--Text objects
P.endCounter=0--Used after gameover
P.result=false--String: 'finish'|'win'|'lose'
return P
end
local function loadGameEnv(P)--Load gameEnv
@@ -321,7 +322,7 @@ local function applyGameEnv(P)--Finish gameEnv processing
P.newNext=coroutine.wrap(seqGenerators(P))
P.newNext(P,P.gameEnv.seqData)
if P.mini then
if P.miniMode then
ENV.lockFX=false
ENV.dropFX=false
ENV.moveFX=false

View File

@@ -105,7 +105,7 @@ function Player:createClearingFX(y,spd)
end
function Player:createBeam(R,send,power,color)
local x1,y1,x2,y2
if self.mini then x1,y1=self.centerX,self.centerY
if self.miniMode then x1,y1=self.centerX,self.centerY
else x1,y1=self.x+(30*(self.curX+self.cur.sc[2])-30+15+150)*self.size,self.y+(600-30*(self.curY+self.cur.sc[1])+15)*self.size
end
if R.small then x2,y2=R.centerX,R.centerY
@@ -136,7 +136,7 @@ end
function Player:setPosition(x,y,size)
size=size or 1
self.x,self.y,self.size=x,y,size
if self.mini or self.demo then
if self.miniMode or self.demo then
self.fieldX,self.fieldY=x,y
self.centerX,self.centerY=x+300*size,y+600*size
else
@@ -1380,6 +1380,13 @@ do--Player.drop(self)--Place piece
self.combo=cmb
--Spike
if atk>0 then
self.spike=self.spikeTime==0 and atk or self.spike+atk
self.spikeTime=min(self.spikeTime+atk*20,100)
self.spikeText:set(self.spike)
end
--DropSpeed bonus
if self._20G then
cscore=cscore*2
@@ -1727,7 +1734,7 @@ function Player:lose(force)
for i=A.strength+1,4 do
if A.badge>=ROYALEDATA.powerUp[i]then
A.strength=i
A:setFrameColor(A.strength)
A:setFrameColor(i)
end
end
self.lastRecv=A
@@ -1757,7 +1764,7 @@ function Player:lose(force)
end
gameOver()
self:newTask(#PLAYERS>1 and tick_lose or tick_finish)
if GAME.net then
if GAME.net and not NET.spectate then
NET.signal_die()
else
TASK.new(tick_autoPause)

View File

@@ -3,7 +3,7 @@ local int,abs,rnd=math.floor,math.abs,math.random
local rem=table.remove
local assert,resume,status=assert,coroutine.resume,coroutine.status
local TEXT,GAME=TEXT,GAME
local TEXT,GAME,CC=TEXT,GAME,CC
local PLY_ALIVE=PLY_ALIVE
local function update_misc(P,dt)
@@ -12,6 +12,9 @@ local function update_misc(P,dt)
P.finesseComboTime=P.finesseComboTime-1
end
--Update spike counter
if P.spikeTime>0 then P.spikeTime=P.spikeTime-1 end
--Update atkBuffer alert
local t=P.atkBufferSum1
if t<P.atkBufferSum then
@@ -402,14 +405,15 @@ function update.dead(P,dt)
end
function update.remote_alive(P,dt)
local frameRate=(P.stream[#P.stream-1]or 0)-P.frameRun
frameRate=frameRate<20 and 1 or
frameRate<30 and rnd(2)or
frameRate<60 and 2 or
frameRate<90 and 3 or
frameRate<120 and 5 or
frameRate<150 and 7 or
frameRate<180 and 10 or
20
frameRate=
frameRate<20 and 1 or
frameRate<30 and rnd(2)or
frameRate<60 and 2 or
frameRate<90 and 3 or
frameRate<120 and 5 or
frameRate<150 and 7 or
frameRate<180 and 10 or
20
for _=1,frameRate do
local eventTime=P.stream[P.streamProgress]
if eventTime then--Normal state, event forward

View File

@@ -116,16 +116,16 @@ local function tapBoard(x,y,key)
if checkBoard(b)then
state=2
time=TIME()-startTime
if time<1 then LOG.print("不是人",COLOR.lB)
elseif time<2 then LOG.print("还是人",COLOR.lB)
elseif time<3 then LOG.print("神仙",COLOR.lB)
elseif time<5 then LOG.print("太强了",COLOR.lB)
elseif time<7.5 then LOG.print("很强",COLOR.lB)
elseif time<10 then LOG.print("可以的",COLOR.lB)
elseif time<20 then LOG.print("马上入门了",COLOR.lB)
elseif time<30 then LOG.print("入门不远了",COLOR.lB)
elseif time<60 then LOG.print("多加练习",COLOR.lB)
else LOG.print("第一次玩?加油",COLOR.lB)
if time<1 then LOG.print("不是人")
elseif time<2 then LOG.print("还是人")
elseif time<3 then LOG.print("神仙")
elseif time<5 then LOG.print("太强了")
elseif time<7.5 then LOG.print("很强")
elseif time<10 then LOG.print("可以的")
elseif time<20 then LOG.print("马上入门了")
elseif time<30 then LOG.print("入门不远了")
elseif time<60 then LOG.print("多加练习")
else LOG.print("第一次玩?加油")
end
SFX.play('win')
return

View File

@@ -677,8 +677,7 @@ userG.the_box=first_box
local scene={}
function scene.sceneInit()
TASK.new(function()YIELD()WIDGET.sel=inputBox end)
enableTextInput()
TASK.new(function()WIDGET.focus(inputBox)end)
BG.set('none')
end
@@ -688,7 +687,7 @@ end
function scene.keyDown(k)
if k=="return"then
local input=inputBox:getText()
local input=STRING.trim(inputBox:getText())
if input==""then return end
--Write History
@@ -700,7 +699,6 @@ function scene.keyDown(k)
log""
--Execute
input=input:sub((input:find("%S")))
if input:byte()==35 then
--Execute lua code
log{C.lC,"> "..input}
@@ -780,13 +778,13 @@ function scene.keyDown(k)
elseif combKey[k]and kb.isDown("lctrl","rctrl")then
combKey[k]()
elseif k=="escape"then
if WIDGET.sel~=inputBox then
WIDGET.sel=inputBox
if not WIDGET.isFocus(inputBox)then
WIDGET.focus(inputBox)
else
SCN.back()
end
else
if WIDGET.sel~=inputBox then WIDGET.sel=inputBox end
if not WIDGET.isFocus(inputBox)then WIDGET.focus(inputBox)end
WIDGET.keyPressed(k)
end
end

View File

@@ -82,7 +82,7 @@ function scene.keyDown(key)
str=str.."!"
if #MISSION>0 then str=str..DATA.copyMission()end
sys.setClipboardText(str.."!"..DATA.copyBoards().."!")
LOG.print(text.exportSuccess,COLOR.G)
LOG.print(text.exportSuccess,'message')
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
local str=sys.getClipboardText()
local args=STRING.split(str:sub((str:find(":")or 0)+1),"!")
@@ -98,9 +98,9 @@ function scene.keyDown(key)
if args[i]:find("%S")and not DATA.pasteBoard(args[i],i-3)and i<#args then goto THROW_fail end
end
freshMiniFieldVisible()
LOG.print(text.importSuccess,COLOR.G)
LOG.print(text.importSuccess,'message')
do return end
::THROW_fail::LOG.print(text.dataCorrupted,COLOR.R)
::THROW_fail::LOG.print(text.dataCorrupted,'error')
elseif key=="escape"then
FILE.save(CUSTOMENV,'conf/customEnv','q')
SCN.back()

View File

@@ -1,6 +1,6 @@
local sList={
visible={"show","easy","slow","medium","fast","none"},
freshLimit={0,8,15,1e99},
freshLimit={0,1,2,4,6,8,10,12,15,30,1e99},
opponent={"X","9S Lv.1","9S Lv.2","9S Lv.3","9S Lv.4","9S Lv.5","CC Lv.1","CC Lv.2","CC Lv.3","CC Lv.4","CC Lv.5"},
life={0,1,2,3,5,10,15,26,42,87,500},
pushSpeed={1,2,3,5,15},

View File

@@ -216,21 +216,20 @@ function scene.keyDown(key)
SFX.play('fall',.8)
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
sys.setClipboardText("Techmino Field:"..DATA.copyBoard(page))
LOG.print(text.exportSuccess,COLOR.G)
LOG.print(text.exportSuccess,'message')
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
local str=sys.getClipboardText()
local p=str:find(":")--ptr*
if p then
if not str:sub(1,p-1):find("Field")then
LOG.print(text.pasteWrongPlace)
LOG.print(text.pasteWrongPlace,'warn')
end
str=str:sub(p+1)
end
if DATA.pasteBoard(str,page)then
LOG.print(text.importSuccess,COLOR.G)
LOG.print(text.importSuccess,'message')
else
print(text.dataCorrupted)
LOG.print(text.dataCorrupted,COLOR.R)
LOG.print(text.dataCorrupted,'error')
end
elseif key=="pageup"then
page=max(page-1,1)

View File

@@ -71,22 +71,22 @@ function scene.keyDown(key)
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
if #MISSION>0 then
sys.setClipboardText("Techmino Target:"..DATA.copyMission())
LOG.print(text.exportSuccess,COLOR.G)
LOG.print(text.exportSuccess,'message')
end
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
local str=sys.getClipboardText()
local p=str:find(":")--ptr*
if p then
if not str:sub(1,p-1):find("Target")then
LOG.print(text.pasteWrongPlace)
LOG.print(text.pasteWrongPlace,'warn')
end
str=str:sub(p+1)
end
if DATA.pasteMission(str)then
LOG.print(text.importSuccess,COLOR.G)
LOG.print(text.importSuccess,'message')
cur=#MISSION
else
LOG.print(text.dataCorrupted,COLOR.R)
LOG.print(text.dataCorrupted,'error')
end
elseif key=="escape"then
SCN.back()

View File

@@ -85,22 +85,22 @@ function scene.keyDown(key)
elseif key=="c"and kb.isDown("lctrl","rctrl")or key=="cC"then
if #BAG>0 then
sys.setClipboardText("Techmino SEQ:"..DATA.copySequence())
LOG.print(text.exportSuccess,COLOR.G)
LOG.print(text.exportSuccess,'message')
end
elseif key=="v"and kb.isDown("lctrl","rctrl")or key=="cV"then
local str=sys.getClipboardText()
local p=str:find(":")--ptr*
if p then
if not str:sub(1,p-1):find("SEQ")then
LOG.print(text.pasteWrongPlace)
LOG.print(text.pasteWrongPlace,'warn')
end
str=str:sub(p+1)
end
if DATA.pasteSequence(str)then
LOG.print(text.importSuccess,COLOR.G)
LOG.print(text.importSuccess,'message')
cur=#BAG
else
LOG.print(text.dataCorrupted,COLOR.R)
LOG.print(text.dataCorrupted,'error')
end
elseif key=="escape"then
SCN.back()

View File

@@ -68,8 +68,7 @@ function scene.sceneInit()
scrollPos=0
lastSearch=false
TASK.new(function()YIELD()WIDGET.sel=inputBox end)
enableTextInput()
TASK.new(function()YIELD()WIDGET.focus(inputBox)end)
BG.set('rainbow')
end

View File

@@ -197,8 +197,8 @@ local loadingThread=coroutine.wrap(function()
upFloor()
end
if progress==25 then
SFX.play("emit",.6)
SFX.play("enter",.8)
SFX.play('emit',.6)
SFX.play('enter',.8)
SFX.play('welcome_sfx')
VOC.play('welcome_voc')
THEME.fresh()

View File

@@ -6,9 +6,9 @@ local savePW=false
local function login()
local email,password=emailBox:getText(),passwordBox:getText()
if not STRING.simpEmailCheck(email)then
LOG.print(text.wrongEmail)return
LOG.print(text.wrongEmail,'warn')return
elseif #password==0 then
LOG.print(text.noPassword)return
LOG.print(text.noPassword,'warn')return
end
NET.wsconn_user_pswd(email,password)
if savePW then
@@ -29,7 +29,6 @@ function scene.sceneInit()
emailBox:setText(data[1])
passwordBox:setText(data[2])
end
enableTextInput()
end
scene.widgetList={

View File

@@ -46,10 +46,10 @@ function scene.mouseDown(x,y)
end
scene.touchDown=scene.mouseDown
local function testButton(n)
if WIDGET.sel==scene.widgetList[n]then
if WIDGET.isFocus(scene.widgetList[n])then
return true
else
WIDGET.sel=scene.widgetList[n]
WIDGET.focus(scene.widgetList[n])
end
end
function scene.keyDown(key)
@@ -64,20 +64,11 @@ function scene.keyDown(key)
elseif key=="a"then
if testButton(3)then
if NET.connected then
if NET.allow_online then
if WS.status('user')=='running'then
NET.getAccessToken()
else
SCN.go('login')
end
else
TEXT.show(text.needUpdate,640,450,60,'flicker')
SFX.play('finesseError')
end
NET.tryLogin(false)
else
TEXT.show(text.noInternet,640,450,60,'flicker')
NET.wsconn_app()
SFX.play('finesseError')
LOG.print(text.wsConnecting,'message')
SFX.play('connect')
end
end
elseif key=="z"then
@@ -130,7 +121,7 @@ function scene.update(dt)
end
local L=scene.widgetList
for i=1,8 do
L[i].x=L[i].x*.9+(widgetX0[i]-400+(WIDGET.sel==L[i]and(i<5 and 100 or -100)or 0))*.1
L[i].x=L[i].x*.9+(widgetX0[i]-400+(WIDGET.isFocus(L[i])and(i<5 and 100 or -100)or 0))*.1
end
end

View File

@@ -21,7 +21,7 @@ local scene={}
function scene.sceneInit(org)
BG.set()
destroyPlayers()
mapCam.zoomK=org=="main"and 5 or 1
mapCam.zoomK=org=='main'and 5 or 1
end
local function getK()

View File

@@ -1,10 +1,15 @@
local gc,tc,kb=love.graphics,love.touch,love.keyboard
local gc,kb,tc=love.graphics,love.keyboard,love.touch
local gc_setColor,gc_print=gc.setColor,gc.print
local setFont,mStr=setFont,mStr
local ins=table.insert
local SCR,VK,NET,netPLY=SCR,VK,NET,netPLY
local PLAYERS,GAME=PLAYERS,GAME
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=560,hide=false}
local inputBox=WIDGET.newInputBox{name="input",x=340,y=660,w=600,h=50,hide=false}
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=560}
local inputBox=WIDGET.newInputBox{name="input",x=340,y=660,w=600,h=50}
local playing
local lastUpstreamTime
@@ -13,6 +18,34 @@ local lastBackTime=0
local noTouch,noKey=false,false
local touchMoveLastFrame=false
local function _setReady()NET.signal_joinMode(1)end
local function _setSpectate()NET.signal_joinMode(2)end
local function _setCancel()NET.signal_joinMode(0)end
local function _gotoSetting()
if not(netPLY.getSelfReady()or NET.getlock('ready'))then
SCN.go('setting_game')
end
end
local function _quit()
if TIME()-lastBackTime<1 then
NET.signal_quit()
else
lastBackTime=TIME()
LOG.print(text.sureQuit,'warn')
end
end
local function _switchChat()
if inputBox.hide then
textBox.hide=false
inputBox.hide=false
WIDGET.focus(inputBox)
else
textBox.hide=true
inputBox.hide=true
WIDGET.unFocus(true)
end
end
local scene={}
function scene.sceneInit(org)
@@ -25,8 +58,10 @@ function scene.sceneInit(org)
lastUpstreamTime=0
upstreamProgress=1
if org=="setting_game"then
NET.changeConfig()
if org=='setting_game'then NET.changeConfig()end
if NET.streamRoomID then
NET.wsconn_stream()
NET.streamRoomID=false
end
end
function scene.sceneBack()
@@ -36,7 +71,8 @@ end
scene.mouseDown=NULL
function scene.mouseMove(x,y)netPLY.mouseMove(x,y)end
function scene.touchDown(x,y)
if not playing or noTouch then return end
if not playing then netPLY.mouseMove(x,y)return end
if noTouch then return end
local t=VK.on(x,y)
if t then
@@ -46,16 +82,14 @@ function scene.touchDown(x,y)
end
function scene.touchUp(x,y)
if not playing or noTouch then return end
local n=VK.on(x,y)
if n then
PLAYERS[1]:releaseKey(n)
VK.release(n)
end
end
function scene.touchMove(x,y)
if not playing then netPLY.mouseMove(x,y)end
if touchMoveLastFrame or noTouch then return end
function scene.touchMove()
if touchMoveLastFrame or not playing or noTouch then return end
touchMoveLastFrame=true
local L=tc.getTouches()
@@ -79,35 +113,29 @@ function scene.touchMove(x,y)
end
function scene.keyDown(key)
if key=="escape"then
if TIME()-lastBackTime<1 then
NET.signal_quit()
if not inputBox.hide then
scene.keyDown("switchChat")
else
lastBackTime=TIME()
LOG.print(text.sureQuit,COLOR.O)
_quit()
end
elseif key=="return"then
if inputBox.hide then
textBox.hide=false
inputBox.hide=false
TASK.new(function()YIELD()WIDGET.sel=inputBox end)
enableTextInput()
else
local mes=inputBox:getText():match"%S+"
if mes and #mes>0 then
local mes=STRING.trim(inputBox:getText())
if not inputBox.hide then
if #mes>0 then
NET.sendMessage(mes)
inputBox:clear()
elseif #EDITING==0 then
textBox.hide=true
inputBox.hide=true
WIDGET.sel=nil
kb.setTextInput(false)
_switchChat()
end
else
_switchChat()
end
elseif not inputBox.hide then
WIDGET.sel=inputBox
WIDGET.keyPressed(key)
print(1)
WIDGET.focus(inputBox)
inputBox:keypress(key)
elseif playing then
if noKey then return end
if not playing or noKey then return end
local k=keyMap.keyboard[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
@@ -115,16 +143,17 @@ function scene.keyDown(key)
end
else
if key=="space"then
NET.signal_ready(not netPLY.getSelfReady())
elseif key=="s"then
if not(netPLY.getSelfReady()or NET.getlock('ready'))then
SCN.go('setting_game')
if netPLY.getSelfJoinMode()==0 then
(kb.isDown("lctrl","rctrl","lalt","ralt")and _setSpectate or _setReady)()
else
_setCancel()
end
_gotoSetting()
end
end
end
function scene.keyUp(key)
if noKey then return end
if not playing or noKey then return end
local k=keyMap.keyboard[key]
if k and k>0 then
PLAYERS[1]:releaseKey(k)
@@ -133,13 +162,9 @@ function scene.keyUp(key)
end
function scene.gamepadDown(key)
if key=="back"then
if TIME()-lastBackTime<1 then
NET.signal_quit()
else
lastBackTime=TIME()
LOG.print(text.sureQuit,COLOR.O)
end
scene.keyDown("escape")
else
if not playing then return end
local k=keyMap.joystick[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
@@ -148,6 +173,7 @@ function scene.gamepadDown(key)
end
end
function scene.gamepadUp(key)
if not playing then return end
local k=keyMap.joystick[key]
if k and k>0 then
PLAYERS[1]:releaseKey(k)
@@ -179,13 +205,12 @@ function scene.socketRead(cmd,d)
if not playing then
playing=true
love.keyboard.setKeyRepeat(false)
netPLY.resetReady()
netPLY.mouseMove(0,0)
lastUpstreamTime=0
upstreamProgress=1
resetGameData('n',d.seed)
resetGameData('n',NET.seed)
netPLY.mouseMove(0,0)
else
LOG.print("Redundant [Go]",30,COLOR.G)
LOG.print("Redundant [Go]",'warn')
end
elseif cmd=='finish'then
playing=false
@@ -198,21 +223,24 @@ function scene.socketRead(cmd,d)
end
end
if winnerUID then
TEXT.show(text.champion:gsub("$1",netPLY.getUsername(winnerUID)),640,260,80,'zoomout',.26)
TEXT.show(text.champion:gsub("$1",USERS.getUsername(winnerUID)),640,260,80,'zoomout',.26)
end
netPLY.resetState()
elseif cmd=='stream'then
if d.uid~=USER.uid and playing then
if d.uid~=USER.uid then
for _,P in next,PLAYERS do
if P.uid==d.uid then
local res,stream=pcall(love.data.decode,'string','base64',d.stream)
if res then
DATA.pumpRecording(stream,P.stream)
else
LOG.print("Bad stream from "..P.username.."#"..P.uid)
LOG.print("Bad stream from "..P.username.."#"..P.uid,30)
end
break
end
end
end
end
end
@@ -234,15 +262,19 @@ function scene.update(dt)
checkWarning()
--Upload stream
if P1.frameRun-lastUpstreamTime>8 then
if not NET.spectate and P1.frameRun-lastUpstreamTime>8 then
local stream
stream,upstreamProgress=DATA.dumpRecording(GAME.rep,upstreamProgress)
if #stream>0 then
NET.uploadRecStream(stream)
else
if not GAME.rep[upstreamProgress]then
ins(GAME.rep,P1.frameRun)
ins(GAME.rep,0)
end
stream,upstreamProgress=DATA.dumpRecording(GAME.rep,upstreamProgress)
if #stream%3==1 then
stream=stream.."\0\0"
elseif #stream%3==2 then
stream=stream.."\0\0\0\0"
end
NET.uploadRecStream(stream)
lastUpstreamTime=PLAYERS[1].alive and P1.frameRun or 1e99
end
else
@@ -264,27 +296,37 @@ function scene.draw()
--Warning
drawWarning()
if NET.spectate then
setFont(30)
gc_setColor(.2,1,0,.8)
gc_print(text.spectating,940,0)
end
else
--Users
netPLY.draw()
--Ready & Set mark
gc.setColor(.1,1,0,.9)
setFont(60)
if NET.connectingStream then
mStr(text.set,640,10)
elseif NET.allReady then
mStr(text.ready,640,10)
setFont(50)
if NET.allReady then
gc_setColor(0,1,.5,.9)
mStr(text.ready,640,15)
elseif NET.connectingStream then
gc_setColor(.1,1,.8,.9)
mStr(text.connStream,640,15)
elseif NET.waitingStream then
gc_setColor(0,.8,1,.9)
mStr(text.waitStream,640,15)
end
--Room info.
gc.setColor(1,1,1)
gc_setColor(1,1,1)
setFont(25)
gc.printf(NET.roomInfo.name,0,685,1270,'right')
gc.printf(NET.roomState.roomInfo.name,0,685,1270,'right')
setFont(40)
gc.print(netPLY.getCount().."/"..NET.roomInfo.capacity,70,655)
if NET.roomInfo.private then gc.draw(IMG.lock,30,668)end
if NET.roomInfo.start then gc.setColor(0,1,0)gc.print(text.started,230,655)end
gc.print(netPLY.getCount().."/"..NET.roomState.capacity,70,655)
if NET.roomState.private then gc.draw(IMG.lock,30,668)end
if NET.roomState.start then gc_setColor(0,1,0)gc_print(text.started,230,655)end
--Profile
drawSelfProfile()
@@ -296,32 +338,40 @@ function scene.draw()
--New message
if textBox.new then
setFont(40)
gc.setColor(1,1,0)
gc_setColor(1,1,0)
gc.print("M",430,10)
end
end
scene.widgetList={
textBox,
inputBox,
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=pressKey"s",hideF=function()return playing or netPLY.getSelfReady()or NET.getlock('ready')end},
WIDGET.newKey{name="ready",x=1060,y=630,w=300,h=80,color='lB',font=40,code=pressKey"space",
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=_gotoSetting,hideF=function()return playing or netPLY.getSelfReady()or NET.getlock('ready')end},
WIDGET.newKey{name="ready",x=1060,y=510,w=370,h=90,color='lG',font=35,code=_setReady,
hideF=function()
return
playing or
NET.serverGaming or
netPLY.getSelfReady()or
NET.roomState.start or
netPLY.getSelfReady() or
NET.getlock('ready')
end},
WIDGET.newKey{name="cancel",x=1060,y=630,w=300,h=80,color='H',font=40,code=pressKey"space",
WIDGET.newKey{name="spectate",x=1060,y=610,w=370,h=90,color='lO',font=35,code=_setSpectate,
hideF=function()
return
playing or
NET.serverGaming or
not netPLY.getSelfReady()or
NET.roomState.start or
netPLY.getSelfReady() or
NET.getlock('ready')
end},
WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=pressKey"return"},
WIDGET.newKey{name="quit",fText="X",x=900,y=35,w=60,font=40,code=pressKey"escape"},
WIDGET.newKey{name="cancel",x=1060,y=560,w=370,h=120,color='lH',font=40,code=_setCancel,
hideF=function()
return
playing or
NET.roomState.start or
not netPLY.getSelfReady() or
NET.getlock('ready')
end},
WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=_switchChat},
WIDGET.newKey{name="quit",fText="X",x=900,y=35,w=60,font=40,code=_quit},
}
return scene

View File

@@ -31,7 +31,7 @@ scene.widgetList={
SCN.back()
end
else
LOG.print(text.sureQuit,COLOR.O)
LOG.print(text.sureQuit,'warn')
lastLogoutTime=TIME()
end
end},

View File

@@ -8,8 +8,20 @@ local scrollPos,selected
local fetchTimer
local lastCreateRoomTime=0
--[[room={
rid="qwe",
roomInfo={
name="MrZ's room",
type="classic",
version=1409,
},
private=false,
start=false,
count=4,
capacity=5,
}]]
local function fetchRoom()
fetchTimer=5
fetchTimer=10
NET.fetchRoom()
end
@@ -17,8 +29,6 @@ local scene={}
function scene.sceneInit()
BG.set()
NET.allReady=false
NET.connectingStream=false
scrollPos=0
selected=1
fetchRoom()
@@ -29,7 +39,7 @@ function scene.wheelMoved(_,y)
end
function scene.keyDown(k)
if k=="r"then
if fetchTimer<=3.26 then
if fetchTimer<=7 then
fetchRoom()
end
elseif k=="s"then
@@ -73,27 +83,26 @@ function scene.keyDown(k)
end
elseif k=="return"then
if NET.getlock('fetchRoom')or not NET.roomList[selected]then return end
if NET.roomList[selected].private then
LOG.print("Can't enter private room now")
return
end
NET.enterRoom(NET.roomList[selected])--,password
local R=NET.roomList[selected]
if R.roomInfo.version~=VERSION.short then LOG.print("Version doesn't match",'message')return end
if R.private then LOG.print("Can't enter private room now",'message')return end
NET.enterRoom(R)--,password
end
end
end
function scene.mouseMove(x,y,_,dy)
if ms.isDown(1)and x>50 and x<1110 and y>110 and y<510 then
if ms.isDown(1)and x>50 and x<850 and y>110 and y<510 then
scene.wheelMoved(0,dy/40)
end
end
function scene.touchMove(x,y,_,dy)
if x>50 and x<1110 and y>110 and y<510 then
if x>50 and x<850 and y>110 and y<510 then
scene.wheelMoved(0,dy/40)
end
end
function scene.mouseClick(x,y)
if x>50 and x<1110 then
if x>50 and x<850 then
y=int((y-70)/40)
if y>=1 and y<=10 then
local s=int(y+scrollPos)
@@ -128,46 +137,64 @@ end
function scene.draw()
--Fetching timer
gc.setColor(1,1,1,.12)
gc.arc('fill','pie',300,620,60,-1.5708,-1.5708-1.2566*fetchTimer)
gc.arc('fill','pie',300,620,60,-1.5708,-1.5708-.6283*fetchTimer)
--Room list
gc.setColor(1,1,1)
gc.setLineWidth(2)
gc.rectangle('line',50,110,1060,400)
gc.rectangle('line',50,110,800,400)
local roomCount=#NET.roomList
if roomCount>0 then
setFont(35)
if roomCount>10 then
local len=400*10/roomCount
gc.rectangle('fill',837,110+(400-len)*scrollPos/(roomCount-10),12,len)
end
gc.push('transform')
gc.stencil(roomListStencil,'replace',1)
gc.setStencilTest('equal',1)
gc.translate(0,scrollPos%1*-40)
setFont(35)
local pos=int(scrollPos)
for i=1,math.min(11,roomCount-pos)do
local R=NET.roomList[pos+i]
if pos+i==selected then
gc.setColor(1,1,1,.3)
gc.rectangle('fill',50,70+40*i,1060,40)
end
if R.start then
gc.setColor(0,1,0)
gc.print(text.started,660,66+40*i)
gc.rectangle('fill',50,70+40*i,800,40)
end
gc.setColor(1,1,1)
if R.private then gc.draw(IMG.lock,60,75+40*i)end
gc.print(R.count.."/"..R.capacity,720,66+40*i)
gc.setColor(.9,.9,1)
gc.print(pos+i,95,66+40*i)
gc.setColor(1,1,.7)
gc.print(R.name,250,66+40*i)
gc.setColor(1,1,1)
gc.printf(R.type,430,66+40*i,500,'right')
gc.print(R.count.."/"..R.capacity,980,66+40*i)
if R.private then
gc.draw(IMG.lock,59,75+40*i)
if R.start then
gc.setColor(0,.4,.1)
else
gc.setColor(1,1,.7)
end
gc.print(R.roomInfo.name,250,66+40*i)
end
gc.setStencilTest()
gc.pop()
if roomCount>10 then
local len=400*10/roomCount
gc.rectangle('fill',1218,110+(400-len)*scrollPos/(roomCount-10),12,len)
gc.setColor(1,1,1)
gc.rectangle('line',860,240,385,270)
if NET.roomList[selected]then
local R=NET.roomList[selected]
setFont(25)
gc.print(R.roomInfo.type,870,265)
gc.setColor(1,1,.7)
gc.printf(R.roomInfo.name,870,240,365)
setFont(20)
if R.start then
gc.setColor(0,1,.2)
gc.print(text.started,870,475)
end
if R.roomInfo.version~=VERSION.short then
gc.setColor(1,.2,0)
gc.printf(R.roomInfo.version,870,475,365,'right')
end
end
end
@@ -180,9 +207,9 @@ end
scene.widgetList={
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=pressKey"s"},
WIDGET.newText{name="refreshing",x=580,y=255,font=45,hideF=function()return not NET.getlock('fetchRoom')end},
WIDGET.newText{name="noRoom", x=580,y=260,font=40,hideF=function()return #NET.roomList>0 or NET.getlock('fetchRoom')end},
WIDGET.newKey{name="refresh", x=300,y=620,w=140,h=140,font=35,code=fetchRoom,hideF=function()return fetchTimer>3.26 end},
WIDGET.newText{name="refreshing",x=450,y=255,font=45,hideF=function()return not NET.getlock('fetchRoom')end},
WIDGET.newText{name="noRoom", x=450,y=260,font=40,hideF=function()return #NET.roomList>0 or NET.getlock('fetchRoom')end},
WIDGET.newKey{name="refresh", x=300,y=620,w=140,h=140,font=35,code=fetchRoom,hideF=function()return fetchTimer>7 end},
WIDGET.newKey{name="new", x=500,y=620,w=140,h=140,font=20,code=pressKey"n"},
WIDGET.newKey{name="new2", x=700,y=620,w=140,h=140,font=20,code=pressKey"m"},
WIDGET.newKey{name="join", x=900,y=620,w=140,h=140,font=40,code=pressKey"return",hideF=function()return #NET.roomList==0 or NET.getlock('enterRoom')end},

View File

@@ -34,7 +34,7 @@ function scene.sceneInit(org)
local P=PLAYERS[1]
local S=P.stat
timer=org=="game"and 0 or 50
timer=org=='game'and 0 or 50
local frameLostRate=(S.frame/S.time/60-1)*100
form={
@@ -122,7 +122,7 @@ function scene.sceneBack()
STAT.todayTime=STAT.todayTime+PLAYERS[1].stat.time
if not GAME.replaying and(PLAYERS[1].frameRun>400 or GAME.result)and not GAME.result then
mergeStat(STAT,PLAYERS[1].stat)
FILE.save(STAT,'conf/data')
FILE.save(STAT,'conf/data','q')
end
end

View File

@@ -6,21 +6,17 @@ local function register()
local password= WIDGET.active.password:getText()
local password2=WIDGET.active.password2:getText()
if #username==0 then
LOG.print(text.noUsername)return
LOG.print(text.noUsername,'warn')return
elseif not STRING.simpEmailCheck(email)then
LOG.print(text.wrongEmail)return
LOG.print(text.wrongEmail,'warn')return
elseif #password==0 or #password2==0 then
LOG.print(text.noPassword)return
LOG.print(text.noPassword,'warn')return
elseif password~=password2 then
LOG.print(text.diffPassword)return
LOG.print(text.diffPassword,'warn')return
end
NET.register(username,email,password)
end
function scene.sceneInit()
enableTextInput()
end
scene.widgetList={
WIDGET.newText{name="title", x=80, y=50,font=70,align='L'},
WIDGET.newButton{name="login", x=1140, y=100,w=170,h=80,color='lY',code=function()SCN.swapTo('login','swipeL')end},

View File

@@ -10,7 +10,7 @@ local function dumpCB(T)
)
)
)
LOG.print(text.exportSuccess)
LOG.print(text.exportSuccess,'message')
end
local function parseCB()
local _
@@ -18,9 +18,9 @@ local function parseCB()
--Decode
_,s=pcall(love.data.decode,'string','base64',s)
if not _ then LOG.print(text.dataCorrupted,COLOR.R)return end
if not _ then LOG.print(text.dataCorrupted,'error')return end
_,s=pcall(love.data.decompress,'string','zlib',s)
if not _ then LOG.print(text.dataCorrupted,COLOR.R)return end
if not _ then LOG.print(text.dataCorrupted,'error')return end
s=loadstring(s)
if s then

View File

@@ -76,7 +76,7 @@ function scene.touchUp()
end
end
function scene.touchMove(_,_,dx,dy)
if selected and not WIDGET.sel then
if selected and WIDGET.isFocus(false)then
local B=VK_org[selected]
B.x,B.y=B.x+dx,B.y+dy
end
@@ -84,8 +84,8 @@ end
function scene.draw()
gc.setColor(1,1,1)
gc.setLineWidth(7)gc.rectangle('line',340,15,600,690)
gc.setLineWidth(3)gc.rectangle('line',490,85,300,600)
gc.setLineWidth(3)
gc.rectangle('line',490,85,300,600)
VK.preview(selected)
if snapUnit>=10 then
gc.setLineWidth(3)
@@ -188,16 +188,13 @@ scene.widgetList={
B.x,B.y,B.r=T[2],T[3],T[4]
end
end
LOG.print(("[ %d ]"):format(defaultSetSelect))
LOG.print(("==[ %d ]=="):format(defaultSetSelect))
defaultSetSelect=defaultSetSelect%5+1
selected=false
end},
WIDGET.newSelector{name="snap", x=750,y=90,w=200,h=80,color='Y',list={1,10,20,40,60,80},disp=function()return snapUnit end,code=function(i)snapUnit=i end},
WIDGET.newButton{name="option", x=530,y=190,w=200,h=80,font=40,
code=function()
SCN.go('setting_touchSwitch')
end},
WIDGET.newButton{name="back", x=750,y=190,w=200,h=70,font=35,code=backScene},
WIDGET.newButton{name="option", x=530,y=190,w=200,h=80,font=40,code=function()SCN.go('setting_touchSwitch')end},
WIDGET.newButton{name="back", x=750,y=190,w=200,h=80,font=35,code=backScene},
WIDGET.newKey{name="save1", x=475,y=290,w=90,h=70,code=save1},
WIDGET.newKey{name="load1", x=585,y=290,w=90,h=70,code=load1},
WIDGET.newKey{name="save2", x=695,y=290,w=90,h=70,code=save2},
@@ -214,6 +211,7 @@ scene.widgetList={
hideF=function()
return not selected
end},
WIDGET.newKey{name="shape",x=640,y=600,w=200,h=80,code=function()SETTING.VKSkin=VK.nextShape()end},
}
return scene

View File

@@ -13,41 +13,42 @@ scene.widgetList={
WIDGET.newButton{name="sound", x=200,y=80,w=240,h=80,color='lC',font=35,code=swapScene("setting_sound",'swipeR')},
WIDGET.newButton{name="game", x=1080,y=80,w=240,h=80,color='lC',font=35,code=swapScene("setting_game",'swipeL')},
WIDGET.newSwitch{name="block", x=350,y=160,disp=SETval("block"),code=SETrev("block")},
WIDGET.newSwitch{name="smooth", x=350,y=210,disp=SETval("smooth"),code=SETrev("smooth")},
WIDGET.newSwitch{name="upEdge", x=350,y=260,disp=SETval("upEdge"),code=SETrev("upEdge")},
WIDGET.newSwitch{name="bagLine", x=350,y=310,disp=SETval("bagLine"),code=SETrev("bagLine")},
WIDGET.newSwitch{name="block", x=270,y=160,disp=SETval("block"),code=SETrev("block")},
WIDGET.newSwitch{name="smooth", x=270,y=210,disp=SETval("smooth"),code=SETrev("smooth")},
WIDGET.newSwitch{name="upEdge", x=270,y=260,disp=SETval("upEdge"),code=SETrev("upEdge")},
WIDGET.newSwitch{name="bagLine", x=270,y=310,disp=SETval("bagLine"),code=SETrev("bagLine")},
WIDGET.newSlider{name="ghost", x=700,y=180,w=380,unit=.6, disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
WIDGET.newSlider{name="grid", x=700,y=240,w=380,unit=.4, disp=SETval("grid"),show="percent", code=SETsto("grid")},
WIDGET.newSlider{name="center", x=700,y=300,w=380,unit=1, disp=SETval("center"), code=SETsto("center")},
WIDGET.newSlider{name="ghost", x=610,y=180,w=320,unit=.6, disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
WIDGET.newSlider{name="grid", x=610,y=240,w=320,unit=.4, disp=SETval("grid"),show="percent", code=SETsto("grid")},
WIDGET.newSlider{name="center", x=610,y=300,w=320,unit=1, disp=SETval("center"), code=SETsto("center")},
WIDGET.newSlider{name="lockFX", x=220,y=365,w=380,unit=5, disp=SETval("lockFX"), code=SETsto("lockFX")},
WIDGET.newSlider{name="dropFX", x=220,y=405,w=380,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
WIDGET.newSlider{name="moveFX", x=220,y=445,w=380,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
WIDGET.newSlider{name="clearFX", x=220,y=485,w=380,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
WIDGET.newSlider{name="splashFX", x=220,y=525,w=380,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
WIDGET.newSlider{name="shakeFX", x=220,y=565,w=380,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
WIDGET.newSlider{name="atkFX", x=220,y=605,w=380,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
WIDGET.newSelector{name="frame", x=410,y=660,w=360,list={8,10,13,17,22,29,37,47,62,80,100},disp=SETval("frameMul"),code=SETsto("frameMul")},
WIDGET.newSlider{name="dropFX", x=220,y=415,w=380,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
WIDGET.newSlider{name="moveFX", x=220,y=465,w=380,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
WIDGET.newSlider{name="clearFX", x=220,y=515,w=380,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
WIDGET.newSlider{name="splashFX", x=220,y=565,w=380,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
WIDGET.newSlider{name="shakeFX", x=220,y=615,w=380,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
WIDGET.newSlider{name="atkFX", x=220,y=665,w=380,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
WIDGET.newSelector{name="frame", x=830,y=640,w=360,list={8,10,13,17,22,29,37,47,62,80,100},disp=SETval("frameMul"),code=SETsto("frameMul")},
WIDGET.newSwitch{name="text", x=900,y=360,disp=SETval("text"), code=SETrev("text")},
WIDGET.newSwitch{name="score", x=900,y=410,disp=SETval("score"), code=SETrev("score")},
WIDGET.newSwitch{name="warn", x=900,y=460,disp=SETval('warn'), code=SETrev('warn')},
WIDGET.newSwitch{name="bufferWarn", x=900,y=510,disp=SETval('bufferWarn'), code=SETrev('bufferWarn')},
WIDGET.newSwitch{name="bufferWarn", x=900,y=460,disp=SETval('bufferWarn'), code=SETrev('bufferWarn')},
WIDGET.newSwitch{name="showSpike", x=900,y=510,disp=SETval('showSpike'), code=SETrev('showSpike')},
WIDGET.newSwitch{name="highCam", x=900,y=560,disp=SETval("highCam"), code=SETrev("highCam")},
WIDGET.newSwitch{name="nextPos", x=1180,y=360,disp=SETval("nextPos"), code=SETrev("nextPos")},
WIDGET.newSwitch{name="fullscreen", x=1180,y=410,disp=SETval("fullscreen"), code=switchFullscreen},
WIDGET.newSwitch{name="power", x=1180,y=460,disp=SETval("powerInfo"), code=SETrev("powerInfo")},
WIDGET.newSwitch{name="clickFX", x=1180,y=510,disp=SETval("clickFX"), code=SETrev("clickFX")},
WIDGET.newSwitch{name="bg", x=1180,y=560,disp=SETval("bg"),
WIDGET.newSwitch{name="nextPos", x=1180,y=260,disp=SETval("nextPos"), code=SETrev("nextPos")},
WIDGET.newSwitch{name="fullscreen", x=1180,y=310,disp=SETval("fullscreen"), code=switchFullscreen},
WIDGET.newSwitch{name="power", x=1180,y=360,disp=SETval("powerInfo"), code=SETrev("powerInfo")},
WIDGET.newSwitch{name="clickFX", x=1180,y=410,disp=SETval("clickFX"), code=SETrev("clickFX")},
WIDGET.newSwitch{name="bg", x=1180,y=460,disp=SETval("bg"),
code=function()
BG.set('none')
SETTING.bg=not SETTING.bg
BG.set()
end},
WIDGET.newSwitch{name="clean", x=990,y=640,font=35,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
WIDGET.newSwitch{name="clean", x=1180,y=510,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
WIDGET.newSwitch{name="warn", x=1180,y=560,disp=SETval("warn"), code=SETrev("warn")},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=40,code=backScene},
}

View File

@@ -12,17 +12,65 @@ return STRING.split([=[
Tetra-link; 速算(前缀后缀表达式,二八十六进制)
连连看; 求合体; 坦克大战; 扫雷; 接水管
其他未来内容:
详细开房界面; 自适应UI; 高级自定义序列; 对战结束后展示数据和排行
重做模式选择UI; MOD的UI; 可滚动控件模块(自定义/设置UI)
XRS; 移动n格+硬降复合操作键; 更好的手柄支持
自适应UI; 高级自定义序列; 对战结束后展示数据和排行
重做模式选择UI, MOD的UI, 自定义游戏UI
区分各种消除(隔断/架空/混合/彩色/穿墙)
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹/厚度)
可调场地宽度; 左右三按键; 手势操作; 特殊控件(虚拟摇杆等); 切换高低镜头键
DAS系统和Deepdrop系统更细节的选项; spike计数器; 攻击总缓冲显示
成就系统; 更强的主题系统; 多方块; 3D背景; TGM3的开局无限hold调整序列
工程编译到字节码; task-Z(新AI); 开房机制修改
等级系统; 旁观; 收集向抽奖玩法
录像回放菜单; 跳帧开关; 教学关; 超60帧; 热更新
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹/厚度)
DAS系统和Deepdrop系统更细节的选项
成就系统; 更强的主题系统; 3D背景
工程编译到字节码; task-Z(新AI)
等级系统; 收集向抽奖玩法; 教学关
录像回放菜单; 跳帧开关; 多方块; 超60帧; 热更新
0.15.1: 耀斑 Flare
新增:
允许开局跳过若干next时,倒计时数字颜色会略有不同
改动:
微调联网房间内准备前ui,修改键盘准备/观战快捷键
混战模式和联网对战允许开局跳块
优化爆发累计和缓冲预警的画面效果
优化开局倒计时画面效果
修复自定义-消除模式左侧信息显示问题
修复:
一处cc库相关的报错
[服务器]观战玩家会影响游戏结束判定
0.15.0: 超新星 Supernova
新增:
[双端]观战功能
spike计数器
全新房间列表ui
重新启用临界时间(基于帧)
新增虚拟按键形状设置
改动:
主菜单按钮行为更容易理解,添加连接音效和连接成功音效
移除next和hold栏上的文本
聊天窗交互更自然
词典添加游戏官网词条
修改默认空用户名
更新cc模块
代码:
升级控件模块
升级本地和服务器提供的房间数据格式
修复:
结算显示胜利者时可能报错
"游戏中"标记会被带到别的房间
命令行执行空白字符串报错
0.14.8: 冰激凌 Icecream
新增:
新增无尽pc挑战模式
联网对战游戏开始前可以显示其他玩家的连接状态
改动:
增加自定义游戏锁延刷新次数挡位
减少生存模式最高两个难度的锁延刷新次数
代码:
简化LOG模块用法
textBox控件在隐藏时也会自动滚动
修复:
聊天窗带空格的消息会被截断
0.14.7: 烈日 Burn
新增:
@@ -51,6 +99,7 @@ return STRING.split([=[
控制台支持滚轮和键盘导航
缩短联网ping间隔和自我认定掉线时间
调整rnd出块算法的一些细节
更新naki立绘
代码:
控件系统hide机制大改
场景模块支持拖拽文件(夹)事件

View File

@@ -13,7 +13,7 @@ local function loadAvatar(path)
end
local emptyUser={
username="Player",
username="_Stacker",
motto="",
hash="",
new=false,

View File

@@ -1,8 +1,34 @@
local gc=love.graphics
local gc_draw,gc_setColor,gc_setLineWidth=gc.draw,gc.setColor,gc.setLineWidth
local next=next
local SETTING,TIME=SETTING,TIME
local VK_org=VK_org
local skin=1
local r=10
local buttonImages={
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98},{'dCirc',100,100,90}},
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98,8},{'dCirc',100,100,90,8}},
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98,6},{'dCirc',100,100,90,6}},
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98,4},{'dCirc',100,100,89,4}},
DOGC{200,200,{'setLW',4},{'dRect',31,31,138,138},{'dRect',39,39,122,122}},
}
local rippleImages={
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98}},
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98,8}},
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98,6}},
DOGC{200,200,{'setLW',4},{'dCirc',100,100,98,4}},
DOGC{200,200,{'setLW',4},{'dRect',31,31,138,138}},
}
local holdImages={
DOGC{200,200,{'fCirc',100,100,86}},
DOGC{200,200,{'fCirc',100,100,86,8}},
DOGC{200,200,{'fCirc',100,100,85,6}},
DOGC{200,200,{'fCirc',100,100,83,4}},
DOGC{200,200,{'fRect',43,43,114,114}},
}
--Virtualkey icons
local VKIcon={}
gc.setDefaultFilter('nearest','nearest')
@@ -69,6 +95,14 @@ function VK.release(id)
keys[id].isDown=false
end
function VK.setShape(s)
skin=s
end
function VK.nextShape()
skin=skin%#buttonImages+1
return skin
end
function VK.switchKey(id,on)
keys[id].ava=on
end
@@ -100,47 +134,53 @@ function VK.update()
end
end
local gc_circle,gc_draw,gc_setColor,gc_setLineWidth=gc.circle,gc.draw,gc.setColor,gc.setLineWidth
function VK.draw()
if not SETTING.VKSwitch then return end
local a=SETTING.VKAlpha
local buttonImage=buttonImages[skin]
local rippleImage=rippleImages[skin]
local holdImage=holdImages[skin]
if SETTING.VKIcon then
for i,B in next,keys do
if B.ava then
local r=B.r
--Button outline
gc_setColor(1,1,1,a)
gc_setLineWidth(B.r*.07)
gc_circle('line',B.x,B.y,B.r,10)
gc_setLineWidth(r*.07)
gc_draw(buttonImage,B.x,B.y,nil,r*.01,nil,100,100)
--Icon
local _=B.pressTime
gc_setColor(1,1,1,a)
gc_draw(VKIcon[i],B.x,B.y,nil,B.r*.026+_*.08,nil,18,18)
gc_draw(VKIcon[i],B.x,B.y,nil,r*.024+_*.06,nil,18,18)
--Ripple
if _>0 then
gc_setColor(1,1,1,a*_*.08)
gc_circle('line',B.x,B.y,B.r*(1.4-_*.04),10)
local d=r*(1.4-_*.04)
gc_draw(rippleImage,B.x,B.y,nil,d*.01,nil,100,100)
end
--Glow when press
if B.isDown then
gc_setColor(1,1,1,a*.4)
gc_circle('fill',B.x,B.y,B.r*.94,10)
gc_draw(holdImage,B.x,B.y,nil,r*.01,nil,100,100)
end
end
end
else
for _,B in next,keys do
if B.ava then
local r=B.r
gc_setColor(1,1,1,a)
gc_setLineWidth(B.r*.07)
gc_circle('line',B.x,B.y,B.r,10)
gc_setLineWidth(r*.07)
gc_draw(buttonImage,B.x,B.y,nil,r*.01,nil,100,100)
local _=B.pressTime
if _>0 then
gc_setColor(1,1,1,a*_*.08)
gc_circle('fill',B.x,B.y,B.r*.94,10)
gc_circle('line',B.x,B.y,B.r*(1.4-_*.04),10)
gc_draw(holdImage,B.x,B.y,nil,r*.01,nil,100,100)
local d=r*(1.4-_*.04)
gc_draw(rippleImage,B.x,B.y,nil,d*.01,nil,100,100)
end
end
end
@@ -148,18 +188,21 @@ function VK.draw()
end
function VK.preview(selected)
if not SETTING.VKSwitch then return end
for id,B in next,VK_org do
local buttonImage=buttonImages[skin]
local holdImage=holdImages[skin]
for i,B in next,VK_org do
if B.ava then
local r=B.r
gc_setColor(1,1,1,SETTING.VKAlpha)
gc_setLineWidth(B.r*.07)
gc_circle('line',B.x,B.y,B.r,10)
if selected==id and TIME()%.26<.13 then
gc_setLineWidth(r*.07)
gc_draw(buttonImage,B.x,B.y,nil,r*.01,nil,100,100)
if selected==i and TIME()%.26<.13 then
gc_setColor(1,1,1,SETTING.VKAlpha*.62)
gc_circle('fill',B.x,B.y,B.r,10)
gc_draw(holdImage,B.x,B.y,nil,r*.01,nil,100,100)
end
if SETTING.VKIcon then
gc_setColor(1,1,1,SETTING.VKAlpha)
gc_draw(VKIcon[id],B.x,B.y,nil,B.r*.025,nil,18,18)
gc_draw(VKIcon[i],B.x,B.y,nil,r*.024,nil,18,18)
end
end
end