Merge branch 'wstest_3_28' into main

This commit is contained in:
MrZ626
2021-04-07 09:39:21 +08:00
72 changed files with 2179 additions and 1772 deletions

View File

@@ -165,7 +165,7 @@ function love.touchpressed(id,x,y)
if SCN.touchDown then SCN.touchDown(x,y)end if SCN.touchDown then SCN.touchDown(x,y)end
if kb.hasTextInput()then kb.setTextInput(false)end if kb.hasTextInput()then kb.setTextInput(false)end
end end
function love.touchmoved(id,x,y,dx,dy) function love.touchmoved(_,x,y,dx,dy)
if SCN.swapping then return end if SCN.swapping then return end
x,y=xOy:inverseTransformPoint(x,y) x,y=xOy:inverseTransformPoint(x,y)
if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k)end
@@ -205,7 +205,7 @@ local function noDevkeyPressed(key)
LOG.print(string.format("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s",SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num)) LOG.print(string.format("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s",SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num))
elseif key=="f3"then elseif key=="f3"then
for _=1,8 do for _=1,8 do
local P=PLAYERS.alive[rnd(#PLAYERS.alive)] local P=PLY_ALIVE[rnd(#PLY_ALIVE)]
if P~=PLAYERS[1]then if P~=PLAYERS[1]then
P.lastRecv=PLAYERS[1] P.lastRecv=PLAYERS[1]
P:lose() P:lose()
@@ -382,7 +382,7 @@ function love.errorhandler(msg)
love.audio.stop() love.audio.stop()
gc.reset() gc.reset()
if LOADED and #ERRDATA<5 then if LOADED and #ERRDATA<3 then
BG.set("none") BG.set("none")
local scn=SCN and SCN.cur or"NULL" local scn=SCN and SCN.cur or"NULL"
ERRDATA[#ERRDATA+1]={mes=err,scene=scn} ERRDATA[#ERRDATA+1]={mes=err,scene=scn}
@@ -444,13 +444,13 @@ function love.errorhandler(msg)
end end
end end
end end
local WSnames={"app","user","chat","play","stream"} local WSnames={"app","user","play","stream","chat"}
local WScolor={ local WScolor={
{1,0,0,.26}, {1,.5,.5,.7},
{1,.7,0,.26}, {1,.8,.3,.7},
{0,.7,1,.26}, {1,1,.4,.7},
{0,1,0,.26}, {.4,1,.7,.7},
{1,1,0,.26} {.5,.8,1,.7},
} }
local devColor={ local devColor={
COLOR.white, COLOR.white,
@@ -511,7 +511,7 @@ function love.run()
if SCN.swapping then SCN.swapUpdate()end--Scene swapping animation if SCN.swapping then SCN.swapUpdate()end--Scene swapping animation
WIDGET.update()--Widgets animation WIDGET.update()--Widgets animation
LOG.update() LOG.update()
WS.update() WS.update(dt)
--DRAW --DRAW
if not MINI()then if not MINI()then
@@ -587,22 +587,21 @@ function love.run()
for i=1,5 do for i=1,5 do
local status=WS.status(WSnames[i]) local status=WS.status(WSnames[i])
gc_setColor(WScolor[i]) gc_setColor(WScolor[i])
gc_rectangle("fill",0,20*i,-20,-20) gc_rectangle("fill",0,20*i,-80,-20)
if status=="dead"then if status=="dead"then
gc_setColor(.8,.8,.8) gc_setColor(1,1,1)
gc_draw(TEXTURE.ws_dead,-20,20*i-20) gc_draw(TEXTURE.ws_dead,-20,20*i-20)
elseif status=="connecting"then elseif status=="connecting"then
gc_setColor(.8,.8,.8,.5+.3*sin(t*6.26)) gc_setColor(1,1,1,.5+.3*sin(t*6.26))
gc_draw(TEXTURE.ws_connecting,-20,20*i-20) gc_draw(TEXTURE.ws_connecting,-20,20*i-20)
elseif status=="running"then elseif status=="running"then
gc_setColor(.8,.8,.8) gc_setColor(1,1,1)
gc_draw(TEXTURE.ws_running,-20,20*i-20) gc_draw(TEXTURE.ws_running,-20,20*i-20)
end end
local lastPongTime=WS.lastPongTime(WSnames[i]) local t1,t2,t3=WS.getTimers(WSnames[i])
if lastPongTime<1 then gc_setColor(1,1,1,t1)gc_rectangle("fill",-60,20*i,-20,-20)
gc_setColor(1,1,1,1-lastPongTime) gc_setColor(0,1,0,t2)gc_rectangle("fill",-40,20*i,-20,-20)
gc_rectangle("fill",0,20*i,-20,-20) gc_setColor(1,0,0,t3)gc_rectangle("fill",-20,20*i,-20,-20)
end
end end
gc_pop() gc_pop()

View File

@@ -137,7 +137,8 @@ function SCN.swapTo(tar,style)--Parallel scene swapping, cannot back
SCN.swapping=true SCN.swapping=true
local S=SCN.stat local S=SCN.stat
S.tar,S.style=tar,style S.tar,S.style=tar,style
S.time,S.mid,S.draw=unpack(swap[style]) local s=swap[style]
S.time,S.mid,S.draw=s[1],s[2],s[3]
end end
else else
LOG.print("No Scene: "..tar,"warn") LOG.print("No Scene: "..tar,"warn")
@@ -152,6 +153,8 @@ function SCN.go(tar,style)--Normal scene swapping, can back
end end
end end
function SCN.back() function SCN.back()
if SCN.swapping then return end
--Leave scene --Leave scene
if SCN.sceneBack then SCN.sceneBack()end if SCN.sceneBack then SCN.sceneBack()end

View File

@@ -1,5 +1,6 @@
local gc=love.graphics local gc=love.graphics
local setColor,setWidth=gc.setColor,gc.setLineWidth local setColor,setWidth=gc.setColor,gc.setLineWidth
local sin,cos=math.sin,math.cos
local max,min=math.max,math.min local max,min=math.max,math.min
local rnd=math.random local rnd=math.random
local rem=table.remove local rem=table.remove
@@ -77,8 +78,13 @@ function FXdraw.tap(S)
gc.circle("line",S.x,S.y,t*(2-t)*30) gc.circle("line",S.x,S.y,t*(2-t)*30)
setColor(1,1,1,(1-t)*.5) setColor(1,1,1,(1-t)*.5)
gc.circle("fill",S.x,S.y,t*30) gc.circle("fill",S.x,S.y,t*30)
setColor(1,1,1,(1-t)*.2)
gc.circle("fill",S.x,S.y,(t*(1-t)*2)*30) setColor(1,1,1,1-t)
for i=1,10 do
local p=S.ptc[i]
local T=t^.5
gc.rectangle("fill",p[1]*(1-T)+p[3]*T-5,p[2]*(1-T)+p[4]*T-5,11,11)
end
end end
function FXdraw.ripple(S) function FXdraw.ripple(S)
local t=S.t local t=S.t
@@ -142,13 +148,21 @@ function SYSFX.newAttack(rate,x1,y1,x2,y2,wid,r,g,b,a)
} }
end end
function SYSFX.newTap(rate,x,y) function SYSFX.newTap(rate,x,y)
fx[#fx+1]={ local T=
{
update=FXupdate.tap, update=FXupdate.tap,
draw=FXdraw.tap, draw=FXdraw.tap,
t=0, t=0,
rate=rate, rate=rate,
x=x,y=y, x=x,y=y,
ptc={},
} }
for i=1,10 do
local d=40+50*rnd()
local ang=rnd()*6.2832
T.ptc[i]={x,y,x+d*cos(ang),y+d*sin(ang)}
end
fx[#fx+1]=T
end end
function SYSFX.newRipple(rate,x,y,r) function SYSFX.newRipple(rate,x,y,r)
fx[#fx+1]={ fx[#fx+1]={

View File

@@ -1,5 +1,7 @@
local next,type=next,type local next,type=next,type
local TABLE={} local TABLE={}
--Copy [1~#] elements
function TABLE.shift(org) function TABLE.shift(org)
local L={} local L={}
for i=1,#org do for i=1,#org do
@@ -11,6 +13,8 @@ function TABLE.shift(org)
end end
return L return L
end end
--Copy all elements
function TABLE.copy(org) function TABLE.copy(org)
local L={} local L={}
for k,v in next,org do for k,v in next,org do
@@ -22,18 +26,22 @@ function TABLE.copy(org)
end end
return L return L
end end
function TABLE.add(G,base)--For all things in G if same type in base, push to base
--For all things in G if same type in base, push to base
function TABLE.update(G,base)
for k,v in next,G do for k,v in next,G do
if type(v)==type(base[k])then if type(v)==type(base[k])then
if type(v)=="table"then if type(v)=="table"then
TABLE.add(v,base[k]) TABLE.update(v,base[k])
else else
base[k]=v base[k]=v
end end
end end
end end
end end
function TABLE.complete(G,base)--For all things in G if no val in base, push to base
--For all things in G if no val in base, push to base
function TABLE.complete(G,base)
for k,v in next,G do for k,v in next,G do
if base[k]==nil then if base[k]==nil then
base[k]=v base[k]=v
@@ -42,6 +50,22 @@ function TABLE.complete(G,base)--For all things in G if no val in base, push to
end end
end end
end end
--Remove positive integer index of table
function TABLE.cut(G)
for i=#G,1,-1 do
G[i]=nil
end
end
--Clear table
function TABLE.clear(G)
for k in next,G do
G[k]=nil
end
end
--Re-index string value of a table
function TABLE.reIndex(org) function TABLE.reIndex(org)
for k,v in next,org do for k,v in next,org do
if type(v)=="string"then if type(v)=="string"then

View File

@@ -1,6 +1,5 @@
local rem=table.remove local rem=table.remove
local ct=coroutine local assert,resume,status=assert,coroutine.resume,coroutine.status
local assert=assert
local tasks={} local tasks={}
local TASK={} local TASK={}
@@ -10,16 +9,17 @@ end
function TASK.update() function TASK.update()
for i=#tasks,1,-1 do for i=#tasks,1,-1 do
local T=tasks[i] local T=tasks[i]
assert(ct.resume(T.thread)) if status(T.thread)=="dead"then
if ct.status(T.thread)=="dead"then rem(tasks,i)
rem(tasks,i) else
assert(resume(T.thread))
end end
end end
end end
function TASK.new(code,...) function TASK.new(code,...)
local thread=ct.create(code) local thread=coroutine.create(code)
ct.resume(thread,...) resume(thread,...)
if ct.status(thread)~="dead"then if status(thread)~="dead"then
tasks[#tasks+1]={ tasks[#tasks+1]={
thread=thread, thread=thread,
code=code, code=code,

View File

@@ -27,6 +27,10 @@ function THEME.calculate(Y,M,D)
})[Y-2000]or -26)-((M-1)*31+D))<6 and })[Y-2000]or -26)-((M-1)*31+D))<6 and
"sprfes"or "sprfes"or
--April fool's day
M=="04"and D=="01"and
"fool"or
--Z day (Feb./Mar./Apr./May./June 26) --Z day (Feb./Mar./Apr./May./June 26)
math.abs(M-4)<=2 and D+0==26 and math.abs(M-4)<=2 and D+0==26 and
"zday"or "zday"or
@@ -53,6 +57,9 @@ function THEME.set(theme)
elseif theme=="zday"then elseif theme=="zday"then
BG.setDefault("lanterns") BG.setDefault("lanterns")
BGM.setDefault("overzero") BGM.setDefault("overzero")
elseif theme=="fool"then
BG.setDefault("blockrain")
BGM.setDefault("how feeling")
else else
return return
end end

View File

@@ -4,51 +4,19 @@ local host="hdustea.3322.org"
local port="10026" local port="10026"
local path="/tech/socket/v1" local path="/tech/socket/v1"
local debug=false
local wsThread=[[ local wsThread=[[
-- lua + love2d threading websocket client -- lua + love2d threading websocket client
-- Original pure lua ver. by flaribbit and Particle_G and MrZ -- Original pure lua ver. by flaribbit and Particle_G
-- Threading version by MrZ -- Threading version by MrZ
local triggerCHN,sendCHN,readCHN=... local triggerCHN,sendCHN,readCHN,threadName=...
local byte,char=string.byte,string.char
local band,bor,bxor=bit.band,bit.bor,bit.bxor
local shl,shr=bit.lshift,bit.rshift
local SOCK=require"socket".tcp() local SOCK=require"socket".tcp()
local JSON=require"Zframework.json" local JSON=require"Zframework.json"
local mask_key={1,14,5,14}
local function _send(opcode,message)
--Message type
SOCK:send(char(bor(0x80,opcode)))
if not message then
SOCK:send(char(0x80,unpack(mask_key)))
return 0
end
--Length
local length=#message
if length>65535 then
SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff)))
elseif length>125 then
SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff)))
else
SOCK:send(char(bor(length,0x80)))
end
SOCK:send(char(unpack(mask_key)))
local msgbyte={byte(message,1,length)}
for i=1,length do
msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1])
end
return SOCK:send(char(unpack(msgbyte)))
end
do--Connect do--Connect
local host=sendCHN:demand() local host=sendCHN:demand()
local port=sendCHN:demand() local port=sendCHN:demand()
@@ -57,48 +25,97 @@ do--Connect
SOCK:settimeout(2.6) SOCK:settimeout(2.6)
local res,err=SOCK:connect(host,port) local res,err=SOCK:connect(host,port)
if res then if err then readCHN:push(err)return end
--WebSocket handshake
if not body then body=""end
SOCK:send(
"GET "..path.." HTTP/1.1\r\n"..
"Host: "..host..":"..port.."\r\n"..
"Connection: Upgrade\r\n"..
"Upgrade: websocket\r\n"..
"Content-Type: application/json\r\n"..
"Content-Length: "..#body.."\r\n"..
"Sec-WebSocket-Version: 13\r\n"..
"Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n\r\n"..--secKey
body
)
--First line of HTTP --WebSocket handshake
local l=SOCK:receive("*l") if not body then body=""end
local code,ctLen SOCK:send(
if l then "GET "..path.." HTTP/1.1\r\n"..
code=l:find(" "); code=l:sub(code+1,code+3) "Host: "..host..":"..port.."\r\n"..
repeat "Connection: Upgrade\r\n"..
l=SOCK:receive("*l") "Upgrade: websocket\r\n"..
if not ctLen and l:find"length"then "Content-Type: application/json\r\n"..
ctLen=tonumber(l:match"%d+") "Content-Length: "..#body.."\r\n"..
end "Sec-WebSocket-Version: 13\r\n"..
until l=="" "Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n\r\n"..--secKey
body
)
--First line of HTTP
res,err=SOCK:receive("*l")
if not res then readCHN:push(err)return end
local code,ctLen
code=res:find(" ")
code=res:sub(code+1,code+3)
--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 ctLen and res:find"length"then
ctLen=tonumber(res:match"%d+")
end end
until res==""
--Result
if ctLen then
if code=="101"then if code=="101"then
readCHN:push("success") readCHN:push("success")
else else
local reason=JSON.decode(SOCK:receive(ctLen)) res,err=SOCK:receive(ctLen)
readCHN:push(code..":"..(reason and reason.message or"Server Error")) if not res then readCHN:push(err)return end
res=JSON.decode(res)
readCHN:push((code or"XXX")..":"..(res and res.reason or"Server Error"))
end end
else
readCHN:push(err)
end end
SOCK:settimeout(0) SOCK:settimeout(0)
end end
local byte=string.byte
local band,shl=bit.band,bit.lshift
local _send do
local char=string.char
local bor,bxor=bit.bor,bit.bxor
local shr=bit.rshift
local mask_key={1,14,5,14}
local mask_str=char(unpack(mask_key))
function _send(opcode,message)
--Message type
SOCK:send(char(bor(0x80,opcode)))
if message then
--Length
local length=#message
if length>65535 then
SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff)))
elseif length>125 then
SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff)))
else
SOCK:send(char(bor(length,0x80)))
end
SOCK:send(mask_str)
local msgbyte={byte(message,1,length)}
for i=1,length do
msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1])
end
return SOCK:send(char(unpack(msgbyte)))
else
SOCK:send("\128"..mask_str)
return 0
end
end
end
local length
local lBuffer=""--Long multi-data buffer
local UFF--Un-finished-frame mode
local sBuffer=""--Short multi-frame buffer
while true do--Running while true do--Running
--Send
triggerCHN:demand() triggerCHN:demand()
while sendCHN:getCount()>=2 do while sendCHN:getCount()>=2 do
local op=sendCHN:pop() local op=sendCHN:pop()
@@ -106,39 +123,85 @@ while true do--Running
_send(op,message) _send(op,message)
end end
while true do--Read --Read
--Byte 0-1 while true do
local res,err=SOCK:receive(2) if UFF then--UNF process
if not res then break end local s,e,p=SOCK:receive(length)
if s then
local op=band(byte(res,1),0x0f) sBuffer=sBuffer..s
UFF=false
--Calculating data length elseif p then
local length=band(byte(res,2),0x7f) sBuffer=sBuffer..p
if length==126 then length=length-#p
res=SOCK:receive(2) if length==0 then
length=shl(byte(res,1),8)+byte(res,2) UFF=false
elseif length==127 then end
res=SOCK:receive(8)
local b={byte(res,1,8)}
length=shl(b[5],32)+shl(b[6],24)+shl(b[7],8)+b[8]
end
--Receive data
res=SOCK:receive(length)
--React
readCHN:push(op)
if op==8 then--close
SOCK:close()
if type(res)=="string"then
local reason=JSON.decode(res)
readCHN:push(reason and reason.message or"Server Error")
else
readCHN:push("Server Error")
end end
else else
readCHN:push(res) --Byte 0-1
local res,err=SOCK:receive(2)
if err then break end
local op=band(byte(res,1),0x0f)
local fin=band(byte(res,1),0x80)==0x80
--Calculating data length
length=band(byte(res,2),0x7f)
if length==126 then
res=SOCK:receive(2)
length=shl(byte(res,1),8)+byte(res,2)
elseif length==127 then
local b={byte(SOCK:receive(8),1,8)}
length=shl(b[5],24)+shl(b[6],16)+shl(b[7],8)+b[8]
end
if length>0 then
--Receive data
local s,_,p=SOCK:receive(length)
if s then
]]..(debug==1 and""or"--")..[[print(("%s[%d]:%s"):format(threadName,length,s))
res=s
elseif p then--UNF head
]]..(debug==1 and""or"--")..[[print(("%s[%d/%d]:%s"):format(threadName,#p,length,p))
UFF=true
sBuffer=sBuffer..p
length=length-#p
break
end
else
res=""
end
--React
if op==8 then--8=close
readCHN:push(op)
SOCK:close()
if type(res)=="string"then
res=JSON.decode(res)
readCHN:push(res and res.reason or"WS Error")
else
readCHN:push("WS Error")
end
elseif op==0 then--0=continue
lBuffer=lBuffer..res
if fin then
]]..(debug==2 and""or"--")..[[print("FIN=1 (c")
readCHN:push(lBuffer)
lBuffer=""
else
]]..(debug==2 and""or"--")..[[print("FIN=0 (c")
end
else
readCHN:push(op)
if fin then
]]..(debug==2 and""or"--")..[[print("OP: "..op.."\tFIN=1")
readCHN:push(res)
else
]]..(debug==2 and""or"--")..[[print("OP: "..op.."\tFIN=0")
sBuffer=res
]]..(debug==2 and""or"--")..[[print("START pack: "..res)
end
end
end end
end end
end end
@@ -146,10 +209,24 @@ end
local timer=love.timer.getTime local timer=love.timer.getTime
local WS={} local WS={}
local wsList={} local wsList=setmetatable({},{
__index=function(l,k)
local ws={
real=false,
status="dead",
lastPongTime=timer(),
sendTimer=0,
alertTimer=0,
pongTimer=0,
}
l[k]=ws
return ws
end
})
function WS.connect(name,subPath,body) function WS.connect(name,subPath,body)
local ws={ local ws={
real=true,
thread=love.thread.newThread(wsThread), thread=love.thread.newThread(wsThread),
triggerCHN=love.thread.newChannel(), triggerCHN=love.thread.newChannel(),
sendCHN=love.thread.newChannel(), sendCHN=love.thread.newChannel(),
@@ -158,9 +235,12 @@ function WS.connect(name,subPath,body)
lastPongTime=timer(), lastPongTime=timer(),
pingInterval=26, pingInterval=26,
status="connecting",--connecting, running, dead status="connecting",--connecting, running, dead
sendTimer=0,
alertTimer=0,
pongTimer=0,
} }
wsList[name]=ws wsList[name]=ws
ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN) ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN,name)
ws.sendCHN:push(host) ws.sendCHN:push(host)
ws.sendCHN:push(port) ws.sendCHN:push(port)
ws.sendCHN:push(path..subPath) ws.sendCHN:push(path..subPath)
@@ -168,11 +248,13 @@ function WS.connect(name,subPath,body)
end end
function WS.status(name) function WS.status(name)
return wsList[name]and wsList[name].status or"dead" local ws=wsList[name]
return ws.status or"dead"
end end
function WS.lastPongTime(name) function WS.getTimers(name)
return wsList[name]and timer()-wsList[name].lastPongTime or 999 local ws=wsList[name]
return ws.pongTimer,ws.sendTimer,ws.alertTimer
end end
function WS.setPingInterval(name,time) function WS.setPingInterval(name,time)
@@ -180,6 +262,11 @@ function WS.setPingInterval(name,time)
ws.pingInterval=math.max(time or 1,2.6) ws.pingInterval=math.max(time or 1,2.6)
end end
function WS.alert(name)
local ws=wsList[name]
ws.alertTimer=2
end
local OPcode={ local OPcode={
continue=0, continue=0,
text=1, text=1,
@@ -188,54 +275,76 @@ local OPcode={
ping=9, ping=9,
pong=10, pong=10,
} }
local OPname={
[0]="continue",
[1]="text",
[2]="binary",
[8]="close",
[9]="ping",
[10]="pong",
}
function WS.send(name,message,op) function WS.send(name,message,op)
local ws=wsList[name] local ws=wsList[name]
ws.sendCHN:push(op and OPcode[op]or 2)--2=binary if ws.real then
ws.sendCHN:push(message) ws.sendCHN:push(op and OPcode[op]or 2)--2=binary
ws.lastPingTime=timer() ws.sendCHN:push(message)
ws.lastPingTime=timer()
ws.sendTimer=1
end
end end
function WS.read(name) function WS.read(name)
local ws=wsList[name] local ws=wsList[name]
if ws.readCHN:getCount()>=2 then if ws.real and ws.readCHN:getCount()>=2 then
local op=ws.readCHN:pop() local op=ws.readCHN:pop()
local message=ws.readCHN:pop() local message=ws.readCHN:pop()
if op==8 then ws.status="dead"end if op==8 then ws.status="dead"end--8=close
ws.lastPongTime=timer() ws.lastPongTime=timer()
return message,op ws.pongTimer=1
return message,OPname[op]or op
end end
end end
function WS.close(name) function WS.close(name)
local ws=wsList[name] local ws=wsList[name]
ws.sendCHN:push(8)--close if ws.real then
ws.sendCHN:push("") ws.sendCHN:push(8)--close
ws.status="dead" ws.sendCHN:push("")
ws.status="dead"
end
end end
function WS.update() function WS.update(dt)
local time=timer() local time=timer()
for name,ws in next,wsList do for name,ws in next,wsList do
ws.triggerCHN:push(0) if ws.real then
if ws.status=="connecting"then ws.triggerCHN:push(0)
local mes=ws.readCHN:pop() if ws.status=="connecting"then
if mes then local mes=ws.readCHN:pop()
if mes=="success"then if mes then
ws.status="running" if mes=="success"then
ws.status="running"
ws.lastPingTime=time
ws.lastPongTime=time
ws.pongTimer=1
else
ws.status="dead"
LOG.print(text.wsFailed..": "..(mes=="timeout"and text.netTimeout or mes),"warn")
end
end
elseif ws.status=="running"then
if time-ws.lastPingTime>ws.pingInterval then
ws.sendCHN:push(9)
ws.sendCHN:push("")--ping
ws.lastPingTime=time ws.lastPingTime=time
ws.lastPongTime=time end
else if time-ws.lastPongTime>10+3*ws.pingInterval then
ws.status="dead" WS.close(name)
LOG.print(text.wsFailed.." "..mes,"warn")
end end
end end
elseif time-ws.lastPingTime>ws.pingInterval then if ws.sendTimer>0 then ws.sendTimer=ws.sendTimer-dt end
ws.sendCHN:push(9) if ws.pongTimer>0 then ws.pongTimer=ws.pongTimer-dt end
ws.sendCHN:push("")--ping if ws.alertTimer>0 then ws.alertTimer=ws.alertTimer-dt end
ws.lastPingTime=time
end
if time-ws.lastPongTime>10+3*ws.pingInterval then
WS.close(name)
end end
end end
end end

View File

@@ -141,7 +141,8 @@ end
function button:draw() function button:draw()
local x,y,w,h=self.x,self.y,self.w,self.h local x,y,w,h=self.x,self.y,self.w,self.h
local ATV=self.ATV local ATV=self.ATV
local r,g,b=unpack(self.color) local c=self.color
local r,g,b=c[1],c[2],c[3]
gc.setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7) gc.setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7)
gc.rectangle("fill",x-ATV,y-ATV,w+2*ATV,h+2*ATV) gc.rectangle("fill",x-ATV,y-ATV,w+2*ATV,h+2*ATV)
if ATV>0 then if ATV>0 then
@@ -233,7 +234,8 @@ end
function key:draw() function key:draw()
local x,y,w,h=self.x,self.y,self.w,self.h local x,y,w,h=self.x,self.y,self.w,self.h
local ATV=self.ATV local ATV=self.ATV
local r,g,b=unpack(self.color) local c=self.color
local r,g,b=c[1],c[2],c[3]
gc.setColor(1,1,1,ATV*.125) gc.setColor(1,1,1,ATV*.125)
gc.rectangle("fill",x,y,w,h) gc.rectangle("fill",x,y,w,h)

View File

@@ -1,5 +1,5 @@
VERSION_CODE=1303 VERSION_CODE=1400
VERSION_NAME="Alpha V0.13.3" VERSION_NAME="Alpha V0.14.0"
function love.conf(t) function love.conf(t)
t.identity="Techmino"--Saving folder t.identity="Techmino"--Saving folder
t.version="11.1" t.version="11.1"

View File

@@ -23,12 +23,7 @@ SAVEDIR=fs.getSaveDirectory()
--Global Vars & Settings --Global Vars & Settings
LOADED=false LOADED=false
DAILYLAUNCH=false DAILYLAUNCH=false
LOGIN=false
EDITING="" EDITING=""
NET={
allow_online=false,
try_enter_netmenu=false,
}
ERRDATA={} ERRDATA={}
--System setting --System setting
@@ -81,6 +76,7 @@ require"parts.gametoolfunc"
SCR.setSize(1280,720)--Initialize Screen size SCR.setSize(1280,720)--Initialize Screen size
FIELD[1]=newBoard()--Initialize field[1] FIELD[1]=newBoard()--Initialize field[1]
NET= require"parts.net"
AIBUILDER= require"parts.AITemplate" AIBUILDER= require"parts.AITemplate"
FREEROW= require"parts.freeRow" FREEROW= require"parts.freeRow"
@@ -113,14 +109,14 @@ IMG.init{
pay1="mess/pay1.png", pay1="mess/pay1.png",
pay2="mess/pay2.png", pay2="mess/pay2.png",
miyaCH="miya/ch.png", nakiCH="characters/naki.png",
miyaF1="miya/f1.png", miyaCH="characters/miya.png",
miyaF2="miya/f2.png", miyaF1="characters/miya_f1.png",
miyaF3="miya/f3.png", miyaF2="characters/miya_f2.png",
miyaF4="miya/f4.png", miyaF3="characters/miya_f3.png",
miyaF4="characters/miya_f4.png",
electric="mess/electric.png", electric="characters/electric.png",
hbm="mess/hbm.png", hbm="characters/hbm.png",
lanterns={ lanterns={
"lanterns/1.png", "lanterns/1.png",
@@ -259,14 +255,12 @@ do
if type(STAT.version)~="number"then if type(STAT.version)~="number"then
STAT.version=0 STAT.version=0
end end
if STAT.version<1204 then if STAT.version<1300 then
STAT.frame=math.floor(STAT.time*60) STAT.frame=math.floor(STAT.time*60)
STAT.lastPlay="sprint_10l" STAT.lastPlay="sprint_10l"
RANKS.sprintFix=nil RANKS.sprintFix=nil
RANKS.sprintLock=nil RANKS.sprintLock=nil
needSave=true needSave=true
end
if STAT.version<1300 then
for _,name in next,fs.getDirectoryItems("replay")do for _,name in next,fs.getDirectoryItems("replay")do
fs.remove("replay/"..name) fs.remove("replay/"..name)
end end
@@ -274,13 +268,15 @@ do
if STAT.version<1302 then if STAT.version<1302 then
if RANKS.pctrain_n then RANKS.pctrain_n=0 end if RANKS.pctrain_n then RANKS.pctrain_n=0 end
if RANKS.pctrain_l then RANKS.pctrain_l=0 end if RANKS.pctrain_l then RANKS.pctrain_l=0 end
fs.remove("conf/user")
fs.remove("conf/settings") fs.remove("conf/settings")
needSave=true
autoRestart=true autoRestart=true
end end
if STAT.version<1303 then if STAT.version<1400 then
fs.remove("conf/user")
SETTING.appLock=false SETTING.appLock=false
needSave=true needSave=true
autoRestart=true
end end
for _,v in next,VK_org do for _,v in next,VK_org do

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@@ -1,6 +1,6 @@
local int,ceil,min,abs,rnd,modf=math.floor,math.ceil,math.min,math.abs,math.random,math.modf local int,ceil,min,abs,rnd,modf=math.floor,math.ceil,math.min,math.abs,math.random,math.modf
local ins,rem=table.insert,table.remove local ins,rem=table.insert,table.remove
local resume,yield=coroutine.resume,coroutine.yield local yield=coroutine.yield
-- controlname: -- controlname:
-- 1~5:mL,mR,rR,rL,rF, -- 1~5:mL,mR,rR,rL,rF,
-- 6~10:hD,sD,H,A,R, -- 6~10:hD,sD,H,A,R,
@@ -73,13 +73,13 @@ if type(_CC)=="table"then
end end
CC.updateField(P) CC.updateField(P)
while P.holdQueue[1]do rem(P.holdQueue)end TABLE.clear(P.holdQueue)
P.holdTime=P.gameEnv.holdCount P.holdTime=P.gameEnv.holdCount
P.cur=rem(P.nextQueue,1) P.cur=rem(P.nextQueue,1)
P.curX,P.curY=blockPos[P.cur.id],int(P.gameEnv.fieldH+1-modf(P.cur.sc[1]))+ceil(P.fieldBeneath/30) P.curX,P.curY=blockPos[P.cur.id],int(P.gameEnv.fieldH+1-modf(P.cur.sc[1]))+ceil(P.fieldBeneath/30)
assert(resume(P.newNext)) P.newNext()
local id=CCblockID[P.nextQueue[P.AIdata.next].id] local id=CCblockID[P.nextQueue[P.AIdata.next].id]
if id then if id then
CC.addNext(P.AI_bot,id) CC.addNext(P.AI_bot,id)

View File

@@ -0,0 +1,56 @@
--Block rain
local gc=love.graphics
local rnd=math.random
local ins,rem=table.insert,table.remove
local back={}
local t
local cell
function back.init()
t=0
cell={}
end
function back.update()
t=t+1
if t%10==0 then
ins(cell,{
bid=rnd(29),
x=SCR.w*rnd(),
y=-25,
a=rnd()*6.2832,
vy=.5+rnd()*.4,
vx=rnd()*.4-.2,
va=rnd()*.04-.02,
})
end
for i=#cell,1,-1 do
local P=cell[i]
P.y=P.y+P.vy
if P.y>SCR.h+25 then
rem(cell,i)
else
P.x=P.x+P.vx
P.a=P.a+P.va
P.vx=P.vx-.01+rnd()*.02
end
end
end
function back.draw()
gc.clear(.15,.15,.15)
gc.push("transform")
gc.origin()
local texture=TEXTURE.miniBlock
local minoColor=minoColor
for i=1,#cell do
local C=cell[i]
local tex=texture[C.bid]
local c=minoColor[SETTING.skin[C.bid]]
gc.setColor(c[1],c[2],c[3],.5)
gc.draw(tex,C.x,C.y,C.a,10,10,tex:getWidth()/2,tex:getHeight()/2)
end
gc.pop()
end
function back.discard()
cell=nil
end
return back

View File

@@ -271,10 +271,10 @@ end
--Royale mode --Royale mode
function randomTarget(P)--Return a random opponent for P function randomTarget(P)--Return a random opponent for P
if #PLAYERS.alive>1 then if #PLY_ALIVE>1 then
local R local R
repeat repeat
R=PLAYERS.alive[rnd(#PLAYERS.alive)] R=PLY_ALIVE[rnd(#PLY_ALIVE)]
until R~=P until R~=P
return R return R
end end
@@ -282,28 +282,28 @@ end
function freshMostDangerous() function freshMostDangerous()
GAME.mostDangerous,GAME.secDangerous=false,false GAME.mostDangerous,GAME.secDangerous=false,false
local m,m2=0,0 local m,m2=0,0
for i=1,#PLAYERS.alive do for i=1,#PLY_ALIVE do
local h=#PLAYERS.alive[i].field local h=#PLY_ALIVE[i].field
if h>=m then if h>=m then
GAME.mostDangerous,GAME.secDangerous=PLAYERS.alive[i],GAME.mostDangerous GAME.mostDangerous,GAME.secDangerous=PLY_ALIVE[i],GAME.mostDangerous
m,m2=h,m m,m2=h,m
elseif h>=m2 then elseif h>=m2 then
GAME.secDangerous=PLAYERS.alive[i] GAME.secDangerous=PLY_ALIVE[i]
m2=h m2=h
end end
end end
for i=1,#PLAYERS.alive do for i=1,#PLY_ALIVE do
if PLAYERS.alive[i].atkMode==3 then if PLY_ALIVE[i].atkMode==3 then
PLAYERS.alive[i]:freshTarget() PLY_ALIVE[i]:freshTarget()
end end
end end
end end
function freshMostBadge() function freshMostBadge()
GAME.mostBadge,GAME.secBadge=false,false GAME.mostBadge,GAME.secBadge=false,false
local m,m2=0,0 local m,m2=0,0
for i=1,#PLAYERS.alive do for i=1,#PLY_ALIVE do
local P=PLAYERS.alive[i] local P=PLY_ALIVE[i]
local b=P.badge local b=P.badge
if b>=m then if b>=m then
GAME.mostBadge,GAME.secBadge=P,GAME.mostBadge GAME.mostBadge,GAME.secBadge=P,GAME.mostBadge
@@ -314,44 +314,44 @@ function freshMostBadge()
end end
end end
for i=1,#PLAYERS.alive do for i=1,#PLY_ALIVE do
if PLAYERS.alive[i].atkMode==4 then if PLY_ALIVE[i].atkMode==4 then
PLAYERS.alive[i]:freshTarget() PLY_ALIVE[i]:freshTarget()
end end
end end
end end
function royaleLevelup() function royaleLevelup()
GAME.stage=GAME.stage+1 GAME.stage=GAME.stage+1
local spd local spd
TEXT.show(text.royale_remain:gsub("$1",#PLAYERS.alive),640,200,40,"beat",.3) TEXT.show(text.royale_remain:gsub("$1",#PLY_ALIVE),640,200,40,"beat",.3)
if GAME.stage==2 then if GAME.stage==2 then
spd=30 spd=30
elseif GAME.stage==3 then elseif GAME.stage==3 then
spd=15 spd=15
for _,P in next,PLAYERS.alive do for _,P in next,PLY_ALIVE do
P.gameEnv.garbageSpeed=.6 P.gameEnv.garbageSpeed=.6
end end
if PLAYERS[1].alive then BGM.play("cruelty")end if PLAYERS[1].alive then BGM.play("cruelty")end
elseif GAME.stage==4 then elseif GAME.stage==4 then
spd=10 spd=10
for _,P in next,PLAYERS.alive do for _,P in next,PLY_ALIVE do
P.gameEnv.pushSpeed=3 P.gameEnv.pushSpeed=3
end end
elseif GAME.stage==5 then elseif GAME.stage==5 then
spd=5 spd=5
for _,P in next,PLAYERS.alive do for _,P in next,PLY_ALIVE do
P.gameEnv.garbageSpeed=1 P.gameEnv.garbageSpeed=1
end end
elseif GAME.stage==6 then elseif GAME.stage==6 then
spd=3 spd=3
if PLAYERS[1].alive then BGM.play("final")end if PLAYERS[1].alive then BGM.play("final")end
end end
for _,P in next,PLAYERS.alive do for _,P in next,PLY_ALIVE do
P.gameEnv.drop=spd P.gameEnv.drop=spd
end end
if GAME.curMode.name:find("_u")then if GAME.curMode.name:find("_u")then
for i=1,#PLAYERS.alive do for i=1,#PLY_ALIVE do
local P=PLAYERS.alive[i] local P=PLY_ALIVE[i]
P.gameEnv.drop=int(P.gameEnv.drop*.3) P.gameEnv.drop=int(P.gameEnv.drop*.3)
if P.gameEnv.drop==0 then if P.gameEnv.drop==0 then
P.curY=P.ghoY P.curY=P.ghoY
@@ -537,9 +537,7 @@ function destroyPlayers()--Destroy all player objects, restore freerows and free
end end
PLAYERS[i]=nil PLAYERS[i]=nil
end end
for i=#PLAYERS.alive,1,-1 do TABLE.clear(PLY_ALIVE)
PLAYERS.alive[i]=nil
end
collectgarbage() collectgarbage()
end end
function restoreVirtualkey() function restoreVirtualkey()
@@ -611,7 +609,7 @@ function loadGame(M,ifQuickPlay,ifNet)--Load a mode and go to game scene
end end
end end
function initPlayerPosition(sudden)--Set initial position for every player function initPlayerPosition(sudden)--Set initial position for every player
local L=PLAYERS.alive local L=PLY_ALIVE
if not sudden then if not sudden then
for i=1,#L do for i=1,#L do
L[i]:setPosition(640,#L<=5 and 360 or -62,0) L[i]:setPosition(640,#L<=5 and 360 or -62,0)
@@ -715,7 +713,7 @@ do--function resetGameData(args)
end end
return S return S
end end
function resetGameData(args,playerData,seed) function resetGameData(args,seed)
if not args then args=""end if not args then args=""end
if PLAYERS[1]and not GAME.replaying and(GAME.frame>400 or GAME.result)then if PLAYERS[1]and not GAME.replaying and(GAME.frame>400 or GAME.result)then
mergeStat(STAT,PLAYERS[1].stat) mergeStat(STAT,PLAYERS[1].stat)
@@ -744,7 +742,7 @@ do--function resetGameData(args)
end end
destroyPlayers() destroyPlayers()
GAME.curMode.load(playerData) GAME.curMode.load()
initPlayerPosition(args:find("q")) initPlayerPosition(args:find("q"))
restoreVirtualkey() restoreVirtualkey()
if GAME.modeEnv.task then if GAME.modeEnv.task then
@@ -958,7 +956,7 @@ do--function saveRecording()
os.date("%Y/%m/%d %A %H:%M:%S\n").. os.date("%Y/%m/%d %A %H:%M:%S\n")..
GAME.curModeName.."\n".. GAME.curModeName.."\n"..
VERSION_NAME.."\n".. VERSION_NAME.."\n"..
(USER.name or"Player") (USER.username or"Player")
local fileBody= local fileBody=
GAME.seed.."\n".. GAME.seed.."\n"..
JSON.encode(GAME.setting).."\n".. JSON.encode(GAME.setting).."\n"..
@@ -982,25 +980,26 @@ end
--Game draw --Game draw
do--function drawFWM() do--function drawFWM()
local m={ local m={
"\230\184\184\230\136\143\228\189\156\232\128\133\58\77\114\90\95\50\54\10\228\187\187\228\189\149\232\167\134\233\162\145\47\231\155\180\230\146\173\228\184\141\229\190\151\229\135\186\231\142\176\230\173\164\230\176\180\229\141\176\10\228\187\187\228\189\149\232\189\172\232\191\176\229\163\176\230\152\142\230\151\160\230\149\136", string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
"\230\184\184\230\136\143\228\189\156\232\128\133\58\77\114\90\95\50\54\10\228\187\187\228\189\149\232\167\134\233\162\145\47\231\155\180\230\146\173\228\184\141\229\190\151\229\135\186\231\142\176\230\173\164\230\176\180\229\141\176\10\228\187\187\228\189\149\232\189\172\232\191\176\229\163\176\230\152\142\230\151\160\230\149\136", string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
"\230\184\184\230\136\143\228\189\156\232\128\133\58\77\114\90\95\50\54\10\228\187\187\228\189\149\232\167\134\233\162\145\47\231\155\180\230\146\173\228\184\141\229\190\151\229\135\186\231\142\176\230\173\164\230\176\180\229\141\176\10\228\187\187\228\189\149\232\189\172\232\191\176\229\163\176\230\152\142\230\151\160\230\149\136", string.char(230,184,184,230,136,143,228,189,156,232,128,133,58,77,114,90,95,50,54,10,228,187,187,228,189,149,232,167,134,233,162,145,47,231,155,180,230,146,173,228,184,141,229,190,151,229,135,186,231,142,176,230,173,164,230,176,180,229,141,176,10,228,187,187,228,189,149,232,189,172,232,191,176,229,163,176,230,152,142,230,151,160,230,149,136),
"\65\117\116\104\111\114\58\32\77\114\90\95\50\54\n\82\101\99\111\114\100\105\110\103\115\32\99\111\110\116\97\105\110\105\110\103\32\116\104\105\115\n\119\97\116\101\114\109\97\114\107\32\97\114\101\32\117\110\97\117\116\104\111\114\105\122\101\100", string.char(65,117,116,104,111,114,58,32,77,114,90,95,50,54,10,82,101,99,111,114,100,105,110,103,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,105,115,10,119,97,116,101,114,109,97,114,107,32,97,114,101,32,117,110,97,117,116,104,111,114,105,122,101,100),
"\67\114\195\169\97\116\101\117\114\32\100\117\32\106\101\117\58\32\77\114\90\95\50\54\10\69\110\114\101\103\105\115\116\114\101\109\101\110\116\32\110\111\110\32\97\117\116\111\114\105\115\195\169\10\99\111\110\116\101\110\97\110\116\32\99\101\32\102\105\108\105\103\114\97\110\101", string.char(67,114,195,169,97,116,101,117,114,32,100,117,32,106,101,117,58,32,77,114,90,95,50,54,10,69,110,114,101,103,105,115,116,114,101,109,101,110,116,32,110,111,110,32,97,117,116,111,114,105,115,195,169,10,99,111,110,116,101,110,97,110,116,32,99,101,32,102,105,108,105,103,114,97,110,101),
"\65\117\116\111\114\58\32\77\114\90\95\50\54\10\71\114\97\98\97\99\105\195\179\110\32\110\111\32\97\117\116\111\114\105\122\97\100\97\32\113\117\101\10\99\111\110\116\105\101\110\101\32\101\115\116\97\32\109\97\114\99\97\32\100\101\32\97\103\117\97", string.char(65,117,116,111,114,58,32,77,114,90,95,50,54,10,71,114,97,98,97,99,105,195,179,110,32,110,111,32,97,117,116,111,114,105,122,97,100,97,32,113,117,101,10,99,111,110,116,105,101,110,101,32,101,115,116,97,32,109,97,114,99,97,32,100,101,32,97,103,117,97),
"\65\117\116\111\114\32\100\111\32\106\111\103\111\58\32\77\114\90\95\50\54\10\71\114\97\118\97\195\167\195\181\101\115\32\99\111\110\116\101\110\100\111\32\101\115\116\97\32\77\97\114\99\97\10\100\101\32\195\161\103\117\97\32\110\195\163\111\32\115\195\163\111\32\97\117\116\111\114\105\122\97\100\97\115", string.char(65,117,116,111,114,32,100,111,32,106,111,103,111,58,32,77,114,90,95,50,54,10,71,114,97,118,97,195,167,195,181,101,115,32,99,111,110,116,101,110,100,111,32,101,115,116,97,32,77,97,114,99,97,10,100,101,32,195,161,103,117,97,32,110,195,163,111,32,115,195,163,111,32,97,117,116,111,114,105,122,97,100,97,115),
"\65\117\116\104\111\114\58\32\77\114\90\95\50\54\10\82\101\99\111\114\100\105\110\103\115\32\99\111\110\116\97\105\110\105\110\103\32\116\104\105\115\10\119\97\116\101\114\109\97\114\107\32\97\114\101\32\117\110\97\117\116\104\111\114\105\122\101\100", string.char(65,117,116,104,111,114,58,32,77,114,90,95,50,54,10,82,101,99,111,114,100,105,110,103,115,32,99,111,110,116,97,105,110,105,110,103,32,116,104,105,115,10,119,97,116,101,114,109,97,114,107,32,97,114,101,32,117,110,97,117,116,104,111,114,105,122,101,100),
} }
--你竟然找到了这里!那么在动手之前读读下面这些吧。 --你竟然找到了这里!那么在动手之前读读下面这些吧。
--千万不要为了在网络公共场合发视 频或者直播需要而擅自删除这部分代码! --【魔幻躲关键字搜索警告,看得懂就行】
--录制视 频上传到公共场合(包括但不限于任何视 频平台/论坛/几十个人以上的社区群等)很可能会对Techmino未来的发展有负面影响 --千万不要为了在网络公共场合发视屏或者直播需要而擅自删除这部分代码!
--录制视屏上传到公共场合(包括但不限于任何视屏平台/论坛/几十个人以上的社区群等)很可能会对Techmino未来的发展有负面影响
--如果被TTC发现TTC随时可以用DMCA从法律层面强迫停止开发到时候谁都没得玩。这是真的已经有几个方块这么死了… --如果被TTC发现TTC随时可以用DMCA从法律层面强迫停止开发到时候谁都没得玩。这是真的已经有几个方块这么死了…
--印限制还可以减少低质量视泛滥,也能减轻过多不是真的感兴趣路人玩家入坑可能带来的压力 --印限制还可以减少低质量视泛滥,也能减轻过多不是真的感兴趣路人玩家入坑可能带来的压力
--想发视的话请先向作者申请,描述录制的大致内容,同意了才可以去关闭 --想发视的话请先向作者申请,描述录制的大致内容,同意了才可以去关闭
--等Techmino发展到一定程度之后会解除这个限制 --等Techmino发展到一定程度之后会解除这个限制
--最后,别把藏在这里的东西截图/复制出去哦~ --最后,别把藏在这里的东西截图/复制出去哦~
--感谢您对Techmino的支持 --感谢您对Techmino的支持
local setFont=setFont local setFont,TIME,mStr=setFont,TIME,mStr
function drawFWM() function drawFWM()
local t=TIME() local t=TIME()
setFont(25) setFont(25)
@@ -1051,221 +1050,12 @@ do--function pressKey(k)
return cache[k] return cache[k]
end end
end end
do--lnk_CUS/SETXXX(k) do--CUS/SETXXX(k)
local c,s=CUSTOMENV,SETTING local c,s=CUSTOMENV,SETTING
function lnk_CUSval(k)return function()return c[k] end end function CUSval(k)return function()return c[k]end end
function lnk_SETval(k)return function()return s[k] end end function SETval(k)return function()return s[k]end end
function lnk_CUSrev(k)return function()c[k]=not c[k]end end function CUSrev(k)return function()c[k]=not c[k]end end
function lnk_SETrev(k)return function()s[k]=not s[k]end end function SETrev(k)return function()s[k]=not s[k]end end
function lnk_CUSsto(k)return function(i)c[k]=i end end function CUSsto(k)return function(i)c[k]=i end end
function lnk_SETsto(k)return function(i)s[k]=i end end function SETsto(k)return function(i)s[k]=i end end
end
--Network funcs
do
--[[
register:
if response.message=="OK"then
LOGIN=true
USER.name=res.name
USER.id=res.id
USER.motto=res.motto
USER.avatar=res.avatar
FILE.save(USER,"conf/user","q")
LOG.print(text.registerSuccessed..": "..res.message)
else
LOG.print(text.httpCode..response.code..": "..res.message,"warn")
end
goChatRoom:
if res.message=="OK"then
SCN.go("net_chat")
LOG.print(text.wsSuccessed,"warn")
else
LOG.print(text.wsFailed..": "..connErr,"warn")
end
fetchRooms:
if res.message=="OK"then
rooms=res.room_list
else
LOG.print(text.httpCode..response.code..": "..res.message,"warn")
end
createRoom:
if res.message=="OK"then
LOG.print(text.createRoomSuccessed)
enterRoom(res.room.id)
else
LOG.print(text.httpCode..res.code..": "..res.message,"warn")
end
enterRoom:
if res.message=="OK"then
loadGame("netBattle",true,true)
LOG.print(text.wsSuccessed,"warn")
else
LOG.print(text.wsFailed..": "..connErr,"warn")
end
]]
function TICK_WS_app()
local retryTime=5
while true do
YIELD()
local status=WS.status("app")
if status=="running"then
local message,op=WS.read("app")
if message then
if op=="ping"then
WS.send("app",message,"pong")
elseif op=="close"then
message=JSON.decode(message)
if message then
LOG.print(text.wsClose..message.message,"warn")
end
return
else
local res=JSON.decode(message)
if VERSION_CODE>=res.lowest then
NET.allow_online=true
end
if VERSION_CODE<res.newestCode then
LOG.print(text.oldVersion:gsub("$1",res.newestName),180,COLOR.sky)
end
LOG.print(res.notice,300,COLOR.sky)
end
end
elseif status=="dead"then
retryTime=retryTime-1
if retryTime==0 then return end
for _=1,120 do YIELD()end
WS.connect("app","/app")
end
end
end
function TICK_WS_user()
while true do
YIELD()
local status=WS.status("user")
if status=="running"then
local message,op=WS.read("user")
if message then
if op=="ping"then
WS.send("user",message,"pong")
elseif op=="close"then
message=JSON.decode(message)
if message then
LOG.print(text.wsClose..message.message,"warn")
end
return
else
local res=JSON.decode(message)
if res.message=="Connected"then
LOGIN=true
if res.id then
USER.id=res.id
USER.authToken=res.authToken
NET.try_enter_netmenu=true
WS.send("user",JSON.encode{action=0})
end
FILE.save(USER,"conf/user","q")
LOG.print(text.loginSuccessed)
--Get self infos
WS.send("user",JSON.encode{
action=1,
data={
id=USER.id,
},
})
elseif res.action==0 then
USER.accessToken=res.accessToken
LOG.print(text.accessSuccessed)
if NET.try_enter_netmenu then
NET.try_enter_netmenu=false
SCN.go("net_menu")
end
elseif res.action==1 then
USER.name=res.username
USER.motto=res.motto
USER.avatar=res.avatar
FILE.save(USER,"conf/user")
end
end
end
end
end
end
function TICK_WS_chat()
while true do
YIELD()
local status=WS.status("chat")
if status=="running"then
local message,op=WS.read("chat")
if message then
if op=="ping"then
WS.send("chat",message,"pong")
elseif op=="close"then
message=JSON.decode(message)
if message then
LOG.print(text.wsClose..message.message,"warn")
end
return
else
local res=JSON.decode(message)
--TODO
end
end
end
end
end
function TICK_WS_play()
while true do
YIELD()
local status=WS.status("play")
if status=="running"then
local message,op=WS.read("play")
if message then
if op=="ping"then
WS.send("play",message,"pong")
elseif op=="close"then
message=JSON.decode(message)
if message then
LOG.print(text.wsClose..message.message,"warn")
end
return
else
local res=JSON.decode(message)
--TODO
end
end
end
end
end
function TICK_WS_stream()
while true do
YIELD()
local status=WS.status("stream")
if status=="running"then
local message,op=WS.read("stream")
if message then
if op=="ping"then
WS.send("stream",message,"pong")
elseif op=="close"then
message=JSON.decode(message)
if message then
LOG.print(text.wsClose..message.message,"warn")
end
return
else
local res=JSON.decode(message)
--TODO
end
end
end
end
end
end end

View File

@@ -142,7 +142,9 @@ for i=1,#MODOPT do
end end
--Game tables --Game tables
PLAYERS={alive={}}--Players data PLAYERS={}--Players data
PLY_ALIVE={}
PLY_NET={}
FIELD={}--Field(s) for custom game FIELD={}--Field(s) for custom game
BAG={}--Sequence for custom game BAG={}--Sequence for custom game
MISSION={}--Clearing mission for custom game MISSION={}--Clearing mission for custom game
@@ -220,17 +222,14 @@ GAME={--Global game data
RANKS=FILE.load("conf/unlock")or{sprint_10l=0}--Ranks of modes RANKS=FILE.load("conf/unlock")or{sprint_10l=0}--Ranks of modes
USER=FILE.load("conf/user")or{--User infomation USER=FILE.load("conf/user")or{--User infomation
--Network infos --Network infos
name=false, username=false,
id=false, uid=false,
email=false,
motto=false,
avatar=false,
authToken=false, authToken=false,
accessToken=false,
--Local data --Local data
xp=0,lv=1, xp=0,lv=1,
} }
USERS=FILE.load("conf/users")or{}
SETTING={--Settings SETTING={--Settings
--Tuning --Tuning
das=10,arr=2,dascut=0, das=10,arr=2,dascut=0,
@@ -300,7 +299,7 @@ SETTING={--Settings
VKAlpha=.3, VKAlpha=.3,
} }
local S=FILE.load("conf/settings") local S=FILE.load("conf/settings")
if S then TABLE.add(S,SETTING)end if S then TABLE.update(S,SETTING)end
S=FILE.load("conf/data") S=FILE.load("conf/data")
if S then--Statistics if S then--Statistics
STAT=S STAT=S

View File

@@ -75,7 +75,6 @@ return{
needUpdate="Newer version required!", needUpdate="Newer version required!",
notFinished="Coming soon!", notFinished="Coming soon!",
httpCode="HTTP status code",
jsonError="JSON error", jsonError="JSON error",
noUsername="Please specify a username.", noUsername="Please specify a username.",
@@ -90,10 +89,8 @@ return{
accessFailed="Access Denied.", accessFailed="Access Denied.",
wsSuccessed="WebSocket: Connected.", wsSuccessed="WebSocket: Connected.",
wsFailed="WebSocket: Connection Failed.", wsFailed="WebSocket: Connection Failed.",
wsDisconnected="WebSocket: Disconnected.",
wsNoConn="WebSocket: Not Connected.",
wsClose="WebSocket Closed: ", wsClose="WebSocket Closed: ",
waitNetTask="Connecting. Please wait...", netTimeout="Network connection timeout",
createRoomTooFast="Hold on there! We can't handle this fast!", createRoomTooFast="Hold on there! We can't handle this fast!",
createRoomSuccessed="Room successfully created!", createRoomSuccessed="Room successfully created!",
@@ -106,7 +103,6 @@ return{
chatStart="------Beginning of log------", chatStart="------Beginning of log------",
chatHistory="------New messages below------", chatHistory="------New messages below------",
noRooms="Such emptiness much void, come back later?",
roomsCreateFailed="Failed to create room.", roomsCreateFailed="Failed to create room.",
roomsFetchFailed="Failed to fetch room list.", roomsFetchFailed="Failed to fetch room list.",
@@ -252,7 +248,9 @@ return{
chat="Chat", chat="Chat",
}, },
net_rooms={ net_rooms={
fresh="Reresh", refreshing="Refreshing Rooms",
noRoom="Such emptiness much void, come back later?",
refresh="Refresh",
new="New Room", new="New Room",
join="Join", join="Join",
up="", up="",

View File

@@ -76,7 +76,6 @@ return{
-- needUpdate="Newer version required!", -- needUpdate="Newer version required!",
-- notFinished="Coming soon!", -- notFinished="Coming soon!",
httpCode="Code de statut Http",
jsonError="Erreur json", jsonError="Erreur json",
noUsername="Entrez votre nom d'utilisateur", noUsername="Entrez votre nom d'utilisateur",
@@ -91,10 +90,8 @@ return{
accessFailed="Autorisation échouée", accessFailed="Autorisation échouée",
wsSuccessed="WebSocket: connecté", wsSuccessed="WebSocket: connecté",
wsFailed="WebSocket: connection échouée", wsFailed="WebSocket: connection échouée",
wsDisconnected="WebSocket: déconnecté", -- wsClose="WebSocket Closed: ",
wsNoConn="WebSocket: vous n'êtes pas connecté", -- netTimeout="Network connection timeout",
wsError="Erreur WebSocket : ",
waitNetTask="Connexion, veuillez patienter",
createRoomTooFast="Vous avez créé un salon trop rapidement !", createRoomTooFast="Vous avez créé un salon trop rapidement !",
createRoomSuccessed="Salon créé avec succès !", createRoomSuccessed="Salon créé avec succès !",
@@ -107,7 +104,6 @@ return{
chatStart="--------Début des logs--------", chatStart="--------Début des logs--------",
chatHistory="-Nouveaux messages en dessous-", chatHistory="-Nouveaux messages en dessous-",
noRooms="Aucun salon actuellement",
roomsCreateFailed="Echec de la création du salon", roomsCreateFailed="Echec de la création du salon",
roomsFetchFailed="Echec de la récupération des salons", roomsFetchFailed="Echec de la récupération des salons",
@@ -186,7 +182,7 @@ return{
simple-love-lights [dylhunn] simple-love-lights [dylhunn]
]], ]],
support="Aider le créateur", support="Aider le créateur",
group="Groupe QQ officiel (si non piraté) : 913154753", group="Groupe QQ officiel : 913154753",
WidgetText={ WidgetText={
main={ main={
-- offline="Solo", -- offline="Solo",
@@ -225,8 +221,9 @@ return{
chat="Chat", chat="Chat",
}, },
net_rooms={ net_rooms={
fresh="Fresh", -- refreshing="Refreshing Rooms",
new="Nouveau salon", noRoom="Aucun salon actuellement",
-- refresh="Refresh",
join="Rejoindre", join="Rejoindre",
up="", up="",
down="", down="",

View File

@@ -75,7 +75,6 @@ return{
-- needUpdate="Newer version required!", -- needUpdate="Newer version required!",
-- notFinished="Coming soon!", -- notFinished="Coming soon!",
-- httpCode="Http status code",
jsonError="Json error", jsonError="Json error",
noUsername="Insira seu nome de usuário", noUsername="Insira seu nome de usuário",
@@ -90,10 +89,8 @@ return{
accessFailed="Falha na autorização", accessFailed="Falha na autorização",
wsSuccessed="WebSocket: conectado", wsSuccessed="WebSocket: conectado",
wsFailed="WebSocket: falha na conexão", wsFailed="WebSocket: falha na conexão",
wsDisconnected="WebSocket: desconectado",
wsNoConn="WebSocket: você não está conectado",
wsClose="WebSocket closed: ", wsClose="WebSocket closed: ",
waitNetTask="Conectando, aguarde", -- netTimeout="Network connection timeout",
-- createRoomTooFast="Create room too fast!", -- createRoomTooFast="Create room too fast!",
-- createRoomSuccessed="Room successfully created!", -- createRoomSuccessed="Room successfully created!",
@@ -106,7 +103,6 @@ return{
chatStart="------Começo do log------", chatStart="------Começo do log------",
chatHistory="------Novas mensagens abaixo------", chatHistory="------Novas mensagens abaixo------",
noRooms="Nenhuma sala agora",
-- roomsCreateFailed="Failed to create room", -- roomsCreateFailed="Failed to create room",
roomsFetchFailed="Falha ao buscar salas", roomsFetchFailed="Falha ao buscar salas",
@@ -252,7 +248,9 @@ return{
chat="Chat", chat="Chat",
}, },
net_rooms={ net_rooms={
fresh="Fresh", -- refreshing="Refreshing Rooms",
noRoom="Nenhuma sala agora",
-- refresh="Refresh",
-- new="New room", -- new="New room",
-- join="Join", -- join="Join",
up="", up="",

View File

@@ -76,11 +76,9 @@ return{
-- needUpdate="Newer version required!", -- needUpdate="Newer version required!",
-- notFinished="Coming soon!", -- notFinished="Coming soon!",
-- httpCode="Http status code",
-- jsonError="Json error", -- jsonError="Json error",
noUsername="Por favor ingresa un nombre de usuario", noUsername="Por favor ingresa un nombre de usuario",
-- wrongEmail="Wrong email address", -- wrongEmail="Wrong email address",
noPassword="Por favor ingresa una contraseña", noPassword="Por favor ingresa una contraseña",
diffPassword="Las contraseñas no coinciden", diffPassword="Las contraseñas no coinciden",
@@ -92,10 +90,8 @@ return{
-- accessFailed="Authorization failed", -- accessFailed="Authorization failed",
-- wsSuccessed="WebSocket: connected", -- wsSuccessed="WebSocket: connected",
-- wsFailed="WebSocket: connection failed", -- wsFailed="WebSocket: connection failed",
-- wsDisconnected="WebSocket: disconnected",
-- wsNoConn="WebSocket: you are not connected",
-- wsClose="WebSocket closed: ", -- wsClose="WebSocket closed: ",
-- waitNetTask="Connecting, please wait", -- netTimeout="Network connection timeout",
-- createRoomTooFast="Create room too fast!", -- createRoomTooFast="Create room too fast!",
-- createRoomSuccessed="Room successfully created!", -- createRoomSuccessed="Room successfully created!",
@@ -108,7 +104,6 @@ return{
-- chatStart="------Beginning of log------", -- chatStart="------Beginning of log------",
-- chatHistory="------New messages below------", -- chatHistory="------New messages below------",
-- noRooms="No Rooms Now",
-- roomsCreateFailed="Failed to create room", -- roomsCreateFailed="Failed to create room",
-- roomsFetchFailed="Failed to fetch rooms", -- roomsFetchFailed="Failed to fetch rooms",
@@ -188,7 +183,7 @@ return{
simple-love-lights [dylhunn] simple-love-lights [dylhunn]
]], ]],
support="Apoyen al Autor", support="Apoyen al Autor",
group="Grupo Oficial de QQ (si no lo hackean) : 913154753", group="Grupo Oficial de QQ : 913154753",
WidgetText={ WidgetText={
main={ main={
-- offline="Single", -- offline="Single",
@@ -231,7 +226,9 @@ return{
-- chat="Chat", -- chat="Chat",
}, },
net_rooms={ net_rooms={
-- fresh="Fresh", -- refreshing="Refreshing Rooms",
-- noRoom="No Rooms Now",
-- refresh="Refresh",
-- new="New room", -- new="New room",
-- join="Join", -- join="Join",
up="", up="",

View File

@@ -83,11 +83,12 @@ return{
"□!!~~~,□□□□X", "□!!~~~,□□□□X",
"□!!==*/*/*/*~", "□!!==*/*/*/*~",
"", "",
"bug reports/suggestions, sent to the author's testing group or email ~", "Powered by LÖVE/love2d",
"This is a free download available only through discord.gg/f9pUvkh", "Any suggestions or bug reports are appreciated!",
"The game downloaded from other sources may contain viruses,", "Make sure to only obtain the game from official sources;",
"and only vibration & networking permissions are needed for mobile versions!", "We can't make sure you're safe if you got it elsewhere.",
"The author is not responsible for any losses from modifying the game.", "The author is not responsible for any modified binaries.",
"While the game is free, donations are appreciated."
}, },
WidgetText={ WidgetText={
main={ main={

View File

@@ -75,7 +75,6 @@ return{
needUpdate="此功能需要更新游戏!", needUpdate="此功能需要更新游戏!",
notFinished="暂未完成,敬请期待!", notFinished="暂未完成,敬请期待!",
httpCode="Http码",
jsonError="json错误", jsonError="json错误",
noUsername="请填写用户名", noUsername="请填写用户名",
@@ -90,10 +89,8 @@ return{
accessFailed="身份验证失败", accessFailed="身份验证失败",
wsSuccessed="WS连接成功", wsSuccessed="WS连接成功",
wsFailed="WS连接失败", wsFailed="WS连接失败",
wsDisconnected="WS连接断开",
wsNoConn="WS未连接",
wsClose="WS被断开: ", wsClose="WS被断开: ",
waitNetTask="正在连接,请稍候", netTimeout="网络连接超时",
createRoomTooFast="创建房间太快啦,等等吧", createRoomTooFast="创建房间太快啦,等等吧",
createRoomSuccessed="创建房间成功!", createRoomSuccessed="创建房间成功!",
@@ -106,7 +103,6 @@ return{
chatStart="------消息的开头------", chatStart="------消息的开头------",
chatHistory="------以上是历史消息------", chatHistory="------以上是历史消息------",
noRooms="一个房间都没有哎...",
roomsCreateFailed="创建房间失败", roomsCreateFailed="创建房间失败",
roomsFetchFailed="拉取房间列表失败", roomsFetchFailed="拉取房间列表失败",
@@ -177,7 +173,7 @@ return{
"", "",
"使用LOVE2D引擎", "使用LOVE2D引擎",
"错误或者建议请附带截图发送到内测群或者作者邮箱~", "错误或者建议请附带截图发送到内测群或者作者邮箱~",
"仅通过内测群1127702001进行免费下载/更新", "仅通过内测qq群/discord群进行免费下载/更新",
"其他渠道获得游戏皆有被修改/加广告/植入病毒的风险,程序只申请了振动&联网权限!", "其他渠道获得游戏皆有被修改/加广告/植入病毒的风险,程序只申请了振动&联网权限!",
"若由于被修改的本游戏产生的各种损失作者不负责(我怎么负责啊跟我有啥关系)", "若由于被修改的本游戏产生的各种损失作者不负责(我怎么负责啊跟我有啥关系)",
"请从正规途径获得最新版,游戏现为免费,不过有打赏当然感谢啦~", "请从正规途径获得最新版,游戏现为免费,不过有打赏当然感谢啦~",
@@ -209,7 +205,7 @@ return{
simple-love-lights [dylhunn] simple-love-lights [dylhunn]
]], ]],
support="支持作者", support="支持作者",
group="官方QQ群(如果没有被暗改的话就是这个):913154753", group="官方QQ群:913154753",
WidgetText={ WidgetText={
main={ main={
offline="单机游戏", offline="单机游戏",
@@ -252,7 +248,9 @@ return{
chat="聊天室", chat="聊天室",
}, },
net_rooms={ net_rooms={
fresh="刷新", refreshing="刷新房间列表中",
noRoom="一个房间都没有哎...",
refresh="刷新",
new="创建房间", new="创建房间",
join="加入", join="加入",
up="", up="",

View File

@@ -71,7 +71,7 @@ return{
PLY.newAIPlayer(2,AIBUILDER("CC",2*AIlevel-1,math.floor(AIlevel*.5+1),true,20000+5000*AIlevel)) PLY.newAIPlayer(2,AIBUILDER("CC",2*AIlevel-1,math.floor(AIlevel*.5+1),true,20000+5000*AIlevel))
end end
for _,P in next,PLAYERS.alive do for _,P in next,PLY_ALIVE do
setField(P,1) setField(P,1)
end end
end, end,

View File

@@ -9,17 +9,15 @@ return{
task=function(P)P.modeData.target=50 end, task=function(P)P.modeData.target=50 end,
dropPiece=function(P) dropPiece=function(P)
if P.stat.row>=P.modeData.target then if P.stat.row>=P.modeData.target then
local T=P.modeData.target if P.modeData.target==50 then
if T==50 then
P.gameEnv.drop=.25 P.gameEnv.drop=.25
P.modeData.target=100 P.modeData.target=100
SFX.play("reach") SFX.play("reach")
elseif T==100 then elseif P.modeData.target==100 then
P:set20G(true) P:set20G(true)
P.modeData.target=200 P.modeData.target=200
SFX.play("reach") SFX.play("reach")
else else
P.stat.row=200
P:win("finish") P:win("finish")
end end
end end

View File

@@ -8,14 +8,15 @@ return{
drop=60,wait=8,fall=20, drop=60,wait=8,fall=20,
task=function(P)P.modeData.target=10 end, task=function(P)P.modeData.target=10 end,
dropPiece=function(P) dropPiece=function(P)
local T=P.modeData.target if P.stat.row<180 then
if P.stat.row>=T then P.stat.row=180
if T==200 then end
if P.stat.row>=P.modeData.target then
if P.modeData.target==200 then
P:win("finish") P:win("finish")
else else
T=T+10 P.gameEnv.drop=dropSpeed[P.modeData.target/10]
P.gameEnv.drop=dropSpeed[T/10] P.modeData.target=P.modeData.target+10
P.modeData.target=T
SFX.play("reach") SFX.play("reach")
end end
end end
@@ -31,7 +32,7 @@ return{
mesDisp=function(P) mesDisp=function(P)
setFont(45) setFont(45)
mStr(P.stat.row,69,320) mStr(P.stat.row,69,320)
mStr(P.modeData.target+10,69,370) mStr(P.modeData.target,69,370)
gc.rectangle("fill",25,375,90,4) gc.rectangle("fill",25,375,90,4)
end, end,
score=function(P)return{math.min(P.stat.row,200),P.stat.time}end, score=function(P)return{math.min(P.stat.row,200),P.stat.time}end,

View File

@@ -4,15 +4,16 @@ return{
drop=30, drop=30,
freshLimit=15, freshLimit=15,
noMod=true, noMod=true,
bg="space",
}, },
load=function(playerData) load=function()
PLY.newPlayer(1) PLY.newPlayer(1)
local N=2 local N=2
for i=1,#playerData do for i=1,#PLY_NET do
if playerData[i].id==tostring(USER.id)then if PLY_NET[i].uid==USER.uid then
PLAYERS[1].subID=playerData[1].sid PLAYERS[1].subID=PLY_NET[1].sid
else else
PLY.newRemotePlayer(N,false,playerData[i]) PLY.newRemotePlayer(N,false,PLY_NET[i])
N=N+1 N=N+1
end end
end end

View File

@@ -1,5 +1,5 @@
local function update_round(P) local function update_round(P)
if #PLAYERS.alive>1 then if #PLY_ALIVE>1 then
P.control=false P.control=false
local ID=P.id local ID=P.id
repeat repeat

View File

@@ -1,5 +1,5 @@
local function update_round(P) local function update_round(P)
if #PLAYERS.alive>1 then if #PLY_ALIVE>1 then
P.control=false P.control=false
local ID=P.id local ID=P.id
repeat repeat

View File

@@ -1,5 +1,5 @@
local function update_round(P) local function update_round(P)
if #PLAYERS.alive>1 then if #PLY_ALIVE>1 then
P.control=false P.control=false
local ID=P.id local ID=P.id
repeat repeat

View File

@@ -1,5 +1,5 @@
local function update_round(P) local function update_round(P)
if #PLAYERS.alive>1 then if #PLY_ALIVE>1 then
P.control=false P.control=false
local ID=P.id local ID=P.id
repeat repeat

View File

@@ -1,5 +1,5 @@
local function update_round(P) local function update_round(P)
if #PLAYERS.alive>1 then if #PLY_ALIVE>1 then
P.control=false P.control=false
local ID=P.id local ID=P.id
repeat repeat

View File

@@ -59,7 +59,7 @@ return{
end, end,
mesDisp=function(P) mesDisp=function(P)
setFont(35) setFont(35)
mStr(#PLAYERS.alive.."/49",69,175) mStr(#PLY_ALIVE.."/49",69,175)
mStr(P.modeData.ko,80,215) mStr(P.modeData.ko,80,215)
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222) gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
setFont(20) setFont(20)

View File

@@ -59,7 +59,7 @@ return{
end, end,
mesDisp=function(P) mesDisp=function(P)
setFont(35) setFont(35)
mStr(#PLAYERS.alive.."/49",69,175) mStr(#PLY_ALIVE.."/49",69,175)
mStr(P.modeData.ko,80,215) mStr(P.modeData.ko,80,215)
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222) gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
setFont(20) setFont(20)

View File

@@ -59,7 +59,7 @@ return{
end, end,
mesDisp=function(P) mesDisp=function(P)
setFont(35) setFont(35)
mStr(#PLAYERS.alive.."/49",69,175) mStr(#PLY_ALIVE.."/49",69,175)
mStr(P.modeData.ko,80,215) mStr(P.modeData.ko,80,215)
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222) gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
setFont(20) setFont(20)

View File

@@ -59,7 +59,7 @@ return{
end, end,
mesDisp=function(P) mesDisp=function(P)
setFont(35) setFont(35)
mStr(#PLAYERS.alive.."/99",69,175) mStr(#PLY_ALIVE.."/99",69,175)
mStr(P.modeData.ko,80,215) mStr(P.modeData.ko,80,215)
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222) gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
setFont(20) setFont(20)

View File

@@ -59,7 +59,7 @@ return{
end, end,
mesDisp=function(P) mesDisp=function(P)
setFont(35) setFont(35)
mStr(#PLAYERS.alive.."/99",69,175) mStr(#PLY_ALIVE.."/99",69,175)
mStr(P.modeData.ko,80,215) mStr(P.modeData.ko,80,215)
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222) gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
setFont(20) setFont(20)

View File

@@ -59,7 +59,7 @@ return{
end, end,
mesDisp=function(P) mesDisp=function(P)
setFont(35) setFont(35)
mStr(#PLAYERS.alive.."/99",69,175) mStr(#PLY_ALIVE.."/99",69,175)
mStr(P.modeData.ko,80,215) mStr(P.modeData.ko,80,215)
gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222) gc.draw(drawableText.ko,60-drawableText.ko:getWidth(),222)
setFont(20) setFont(20)

434
parts/net.lua Normal file
View File

@@ -0,0 +1,434 @@
local data=love.data
local ins,rem=table.insert,table.remove
local NET={
login=false,
allow_online=false,
roomList={},
accessToken=false,
rid=false,
rsid=false,
}
local mesType={
Connect=true,
Self=true,
Broadcast=true,
Private=true,
Server=true,
}
--Lock & Unlock submodule
local locks={}
local function _lock(name,T)
if locks[name]and TIME()<locks[name]then
return false
else
locks[name]=TIME()+(T or 1e99)
return true
end
end
local function _unlock(name)
locks[name]=false
end
function NET.getLock(name)
return locks[name]
end
--Parse json message
local function _parse(res)
res=JSON.decode(res)
if res then
if mesType[res.type]then
return res
else
LOG.print(
"WS error:"..(
res.type and(
res.reason and res.type..": "..res.reason or
res.type
)or
"[NO Message]"
),
"warning")
end
end
end
--wsEvent
function NET.wsCloseMessage(message)
local mes=JSON.decode(message)
if mes then
LOG.print(("%s [%s] %s"):format(text.wsClose,mes.type or"unknown type",mes.reason or""),"warn")
else
LOG.print(text.wsClose.."","warn")
end
end
--Account
function NET.pong(wsName,message)
WS.send(wsName,message,"pong")
end
function NET.getAccessToken()
if _lock("accessToken")then
WS.send("user",JSON.encode{action=0})
end
end
function NET.getUserInfo(id,ifDetail)
WS.send("user",JSON.encode{
action=1,
data={
id=id or USER.uid,
detailed=ifDetail or false,
},
})
end
function NET.storeUserInfo(res)
local user=USERS[res.uid]
if not user then
user={}
user.email=res.email
user.name=res.username
USERS[res.uid]=user
else
user.email=res.email
user.name=res.username
if not user.motto then user.motto=res.motto end
if not user.avatar then user.avatar=res.avatar end
end
--Get own name
if res.uid==USER.uid then
USER.username=res.username
FILE.save(USER,"conf/user")
end
-- FILE.save(USERS,"conf/users")
end
--Room
function NET.fetchRoom()
if _lock("fetchRoom")then
WS.send("play",JSON.encode{
action=0,
data={
type=nil,
begin=0,
count=10,
}
})
end
end
function NET.createRoom()
if _lock("enterRoom")then
WS.send("play",JSON.encode{
action=1,
data={
type="classic",
name=(USER.username or"???").."'s room",
password=nil,
config=dumpBasicConfig(),
}
})
end
end
function NET.enterRoom(roomID,password)
if _lock("enterRoom")then
NET.rid=roomID
WS.send("play",JSON.encode{
action=2,
data={
rid=roomID,
config=dumpBasicConfig(),
password=password,
}
})
end
end
--Play
function NET.wsConnectPlay()
if _lock("connectPlay")then
WS.connect("play","/play",JSON.encode{
uid=USER.uid,
accessToken=NET.accessToken,
})
end
end
function NET.signal_ready()
if _lock("ready")then
WS.send("play",'{"action":6,"data":{"ready":true}}')
end
end
function NET.signal_quit()
WS.send("play",'{"action":3}')
end
function NET.wsConnectStream()
if _lock("connectStream")then
WS.connect("stream","/stream",JSON.encode{
uid=USER.uid,
accessToken=NET.accessToken,
rid=NET.rsid,
})
end
end
function NET.uploadRecStream(stream)
WS.send("stream",'{"action":2,"data":{"stream":"'..data.encode("string","base64",stream)..'"}}')
end
function NET.signal_die()
WS.send("stream",'{"action":3,"data":{"score":0,"survivalTime":0}}')
end
--Chat
function NET.sendChatMes(mes)
WS.send("chat","T"..data.encode("string","base64",mes))
end
function NET.quitChat()
WS.send("chat","Q")
end
--WS tick funcs
function NET.updateWS_app()
local retryTime=5
while true do
YIELD()
local status=WS.status("app")
if status=="running"then
local message,op=WS.read("app")
if message then
if op=="ping"then
NET.pong("app",message)
elseif op=="pong"then
elseif op=="close"then
NET.wsCloseMessage(message)
return
else
local res=_parse(message)
if res then
if VERSION_CODE>=res.lowest then
NET.allow_online=true
end
if VERSION_CODE<res.newestCode then
LOG.print(text.oldVersion:gsub("$1",res.newestName),180,COLOR.sky)
end
LOG.print(res.notice,300,COLOR.sky)
else
WS.alert("app")
end
end
end
elseif status=="dead"then
retryTime=retryTime-1
if retryTime==0 then return end
for _=1,120 do YIELD()end
WS.connect("app","/app")
end
end
end
function NET.updateWS_user()
while true do
YIELD()
local status=WS.status("user")
if status=="running"then
local message,op=WS.read("user")
if message then
if op=="ping"then
NET.pong("user",message)
elseif op=="pong"then
elseif op=="close"then
NET.wsCloseMessage(message)
return
else
local res=_parse(message)
if res then
if res.type=="Connect"then
NET.login=true
if res.uid then
USER.uid=res.uid
USER.authToken=res.authToken
FILE.save(USER,"conf/user","q")
SCN.back()
end
LOG.print(text.loginSuccessed)
--Get self infos
NET.getUserInfo(USER.uid)
elseif res.action==0 then--Get accessToken
NET.accessToken=res.accessToken
LOG.print(text.accessSuccessed)
NET.wsConnectPlay()
_unlock("accessToken")
elseif res.action==1 then--Get userInfo
NET.storeUserInfo(res)
end
else
WS.alert("user")
end
end
end
end
end
end
function NET.updateWS_play()
while true do
YIELD()
local status=WS.status("play")
if status=="running"then
local message,op=WS.read("play")
if message then
if op=="ping"then
NET.pong("play",message)
elseif op=="pong"then
elseif op=="close"then
NET.wsCloseMessage(message)
return
else
local res=_parse(message)
if res then
if res.type=="Connect"then
SCN.go("net_menu")
_unlock("connectPlay")
elseif res.action==0 then--Fetch rooms
NET.roomList=res.roomList
_unlock("fetchRoom")
elseif res.action==1 then--Create room (not used)
elseif res.action==2 then--Player join
local d=res.data
if res.type=="Self"then
--Create room
TABLE.clear(PLY_NET)
ins(PLY_NET,{
uid=USER.uid,
username=USER.username,
sid=d.sid,
ready=d.ready,
conf=dumpBasicConfig(),
})
if d.players then
for _,p in next,d.players do
ins(PLY_NET,{
uid=p.uid,
username=p.username,
sid=p.sid,
ready=p.ready,
conf=p.config,
})
end
end
loadGame("netBattle",true,true)
_unlock("enterRoom")
else
--Load other players
ins(PLY_NET,{
uid=d.uid,
username=d.username,
sid=d.sid,
ready=d.ready,
conf=d.config,
})
SCN.socketRead("Join",res.data)
end
elseif res.action==3 then--Player leave
for i=1,#PLY_NET do
if PLY_NET[i].uid==data.uid then
rem(PLY_NET,i)
break
end
end
for i=1,#PLAYERS do
if PLAYERS[i].userID==data.uid then
rem(PLAYERS,i)
break
end
end
for i=1,#PLY_ALIVE do
if PLY_ALIVE[i].userID==data.uid then
rem(PLY_ALIVE,i)
break
end
end
SCN.socketRead("Leave",res.data)
elseif res.action==4 then--Player talk
SCN.socketRead("Talk",res.data)
elseif res.action==5 then--Player change settings
SCN.socketRead("Config",res.data)
elseif res.action==6 then--Player ready
SCN.socketRead("Ready",res.data)
_unlock("ready")
elseif res.action==7 then--All ready
elseif res.action==8 then--Sure ready
SCN.socketRead("Set",res.data)
end
else
WS.alert("play")
end
end
end
end
end
end
function NET.updateWS_stream()
while true do
YIELD()
local status=WS.status("stream")
if status=="running"then
local message,op=WS.read("stream")
if message then
if op=="ping"then
NET.pong("stream",message)
elseif op=="pong"then
elseif op=="close"then
NET.wsCloseMessage(message)
return
else
local res=_parse(message)
if res then
if res.type=="Connect"then
--?
elseif res.action==0 then--Game start
SCN.socketRead("Begin",res.data)
elseif res.action==1 then--Game finished
SCN.socketRead("Finish",res.data)
elseif res.action==2 then--Player join
--?
elseif res.action==3 then--Player leave
--?
elseif res.action==4 then--Player died
SCN.socketRead("Die",res.data)
elseif res.action==5 then--Receive stream
SCN.socketRead("Stream",res.data)
end
else
WS.alert("stream")
end
end
end
end
end
end
function NET.updateWS_chat()
while true do
YIELD()
local status=WS.status("chat")
if status=="running"then
local message,op=WS.read("chat")
if message then
if op=="ping"then
NET.pong("chat",message)
elseif op=="pong"then
elseif op=="close"then
NET.wsCloseMessage(message)
return
else
local res=_parse(message)
if res then
--TODO
else
WS.alert("chat")
end
end
end
end
end
end
return NET

View File

@@ -75,7 +75,7 @@ end
local function newEmptyPlayer(id,mini) local function newEmptyPlayer(id,mini)
local P={id=id} local P={id=id}
PLAYERS[id]=P PLAYERS[id]=P
PLAYERS.alive[id]=P PLY_ALIVE[id]=P
--Inherit functions of Player class --Inherit functions of Player class
for k,v in next,Player do P[k]=v end for k,v in next,Player do P[k]=v end
@@ -134,6 +134,9 @@ local function newEmptyPlayer(id,mini)
P.atker,P.atking,P.lastRecv={} P.atker,P.atking,P.lastRecv={}
--Network-related --Network-related
P.userName="_"
P.userID=-1
P.subID=-1
P.ready=false P.ready=false
P.dropDelay,P.lockDelay=0,0 P.dropDelay,P.lockDelay=0,0
@@ -178,7 +181,7 @@ local function newEmptyPlayer(id,mini)
P.type="none" P.type="none"
P.sound=false P.sound=false
-- P.newNext=false--Coroutine to get new next, loaded in applyGameEnv() -- P.newNext=false--Warped coroutine to get new next, loaded in applyGameEnv()
P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end P.keyPressing={}for i=1,12 do P.keyPressing[i]=false end
P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging P.movDir,P.moving,P.downing=0,0,0--Last move key,DAS charging,downDAS charging
@@ -312,8 +315,8 @@ local function applyGameEnv(P)--Finish gameEnv processing
if ENV.nextCount==0 then ENV.nextPos=false end if ENV.nextCount==0 then ENV.nextPos=false end
P.newNext=coroutine.create(getSeqGen(P)) P.newNext=coroutine.wrap(getSeqGen(P))
assert(coroutine.resume(P.newNext,P,P.gameEnv.seqData)) P.newNext(P,P.gameEnv.seqData)
if P.mini then if P.mini then
ENV.lockFX=false ENV.lockFX=false
@@ -369,7 +372,7 @@ function PLY.newDemoPlayer(id)
} }
P:popNext() P:popNext()
end end
function PLY.newRemotePlayer(id,mini,playerData) function PLY.newRemotePlayer(id,mini,data)
local P=newEmptyPlayer(id,mini) local P=newEmptyPlayer(id,mini)
P.type="remote" P.type="remote"
P.update=PLY.update.remote_alive P.update=PLY.update.remote_alive
@@ -379,13 +382,13 @@ function PLY.newRemotePlayer(id,mini,playerData)
P.stream={} P.stream={}
P.streamProgress=1 P.streamProgress=1
playerData.p=P data.p=P
P.userName=playerData.name P.userID=data.uid
P.userID=playerData.id P.userName=data.username
P.subID=playerData.sid P.subID=data.sid
P.ready=playerData.ready P.ready=data.ready
loadRemoteEnv(P,data.conf)
loadRemoteEnv(P,playerData.conf)
applyGameEnv(P) applyGameEnv(P)
end end
@@ -405,6 +408,9 @@ function PLY.newPlayer(id,mini)
P.type="human" P.type="human"
P.sound=true P.sound=true
P.userID=USER.uid
P.subID=-1
loadGameEnv(P) loadGameEnv(P)
applyGameEnv(P) applyGameEnv(P)
end end

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,7 @@
local max,min=math.max,math.min local max,min=math.max,math.min
local int,abs,rnd=math.floor,math.abs,math.random local int,abs,rnd=math.floor,math.abs,math.random
local rem=table.remove local rem=table.remove
local resume=coroutine.resume local assert,resume,status=assert,coroutine.resume,coroutine.status
local status=coroutine.status
local function updateLine(P)--Attacks, line pushing, cam moving local function updateLine(P)--Attacks, line pushing, cam moving
local bf=P.atkBuffer local bf=P.atkBuffer
@@ -100,16 +99,13 @@ local function updateFXs(P,dt)
TEXT.update(P.bonus) TEXT.update(P.bonus)
end end
end end
local updateTasks do--updateTasks(P) local function updateTasks(P)
local assert=assert local L=P.tasks
function updateTasks(P) for i=#L,1,-1 do
local L=P.tasks local tr=L[i].thread
for i=#L,1,-1 do assert(resume(tr))
local tr=L[i].thread if status(tr)=="dead"then
assert(resume(tr)) rem(L,i)
if status(tr)=="dead"then
rem(L,i)
end
end end
end end
end end
@@ -135,7 +131,7 @@ function update.alive(P,dt)
end end
if GAME.modeEnv.royaleMode then if GAME.modeEnv.royaleMode then
v=P.swappingAtkMode local v=P.swappingAtkMode
if P.keyPressing[9]then if P.keyPressing[9]then
P.swappingAtkMode=min(v+2,30) P.swappingAtkMode=min(v+2,30)
else else
@@ -150,8 +146,8 @@ function update.alive(P,dt)
local C=P.AI_keys local C=P.AI_keys
P.AI_delay=P.AI_delay-1 P.AI_delay=P.AI_delay-1
if not C[1]then if not C[1]then
if status(P.AI_thread)=="suspended"then if P.AI_thread and not pcall(P.AI_thread)then
resume(P.AI_thread) P.AI_thread=false
end end
elseif P.AI_delay<=0 then elseif P.AI_delay<=0 then
P:pressKey(C[1])P:releaseKey(C[1]) P:pressKey(C[1])P:releaseKey(C[1])
@@ -398,7 +394,7 @@ function update.remote_alive(P,dt)
local amount=int(event/0x100)%0x100 local amount=int(event/0x100)%0x100
local time=int(event/0x10000)%0x10000 local time=int(event/0x10000)%0x10000
local line=int(event/0x100000000)%0x10000 local line=int(event/0x100000000)%0x10000
local L=PLAYERS.alive local L=PLY_ALIVE
for i=1,#L do for i=1,#L do
if L[i].subID==sid then if L[i].subID==sid then
P:attack(L[i],amount,time,line,true) P:attack(L[i],amount,time,line,true)
@@ -409,7 +405,7 @@ function update.remote_alive(P,dt)
end end
end end
elseif event>0x1000000000000 then--Receiving lines elseif event>0x1000000000000 then--Receiving lines
local L=PLAYERS.alive local L=PLY_ALIVE
local sid=tostring(event%0x100) local sid=tostring(event%0x100)
for i=1,#L do for i=1,#L do
if L[i].subID==sid then if L[i].subID==sid then

View File

@@ -52,6 +52,7 @@ local function reset()
end end end end
board[rnd(5)][rnd(5)]=2 board[rnd(5)][rnd(5)]=2
fallingTimer=false fallingTimer=false
failPos=false
end end
function scene.sceneInit() function scene.sceneInit()
BG.set("rainbow2") BG.set("rainbow2")
@@ -76,7 +77,8 @@ local function merge()
local connected={{cy,cx}} local connected={{cy,cx}}
local count=1 local count=1
repeat repeat
local y,x=unpack(rem(connected)) local c=rem(connected)
local y,x=c[1],c[2]
if board[y][x]~=0 then if board[y][x]~=0 then
board[y][x]=0 board[y][x]=0
SYSFX.newShade(2,320+x*128-128,40+y*128-128,128,128) SYSFX.newShade(2,320+x*128-128,40+y*128-128,128,128)

View File

@@ -149,14 +149,14 @@ scene.widgetList={
WIDGET.newText{name="noMsn", x=610, y=550,align="L",color="grey",hide=function()return MISSION[1]end}, WIDGET.newText{name="noMsn", x=610, y=550,align="L",color="grey",hide=function()return MISSION[1]end},
--Basic --Basic
WIDGET.newSelector{name="drop", x=170, y=150,w=220,color="orange", list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},disp=lnk_CUSval("drop"),code=lnk_CUSsto("drop")}, WIDGET.newSelector{name="drop", x=170, y=150,w=220,color="orange", list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},disp=CUSval("drop"),code=CUSsto("drop")},
WIDGET.newSelector{name="lock", x=170, y=230,w=220,color="red", list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99}, disp=lnk_CUSval("lock"),code=lnk_CUSsto("lock")}, WIDGET.newSelector{name="lock", x=170, y=230,w=220,color="red", list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99}, disp=CUSval("lock"),code=CUSsto("lock")},
WIDGET.newSelector{name="wait", x=410, y=150,w=220,color="green", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=lnk_CUSval("wait"),code=lnk_CUSsto("wait")}, WIDGET.newSelector{name="wait", x=410, y=150,w=220,color="green", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=CUSval("wait"),code=CUSsto("wait")},
WIDGET.newSelector{name="fall", x=410, y=230,w=220,color="yellow", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=lnk_CUSval("fall"),code=lnk_CUSsto("fall")}, WIDGET.newSelector{name="fall", x=410, y=230,w=220,color="yellow", list={0,1,2,3,4,5,6,7,8,10,15,20,30,60}, disp=CUSval("fall"),code=CUSsto("fall")},
--Else --Else
WIDGET.newSelector{name="bg", x=1070, y=150,w=250,color="yellow",list=BG.getList(),disp=lnk_CUSval("bg"), code=function(i)CUSTOMENV.bg=i BG.set(i)end}, WIDGET.newSelector{name="bg", x=1070, y=150,w=250,color="yellow",list=BG.getList(),disp=CUSval("bg"), code=function(i)CUSTOMENV.bg=i BG.set(i)end},
WIDGET.newSelector{name="bgm", x=1070, y=230,w=250,color="yellow", list=BGM.getList(), disp=lnk_CUSval("bgm"), code=function(i)CUSTOMENV.bgm=i BGM.play(i)end}, WIDGET.newSelector{name="bgm", x=1070, y=230,w=250,color="yellow", list=BGM.getList(), disp=CUSval("bgm"), code=function(i)CUSTOMENV.bgm=i BGM.play(i)end},
--Copy/Paste/Start --Copy/Paste/Start
WIDGET.newButton{name="copy", x=1070, y=310,w=310,h=70,color="lRed", font=25,code=pressKey"cC"}, WIDGET.newButton{name="copy", x=1070, y=310,w=310,h=70,color="lRed", font=25,code=pressKey"cC"},

View File

@@ -15,26 +15,26 @@ scene.widgetList={
WIDGET.newText{name="subTitle", x=530,y=50,font=35,align="L",color="grey"}, WIDGET.newText{name="subTitle", x=530,y=50,font=35,align="L",color="grey"},
--Control --Control
WIDGET.newSlider{name="nextCount", x=200, y=150, w=200,unit=6,disp=lnk_CUSval("nextCount"),code=lnk_CUSsto("nextCount")}, WIDGET.newSlider{name="nextCount", x=200, y=150, w=200,unit=6,disp=CUSval("nextCount"),code=CUSsto("nextCount")},
WIDGET.newSlider{name="holdCount", x=200, y=240, w=200,unit=6,disp=lnk_CUSval("holdCount"),code=lnk_CUSsto("holdCount")}, WIDGET.newSlider{name="holdCount", x=200, y=240, w=200,unit=6,disp=CUSval("holdCount"),code=CUSsto("holdCount")},
WIDGET.newSwitch{name="infHold", x=350, y=340, disp=lnk_CUSval("infHold"), code=lnk_CUSrev("infHold"),hide=function()return CUSTOMENV.holdCount==0 end}, WIDGET.newSwitch{name="infHold", x=350, y=340, disp=CUSval("infHold"), code=CUSrev("infHold"),hide=function()return CUSTOMENV.holdCount==0 end},
WIDGET.newSwitch{name="phyHold", x=350, y=430, disp=lnk_CUSval("phyHold"), code=lnk_CUSrev("phyHold"),hide=function()return CUSTOMENV.holdCount==0 end}, WIDGET.newSwitch{name="phyHold", x=350, y=430, disp=CUSval("phyHold"), code=CUSrev("phyHold"),hide=function()return CUSTOMENV.holdCount==0 end},
--Rule --Rule
WIDGET.newSelector{name="fieldH", x=270, y=520, w=260,color="sky", list=sList.fieldH, disp=lnk_CUSval("fieldH"),code=lnk_CUSsto("fieldH")}, WIDGET.newSelector{name="fieldH", x=270, y=520, w=260,color="sky", list=sList.fieldH, disp=CUSval("fieldH"),code=CUSsto("fieldH")},
WIDGET.newSelector{name="visible", x=840, y=60, w=260,color="lBlue",list=sList.visible, disp=lnk_CUSval("visible"),code=lnk_CUSsto("visible")}, WIDGET.newSelector{name="visible", x=840, y=60, w=260,color="lBlue",list=sList.visible, disp=CUSval("visible"),code=CUSsto("visible")},
WIDGET.newSelector{name="target", x=840, y=160, w=260,color="green",list=sList.target, disp=lnk_CUSval("target"),code=lnk_CUSsto("target")}, WIDGET.newSelector{name="target", x=840, y=160, w=260,color="green",list=sList.target, disp=CUSval("target"),code=CUSsto("target")},
WIDGET.newSelector{name="freshLimit",x=840, y=260, w=260,color="purple",list=sList.freshLimit, disp=lnk_CUSval("freshLimit"),code=lnk_CUSsto("freshLimit")}, WIDGET.newSelector{name="freshLimit",x=840, y=260, w=260,color="purple",list=sList.freshLimit, disp=CUSval("freshLimit"),code=CUSsto("freshLimit")},
WIDGET.newSelector{name="opponent", x=1120, y=60, w=260,color="red", list=sList.opponent, disp=lnk_CUSval("opponent"),code=lnk_CUSsto("opponent")}, WIDGET.newSelector{name="opponent", x=1120, y=60, w=260,color="red", list=sList.opponent, disp=CUSval("opponent"),code=CUSsto("opponent")},
WIDGET.newSelector{name="life", x=1120, y=160, w=260,color="red", list=sList.life, disp=lnk_CUSval("life"),code=lnk_CUSsto("life")}, WIDGET.newSelector{name="life", x=1120, y=160, w=260,color="red", list=sList.life, disp=CUSval("life"),code=CUSsto("life")},
WIDGET.newSelector{name="pushSpeed",x=1120, y=260, w=260,color="red", list=sList.pushSpeed, disp=lnk_CUSval("pushSpeed"),code=lnk_CUSsto("pushSpeed")}, WIDGET.newSelector{name="pushSpeed",x=1120, y=260, w=260,color="red", list=sList.pushSpeed, disp=CUSval("pushSpeed"),code=CUSsto("pushSpeed")},
WIDGET.newSwitch{name="ospin", x=870, y=350, font=30,disp=lnk_CUSval("ospin"), code=lnk_CUSrev("ospin")}, WIDGET.newSwitch{name="ospin", x=870, y=350, font=30,disp=CUSval("ospin"), code=CUSrev("ospin")},
WIDGET.newSwitch{name="fineKill", x=870, y=530, font=20,disp=lnk_CUSval("fineKill"),code=lnk_CUSrev("fineKill")}, WIDGET.newSwitch{name="fineKill", x=870, y=530, font=20,disp=CUSval("fineKill"),code=CUSrev("fineKill")},
WIDGET.newSwitch{name="b2bKill", x=870, y=620, font=20,disp=lnk_CUSval("b2bKill"), code=lnk_CUSrev("b2bKill")}, WIDGET.newSwitch{name="b2bKill", x=870, y=620, font=20,disp=CUSval("b2bKill"), code=CUSrev("b2bKill")},
WIDGET.newSwitch{name="easyFresh", x=1160, y=350, font=20,disp=lnk_CUSval("easyFresh"),code=lnk_CUSrev("easyFresh")}, WIDGET.newSwitch{name="easyFresh", x=1160, y=350, font=20,disp=CUSval("easyFresh"),code=CUSrev("easyFresh")},
WIDGET.newSwitch{name="deepDrop", x=1160, y=440, font=30,disp=lnk_CUSval("deepDrop"),code=lnk_CUSrev("deepDrop")}, WIDGET.newSwitch{name="deepDrop", x=1160, y=440, font=30,disp=CUSval("deepDrop"),code=CUSrev("deepDrop")},
WIDGET.newSwitch{name="bone", x=1160, y=530, disp=lnk_CUSval("bone"), code=lnk_CUSrev("bone")}, WIDGET.newSwitch{name="bone", x=1160, y=530, disp=CUSval("bone"), code=CUSrev("bone")},
WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80, font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80, font=40,code=backScene},
} }

View File

@@ -1,5 +1,5 @@
local gc,sys=love.graphics,love.system local gc,sys=love.graphics,love.system
local ms,kb=love.mouse,love.keyboard local kb=love.keyboard
local max,min,int=math.max,math.min,math.floor local max,min,int=math.max,math.min,math.floor
local ins,rem=table.insert,table.remove local ins,rem=table.insert,table.remove
@@ -9,7 +9,8 @@ local FIELD=FIELD
local scene={} local scene={}
local sure local sure
local pen--Pen type local penColor--Pen color
local penMode--Pen mode (false=unavailable, else=mouse button)
local penX,penY--Pen position local penX,penY--Pen position
local demo--If show x local demo--If show x
local page local page
@@ -54,6 +55,7 @@ local minoPosCode={
local SPmode local SPmode
local SPlist={}--Smart pen path list local SPlist={}--Smart pen path list
local function SPpath(x,y) local function SPpath(x,y)
if not penMode then return end
for i=1,#SPlist do for i=1,#SPlist do
if x==SPlist[i][1]and y==SPlist[i][2]then if x==SPlist[i][1]and y==SPlist[i][2]then
return return
@@ -61,8 +63,7 @@ local function SPpath(x,y)
end end
ins(SPlist,{x,y}) ins(SPlist,{x,y})
if #SPlist==1 then if #SPlist==1 then
local start=FIELD[page][y][x] SPmode=FIELD[page][y][x]==0 and 0 or 1
SPmode=start==0 and 0 or 1
end end
end end
local function SPdraw() local function SPdraw()
@@ -98,99 +99,88 @@ local function SPdraw()
end end
end end
SPlist={} SPlist={}
SPmode=0
end end
function scene.sceneInit() function scene.sceneInit()
sure=0 sure=0
pen=1 penColor=1
penMode=false
penX,penY=1,1 penX,penY=1,1
demo=false demo=false
page=1 page=1
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end end
function scene.mouseMove(x,y) function scene.mouseMove(x,y)
local sx,sy=int((x-200)/30)+1,20-int((y-60)/30) local sx,sy=int((x-200)/30)+1,20-int((y-60)/30)
if sx<1 or sx>10 then sx=nil end if sx>=1 and sx<=10 and sy>=1 and sy<=20 then
if sy<1 or sy>20 then sy=nil end penX,penY=sx,sy
penX,penY=sx,sy if penMode then
if ms.isDown(1,2,3)then if penColor==-2 and penMode==1 then
if sx and sy then SPpath(sx,sy)
if pen==-2 then
if ms.isDown(1)then
SPpath(sx,sy)
else
FIELD[page][sy][sx]=-1
end
else else
FIELD[page][sy][sx]= FIELD[page][sy][sx]=
ms.isDown(1)and pen or penMode==1 and penColor or
ms.isDown(2)and -1 penMode==2 and -1 or
or 0 -- penMode==3 and 0
0
end end
end end
else
penX,penY=nil
end end
end end
function scene.mouseDown(x,y,k) function scene.mouseDown(x,y,k)
if k==2 and pen==-2 then if not penMode then
SPlist={} penMode=k
else elseif penMode~=k then
scene.mouseMove(x,y) penMode=false
if penColor==-2 then
SPlist={}
end
end end
end
function scene.mouseUp()
if pen==-2 then SPdraw()end
end
function scene.wheelMoved(_,y)
if y<0 then
pen=pen+1
if pen==25 then pen=1 end
else
pen=pen-1
if pen==0 then pen=24 end
end
end
function scene.touchDown(x,y)
scene.mouseMove(x,y) scene.mouseMove(x,y)
end end
function scene.touchMove(x,y) function scene.mouseUp(_,_,k)
local sx,sy=int((x-200)/30)+1,20-int((y-60)/30) if penMode==k then
if sx<1 or sx>10 then sx=nil end penMode=false
if sy<1 or sy>20 then sy=nil end if penColor==-2 then
penX,penY=sx,sy SPdraw()
if sx and sy then
if pen==-2 then
SPpath(sx,sy)
else
FIELD[page][sy][sx]=pen
end end
end end
end end
scene.touchUp=scene.mouseUp
function scene.wheelMoved(_,y)
if penColor>0 then
penColor=(penColor+(y<0 and 1 or -1)-1)%24+1
end
end
function scene.touchDown(x,y)scene.mouseDown(x,y,1)end
function scene.touchMove(x,y)scene.mouseMove(x,y)end
function scene.touchUp(x,y)scene.mouseUp(x,y,1)end
function scene.keyDown(key) function scene.keyDown(key)
local sx,sy=penX,penY
if key=="up"or key=="down"or key=="left"or key=="right"then if key=="up"or key=="down"or key=="left"or key=="right"then
if not sx then sx=1 end if not penX or not penY then penX,penY=1,1 end
if not sy then sy=1 end if key=="up"then
if key=="up"and sy<20 then sy=sy+1 if penY<20 then penY=penY+1 end
elseif key=="down"and sy>1 then sy=sy-1 elseif key=="down"then
elseif key=="left"and sx>1 then sx=sx-1 if penY>1 then penY=penY-1 end
elseif key=="right"and sx<10 then sx=sx+1 elseif key=="left"then
if penX>1 then penX=penX-1 end
elseif key=="right"then
if penX<10 then penX=penX+1 end
end end
if kb.isDown("space")then if kb.isDown("space")then
scene.keyDown("space") scene.keyDown("space")
end end
elseif key=="space"then elseif key=="space"then
if sx and sy then if penX and penY then
if pen==-2 then penMode=1
SPpath(sx,sy) if penColor==-2 then
SPpath(penX,penY)
else else
FIELD[page][sy][sx]=pen FIELD[page][penY][penX]=penColor
end end
end end
elseif key=="delete"then elseif key=="delete"then
@@ -260,13 +250,15 @@ function scene.keyDown(key)
elseif key=="escape"then elseif key=="escape"then
SCN.back() SCN.back()
else else
pen=penKey[key]or pen penColor=penKey[key]or penColor
end end
penX,penY,pen=sx,sy,pen
end end
function scene.keyUp(key) function scene.keyUp(key)
if key=="space"and pen==-2 then if key=="space"then
SPdraw() if penColor==-2 then
SPdraw()
end
penMode=false
end end
end end
@@ -303,20 +295,19 @@ function scene.draw()
--Draw pen --Draw pen
if penX and penY then if penX and penY then
local x,y=30*penX,600-30*penY local x,y=30*penX,600-30*penY
if kb.isDown("space")or ms.isDown(1)then if penMode==1 or penMode==2 then
gc.setLineWidth(5) gc.setLineWidth(5)
gc.rectangle("line",x-30,y,30,30,4) gc.rectangle("line",x-30,y,30,30,4)
elseif ms.isDown(3)then elseif penMode==3 then
gc.setLineWidth(3) gc.setLineWidth(3)
gc.line(x-15,y,x-30,y+15) gc.line(x-15,y,x-30,y+15)
gc.line(x,y,x-30,y+30) gc.line(x,y,x-30,y+30)
gc.line(x,y+15,x-15,y+30) gc.line(x,y+15,x-15,y+30)
else
gc.setLineWidth(2)
gc.rectangle("line",x-30,y,30,30,3)
gc.setColor(1,1,1,.2)
gc.rectangle("fill",x-30,y,30,30,3)
end end
gc.setLineWidth(2)
gc.rectangle("line",x-30,y,30,30,3)
gc.setColor(1,1,1,.2)
gc.rectangle("fill",x-30,y,30,30,3)
end end
--Draw smart pen path --Draw smart pen path
@@ -326,14 +317,15 @@ function scene.draw()
if #SPlist<=5 then if #SPlist<=5 then
gc.setColor(COLOR.rainbow_light(TIME()*6.2)) gc.setColor(COLOR.rainbow_light(TIME()*6.2))
else else
gc.setColor(COLOR.grey) gc.setColor(.9,.9,.9,.7+.2*math.sin(TIME()*12.6))
end end
for i=1,#SPlist do for i=1,#SPlist do
gc.rectangle("line",30*SPlist[i][1]-30+2,600-30*SPlist[i][2]+2,30-4,30-4,3) gc.rectangle("line",30*SPlist[i][1]-30+2,600-30*SPlist[i][2]+2,30-4,30-4,3)
end end
elseif SPmode==1 then else
gc.setColor(1,0,0)
for i=1,#SPlist do for i=1,#SPlist do
gc.rectangle("line",30*SPlist[i][1]-30+2,600-30*SPlist[i][2]+2,30-4,30-4,3) gc.draw(cross,30*SPlist[i][1]-30+math.random(-1,1),600-30*SPlist[i][2]+math.random(-1,1))
end end
end end
end end
@@ -347,20 +339,38 @@ function scene.draw()
gc.rectangle("fill",50,600,100,6) gc.rectangle("fill",50,600,100,6)
--Draw pen color --Draw pen color
if pen>0 then gc.translate(560,475)
gc.setLineWidth(13) --Right mouse button
gc.setColor(minoColor[pen]) gc.setLineWidth(3)
gc.rectangle("line",565,495,70,70) gc.setColor(1,1,1,.9)
elseif pen==-1 then gc.line(52,5,75,35)
gc.setLineWidth(5) gc.line(75,5,52,35)
gc.setColor(.9,.9,.9) --Left mouse button
gc.line(575,505,625,555) if penColor>0 then
gc.line(575,555,625,505) gc.setColor(minoColor[penColor])
elseif pen==-2 then gc.rectangle("fill",5,5,23,30)
gc.setLineWidth(13) elseif penColor==-1 then
gc.setColor(COLOR.rainbow(TIME()*6.2)) gc.line(5,5,28,35)
gc.rectangle("line",565,495,70,70) gc.line(28,5,5,35)
end elseif penColor==-2 then
if SPmode==1 then
gc.setColor(1,0,0)
gc.line(5,5,28,35)
gc.line(28,5,5,35)
else
gc.setLineWidth(13)
gc.setColor(COLOR.rainbow(TIME()*12.6))
gc.rectangle("fill",5,5,23,30)
end
end
--Draw mouse
gc.setLineWidth(2)
gc.setColor(1,1,1)
gc.rectangle("line",0,0,80,110,5)
gc.line(0,40,80,40)
gc.line(33,0,33,40)
gc.line(47,0,47,40)
gc.translate(-560,-475)
--Confirm reset --Confirm reset
if sure>0 then if sure>0 then
@@ -382,7 +392,7 @@ function scene.draw()
end end
end end
local function setPen(i)return function()pen=i end end local function setPen(i)return function()penColor=i end end
scene.widgetList={ scene.widgetList={
WIDGET.newText{name="title", x=1020,y=5,font=70,align="R"}, WIDGET.newText{name="title", x=1020,y=5,font=70,align="R"},
WIDGET.newText{name="subTitle", x=1030,y=50,font=35,align="L",color="grey"}, WIDGET.newText{name="subTitle", x=1030,y=50,font=35,align="L",color="grey"},

View File

@@ -231,7 +231,7 @@ scene.widgetList={
WIDGET.newKey{name="reset", x=1000, y=640, w=90, color="lYellow",font=50,code=pressKey"delete"}, WIDGET.newKey{name="reset", x=1000, y=640, w=90, color="lYellow",font=50,code=pressKey"delete"},
WIDGET.newButton{name="copy", x=1140, y=440, w=170,h=80, color="lRed", font=40,code=pressKey"cC",hide=function()return #MISSION==0 end}, WIDGET.newButton{name="copy", x=1140, y=440, w=170,h=80, color="lRed", font=40,code=pressKey"cC",hide=function()return #MISSION==0 end},
WIDGET.newButton{name="paste", x=1140, y=540, w=170,h=80, color="lBlue", font=40,code=pressKey"cV"}, WIDGET.newButton{name="paste", x=1140, y=540, w=170,h=80, color="lBlue", font=40,code=pressKey"cV"},
WIDGET.newSwitch{name="mission",x=1150, y=350, disp=lnk_CUSval("missionKill"),code=lnk_CUSrev("missionKill")}, WIDGET.newSwitch{name="mission",x=1150, y=350, disp=CUSval("missionKill"),code=CUSrev("missionKill")},
WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80, font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80, font=40,code=backScene},
} }

View File

@@ -191,8 +191,8 @@ scene.widgetList={
WIDGET.newSelector{name="sequence", WIDGET.newSelector{name="sequence",
x=1080,y=60,w=200,color="yellow", x=1080,y=60,w=200,color="yellow",
list={"bag","his4","c2","rnd","mess","reverb","loop","fixed"}, list={"bag","his4","c2","rnd","mess","reverb","loop","fixed"},
disp=lnk_CUSval("sequence"), disp=CUSval("sequence"),
code=lnk_CUSsto("sequence") code=CUSsto("sequence")
}, },
WIDGET.newKey{name="Z", x=120,y=460,w=80,font=50,code=pressKey(1)}, WIDGET.newKey{name="Z", x=120,y=460,w=80,font=50,code=pressKey(1)},

View File

@@ -36,7 +36,7 @@ function scene.sceneInit()
end end
local function clearResult() local function clearResult()
for _=1,#result do rem(result)end TABLE.clear(result)
selected,scrollPos=1,0 selected,scrollPos=1,0
waiting,lastSearch=0,false waiting,lastSearch=0,false
end end
@@ -60,6 +60,9 @@ local function search()
lastSearch=input lastSearch=input
end end
function scene.wheelMoved(_,y)
WHEELMOV(y)
end
function scene.keyDown(key) function scene.keyDown(key)
if key=="up"then if key=="up"then
if selected and selected>1 then if selected and selected>1 then
@@ -75,6 +78,10 @@ function scene.keyDown(key)
scrollPos=selected-15 scrollPos=selected-15
end end
end end
elseif key=="pageup"then
for _=1,12 do scene.keyDown("up")end
elseif key=="pagedown"then
for _=1,12 do scene.keyDown("down")end
elseif key=="link"then elseif key=="link"then
love.system.openURL(url) love.system.openURL(url)
elseif key=="delete"then elseif key=="delete"then

View File

@@ -36,7 +36,7 @@ local function upFloor()
SFX.play("click",.3) SFX.play("click",.3)
end end
end end
local loadingThread=coroutine.create(function() local loadingThread=coroutine.wrap(function()
for i=1,SFX.getCount()do for i=1,SFX.getCount()do
SFX.loadOne() SFX.loadOne()
if i%3==0 then YIELD()end if i%3==0 then YIELD()end
@@ -175,15 +175,15 @@ local loadingThread=coroutine.create(function()
logoColor2={COLOR.rainbow_light(r)} logoColor2={COLOR.rainbow_light(r)}
end end
STAT.run=STAT.run+1 STAT.run=STAT.run+1
LOADED=true
--Connect to server --Connect to server
TASK.new(TICK_WS_app) TASK.new(NET.updateWS_app)
TASK.new(TICK_WS_user) TASK.new(NET.updateWS_user)
TASK.new(NET.updateWS_play)
WS.connect("app","/app") WS.connect("app","/app")
if USER.authToken then if USER.authToken then
WS.connect("user","/user",JSON.encode{ WS.connect("user","/user",JSON.encode{
id=USER.id, uid=USER.uid,
authToken=USER.authToken, authToken=USER.authToken,
}) })
end end
@@ -193,10 +193,10 @@ local loadingThread=coroutine.create(function()
upFloor() upFloor()
end end
if progress==25 then if progress==25 then
loadingThread=false
SFX.play("welcome_sfx") SFX.play("welcome_sfx")
VOC.play("welcome_voc") VOC.play("welcome_voc")
THEME.fresh() THEME.fresh()
LOADED=true
return return
end end
YIELD() YIELD()
@@ -255,8 +255,8 @@ function scene.update(dt)
if progress<25 then if progress<25 then
local p=progress local p=progress
repeat repeat
assert(coroutine.resume(loadingThread)) loadingThread()
until not loadingThread or skip<=0 or progress~=p until LOADED or skip<=0 or progress~=p
if skip>0 then skip=skip-1 end if skip>0 then skip=skip-1 end
else else
openTime=openTime+dt openTime=openTime+dt

View File

@@ -6,7 +6,6 @@ local function login()
elseif #password==0 then elseif #password==0 then
LOG.print(text.noPassword)return LOG.print(text.noPassword)return
end end
USER.email=email
WS.connect("user","/user",JSON.encode{ WS.connect("user","/user",JSON.encode{
email=email, email=email,
password=password, password=password,

View File

@@ -12,15 +12,13 @@ local widgetX0={
1290,1290,1290,1290, 1290,1290,1290,1290,
} }
local cmdEntryThread=coroutine.create(function() local cmdEntryThread=coroutine.wrap(function()
while true do while true do
while true do if
if YIELD()~="c"then break end YIELD()=="c"and(SFX.play("ren_6")or 1)and
SFX.play("ren_6") YIELD()=="m"and(SFX.play("ren_9")or 1)and
if YIELD()~="m"then break end YIELD()=="d"and(SFX.play("ren_11")or 1)
SFX.play("ren_9") then
if YIELD()~="d"then break end
SFX.play("ren_11")
SCN.go("app_cmd") SCN.go("app_cmd")
end end
end end
@@ -30,7 +28,7 @@ function scene.sceneInit()
scrollX=tipLength scrollX=tipLength
BG.set() BG.set()
coroutine.resume(cmdEntryThread) cmdEntryThread()
--Set quick-play-button text --Set quick-play-button text
scene.widgetList[2].text=text.WidgetText.main.qplay..": "..text.modes[STAT.lastPlay][1] scene.widgetList[2].text=text.WidgetText.main.qplay..": "..text.modes[STAT.lastPlay][1]
@@ -43,15 +41,11 @@ function scene.sceneInit()
GAME.seed=math.random(2e6) GAME.seed=math.random(2e6)
PLY.newDemoPlayer(1) PLY.newDemoPlayer(1)
PLAYERS[1]:setPosition(520,140,.8) PLAYERS[1]:setPosition(520,140,.8)
love.keyboard.setKeyRepeat(false)
end
function scene.sceneBack()
love.keyboard.setKeyRepeat(true)
end end
function scene.mouseDown(x,y) function scene.mouseDown(x,y)
if x>=520 and x<=760 and y>=140 and y<=620 then if x>=520 and x<=760 and y>=140 and y<=620 then
coroutine.resume(cmdEntryThread, cmdEntryThread(
x<520+80 and y>620-80 and"c"or x<520+80 and y>620-80 and"c"or
x>760-80 and y>620-80 and"m"or x>760-80 and y>620-80 and"m"or
x<520+80 and y<140+80 and"d" x<520+80 and y<140+80 and"d"
@@ -77,12 +71,12 @@ function scene.keyDown(key)
end end
elseif key=="a"then elseif key=="a"then
if testButton(3)then if testButton(3)then
if LOGIN then if NET.login then
if not NET.allow_online then if not NET.allow_online then
TEXT.show(text.needUpdate,640,450,60,"flicker") TEXT.show(text.needUpdate,640,450,60,"flicker")
SFX.play("finesseError") SFX.play("finesseError")
else else
WS.send("user",JSON.encode{action=0}) NET.getAccessToken()
end end
else else
SCN.go("login") SCN.go("login")
@@ -125,7 +119,7 @@ function scene.keyDown(key)
SCN.back() SCN.back()
end end
else else
coroutine.resume(cmdEntryThread,key) cmdEntryThread(key)
end end
end end
@@ -183,9 +177,9 @@ scene.widgetList={
WIDGET.newButton{name="dict", x=2480,y=450,w=800,h=100, color="lGreen", font=40,align="L",edge=30, code=pressKey"l"}, WIDGET.newButton{name="dict", x=2480,y=450,w=800,h=100, color="lGreen", font=40,align="L",edge=30, code=pressKey"l"},
WIDGET.newButton{name="manual", x=2480,y=570,w=800,h=100, color="lC", font=40,align="L",edge=30, code=pressKey","}, WIDGET.newButton{name="manual", x=2480,y=570,w=800,h=100, color="lC", font=40,align="L",edge=30, code=pressKey","},
WIDGET.newButton{name="music", x=160,y=80,w=200,h=90, color="lOrange",font=35, code=pressKey"f2"}, WIDGET.newButton{name="music", x=160,y=80,w=200,h=90, color="lOrange",font=35, code=pressKey"2"},
WIDGET.newButton{name="lang", x=1120,y=80,w=200,h=90, color="lY", font=40, code=pressKey"f3"}, WIDGET.newButton{name="lang", x=1120,y=80,w=200,h=90, color="lY", font=40, code=pressKey"0"},
WIDGET.newButton{name="about", x=-110,y=670,w=600,h=70, color="lB", font=35,align="R",edge=30, code=pressKey"f1"}, WIDGET.newButton{name="about", x=-110,y=670,w=600,h=70, color="lB", font=35,align="R",edge=30, code=pressKey"x"},
WIDGET.newButton{name="quit", x=1390,y=670,w=600,h=70, color="lR", font=40,align="L",edge=30, code=function()VOC.play("bye")SCN.swapTo("quit","slowFade")end}, WIDGET.newButton{name="quit", x=1390,y=670,w=600,h=70, color="lR", font=40,align="L",edge=30, code=function()VOC.play("bye")SCN.swapTo("quit","slowFade")end},
} }

View File

@@ -88,7 +88,7 @@ scene.widgetList={
WIDGET.newText{name="title", x=30, y=30,font=80,align="L"}, WIDGET.newText{name="title", x=30, y=30,font=80,align="L"},
WIDGET.newText{name="arrow", x=270, y=360,font=45,align="L"}, WIDGET.newText{name="arrow", x=270, y=360,font=45,align="L"},
WIDGET.newText{name="now", x=700, y=500,font=50,align="R",hide=function()return not BGM.nowPlay end}, WIDGET.newText{name="now", x=700, y=500,font=50,align="R",hide=function()return not BGM.nowPlay end},
WIDGET.newSlider{name="bgm", x=760, y=80,w=400, font=35,disp=lnk_SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end}, WIDGET.newSlider{name="bgm", x=760, y=80,w=400, font=35,disp=SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end},
WIDGET.newButton{name="up", x=200, y=250,w=120, font=55,code=pressKey"up",hide=function()return selected==1 end}, WIDGET.newButton{name="up", x=200, y=250,w=120, font=55,code=pressKey"up",hide=function()return selected==1 end},
WIDGET.newButton{name="play", x=200, y=390,w=120, font=35,code=pressKey"space"}, WIDGET.newButton{name="play", x=200, y=390,w=120, font=35,code=pressKey"space"},
WIDGET.newButton{name="down", x=200, y=530,w=120, font=55,code=pressKey"down",hide=function()return selected==#bgmList end}, WIDGET.newButton{name="down", x=200, y=530,w=120, font=55,code=pressKey"down",hide=function()return selected==#bgmList end},

View File

@@ -3,12 +3,12 @@ local data=love.data
local textBox=WIDGET.newTextBox{name="texts",x=40,y=50,w=1200,h=430} local textBox=WIDGET.newTextBox{name="texts",x=40,y=50,w=1200,h=430}
local remain--People in chat room local remain--People in chat room
local heartBeatTimer
local escapeTimer=0 local escapeTimer=0
local function sendMessage() local function sendMessage()
local W=WIDGET.active.input local W=WIDGET.active.input
if #W.value>0 and WS.send("chat","T"..data.encode("string","base64",W.value))then if #W.value>0 then
NET.sendChatMes(W.value)
W.value="" W.value=""
end end
end end
@@ -16,7 +16,6 @@ end
local scene={} local scene={}
function scene.sceneInit() function scene.sceneInit()
heartBeatTimer=0
remain=false remain=false
local texts=textBox.texts local texts=textBox.texts
@@ -30,8 +29,7 @@ function scene.sceneInit()
BG.set("none") BG.set("none")
end end
function scene.sceneBack() function scene.sceneBack()
WS.send("chat","Q") NET.quitChat()
LOG.print(text.wsDisconnected,"warn")
end end
function scene.wheelMoved(_,y) function scene.wheelMoved(_,y)
@@ -80,13 +78,6 @@ function scene.socketRead(mes)
end end
end end
function scene.update(dt)
heartBeatTimer=heartBeatTimer+dt
if heartBeatTimer>42 then
heartBeatTimer=0
WS.send("chat","P")
end
end
function scene.draw() function scene.draw()
setFont(25) setFont(25)
gc.setColor(1,1,1) gc.setColor(1,1,1)

View File

@@ -1,9 +1,7 @@
local data=love.data
local gc=love.graphics local gc=love.graphics
local tc=love.touch local tc=love.touch
local playerData local ins=table.insert
local ins,rem=table.insert,table.remove
local SCR=SCR local SCR=SCR
local VK=virtualkey local VK=virtualkey
@@ -13,14 +11,8 @@ local updateVirtualkey=updateVirtualkey
local hideChatBox local hideChatBox
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=function()return hideChatBox end} local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=function()return hideChatBox end}
local function switchChat()
hideChatBox=not hideChatBox
end
local playerInitialized
local playing local playing
local heartBeatTimer
local lastUpstreamTime local lastUpstreamTime
local upstreamProgress local upstreamProgress
local lastBackTime=0 local lastBackTime=0
@@ -30,23 +22,19 @@ local touchMoveLastFrame=false
local scene={} local scene={}
function scene.sceneBack() function scene.sceneBack()
WS.send("play","Q") NET.signal_quit()
LOG.print(text.wsDisconnected,"warn")
love.keyboard.setKeyRepeat(true) love.keyboard.setKeyRepeat(true)
end end
function scene.sceneInit() function scene.sceneInit()
love.keyboard.setKeyRepeat(false) love.keyboard.setKeyRepeat(false)
hideChatBox=true hideChatBox=true
playerInitialized=false
textBox:clear() textBox:clear()
playerData={} resetGameData("n")
resetGameData("n",playerData)
noTouch=not SETTING.VKSwitch noTouch=not SETTING.VKSwitch
playing=false playing=false
lastUpstreamTime=0 lastUpstreamTime=0
upstreamProgress=1 upstreamProgress=1
heartBeatTimer=0
end end
function scene.touchDown(x,y) function scene.touchDown(x,y)
@@ -96,7 +84,7 @@ function scene.keyDown(key)
LOG.print(text.sureQuit,COLOR.orange) LOG.print(text.sureQuit,COLOR.orange)
end end
elseif key=="\\"then elseif key=="\\"then
switchChat() hideChatBox=not hideChatBox
elseif playing then elseif playing then
if noKey then return end if noKey then return end
local k=keyMap.keyboard[key] local k=keyMap.keyboard[key]
@@ -106,8 +94,8 @@ function scene.keyDown(key)
VK[k].pressTime=10 VK[k].pressTime=10
end end
elseif key=="space"then elseif key=="space"then
if not PLAYERS[1].ready then if not NET.getLock("ready")then
WS.send("play","R") NET.signal_ready()
end end
end end
end end
@@ -147,77 +135,85 @@ function scene.gamepadUp(key)
end end
end end
function scene.socketRead(mes) function scene.socketRead(cmd,data)
local cmd=mes:sub(1,1) if cmd=="Join"then
local args=SPLITSTR(mes:sub(2),";") textBox:push{
if cmd=="J"then COLOR.lR,data.username,
if playerInitialized then COLOR.dY,"#"..data.uid.." ",
local L=SPLITSTR(args[1],",") COLOR.Y,text.joinRoom,
textBox:push{ }
COLOR.lR,L[1],
COLOR.dY,"#"..L[2].." ",
COLOR.Y,text.joinRoom,
}
end
for i=1,#args do
local L=SPLITSTR(args[i],",")
ins(playerData,{name=L[1],id=L[2],sid=L[3],conf=L[4],ready=L[5]=="1"})
end
playerInitialized=true
SFX.play("click") SFX.play("click")
if not playing then if not playing then
resetGameData("qn",playerData) resetGameData("qn")
end end
elseif cmd=="L"then elseif cmd=="Leave"then
textBox:push{ textBox:push{
COLOR.lR,args[1], COLOR.lR,data.username,
COLOR.dY,"#"..args[2].." ", COLOR.dY,"#"..data.uid.." ",
COLOR.Y,text.leaveRoom, COLOR.Y,text.leaveRoom,
} }
for i=1,#playerData do if not playing then
if playerData[i].id==args[2]then initPlayerPosition(true)
rem(playerData,i)
break
end
end end
for i=1,#PLAYERS do elseif cmd=="Talk"then
if PLAYERS[i].userID==args[2]then
rem(PLAYERS,i)
break
end
end
for i=1,#PLAYERS.alive do
if PLAYERS.alive[i].userID==args[2]then
rem(PLAYERS.alive,i)
break
end
end
initPlayerPosition(true)
elseif cmd=="T"then
local _,text=pcall(data.decode,"string","base64",args[3])
if not _ then text=args[3]end
textBox:push{ textBox:push{
COLOR.W,args[1], COLOR.W,data.username,
COLOR.dY,"#"..args[2].." ", COLOR.dY,"#"..data.uid.." ",
COLOR.sky,text COLOR.sky,data.message or"[_]",
} }
elseif cmd=="C"then elseif cmd=="Config"then
if tostring(USER.id)~=args[2]then if tostring(USER.uid)~=data.uid then
for i=1,#playerData do for i=1,#PLY_NET do
if playerData[i].id==args[2]then if PLY_NET[i].uid==data.uid then
playerData[i].conf=args[4] PLY_NET[i].conf=data.config
playerData[i].p:setConf(args[4]) PLY_NET[i].p:setConf(data.config)
return return
end end
end end
resetGameData("qn",playerData) resetGameData("qn")
end end
elseif cmd=="S"then elseif cmd=="Ready"then
if playing and args[1]~=PLAYERS[1].subID then if data.uid==USER.uid then
PLAYERS[1].ready=true
SFX.play("reach",.6)
else
for i=1,#PLAYERS do
if PLAYERS[i].userID==data.uid then
PLAYERS[i].ready=true
SFX.play("reach",.6)
break
end
end
end
elseif cmd=="Set"then
NET.rsid=data.rid
NET.wsConnectStream()
TASK.new(NET.updateWS_stream)
elseif cmd=="Begin"then
if not playing then
playing=true
lastUpstreamTime=0
upstreamProgress=1
resetGameData("n",data.seed)
else
LOG.print("Redundant signal: B(begin)",30,COLOR.green)
end
elseif cmd=="Finish"then
playing=false
resetGameData("n")
TEXT.show(text.champion:gsub("$1","SOMEBODY"),640,260,80,"zoomout",.26)
elseif cmd=="Die"then
LOG.print("One player failed",COLOR.sky)
elseif cmd=="Stream"then
if data.uid==USER.uid then
LOG.print("SELF STREAM")
return
end
if playing then
for _,P in next,PLAYERS do for _,P in next,PLAYERS do
if P.subID==args[1]then if P.userID==data.uid then
local _,stream=pcall(data.decode,"string","base64",args[2]) local res,stream=pcall(love.data.decode,"string","base64",data.stream)
if _ then if res then
pumpRecording(stream,P.stream) pumpRecording(stream,P.stream)
else else
LOG.print("Bad stream from "..P.userName.."#"..P.userID) LOG.print("Bad stream from "..P.userName.."#"..P.userID)
@@ -225,35 +221,6 @@ function scene.socketRead(mes)
end end
end end
end end
elseif cmd=="R"then
local L=PLAYERS.alive
for i=1,#L do
if L[i].subID==args[1]then
L[i].ready=true
SFX.play("reach",.6)
break
end
end
elseif cmd=="B"then
if not playing then
playing=true
lastUpstreamTime=0
upstreamProgress=1
resetGameData("n",playerData,tonumber(args[1]))
else
LOG.print("Redundant signal: B(begin)",30,COLOR.green)
end
elseif cmd=="F"then
playing=false
resetGameData("n",playerData)
for i=1,#playerData do
if playerData[i].sid==args[1]then
TEXT.show(text.champion:gsub("$1",playerData[i].name.."#"..playerData[i].id),640,260,80,"zoomout",.26)
break
end
end
else
LOG.print("Illegal message: ["..mes.."]",30,COLOR.green)
end end
end end
@@ -261,15 +228,8 @@ function scene.update(dt)
local _ local _
local GAME=GAME local GAME=GAME
if WS.status("play")~="running"and not SCN.swapping then SCN.back()end if WS.status("play")~="running"then SCN.back()end
if not playing then if not playing then return end
heartBeatTimer=heartBeatTimer+dt
if heartBeatTimer>42 then
heartBeatTimer=0
WS.send("play","P")
end
return
end
touchMoveLastFrame=false touchMoveLastFrame=false
updateVirtualkey() updateVirtualkey()
@@ -289,7 +249,7 @@ function scene.update(dt)
local stream local stream
stream,upstreamProgress=dumpRecording(GAME.rep,upstreamProgress) stream,upstreamProgress=dumpRecording(GAME.rep,upstreamProgress)
if #stream>0 then if #stream>0 then
WS.send("stream",data.encode("string","base64",stream)) NET.uploadRecStream(stream)
else else
ins(GAME.rep,GAME.frame) ins(GAME.rep,GAME.frame)
ins(GAME.rep,0) ins(GAME.rep,0)
@@ -322,7 +282,7 @@ end
scene.widgetList={ scene.widgetList={
textBox, textBox,
WIDGET.newKey{name="ready",x=640,y=440,w=200,h=80,color="yellow",font=40,code=pressKey"space",hide=function()return playing or not hideChatBox or PLAYERS[1].ready end}, WIDGET.newKey{name="ready",x=640,y=440,w=200,h=80,color="yellow",font=40,code=pressKey"space",hide=function()return playing or not hideChatBox or PLAYERS[1].ready end},
WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=switchChat}, WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=pressKey"\\"},
WIDGET.newKey{name="quit",fText="X",x=900,y=35,w=60,font=40,code=pressKey"escape"}, WIDGET.newKey{name="quit",fText="X",x=900,y=35,w=60,font=40,code=pressKey"escape"},
} }

View File

@@ -1,13 +1,13 @@
local scene={} local scene={}
function scene.sceneInit() function scene.sceneInit()
BG.set("matrix") BG.set("space")
end end
scene.widgetList={ scene.widgetList={
WIDGET.newButton{name="ffa", x=640, y=200,w=350,h=120,font=40,code=NULL}, -- WIDGET.newButton{name="ffa", x=640, y=200,w=350,h=120,font=40,code=NULL},
WIDGET.newButton{name="rooms", x=640, y=360,w=350,h=120,font=40,code=goScene"net_rooms"}, WIDGET.newButton{name="rooms", x=640, y=360,w=350,h=120,font=40,code=goScene"net_rooms"},
WIDGET.newButton{name="chat", x=640, y=540,w=350,h=120,font=40,code=goScene"net_chat",hide=function()return WS.status("chat")~="running"end}, -- WIDGET.newButton{name="chat", x=640, y=540,w=350,h=120,font=40,code=goScene"net_chat"},
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
} }

View File

@@ -1,40 +1,23 @@
local gc=love.graphics local gc=love.graphics
local min=math.min local min=math.min
local rooms local NET=NET
local scrollPos,selected local scrollPos,selected
local lastfreshTime local fetchTimer
local lastCreateRoomTime=0 local lastCreateRoomTime=0
local function enterRoom(roomID) local function fetchRoom()
--[[TODO fetchTimer=5
WS.connect("play","/play",JSON.encode{ NET.fetchRoom()
email=USER.email,
token=USER.accessToken,
id=roomID,
conf=dumpBasicConfig(),
-- password=password,
})
]]
end
local function fresh()
lastfreshTime=TIME()
rooms=nil
--[[TODO
WS.connect("play","/play",JSON.encode{
email=USER.email,
accessToken=USER.accessToken,
})
]]
end end
local scene={} local scene={}
function scene.sceneInit() function scene.sceneInit()
BG.set("bg1") BG.set("space")
scrollPos=0 scrollPos=0
selected=1 selected=1
fresh() fetchRoom()
end end
function scene.wheelMoved(_,y) function scene.wheelMoved(_,y)
@@ -42,28 +25,21 @@ function scene.wheelMoved(_,y)
end end
function scene.keyDown(k) function scene.keyDown(k)
if k=="r"then if k=="r"then
if TIME()-lastfreshTime>1 then if fetchTimer<=3.26 then
fresh() fetchRoom()
end end
elseif k=="n"then elseif k=="n"then
if TIME()-lastCreateRoomTime>26 then if TIME()-lastCreateRoomTime>26 then
--[[TODO NET.createRoom()
WS.send("room",JSON.encode{
email=USER.email,
accessToken=USER.accessToken,
room_name=(USER.name or"???").."'s room",
room_password=nil,
})
]]
lastCreateRoomTime=TIME() lastCreateRoomTime=TIME()
else else
LOG.print(text.createRoomTooFast,"warn") LOG.print(text.createRoomTooFast,"warn")
end end
elseif k=="escape"then elseif k=="escape"then
SCN.back() SCN.back()
elseif rooms and #rooms>0 then elseif #NET.roomList>0 then
if k=="down"then if k=="down"then
if selected<#rooms then if selected<#NET.roomList then
selected=selected+1 selected=selected+1
if selected>scrollPos+10 then if selected>scrollPos+10 then
scrollPos=scrollPos+1 scrollPos=scrollPos+1
@@ -77,59 +53,63 @@ function scene.keyDown(k)
end end
end end
elseif k=="return"then elseif k=="return"then
if rooms[selected].private then if NET.getLock("fetchRoom")then return end
if NET.roomList[selected].private then
LOG.print("Can't enter private room now") LOG.print("Can't enter private room now")
return return
end end
enterRoom(rooms[selected].id) NET.enterRoom(NET.roomList[selected].rid)--,password
end end
end end
end end
function scene.update() function scene.update(dt)
if TIME()-lastfreshTime>5 then if not NET.getLock("fetchRoom")then
fresh() fetchTimer=fetchTimer-dt
if fetchTimer<=0 then
fetchRoom()
end
end end
end end
function scene.draw() function scene.draw()
--Fetching timer
gc.setColor(1,1,1,.26) gc.setColor(1,1,1,.26)
gc.arc("fill","pie",240,620,60,-1.5708,-1.5708+1.2566*(TIME()-lastfreshTime)) gc.arc("fill","pie",240,620,60,-1.5708,-1.5708-1.2566*fetchTimer)
if rooms then
gc.setColor(1,1,1) --Room list
if #rooms>0 then gc.setColor(1,1,1)
gc.setLineWidth(2) gc.setLineWidth(2)
gc.rectangle("line",55,110,1100,400) gc.rectangle("line",50,110,1180,400)
gc.setColor(1,1,1,.3) if #NET.roomList>0 then
gc.rectangle("fill",55,40*(1+selected-scrollPos)+30,1100,40) gc.setColor(1,1,1,.3)
setFont(35) gc.rectangle("fill",50,40*(1+selected-scrollPos)+30,1180,40)
for i=1,min(10,#rooms-scrollPos)do setFont(35)
local R=rooms[scrollPos+i] for i=1,min(10,#NET.roomList-scrollPos)do
if R.private then local R=NET.roomList[scrollPos+i]
gc.setColor(1,1,1) if R.private then
gc.draw(IMG.lock,64,75+40*i)
end
gc.setColor(.9,.9,1)
gc.print(scrollPos+i,100,66+40*i)
gc.setColor(1,1,.7)
gc.print(R.name,200,66+40*i)
gc.setColor(1,1,1) gc.setColor(1,1,1)
gc.printf(R.type,500,66+40*i,500,"right") gc.draw(IMG.lock,59,75+40*i)
gc.print(R.count.."/"..R.capacity,1050,66+40*i)
end end
else gc.setColor(.9,.9,1)
setFont(60) gc.print(scrollPos+i,95,66+40*i)
mStr(text.noRooms,640,315) gc.setColor(1,1,.7)
gc.print(R.name,250,66+40*i)
gc.setColor(1,1,1)
gc.printf(R.type,550,66+40*i,500,"right")
gc.print(R.count.."/"..R.capacity,1100,66+40*i)
end end
end end
end end
scene.widgetList={ scene.widgetList={
WIDGET.newKey{name="fresh", x=240,y=620,w=140,h=140,font=40,code=fresh,hide=function()return TIME()-lastfreshTime<1.26 end}, WIDGET.newText{name="refreshing",x=640,y=260,font=65,hide=function()return not NET.getLock("fetchRoom")end},
WIDGET.newText{name="noRoom", x=640,y=260,font=40,hide=function()return #NET.roomList>0 or NET.getLock("fetchRoom")end},
WIDGET.newKey{name="refresh", x=240,y=620,w=140,h=140,font=40,code=fetchRoom, hide=function()return fetchTimer>3.26 end},
WIDGET.newKey{name="new", x=440,y=620,w=140,h=140,font=25,code=pressKey"n"}, WIDGET.newKey{name="new", x=440,y=620,w=140,h=140,font=25,code=pressKey"n"},
WIDGET.newKey{name="join", x=640,y=620,w=140,h=140,font=40,code=pressKey"return",hide=function()return not rooms end}, WIDGET.newKey{name="join", x=640,y=620,w=140,h=140,font=40,code=pressKey"return", hide=function()return #NET.roomList==0 end},
WIDGET.newKey{name="up", x=840,y=585,w=140,h=70,font=40,code=pressKey"up",hide=function()return not rooms end}, WIDGET.newKey{name="up", x=840,y=585,w=140,h=70,font=40,code=pressKey"up", hide=function()return #NET.roomList==0 end},
WIDGET.newKey{name="down", x=840,y=655,w=140,h=70,font=40,code=pressKey"down",hide=function()return not rooms end}, WIDGET.newKey{name="down", x=840,y=655,w=140,h=70,font=40,code=pressKey"down", hide=function()return #NET.roomList==0 end},
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=40,code=backScene}, WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=40,code=backScene},
} }

View File

@@ -49,7 +49,7 @@ scene.widgetList={
WIDGET.newButton{name="importUnlock", x=190,y=300,w=280,h=100,color="lBlue",font=25,code=function() WIDGET.newButton{name="importUnlock", x=190,y=300,w=280,h=100,color="lBlue",font=25,code=function()
local D=parseCB() local D=parseCB()
if D then if D then
TABLE.add(D,RANKS) TABLE.update(D,RANKS)
FILE.save(RANKS,"conf/unlock") FILE.save(RANKS,"conf/unlock")
LOG.print(text.importSuccess,"message") LOG.print(text.importSuccess,"message")
else else
@@ -59,7 +59,7 @@ scene.widgetList={
WIDGET.newButton{name="importData", x=490,y=300,w=280,h=100,color="lBlue",font=25,code=function() WIDGET.newButton{name="importData", x=490,y=300,w=280,h=100,color="lBlue",font=25,code=function()
local D=parseCB() local D=parseCB()
if D and D.version==STAT.version then if D and D.version==STAT.version then
TABLE.add(D,STAT) TABLE.update(D,STAT)
FILE.save(STAT,"conf/data") FILE.save(STAT,"conf/data")
LOG.print(text.importSuccess,"message") LOG.print(text.importSuccess,"message")
else else
@@ -69,7 +69,7 @@ scene.widgetList={
WIDGET.newButton{name="importSetting", x=790,y=300,w=280,h=100,color="lBlue",font=25,code=function() WIDGET.newButton{name="importSetting", x=790,y=300,w=280,h=100,color="lBlue",font=25,code=function()
local D=parseCB() local D=parseCB()
if D then if D then
TABLE.add(D,SETTING) TABLE.update(D,SETTING)
FILE.save(SETTING,"conf/settings") FILE.save(SETTING,"conf/settings")
LOG.print(text.importSuccess,"message") LOG.print(text.importSuccess,"message")
else else
@@ -79,7 +79,7 @@ scene.widgetList={
WIDGET.newButton{name="importVK", x=1090,y=300,w=280,h=100,color="lBlue",font=25,code=function() WIDGET.newButton{name="importVK", x=1090,y=300,w=280,h=100,color="lBlue",font=25,code=function()
local D=parseCB() local D=parseCB()
if D then if D then
TABLE.add(D,VK_org) TABLE.update(D,VK_org)
FILE.save(VK_org,"conf/virtualkey") FILE.save(VK_org,"conf/virtualkey")
LOG.print(text.importSuccess,"message") LOG.print(text.importSuccess,"message")
else else

View File

@@ -81,14 +81,14 @@ scene.widgetList={
WIDGET.newText{name="title", x=80, y=50,font=70,align="L"}, 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=540,font=40,align="R"},
WIDGET.newSlider{name="das", x=250, y=190,w=600,unit=20,disp=lnk_SETval("das"), show=sliderShow,code=lnk_SETsto("das")}, 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=lnk_SETval("arr"), show=sliderShow,code=lnk_SETsto("arr")}, 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=lnk_SETval("sddas"),show=sliderShow,code=lnk_SETsto("sddas")}, 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=lnk_SETval("sdarr"),show=sliderShow,code=lnk_SETsto("sdarr")}, 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=lnk_SETval("dascut"),show=sliderShow,code=lnk_SETsto("dascut")}, WIDGET.newSlider{name="dascut", x=250, y=470,w=600,unit=20,disp=SETval("dascut"),show=sliderShow,code=SETsto("dascut")},
WIDGET.newSwitch{name="ihs", x=1100, y=260, disp=lnk_SETval("ihs"), code=lnk_SETrev("ihs")}, WIDGET.newSwitch{name="ihs", x=1100, y=260, disp=SETval("ihs"), code=SETrev("ihs")},
WIDGET.newSwitch{name="irs", x=1100, y=330, disp=lnk_SETval("irs"), code=lnk_SETrev("irs")}, WIDGET.newSwitch{name="irs", x=1100, y=330, disp=SETval("irs"), code=SETrev("irs")},
WIDGET.newSwitch{name="ims", x=1100, y=400, disp=lnk_SETval("ims"), code=lnk_SETrev("ims")}, 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="lRed",font=40, WIDGET.newButton{name="reset", x=160, y=580,w=200,h=100,color="lRed",font=40,
code=function() code=function()
local _=SETTING local _=SETTING

View File

@@ -27,14 +27,14 @@ scene.widgetList={
WIDGET.newButton{name="ctrl", x=290, y=220, w=320,h=80, color="lYellow",font=35,code=goScene"setting_control"}, WIDGET.newButton{name="ctrl", x=290, y=220, w=320,h=80, color="lYellow",font=35,code=goScene"setting_control"},
WIDGET.newButton{name="key", x=640, y=220, w=320,h=80, color="lGreen", font=35,code=goScene"setting_key"}, WIDGET.newButton{name="key", x=640, y=220, w=320,h=80, color="lGreen", font=35,code=goScene"setting_key"},
WIDGET.newButton{name="touch", x=990, y=220, w=320,h=80, color="lBlue", font=35,code=goScene"setting_touch"}, WIDGET.newButton{name="touch", x=990, y=220, w=320,h=80, color="lBlue", font=35,code=goScene"setting_touch"},
WIDGET.newSlider{name="reTime", x=350, y=340, w=300,unit=10,disp=lnk_SETval("reTime"),code=lnk_SETsto("reTime"),show=function(S)return(.5+S.disp()*.25).."s"end}, WIDGET.newSlider{name="reTime", x=350, y=340, w=300,unit=10,disp=SETval("reTime"),code=SETsto("reTime"),show=function(S)return(.5+S.disp()*.25).."s"end},
WIDGET.newSelector{name="RS", x=500, y=420, w=300,color="sea",list={"TRS","SRS","C2","C2sym","Classic","None"},disp=lnk_SETval("RS"),code=lnk_SETsto("RS")}, WIDGET.newSelector{name="RS", x=500, y=420, w=300,color="sea",list={"TRS","SRS","C2","C2sym","Classic","None"},disp=SETval("RS"),code=SETsto("RS")},
WIDGET.newButton{name="layout", x=550, y=540, w=200,h=70, font=35,code=goScene"setting_skin"}, WIDGET.newButton{name="layout", x=550, y=540, w=200,h=70, font=35,code=goScene"setting_skin"},
WIDGET.newSwitch{name="autoPause", x=1060, y=310, font=20,disp=lnk_SETval("autoPause"),code=lnk_SETrev("autoPause")}, WIDGET.newSwitch{name="autoPause", x=1060, y=310, font=20,disp=SETval("autoPause"),code=SETrev("autoPause")},
WIDGET.newSwitch{name="swap", x=1060, y=370, font=20,disp=lnk_SETval("swap"), code=lnk_SETrev("swap")}, WIDGET.newSwitch{name="swap", x=1060, y=370, font=20,disp=SETval("swap"), code=SETrev("swap")},
WIDGET.newSwitch{name="fine", x=1060, y=430, font=20,disp=lnk_SETval("fine"), code=function()SETTING.fine=not SETTING.fine if SETTING.fine then SFX.play("finesseError",.6) end end}, WIDGET.newSwitch{name="fine", x=1060, y=430, font=20,disp=SETval("fine"), code=function()SETTING.fine=not SETTING.fine if SETTING.fine then SFX.play("finesseError",.6) end end},
WIDGET.newSwitch{name="appLock", x=1060, y=490, font=20,disp=lnk_SETval("appLock"), code=lnk_SETrev("appLock")}, WIDGET.newSwitch{name="appLock", x=1060, y=490, font=20,disp=SETval("appLock"), code=SETrev("appLock")},
WIDGET.newSwitch{name="simpMode", x=1060, y=550, font=25,disp=lnk_SETval("simpMode"),code=function() WIDGET.newSwitch{name="simpMode", x=1060, y=550, font=25,disp=SETval("simpMode"),code=function()
SETTING.simpMode=not SETTING.simpMode SETTING.simpMode=not SETTING.simpMode
for i=1,#SCN.stack,2 do for i=1,#SCN.stack,2 do
if SCN.stack[i]=="main"or SCN.stack[i]=="main_simple"then if SCN.stack[i]=="main"or SCN.stack[i]=="main_simple"then

View File

@@ -10,8 +10,7 @@ local jump--Animation timer(10 to 0)
local cv=SETTING.cv local cv=SETTING.cv
function scene.sceneInit() function scene.sceneInit()
last=0 last,jump=0,0
jump=0
cv=SETTING.cv cv=SETTING.cv
BG.set() BG.set()
end end
@@ -34,24 +33,24 @@ function scene.touchDown(x,y)
end end
function scene.update() function scene.update()
local t=jump if jump>0 then jump=jump-1 end
if t>0 then
jump=t-1
end
end end
function scene.draw() function scene.draw()
gc.setColor(1,1,1) gc.setColor(1,1,1)
local t=TIME() local t=TIME()
local _=jump local x,y=800,340+10*sin(t*.5)+(jump-10)*jump*.3
local x,y=800,340+10*sin(t*.5)+(_-10)*_*.3
gc.translate(x,y) gc.translate(x,y)
gc.draw(IMG.miyaCH,0,0) if cv=="miya"then
gc.setColor(1,1,1,.7) gc.draw(IMG.miyaCH)
gc.draw(IMG.miyaF1,4,47+4*sin(t*.9)) gc.setColor(1,1,1,.7)
gc.draw(IMG.miyaF2,42,107+5*sin(t)) gc.draw(IMG.miyaF1,4,47+4*sin(t*.9))
gc.draw(IMG.miyaF3,93,126+3*sin(t*.7)) gc.draw(IMG.miyaF2,42,107+5*sin(t))
gc.draw(IMG.miyaF4,129,98+3*sin(t*.7)) gc.draw(IMG.miyaF3,93,126+3*sin(t*.7))
gc.draw(IMG.miyaF4,129,98+3*sin(t*.5))
elseif cv=="naki"then
gc.draw(IMG.nakiCH)
end
gc.translate(-x,-y) gc.translate(-x,-y)
end end
@@ -61,13 +60,13 @@ scene.widgetList={
WIDGET.newButton{name="game", x=200, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_game","swipeR"}, WIDGET.newButton{name="game", x=200, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_game","swipeR"},
WIDGET.newButton{name="graphic",x=1080, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_video","swipeL"}, WIDGET.newButton{name="graphic",x=1080, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_video","swipeL"},
WIDGET.newSlider{name="sfx", x=180, y=200,w=400, font=35,change=function()SFX.play("blip_1")end, disp=lnk_SETval("sfx"),code=lnk_SETsto("sfx")}, WIDGET.newSlider{name="sfx", x=180, y=200,w=400, font=35,change=function()SFX.play("blip_1")end, disp=SETval("sfx"),code=SETsto("sfx")},
WIDGET.newSlider{name="spawn", x=180, y=300,w=400, font=30,change=function()SFX.fplay("spawn_"..math.random(7),SETTING.sfx_spawn)end,disp=lnk_SETval("sfx_spawn"),code=lnk_SETsto("sfx_spawn")}, WIDGET.newSlider{name="spawn", x=180, y=300,w=400, font=30,change=function()SFX.fplay("spawn_"..math.random(7),SETTING.sfx_spawn)end,disp=SETval("sfx_spawn"),code=SETsto("sfx_spawn")},
WIDGET.newSlider{name="warn", x=180, y=400,w=400, font=30,change=function()SFX.fplay("warning",SETTING.sfx_warn)end,disp=lnk_SETval("sfx_warn"),code=lnk_SETsto("sfx_warn")}, WIDGET.newSlider{name="warn", x=180, y=400,w=400, font=30,change=function()SFX.fplay("warning",SETTING.sfx_warn)end,disp=SETval("sfx_warn"),code=SETsto("sfx_warn")},
WIDGET.newSlider{name="bgm", x=180, y=500,w=400, font=35, disp=lnk_SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end}, WIDGET.newSlider{name="bgm", x=180, y=500,w=400, font=35, disp=SETval("bgm"),code=function(v)SETTING.bgm=v BGM.freshVolume()end},
WIDGET.newSlider{name="stereo", x=180, y=600,w=400, font=35,change=function()SFX.play("move",1,-1)SFX.play("lock",1,1)end,disp=lnk_SETval("stereo"),code=lnk_SETsto("stereo"),hide=function()return SETTING.sx==0 end}, WIDGET.newSlider{name="stereo", x=180, y=600,w=400, font=35,change=function()SFX.play("move",1,-1)SFX.play("lock",1,1)end,disp=SETval("stereo"),code=SETsto("stereo"),hide=function()return SETTING.sx==0 end},
WIDGET.newSlider{name="vib", x=750, y=200,w=400,unit=5, font=25,change=function()VIB(2)end, disp=lnk_SETval("vib"),code=lnk_SETsto("vib")}, WIDGET.newSlider{name="vib", x=750, y=200,w=400,unit=5, font=25,change=function()VIB(2)end, disp=SETval("vib"),code=SETsto("vib")},
WIDGET.newSlider{name="voc", x=750, y=300,w=400, font=35,change=function()VOC.play("test")end, disp=lnk_SETval("voc"),code=lnk_SETsto("voc")}, WIDGET.newSlider{name="voc", x=750, y=300,w=400, font=35,change=function()VOC.play("test")end, disp=SETval("voc"),code=SETsto("voc")},
WIDGET.newSelector{name="cv", x=1100, y=380,w=200, list={"miya","naki"}, disp=function()return cv end,code=function(i)cv=i end}, WIDGET.newSelector{name="cv", x=1100, y=380,w=200, list={"miya","naki"}, disp=function()return cv end,code=function(i)cv=i end},
WIDGET.newButton{name="apply", x=1100, y=460,w=180,h=80, code=function()SETTING.cv=cv VOC.loadAll()end,hide=function()return SETTING.cv==cv end}, WIDGET.newButton{name="apply", x=1100, y=460,w=180,h=80, code=function()SETTING.cv=cv VOC.loadAll()end,hide=function()return SETTING.cv==cv end},
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80, font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80, font=40,code=backScene},

View File

@@ -30,11 +30,11 @@ scene.widgetList={
WIDGET.newSwitch{name="b20", x=580, y=620, font=35,disp=VKAdisp(20),code=VKAcode(20)}, WIDGET.newSwitch{name="b20", x=580, y=620, font=35,disp=VKAdisp(20),code=VKAcode(20)},
WIDGET.newButton{name="norm", x=840, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=i<11 end end}, WIDGET.newButton{name="norm", x=840, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=i<11 end end},
WIDGET.newButton{name="pro", x=1120, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=true end end}, WIDGET.newButton{name="pro", x=1120, y=100, w=240,h=80, font=35,code=function()for i=1,20 do VK_org[i].ava=true end end},
WIDGET.newSwitch{name="hide", x=1170, y=200, font=40,disp=lnk_SETval("VKSwitch"),code=lnk_SETrev("VKSwitch")}, WIDGET.newSwitch{name="hide", x=1170, y=200, font=40,disp=SETval("VKSwitch"),code=SETrev("VKSwitch")},
WIDGET.newSwitch{name="track", x=1170, y=300, font=35,disp=lnk_SETval("VKTrack"),code=lnk_SETrev("VKTrack")}, WIDGET.newSwitch{name="track", x=1170, y=300, font=35,disp=SETval("VKTrack"),code=SETrev("VKTrack")},
WIDGET.newSlider{name="sfx", x=800, y=380, w=180, font=35,change=function()SFX.play("virtualKey",SETTING.VKSFX)end,disp=lnk_SETval("VKSFX"),code=lnk_SETsto("VKSFX")}, WIDGET.newSlider{name="sfx", x=800, y=380, w=180, font=35,change=function()SFX.play("virtualKey",SETTING.VKSFX)end,disp=SETval("VKSFX"),code=SETsto("VKSFX")},
WIDGET.newSlider{name="vib", x=800, y=460, w=180,unit=2, font=35,change=function()VIB(SETTING.VKVIB)end,disp=lnk_SETval("VKVIB"),code=lnk_SETsto("VKVIB")}, WIDGET.newSlider{name="vib", x=800, y=460, w=180,unit=2, font=35,change=function()VIB(SETTING.VKVIB)end,disp=SETval("VKVIB"),code=SETsto("VKVIB")},
WIDGET.newSwitch{name="icon", x=850, y=300, font=40,disp=lnk_SETval("VKIcon"),code=lnk_SETrev("VKIcon")}, WIDGET.newSwitch{name="icon", x=850, y=300, font=40,disp=SETval("VKIcon"),code=SETrev("VKIcon")},
WIDGET.newButton{name="tkset", x=1120, y=420, w=240,h=80, WIDGET.newButton{name="tkset", x=1120, y=420, w=240,h=80,
code=function() code=function()
SCN.go("setting_trackSetting") SCN.go("setting_trackSetting")
@@ -42,7 +42,7 @@ scene.widgetList={
hide=function() hide=function()
return not SETTING.VKTrack return not SETTING.VKTrack
end}, end},
WIDGET.newSlider{name="alpha", x=840, y=540, w=400,font=40,disp=lnk_SETval("VKAlpha"),code=lnk_SETsto("VKAlpha")}, WIDGET.newSlider{name="alpha", x=840, y=540, w=400,font=40,disp=SETval("VKAlpha"),code=SETsto("VKAlpha")},
WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80,font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640, w=170,h=80,font=40,code=backScene},
} }

View File

@@ -11,9 +11,9 @@ function scene.draw()
end end
scene.widgetList={ scene.widgetList={
WIDGET.newSwitch{name="VKDodge",x=400, y=530, font=35,disp=lnk_SETval("VKDodge"),code=lnk_SETrev("VKDodge")}, WIDGET.newSwitch{name="VKDodge",x=400, y=530, font=35,disp=SETval("VKDodge"),code=SETrev("VKDodge")},
WIDGET.newSlider{name="VKTchW", x=140, y=320,w=1000, font=35,disp=lnk_SETval("VKTchW"),code=function(i)SETTING.VKTchW=i SETTING.VKCurW=math.max(SETTING.VKCurW,i)end}, WIDGET.newSlider{name="VKTchW", x=140, y=320,w=1000, font=35,disp=SETval("VKTchW"),code=function(i)SETTING.VKTchW=i SETTING.VKCurW=math.max(SETTING.VKCurW,i)end},
WIDGET.newSlider{name="VKCurW", x=140, y=390,w=1000, font=35,disp=lnk_SETval("VKCurW"),code=function(i)SETTING.VKCurW=i SETTING.VKTchW=math.min(SETTING.VKTchW,i)end}, WIDGET.newSlider{name="VKCurW", x=140, y=390,w=1000, font=35,disp=SETval("VKCurW"),code=function(i)SETTING.VKCurW=i SETTING.VKTchW=math.min(SETTING.VKTchW,i)end},
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
} }

View File

@@ -13,22 +13,22 @@ scene.widgetList={
WIDGET.newButton{name="sound", x=200, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_sound","swipeR"}, WIDGET.newButton{name="sound", x=200, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_sound","swipeR"},
WIDGET.newButton{name="game", x=1080, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_game","swipeL"}, WIDGET.newButton{name="game", x=1080, y=80,w=240,h=80,color="lCyan",font=35,code=swapScene"setting_game","swipeL"},
WIDGET.newSwitch{name="block", x=340, y=150, disp=lnk_SETval("block"), code=lnk_SETrev("block")}, WIDGET.newSwitch{name="block", x=340, y=150, disp=SETval("block"), code=SETrev("block")},
WIDGET.newSwitch{name="smooth", x=340, y=210, disp=lnk_SETval("smooth"), code=lnk_SETrev("smooth")}, WIDGET.newSwitch{name="smooth", x=340, y=210, disp=SETval("smooth"), code=SETrev("smooth")},
WIDGET.newSwitch{name="upEdge", x=340, y=270, disp=lnk_SETval("upEdge"), code=lnk_SETrev("upEdge")}, WIDGET.newSwitch{name="upEdge", x=340, y=270, disp=SETval("upEdge"), code=SETrev("upEdge")},
WIDGET.newSwitch{name="bagLine", x=340, y=330, disp=lnk_SETval("bagLine"), code=lnk_SETrev("bagLine")}, WIDGET.newSwitch{name="bagLine", x=340, y=330, disp=SETval("bagLine"), code=SETrev("bagLine")},
WIDGET.newSlider{name="ghost", x=630, y=180,w=200,unit=.6,disp=lnk_SETval("ghost"),show="percent",code=lnk_SETsto("ghost")}, WIDGET.newSlider{name="ghost", x=630, y=180,w=200,unit=.6,disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
WIDGET.newSlider{name="grid", x=630, y=240,w=200,unit=.4,disp=lnk_SETval("grid"),show="percent", code=lnk_SETsto("grid")}, WIDGET.newSlider{name="grid", x=630, y=240,w=200,unit=.4,disp=SETval("grid"),show="percent", code=SETsto("grid")},
WIDGET.newSlider{name="center", x=630, y=300,w=200,unit=1, disp=lnk_SETval("center"), code=lnk_SETsto("center")}, WIDGET.newSlider{name="center", x=630, y=300,w=200,unit=1, disp=SETval("center"), code=SETsto("center")},
WIDGET.newSlider{name="lockFX", x=350, y=375,w=373,unit=5, disp=lnk_SETval("lockFX"), code=lnk_SETsto("lockFX")}, WIDGET.newSlider{name="lockFX", x=350, y=375,w=373,unit=5, disp=SETval("lockFX"), code=SETsto("lockFX")},
WIDGET.newSlider{name="dropFX", x=350, y=420,w=373,unit=5, disp=lnk_SETval("dropFX"), code=lnk_SETsto("dropFX")}, WIDGET.newSlider{name="dropFX", x=350, y=420,w=373,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
WIDGET.newSlider{name="moveFX", x=350, y=465,w=373,unit=5, disp=lnk_SETval("moveFX"), code=lnk_SETsto("moveFX")}, WIDGET.newSlider{name="moveFX", x=350, y=465,w=373,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
WIDGET.newSlider{name="clearFX", x=350, y=510,w=373,unit=5, disp=lnk_SETval("clearFX"), code=lnk_SETsto("clearFX")}, WIDGET.newSlider{name="clearFX", x=350, y=510,w=373,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
WIDGET.newSlider{name="splashFX", x=350, y=555,w=373,unit=5, disp=lnk_SETval("splashFX"),code=lnk_SETsto("splashFX")}, WIDGET.newSlider{name="splashFX", x=350, y=555,w=373,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
WIDGET.newSlider{name="shakeFX", x=350, y=600,w=373,unit=5, disp=lnk_SETval("shakeFX"), code=lnk_SETsto("shakeFX")}, WIDGET.newSlider{name="shakeFX", x=350, y=600,w=373,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
WIDGET.newSlider{name="atkFX", x=350, y=645,w=373,unit=5, disp=lnk_SETval("atkFX"), code=lnk_SETsto("atkFX")}, WIDGET.newSlider{name="atkFX", x=350, y=645,w=373,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
WIDGET.newSlider{name="frame", x=350, y=690,w=373,unit=10, WIDGET.newSlider{name="frame", x=350, y=690,w=373,unit=10,
disp=function() disp=function()
return SETTING.frameMul>35 and SETTING.frameMul/10 or SETTING.frameMul/5-4 return SETTING.frameMul>35 and SETTING.frameMul/10 or SETTING.frameMul/5-4
@@ -37,20 +37,20 @@ scene.widgetList={
SETTING.frameMul=i<5 and 5*i+20 or 10*i SETTING.frameMul=i<5 and 5*i+20 or 10*i
end}, end},
WIDGET.newSwitch{name="text", x=1100, y=180,font=35,disp=lnk_SETval("text"), code=lnk_SETrev("text")}, WIDGET.newSwitch{name="text", x=1100, y=180,font=35,disp=SETval("text"), code=SETrev("text")},
WIDGET.newSwitch{name="score", x=1100, y=240,font=35,disp=lnk_SETval("score"), code=lnk_SETrev("score")}, WIDGET.newSwitch{name="score", x=1100, y=240,font=35,disp=SETval("score"), code=SETrev("score")},
WIDGET.newSwitch{name="warn", x=1100, y=300,font=35,disp=lnk_SETval("warn"), code=lnk_SETrev("warn")}, WIDGET.newSwitch{name="warn", x=1100, y=300,font=35,disp=SETval("warn"), code=SETrev("warn")},
WIDGET.newSwitch{name="highCam", x=1100, y=360,font=35,disp=lnk_SETval("highCam"),code=lnk_SETrev("highCam")}, WIDGET.newSwitch{name="highCam", x=1100, y=360,font=35,disp=SETval("highCam"),code=SETrev("highCam")},
WIDGET.newSwitch{name="nextPos", x=1100, y=420,font=35,disp=lnk_SETval("nextPos"),code=lnk_SETrev("nextPos")}, WIDGET.newSwitch{name="nextPos", x=1100, y=420,font=35,disp=SETval("nextPos"),code=SETrev("nextPos")},
WIDGET.newSwitch{name="fullscreen",x=1100, y=480,disp=lnk_SETval("fullscreen"), code=switchFullscreen}, WIDGET.newSwitch{name="fullscreen",x=1100, y=480,disp=SETval("fullscreen"), code=switchFullscreen},
WIDGET.newSwitch{name="bg", x=1100, y=540,font=35,disp=lnk_SETval("bg"), WIDGET.newSwitch{name="bg", x=1100, y=540,font=35,disp=SETval("bg"),
code=function() code=function()
BG.set("none") BG.set("none")
SETTING.bg=not SETTING.bg SETTING.bg=not SETTING.bg
BG.set() BG.set()
end}, end},
WIDGET.newSwitch{name="power", x=990, y=610,font=35,disp=lnk_SETval("powerInfo"),code=lnk_SETrev("powerInfo")}, WIDGET.newSwitch{name="power", x=990, y=610,font=35,disp=SETval("powerInfo"),code=SETrev("powerInfo")},
WIDGET.newSwitch{name="clean", x=990, y=670,font=35,disp=lnk_SETval("cleanCanvas"),code=lnk_SETrev("cleanCanvas")}, WIDGET.newSwitch{name="clean", x=990, y=670,font=35,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene}, WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
} }

View File

@@ -39,8 +39,8 @@ end
scene.widgetList={ scene.widgetList={
WIDGET.newText{name="title", x=30, y=15,font=70,align="L"}, WIDGET.newText{name="title", x=30, y=15,font=70,align="L"},
WIDGET.newSlider{name="sfx", x=510, y=60,w=330,font=35,change=function()SFX.play("blip_1")end,disp=lnk_SETval("sfx"),code=lnk_SETsto("sfx")}, WIDGET.newSlider{name="sfx", x=510, y=60,w=330,font=35,change=function()SFX.play("blip_1")end,disp=SETval("sfx"),code=SETsto("sfx")},
WIDGET.newSlider{name="voc", x=510, y=120,w=330,font=35,change=function()VOC.play("test")end,disp=lnk_SETval("voc"),code=lnk_SETsto("voc")}, WIDGET.newSlider{name="voc", x=510, y=120,w=330,font=35,change=function()VOC.play("test")end,disp=SETval("voc"),code=SETsto("voc")},
WIDGET.newKey{name="move", x=110, y=140,w=160,h=50,font=20,code=function()SFX.play("move")end}, WIDGET.newKey{name="move", x=110, y=140,w=160,h=50,font=20,code=function()SFX.play("move")end},
WIDGET.newKey{name="lock", x=110, y=205,w=160,h=50,font=20,code=function()SFX.play("lock")end}, WIDGET.newKey{name="lock", x=110, y=205,w=160,h=50,font=20,code=function()SFX.play("lock")end},

View File

@@ -144,14 +144,14 @@ end
--WS icons --WS icons
setFont(20) setFont(20)
TEXTURE.ws_dead=NSC(20,20) TEXTURE.ws_dead=NSC(20,20)
gc.setColor(1,.4,.3) gc.setColor(1,.3,.3)
gc.print("X",3,-4) gc.print("X",3,-4)
TEXTURE.ws_connecting=NSC(20,20) TEXTURE.ws_connecting=NSC(20,20)
gc.setLineWidth(3) gc.setLineWidth(3)
gc.setColor(1,1,1) gc.setColor(1,1,1)
gc.arc("line","open",11.5,10,6.26,1,5.28) gc.arc("line","open",11.5,10,6.26,1,5.28)
TEXTURE.ws_running=NSC(20,20) TEXTURE.ws_running=NSC(20,20)
gc.setColor(0,.9,0) gc.setColor(.5,1,0)
gc.print("R",3,-4) gc.print("R",3,-4)

View File

@@ -1,24 +1,70 @@
return SPLITSTR([=[ return SPLITSTR([=[
未来计划: 未来模式:
新模式: 无尽PC挑战; 简单极简练习; 任务生存; 对称; 无摩擦; 连击练习; 拼方形
无尽PC挑战; 简单极简练习; 任务生存; 对称; 跑酷; 教学; 术语问答; 无摩擦 极简教程/考试; 大爆炸; 音游模式; 跑酷; 术语问答; 养成玩法
极简教程/考试; 连击练习; 自攻自受; 大爆炸; 音游模式; 拼方形; 养成玩法 OSD; 强制Misdrop; 涂色模式(模仿喷喷, designed by teatube)
OSD; 强制Misdrop; 涂色模式(模仿喷喷, designed by teatube) 未来大游戏:
其他: puyo; 花仙子方块; 2048; 泡泡龙
小游戏: 未来Mod:
速算(前缀后缀表达式,二八十六进制); 动态视力测试(记数字) 修改颜色配置; 只显示场地边框线/顶线
Tetro-1010(四/五连块, 2C2N, 若干回合改变重力方向) 未来小游戏:
求合体; 坦克大战; 扫雷; 接水管; 各种NS计算器小游戏移植 Tetro-1010(四/五连块, 2C2N, 若干回合改变重力方向)
多方块; XRS; 移动n格+硬降复合操作键; 更好的手柄支持; 手势操作 Tetra-link; 速算(前缀后缀表达式,二八十六进制)
区分各种消除(隔断/架空/混合/彩色/穿墙) 连连看; 求合体; 坦克大战; 扫雷; 接水管
更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹) 其他未来内容:
可调场地宽度; DAS系统更细节的折返选项; 特殊控件(虚拟摇杆等) XRS; 移动n格+硬降复合操作键; 更好的手柄支持
主菜单和选关UI重做; 适应任意屏幕尺寸的UI 自适应UI; 重做模式选择UI和MOD的UI; 高级自定义序列
可更换的全局主题系统; 成就系统; 3D背景 区分各种消除(隔断/架空/混合/彩色/穿墙)
可选虚拟按键颜色; 工程编译到字节码; task-Z(新AI) 更复杂的垃圾行(数量/等待时间/抵消倍率/洞数/连接/炸弹)
录像回放菜单; 跳帧开关; 超60帧; 热更新 可调场地宽度; 手势操作; 特殊控件(虚拟摇杆等); 切换高低镜头的按键
DAS系统和Deepdrop系统更细节的选项; spike计数器; 攻击总缓冲显示
成就系统; 更强的主题系统; 多方块; 3D背景
可选虚拟按键颜色; 工程编译到字节码; task-Z(新AI)
录像回放菜单; 跳帧开关; 教学关; 超60帧; 热更新
0.13.3: 科技飞跃 0.14.0: 地平线 The Horizon
新增:
重新开放联网游戏测试
主菜单UI更新,改变几个场景间的关系
场地晃动加入旋转分量
加入c2和mess序列模式,可以在自定义或mod中开启
新模式:Backfire(四个难度)
新背景:BlackHole(用于Backfire)
新增BGM:echo(用于Backfire), hang out(用于两个小程序)
调整自定义场地的ui可以看到鼠标不同按键对应画笔颜色
小程序DTW增加双押功能
新增绘制优化设置(手机开启可能加速,花屏可能关闭解决)
改动:
错误处理机制大升级,更不容易闪退(CC爆炸除外)
赞助名单移至staff场景并添加动画(已经在榜上的可以来定制颜色!)
修改GM模式的名称和段位名以及修改连带内容,加高成绩上限,修复一个旧版本存档转换错误
封面NOGAME改为启动时弹窗提示重启
鼠标按下时光标显示会变化
优化场地绘制交互,添加一个鼠标功能指示器
微调生存模式下落速度
修改时间字符串格式
词典不再大小写敏感
调整徽章图标
添加naki立绘
报错时会把traceback信息保存到日志文件便于debug
cmd添加一些测试用命令和一些文件管理命令,可以用于自行修复存档
cmd添加复制粘贴剪切和tab补全,不再需要切焦点
ws状态展示样式升级,只在debug模式下显示
代码:
序列生成器改用协程实现
THEME做成独立模块
玩家属性modeData地位提升
不再每次启动时强制删除存档目录内所有非文件夹内容
绘制玩家场地用的scissor换成stencil(支持旋转和变形)
优化/大规模整理代码,网络相关全面升级
修复:
物理hold可能会卡死和踢墙测试位置不正确
词典中c2序列生成器的说明错误
刚安装就用简洁模式玩会报错(修改成绩比较逻辑)
报错提示的场景显示不正确
智能画笔问题
0.13.3: 科技飞跃 Technological Advancements
新增: 新增:
地图UI升级,增加模式图标 地图UI升级,增加模式图标
自定义场地新增智能画笔 自定义场地新增智能画笔
@@ -45,7 +91,7 @@ return SPLITSTR([=[
一个老存档转换问题 一个老存档转换问题
重开后虚拟按键失效 重开后虚拟按键失效
0.13.2+: 工作室搬迁 0.13.2+: 工作室搬迁 Moving the Studio
新增: 新增:
全新加载动画与资源加载机制 全新加载动画与资源加载机制
显示ai计算的下一块位置 显示ai计算的下一块位置
@@ -59,7 +105,7 @@ return SPLITSTR([=[
修复: 修复:
CC闪退(可能修复) CC闪退(可能修复)
0.13.2: 节奏模式 0.13.2: 节奏模式 Rhythm Mode
新增: 新增:
新增节奏模式(三个难度) 新增节奏模式(三个难度)
加入deepDrop功能(暂时只在自定义开放) 加入deepDrop功能(暂时只在自定义开放)