Compare commits

...

51 Commits

Author SHA1 Message Date
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
45 changed files with 769 additions and 528 deletions

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
@@ -214,7 +210,7 @@ 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")
@@ -224,8 +220,8 @@ local function noDevkeyPressed(key)
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
@@ -464,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},
@@ -626,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

@@ -10,33 +10,28 @@ return function(name,libName)
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",'message')
else
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("Cannot load "..name..": "..mes2,'error')
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 %s-%s to saving failed: %s"):format(name,platform[i],mes2),'error')
LOG.print("Cannot load "..name..": "..mes2,'error')
end
else
LOG.print(("Read %s-%s to saving failed: %s"):format(name,platform[i],mes1),'error')
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,'error')
return
end
end
if not libFunc then
LOG.print("Cannot load "..name,'error')
return
end
return libFunc()
else

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
@@ -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=1408,
string="Alpha V0.14.8",
name="冰激凌 Icecream",
code=1500,
short="V0.15.0",
string="Alpha V0.15.0",
name="超新星 Supernovas",
}
function love.conf(t)
t.identity='Techmino'--Saving folder

View File

@@ -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

@@ -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)
@@ -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=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",
"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可以在上面修改头像和个人信息",
"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",
@@ -107,10 +105,11 @@ return{
started="Playing",
joinRoom="has joined the room.",
leaveRoom="has left the room.",
ready="READY",
connStream="CONNECTING",
waitStream="WAITING",
ready="Ready",
connStream="Connecting",
waitStream="Waiting",
champion="$1 won",
spectating="Spectating",
chatRemain="Online",
chatStart="------Beginning of log------",
chatHistory="------New messages below------",
@@ -268,6 +267,7 @@ return{
},
net_game={
ready="Ready",
spectate="Spectate",
cancel="Cancel",
},
setting_game={
@@ -312,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",
@@ -321,6 +321,7 @@ return{
power="Power Info",
clickFX="Click FX",
bg="Background",
warn="Danger Alert",
clean="Fast Draw",
},
setting_sound={
@@ -388,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:",
@@ -793,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???",
@@ -813,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",
@@ -832,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!",
@@ -849,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?",
@@ -866,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",
@@ -111,6 +109,7 @@ return{
-- connStream="CONNECTING",
-- waitStream="WAITING",
champion="$1 a gagné",
-- spectating="Spectating",
chatRemain="En ligne : ",
chatStart="--------Début des logs--------",
chatHistory="-Nouveaux messages en dessous-",
@@ -238,6 +237,7 @@ return{
},
net_game={
-- ready="Ready",
-- spectate="Spectate",
-- cancel="Cancel",
},
setting_game={
@@ -284,7 +284,6 @@ return{
text="Texte d'action",
score="Pop-up de score",
warn="Alerte de danger",
-- bufferWarn="Buffer Alert",
highCam="Vue d'oiseau",
@@ -293,6 +292,7 @@ return{
power="Infos d'alimentation",
-- clickFX="Click FX",
bg="Arrière-plan",
warn="Alerte de danger",
-- clean="Fast Draw",
},
setting_sound={
@@ -358,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:",

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",
@@ -268,6 +266,7 @@ return{
},
net_game={
-- ready="Ready",
-- spectate="Spectate",
-- cancel="Cancel",
},
setting_game={
@@ -312,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.",
@@ -321,6 +320,7 @@ return{
power="Informação bateria",
-- clickFX="Click FX",
bg="Fundo",
warn="Alerta de perigo",
-- clean="Fast Draw",
},
setting_sound={
@@ -388,6 +388,7 @@ return{
-- save2="Save2",
-- load2="Load2",
size="Tamanho",
-- shape="Shape",
},
setting_touchSwitch={
b1= "Esquerda:", b2="Direita:", b3="Giro Dir.:", b4="Giro Esq.:",

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",
@@ -111,6 +109,7 @@ return{
-- connStream="CONNECTING",
-- waitStream="WAITING",
champion="$1 ganó!",
-- spectating="Spectating",
chatRemain="Usuarios en línea: ",
chatStart="------Comienzo del historial------",
chatHistory="------Nuevos mensajes------",
@@ -245,6 +244,7 @@ return{
},
net_game={
ready="Estoy Listo",
-- spectate="Spectate",
-- cancel="Cancel",
},
setting_game={
@@ -289,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.",
@@ -298,6 +298,7 @@ return{
power="Inf. de Batería",
-- clickFX="Click FX",
bg="Fondo",
warn="Alerta de Peligro",
clean="Fast Draw",
},
setting_sound={
@@ -361,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.:",

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="改声音",

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错误",
@@ -111,6 +109,7 @@ return{
connStream="正在连接",
waitStream="等待其他人连接",
champion="$1 获胜",
spectating="观战中",
chatRemain="人数:",
chatStart="------消息的开头------",
chatHistory="------以上是历史消息------",
@@ -268,6 +267,7 @@ return{
},
net_game={
ready="准备",
spectate="观战",
cancel="取消",
},
setting_game={
@@ -312,8 +312,8 @@ return{
text="消行文本",
score="分数动画",
warn="死亡预警",
bufferWarn="缓冲预警",
showSpike="爆发累计",
highCam="超屏视野",
nextPos="生成预览",
@@ -321,6 +321,7 @@ return{
power="电量显示",
clickFX="点按特效",
bg="背景",
warn="死亡预警",
clean="绘制优化",
},
setting_sound={
@@ -387,6 +388,7 @@ return{
save2="保存2",
load2="读取2",
size="大小",
shape="形状",
},
setting_touchSwitch={
b1= "左移:", b2="右移:", b3="顺时针旋转:", b4="逆时针旋转:",
@@ -807,10 +809,10 @@ return{
"3next 1hold?",
"40行世界纪录:15.654s by VinceHD",
"6236326236327175",
"626in1",
"6next 1hold!",
"6next 6hold?!",
"7宽三SZ架空捐了解一下",
"626in1",
"按钮风格进化史",
"把手机调到特殊的日期也许会发生什么",
"报时机器人:新的一天开始了",
@@ -818,7 +820,7 @@ return{
"本游戏不是产品,是作品(至少目前是,嗯…)",
"本游戏的一部分内容是国际合作的!",
"本游戏的B2B是气槽机制,和传统的开关机制不一样哦",
"本游戏内置了几个休(ying)闲(he)小游戏哦~入口就藏在这个菜单",
"本游戏内置了几个休(ying)闲(he)小游戏哦~",
"本游戏在设计的时候受到了大量其他块游甚至一些音游的启发",
"必须要软降才能到达的位置都会判定为极简操作",
"别看攻击效率不高,其实消四还是很强的",
@@ -843,7 +845,6 @@ return{
"低帧率会降低游戏体验",
"点击添加标题",
"点击添加副标题",
"点击退出按钮会有极小概率会…",
"电脑游玩自带按键显示~",
"对编程有真·兴趣推荐Lua,安装无脑 语法简单 执行速度快 远离枯燥学校编程(雾",
"对战游戏不是单机游戏,所以timing在对战里也非常重要!",
@@ -956,6 +957,8 @@ return{
"音乐使用beepbox制作",
"音游方块是一家(暴论",
"游戏使用love2d引擎制作",
"游戏使用un...love2d引擎制作",
"游戏也是一种艺术形式",
"游戏中左下角三个信息分别是分数/时间/极简连击数",
"有建议的话可以把信息反馈给作者~",
"有三个隐藏模式不能从地图进入,到处找找看吧",
@@ -966,7 +969,7 @@ return{
"众所周知俄罗斯方块是经典编程练手游戏(?",
"注意到方块\"旋转\"的时候到底发生了些什么吗?",
"自定义场地可以画图实现逐页演示",
"总共有300条tip哦",
"总共有将近400条tip哦",
"作者40行sub26了",
"作者电脑上装了10个方块",
"作者浏览器收藏夹里有6个方块",
@@ -1123,20 +1126,27 @@ return{
{C.dH,"3pps不是人均水平?"},
{C.dH,"40行还要40多秒,就这?"},
{C.dH,"别动不动大惊小怪,就你没见过"},
{C.dH,"别会个c4w就以为自己多强,基本功罢了。"},
{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,"设置都看过一遍了吗?明明都有还在那嫌弃,谁的问题?"},
@@ -1151,6 +1161,7 @@ return{
{C.dH,"隐形哪难了,你练了吗?没专门练几个小时就说难也太没耐心了吧"},
{C.dH,"有问题建议先找找是不是自己的问题,那么多人怎么就你事多?"},
{C.dH,"这不是休闲游戏…别怪关卡要求太高,就是你菜,请多练。"},
{C.dH,"这年头不会双旋还敢跟人打对战?"},
{C.dH,"Techmino没有抽卡没有氪金没有逼肝,良不良心自己没点数?"},
}
}

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

@@ -1,3 +1,4 @@
local yield=YIELD
return{
color=COLOR.white,
env={
@@ -6,13 +7,25 @@ return{
pushSpeed=5,
garbageSpeed=2,
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

@@ -8,21 +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,
waitingStream=false,
serverGaming=false,
streamRoomID=false,
UserCount="_",
PlayCount="_",
@@ -130,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
@@ -145,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
@@ -162,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
@@ -204,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(),
}
})
@@ -223,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={
@@ -254,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()
@@ -296,12 +311,15 @@ 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,'message')
end
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
@@ -392,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')
@@ -407,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
@@ -442,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')
@@ -484,17 +522,38 @@ function NET.updateWS_stream()
if res.type=='Connect'then
NET.unlock('wsc_stream')
NET.connectingStream=false
NET.waitingStream=true
netPLY.setConnect(USER.uid)
netPLY.freshStreamConn(res.data.connected)
elseif res.action==0 then--Game start
NET.waitingStream=false
if SCN.socketRead then SCN.socketRead('go',d)end
NET.roomInfo.start=true
SCN.socketRead('go')
elseif res.action==1 then--Game finished
--?
elseif res.action==2 then--Player join
netPLY.setConnect(d.uid)
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,7 @@ 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
@@ -99,23 +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,22 +127,10 @@ function netPLY.setReady(uid,ready)
end
end
end
function netPLY.setConnect(uid)
for _,p in next,PLY do
if p.uid==uid then
p.connected=true
return
end
end
end
function netPLY.freshStreamConn(list)
for _,p in next,list do
getPLY(p.uid).connected=true
end
end
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
@@ -179,7 +168,11 @@ function netPLY.draw()
local p=PLY[i]
gc.translate(p.x,p.y)
--Rectangle
gc.setColor(COLOR[p.connected and"N"or p.ready and'A'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)
@@ -199,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

@@ -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
@@ -312,14 +311,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 +332,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
@@ -455,11 +453,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 +481,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 +515,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 +632,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 +656,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 +668,22 @@ function draw.norm(P)
end
gc_setStencilTest()
end
--Spike
if ENV.showSpike and P.spikeTime>0 and P.spike>=10 then
local gb=10/P.spike
gc_setColor(1,gb,gb,min(P.spikeTime/30,.8))
mDraw(P.spikeText,150,100,nil,min(.3+(P.spike/26)*.4+P.spikeTime/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()

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

@@ -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

@@ -229,7 +229,6 @@ function scene.keyDown(key)
if DATA.pasteBoard(str,page)then
LOG.print(text.importSuccess,'message')
else
print(text.dataCorrupted)
LOG.print(text.dataCorrupted,'error')
end
elseif key=="pageup"then

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

@@ -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,21 +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()
LOG.print(text.wsConnecting,'message')
SFX.play('finesseError')
SFX.play('connect')
end
end
elseif key=="z"then
@@ -131,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,tc=love.graphics,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
@@ -52,9 +88,8 @@ function scene.touchUp(x,y)
VK.release(n)
end
end
function scene.touchMove(x,y)
if not playing then netPLY.mouseMove(x,y)return 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()
@@ -78,33 +113,27 @@ 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,'warn')
_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=STRING.trim(inputBox:getText())
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 not playing or noKey then return end
local k=keyMap.keyboard[key]
@@ -114,11 +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
_setReady()
else
_setCancel()
end
elseif key=="p"then
if netPLY.getSelfJoinMode()==0 then
_setSpectate()
end
elseif key=="s"then
_gotoSetting()
end
end
end
@@ -175,11 +210,10 @@ function scene.socketRead(cmd,d)
if not playing then
playing=true
love.keyboard.setKeyRepeat(false)
netPLY.resetState()
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]",'warn')
end
@@ -194,10 +228,11 @@ 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)
@@ -206,9 +241,11 @@ function scene.socketRead(cmd,d)
else
LOG.print("Bad stream from "..P.username.."#"..P.uid,30)
end
break
end
end
end
end
end
@@ -230,15 +267,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
@@ -260,6 +301,12 @@ 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()
@@ -267,24 +314,24 @@ function scene.draw()
--Ready & Set mark
setFont(50)
if NET.allReady then
gc.setColor(0,1,.5,.9)
gc_setColor(0,1,.5,.9)
mStr(text.ready,640,15)
elseif NET.connectingStream then
gc.setColor(.1,1,.8,.9)
gc_setColor(.1,1,.8,.9)
mStr(text.connStream,640,15)
elseif NET.waitingStream then
gc.setColor(0,.8,1,.9)
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 +343,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=950,y=630,w=190,h=80,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=1150,y=630,w=190,h=80,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=1050,y=630,w=390,h=80,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

@@ -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,9 +29,6 @@ local scene={}
function scene.sceneInit()
BG.set()
NET.allReady=false
NET.connectingStream=false
NET.waitingStream=false
scrollPos=0
selected=1
fetchRoom()
@@ -30,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
@@ -74,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",'message')
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)
@@ -129,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
@@ -181,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={

View File

@@ -17,10 +17,6 @@ local function register()
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

@@ -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)
@@ -193,11 +193,8 @@ scene.widgetList={
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,39 @@ return STRING.split([=[
Tetra-link; 速算(前缀后缀表达式,二八十六进制)
连连看; 求合体; 坦克大战; 扫雷; 接水管
其他未来内容:
详细开房界面; 自适应UI; 高级自定义序列; 对战结束后展示数据和排行
重做模式选择UI; MOD的UI; 可滚动控件模块(自定义/设置UI)
XRS; 移动n格+硬降复合操作键; 更好的手柄支持
自适应UI; 高级自定义序列; 对战结束后展示数据和排行
重做模式选择UI, MOD的UI, 自定义游戏UI
区分各种消除(隔断/架空/混合/彩色/穿墙)
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹/厚度)
可调场地宽度; 左右三按键; 手势操作; 特殊控件(虚拟摇杆等); 切换高低镜头键
DAS系统和Deepdrop系统更细节的选项; spike计数器
成就系统; 更强的主题系统; 多方块; 3D背景
工程编译到字节码; task-Z(新AI); 开房机制修改
等级系统; 旁观; 收集向抽奖玩法
录像回放菜单; 跳帧开关; 教学关; 超60帧; 热更新
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹/厚度)
DAS系统和Deepdrop系统更细节的选项
成就系统; 更强的主题系统; 3D背景
工程编译到字节码; task-Z(新AI)
等级系统; 收集向抽奖玩法; 教学关
录像回放菜单; 跳帧开关; 多方块; 超60帧; 热更新
0.15.0: 超新星 Supernova
新增:
[双端]观战功能
spike计数器
全新房间列表ui
重新启用临界时间(基于帧)
新增虚拟按键形状设置
改动:
主菜单按钮行为更容易理解,添加连接音效和连接成功音效
移除next和hold栏上的文本
聊天窗交互更自然
词典添加游戏官网词条
修改默认空用户名
更新cc模块
代码:
升级控件模块
升级本地和服务器提供的房间数据格式
修复:
结算显示胜利者时可能报错
"游戏中"标记会被带到别的房间
命令行执行空白字符串报错
0.14.8: 冰激凌 Icecream
新增:

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