新增virtualKey模块整理虚拟按键相关代码,整理代码

This commit is contained in:
MrZ626
2021-04-22 15:15:31 +08:00
parent 2400325b22
commit 9f956f965a
11 changed files with 359 additions and 341 deletions

View File

@@ -66,6 +66,7 @@ USERS= require"parts.users"
TEXTURE= require"parts.texture"
SKIN= require"parts.skin"
NET= require"parts.net"
VK= require"parts.virtualKey"
PLY= require"parts.player"
AIFUNC= require"parts.ai"
AIBUILDER= require"parts.AITemplate"

View File

@@ -239,7 +239,7 @@ function DATA.copyQuestArgs()
ENV.sequence
return str
end
do--function pasteQuestArgs(str)
do--function DATA.pasteQuestArgs(str)
local sub=string.sub
function pasteQuestArgs(str)
if #str<4 then return end
@@ -252,4 +252,143 @@ do--function pasteQuestArgs(str)
end
end
--[[
Table data format:
{frame,event, frame,event, ...}
Byte data format: (1 byte each period)
dt, event, dt, event, ...
all data range from 0 to 127
large value will be encoded as 1xxxxxxx(high)-1xxxxxxx-...-0xxxxxxx(low)
Example (decoded):
6,1, 20,-1, 0,2, 26,-2, 872,4, ...
This means:
Press key1 at 6f
Release key1 at 26f (6+20)
Press key2 at the same time (26+0)
Release key 2 after 26 frame (26+26)
Press key 4 after 872 frame (52+872)
...
]]
function DATA.dumpRecording(list,ptr)
local out=""
local buffer,buffer2=""
if not ptr then ptr=1 end
local prevFrm=list[ptr-2]or 0
while list[ptr]do
--Flush buffer
if #buffer>10 then
out=out..buffer
buffer=""
end
--Encode time
local t=list[ptr]-prevFrm
prevFrm=list[ptr]
if t>=128 then
buffer2=char(t%128)
t=int(t/128)
while t>=128 do
buffer2=char(128+t%128)..buffer2
t=int(t/128)
end
buffer=buffer..char(128+t)..buffer2
else
buffer=buffer..char(t)
end
--Encode event
t=list[ptr+1]
if t>=128 then
buffer2=char(t%128)
t=int(t/128)
while t>=128 do
buffer2=char(128+t%128)..buffer2
t=int(t/128)
end
buffer=buffer..char(128+t)..buffer2
else
buffer=buffer..char(t)
end
--Step
ptr=ptr+2
end
return out..buffer,ptr
end
function DATA.pumpRecording(str,L)
local len=#str
local p=1
local curFrm=L[#L-1]or 0
local code
while p<=len do
--Read delta time
code=0
local b=byte(str,p)
while b>=128 do
code=code*128+b-128
p=p+1
b=byte(str,p)
end
curFrm=curFrm+code*128+b
L[#L+1]=curFrm
p=p+1
local event=0
b=byte(str,p)
while b>=128 do
event=event*128+b-128
p=p+1
b=byte(str,p)
end
L[#L+1]=event*128+b
p=p+1
end
end
do--function DATA.saveRecording()
local noRecList={"custom","solo","round","techmino"}
local function getModList()
local res={}
for _,v in next,GAME.mod do
if v.sel>0 then
ins(res,{v.no,v.sel})
end
end
return res
end
function DATA.saveRecording()
--Filtering modes that cannot be saved
for _,v in next,noRecList do
if GAME.curModeName:find(v)then
LOG.print("Cannot save recording of this mode now!",COLOR.N)
return
end
end
--Write file
local fileName="replay/"..os.date("%Y_%m_%d_%a_%H%M%S.rep")
if not love.filesystem.getInfo(fileName)then
local fileHead=
os.date("%Y/%m/%d %A %H:%M:%S\n")..
GAME.curModeName.."\n"..
VERSION.string.."\n"..
"Local Player"
local fileBody=
GAME.seed.."\n"..
JSON.encode(GAME.setting).."\n"..
JSON.encode(getModList()).."\n"..
DATA.dumpRecording(GAME.rep)
love.filesystem.write(fileName,fileHead.."\n"..data.compress("string","zlib",fileBody))
ins(REPLAY,fileName)
FILE.save(REPLAY,"conf/replay")
return true
else
LOG.print("Save failed: File already exists")
end
end
end
return DATA

View File

@@ -1,12 +1,7 @@
local data=love.data
local gc=love.graphics
local gc_setColor,gc_setLineWidth,gc_setShader=gc.setColor,gc.setLineWidth,gc.setShader
local gc_push,gc_pop,gc_origin,gc_translate=gc.push,gc.pop,gc.origin,gc.translate
local gc_draw,gc_rectangle,gc_circle=gc.draw,gc.rectangle,gc.circle
local int,rnd=math.floor,math.random
local char,byte=string.char,string.byte
local ins,rem=table.insert,table.remove
local gc_draw,gc_rectangle=gc.draw,gc.rectangle
@@ -21,6 +16,7 @@ end
--Royale mode
function randomTarget(P)--Return a random opponent for P
local rnd=math.random
if #PLY_ALIVE>1 then
local R
repeat
@@ -100,6 +96,7 @@ function royaleLevelup()
P.gameEnv.drop=spd
end
if GAME.curMode.name:find("_u")then
local int=math.floor
for i=1,#PLY_ALIVE do
local P=PLY_ALIVE[i]
P.gameEnv.drop=int(P.gameEnv.drop*.3)
@@ -113,108 +110,6 @@ end
--Virtualkey
local VK=virtualkey
function drawVirtualkeys()
if SETTING.VKSwitch then
local a=SETTING.VKAlpha
local _
if SETTING.VKIcon then
local icons=TEXTURE.VKIcon
for i=1,#VK do
if VK[i].ava then
local B=VK[i]
gc_setColor(1,1,1,a)
gc_setLineWidth(B.r*.07)
gc_circle("line",B.x,B.y,B.r,10)--Button outline
_=VK[i].pressTime
gc_setColor(B.color[1],B.color[2],B.color[3],a)
gc_draw(icons[i],B.x,B.y,nil,B.r*.026+_*.08,nil,18,18)--Icon
if _>0 then
gc_setColor(1,1,1,a*_*.08)
gc_circle("fill",B.x,B.y,B.r*.94,10)--Glow when press
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)--Ripple
end
end
end
else
for i=1,#VK do
if VK[i].ava then
local B=VK[i]
gc_setColor(1,1,1,a)
gc_setLineWidth(B.r*.07)
gc_circle("line",B.x,B.y,B.r,10)
_=VK[i].pressTime
if _>0 then
gc_setColor(1,1,1,a*_*.08)
gc_circle("fill",B.x,B.y,B.r*.94,10)
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)
end
end
end
end
end
end
function onVirtualkey(x,y)
local dist,nearest=1e10
for K=1,#VK do
local B=VK[K]
if B.ava then
local d1=(x-B.x)^2+(y-B.y)^2
if d1<B.r^2 then
if d1<dist then
nearest,dist=K,d1
end
end
end
end
return nearest
end
function pressVirtualkey(t,x,y)
local SETTING=SETTING
local B=VK[t]
B.isDown=true
B.pressTime=10
if x then
if SETTING.VKTrack then
--Auto follow
local O=VK_org[t]
local _FW,_CW=SETTING.VKTchW,1-SETTING.VKCurW
local _OW=1-_FW-_CW
--(finger+current+origin)
B.x=x*_FW+B.x*_CW+O.x*_OW
B.y=y*_FW+B.y*_CW+O.y*_OW
--Button collision (not accurate)
if SETTING.VKDodge then
for i=1,#VK do
local b=VK[i]
local d=B.r+b.r-((B.x-b.x)^2+(B.y-b.y)^2)^.5--Hit depth(Neg means distance)
if d>0 then
b.x=b.x+(b.x-B.x)*d*b.r*2.6e-5
b.y=b.y+(b.y-B.y)*d*b.r*2.6e-5
end
end
end
end
SFX.play("virtualKey",SETTING.VKSFX)
VIB(SETTING.VKVIB)
end
end
function updateVirtualkey()
if SETTING.VKSwitch then
for i=1,#VK do
local _=VK[i]
if _.pressTime>0 then
_.pressTime=_.pressTime-1
end
end
end
end
--Game
function generateLine(hole)
return 1023-2^(hole-1)
@@ -272,6 +167,7 @@ function scoreValid()--Check if any unranked mods are activated
return true
end
function destroyPlayers()--Destroy all player objects, restore freerows and free CCs
local rem=table.remove
for i=#PLAYERS,1,-1 do
local P=PLAYERS[i]
if P.canvas then P.canvas:release()end
@@ -290,23 +186,6 @@ function destroyPlayers()--Destroy all player objects, restore freerows and free
TABLE.clear(PLY_ALIVE)
collectgarbage()
end
function restoreVirtualkey()
for i=1,#VK_org do
local B,O=virtualkey[i],VK_org[i]
B.ava=O.ava
B.x=O.x
B.y=O.y
B.r=O.r
B.color=O.color
B.isDown=false
B.pressTime=0
end
for k,v in next,PLAYERS[1].keyAvailable do
if not v then
virtualkey[k].ava=false
end
end
end
function pauseGame()
if not SCN.swapping then
if not GAME.replaying then
@@ -485,7 +364,7 @@ do--function resetGameData(args)
GAME.replaying=1
else
GAME.frameStart=args:find("n")and 0 or 150-SETTING.reTime*15
GAME.seed=seed or rnd(1046101471,2662622626)
GAME.seed=seed or math.random(1046101471,2662622626)
GAME.pauseTime=0
GAME.pauseCount=0
GAME.saved=false
@@ -500,7 +379,7 @@ do--function resetGameData(args)
destroyPlayers()
GAME.curMode.load()
initPlayerPosition(args:find("q"))
restoreVirtualkey()
VK.restore()
if GAME.modeEnv.task then
for i=1,#PLAYERS do
PLAYERS[i]:newTask(GAME.modeEnv.task)
@@ -508,7 +387,7 @@ do--function resetGameData(args)
end
BG.set(GAME.modeEnv.bg)
local bgm=GAME.modeEnv.bgm
BGM.play(type(bgm)=="string"and bgm or type(bgm)=="table"and bgm[rnd(#bgm)])
BGM.play(type(bgm)=="string"and bgm or type(bgm)=="table"and bgm[math.random(#bgm)])
TEXT.clear()
if GAME.modeEnv.royaleMode then
@@ -566,146 +445,6 @@ do--function checkWarning()
end
end
--[[
Table data format:
{frame,event, frame,event, ...}
Byte data format: (1 byte each period)
dt, event, dt, event, ...
all data range from 0 to 127
large value will be encoded as 1xxxxxxx(high)-1xxxxxxx-...-0xxxxxxx(low)
Example (decoded):
6,1, 20,-1, 0,2, 26,-2, 872,4, ...
This means:
Press key1 at 6f
Release key1 at 26f (6+20)
Press key2 at the same time (26+0)
Release key 2 after 26 frame (26+26)
Press key 4 after 872 frame (52+872)
...
]]
function dumpRecording(list,ptr)
local out=""
local buffer,buffer2=""
if not ptr then ptr=1 end
local prevFrm=list[ptr-2]or 0
while list[ptr]do
--Flush buffer
if #buffer>10 then
out=out..buffer
buffer=""
end
--Encode time
local t=list[ptr]-prevFrm
prevFrm=list[ptr]
if t>=128 then
buffer2=char(t%128)
t=int(t/128)
while t>=128 do
buffer2=char(128+t%128)..buffer2
t=int(t/128)
end
buffer=buffer..char(128+t)..buffer2
else
buffer=buffer..char(t)
end
--Encode event
t=list[ptr+1]
if t>=128 then
buffer2=char(t%128)
t=int(t/128)
while t>=128 do
buffer2=char(128+t%128)..buffer2
t=int(t/128)
end
buffer=buffer..char(128+t)..buffer2
else
buffer=buffer..char(t)
end
--Step
ptr=ptr+2
end
return out..buffer,ptr
end
function pumpRecording(str,L)
local len=#str
local p=1
local curFrm=L[#L-1]or 0
local code
while p<=len do
--Read delta time
code=0
local b=byte(str,p)
while b>=128 do
code=code*128+b-128
p=p+1
b=byte(str,p)
end
curFrm=curFrm+code*128+b
L[#L+1]=curFrm
p=p+1
local event=0
b=byte(str,p)
while b>=128 do
event=event*128+b-128
p=p+1
b=byte(str,p)
end
L[#L+1]=event*128+b
p=p+1
end
end
do--function saveRecording()
local noRecList={"custom","solo","round","techmino"}
local function getModList()
local res={}
for _,v in next,GAME.mod do
if v.sel>0 then
ins(res,{v.no,v.sel})
end
end
return res
end
function saveRecording()
--Filtering modes that cannot be saved
for _,v in next,noRecList do
if GAME.curModeName:find(v)then
LOG.print("Cannot save recording of this mode now!",COLOR.N)
return
end
end
--File contents
local fileName="replay/"..os.date("%Y_%m_%d_%a_%H%M%S.rep")
local fileHead=
os.date("%Y/%m/%d %A %H:%M:%S\n")..
GAME.curModeName.."\n"..
VERSION.string.."\n"..
"Local Player"
local fileBody=
GAME.seed.."\n"..
JSON.encode(GAME.setting).."\n"..
JSON.encode(getModList()).."\n"..
dumpRecording(GAME.rep)
--Write file
if not love.filesystem.getInfo(fileName)then
love.filesystem.write(fileName,fileHead.."\n"..data.compress("string","zlib",fileBody))
ins(REPLAY,fileName)
FILE.save(REPLAY,"conf/replay")
return true
else
LOG.print("Save failed: File already exists")
end
end
end
--Game draw

View File

@@ -355,5 +355,4 @@ VK_org=FILE.load("conf/virtualkey")or{--Virtualkey layout, refresh all VKs' posi
{ava=false, x=900, y=50, r=80,color=COLOR.lA},--addToLeft
{ava=false, x=1000, y=50, r=80,color=COLOR.lA},--addToRight
}
virtualkey={}for i=1,#VK_org do virtualkey[i]={}end--In-game virtualkey layout
REPLAY=FILE.load("conf/replay")or{}

View File

@@ -172,7 +172,7 @@ function Player:switchKey(id,on)
self:releaseKey(id)
end
if self.type=="human"then
virtualkey[id].ava=on
VK.switchKey(id,on)
end
end
function Player:set20G(if20g)

View File

@@ -5,10 +5,7 @@ local tc=love.touch
local sin=math.sin
local SCR=SCR
local VK=virtualkey
local onVirtualkey=onVirtualkey
local pressVirtualkey=pressVirtualkey
local updateVirtualkey=updateVirtualkey
local VK=VK
local noTouch,noKey=false,false
local touchMoveLastFrame=false
@@ -34,16 +31,16 @@ end
function scene.touchDown(x,y)
if noTouch then return end
local t=onVirtualkey(x,y)
local t=VK.on(x,y)
if t then
PLAYERS[1]:pressKey(t)
pressVirtualkey(t,x,y)
VK.touch(t,x,y)
end
end
function scene.touchUp(x,y)
if noTouch then return end
local t=onVirtualkey(x,y)
local t=VK.on(x,y)
if t then
PLAYERS[1]:releaseKey(t)
end
@@ -56,8 +53,9 @@ function scene.touchMove()
for i=#L,1,-1 do
L[2*i-1],L[2*i]=SCR.xOy:inverseTransformPoint(tc.getPosition(L[i]))
end
for n=1,#VK do
local B=VK[n]
local keys=VK.getKeys
for n=1,#keys do
local B=keys[n]
if B.ava then
for i=1,#L,2 do
if(L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
@@ -75,8 +73,9 @@ function scene.keyDown(key)
if k>0 then
if noKey then return end
PLAYERS[1]:pressKey(k)
VK[k].isDown=true
VK[k].pressTime=10
local vk=VK.getKeys()[k]
vk.isDown=true
vk.pressTime=10
else
restart()
end
@@ -90,7 +89,7 @@ function scene.keyUp(key)
if k then
if k>0 then
PLAYERS[1]:releaseKey(k)
VK[k].isDown=false
VK.release(k)
end
elseif key=="back"then
pauseGame()
@@ -102,8 +101,7 @@ function scene.gamepadDown(key)
if k then
if k>0 then
PLAYERS[1]:pressKey(k)
VK[k].isDown=true
VK[k].pressTime=10
VK.press(k)
else
restart()
end
@@ -117,7 +115,7 @@ function scene.gamepadUp(key)
if k then
if k>0 then
PLAYERS[1]:releaseKey(k)
VK[k].isDown=false
VK.release(k)
end
elseif key=="back"then
pauseGame()
@@ -138,10 +136,10 @@ function scene.update(dt)
if key==0 then--Just wait
elseif key<=32 then--Press key
P1:pressKey(key)
pressVirtualkey(key)
VK.press(key)
elseif key<=64 then--Release key
P1:releaseKey(key-32)
VK[key-32].isDown=false
VK.release(key-32)
end
_=_+2
end
@@ -149,7 +147,7 @@ function scene.update(dt)
end
touchMoveLastFrame=false
updateVirtualkey()
VK.update()
--Update players
for p=1,#PLAYERS do PLAYERS[p]:update(dt)end
@@ -183,7 +181,7 @@ function scene.draw()
end
--Virtual keys
drawVirtualkeys()
VK.draw()
--Attacking & Being attacked
if GAME.modeEnv.royaleMode then

View File

@@ -4,10 +4,7 @@ local tc=love.touch
local ins=table.insert
local SCR=SCR
local VK=virtualkey
local onVirtualkey=onVirtualkey
local pressVirtualkey=pressVirtualkey
local updateVirtualkey=updateVirtualkey
local VK=VK
local textBox=WIDGET.newTextBox{name="texts",x=340,y=80,w=600,h=550,hide=false}
@@ -38,16 +35,16 @@ scene.mouseDown=NULL
function scene.touchDown(x,y)
if noTouch or not playing then return end
local t=onVirtualkey(x,y)
local t=VK.on(x,y)
if t then
PLAYERS[1]:pressKey(t)
pressVirtualkey(t,x,y)
VK.touch(t,x,y)
end
end
function scene.touchUp(x,y)
if noTouch or not playing then return end
local t=onVirtualkey(x,y)
local t=VK.on(x,y)
if t then
PLAYERS[1]:releaseKey(t)
end
@@ -60,8 +57,9 @@ function scene.touchMove()
for i=#L,1,-1 do
L[2*i-1],L[2*i]=SCR.xOy:inverseTransformPoint(tc.getPosition(L[i]))
end
for n=1,#VK do
local B=VK[n]
local keys=VK.getKeys
for n=1,#keys do
local B=keys[n]
if B.ava then
for i=1,#L,2 do
if(L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
@@ -88,8 +86,9 @@ function scene.keyDown(key)
local k=keyMap.keyboard[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
VK[k].isDown=true
VK[k].pressTime=10
local vk=VK.getKeys()[k]
vk.isDown=true
vk.pressTime=10
end
elseif key=="space"then
NET.signal_ready(not PLY_NET[1].ready)
@@ -100,7 +99,7 @@ function scene.keyUp(key)
local k=keyMap.keyboard[key]
if k and k>0 then
PLAYERS[1]:releaseKey(k)
VK[k].isDown=false
VK.release(k)
end
end
function scene.gamepadDown(key)
@@ -116,8 +115,7 @@ function scene.gamepadDown(key)
local k=keyMap.joystick[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
VK[k].isDown=true
VK[k].pressTime=10
VK.press(k)
end
end
end
@@ -126,7 +124,7 @@ function scene.gamepadUp(key)
local k=keyMap.joystick[key]
if k and k>0 then
PLAYERS[1]:releaseKey(k)
VK[k].isDown=false
VK.release(k)
return
end
end
@@ -185,7 +183,7 @@ function scene.socketRead(cmd,d)
if P.uid==d.uid then
local res,stream=pcall(love.data.decode,"string","base64",d.stream)
if res then
pumpRecording(stream,P.stream)
DATA.pumpRecording(stream,P.stream)
else
LOG.print("Bad stream from "..P.username.."#"..P.uid)
end
@@ -203,7 +201,7 @@ function scene.update(dt)
local GAME=GAME
touchMoveLastFrame=false
updateVirtualkey()
VK.update()
--Update players
for p=1,#PLAYERS do PLAYERS[p]:update(dt)end
@@ -214,7 +212,7 @@ function scene.update(dt)
--Upload stream
if P1.frameRun-lastUpstreamTime>8 then
local stream
stream,upstreamProgress=dumpRecording(GAME.rep,upstreamProgress)
stream,upstreamProgress=DATA.dumpRecording(GAME.rep,upstreamProgress)
if #stream>0 then
NET.uploadRecStream(stream)
else
@@ -235,7 +233,7 @@ function scene.draw()
end
--Virtual keys
drawVirtualkeys()
VK.draw()
--Warning
drawWarning()

View File

@@ -143,8 +143,10 @@ function scene.keyDown(key)
SCN.swapTo("game","none")
end
elseif key=="o"then
if(GAME.result or GAME.replaying)and #PLAYERS==1 and not GAME.saved and saveRecording()then
GAME.saved=true
if(GAME.result or GAME.replaying)and #PLAYERS==1 and not GAME.saved then
if DATA.saveRecording()then
GAME.saved=true
end
end
else
WIDGET.keyPressed(key)

View File

@@ -51,8 +51,7 @@ end
function scene.touchUp()
if selected then
local B=VK_org[selected]
local k=snapUnit
B.x,B.y=int(B.x/k+.5)*k,int(B.y/k+.5)*k
B.x,B.y=int(B.x/snapUnit+.5)*snapUnit,int(B.y/snapUnit+.5)*snapUnit
end
end
function scene.touchMove(_,_,dx,dy)
@@ -62,41 +61,19 @@ function scene.touchMove(_,_,dx,dy)
end
end
local function virtualkeyPreview()
if SETTING.VKSwitch then
for i=1,#VK_org do
local B=VK_org[i]
if B.ava then
gc.setColor(1,1,1,SETTING.VKAlpha)
gc.setLineWidth(B.r*.07)
gc.circle("line",B.x,B.y,B.r,10)
if selected==i and TIME()%.26<.13 then
gc.setColor(1,1,1,SETTING.VKAlpha*.62)
gc.circle("fill",B.x,B.y,B.r,10)
end
if SETTING.VKIcon then
local c=B.color
gc.setColor(c[1],c[2],c[3],SETTING.VKAlpha)
gc.draw(TEXTURE.VKIcon[i],B.x,B.y,nil,B.r*.025,nil,18,18)
end
end
end
end
end
function scene.draw()
gc.setColor(1,1,1)
gc.setLineWidth(7)gc.rectangle("line",340,15,600,690)
gc.setLineWidth(3)gc.rectangle("line",490,85,300,600)
virtualkeyPreview()
local d=snapUnit
if d>=10 then
VK.preview(selected)
if snapUnit>=10 then
gc.setLineWidth(3)
gc.setColor(1,1,1,sin(TIME()*4)*.1+.1)
for i=1,1280/d-1 do
gc.line(d*i,0,d*i,720)
for i=1,1280/snapUnit-1 do
gc.line(snapUnit*i,0,snapUnit*i,720)
end
for i=1,720/d-1 do
gc.line(0,d*i,1280,d*i)
for i=1,720/snapUnit-1 do
gc.line(0,snapUnit*i,1280,snapUnit*i)
end
end
end

View File

@@ -52,6 +52,7 @@ return STRING.split([=[
新增users模块用来管理网络用户缓存信息
play场景改名game
重构GAME.frame相关内容
大规模整理代码
修复:
登录界面邮箱格式判定错误
调整主菜单点击联网游戏按钮代码的逻辑

164
parts/virtualKey.lua Normal file
View File

@@ -0,0 +1,164 @@
local SETTING=SETTING
local keys={}
for i=1,#VK_org do keys[i]={}end--In-game virtualkey layout
local VK={}
function VK.getKeys()
return keys
end
function VK.on(x,y)
local dist,nearest=1e10
for K=1,#keys do
local B=keys[K]
if B.ava then
local d1=(x-B.x)^2+(y-B.y)^2
if d1<B.r^2 then
if d1<dist then
nearest,dist=K,d1
end
end
end
end
return nearest
end
function VK.touch(id,x,y)
local B=keys[id]
B.isDown=true
B.pressTime=10
if SETTING.VKTrack then
--Auto follow
local O=VK_org[id]
local _FW,_CW=SETTING.VKTchW,1-SETTING.VKCurW
local _OW=1-_FW-_CW
--(finger+current+origin)
B.x=x*_FW+B.x*_CW+O.x*_OW
B.y=y*_FW+B.y*_CW+O.y*_OW
--Button collision (not accurate)
if SETTING.VKDodge then
for i=1,#keys do
local b=keys[i]
local d=B.r+b.r-((B.x-b.x)^2+(B.y-b.y)^2)^.5--Hit depth(Neg means distance)
if d>0 then
b.x=b.x+(b.x-B.x)*d*b.r*2.6e-5
b.y=b.y+(b.y-B.y)*d*b.r*2.6e-5
end
end
end
end
SFX.play("virtualKey",SETTING.VKSFX)
VIB(SETTING.VKVIB)
end
function VK.press(id)
keys[id].isDown=true
keys[id].pressTime=10
end
function VK.release(id)
keys[id].isDown=false
end
function VK.switchKey(id,on)
keys[id].ava=on
end
function VK.restore()
for i=1,#VK_org do
local B,O=keys[i],VK_org[i]
B.ava=O.ava
B.x=O.x
B.y=O.y
B.r=O.r
B.color=O.color
B.isDown=false
B.pressTime=0
end
for k,v in next,PLAYERS[1].keyAvailable do
if not v then
keys[k].ava=false
end
end
end
function VK.update()
if SETTING.VKSwitch then
for i=1,#keys do
local _=keys[i]
if _.pressTime>0 then
_.pressTime=_.pressTime-1
end
end
end
end
local gc=love.graphics
local gc_circle,gc_draw,gc_setColor,gc_setLineWidth=gc.circle,gc.draw,gc.setColor,gc.setLineWidth
function VK.draw()
if SETTING.VKSwitch then
local a=SETTING.VKAlpha
local _
if SETTING.VKIcon then
local icons=TEXTURE.VKIcon
for i=1,#keys do
if keys[i].ava then
local B=keys[i]
gc_setColor(1,1,1,a)
gc_setLineWidth(B.r*.07)
gc_circle("line",B.x,B.y,B.r,10)--Button outline
_=keys[i].pressTime
gc_setColor(B.color[1],B.color[2],B.color[3],a)
gc_draw(icons[i],B.x,B.y,nil,B.r*.026+_*.08,nil,18,18)--Icon
if _>0 then
gc_setColor(1,1,1,a*_*.08)
gc_circle("fill",B.x,B.y,B.r*.94,10)--Glow when press
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)--Ripple
end
end
end
else
for i=1,#keys do
if keys[i].ava then
local B=keys[i]
gc_setColor(1,1,1,a)
gc_setLineWidth(B.r*.07)
gc_circle("line",B.x,B.y,B.r,10)
_=keys[i].pressTime
if _>0 then
gc_setColor(1,1,1,a*_*.08)
gc_circle("fill",B.x,B.y,B.r*.94,10)
gc_circle("line",B.x,B.y,B.r*(1.4-_*.04),10)
end
end
end
end
end
end
function VK.preview(selected)
if SETTING.VKSwitch then
for i=1,#VK_org do
local B=VK_org[i]
if B.ava then
gc_setColor(1,1,1,SETTING.VKAlpha)
gc_setLineWidth(B.r*.07)
gc_circle("line",B.x,B.y,B.r,10)
if selected==i and TIME()%.26<.13 then
gc_setColor(1,1,1,SETTING.VKAlpha*.62)
gc_circle("fill",B.x,B.y,B.r,10)
end
if SETTING.VKIcon then
local c=B.color
gc_setColor(c[1],c[2],c[3],SETTING.VKAlpha)
gc_draw(TEXTURE.VKIcon[i],B.x,B.y,nil,B.r*.025,nil,18,18)
end
end
end
end
end
return VK