Compare commits

...

61 Commits

Author SHA1 Message Date
MrZ626
076d854f11 微调文本框控件滚动条件,微调联网游戏按钮行为,微调控制台输出空行的时机 2021-06-25 23:41:06 +08:00
MrZ626
14852fa3e9 修改更新历史 2021-06-25 21:03:28 +08:00
MrZ626
42e2823e28 允许任何人开大房间,整理代码 2021-06-25 21:02:19 +08:00
MrZ626
535e78a8b3 移除无效的debug功能键,整理代码 2021-06-25 20:53:47 +08:00
MrZ626
c8480a17e9 整理代码,再次优化主菜单联网游戏按钮交互,连接过程中不允许切去其他场景 2021-06-25 20:20:55 +08:00
MrZ626
6989158216 修改更新历史 2021-06-25 16:32:12 +08:00
MrZ626
7fc3d13c99 升级几个控件的scroll和drag方法,按键响应逻辑更严谨 2021-06-25 16:31:42 +08:00
MrZ626
7ce56b8913 中文词典添加一个关于tspin学习门槛的词条 2021-06-25 15:19:12 +08:00
MrZ626
a0980138f9 所有mod都会让成绩无效,等待重做 close #90 2021-06-25 03:44:54 +08:00
MrZ626
16e01e510e 整理代码 2021-06-25 03:42:41 +08:00
MrZ626
ee628778cf 修复自定义模式进入消除模式后不再恢复正常无尽模式 close #91 2021-06-25 03:39:42 +08:00
MrZ626
36a30a6318 修改房间准备状态变量修改条件,减少出现问题状态的可能性 2021-06-24 14:26:14 +08:00
MrZ626
096f162ea6 修复WS模块可以在连接成功之前read出数据导致连接流程被打断 2021-06-24 12:54:58 +08:00
MrZ626
22c213b10f 整理代码,修复拼图模式胜利后文字不会消失 2021-06-24 11:29:17 +08:00
MrZ626
ba66610a01 修改build号和更新历史 2021-06-24 04:41:46 +08:00
MrZ626
ab4a055194 更易读的进房版本检测 2021-06-24 04:41:20 +08:00
MrZ626
2ce2f91414 新增误硬降打断延迟机制 2021-06-24 03:13:57 +08:00
MrZ626
0f1c8c7b2f 微调一点ui问题 2021-06-23 05:58:27 +08:00
MrZ626
8adcd4b8a9 修改build号和更新历史 2021-06-23 05:53:17 +08:00
MrZ626
db5a8594fd 移除20G极限难度400~500背景 close #86 2021-06-23 05:52:11 +08:00
MrZ626
5238d855b4 修复任务编辑(潜在)和序列编辑粘贴不当格式数据会有污染信息影响数据导致后续错误 closed #89 2021-06-23 05:49:55 +08:00
MrZ626
6c2cbe5f20 删除测试代码,升级textBox控件,改进listBox控件,整理代码 2021-06-23 05:49:54 +08:00
MrZ626
27ce516dd9 科研模式修改目标后评级代码未更新 2021-06-22 20:39:47 +08:00
MrZ626
981479ca5f hold被禁用时虚拟按键不消失 2021-06-22 20:39:19 +08:00
MrZ626
70a41855d1 控件更新时改回先刷新hide状态再选择是否update 2021-06-22 12:28:15 +08:00
MrZ626
3571ef404c 新增列表框控件,并用于房间列表,整理代码 2021-06-22 03:00:10 +08:00
MrZ626
86ee26381c 调整倒计时数字样式,微调颜色 2021-06-21 11:49:31 +08:00
MrZ626
198b18ec89 修复开启3d方块时消行特效也会有两个叠在一起 2021-06-21 10:06:18 +08:00
MrZ_26
18ff09befa Merge pull request #85 from 26F-Studio/user670-patch-20210618-readme
Make the readme Github/Gitee-compatible
2021-06-21 10:05:41 +08:00
MrZ626
bd48c266b8 修正tip中对魔方名字的错误拼写 close #88 2021-06-20 00:02:58 +08:00
MrZ626
cf410dfbdd 修改更新历史 2021-06-19 21:57:10 +08:00
MrZ626
4afac2a2fb 添加一位赞助者 2021-06-19 21:57:00 +08:00
MrZ626
d96f45c3b3 优化ws模块性能(函数local化) 2021-06-19 21:41:58 +08:00
MrZ626
e381f66767 整理代码,移除多余的保存成功提示 2021-06-19 20:46:23 +08:00
MrZ626
d0b9cdc503 修复修改ws机制之后不能完全断开导致重复连接 2021-06-19 20:27:06 +08:00
MrZ626
e846222ace 简化MES.traceback 2021-06-19 20:17:10 +08:00
MrZ626
b3e9b128b6 修复c4w模式一直响警报的问题 2021-06-19 20:15:24 +08:00
MrZ626
0708d05ec9 同时允许进入0.15.2/3/4版本的房间 2021-06-19 14:46:34 +08:00
MrZ626
f4eda19684 修改更新日志 2021-06-19 14:42:33 +08:00
MrZ626
b0c71e0f6c 文件保存或json编解码失败时会有代码位置指示消息 2021-06-19 14:24:21 +08:00
MrZ626
3b675ad8ed ws没有连接上时不再会向队列里push消息 2021-06-19 14:06:39 +08:00
MrZ626
4c95f6bfbc 文件保存时一般不再弹出保存成功的消息 2021-06-19 14:05:59 +08:00
MrZ626
98715e4579 修复ws被切断时消息解析错误 2021-06-19 13:07:30 +08:00
MrZ626
89af52b14b 修复1/30的概率死亡后濒死音效错误播放 2021-06-18 15:18:32 +08:00
user670
1b4c1b8d7f Make the readme Github/Gitee-compatible
- The formatted text replaced with a # heading
- removed other useless font tags
- Added https to the link so that it's clickable
2021-06-18 13:29:42 +08:00
MrZ626
aea6840263 整理代码 2021-06-18 13:10:16 +08:00
MrZ626
cc33d04f32 更新readme 2021-06-18 13:10:08 +08:00
MrZ626
e75ab93838 调整部分小程序说明和进入方法 2021-06-18 12:46:46 +08:00
scdhh
85f3cb4d19 Create README.md
有了,但似乎和没有一样(
2021-06-18 12:38:41 +08:00
MrZ626
dab880bc82 修复WS.update会往triggerChannel无条件一直push导致无意义消息数量过多 2021-06-18 10:34:10 +08:00
MrZ626
004bb0cfca 自定义游戏重置功能会重置场地/序列/任务了 2021-06-18 09:58:51 +08:00
MrZ626
ca0ca8fd98 修改更新历史和版本号,整理代码 2021-06-18 02:15:14 +08:00
MrZ626
660f027c01 房间列表ui升级,支持输入密码 2021-06-18 02:00:39 +08:00
MrZ626
a69648274c 修改自定义游戏默认背景和自定义房间默认bgm 2021-06-18 02:00:32 +08:00
MrZ626
eee820bc73 微调输入框边框样式,控件被隐藏时会自动失去焦点 2021-06-18 01:45:45 +08:00
MrZ626
4e9fbf6764 修正服务器传来警告/错误信息时弹出消息的奇怪格式 2021-06-17 23:16:55 +08:00
MrZ626
f78856c58e 自定义房间可以设置密码(暂时不可加入) 2021-06-17 22:35:15 +08:00
MrZ626
e5a3b6c6ac 控件模块/场景代码更好地响应系统长按 2021-06-17 22:17:35 +08:00
MrZ626
37a3e36bd5 DOGC模块不会创建超过系统限制大小的画布 2021-06-17 12:46:58 +08:00
MrZ626
99eeeb915a 小程序tap不再认为鼠标左右键为同一个键 2021-06-17 12:13:46 +08:00
MrZ626
00f6d46f71 简化更新历史 2021-06-16 21:19:50 +08:00
92 changed files with 1034 additions and 812 deletions

8
README.md Normal file
View File

@@ -0,0 +1,8 @@
# Techmino
《Techmino:方块研究所》
——Github & Gitee 官方仓库 Official Repository
集合各种现代方块规则,更多玩法,全新体验。
官网(建设中) https://home.techmino.org

View File

@@ -37,9 +37,10 @@ local cmds={
fArc=function(...)gc.arc('fill','open',...)end,
fBow=function(...)gc.arc('fill','closed',...)end,
}
local sizeLimit=gc.getSystemLimits().texturesize
return function(L)
gc.push()
local canvas=gc.newCanvas(L[1],L[2])
local canvas=gc.newCanvas(math.min(L[1],sizeLimit),math.min(L[2],sizeLimit))
gc.setCanvas(canvas)
gc.origin()
gc.setColor(1,1,1)

View File

@@ -48,14 +48,11 @@ function FILE.save(data,name,mode)
F:open'w'
local success,mes=F:write(data)
F:flush()F:close()
if success then
if not mode:find'q'then
MES.new('check',text.saveDone)
end
else
if not success then
MES.new('error',text.saveError..(mes or"unknown error"))
MES.new(false,debug.traceback())
MES.traceback()
end
return success
end
function FILE.clear(path)
if fs.getRealDirectory(path)~=SAVEDIR or fs.getInfo(path).type~='directory'then return end

View File

@@ -58,6 +58,7 @@ local ins,rem=table.insert,table.remove
local WIDGET,SCR,SCN=WIDGET,SCR,SCN
local xOy=SCR.xOy
local ITP=xOy.inverseTransformPoint
local mx,my,mouseShow=-20,-20,false
local touching--First touching ID(userdata)
@@ -117,7 +118,7 @@ local lastX,lastY=0,0--Last click pos
function love.mousepressed(x,y,k,touch)
if touch then return end
mouseShow=true
mx,my=xOy:inverseTransformPoint(x,y)
mx,my=ITP(xOy,x,y)
if devMode==1 then
print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format(
mx,my,
@@ -135,7 +136,7 @@ end
function love.mousemoved(x,y,dx,dy,touch)
if touch then return end
mouseShow=true
mx,my=xOy:inverseTransformPoint(x,y)
mx,my=ITP(xOy,x,y)
if SCN.swapping then return end
dx,dy=dx/SCR.k,dy/SCR.k
if SCN.mouseMove then SCN.mouseMove(mx,my,dx,dy)end
@@ -147,7 +148,7 @@ function love.mousemoved(x,y,dx,dy,touch)
end
function love.mousereleased(x,y,k,touch)
if touch or SCN.swapping then return end
mx,my=xOy:inverseTransformPoint(x,y)
mx,my=ITP(xOy,x,y)
WIDGET.release(mx,my)
if SCN.mouseUp then SCN.mouseUp(mx,my,k)end
if lastX and SCN.mouseClick and(mx-lastX)^2+(my-lastY)^2<62 then
@@ -172,14 +173,14 @@ function love.touchpressed(id,x,y)
WIDGET.unFocus(true)
love.touchmoved(id,x,y,0,0)
end
x,y=xOy:inverseTransformPoint(x,y)
x,y=ITP(xOy,x,y)
lastX,lastY=x,y
if SCN.touchDown then SCN.touchDown(x,y)end
if kb.hasTextInput()then kb.setTextInput(false)end
end
function love.touchmoved(_,x,y,dx,dy)
if SCN.swapping then return end
x,y=xOy:inverseTransformPoint(x,y)
x,y=ITP(xOy,x,y)
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end
WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k)
if touching then
@@ -189,7 +190,7 @@ function love.touchmoved(_,x,y,dx,dy)
end
function love.touchreleased(id,x,y)
if SCN.swapping then return end
x,y=xOy:inverseTransformPoint(x,y)
x,y=ITP(xOy,x,y)
if id==touching then
WIDGET.press(x,y,1)
WIDGET.release(x,y)
@@ -210,6 +211,8 @@ local function noDevkeyPressed(key)
elseif key=="f2"then
MES.new('info',("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s"):format(SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num))
elseif key=="f3"then
MES.new('error',"挂了")
elseif key=="f4"then
for _=1,8 do
local P=PLY_ALIVE[rnd(#PLY_ALIVE)]
if P~=PLAYERS[1]then
@@ -217,10 +220,8 @@ local function noDevkeyPressed(key)
P:lose()
end
end
elseif key=="f4"and not kb.isDown("lalt","ralt")then
MES.new.copy()
elseif key=="f5"then
print(WIDGET.isFocus()or"no widget selected")
print(WIDGET.getSel()or"no widget selected")
elseif key=="f6"then
for k,v in next,_G do print(k,v)end
elseif key=="f7"and love._openConsole then
@@ -257,7 +258,7 @@ local function noDevkeyPressed(key)
return true
end
end
function love.keypressed(key)
function love.keypressed(key,_,isRep)
mouseShow=false
if devMode and not noDevkeyPressed(key)then
return
@@ -272,11 +273,13 @@ function love.keypressed(key)
end
elseif not SCN.swapping then
if SCN.keyDown then
if #EDITING==0 then SCN.keyDown(key)end
elseif key=="escape"then
if EDITING==""then
SCN.keyDown(key,isRep)
end
elseif key=="escape"and not isRep then
SCN.back()
else
WIDGET.keyPressed(key)
WIDGET.keyPressed(key,isRep)
end
end
end

View File

@@ -118,8 +118,8 @@ function json.encode(val)
local a,b=pcall(encode,val)
if a then
return b
elseif MES.new then
MES.new('error',text.jsonError..": "..(b or"uknErr"))
elseif MES then
MES.traceback()
end
end
@@ -348,8 +348,8 @@ function json.decode(str)
local a,b=pcall(decode,str)
if a then
return b
elseif MES.new then
MES.new('error',text.jsonError..": "..(b or"uknErr"))
elseif MES then
MES.traceback()
end
end
return json

View File

@@ -63,7 +63,7 @@ function MES.new(icon,str,time)
if type(icon)=='string'then icon=mesIcon[icon]end
local t=gc.newText(getFont(30),str)
local w=math.max(t:getWidth()+(icon and 45 or 5),200)+20
local h=math.max(t:getHeight(),46)
local h=math.max(t:getHeight(),46)+3
local L={w,h,
{'clear',.5,.5,.5,.7},
{'setCL',.7,.7,.7},
@@ -114,4 +114,17 @@ function MES.draw()
end
gc_pop()
end
function MES.traceback()
local mes=
debug.traceback("",1)
:gsub(": in function",", in")
:gsub(":"," ")
:gsub("\t","")
MES.new('error',mes:sub(
mes:find("\n",2)+1,
mes:find("\n%[C%], in 'xpcall'")
),5)
end
return MES

View File

@@ -13,8 +13,8 @@ local SCR={
--Screen transformation objects
origin=love.math.newTransform(),
xOy_m=love.math.newTransform(),
xOy=love.math.newTransform(),
xOy_m=love.math.newTransform(),
xOy_ul=love.math.newTransform(),
xOy_u=love.math.newTransform(),
xOy_ur=love.math.newTransform(),

View File

@@ -15,20 +15,22 @@ local wsThread=[[
local triggerCHN,sendCHN,readCHN,threadName=...
local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount
local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop
local SOCK=require"socket".tcp()
local JSON=require"Zframework.json"
do--Connect
local host=sendCHN:demand()
local port=sendCHN:demand()
local path=sendCHN:demand()
local body=sendCHN:demand()
local timeout=sendCHN:demand()
local host=CHN_demand(sendCHN)
local port=CHN_demand(sendCHN)
local path=CHN_demand(sendCHN)
local body=CHN_demand(sendCHN)
local timeout=CHN_demand(sendCHN)
SOCK:settimeout(timeout)
local res,err=SOCK:connect(host,port)
if err then readCHN:push(err)return end
if err then CHN_push(readCHN,err)return end
--WebSocket handshake
if not body then body=""end
@@ -46,7 +48,7 @@ do--Connect
--First line of HTTP
res,err=SOCK:receive("*l")
if not res then readCHN:push(err)return end
if not res then CHN_push(readCHN,err)return end
local code,ctLen
code=res:find(" ")
code=res:sub(code+1,code+3)
@@ -54,7 +56,7 @@ do--Connect
--Get body length from headers and remove headers
repeat
res,err=SOCK:receive("*l")
if not res then readCHN:push(err)return end
if not res then CHN_push(readCHN,err)return end
if not ctLen and res:find("length")then
ctLen=tonumber(res:match("%d+"))
end
@@ -63,14 +65,14 @@ do--Connect
--Result
if ctLen then
if code=="101"then
readCHN:push('success')
CHN_push(readCHN,'success')
else
res,err=SOCK:receive(ctLen)
if not res then
readCHN:push(err)
CHN_push(readCHN,err)
else
res=JSON.decode(res)
readCHN:push((code or"XXX")..":"..(res and res.reason or"Server Error"))
CHN_push(readCHN,(code or"XXX")..":"..(res and res.reason or"Server Error"))
end
return
end
@@ -125,11 +127,12 @@ local lBuffer=""--Long multi-data buffer
local UFF--Un-finished-frame mode
local sBuffer=""--Short multi-frame buffer
while true do--Running
CHN_demand(triggerCHN)
--Send
triggerCHN:demand()
while sendCHN:getCount()>=2 do
local op=sendCHN:pop()
local message=sendCHN:pop()
while CHN_getCount(sendCHN)>=2 do
local op=CHN_pop(sendCHN)
local message=CHN_pop(sendCHN)
_send(op,message)
end
@@ -190,27 +193,27 @@ while true do--Running
--React
if op==8 then--8=close
readCHN:push(op)
CHN_push(readCHN,op)
SOCK:close()
if type(res)=='string'then
readCHN:push(res:sub(3))--Warning: with 2 bytes close code
CHN_push(readCHN,res:sub(3))--Warning: with 2 bytes close code
else
readCHN:push("WS Error")
CHN_push(readCHN,"WS Error")
end
elseif op==0 then--0=continue
lBuffer=lBuffer..res
if fin then
]]..(debugMode:find'M'and""or"--")..[[print("FIN=1 (c")
readCHN:push(lBuffer)
CHN_push(readCHN,lBuffer)
lBuffer=""
else
]]..(debugMode:find'M'and""or"--")..[[print("FIN=0 (c")
end
else
readCHN:push(op)
CHN_push(readCHN,op)
if fin then
]]..(debugMode:find'M'and""or"--")..[[print("OP: "..op.."\tFIN=1")
readCHN:push(res)
CHN_push(readCHN,res)
else
]]..(debugMode:find'M'and""or"--")..[[print("OP: "..op.."\tFIN=0")
sBuffer=res
@@ -222,6 +225,9 @@ end
]]
local timer=love.timer.getTime
local CHN=love.thread.newChannel()
local CHN_getCount,CHN_push,CHN_pop=CHN.getCount,CHN.push,CHN.pop
local WS={}
local wsList=setmetatable({},{
__index=function(l,k)
@@ -264,11 +270,11 @@ function WS.connect(name,subPath,body,timeout)
}
wsList[name]=ws
ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN,name)
ws.sendCHN:push(host)
ws.sendCHN:push(port)
ws.sendCHN:push(path..subPath)
ws.sendCHN:push(body or"")
ws.sendCHN:push(timeout or 2.6)
CHN_push(ws.sendCHN,host)
CHN_push(ws.sendCHN,port)
CHN_push(ws.sendCHN,path..subPath)
CHN_push(ws.sendCHN,body or"")
CHN_push(ws.sendCHN,timeout or 2.6)
end
function WS.status(name)
@@ -309,9 +315,9 @@ local OPname={
}
function WS.send(name,message,op)
local ws=wsList[name]
if ws.real then
ws.sendCHN:push(op and OPcode[op]or 2)--2=binary
ws.sendCHN:push(message)
if ws.real and ws.status=='running'then
CHN_push(ws.sendCHN,op and OPcode[op]or 2)--2=binary
CHN_push(ws.sendCHN,message)
ws.lastPingTime=timer()
ws.sendTimer=1
end
@@ -319,8 +325,8 @@ end
function WS.read(name)
local ws=wsList[name]
if ws.real and ws.readCHN:getCount()>=2 then
local op,message=ws.readCHN:pop(),ws.readCHN:pop()
if ws.real and ws.status~='connecting'and CHN_getCount(ws.readCHN)>=2 then
local op,message=CHN_pop(ws.readCHN),CHN_pop(ws.readCHN)
if op==8 then ws.status='dead'end--8=close
ws.lastPongTime=timer()
ws.pongTimer=1
@@ -331,8 +337,8 @@ end
function WS.close(name)
local ws=wsList[name]
if ws.real then
ws.sendCHN:push(8)--close
ws.sendCHN:push("")
CHN_push(ws.sendCHN,8)--close
CHN_push(ws.sendCHN,"")
ws.status='dead'
end
end
@@ -341,9 +347,11 @@ function WS.update(dt)
local time=timer()
for name,ws in next,wsList do
if ws.real then
ws.triggerCHN:push(0)
if CHN_getCount(ws.triggerCHN)==0 then
CHN_push(ws.triggerCHN,0)
end
if ws.status=='connecting'then
local mes=ws.readCHN:pop()
local mes=CHN_pop(ws.readCHN)
if mes then
if mes=='success'then
ws.status='running'
@@ -357,8 +365,8 @@ function WS.update(dt)
end
elseif ws.status=='running'then
if time-ws.lastPingTime>ws.pingInterval then
ws.sendCHN:push(9)
ws.sendCHN:push("")--ping
CHN_push(ws.sendCHN,9)
CHN_push(ws.sendCHN,"")--ping
ws.lastPingTime=time
end
if time-ws.lastPongTime>6+2*ws.pingInterval then

View File

@@ -1,6 +1,8 @@
local gc=love.graphics
local gc_clear,gc_origin=gc.clear,gc.origin
local gc_origin=gc.origin
local gc_translate,gc_replaceTransform=gc.translate,gc.replaceTransform
local gc_stencil,gc_setStencilTest=gc.stencil,gc.setStencilTest
local gc_push,gc_pop=gc.push,gc.pop
local gc_setCanvas,gc_setBlendMode=gc.setCanvas,gc.setBlendMode
local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth
local gc_draw,gc_line=gc.draw,gc.line
@@ -10,7 +12,7 @@ local gc_print,gc_printf=gc.print,gc.printf
local kb=love.keyboard
local next=next
local int,abs=math.floor,math.abs
local int,ceil,abs=math.floor,math.ceil,math.abs
local max,min=math.max,math.min
local sub,ins=string.sub,table.insert
local getFont,setFont,mStr=getFont,setFont,mStr
@@ -37,6 +39,11 @@ local largerThen=DOGC{20,20,
{'line',2,2,19,10,2,18},
}
local STW,STH--stencil-wid/hei
local function rectangleStencil()
gc.rectangle('fill',1,1,STW-2,STH-2)
end
local WIDGET={}
local widgetMetatable={
__tostring=function(self)
@@ -539,10 +546,10 @@ function slider:release(x)
self:drag(x)
self.lastTime=0
end
function slider:arrowKey(isLeft)
function slider:scroll(n)
local p=self.disp()
local u=(self.smooth and .01 or 1)
local P=isLeft and max(p-u,0)or min(p+u,self.unit)
local u=self.smooth and .01 or 1
local P=n==-1 and max(p-u,0)or min(p+u,self.unit)
if p==P or not P then return end
self.code(P)
if self.change and TIME()-self.lastTime>.18 then
@@ -550,6 +557,9 @@ function slider:arrowKey(isLeft)
self.change()
end
end
function slider:arrowKey(k)
self:scroll(k=="left"or k=="up"and -1 or 1)
end
function WIDGET.newSlider(D)--name,x,y,w[,fText][,color][,unit][,smooth][,font=30][,change],disp,code,hide
local _={
name= D.name or"_",
@@ -701,10 +711,10 @@ function selector:press(x)
end
end
end
function selector:arrowKey(isLeft)
function selector:scroll(n)
local s=self.select
if isLeft and s==1 or not isLeft and s==#self.list then return end
if isLeft then
if n==-1 and s==1 or not n and s==#self.list then return end
if n==-1 then
s=s-1
SYSFX.newShade(3,self.x,self.y-WIDGET.scrollPos,self.w*.5,60)
else
@@ -716,6 +726,10 @@ function selector:arrowKey(isLeft)
self.selText=self.list[s]
if self.sound then SFX.play('prerotate')end
end
function selector:arrowKey(k)
self:scroll(k=="left"or k=="up"and -1 or 1)
end
function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp,code,hide
local _={
name= D.name or"_",
@@ -799,11 +813,11 @@ function inputBox:draw()
local x,y,w,h=self.x,self.y,self.w,self.h
local ATV=self.ATV
gc_setColor(1,1,1,ATV*.1)
gc_setColor(1,1,1,ATV*.08)
gc_rectangle('fill',x,y,w,h)
gc_setColor(1,1,1)
gc_setLineWidth(4)
gc_setLineWidth(3)
gc_rectangle('line',x,y,w,h)
--Drawable
@@ -877,18 +891,20 @@ end
local textBox={
type='textBox',
scrollPos=0,--Which line display at bottom
scrollPix=0,--Hidden wheel move value
scrollPos=0,--Scroll-down-distance
sure=0,--Sure-timer for clear history
new=false,--If there is a new message
-- texts={},
}
function textBox:reset()
--haha nothing here, but techmino is fun!
--haha nothing here, techmino is so fun!
end
function textBox:setTexts(t)
self.texts=t
self.scrollPos=min(#self.texts,self.capacity)
self.scrollPos=0
end
function textBox:clear()
self.texts={}
self.scrollPos=0
SFX.play('fall')
end
function textBox:isAbove(x,y)
return
@@ -907,10 +923,8 @@ function textBox:update()
end
function textBox:push(t)
ins(self.texts,t)
if self.scrollPos==#self.texts-1 then
self.scrollPos=#self.texts
else
self.new=true
if self.scrollPos==(#self.texts-1-self.capacity)*self.lineH then--minus 1 for the new message
self.scrollPos=min(self.scrollPos+self.lineH,(#self.texts-self.capacity)*self.lineH)
end
end
function textBox:press(x,y)
@@ -919,7 +933,6 @@ function textBox:press(x,y)
if not self.fix and x>self.x+self.w-40 and y<self.y+40 then
if self.sure>0 then
self:clear()
self.new=false
self.sure=0
else
self.sure=60
@@ -927,73 +940,72 @@ function textBox:press(x,y)
end
end
function textBox:drag(_,_,_,dy)
_=self.scrollPix+dy
local sign=_>0 and 1 or -1
while abs(_)>30 do
_=_-30*sign
self:scroll(-sign)
end
self.scrollPix=_
self.scrollPos=max(0,min(self.scrollPos-dy,(#self.texts-self.capacity)*self.lineH))
end
function textBox:scroll(n)
if n<0 then
self.scrollPos=max(self.scrollPos+n,min(#self.texts,self.capacity))
else
self.scrollPos=min(self.scrollPos+n,#self.texts)
function textBox:scroll(dir)
if type(dir)=='string'then
if dir=="up"then
dir=-1
elseif dir=="down"then
dir=1
else
return
end
end
self:drag(nil,nil,nil,-dir*self.lineH)
end
function textBox:clear()
self.texts={}
self.scrollPos=0
self.new=false
SFX.play('fall')
function textBox:arrowKey(k)
if k=="up"then
self:scroll(-1)
elseif k=="down"then
self:scroll(-1)
end
end
function textBox:draw()
local x,y,w,h=self.x,self.y,self.w,self.h
local texts=self.texts
local scroll=self.scrollPos
local scrollPos=self.scrollPos
local cap=self.capacity
--Update new message status, necessary when hide==true
if self.scrollPos==#self.texts then
self.new=false
end
local lineH=self.lineH
--Background
gc_setColor(0,0,0,.4)
gc_rectangle('fill',x,y,w,h)
--Frame
gc_setLineWidth(4)
gc_setColor(1,1,WIDGET.sel==self and .8 or 1)
gc_setLineWidth(3)
gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z)
gc_rectangle('line',x,y,w,h)
--Slider
if #texts>cap then
gc_setLineWidth(2)
gc_rectangle('line',x-25,y,20,h)
local len=max(h*cap/#texts,26)
gc_rectangle('fill',x-22,y+(h-len-6)*(scroll-cap)/(#texts-cap)+3,14,len)
end
--Clear button
gc_setColor(1,1,1)
if not self.fix then
gc_rectangle('line',x+w-40,y,40,40)
gc_draw(self.sure==0 and clearIcon or sureIcon,x+w-40,y)
end
--Texts
setFont(self.font)
for i=max(scroll-cap+1,1),scroll do
gc_printf(texts[i],x+8,y+h-10-self.lineH*(scroll-i+1),w)
end
gc_push('transform')
gc_translate(x,y)
--New message
if self.new and self.scrollPos~=#texts then
gc_setColor(1,TIME()%.4<.2 and 1 or 0,0)
gc_print("v",x+w-25,y+h-40)
end
--Slider
gc_setColor(1,1,1)
if #texts>cap then
local len=h*h/(#texts*lineH)
gc_rectangle('fill',-15,(h-len)*scrollPos/((#texts-cap)*lineH),12,len)
end
--Clear button
if not self.fix then
gc_rectangle('line',w-40,0,40,40)
gc_draw(self.sure==0 and clearIcon or sureIcon,w-40,0)
end
gc_setStencilTest('equal',1)
STW,STH=w,h
gc_stencil(rectangleStencil)
gc_translate(0,-(scrollPos%lineH))
local pos=int(scrollPos/lineH)
for i=pos+1,min(pos+cap+1,#texts)do
gc_printf(texts[i],10,4,w-16)
gc_translate(0,lineH)
end
gc_setStencilTest()
gc_pop()
end
function textBox:getInfo()
return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h)
@@ -1026,13 +1038,156 @@ function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,lineH][,fix],hide
hide= D.hide,
}
_.lineH=D.lineH or _.font*7/5
_.capacity=int((D.h-10)/_.lineH)
_.capacity=ceil((D.h-10)/_.lineH)
for k,v in next,textBox do _[k]=v end
setmetatable(_,widgetMetatable)
return _
end
local listBox={
type='listBox',
keepFocus=true,
scrollPos=0,--Scroll-down-distance
selected=0,--Hidden wheel move value
}
function listBox:reset()
--haha nothing here too, techmino is really fun!
end
function listBox:clear()
self.list={}
self.scrollPos=0
end
function listBox:setList(t)
self.list=t
self.selected=1
self.scrollPos=0
end
function listBox:getList()
return self.list
end
function listBox:getLen()
return #self.list
end
function listBox:getSel()
return self.list[self.selected]
end
function listBox:isAbove(x,y)
return
x>self.x and
y>self.y and
x<self.x+self.w and
y<self.y+self.h
end
function listBox:getCenter()
return self.x+self.w*.5,self.y+self.h*.5
end
function listBox:push(t)
ins(self.list,t)
end
function listBox:press(x,y)
x,y=x-self.x,y-self.y
if not(x and y and x>0 and y>0 and x<=self.w and y<=self.h)then return end
self:drag(nil,nil,nil,0)
y=int((y+self.scrollPos)/self.lineH)+1
if self.list[y]then
if self.selected~=y then
self.selected=y
SFX.play('click',.4)
end
end
end
function listBox:drag(_,_,_,dy)
self.scrollPos=max(0,min(self.scrollPos-dy,(#self.list-self.capacity)*self.lineH))
end
function listBox:scroll(n)
self:drag(nil,nil,nil,-n*self.lineH)
end
function listBox:arrowKey(dir)
if dir=="up"then
self.selected=max(self.selected-1,1)
if self.selected<int(self.scrollPos/self.lineH)+2 then
self:drag(nil,nil,nil,self.lineH)
end
elseif dir=="down"then
self.selected=min(self.selected+1,#self.list)
if self.selected>int(self.scrollPos/self.lineH)+self.capacity-1 then
self:drag(nil,nil,nil,-self.lineH)
end
end
end
function listBox:draw()
local x,y,w,h=self.x,self.y,self.w,self.h
local list=self.list
local scrollPos=self.scrollPos
local cap=self.capacity
local lineH=self.lineH
gc_push('transform')
gc_translate(x,y)
--Frame
gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z)
gc_setLineWidth(3)
gc_rectangle('line',0,0,w,h)
--Slider
if #list>cap then
gc_setColor(1,1,1)
local len=h*h/(#list*lineH)
gc_rectangle('fill',-15,(h-len)*scrollPos/((#list-cap)*lineH),12,len)
end
--List
gc_setStencilTest('equal',1)
STW,STH=w,h
gc_stencil(rectangleStencil)
local pos=int(scrollPos/lineH)
gc_translate(0,-(scrollPos%lineH))
for i=pos+1,min(pos+cap+1,#list)do
self.drawF(i==self.selected,i,list[i])
gc_translate(0,lineH)
end
gc_setStencilTest()
gc_pop()
end
function listBox:getInfo()
return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h)
end
function WIDGET.newListBox(D)--name,x,y,w,h[,lineH],hide,drawF
local _={
name= D.name or"_",
resCtr={
D.x+D.w*.5,D.y+D.h*.5,
D.x+D.w*.5,D.y,
D.x-D.w*.5,D.y,
D.x,D.y+D.h*.5,
D.x,D.y-D.h*.5,
D.x,D.y,
D.x+D.w,D.y,
D.x,D.y+D.h,
D.x+D.w,D.y+D.h,
},
x= D.x,
y= D.y,
w= D.w,
h= D.h,
list= {},
lineH= D.lineH,
capacity=ceil(D.h/D.lineH),
drawF= D.drawF,
hideF= D.hideF,
hide= D.hide,
}
for k,v in next,listBox do _[k]=v end
setmetatable(_,widgetMetatable)
return _
end
WIDGET.active={}--Table contains all active widgets
WIDGET.scrollHeight=0--Max drag height, not actual container height!
WIDGET.scrollPos=0--Current scroll position
@@ -1088,8 +1243,15 @@ function WIDGET.setLang(widgetText)
end
end
end
function WIDGET.getSelected()
return WIDGET.sel
end
function WIDGET.isFocus(W)
return W==nil and WIDGET.sel or WIDGET.sel==W
if W then
return W and WIDGET.sel==W
else
return WIDGET.sel~=false
end
end
function WIDGET.focus(W)
if WIDGET.sel==W then return end
@@ -1135,7 +1297,7 @@ end
function WIDGET.drag(x,y,dx,dy)
if WIDGET.sel then
local W=WIDGET.sel
if W.type=='slider'or W.type=='textBox'then
if W.drag then
W:drag(x,y+WIDGET.scrollPos,dx,dy)
elseif not W:isAbove(x,y)then
WIDGET.unFocus(true)
@@ -1146,19 +1308,19 @@ function WIDGET.drag(x,y,dx,dy)
end
function WIDGET.release(x,y)
local W=WIDGET.sel
if W and W.type=='slider'then
if W and W.release then
W:release(x,y+WIDGET.scrollPos)
end
end
function WIDGET.keyPressed(k)
function WIDGET.keyPressed(k,isRep)
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
if W and W.type=='slider'or W.type=='selector'then
W:arrowKey(k=="left")
if not isRep then
WIDGET.press()
end
elseif kb.isDown("lshift","lalt","lctrl")then
--Control some widgets with arrowkeys when hold shift/ctrl/alt
if W and W.arrowKey then W:arrowKey(k)end
elseif k=="up"or k=="down"or k=="left"or k=="right"then
if not W then
for _,w in next,WIDGET.active do
@@ -1167,37 +1329,36 @@ function WIDGET.keyPressed(k)
return
end
end
return
end
if not W.getCenter then return end
local WX,WY=W:getCenter()
local dir=(k=="right"or k=="down")and 1 or -1
local tar
local minDist=1e99
local swap_xy=k=="up"or k=="down"
if swap_xy then WX,WY=WY,WX end -- note that we do not swap them back later
for _,W1 in ipairs(WIDGET.active)do
if W~=W1 and W1.resCtr and not W1.hide then
local L=W1.resCtr
for j=1,#L,2 do
local x,y=L[j],L[j+1]
if swap_xy then x,y=y,x end -- note that we do not swap them back later
local dist=(x-WX)*dir
if dist>10 then
dist=dist+abs(y-WY)*6.26
if dist<minDist then
minDist=dist
tar=W1
elseif W.getCenter then
local WX,WY=W:getCenter()
local dir=(k=="right"or k=="down")and 1 or -1
local tar
local minDist=1e99
local swap_xy=k=="up"or k=="down"
if swap_xy then WX,WY=WY,WX end -- note that we do not swap them back later
for _,W1 in ipairs(WIDGET.active)do
if W~=W1 and W1.resCtr and not W1.hide then
local L=W1.resCtr
for j=1,#L,2 do
local x,y=L[j],L[j+1]
if swap_xy then x,y=y,x end -- note that we do not swap them back later
local dist=(x-WX)*dir
if dist>10 then
dist=dist+abs(y-WY)*6.26
if dist<minDist then
minDist=dist
tar=W1
end
end
end
end
end
end
if tar then
WIDGET.focus(tar)
if tar then
WIDGET.focus(tar)
end
end
else
if W and W.type=='inputBox'then
if W and W.keypress then
W:keypress(k)
end
end
@@ -1247,7 +1408,12 @@ end
function WIDGET.update()
for _,W in next,WIDGET.active do
if W.hideF then W.hide=W.hideF()end
if W.hideF then
W.hide=W.hideF()
if W.hide and W==WIDGET.sel then
WIDGET.unFocus(true)
end
end
if W.update then W:update()end
end
end
@@ -1267,8 +1433,7 @@ function WIDGET.resize(w,h)
widgetCanvas=gc.newCanvas(w,h)
end
function WIDGET.draw()
gc_setCanvas(widgetCanvas)
gc_clear(0,0,0,0)
gc_setCanvas({stencil=true},widgetCanvas)
gc_translate(0,-WIDGET.scrollPos)
for _,W in next,WIDGET.active do
if not W.hide then W:draw()end
@@ -1285,7 +1450,7 @@ function WIDGET.draw()
gc_setBlendMode('multiply','premultiplied')
gc_draw(widgetCover,nil,nil,nil,scr_w,scr_h/360)
end
gc_setCanvas()
gc_setCanvas({stencil=false})
gc_setBlendMode('alpha','premultiplied')
gc_draw(widgetCanvas)
gc_setBlendMode('alpha')

View File

@@ -1,9 +1,9 @@
VERSION={
build=335,
code=1503,
short="V0.15.3",
string="Alpha V0.15.3",
name="卫星 Satellite",
build=338,
code=1504,
short="V0.15.4",
string="Alpha V0.15.4",
name="近地轨道 Low Earth Orbit",
}
function love.conf(t)
t.identity='Techmino'--Saving folder

View File

@@ -289,9 +289,9 @@ do
end
if needSave then
FILE.save(SETTING,'conf/settings','q')
FILE.save(RANKS,'conf/unlock','q')
FILE.save(STAT,'conf/data','q')
FILE.save(SETTING,'conf/settings')
FILE.save(RANKS,'conf/unlock')
FILE.save(STAT,'conf/data')
end
if autoRestart then
love.event.quit('restart')

BIN
media/SFX/drop_cancel.ogg Normal file

Binary file not shown.

View File

@@ -187,7 +187,7 @@ function DATA.copyMission()
end
function DATA.pasteMission(str)
local b
local mission={}
TABLE.cut(MISSION)
local reg
for i=1,#str do
b=byte(str,i)
@@ -200,24 +200,23 @@ function DATA.pasteMission(str)
else
if b>=34 and b<=114 then
if missionEnum[reg]then
ins(mission,reg)
ins(MISSION,reg)
reg=b-33
else
TABLE.cut(MISSION)
return
end
elseif b>=115 and b<=126 then
for _=1,b-113 do
ins(mission,reg)
ins(MISSION,reg)
end
reg=false
end
end
end
if reg then
ins(mission,reg)
ins(MISSION,reg)
end
MISSION=mission
return true
end

View File

@@ -275,7 +275,7 @@ function gameOver()--Save record
end
end
if needSave then
FILE.save(RANKS,'conf/unlock','q')
FILE.save(RANKS,'conf/unlock')
end
end
local D=M.score(P)
@@ -294,7 +294,7 @@ function gameOver()--Save record
D.date=os.date("%Y/%m/%d %H:%M")
ins(L,p+1,D)
if L[11]then L[11]=nil end
FILE.save(L,('record/%s.rec'):format(M.name),'lq')
FILE.save(L,('record/%s.rec'):format(M.name),'l')
end
end
end
@@ -377,7 +377,7 @@ end
do--function dumpBasicConfig()
local gameSetting={
--Tuning
'das','arr','dascut','sddas','sdarr',
'das','arr','dascut','dropcut','sddas','sdarr',
'ihs','irs','ims','RS','swap',
--System
@@ -539,12 +539,12 @@ do--function checkWarning()
_=max(_-.026,0)
end
GAME.warnLVL=_
if GAME.warnLVL>1.126 and P1.frameRun%30==0 then
SFX.fplay('warning',SETTING.sfx_warn)
end
elseif GAME.warnLVL>0 then
GAME.warnLVL=max(GAME.warnLVL-.026,0)
end
if GAME.warnLVL>1.126 and P1.frameRun%30==0 then
SFX.fplay('warning',SETTING.sfx_warn)
end
end
end

View File

@@ -19,6 +19,7 @@ MODOPT={--Mod options
key="e",x=320,y=230,color='A',
list={1,2,3,4,5},
func=function(P,O)P.gameEnv.nextStartPos=O+1 end,
unranked=true,
},
{no=3,id="IH",name="infHold",
key="r",x=440,y=230,color='A',
@@ -28,10 +29,12 @@ MODOPT={--Mod options
{no=4,id="HB",name="hideBlock",
key="y",x=680,y=230,color='V',
func=function(P)P.gameEnv.block=false end,
unranked=true,
},
{no=5,id="HG",name="hideGhost",
key="u",x=800,y=230,color='V',
func=function(P)P.gameEnv.ghost=false end,
unranked=true,
},
{no=6,id="HD",name="hidden",
key="i",x=920,y=230,color='P',
@@ -43,11 +46,13 @@ MODOPT={--Mod options
key="o",x=1040,y=230,color='P',
list={'down','up','all'},
func=function(P,O)P.gameEnv.hideBoard=O end,
unranked=true,
},
{no=8,id="FB",name="flipBoard",
key="p",x=1160,y=230,color='J',
list={'U-D','L-R','180'},
func=function(P,O)P.gameEnv.flipBoard=O end,
unranked=true,
},
{no=9,id="DT",name="dropDelay",
@@ -134,6 +139,7 @@ MODOPT={--Mod options
key="m",x=920,y=470,color='B',
list={'on','off'},
func=function(P,O)P.gameEnv.bone=O=='on'end,
unranked=true,
},
}
for i=1,#MODOPT do
@@ -235,7 +241,7 @@ customEnv0={
missionKill=false,
--Else
bg='blockfall',
bg='blockrain',
bgm='hang out',
}
CUSTOMENV=FILE.load('conf/customEnv')--gameEnv for cutsom game
@@ -246,7 +252,7 @@ else
end
ROOMENV={
--Room config
capacity=5,
capacity=10,
--Basic
drop=30,
@@ -282,11 +288,12 @@ ROOMENV={
--Else
bg='blockfall',
bgm='hang out',
bgm='battle',
}
SETTING={--Settings
--Tuning
das=10,arr=2,dascut=0,
das=10,arr=2,
dascut=0,dropcut=0,
sddas=0,sdarr=2,
ihs=true,irs=true,ims=true,
RS='TRS',

View File

@@ -7,6 +7,11 @@ 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",
},
{"关于T-spin学习",
"tspin",
"help",
"首先指出要能熟练做出各种Tspin并不是只看着Tspin的那一小部分地形就可以玩好的对玩家堆叠能力和计算next能力同样也有较高的要求。\n\n如果不只是出于娱乐、随便玩玩的目的是真的想不断提升Tspin能力变强请在基础能力达到一定要求前不要刻意去学习太多的Tspin而先把重点放在堆叠等基本功上。\n\n参考学T门槛水平40行达到60秒以内可以视个人情况调整为40~120秒、能够轻松完成全消四的40行、不使用hold不降太多速度的前提下比较轻松完成全消四的40行。",
},
{"游戏官网",
"official website homepage guanwang",
"help",

View File

@@ -243,6 +243,7 @@ return{
match="Find Match",
},
net_rooms={
password="Password",
refreshing="Refreshing rooms",
noRoom="There aren't any rooms right now...",
refresh="Refresh",
@@ -252,7 +253,8 @@ return{
net_newRoom={
title="Room config",
roomName="Room name(default to username's room)",
roomDescription="Room description",
password="Password",
description="Room description",
life="Lives",
pushSpeed="Push Speed",
@@ -365,7 +367,9 @@ return{
title="Control Settings",
preview="Preview",
das="DAS",arr="ARR",dascut="DAS cut",
das="DAS",arr="ARR",
dascut="DAS cut",
dropcut="Auto-lock cut",
sddas="Soft Drop DAS",sdarr="Soft Drop ARR",
ihs="Initial Hold",
irs="Initial Rotation",
@@ -542,6 +546,7 @@ return{
stat={
path="Open Data Folder",
save="Data Management",
replays="Saved Replays",
},
music={
title="Music Room",
@@ -896,7 +901,7 @@ return{
{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 Rubik's cube!"},
{C.C,"Also try Terraria!"},
{C.C,"Also try VVVVVV!"},
{C.F,"Also try Cultris II!"},

View File

@@ -218,6 +218,7 @@ return{
match="Buscar Match",
},
net_rooms={
password="Contraseña",
refreshing="Refrescando Salas",
noRoom="No Hay Salas Actualmente",
refresh="Refrescar",
@@ -227,7 +228,8 @@ return{
net_newRoom={
title="Ajustes de sala",
roomName="Nombre (Por defecto: *usuario*'s room)",
roomDescription="Descripción",
password="Contraseña",
description="Descripción",
life="Vida",
pushSpeed="Velocidad de Subida",
@@ -337,7 +339,9 @@ return{
title="Ajustes de Controles",
preview="Ejemplo",
das="DAS",arr="ARR",dascut="Intrrp. de DAS",
das="DAS",arr="ARR",
dascut="Intrrp. de DAS",
-- dropcut="Auto-lock cut",
sddas="DAS de C. Ráp.",sdarr="ARR de C. Rápida",
ihs="Resv. Inicial",
irs="Rot. Inicial",
@@ -497,6 +501,7 @@ return{
stat={
path="Abrir carpeta del juego",
save="Manejo de Datos",
-- replays="Saved Replays",
},
music={
title="Sala de Música",

View File

@@ -214,6 +214,7 @@ return{
-- match="Find Match",
},
net_rooms={
password="Mot de passe",
-- refreshing="Refreshing Rooms",
noRoom="Aucun salon actuellement",
-- refresh="Refresh",
@@ -223,7 +224,8 @@ return{
net_newRoom={
-- title="Room config",
-- roomName="Room name(default to username's room)",
-- roomDescription="Room description",
password="Mot de passe",
-- description="Room description",
life="Vie",
-- pushSpeed="Push Speed",
@@ -336,7 +338,9 @@ return{
title="Paramètres de contrôle",
preview="Aperçu",
das="DAS",arr="ARR",dascut="DAS cut",
das="DAS",arr="ARR",
dascut="DAS cut",
-- dropcut="Auto-lock cut",
sddas="DAS de chute rapide",sdarr="ARR de chute rapide",
ihs="Réserve Initiale",
irs="Rotation Initiale",
@@ -496,6 +500,7 @@ return{
stat={
path="Ouvrir dossier des données",
save="Gestion des données",
-- replays="Saved Replays",
},
music={
title="Salon musical",

View File

@@ -242,6 +242,7 @@ return{
-- match="Find Match",
},
net_rooms={
password="Senha",
-- refreshing="Refreshing Rooms",
noRoom="Nenhuma sala agora",
-- refresh="Refresh",
@@ -251,7 +252,8 @@ return{
net_newRoom={
-- title="Room config",
-- roomName="Room name(default to username's room)",
-- roomDescription="Room description",
password="Senha",
-- description="Room description",
life="Vidas",
pushSpeed="Garbage Speed",
@@ -364,7 +366,9 @@ return{
title="Config. controles",
preview="Preview",
das="DAS",arr="ARR",dascut="DAS cut",
das="DAS",arr="ARR",
dascut="DAS cut",
-- dropcut="Auto-lock cut",
sddas="Soft Drop DAS",sdarr="Soft Drop ARR",
ihs="Segurar Inicial",
irs="Rotação Inicial",
@@ -539,6 +543,7 @@ return{
stat={
path="Abrir Pasta De Data",
save="Gestão De Dados",
-- replays="Saved Replays",
},
music={
title="Sala De Música",
@@ -879,7 +884,7 @@ return{
{C.C,"Tente também Minesweeper"},
{C.C,"Tente também osu!"},
{C.C,"Tente também Phigros"},
{C.C,"Tente também Rubic's cube"},
{C.C,"Tente também Cubo de Rubik"},
{C.C,"Tente também Terraria"},
{C.C,"Tente também VVVVVV"},
{C.F,"Tente também Cultris II"},

View File

@@ -193,7 +193,9 @@ return{
title="[~~]",
preview="?:",
das="x---x x x",arr="x x-x-x",dascut="x x ↓___x x",
das="x---x x x",arr="x x-x-x",
dascut="x x ↓___x x",
dropcut="↓_ !↓↓x",
sddas="↓---↓ ↓ ↓",sdarr="↓ ↓-↓-↓",
ihs="![ ]",
irs="!''",
@@ -354,7 +356,8 @@ return{
},
stat={
path="%$%",
save="%0101%",
save="%0123%",
replays="%0101%",
},
music={
title="(~~~~)",

View File

@@ -243,6 +243,7 @@ return{
match="匹配对手",
},
net_rooms={
password="密码",
refreshing="刷新房间列表中",
noRoom="一个房间都没有哎...",
refresh="刷新",
@@ -252,7 +253,8 @@ return{
net_newRoom={
title="房间参数",
roomName="房间名 (留空默认 用户名's room)",
roomDescription="房间描述",
password="密码",
description="房间描述",
life="命数",
pushSpeed="上涨速度",
@@ -364,7 +366,9 @@ return{
title="控制设置",
preview="预览",
das="DAS",arr="ARR",dascut="DAS打断",
das="DAS",arr="ARR",
dascut="DAS打断",
dropcut="误硬降打断",
sddas="软降DAS",sdarr="软降ARR",
ihs="提前Hold",
irs="提前旋转",
@@ -619,6 +623,7 @@ return{
stat={
path="打开存储目录",
save="用户档案管理",
replays="录像菜单",
},
login={
title="登录",

View File

@@ -7,7 +7,7 @@ local function check_c4w(P)
local h=#P.field
P.field[h+1]=FREEROW.get(20)
P.visTime[h+1]=FREEROW.get(20)
for i=4,7 do P.field[h][i]=0 end
for i=4,7 do P.field[h+1][i]=0 end
end
if P.combo>P.modeData.maxCombo then
P.modeData.maxCombo=P.combo

View File

@@ -5,7 +5,7 @@ local function check_c4w(P)
local h=#P.field
P.field[h+1]=FREEROW.get(20)
P.visTime[h+1]=FREEROW.get(20)
for i=4,7 do P.field[h][i]=0 end
for i=4,7 do P.field[h+1][i]=0 end
end
if P.combo>P.modeData.maxCombo then
P.modeData.maxCombo=P.combo

View File

@@ -54,10 +54,11 @@ return{
if notAir(FIELD[1][y])then
--Switch clear sprint mode on
GAME.modeEnv.dropPiece=checkClear
break
goto BREAK_clearMode
end
end
GAME.modeEnv.dropPiece=NULL
::BREAK_clearMode::
PLY.newPlayer(1)
local AItype=GAME.modeEnv.opponent:sub(1,2)
local AIlevel=tonumber(GAME.modeEnv.opponent:sub(-1))

View File

@@ -18,7 +18,7 @@ local function score(P)
elseif D.pt>=D.target then--Level up!
s=D.target/100
local E=P.gameEnv
BG.set(s==1 and'rainbow'or s==2 and'rainbow2'or s==3 and'lightning'or s==4 and'lightning2'or'lightning')
BG.set(s==1 and'rainbow'or s==2 and'rainbow2'or'lightning')
E.lock=death_lock[s]
E.wait=death_wait[s]
E.fall=death_fall[s]

View File

@@ -50,7 +50,6 @@ return{
freshLimit=15,
dropPiece=check,
RS="SRS",
ospin=false,
bg='rgb',bgm='oxygen',
},
pauseLimit=true,

View File

@@ -41,7 +41,6 @@ return{
sequence='none',
dropPiece=check,
RS="SRS",
ospin=false,
bg='rgb',bgm='oxygen',
},
pauseLimit=true,

View File

@@ -71,11 +71,11 @@ return{
getRank=function(P)
local L=P.stat.row
return
L>=200 and 5 or
L>=170 and 4 or
L>=140 and 3 or
L>=100 and 2 or
L>=50 and 1 or
L>=20 and 0
L>=200 and 5 or
L>=170 and 4 or
L>=140 and 3 or
L>=100 and 2 or
L>=50 and 1 or
L>=20 and 0
end,
}

View File

@@ -71,11 +71,11 @@ return{
getRank=function(P)
local L=P.stat.row
return
L>=200 and 5 or
L>=170 and 4 or
L>=140 and 3 or
L>=100 and 2 or
L>=50 and 1 or
L>=20 and 0
L>=200 and 5 or
L>=170 and 4 or
L>=140 and 3 or
L>=100 and 2 or
L>=50 and 1 or
L>=20 and 0
end,
}

View File

@@ -77,11 +77,11 @@ return{
getRank=function(P)
local L=P.stat.row
return
L>=200 and 5 or
L>=170 and 4 or
L>=140 and 3 or
L>=100 and 2 or
L>=50 and 1 or
L>=20 and 0
L>=200 and 5 or
L>=170 and 4 or
L>=140 and 3 or
L>=100 and 2 or
L>=50 and 1 or
L>=20 and 0
end,
}

View File

@@ -19,23 +19,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<120 and 5 or
T<150 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -32,23 +32,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<120 and 5 or
T<150 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -17,23 +17,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<120 and 5 or
T<150 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -29,23 +29,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<130 and 5 or
T<160 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -17,23 +17,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<130 and 5 or
T<160 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -29,23 +29,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<140 and 5 or
T<180 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -17,23 +17,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<120 and 5 or
T<150 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -29,23 +29,22 @@ return{
mText(drawableText.atk,69,243)
mText(drawableText.eff,69,363)
end,
score=function(P)return{P.stat.atk<=200 and math.floor(P.stat.atk)or 200,P.stat.time}end,
score=function(P)return{P.stat.atk<=100 and math.floor(P.stat.atk)or 100,P.stat.time}end,
scoreDisp=function(D)return D[1].." Attack "..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.atk
if L>=200 then
local A=P.stat.atk
if A>=100 then
local T=P.stat.time
return
T<130 and 5 or
T<160 and 4 or
3
T<50 and 5 or
T<70 and 4 or
T<100 and 3 or
2
else
return
L>=150 and 3 or
L>=100 and 2 or
L>=60 and 1 or
L>=20 and 0
A>=60 and 1 or
A>=30 and 0
end
end,
}

View File

@@ -9,7 +9,6 @@ local NET={
accessToken=false,
cloudData={},
roomList={},--Local roomlist, updated frequently
roomState={--A copy of room structure on server
roomInfo={
name=false,
@@ -26,9 +25,7 @@ local NET={
specSRID=false,--Cached SRID when enter playing room, for connect WS after scene swapped
seed=false,
allReady=false,
connectingStream=false,
waitingStream=false,
roomReadyState=false,
UserCount="_",
PlayCount="_",
@@ -78,24 +75,14 @@ local function _parse(res)
if mesType[res.type]then
return res
else
MES.new('warn',
"Error ws-mes type:"..(
res.type and(
res.reason and
res.type..": "..res.reason
or
res.type
)or
"[NO Message]"
)
)
MES.new('warn',("%s: %s"):format(res.type or"[?]",res.reason or"[NO Message]"))
end
end
end
--WS close message
local function _closeMessage(message)
local mes=JSON.decode(message:sub(3))
local mes=JSON.decode(message)
if mes then
MES.new('info',("%s [%s] %s"):format(text.wsClose,mes.type or"unknown type",mes.reason or""))
else
@@ -132,13 +119,13 @@ end
--Connect
function NET.wsconn_app()
WS.connect('app','/app')
TASK.new(NET.updateWS_app)
TASK.new(NET.freshPlayerCount)
if WS.status('app')=='dead'then
WS.connect('app','/app',nil,6)
TASK.new(NET.updateWS_app)
end
end
function NET.wsconn_user_pswd(email,password)
if WS.status('wsc_user')=='dead'then NET.unlock('wsc_user')end
if NET.lock('wsc_user',5)then
if WS.status('user')=='dead'then
WS.connect('user','/user',JSON.encode{
email=email,
password=password,
@@ -147,8 +134,7 @@ function NET.wsconn_user_pswd(email,password)
end
end
function NET.wsconn_user_token(uid,authToken)
if WS.status('wsc_user')=='dead'then NET.unlock('wsc_user')end
if NET.lock('wsc_user',5)then
if WS.status('user')=='dead'then
WS.connect('user','/user',JSON.encode{
uid=uid,
authToken=authToken,
@@ -157,8 +143,7 @@ function NET.wsconn_user_token(uid,authToken)
end
end
function NET.wsconn_play()
if WS.status('wsc_play')=='dead'then NET.unlock('wsc_play')end
if NET.lock('wsc_play',5)then
if WS.status('play')=='dead'then
WS.connect('play','/play',JSON.encode{
uid=USER.uid,
accessToken=NET.accessToken,
@@ -167,23 +152,22 @@ function NET.wsconn_play()
end
end
function NET.wsconn_stream(srid)
if NET.lock('wsc_stream',5)then
if WS.status('stream')=='dead'then
NET.roomState.start=true
WS.connect('stream','/stream',JSON.encode{
uid=USER.uid,
accessToken=NET.accessToken,
srid=srid,
},10)
},6)
TASK.new(NET.updateWS_stream)
end
end
function NET.wsconn_manage()
if WS.status('wsc_manage')=='dead'then NET.unlock('wsc_manage')end
if NET.lock('wsc_manage',5)then
if WS.status('manage')=='dead'then
WS.connect('manage','/manage',JSON.encode{
uid=USER.uid,
authToken=USER.authToken,
},10)
},6)
TASK.new(NET.updateWS_manage)
end
end
@@ -214,7 +198,9 @@ end
function NET.tryLogin(ifAuto)
if NET.allow_online then
if WS.status('user')=='running'then
NET.getAccessToken()
if NET.lock('access_and_login',8)then
WS.send('user',JSON.encode{action=0})
end
elseif not ifAuto then
SCN.go('login')
end
@@ -223,11 +209,6 @@ function NET.tryLogin(ifAuto)
SFX.play('finesseError')
end
end
function NET.getAccessToken()
if NET.lock('access_and_login',10)then
WS.send('user',JSON.encode{action=0})
end
end
function NET.getUserInfo(uid)
WS.send('user',JSON.encode{
action=1,
@@ -240,7 +221,7 @@ end
--Save
function NET.uploadSave()
if NET.lock('uploadSave',10)then
if NET.lock('uploadSave',8)then
WS.send('user','{"action":2,"data":{"sections":'..JSON.encode{
{section=1,data=STRING.packTable(STAT)},
{section=2,data=STRING.packTable(RANKS)},
@@ -254,7 +235,7 @@ function NET.uploadSave()
end
end
function NET.downloadSave()
if NET.lock('downloadSave',10)then
if NET.lock('downloadSave',8)then
WS.send('user','{"action":3,"data":{"sections":[1,2,3,4,5,6,7]}}')
MES.new('info',"Downloading")
end
@@ -278,23 +259,27 @@ function NET.loadSavedData(sections)
end
end
if STAT.version==NET.cloudData.STAT.version then
local success=true
TABLE.update(NET.cloudData.STAT,STAT)
FILE.save(STAT,'conf/data')
success=success and FILE.save(STAT,'conf/data')
TABLE.update(NET.cloudData.RANKS,RANKS)
FILE.save(RANKS,'conf/unlock')
success=success and FILE.save(RANKS,'conf/unlock')
TABLE.update(NET.cloudData.SETTING,SETTING)
FILE.save(SETTING,'conf/settings')
success=success and FILE.save(SETTING,'conf/settings')
TABLE.update(NET.cloudData.keyMap,keyMap)
FILE.save(keyMap,'conf/key')
success=success and FILE.save(keyMap,'conf/key')
TABLE.update(NET.cloudData.VK_org,VK_org)
FILE.save(VK_org,'conf/virtualkey')
success=success and FILE.save(VK_org,'conf/virtualkey')
FILE.save(NET.cloudData.vkSave1,'conf/vkSave1','q')
FILE.save(NET.cloudData.vkSave2,'conf/vkSave2','q')
success=success and FILE.save(NET.cloudData.vkSave1,'conf/vkSave1')
success=success and FILE.save(NET.cloudData.vkSave2,'conf/vkSave2')
if success then
MES.new('check',text.saveDone)
end
else
MES.new('error',text.versionNotMatch,1)
end
@@ -314,7 +299,7 @@ function NET.fetchRoom()
end
end
function NET.createRoom(roomName,description,capacity,roomType,roomData,password)
if NET.lock('enterRoom',1.26)then
if NET.lock('enterRoom',2)then
NET.roomState.private=not not password
NET.roomState.capacity=capacity
WS.send('play',JSON.encode{
@@ -336,7 +321,7 @@ function NET.createRoom(roomName,description,capacity,roomType,roomData,password
end
end
function NET.enterRoom(room,password)
if NET.lock('enterRoom',1.26)then
if NET.lock('enterRoom',2)then
SFX.play('reach',.6)
WS.send('play',JSON.encode{
action=2,
@@ -386,7 +371,7 @@ end
--WS tick funcs
function NET.freshPlayerCount()
while WS.status('app')~='dead'do
while WS.status('app')=='running'do
for _=1,260 do yield()end
WS.send('app',JSON.encode{action=3})
end
@@ -419,6 +404,7 @@ function NET.updateWS_app()
end
MES.new('broadcast',res.notice,5)
NET.tryLogin(true)
TASK.new(NET.freshPlayerCount)
elseif res.action==0 then--Broadcast
MES.new('broadcast',res.data.message,5)
elseif res.action==1 then--Get notice
@@ -464,7 +450,7 @@ function NET.updateWS_user()
if res.uid then
USER.uid=res.uid
USER.authToken=res.authToken
FILE.save(USER,'conf/user','q')
FILE.save(USER,'conf/user')
if SCN.cur=='login'then SCN.back()end
end
MES.new('check',text.loginSuccessed)
@@ -514,7 +500,9 @@ function NET.updateWS_play()
NET.unlock('access_and_login')
SFX.play('connected')
elseif res.action==0 then--Fetch rooms
NET.roomList=res.roomList
if SCN.cur=="net_rooms"then
WIDGET.active.roomList:setList(res.roomList)
end
NET.unlock('fetchRoom')
elseif res.action==1 then--Create room (not used)
--?
@@ -540,16 +528,14 @@ function NET.updateWS_play()
NET.roomState.private=d.private
NET.roomState.start=d.start
NET.allReady=false
NET.connectingStream=false
NET.waitingStream=false
NET.roomReadyState=false
NET.spectate=false
if d.srid then
NET.spectate=true
NET.specSRID=d.srid
NET.connectingStream=true
NET.roomReadyState='connecting'
end
loadGame('netBattle',true,true)
else
@@ -561,8 +547,10 @@ function NET.updateWS_play()
mode=d.mode,
config=d.config,
}
if SCN.socketRead then SCN.socketRead('join',d)end
NET.allReady=false
if SCN.cur=='net_game'then SCN.socketRead('join',d)end
if NET.roomReadyState=='allReady'then
NET.roomReadyState=false
end
end
elseif res.action==3 then--Player leave
if not d.uid then
@@ -574,23 +562,22 @@ function NET.updateWS_play()
netPLY.remove(d.sid)
removePlayer(PLAYERS,d.sid)
removePlayer(PLY_ALIVE,d.sid)
if SCN.socketRead then SCN.socketRead('leave',d)end
if SCN.cur=='net_game'then SCN.socketRead('leave',d)end
end
elseif res.action==4 then--Player talk
if SCN.socketRead then SCN.socketRead('talk',d)end
if SCN.cur=='net_game'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--Player change join mode
netPLY.setJoinMode(d.uid,d.mode)
elseif res.action==7 then--All Ready
SFX.play('reach',.6)
NET.allReady=true
NET.roomReadyState='allReady'
elseif res.action==8 then--Set
NET.allReady=false
NET.connectingStream=true
NET.roomReadyState='connecting'
NET.wsconn_stream(d.srid)
elseif res.action==9 then--Game finished
if SCN.socketRead then SCN.socketRead('finish',d)end
if SCN.cur=='net_game'then SCN.socketRead('finish',d)end
--d.result: list of {place,survivalTime,uid,score}
for _,p in next,d.result do
@@ -634,9 +621,9 @@ function NET.updateWS_stream()
local d=res.data
if res.type=='Connect'then
NET.unlock('wsc_stream')
NET.connectingStream=false
NET.roomReadyState=false
elseif res.action==0 then--Game start
NET.waitingStream=false
NET.roomReadyState=false
SCN.socketRead('go')
elseif res.action==1 then--Game finished
--?
@@ -660,7 +647,7 @@ function NET.updateWS_stream()
end
end
else
NET.waitingStream=true
NET.roomReadyState='waitConn'
end
else
if d.spectate then

View File

@@ -124,7 +124,7 @@ function netPLY.setJoinMode(uid,ready)
if p.uid==uid then
if p.mode~=ready then
p.mode=ready
if ready==0 then NET.allReady=false end
if ready==0 then NET.roomReadyState=false end
SFX.play('spin_0',.6)
if p.uid==USER.uid then
NET.unlock('ready')
@@ -201,7 +201,7 @@ function netPLY.draw()
--Stencil
stencilW,stencilH=p.w,p.h
gc_setStencilTest('equal',1)
gc_stencil(plyStencil,'replace',1)
gc_stencil(plyStencil)
gc_setColor(1,1,1)
--Avatar

View File

@@ -108,4 +108,5 @@ return{
{font=25,name="[*月]"},
{font=25,name="凌月"},
{font=25,name="e"},
{font=25,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_shear=gc.translate,gc.scale,gc.rotate,gc.shear
local gc_translate,gc_scale,gc_rotate=gc.translate,gc.scale,gc.rotate
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
@@ -142,8 +142,6 @@ local function drawField(P)
while j==P.clearingRow[h]do
h=h+1
gc_translate(0,-stepY)
gc_setColor(1,1,1,alpha)
gc_rectangle('fill',0,30-30*j,300,stepY)
end
drawRow(j,V[j],F[j])
end
@@ -449,18 +447,19 @@ local function drawStartCounter(P)
local count=179-P.frameRun
gc_push('transform')
gc_translate(300,300)
local num=int(count/60+1)
local d=count%60-45
local num=int(count/60)+1
local d=count%60
if num==3 then
gc_setColor(.7,.9,1)
if d>0 then gc_scale(1+d^2*.01,1)end
gc_setColor(.7,.8,.98)
if d>45 then gc_rotate((d-45)^2*.00355)end
elseif num==2 then
gc_setColor(1,.95,.7)
if d>0 then gc_shear(-(d/15)^2,0)end
gc_setColor(.98,.85,.75)
if d>45 then gc_scale(1+(d/15-3)^2,1)end
elseif num==1 then
gc_setColor(1,.8,.8)
if d>0 then gc_rotate(d^2*.00355)end
gc_setColor(1,.7,.7)
if d>45 then gc_scale(1,1+(d/15-3)^2)end
end
if d<20 then gc_scale((d/20)^.4)end
setFont(100)
mStr(num,0,-70)
gc_pop()
@@ -569,7 +568,7 @@ function draw.norm(P)
gc_rectangle('fill',0,-10,300,610)
--Stenciled in-field things
gc_stencil(stencilBoard,'replace',1)
gc_stencil(stencilBoard)
gc_setStencilTest('equal',1)
gc_push('transform')
boardTransform(ENV.flipBoard)
@@ -676,7 +675,7 @@ function draw.norm(P)
--Board cover
if ENV.hideBoard then
gc_stencil(hideBoardStencil[ENV.hideBoard],'replace',1)
gc_stencil(hideBoardStencil[ENV.hideBoard])
gc_setStencilTest('equal',1)
gc_setLineWidth(20)
for i=0,24 do

View File

@@ -1,6 +1,6 @@
return{
das=10,arr=2,
dascut=0,
dascut=0,dropcut=0,
sddas=2,sdarr=2,
ihs=true,irs=true,ims=true,
swap=true,

View File

@@ -197,6 +197,9 @@ local function newEmptyPlayer(id,mini)
P.lastPiece={
id=0,name=0,--block id/name
frame=-1e99,--lock time
autoLock=true,--if lock with gravity
finePts=0,--finesse Points
row=0,dig=0,--lines/garbage cleared

View File

@@ -194,6 +194,7 @@ function Player:setHold(count)--Set hold count (false/true as 0/1)
elseif count==true then
count=1
end
self:switchKey(8,count>0)
self.gameEnv.holdCount=count
self.holdTime=count
while self.holdQueue[count+1]do rem(self.holdQueue)end
@@ -803,7 +804,7 @@ function Player:popNext(ifhold)--Pop nextQueue to hand
--IHdS
if pressing[6]and not ifhold then
self.act_hardDrop(self)
self:act_hardDrop()
pressing[6]=false
end
else
@@ -955,7 +956,7 @@ do--Player.drop(self)--Place piece
end
end
function Player:drop()
function Player:drop(autoLock)
local _
local CHN=VOC.getFreeChannel()
self.dropTime[11]=ins(self.dropTime,1,self.frameRun)--Update speed dial
@@ -974,6 +975,7 @@ do--Player.drop(self)--Place piece
local dospin,mini=0
piece.id,piece.name=C.id,C.name
piece.frame,piece.autoLock=self.frameRun,autoLock
self.waiting=ENV.wait
--Tri-corner spin check
@@ -1533,7 +1535,7 @@ function Player:loadAI(data)--Load AI params
self:setRS('TRS')
end
self.AI_thread=coroutine.wrap(AIFUNC[data.type])
self.AI_thread(self,self.AI_keys)
self:AI_thread(self.AI_keys)
end
--------------------------</Methods>--------------------------
@@ -1699,7 +1701,7 @@ function Player:win(result)
BGM.play('8-bit happiness')
end
end
if GAME.curMode.id=='custom_puzzle'then
if GAME.curMode.name=='custom_puzzle'then
self:showTextF(text.win,0,0,90,'beat',.4)
else
self:showTextF(text.win,0,0,90,'beat',.5,.2)
@@ -1857,31 +1859,36 @@ function Player:act_rot180()
end
end
function Player:act_hardDrop()
local ENV=self.gameEnv
if self.keyPressing[9]then
if self.gameEnv.swap then
if ENV.swap then
self:changeAtkMode(3)
end
self.keyPressing[6]=false
elseif self.control and self.waiting==-1 and self.cur then
if self.curY>self.ghoY then
local CB=self.cur.bk
if self.gameEnv.dropFX and self.gameEnv.block and self.curY-self.ghoY-#CB>-1 then
self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-self.ghoY-#CB+1)
if self.lastPiece.autoLock and self.frameRun-self.lastPiece.frame<ENV.dropcut then
SFX.play('drop_cancel')
else
if self.curY>self.ghoY then
local CB=self.cur.bk
if ENV.dropFX and ENV.block and self.curY-self.ghoY-#CB>-1 then
self:createDropFX(self.curX,self.curY-1,#CB[1],self.curY-self.ghoY-#CB+1)
end
self.curY=self.ghoY
self.spinLast=false
if self.sound then
SFX.play('drop',nil,self:getCenterX()*.15)
VIB(1)
end
end
self.curY=self.ghoY
self.spinLast=false
if self.sound then
SFX.play('drop',nil,self:getCenterX()*.15)
VIB(1)
if ENV.shakeFX then
self.fieldOff.vy=ENV.shakeFX*.6
self.fieldOff.va=self.fieldOff.va+self:getCenterX()*ENV.shakeFX*6e-4
end
self.lockDelay=-1
self:drop()
self.keyPressing[6]=false
end
if self.gameEnv.shakeFX then
self.fieldOff.vy=self.gameEnv.shakeFX*.6
self.fieldOff.va=self.fieldOff.va+self:getCenterX()*self.gameEnv.shakeFX*6e-4
end
self.lockDelay=-1
self:drop()
self.keyPressing[6]=false
end
end
function Player:act_softDrop()

View File

@@ -215,7 +215,7 @@ local seqGenerators={
end
end,
}
return function(P)--Return a piece-generating funtion for player P
return function(P)--Return a piece-generating function for player P
local s=P.gameEnv.sequence
if type(s)=='function'then
return s

View File

@@ -363,7 +363,7 @@ function update.alive(P,dt)
if P.lockDelay>=0 then
goto THROW_stop
end
P:drop()
P:drop(true)
if P.AI_mode=='CC'and P.AI_bot then
CC.updateField(P)
end

View File

@@ -134,7 +134,8 @@ local function tapBoard(x,y,key)
end
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="up"then
tapBoard(cx,cy-(revKB and 1 or -1),true)
elseif key=="down"then

View File

@@ -16,6 +16,7 @@ local startTime,time
local state,progress
local move
local autoPressing
local nextTile,nextCD
local nextPos,prevPos
local prevSpawnTime=0
@@ -232,10 +233,6 @@ function scene.sceneInit()
tapControl=false
startTime=0
reset()
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.mouseDown(x,y,k)
@@ -277,7 +274,9 @@ local function playRep(n)
repeater.focus=false
local move0=move
for i=1,#repeater.seq[n],3 do
autoPressing=true
scene.keyDown(arrows[repeater.seq[n]:sub(i,i+2)],true)
autoPressing=false
end
if move~=move0 then
if repeater.seq[n]~=repeater.last[n]then
@@ -289,7 +288,8 @@ local function playRep(n)
end
end
end
function scene.keyDown(key,auto)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="up"or key=="down"or key=="left"or key=="right"then
if repeater.focus then
local f=repeater.focus
@@ -311,7 +311,7 @@ function scene.keyDown(key,auto)
newTile()
TEXT.show(arrows[key],640,360,80,'beat',3)
move=move+1
if not auto then
if not autoPressing then
SFX.play('move')
end
end

View File

@@ -41,13 +41,10 @@ function scene.sceneInit()
startTime=0
time=0
state=0
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if #key==1 then
if state<2 and frameKeyCount<3 then
if key:upper():byte()==targetString:byte(progress)then

View File

@@ -15,23 +15,23 @@ function scene.sceneInit()
end
scene.mouseDown=NULL
function scene.keyDown(k)
if k:byte()>=48 and k:byte()<=57 then
function scene.keyDown(key)
if key:byte()>=48 and key:byte()<=57 then
if sym=="="then
val=k
val=key
sym=false
elseif sym and not reg then
reg=val
val=k
val=key
else
if #val<14 then
if val=="0"then val=""end
val=val..k
val=val..key
end
end
elseif k:sub(1,2)=="kp"then
scene.keyDown(k:sub(3))
elseif k=="."then
elseif key:sub(1,2)=="kp"then
scene.keyDown(key:sub(3))
elseif key=="."then
if not(val:find(".",nil,true)or val:find("e"))then
if sym and not reg then
reg=val
@@ -39,11 +39,11 @@ function scene.keyDown(k)
end
val=val.."."
end
elseif k=="e"then
elseif key=="e"then
if not val:find("e")then
val=val.."e"
end
elseif k=="backspace"then
elseif key=="backspace"then
if sym=="="then
val=""
elseif sym then
@@ -52,11 +52,11 @@ function scene.keyDown(k)
val=val:sub(1,-2)
end
if val==""then val="0"end
elseif k=="+"or k=="="and kb.isDown("lshift","rshift")then sym="+" reg=false
elseif k=="*"or k=="8"and kb.isDown("lshift","rshift")then sym="*" reg=false
elseif k=="-"then sym="-" reg=false
elseif k=="/"then sym="/" reg=false
elseif k=="return"then
elseif key=="+"or key=="="and kb.isDown("lshift","rshift")then sym="+" reg=false
elseif key=="*"or key=="8"and kb.isDown("lshift","rshift")then sym="*" reg=false
elseif key=="-"then sym="-" reg=false
elseif key=="/"then sym="/" reg=false
elseif key=="return"then
if val:byte(-1)==101 then val=val:sub(1,-2)end
if sym and reg then
if reg:byte(-1)==101 then reg=reg:sub(1,-2)end
@@ -69,13 +69,13 @@ function scene.keyDown(k)
end
sym="="
reg=false
elseif k=="escape"then
elseif key=="escape"then
if val~="0"then
val,reg,sym="0"
else
SCN.back()
end
elseif k=="delete"then
elseif key=="delete"then
val="0"
end
end

View File

@@ -15,13 +15,10 @@ function scene.sceneInit()
ex,ey=626,260
BG.set('matrix')
BGM.play('hang out')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="space"or key=="return"then
if state==0 then
state=1

View File

@@ -498,6 +498,11 @@ local commands={}do
}
do--app
local APPs={
{
code="calc",
scene='app_calc',
description="A simple calculator"
},
{
code="15p",
scene='app_15p',
@@ -511,7 +516,7 @@ local commands={}do
{
code="pong",
scene='app_pong',
description="Pong (2P minigame)"
description="Pong (2P)"
},
{
code="atoz",
@@ -521,17 +526,17 @@ local commands={}do
{
code="uttt",
scene='app_UTTT',
description="Ultimate Tic-Tac-Toe (2P minigame)"
description="Ultimate Tic-Tac-Toe (2P)"
},
{
code="cube",
scene='app_cubefield',
description="Cubefield"
description="Cubefield, original by Max Abernethy"
},
{
code="2048",
scene='app_2048',
description="2048"
description="2048 with some new features"
},
{
code="ten",
@@ -541,7 +546,7 @@ local commands={}do
{
code="tap",
scene='app_tap',
description="Tapping speed test"
description="Clicking/Tapping speed test"
},
{
code="dtw",
@@ -549,29 +554,24 @@ local commands={}do
description="Don't Touch White, a.k.a. Piano Tiles"
},
{
code="cannon",
code="can",
scene='app_cannon',
description="Cannon"
description="A simple cannon shooting game"
},
{
code="dropper",
code="drp",
scene='app_dropper',
description="Dropper"
},
{
code="calc",
scene='app_calc',
description="Calculator"
},
{
code="reflect",
code="rfl",
scene='app_reflect',
description="Reflect (2P minigame)"
description="Reflect (2P)"
},
{
code="poly",
scene='app_polyforge',
description="Polyforge"
description="Polyforge, original by ImpactBlue Studios"
},
}
commands.app={
@@ -587,7 +587,7 @@ local commands={}do
return
end
end
log{C.A,"No this applet"}
log{C.A,"No this applet, type app -list to check all applets"}
else
log{C.A,"Usage:"}
log{C.A,"app -list"}
@@ -611,8 +611,9 @@ local commands={}do
if #key>0 then
if SETTING[key]~=nil then
SETTING[key]=nil
FILE.save(SETTING,'conf/settings','q')
log{C.Y,("Succesfully erased key '%s'"):format(key)}
if FILE.save(SETTING,'conf/settings')then
log{C.Y,("Succesfully erased key '%s'"):format(key)}
end
else
log{C.R,"No key called "..key}
end
@@ -835,8 +836,8 @@ function scene.wheelMoved(_,y)
WHEELMOV(y,"scrollup","scrolldown")
end
function scene.keyDown(k)
if k=="return"then
function scene.keyDown(key)
if key=="return"then
local input=STRING.trim(inputBox:getText())
if input==""then return end
@@ -845,9 +846,6 @@ function scene.keyDown(k)
if history[27]then rem(history,1)end
hisPtr=nil
--Insert empty line
log""
--Execute
if input:byte()==35 then
--Execute lua code
@@ -881,7 +879,10 @@ function scene.keyDown(k)
end
end
inputBox:clear()
elseif k=="up"then
--Insert empty line
log""
elseif key=="up"then
if not hisPtr then
hisPtr=#history
if hisPtr>0 then
@@ -891,7 +892,7 @@ function scene.keyDown(k)
hisPtr=hisPtr-1
inputBox:setText(history[hisPtr])
end
elseif k=="down"then
elseif key=="down"then
if hisPtr then
hisPtr=hisPtr+1
if history[hisPtr]then
@@ -901,7 +902,7 @@ function scene.keyDown(k)
inputBox:clear()
end
end
elseif k=="tab"then
elseif key=="tab"then
local str=inputBox:getText()
if str~=""and not str:find("%s")then
local res={}
@@ -919,15 +920,15 @@ function scene.keyDown(k)
inputBox:setText(res[1])
end
end
elseif k=="scrollup"then outputBox:scroll(-5)
elseif k=="scrolldown"then outputBox:scroll(5)
elseif k=="pageup"then outputBox:scroll(-20)
elseif k=="pagedown"then outputBox:scroll(20)
elseif k=="home"then outputBox:scroll(-1e99)
elseif k=="end"then outputBox:scroll(1e99)
elseif combKey[k]and kb.isDown("lctrl","rctrl")then
combKey[k]()
elseif k=="escape"then
elseif key=="scrollup"then outputBox:scroll(-5)
elseif key=="scrolldown"then outputBox:scroll(5)
elseif key=="pageup"then outputBox:scroll(-20)
elseif key=="pagedown"then outputBox:scroll(20)
elseif key=="home"then outputBox:scroll(-1e99)
elseif key=="end"then outputBox:scroll(1e99)
elseif combKey[key]and kb.isDown("lctrl","rctrl")then
combKey[key]()
elseif key=="escape"then
if not WIDGET.isFocus(inputBox)then
WIDGET.focus(inputBox)
else
@@ -935,7 +936,7 @@ function scene.keyDown(k)
end
else
if not WIDGET.isFocus(inputBox)then WIDGET.focus(inputBox)end
WIDGET.keyPressed(k)
WIDGET.keyPressed(key)
end
end

View File

@@ -64,10 +64,6 @@ function scene.sceneInit()
gc.setLineJoin('bevel')
BGM.play('push')
BG.set('none')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.touchDown(x)
@@ -102,7 +98,8 @@ function scene.touchUp(x)
scene.keyDown("space")
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
SCN.back()
elseif play then

View File

@@ -34,13 +34,10 @@ function scene.sceneInit()
state='menu'
BGM.play('hang out')
BG.set('space')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="space"or key=="return"then
if state=='move'then
if floor>0 then

View File

@@ -108,10 +108,6 @@ function scene.sceneInit()
reset()
BG.set('gray')
BGM.play('way')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
local function touch(n)
@@ -153,7 +149,8 @@ local function touch(n)
SFX.play('clear_2')
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="r"then reset()
elseif key=="escape"then SCN.back()
elseif state~=2 then

View File

@@ -38,16 +38,13 @@ function scene.sceneInit()
end
BG.set('none')
BGM.play('dream')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.keyDown(k)
if k=="escape"then
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
SCN.back()
elseif k=="space"then
elseif key=="space"then
if state==0 then--main
if timer==0 then
state=1

View File

@@ -42,7 +42,8 @@ local function start()
vx=rnd()>.5 and 6 or -6
vy=rnd()*6-3
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="space"then
if state==0 then
start()

View File

@@ -17,13 +17,10 @@ end
function scene.sceneInit()
reset()
BG.set('none')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if state==0 then
if key=="space"then
reset()

View File

@@ -80,7 +80,8 @@ end
function scene.touchDown(x,y)
tapBoard(x,y)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="z"or key=="x"then
love.mousepressed(ms.getPosition())
elseif key=="space"then

View File

@@ -14,13 +14,10 @@ function scene.sceneInit()
keyTime={}for i=1,40 do keyTime[i]=-1e99 end
BG.set('gray')
BGM.play('push')
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
SCN.back()
else
@@ -72,7 +69,7 @@ function scene.draw()
end
scene.widgetList={
WIDGET.newKey{name="tap",x=640,y=540,w=626,h=260,fText="TAP",color='Z',font=100,code=pressKey"button"},
WIDGET.newKey{name="tap",x=640,y=540,w=626,h=260,fText="TAP",color='Z',font=100,code=function(i)love.keypressed('b'..i)end},
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
}

View File

@@ -122,7 +122,8 @@ local function merge()
failPos=cy*10+cx
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="up"or key=="down"or key=="left"or key=="right"then
if state==2 then return end
if not cx then

View File

@@ -47,7 +47,8 @@ function scene.sceneBack()
BGM.play()
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="return"or key=="return2"then
if CUSTOMENV.opponent~="X"then
if CUSTOMENV.opponent:sub(1,2)=='CC'and CUSTOMENV.sequence=="fixed"then
@@ -63,11 +64,11 @@ function scene.keyDown(key)
end
if key=="return2"or kb.isDown("lalt","lctrl","lshift")then
if initField then
FILE.save(CUSTOMENV,'conf/customEnv','q')
FILE.save(CUSTOMENV,'conf/customEnv')
loadGame('custom_puzzle',true)
end
else
FILE.save(CUSTOMENV,'conf/customEnv','q')
FILE.save(CUSTOMENV,'conf/customEnv')
loadGame('custom_clear',true)
end
elseif key=="f"then
@@ -78,6 +79,8 @@ function scene.keyDown(key)
SCN.go('custom_mission','swipeD')
elseif key=="delete"then
if sure>20 then
TABLE.cut(FIELD)TABLE.cut(BAG)TABLE.cut(MISSION)
FIELD[1]=DATA.newBoard()
TABLE.update(customEnv0,CUSTOMENV)
for _,W in next,scene.widgetList do W:reset()end
sure=0
@@ -105,7 +108,7 @@ function scene.keyDown(key)
DATA.pasteSequence(args[2])and
DATA.pasteMission(args[3])
)then goto THROW_fail end
repeat table.remove(FIELD)until #FIELD==0
TABLE.cut(FIELD)
FIELD[1]=DATA.newBoard()
for i=4,#args do
if args[i]:find("%S")and not DATA.pasteBoard(args[i],i-3)and i<#args then goto THROW_fail end
@@ -115,7 +118,7 @@ function scene.keyDown(key)
do return end
::THROW_fail::MES.new('error',text.dataCorrupted)
elseif key=="escape"then
FILE.save(CUSTOMENV,'conf/customEnv','q')
FILE.save(CUSTOMENV,'conf/customEnv')
SCN.back()
else
WIDGET.keyPressed(key)

View File

@@ -100,6 +100,7 @@ function scene.keyDown(key)
MES.new('check',text.importSuccess)
cur=#BAG
else
TABLE.cut(BAG)
MES.new('error',text.dataCorrupted)
end
elseif key=="escape"then

View File

@@ -110,6 +110,8 @@ function scene.keyDown(key)
else
SCN.back()
end
else
return
end
url=getList()[selected][5]
end

View File

@@ -8,7 +8,6 @@ local touchMoveLastFrame=false
local scene={}
function scene.sceneInit()
love.keyboard.setKeyRepeat(false)
if GAME.init then
resetGameData()
GAME.init=false
@@ -17,7 +16,6 @@ function scene.sceneInit()
noTouch=not SETTING.VKSwitch or noKey
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
destroyPlayers()
end
@@ -68,7 +66,8 @@ function scene.touchMove()
::CONTINUE_nextKey::
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
local k=keyMap.keyboard[key]
if k then
if k>0 then

View File

@@ -8,16 +8,16 @@ end
function scene.wheelMoved(_,y)
WHEELMOV(y)
end
function scene.keyDown(k)
if k=="up"then
function scene.keyDown(key)
if key=="up"then
WIDGET.active.texts:scroll(-5)
elseif k=="down"then
elseif key=="down"then
WIDGET.active.texts:scroll(5)
elseif k=="pageup"then
elseif key=="pageup"then
WIDGET.active.texts:scroll(-20)
elseif k=="pagedown"then
elseif key=="pagedown"then
WIDGET.active.texts:scroll(20)
elseif k=="escape"then
elseif key=="escape"then
SCN.back()
end
end

View File

@@ -19,7 +19,8 @@ end
function scene.touchDown()
scene.mouseDown()
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
VOC.play('bye')
SCN.swapTo('quit','slowFade')

View File

@@ -1,4 +1,4 @@
local gc,kb=love.graphics,love.keyboard
local gc=love.graphics
local scene={}
@@ -153,22 +153,28 @@ local loadingThread=coroutine.wrap(function()
upFloor()
SKIN.change(SETTING.skinSet)
local editFlag
for name,rank in next,RANKS do
local M=MODES[name]
if type(rank)~='number'then
RANKS[name]=nil
editFlag=true
elseif M and M.unlock and rank>0 then
for _,unlockName in next,M.unlock do
if not RANKS[unlockName]then
RANKS[unlockName]=0
editFlag=true
end
end
end
if not(M and M.score)then
RANKS[name]=nil
editFlag=true
end
end
FILE.save(RANKS,'conf/unlock','q')
if editFlag then
FILE.save(RANKS,'conf/unlock')
end
YIELD()
upFloor()
@@ -212,13 +218,13 @@ function scene.sceneInit()
shadePhase2=6.26*math.random()
skip=0--Skip time
light[6*3],light[26*3]=true,true
kb.setKeyRepeat(false)
end
function scene.sceneBack()
love.event.quit()
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
SCN.back()
elseif key=="s"then
@@ -252,7 +258,6 @@ function scene.update(dt)
end
if openTime>=3.26 and not SCN.swapping then
SCN.swapTo('intro')
love.keyboard.setKeyRepeat(true)
end
end
end
@@ -278,7 +283,7 @@ function scene.draw()
gc.setColor(.15,.15,.15)
gc.rectangle('fill',340,0,600,720)
gc.stencil(doorStencil,'replace',1)
gc.stencil(doorStencil)
gc.setStencilTest('equal',1)
gc.push('transform')

View File

@@ -12,11 +12,9 @@ local function login()
end
NET.wsconn_user_pswd(email,password)
if savePW then
FILE.save({email,password},'conf/account','q')
FILE.save({email,password},'conf/account')
else
if love.filesystem.getInfo('conf/account')then
love.filesystem.remove('conf/account')
end
love.filesystem.remove('conf/account')
end
end

View File

@@ -46,13 +46,18 @@ function scene.mouseDown(x,y)
end
scene.touchDown=scene.mouseDown
local function testButton(n)
if WIDGET.isFocus(scene.widgetList[n])then
return true
if NET.getlock('access_and_login')then
MES.new('warn',text.wsConnecting)
else
WIDGET.focus(scene.widgetList[n])
if WIDGET.isFocus(scene.widgetList[n])then
return true
else
WIDGET.focus(scene.widgetList[n])
end
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="1"then
if testButton(1)then
SCN.go('mode')
@@ -65,10 +70,10 @@ function scene.keyDown(key)
if testButton(3)then
if WS.status('app')=='running'then
NET.tryLogin(false)
else
elseif WS.status('app')=='dead'then
NET.wsconn_app()
MES.new('info',text.wsConnecting)
SFX.play('connect')
MES.new('info',text.wsConnecting)
end
end
elseif key=="z"then
@@ -143,7 +148,7 @@ function scene.draw()
gc.translate(260,650)
gc.setLineWidth(2)
gc.rectangle('line',0,0,tipLength,42)
gc.stencil(tipStencil,'replace',1)
gc.stencil(tipStencil)
gc.setStencilTest('equal',1)
gc.draw(tip,0+scrollX,0)
gc.setColor(1,1,1,.2)
@@ -158,6 +163,14 @@ function scene.draw()
--Player count
drawOnlinePlayerCount()
--Connecting mark
if NET.getlock('access_and_login')then
gc.setColor(1,1,1)
gc.setLineWidth(10)
local t=TIME()*6.26%6.2832
gc.arc('line','open',scene.widgetList[3].x+865,450,40,t,t+4.26)
end
end
scene.widgetList={

View File

@@ -8,16 +8,16 @@ end
function scene.wheelMoved(_,y)
WHEELMOV(y)
end
function scene.keyDown(k)
if k=="up"then
function scene.keyDown(key)
if key=="up"then
WIDGET.active.texts:scroll(-5)
elseif k=="down"then
elseif key=="down"then
WIDGET.active.texts:scroll(5)
elseif k=="pageup"then
elseif key=="pageup"then
WIDGET.active.texts:scroll(-20)
elseif k=="pagedown"then
elseif key=="pagedown"then
WIDGET.active.texts:scroll(20)
elseif k=="escape"then
elseif key=="escape"then
SCN.back()
end
end

View File

@@ -120,7 +120,8 @@ end
function scene.touchClick(x,y)
scene.mouseClick(x,y)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="return"then
if mapCam.sel then
mapCam.keyCtrl=false

View File

@@ -30,7 +30,7 @@ end
function scene.wheelMoved(_,y)
WHEELMOV(y)
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
local S=selected
if key=="down"then
if S<#bgmList then
@@ -42,17 +42,19 @@ function scene.keyDown(key)
selected=S-1
SFX.play('move',.7)
end
elseif key=="return"or key=="space"then
if BGM.nowPlay~=bgmList[S]then
BGM.play(bgmList[S])
if SETTING.bgm>0 then SFX.play('click')end
else
BGM.stop()
elseif not isRep then
if key=="return"or key=="space"then
if BGM.nowPlay~=bgmList[S]then
BGM.play(bgmList[S])
if SETTING.bgm>0 then SFX.play('click')end
else
BGM.stop()
end
elseif key=="tab"then
SCN.swapTo('sound','none')
elseif key=="escape"then
SCN.back()
end
elseif key=="tab"then
SCN.swapTo('sound','none')
elseif key=="escape"then
SCN.back()
end
end

View File

@@ -73,9 +73,6 @@ function scene.sceneInit(org)
NET.specSRID=false
end
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end
scene.mouseDown=NULL
function scene.mouseMove(x,y)netPLY.mouseMove(x,y)end
@@ -120,22 +117,18 @@ function scene.touchMove()
::CONTINUE_nextKey::
end
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if key=="escape"then
if not inputBox.hide then
scene.keyDown("switchChat")
_switchChat()
else
_quit()
end
elseif key=="return"then
local mes=STRING.trim(inputBox:getText())
if not inputBox.hide then
if #mes>0 then
NET.sendMessage(mes)
inputBox:clear()
else
_switchChat()
end
if not inputBox.hide and #mes>0 then
NET.sendMessage(mes)
inputBox:clear()
else
_switchChat()
end
@@ -143,7 +136,7 @@ function scene.keyDown(key)
WIDGET.focus(inputBox)
inputBox:keypress(key)
elseif playing then
if noKey then return end
if noKey or isRep then return end
local k=keyMap.keyboard[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
@@ -214,7 +207,6 @@ function scene.socketRead(cmd,d)
elseif cmd=='go'then
if not playing then
playing=true
love.keyboard.setKeyRepeat(false)
lastUpstreamTime=0
upstreamProgress=1
resetGameData('n',NET.seed)
@@ -295,13 +287,13 @@ function scene.draw()
--Ready & Set mark
setFont(50)
if NET.allReady then
if NET.roomReadyState=='allReady'then
gc_setColor(0,1,.5,.9)
mStr(text.ready,640,15)
elseif NET.connectingStream then
elseif NET.roomReadyState=='connecting'then
gc_setColor(.1,1,.8,.9)
mStr(text.connStream,640,15)
elseif NET.waitingStream then
elseif NET.roomReadyState=='waitConn'then
gc_setColor(0,.8,1,.9)
mStr(text.waitStream,640,15)
end

View File

@@ -28,7 +28,7 @@ scene.widgetList={
NET.wsclose_user()
USER.uid=false
USER.authToken=false
FILE.save(USER,'conf/user','q')
FILE.save(USER,'conf/user')
SCN.back()
end
else

View File

@@ -1,9 +1,11 @@
local ROOMENV=ROOMENV
local roomName=WIDGET.newText{name="roomName",x=40,y=150,align='L'}
local roomNameBox=WIDGET.newInputBox{name="roomNameBox",x=40,y=200,w=640,h=60}
local description=WIDGET.newText{name="roomDescription",x=700,y=50,align='L'}
local descriptionBox=WIDGET.newInputBox{name="descriptionBox",x=700,y=100,w=550,h=160,font=25}
local roomName=WIDGET.newText{name="roomName", x=40,y=115,align='L'}
local roomNameBox=WIDGET.newInputBox{ x=40,y=160,w=540,h=60}
local password=WIDGET.newText{name="password", x=40,y=255,align='L'}
local passwordBox=WIDGET.newInputBox{ x=40,y=300,w=540,h=60}
local description=WIDGET.newText{name="description",x=650,y=55,align='L'}
local descriptionBox=WIDGET.newInputBox { x=650,y=100,w=550,h=160,font=25}
local sList={
visible={"show","easy","slow","medium","fast","none"},
@@ -23,12 +25,17 @@ local sList={
local scene={}
local function createRoom()
local pw=passwordBox.value
if pw==""then pw=nil end
local roomname=STRING.trim(roomNameBox.value)
if #roomname==0 then roomname=(USERS.getUsername(USER.uid)or"Anonymous").."'s room"end
NET.createRoom(
roomname,
descriptionBox.value,
ROOMENV.capacity,"normal",ROOMENV
ROOMENV.capacity,
"normal",
ROOMENV,
pw
)
end
@@ -42,13 +49,13 @@ function scene.sceneBack()
BGM.play()
end
function scene.keyDown(k)
if k=="return"then
function scene.keyDown(key)
if key=="return"then
createRoom()
elseif k=="escape"then
elseif key=="escape"then
SCN.back()
else
WIDGET.keyPressed(k)
WIDGET.keyPressed(key)
end
end
@@ -56,14 +63,16 @@ scene.widgetScrollHeight=400
scene.widgetList={
WIDGET.newText{name="title",x=40,y=15,font=70,align='L'},
--Room name
--Room name/password/description
roomName,
roomNameBox,
password,
passwordBox,
description,
descriptionBox,
--Selectors
WIDGET.newSelector{name="life", x=170,y=370,w=260,color='R',list=sList.life, disp=ROOMval("life"), code=ROOMsto("life")},
WIDGET.newSelector{name="life", x=170,y=410,w=260,color='R',list=sList.life, disp=ROOMval("life"), code=ROOMsto("life")},
WIDGET.newSelector{name="pushSpeed", x=170,y=520,w=260,color='V',list=sList.pushSpeed, disp=ROOMval("pushSpeed"), code=ROOMsto("pushSpeed")},
WIDGET.newSelector{name="garbageSpeed", x=170,y=600,w=260,color='V',list=sList.pushSpeed, disp=ROOMval("garbageSpeed"),code=ROOMsto("garbageSpeed")},
WIDGET.newSelector{name="visible", x=170,y=710,w=260,color='lB',list=sList.visible, disp=ROOMval("visible"), code=ROOMsto("visible")},
@@ -78,17 +87,8 @@ scene.widgetList={
WIDGET.newSelector{name="wait",x=730,y=520,w=260,color='G',list=sList.wait,disp=ROOMval("wait"),code=ROOMsto("wait")},
WIDGET.newSelector{name="fall",x=730,y=600,w=260,color='G',list=sList.fall,disp=ROOMval("fall"),code=ROOMsto("fall")},
--Capcity & Create & Back
WIDGET.newSelector{name="capacity", x=1070,y=330,w=310,color='lY',list={2,3,4,5,7,10,17,31,49,99},disp=ROOMval("capacity"),
code=function(i)
if USER.uid<100 or i<=10 then
ROOMENV.capacity=i
WIDGET.active.capacity.color=COLOR.lY
else
MES.new('error',"没有权限 Permission Denied")
WIDGET.active.capacity.color=COLOR.R
end
end},
--Capacity & Create & Back
WIDGET.newSelector{name="capacity", x=1070,y=330,w=310,color='lY',list={2,3,4,5,7,10,17,31,49,99},disp=ROOMval("capacity"),code=ROOMsto("capacity")},
WIDGET.newButton{name="create", x=1070,y=480,w=310,h=140,color='lN',font=40,code=pressKey"return"},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},

View File

@@ -1,13 +1,47 @@
local gc=love.graphics
local ms=love.mouse
local gc_translate=gc.translate
local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth
local gc_draw=gc.draw
local gc_rectangle,gc_arc=gc.rectangle,gc.arc
local gc_print,gc_printf=gc.print,gc.printf
local int,max,min=math.floor,math.max,math.min
local NET=NET
local scrollPos,selected
local fetchTimer
--[[NET.roomList[n]={
local compatibleVer={
"V0.15.2",
"V0.15.3",
"V0.15.4",
}
local roomList=WIDGET.newListBox{name="roomList",x=50,y=50,w=800,h=440,lineH=40,drawF=function(ifSel,id,item)
setFont(35)
if ifSel then
gc_setColor(1,1,1,.3)
gc_rectangle('fill',0,0,800,40)
end
gc_setColor(1,1,1)
if item.private then gc_draw(IMG.lock,10,5)end
gc_print(item.count.."/"..item.capacity,670,-4)
gc_setColor(.9,.9,1)
gc_print(id,45,-4)
if item.start then
gc_setColor(0,.4,.1)
else
gc_setColor(1,1,.7)
end
gc_print(item.roomInfo.name,200,-4)
end}
local function hidePW()
local R=roomList:getSel()
return not R or not R.private
end
local passwordBox=WIDGET.newInputBox{name="password",x=350,y=505,w=500,h=50,secret=true,hideF=hidePW}
--[[roomList[n]={
rid="qwerty",
roomInfo={
name="MrZ's room",
@@ -23,158 +57,72 @@ local function fetchRoom()
fetchTimer=10
NET.fetchRoom()
end
local scene={}
function scene.sceneInit()
BG.set()
scrollPos=0
selected=1
fetchRoom()
end
function scene.wheelMoved(_,y)
scrollPos=max(0,min(scrollPos-y,#NET.roomList-10))
end
function scene.keyDown(k)
if k=="r"then
function scene.keyDown(key)
if key=="r"then
if fetchTimer<=7 then
fetchRoom()
end
elseif k=="s"then
elseif key=="s"then
SCN.go('setting_game')
elseif k=="n"then
elseif key=="n"then
SCN.go('net_newRoom')
elseif k=="escape"then
elseif key=="escape"then
SCN.back()
elseif #NET.roomList>0 then
if k=="down"then
if selected<#NET.roomList then
selected=selected+1
scrollPos=max(selected-10,min(scrollPos,selected-1))
end
elseif k=="up"then
if selected>1 then
selected=selected-1
scrollPos=max(selected-10,min(scrollPos,selected-1))
end
elseif k=="return"then
if NET.getlock('fetchRoom')or not NET.roomList[selected]then return end
local R=NET.roomList[selected]
if R.roomInfo.version~=VERSION.short then MES.new('error',"Version doesn't match")return end
if R.private then MES.new('error',"Can't enter private room now")return end
NET.enterRoom(R)--,password
elseif roomList:getLen()>0 and key=="return"then
local R=roomList:getSel()
if NET.getlock('fetchRoom')or not R then return end
if TABLE.find(compatibleVer,R.roomInfo.version)then
NET.enterRoom(R,passwordBox.value)
else
MES.new('error',"Version doesn't compatible 版本不兼容")
end
else
WIDGET.keyPressed(key)
end
end
function scene.mouseMove(x,y,_,dy)
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<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<850 then
y=int((y-70)/40)
if y>=1 and y<=10 then
local s=int(y+scrollPos)
if NET.roomList[s]then
if selected~=s then
selected=s
SFX.play('click',.4)
else
scene.keyDown("return")
end
end
end
end
end
scene.touchClick=scene.mouseClick
function scene.update(dt)
if not NET.getlock('fetchRoom')then
if not NET.getlock('fetchRoom')and hidePW()then
fetchTimer=fetchTimer-dt
if fetchTimer<=0 then
fetchRoom()
end
end
if #NET.roomList>0 then
selected=min(selected,#NET.roomList)
end
end
local function roomListStencil()
gc.rectangle('fill',50,110,1180,400)
end
function scene.draw()
--Fetching timer
gc.setColor(1,1,1,.12)
gc.arc('fill','pie',250,620,60,-1.5708,-1.5708-.6283*fetchTimer)
gc_setColor(1,1,1,.12)
gc_arc('fill','pie',250,630,40,-1.5708,-1.5708-.6283*fetchTimer)
--Room list
gc.setColor(1,1,1)
gc.setLineWidth(2)
gc.rectangle('line',50,110,800,400)
local roomCount=#NET.roomList
if roomCount>0 then
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,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)
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()
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)
gc.setColor(.8,.8,.8)
gc.printf(R.roomInfo.description or"[No description]",870,295,365)
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
local R=roomList:getSel()
if R then
gc_translate(870,220)
gc_setColor(1,1,1)
gc_setLineWidth(3)
gc_rectangle('line',0,0,385,335)
setFont(25)
gc_print(R.roomInfo.type,10,25)
gc_setColor(1,1,.7)
gc_printf(R.roomInfo.name,10,0,365)
setFont(20)
gc_setColor(.8,.8,.8)
gc_printf(R.roomInfo.description or"[No description]",10,55,365)
if R.start then
gc_setColor(0,1,.2)
gc_print(text.started,10,300)
end
gc_setColor(1,.2,0)
gc_printf(R.roomInfo.version,10,300,365,'right')
gc_translate(-870,-220)
end
--Profile
@@ -185,12 +133,14 @@ function scene.draw()
end
scene.widgetList={
roomList,
passwordBox,
WIDGET.newKey{name="setting",fText=TEXTURE.setting,x=1200,y=160,w=90,h=90,code=pressKey"s"},
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=250,y=620,w=140,h=140,font=35,code=fetchRoom,hideF=function()return fetchTimer>7 end},
WIDGET.newKey{name="new", x=550,y=620,w=260,h=140,font=30,code=pressKey"n"},
WIDGET.newKey{name="join", x=850,y=620,w=140,h=140,font=40,code=pressKey"return",hideF=function()return #NET.roomList==0 or NET.getlock('enterRoom')end},
WIDGET.newText{name="refreshing",x=450,y=240,font=45,hideF=function()return not NET.getlock('fetchRoom')end},
WIDGET.newText{name="noRoom", x=450,y=245,font=40,hideF=function()return roomList:getLen()>0 or NET.getlock('fetchRoom')end},
WIDGET.newKey{name="refresh", x=250,y=630,w=140,h=120,font=35,code=fetchRoom,hideF=function()return fetchTimer>7 end},
WIDGET.newKey{name="new", x=510,y=630,w=260,h=120,font=30,code=pressKey"n"},
WIDGET.newKey{name="join", x=780,y=630,w=140,h=120,font=40,code=pressKey"return",hideF=function()return roomList:getLen()==0 or NET.getlock('enterRoom')end},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
}

View File

@@ -119,12 +119,12 @@ function scene.sceneInit(org)
end
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
STAT.todayTime=STAT.todayTime+PLAYERS[1].stat.time
trySave()
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="q"then
SCN.back()
elseif key=="escape"then

15
parts/scenes/replays.lua Normal file
View File

@@ -0,0 +1,15 @@
local gc=love.graphics
local scene={}
function scene.sceneInit()
end
function scene.draw()
end
scene.widgetList={
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
}
return scene

View File

@@ -31,8 +31,9 @@ scene.widgetList={
local D=parseCB()
if D then
TABLE.update(D,RANKS)
FILE.save(RANKS,'conf/unlock')
MES.new('check',text.importSuccess)
if FILE.save(RANKS,'conf/unlock')then
MES.new('check',text.importSuccess)
end
else
MES.new('error',text.dataCorrupted)
end
@@ -42,8 +43,9 @@ scene.widgetList={
local D=parseCB()
if D and D.version==STAT.version then
TABLE.update(D,STAT)
FILE.save(STAT,'conf/data')
MES.new('check',text.importSuccess)
if FILE.save(STAT,'conf/data')then
MES.new('check',text.importSuccess)
end
else
MES.new('error',text.dataCorrupted)
end
@@ -53,8 +55,9 @@ scene.widgetList={
local D=parseCB()
if D then
TABLE.update(D,SETTING)
FILE.save(SETTING,'conf/settings')
MES.new('check',text.importSuccess)
if FILE.save(SETTING,'conf/settings')then
MES.new('check',text.importSuccess)
end
else
MES.new('error',text.dataCorrupted)
end
@@ -64,8 +67,9 @@ scene.widgetList={
local D=parseCB()
if D then
TABLE.update(D,VK_org)
FILE.save(VK_org,'conf/virtualkey')
MES.new('check',text.importSuccess)
if FILE.save(VK_org,'conf/virtualkey')then
MES.new('check',text.importSuccess)
end
else
MES.new('error',text.dataCorrupted)
end

View File

@@ -51,26 +51,28 @@ function scene.update()
end
function scene.draw()
gc.translate(550,600)
--Testing grid line
gc.setLineWidth(4)
gc.setColor(1,1,1,.4)
gc.line(550,540,950,540)
gc.line(550,580,950,580)
gc.line(550,620,950,620)
for x=590,910,40 do
gc.line(x,530,x,630)
gc.line(0,0,400,0)
gc.line(0,40,400,40)
gc.line(0,80,400,80)
for x=40,360,40 do
gc.line(x,-10,x,90)
end
gc.setColor(1,1,1)
gc.line(550,530,550,630)
gc.line(950,530,950,630)
gc.line(0,-10,0,90)
gc.line(400,-10,400,90)
--O mino animation
local O=SKIN.curText[SETTING.skin[6]]
local x=550+40*pos
gc.draw(O,x,540,nil,40/30)
gc.draw(O,x,580,nil,40/30)
gc.draw(O,x+40,540,nil,40/30)
gc.draw(O,x+40,580,nil,40/30)
gc.draw(O,40*pos,0,nil,40/30)
gc.draw(O,40*pos,40,nil,40/30)
gc.draw(O,40*pos+40,0,nil,40/30)
gc.draw(O,40*pos+40,40,nil,40/30)
gc.translate(-550,-600)
end
local function sliderShow(S)
@@ -79,17 +81,18 @@ local function sliderShow(S)
end
scene.widgetList={
WIDGET.newText{name="title", x=80, y=50,font=70,align='L'},
WIDGET.newText{name="preview", x=520, y=540,font=40,align='R'},
WIDGET.newText{name="preview", x=520, y=610,font=40,align='R'},
WIDGET.newSlider{name="das", x=250, y=190,w=600,unit=20,disp=SETval("das"), show=sliderShow,code=SETsto("das")},
WIDGET.newSlider{name="arr", x=250, y=260,w=525,unit=15,disp=SETval("arr"), show=sliderShow,code=SETsto("arr")},
WIDGET.newSlider{name="sddas", x=250, y=330,w=350,unit=10,disp=SETval("sddas"),show=sliderShow,code=SETsto("sddas")},
WIDGET.newSlider{name="sdarr", x=250, y=400,w=140,unit=4, disp=SETval("sdarr"),show=sliderShow,code=SETsto("sdarr")},
WIDGET.newSlider{name="dascut", x=250, y=470,w=600,unit=20,disp=SETval("dascut"),show=sliderShow,code=SETsto("dascut")},
WIDGET.newSlider{name="dropcut",x=250, y=540,w=300,unit=10,disp=SETval("dropcut"),show=sliderShow,code=SETsto("dropcut")},
WIDGET.newSwitch{name="ihs", x=1100, y=260, disp=SETval("ihs"), code=SETrev("ihs")},
WIDGET.newSwitch{name="irs", x=1100, y=330, disp=SETval("irs"), code=SETrev("irs")},
WIDGET.newSwitch{name="ims", x=1100, y=400, disp=SETval("ims"), code=SETrev("ims")},
WIDGET.newButton{name="reset", x=160, y=580,w=200,h=100,color='lR',font=40,
WIDGET.newButton{name="reset", x=160, y=640,w=200,h=100,color='lR',font=40,
code=function()
local _=SETTING
_.das,_.arr,_.dascut=10,2,0

View File

@@ -30,7 +30,8 @@ local forbbidenKeys={
["\\"]=true,
["return"]=true,
}
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
if selected then
for k,v in next,keyMap.keyboard do

View File

@@ -76,7 +76,7 @@ function scene.touchUp()
end
end
function scene.touchMove(_,_,dx,dy)
if selected and WIDGET.isFocus(false)then
if selected and not WIDGET.isFocus()then
local B=VK_org[selected]
B.x,B.y=B.x+dx,B.y+dy
end

View File

@@ -34,8 +34,8 @@ scene.widgetList={
WIDGET.newSwitch{name="text", x=450,y=920,disp=SETval("text"), code=SETrev("text")},
WIDGET.newSwitch{name="score", x=450,y=970,disp=SETval("score"), code=SETrev("score")},
WIDGET.newSwitch{name="bufferWarn", x=450,y=1040,disp=SETval('bufferWarn'), code=SETrev('bufferWarn')},
WIDGET.newSwitch{name="showSpike", x=450,y=1090,disp=SETval('showSpike'), code=SETrev('showSpike')},
WIDGET.newSwitch{name="bufferWarn", x=450,y=1040,disp=SETval("bufferWarn"), code=SETrev("bufferWarn")},
WIDGET.newSwitch{name="showSpike", x=450,y=1090,disp=SETval("showSpike"), code=SETrev("showSpike")},
WIDGET.newSwitch{name="nextPos", x=450,y=1160,disp=SETval("nextPos"), code=SETrev("nextPos")},
WIDGET.newSwitch{name="highCam", x=450,y=1210,disp=SETval("highCam"), code=SETrev("highCam")},
WIDGET.newSwitch{name="warn", x=450,y=1280,disp=SETval("warn"), code=SETrev("warn")},

View File

@@ -8,7 +8,8 @@ end
local blockName={'z','s','j','l','t','o','i'}
local lineCount={'single','double','triple','techrash'}
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
if key=="1"then
mini=not mini
elseif key=="2"then

View File

@@ -33,13 +33,14 @@ function scene.touchDown(x,y)
scene.mouseDown(x,y)
end
function scene.keyDown(k)
if k=="escape"then
function scene.keyDown(key,isRep)
if isRep then return end
if key=="escape"then
SCN.back()
else
if k=="l"then
if key=="l"then
loadGame('sprintLock',true)
elseif k=="f"then
elseif key=="f"then
loadGame('sprintFix',true)
end
end

View File

@@ -100,9 +100,10 @@ function scene.draw()
end
scene.widgetList={
WIDGET.newButton{name="path",x=780,y=540,w=250,h=80,font=25,code=function()love.system.openURL(SAVEDIR)end,hide=MOBILE},
WIDGET.newButton{name="save",x=780,y=640,w=250,h=80,font=25,code=goScene'savedata'},
WIDGET.newButton{name="back",x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
WIDGET.newButton{name="path", x=800,y=540,w=250,h=80,font=25,code=function()love.system.openURL(SAVEDIR)end,hide=MOBILE},
WIDGET.newButton{name="save", x=800,y=640,w=250,h=80,font=25,code=goScene'savedata'},
WIDGET.newButton{name="replays",x=1100,y=540,w=250,h=80,font=25,code=goScene'replays'},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,fText=TEXTURE.back,code=backScene},
}
return scene

View File

@@ -14,12 +14,6 @@ function scene.sceneInit()
backCounter=5
list={}
timer=0
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
list={}
love.keyboard.setKeyRepeat(true)
end
function scene.gamepadDown(key)
@@ -28,7 +22,8 @@ end
function scene.gamepadUp(key)
push{COLOR.H,"[gamepadUp] <"..key..">"}
end
function scene.keyDown(key)
function scene.keyDown(key,isRep)
if isRep then return end
push("[keyDown] <"..key..">")
if key=="escape"then
backCounter=backCounter-1

View File

@@ -1,10 +1,10 @@
return STRING.split([=[
未来模式:
任务生存; 对称; 无摩擦; 拼方形; 限高无尽挖掘; 连击练习
极简教程/考试; 大爆炸; 音游模式; 教学关; 术语问答
极简教程/考试; 大爆炸; 音游模式; 教学关; 术语问答; 仅4lPC模式
OSD; 强制Misdrop; 涂色模式(模仿喷喷, designed by teatube)
未来大游戏:
puyo; 花仙子方块; 2048; Bubble
Puyo; Bubble; 2048; 花仙子方块
未来Mod:
修改颜色配置; 只显示场地边框线/顶线
未来按键:
@@ -19,60 +19,92 @@ return STRING.split([=[
Tetra-link; 速算(前缀后缀表达式,二八十六进制)
连连看; 求合体; 坦克大战; 扫雷; 接水管
其他未来内容:
可调场地宽度; 可调攻击系统; 组队战; 实时数据可视化
重做模式选择UI; MOD的UI; 高级自定义序列
阴影样式; 可调场地宽度; 可调攻击系统; 组队战; 实时数据可视化
重做模式选择UI; 重做模组UI; 高级自定义序列
XRS; 全部方块位移动画; 更好的手柄支持
spike相关统计数据; 模式数据分析
区分各种消除(隔断/架空/混合/彩色/穿墙)
手势操作; 特殊控件(虚拟摇杆等)
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹/厚度)
区分各种消除(隔断/架空/混合/彩色/穿墙)
更复杂的攻击(数量/可抵消延时/不可抵消延时/反击/攻击/防御/洞数/连接/炸弹/厚度)
更细节的DAS选项; 成就系统; 拓展主题系统
工程编译到字节码; task-Z(新AI)
等级系统; 收集向抽奖玩法; 自适应UI
录像回放菜单; 自动跳帧; 多方块; 超60帧
0.15.4: 近地轨道 Low Earth Orbit
新增:
自定义房间支持设置密码,允许任何人开大房间
房间列表ui调整
新增误硬降打断延迟机制
改动:
同时允许进入0.15.2/3/4版本的房间
自定义游戏重置功能会重置场地/序列/任务了
文件保存时一般不再弹出保存成功的消息
更好地响应系统长按
控件被隐藏时会自动失去焦点
微调输入框边框样式
修改自定义游戏默认背景和自定义房间默认bgm
小程序tap不再认为鼠标左右键为同一个键
移除20G极限难度400~500背景
所有mod都会让成绩无效
代码:
MES模块升级,文件保存或json编解码失败时会有代码位置指示消息
修改房间准备状态变量修改条件,减少出现问题状态的可能性
控件模块升级,优化交互体验
略微优化ws模块性能
修复:
c4w模式一直响警报
1/30的概率死亡后濒死音效错误播放
DOGC模块创建超过系统限制大小的画布导致报错
服务器传来警告/错误信息时弹出消息的奇怪格式
序列编辑粘贴不当格式数据会导致后续错误
开启3D方块时消行特效也会有两个叠在一起
hold被禁用时虚拟按键不消失
科研模式评级错误
自定义模式进入消除模式后不再恢复正常无尽模式
点击联网游戏按钮后可以切去其他场景然后引发问题
ws模块连接流程可以被read打断
ws模块trigChn无条件一直push占用内存
0.15.3: 卫星 Satellite
新增:
开房支持自定义参数
房间内玩家框会按照排名排序,右侧显示数据,鼠标放上显示更多信息
新BGM:Moonbeam(用于pc挑战两个最难难度)
云存档(统计-数据管理菜单)
新模式:无摩擦(隐藏)
使用MES模块替换LOG模块
新模式:无摩擦(隐藏,在一级设置菜单)
改动:
贴边ui在非默认长宽比下也会贴边了
滚轮也可以控制屏幕滚动
房间内消息提示标记样式修改
语言选择界面按钮颜色
移除省流模式
隐形模式背景更不干扰
语言界面按钮添加颜色
增加震动档位数
简化staff菜单键盘进隐藏模式操作
移除staff场景赞助文本颜色
注册请求发送后按钮会消失并弹出消息
代码:
ui在非默认长宽比下也会贴边了
简化staff场景键盘进隐藏的操作,移除赞助id颜色
更长的尝试连接ws时间
隐形模式背景更不干扰
优化注册菜单交互
移除省流模式
代码:
升级SCR模块,整理大量坐标系变换代码
控制台添加切换/管理服务器的命令
string/table扩展模块升级
解决输入框焦点和回车键的交互问题
接收网络消息的task不再永久停留于任务队列中
收ws消息的task不再永久停留于任务队列
控件模块允许不提供控件名
修复:
对战房间使用新的消息提示器
NX模组不会让成绩无效
数据保存到统计的时机错误
加载没有翻译名称的模式时报错
输入框交互问题
加载不出的错误格式头像文件会导致崩溃
开启3D场地后shader覆盖了贴图透明度
软降das设为0时需要按住两帧才能触发0arr
复活和联网玩家进入挂起状态检测顺序错误
非极简/非任务判负并未完全判负
复活和联网玩家进入挂起状态的触发顺序错误
非极简/非任务判负后仍继续检测后续其他判定
ws连接失败时不能正确显示消息
联网房间从设置返回后背景错误
声音设置cv控件值不同步
声音设置cv控件值不同步
test场景不能退出
一堆ui小问题
0.15.2: 天线 Antenna
新增:

View File

@@ -7,7 +7,6 @@ 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}},