Compare commits

...

57 Commits

Author SHA1 Message Date
MrZ626
4e073d1bb6 添加0.14.4更新日志和版本号 2021-04-13 00:34:53 +08:00
MrZ626
2fbb295490 修复小程序15p盲打颜色配置错误 2021-04-13 00:32:29 +08:00
MrZ626
b72631cd82 修复一个小程序入口名错误 2021-04-13 00:27:57 +08:00
MrZ626
832c09980a 修复小程序2048之前在删goto时造成的逻辑错误 2021-04-13 00:26:02 +08:00
MrZ626
ca68a8ef87 玩家死亡消息以服务器为准,录像不同步不再影响结算 2021-04-12 23:10:39 +08:00
MrZ626
0645cec207 修改可能导致ws尝试发送数字消息然后报错的一处代码 2021-04-12 21:38:20 +08:00
MrZ626
53dde3ec9e 更换催促等待提示音 2021-04-12 21:27:37 +08:00
MrZ626
df5c16e05f 对战房间的准备按钮颜色和文本会随状态改变 2021-04-12 21:25:11 +08:00
MrZ626
bb3bb938e8 新BGM:vacuum(用于节日主题),zday拆分为zday1和zday2 2021-04-12 21:13:02 +08:00
MrZ626
c196a2104e 修改隐形模式BGM配置 2021-04-12 21:06:14 +08:00
MrZ626
c78c596095 修复master-ph错误,使用新BGM:super7th 2021-04-12 20:59:52 +08:00
MrZ626
8d2d0f0b22 修复his序列模式算法错误 2021-04-12 20:52:49 +08:00
MrZ626
26d06e8f3a 添加触摸/点击特效开关 2021-04-12 20:39:21 +08:00
MrZ626
59eb8ae7f1 调整画面设置ui 2021-04-12 19:15:52 +08:00
MrZ626
7d932016b8 联网对战时禁用鼠标右键返回 2021-04-12 18:48:34 +08:00
MrZ626
998eb56348 调整存档更新代码 2021-04-12 12:57:57 +08:00
MrZ626
7837064e80 不再接受过老版本的存档,每次启动删除存档文件夹内裸露的文件 2021-04-12 12:55:22 +08:00
MrZ626
53745c61e5 修改注册时的合法邮箱格式 2021-04-12 02:37:13 +08:00
MrZ626
14adcff9dc splitStr模块可开关正则(默认不用) 2021-04-12 02:08:54 +08:00
MrZ626
7d67288766 修复O块在变形后hold失去名字和颜色属性 2021-04-12 00:25:28 +08:00
MrZ626
d904b126df 自定义场地默认使用智能画笔 2021-04-11 23:02:05 +08:00
MrZ626
649df9be49 修复催促准备音效在玩家准备后也会播放 2021-04-11 21:50:18 +08:00
MrZ626
4e49c1f80d 修复进游戏场景前收到部分socket消息会报错 2021-04-11 21:38:16 +08:00
MrZ626
41eda72394 更新0.14.3的日志和版本号 2021-04-11 21:04:01 +08:00
MrZ626
8a49398740 修正说明书的错别字 2021-04-11 20:52:00 +08:00
MrZ626
6fbec2b298 自动登录时机修改为ws-app连接成功并且版本是最新 2021-04-11 20:43:29 +08:00
MrZ626
15d8bbead9 文本框控件不再有新消息提示音 2021-04-11 20:42:45 +08:00
MrZ626
f2d72d70f1 微调玩家准备相关交互 2021-04-11 20:42:24 +08:00
MrZ626
0bcfd10a9d 修复test场景触屏点击报错 2021-04-11 20:23:16 +08:00
MrZ626
324b4f1b38 进入联网菜单时获取授权操作的锁改为连接成功后释放 2021-04-11 20:16:47 +08:00
MrZ626
27f11db7f4 注册成功后自动返回主菜单 2021-04-11 16:09:48 +08:00
MrZ626
0c734c5351 更新赞助名单 2021-04-11 15:31:58 +08:00
MrZ626
48da6a84a6 进房固定1.26秒cd 2021-04-11 14:26:23 +08:00
MrZ626
21cb2657ca 整理代码 2021-04-11 14:22:51 +08:00
MrZ626
b7ee5e771e 完善0.14.2更新日志 2021-04-11 13:55:36 +08:00
MrZ626
4967782464 减少一个ws库debug开启后可能输出的信息 2021-04-11 13:37:23 +08:00
MrZ626
29582469d2 成功登录后不再尝试清除登录界面的输入框 2021-04-11 13:36:57 +08:00
MrZ626
18c1c9c69a 重新启用注册菜单 2021-04-11 13:36:04 +08:00
MrZ626
ed3521cc53 添加0.14.2版本号和版本说明 2021-04-11 02:23:14 +08:00
MrZ626
4795d77e84 整理代码(远程玩家录像播放) 2021-04-11 02:19:02 +08:00
MrZ626
e0c594c402 攻击特效从全局改为玩家设置项一部分 2021-04-11 02:18:01 +08:00
MrZ626
5f02042124 微调联网游戏房间内ui 2021-04-11 01:57:03 +08:00
MrZ626
4b09023b21 修改词典的techmino词条,加上联网功能说明 2021-04-11 01:52:45 +08:00
MrZ626
320197198b 整理代码 2021-04-11 01:50:52 +08:00
MrZ626
d31423d91e 删除马拉松模式忘了删的测试代码 2021-04-10 23:00:23 +08:00
MrZ626
23bb6ac486 对战传输的玩家配置信息格式简化和修复一个问题(未使用所以从未触发) 2021-04-10 22:24:38 +08:00
MrZ626
7da178c5ec 减少联网玩家传输的设置项 2021-04-10 22:14:19 +08:00
MrZ626
1fe9d2598b 联网推进(修复尝试保存用户信息时错误) 2021-04-10 21:07:26 +08:00
MrZ626
9f56948f47 移除进入已经开始游戏的房间时弹出的提示 2021-04-10 18:33:42 +08:00
MrZ626
4e2822eb0a 修复创建房间失败问题(打错房间类型),微调房间内ui 2021-04-10 17:05:45 +08:00
MrZ626
54697c44de VERSION改为全局table并包含版本名称 2021-04-10 16:56:27 +08:00
MrZ626
b757055525 点击联网游戏时无网络的提示更加清晰 2021-04-10 16:51:21 +08:00
MrZ626
906211f0f5 更改版本号为0.14.1 2021-04-10 16:34:38 +08:00
MrZ626
05808e4587 整理代码,准备缓存用户信息相关功能 2021-04-10 16:18:47 +08:00
MrZ626
0b685cc9a2 更换新的服务器域名 2021-04-10 15:40:28 +08:00
MrZ626
a9985fec2c 增加联网对战模式的垃圾行上涨速度,添加0.14.1更新说明 2021-04-10 02:57:45 +08:00
MrZ626
315237d0fc 限制客户端一般只能开单挑房,电脑用户可以开多人房,特殊电脑用户可以开更大的房 2021-04-10 02:48:51 +08:00
53 changed files with 435 additions and 319 deletions

View File

@@ -124,7 +124,7 @@ function love.mousepressed(x,y,k,touch)
WIDGET.press(mx,my)
end
lastX,lastY=mx,my
SYSFX.newTap(3,mx,my,30)
if SETTING.clickFX then SYSFX.newTap(3,mx,my,30)end
end
function love.mousemoved(x,y,dx,dy,touch)
if touch then return end
@@ -194,7 +194,7 @@ function love.touchreleased(id,x,y)
if SCN.touchUp then SCN.touchUp(x,y)end
if(x-lastX)^2+(y-lastY)^2<62 then
if SCN.touchClick then SCN.touchClick(x,y)end
SYSFX.newTap(3,x,y,30)
if SETTING.clickFX then SYSFX.newTap(3,x,y,30)end
end
end
@@ -390,7 +390,7 @@ function love.errorhandler(msg)
--Write messages to log file
love.filesystem.append("conf/error.log",
os.date("%Y/%m/%d %A %H:%M:%S\n")..
#ERRDATA.." crash(es) "..SYSTEM.."-"..VERSION_NAME.." scene: "..scn.."\n"..
#ERRDATA.." crash(es) "..SYSTEM.."-"..VERSION.string.." scene: "..scn.."\n"..
table.concat(err,"\n",1,c-2).."\n\n"
)
@@ -432,7 +432,7 @@ function love.errorhandler(msg)
setFont(100)gc_print(":(",100,0,0,1.2)
setFont(40)gc.printf(errorMsg,100,160,SCR.w0-100)
setFont(20)
gc_print(SYSTEM.."-"..VERSION_NAME.." scene:"..(SCN and SCN.cur or"NULL"),100,660)
gc_print(SYSTEM.."-"..VERSION.string.." scene:"..(SCN and SCN.cur or"NULL"),100,660)
gc.printf(err[1],100,360,1260-100)
gc_print("TRACEBACK",100,450)
for i=4,#err-2 do

View File

@@ -4,7 +4,7 @@ local ins,rem=table.insert,table.remove
local debugMesList={}
local debugMesHistory={
"Version: "..VERSION_NAME,
"Version: "..VERSION.string,
os.date("Launched at %Y/%m/%d %H:%M"),
}
local LOG={}

View File

@@ -1,11 +1,19 @@
local find,sub=string.find,string.sub
return function(s,sep)
return function(s,sep,regex)
local L={}
local p1,p2=1--start,target
while p1<=#s do
p2=find(s,sep,p1)or #s+1
L[#L+1]=sub(s,p1,p2-1)
p1=p2+#sep
if regex then
while p1<=#s do
p2=find(s,sep,p1)or #s+1
L[#L+1]=sub(s,p1,p2-1)
p1=p2+#sep
end
else
while p1<=#s do
p2=find(s,sep,p1,true)or #s+1
L[#L+1]=sub(s,p1,p2-1)
p1=p2+#sep
end
end
return L
end

View File

@@ -31,9 +31,13 @@ function THEME.calculate(Y,M,D)
M=="04"and D=="01"and
"fool"or
--Z day (Feb./Mar./Apr./May./June 26)
math.abs(M-4)<=2 and D+0==26 and
"zday"or
--Z day (1) (Feb./Mar./Apr. 26)
math.abs(M-3)<=1 and D=="26"and
"zday1"or
--Z day (2) (May./June 26)
math.abs(M-5.5)<=1 and D=="26"and
"zday2"or
"classic"
end
@@ -54,9 +58,12 @@ function THEME.set(theme)
LOG.print(" ★☆☆★",COLOR.red)
LOG.print("新年快乐!",COLOR.white)
LOG.print(" ★☆☆★",COLOR.red)
elseif theme=="zday"then
elseif theme=="zday1"then
BG.setDefault("lanterns")
BGM.setDefault("overzero")
elseif theme=="zday2"then
BG.setDefault("lanterns")
BGM.setDefault("vacuum")
elseif theme=="fool"then
BG.setDefault("blockrain")
BGM.setDefault("how feeling")

View File

@@ -1,6 +1,8 @@
-- local host="192.168.114.102"
-- local host="127.0.0.1"
local host="hdustea.3322.org"
-- local host="192.168.114.102"
-- local host="krakens.tpddns.cn"
-- local host="hdustea.3322.org"
local host="game.techmino.org"
local port="10026"
local path="/tech/socket/v1"
@@ -84,9 +86,9 @@ local _send do
local mask_key={1,14,5,14}
local mask_str=char(unpack(mask_key))
function _send(opcode,message)
function _send(op,message)
--Message type
SOCK:send(char(bor(0x80,opcode)))
SOCK:send(char(bor(0x80,op)))
if message then
--Length
@@ -149,7 +151,6 @@ while true do--Running
--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))

View File

@@ -848,7 +848,6 @@ function textBox:push(t)
if self.scrollPos==#self.texts-1 then
self.scrollPos=#self.texts
else
SFX.play("spin_0",.6)
self.new=true
end
end

View File

@@ -1,5 +1,8 @@
VERSION_CODE=1400
VERSION_NAME="Alpha V0.14.0"
VERSION={
code=1404,
string="Alpha V0.14.4",
name="日出 Sunrise",
}
function love.conf(t)
t.identity="Techmino"--Saving folder
t.version="11.1"
@@ -12,7 +15,7 @@ function love.conf(t)
end
local W=t.window
W.title="Techmino "..VERSION_NAME
W.title="Techmino "..VERSION.string
W.icon="media/image/icon.png"
W.width,W.height=1280,720
W.minwidth,W.minheight=640,360

View File

@@ -33,37 +33,21 @@ love.keyboard.setKeyRepeat(true)
love.keyboard.setTextInput(false)
love.mouse.setVisible(false)
--Create directories
for _,v in next,{"conf","record","replay"}do
local info=fs.getInfo(v)
if not info then
fs.createDirectory(v)
elseif info.type ~= 'directory' then
fs.remove(v)
fs.createDirectory(v)
--Delete all files from too old version
for _,name in next,fs.getDirectoryItems("")do
if fs.getRealDirectory(name)==SAVEDIR and fs.getInfo(name).type~="directory"then
fs.remove(name)
end
end
--Collect files of old version
if fs.getInfo("data.dat")or fs.getInfo("key.dat")or fs.getInfo("settings.dat")then
for k,v in next,{
["settings.dat"]="conf/settings",
["unlock.dat"]="conf/unlock",
["data.dat"]="conf/data",
["key.dat"]="conf/key",
["virtualkey.dat"]="conf/virtualkey",
["account.dat"]="conf/user",
}do
if fs.getInfo(k)then
fs.write(v,fs.read(k))
fs.remove(k)
end
end
for _,name in next,fs.getDirectoryItems("")do
if name:sub(-4)==".dat"then
fs.write("record/"..name:sub(1,-4).."rec",fs.read(name))
fs.remove(name)
end
--Create directories
for _,v in next,{"conf","record","replay","cache"}do
local info=fs.getInfo(v)
if not info then
fs.createDirectory(v)
elseif info.type~="directory"then
fs.remove(v)
fs.createDirectory(v)
end
end
@@ -274,6 +258,7 @@ do
end
if STAT.version<1400 then
fs.remove("conf/user")
fs.remove("conf/key")
SETTING.appLock=false
needSave=true
autoRestart=true
@@ -316,23 +301,17 @@ do
RANKS.sprint_10l=0
needSave=true
end
if STAT.version~=VERSION.code then
newVersionLaunch=true
STAT.version=VERSION.code
FILE.save(STAT,"conf/data","q")
end
if needSave then
FILE.save(RANKS,"conf/unlock","q")
FILE.save(SETTING,"conf/settings","q")
end
if keyMap[1]then
autoRestart=true
fs.remove("conf/key")
end
USER.username=nil
if STAT.version~=VERSION_CODE then
newVersionLaunch=true
STAT.version=VERSION_CODE
FILE.save(STAT,"conf/data","q")
end
if autoRestart then
love.event.quit("restart")
end

BIN
media/BGM/super7th.ogg Normal file

Binary file not shown.

BIN
media/BGM/vacuum.ogg Normal file

Binary file not shown.

View File

@@ -661,16 +661,21 @@ do--function dumpBasicConfig()
"skin","face",
--Graphic
"block","ghost","center","smooth","grid","bagLine",
"lockFX","dropFX","moveFX","clearFX","splashFX","shakeFX","atkFX",
"text","score","warn","highCam","nextPos",
"block","ghost","center","bagLine",
"dropFX","moveFX","shakeFX",
"text","highCam","nextPos",
--Unnecessary graphic
-- "grid","smooth",
-- "lockFX","clearFX","splashFX","atkFX",
-- "score",
}
function dumpBasicConfig()
local S={}
for _,key in next,gameSetting do
S[key]=SETTING[key]
end
return data.encode("string","base64",JSON.encode(S))
return JSON.encode(S)
end
end
do--function resetGameData(args)
@@ -956,7 +961,7 @@ do--function saveRecording()
local fileHead=
os.date("%Y/%m/%d %A %H:%M:%S\n")..
GAME.curModeName.."\n"..
VERSION_NAME.."\n"..
VERSION.string.."\n"..
(USER.username or"Player")
local fileBody=
GAME.seed.."\n"..

View File

@@ -276,6 +276,7 @@ SETTING={--Settings
fullscreen=true,
bg=true,
powerInfo=false,
clickFX=true,
--Sound
sfx=1,
@@ -305,7 +306,7 @@ if S then--Statistics
STAT=S
else
STAT={
version=VERSION_CODE,
version=VERSION.code,
run=0,game=0,time=0,frame=0,
key=0,rotate=0,hold=0,
extraPiece=0,finesseRate=0,

View File

@@ -148,7 +148,7 @@ return{
{"Techmino",
"techmino",
"game",
"*Windows, MacOS, Android | Single player*\nA game with many modes and loads of customization. Low input delay, decent controls.",
"*Windows, MacOS, Android | Single player and multiplyer*\nA game with many modes and loads of customization. Low input delay, decent controls.",
},
{"Cultris II",
"c2 cultris2 cultrisii",
@@ -924,7 +924,7 @@ return{
{"gggf",
"gggf kissne",
"name",
"Tetris Research community member.\nPersonal bests: Sprint 22.831 seconds (25.483 seconds on mobile), MPH Sprint 56 seconds, U rank on Tetr.io\nOne of the top players of 20G in China, achieved almost every achievement in TGM3.",
"Tetris Research community member.\nPersonal bests: Sprint 22.831 seconds (25.483 seconds on mobile), MPH Sprint 56 seconds, X rank on Tetr.io\nOne of the top players of 20G in China, achieved almost every achievement in TGM3.",
"https://space.bilibili.com/287769888",
},
{"xb",

View File

@@ -153,7 +153,7 @@ return{
{"Techmino",
"techmino tieke",
"game",
"一个win/android/linux/macOS方块只有单机,但是模式和各种设置都很齐全,适合有一定基础的新人,输入延迟很小,手感很好",
"一个win/android/linux/macOS方块单机模式和各种设置都很齐全,联机正在逐渐开发中,输入延迟很小,手感很好",
},
{"Cultris II",
"c2 cultris2 cultrisii",
@@ -603,7 +603,7 @@ return{
{"输入延迟",
"输入延迟 input delay",
"term",
"用任何设备玩任何游戏时,所有的操作(按键盘,点鼠标等)都会晚一点点(很短,几毫秒到几十毫秒)才达游戏如果过长就会很影响游戏手感作用效果类似于你拿qq远程控制打fps游戏\ntop、te等游戏比较明显\n这个延迟一般由硬件性能,硬件状态影响,通常来说不可设置,开启性能模式(或者关闭节能模式)可能会好一点",
"用任何设备玩任何游戏时,所有的操作(按键盘,点鼠标等)都会晚一点点(很短,几毫秒到几十毫秒)才达游戏如果过长就会很影响游戏手感作用效果类似于你拿qq远程控制打fps游戏\ntop、te等游戏比较明显\n这个延迟一般由硬件性能,硬件状态影响,通常来说不可设置,开启性能模式(或者关闭节能模式)可能会好一点",
},
{"Cold Clear",
"cc coldclear",
@@ -934,7 +934,7 @@ return{
{"gggf",
"gggf kissne t127",
"name",
"【研究群】「T127」\n40行22.831秒(手机25.483)MPH40行56秒tetr.io段位Utop数据约60L85A\n20G规则国内一流玩家拿到了TGM3几乎全部的最终成就(全世界都没几个)\n其他名称:小柒 kissne 127\n还是车车人,几个正作成绩:永EX NM 1B FS 风L NM",
"【研究群】「T127」\n40行22.831秒(手机25.483)MPH40行56秒tetr.io段位X数据约60L95A\n20G规则国内一流玩家拿到了TGM3几乎全部的最终成就(全世界都没几个)\n其他名称:小柒 kissne 127\n还是车车人,几个正作成绩:永EX NM 1B FS 风L NM",
"https://space.bilibili.com/287769888",
},
{"xb",

View File

@@ -73,6 +73,7 @@ return{
getVersionFail="Update detection failed",
oldVersion="Version $1 is now available!",
needUpdate="Newer version required!",
noInternet="Not connected to the network",
notFinished="Coming soon!",
jsonError="JSON error",
@@ -258,7 +259,8 @@ return{
down="",
},
net_game={
ready="Ready/Cancel",
ready="Ready",
cancel="Cancel",
},
net_chat={
send="Send",
@@ -309,8 +311,9 @@ return{
highCam="Screen Scrolling",
nextPos="Next Preview",
fullscreen="Full Screen",
bg="Background",
power="Power Info",
clickFX="Click FX",
bg="Background",
clean="Fast Draw",
},
setting_sound={
@@ -600,6 +603,7 @@ return{
email="Email Address",
password="Password",
password2="Re-enter Password",
register="Register",
},
account={
title="Account",

View File

@@ -74,6 +74,7 @@ return{
getVersionFail="Echec d'obtention de la dernière version",
oldVersion="La version $1 est disponible !",
-- needUpdate="Newer version required!",
-- noInternet="Not connected to the network",
-- notFinished="Coming soon!",
jsonError="Erreur json",
@@ -230,7 +231,8 @@ return{
down="",
},
net_game={
-- ready="Ready/Cancel",
-- ready="Ready",
-- cancel="Cancel",
},
net_chat={
send="Envoyer",
@@ -283,8 +285,9 @@ return{
highCam="Vue d'oiseau",
nextPos="Prévisualisation de position",
fullscreen="Plein écran",
bg="Arrière-plan",
power="Infos d'alimentation",
-- clickFX="Click FX",
bg="Arrière-plan",
-- clean="Fast Draw",
},
setting_sound={
@@ -511,6 +514,7 @@ return{
email="E-mail",
password="Mot de passe",
password2="Confirmer le mot de passe",
register="Enregistrement",
},
account={
title="Compte",

View File

@@ -73,6 +73,7 @@ return{
getVersionFail="Falha ao detectar uma versão nova",
oldVersion="Versão $1 esta disponível agora!",
-- needUpdate="Newer version required!",
-- noInternet="Not connected to the network",
-- notFinished="Coming soon!",
jsonError="Json error",
@@ -258,7 +259,8 @@ return{
down="",
},
net_game={
-- ready="Ready/Cancel",
-- ready="Ready",
-- cancel="Cancel",
},
net_chat={
send="Mandar",
@@ -309,8 +311,9 @@ return{
highCam="Vista Olho-de-pássaro",
nextPos="Próxima Pos.",
fullscreen="Tela cheia",
bg="Fundo",
power="Informação bateria",
-- clickFX="Click FX",
bg="Fundo",
-- clean="Fast Draw",
},
setting_sound={
@@ -594,11 +597,12 @@ return{
},
register={
title="Registrar",
login="Registrar",
login="Log in",
username="Nome De Usuário",
email="Endereço De Email",
password="Senha",
password2="Entre Senha Novamente",
register="Registrar",
},
account={
title="Conta",

View File

@@ -74,6 +74,7 @@ return{
getVersionFail="Error al buscar nuevas versiones.",
oldVersion="¡Está disponible la nueva versión $1!",
needUpdate="¡Nueva versión requerida!",
-- noInternet="Not connected to the network",
notFinished="Próximamente",
jsonError="Error en Json",
@@ -237,6 +238,7 @@ return{
},
net_game={
ready="Estoy Listo",
-- cancel="Cancel",
},
net_chat={
send="Enviar",
@@ -287,8 +289,9 @@ return{
highCam="Cám. Vista Aérea",
nextPos="Ver Spawn de Pza. Sig.",
fullscreen="Pant. Completa",
bg="Fondo",
power="Inf. de Batería",
-- clickFX="Click FX",
bg="Fondo",
clean="Fast Draw",
},
setting_sound={
@@ -514,6 +517,7 @@ return{
email="Correo Elec.",
password="Contraseña",
password2="Repetir Contr.",
register="Registrarse",
},
account={
title="Cuenta",

View File

@@ -169,8 +169,9 @@ return{
highCam="↑__↑",
nextPos="???←",
fullscreen="|←→|",
bg="__?__",
power="+.",
clickFX="_.~",
bg="__?__",
clean="[]→→O",
},
setting_sound={
@@ -444,6 +445,7 @@ return{
email="@",
password="*",
password2="*",
register="Sign up",
},
account={
title="@_@",

View File

@@ -113,7 +113,7 @@ return{
qq="QQ对线",
},
register={
password2="觉得应该填啥",
password2="该填啥",
},
sound={
title="音效室",

View File

@@ -72,7 +72,8 @@ return{
getNoticeFail="拉取公告失败",
getVersionFail="检测新版本失败",
oldVersion="最新版本$1可以下载了!",
needUpdate="此功能需要更新游戏!",
needUpdate="更新游戏!",
noInternet="还未连接到网络",
notFinished="暂未完成,敬请期待!",
jsonError="json错误",
@@ -258,7 +259,8 @@ return{
down="",
},
net_game={
ready="准备/取消",
ready="准备",
cancel="取消",
},
net_chat={
send="发送",
@@ -309,8 +311,9 @@ return{
highCam="超屏视野",
nextPos="生成预览",
fullscreen="全屏",
bg="背景",
power="电量显示",
clickFX="点按特效",
bg="背景",
clean="绘制优化",
},
setting_sound={
@@ -598,6 +601,7 @@ return{
email="邮箱",
password="密码",
password2="确认密码",
register="注册",
},
account={
title="账户",

View File

@@ -69,6 +69,6 @@ back to back(B2B)点数说明:
打"X"的格子不允许有方块;
空的格子可以是任何状态;
普通的七种彩色方块必须颜色对应;
垃圾行方块的为止只要有方块就可以,但是不能是空气.
垃圾行方块的位置只要有方块就可以,但是不能是空气.
玩家拼出画的图后就会判定胜利.
]=],"\n")

View File

@@ -6,7 +6,7 @@ return{
visible="easy",
dropPiece=function(P)if P.stat.row>=200 then P:win("finish")end end,
freshLimit=10,
bg="glow",bgm="reason",
bg="glow",bgm="push",
},
pauseLimit=true,
load=function()

View File

@@ -10,7 +10,7 @@ return{
score=false,
dropPiece=function(P)if P.stat.row>=200 then P:win("finish")end end,
freshLimit=15,
bg="rgb",bgm="reason",
bg="rgb",bgm="push",
},
pauseLimit=true,
load=function()

View File

@@ -11,7 +11,7 @@ return{
score=false,
dropPiece=function(P)if P.stat.row>=200 then P:win("finish")end end,
freshLimit=15,
bg="rgb",bgm="reason",
bg="rgb",bgm="push",
},
pauseLimit=true,
load=function()

View File

@@ -7,7 +7,7 @@ return{
freshLimit=10,
visible="fast",
dropPiece=function(P)if P.stat.row>=200 then P:win("finish")end end,
bg="glow",bgm="reason",
bg="glow",bgm="push",
},
pauseLimit=true,
load=function()

View File

@@ -10,7 +10,7 @@ return{
score=false,
dropPiece=function(P)if P.stat.row>=100 then P:win("finish")end end,
freshLimit=15,
bg="rgb",bgm="push",
bg="rgb",bgm="far",
},
pauseLimit=true,
load=function()

View File

@@ -10,7 +10,7 @@ return{
visible="none",
dropPiece=function(P)if P.stat.row>=40 then P:win("finish")end end,
freshLimit=15,
bg="none",bgm="push",
bg="none",bgm="far",
},
pauseLimit=true,
load=function()

View File

@@ -8,9 +8,6 @@ return{
drop=60,wait=8,fall=20,
task=function(P)P.modeData.target=10 end,
dropPiece=function(P)
if P.stat.row<180 then
P.stat.row=180
end
if P.stat.row>=P.modeData.target then
if P.modeData.target==200 then
P:win("finish")

View File

@@ -14,7 +14,7 @@ return{
local p=P.modeData.pt+P.lastPiece.row
if p>=P.modeData.target then
local ENV=P.gameEnv
local T=ENV.target
local T=P.modeData.target
--Stage 1: clear 3 techrash
if T==12 then--Stage 2: swap color of S/Z & J/L
P.waiting=30
@@ -28,7 +28,7 @@ return{
ENV.fall=7
P:setNext(4)
ENV.target=26
P.modeData.target=26
SFX.play("reach")
elseif T==26 then--Stage 3: dig to bottom
if not P.holdQueue[1]then P.life=P.life+1 end--1 up if ban hold
@@ -70,7 +70,7 @@ return{
ENV.fall=6
P:setNext(5)
ENV.target=42
P.modeData.target=42
SFX.play("reach")
elseif T==42 then--Stage 4: survive in high speed
if P.garbageBeneath==0 then
@@ -80,7 +80,7 @@ return{
P:setHold(false)
ENV.bone=true
ENV.target=62
P.modeData.target=62
else
p=41
end
@@ -92,7 +92,7 @@ return{
ENV.easyFresh=false
ENV.target=126
P.modeData.target=126
SFX.play("reach")
elseif T==126 then--Stage 6: speed up
P.life=P.life+1
@@ -101,7 +101,7 @@ return{
ENV.wait=4
ENV.fall=4
ENV.target=162
P.modeData.target=162
elseif T==162 then--Stage 7: speed up+++
P.life=P.life+1
@@ -110,7 +110,7 @@ return{
P:setHold(true)
P:setInvisible(180)
ENV.target=226
P.modeData.target=226
SFX.play("reach")
elseif T==226 then--Stage 8: final invisible
P.life=P.life+2
@@ -118,7 +118,7 @@ return{
ENV.bone=false
P:setInvisible(90)
ENV.target=259
P.modeData.target=259
SFX.play("reach")
elseif T==259 then--Stage 9: ending
P.life=P.life+1
@@ -130,7 +130,7 @@ return{
ENV.mission={4,4,4,4,4,4,4,4}
ENV.missionKill=false
ENV.target=260
P.modeData.target=260
p=260
SFX.play("blip_2")
else
@@ -142,7 +142,7 @@ return{
mission={4,4,4,64},
missionKill=true,
freshLimit=12,
bg="none",bgm="distortion",
bg="none",bgm="super7th",
},
slowMark=true,
load=function()

View File

@@ -3,6 +3,7 @@ return{
env={
drop=30,
freshLimit=15,
pushSpeed=5,
garbageSpeed=2,
noMod=true,
bg="space",

View File

@@ -2,6 +2,7 @@ local data=love.data
local ins,rem=table.insert,table.remove
local WS,TIME=WS,TIME
local NET={
connected=false,
allow_online=false,
roomList={},
accessToken=false,
@@ -120,11 +121,23 @@ function NET.wsclose_stream()
end
--Account
function NET.register(username,email,password)
if NET.lock("register")then
WS.send("app",JSON.encode{
action=2,
data={
username=username,
email=email,
password=password,
}
})
end
end
function NET.pong(wsName,message)
WS.send(wsName,message,"pong")
WS.send(wsName,type(message)=="string"and message or"","pong")
end
function NET.getAccessToken()
if NET.lock("accessToken",3)then
if NET.lock("access_and_login",10)then
WS.send("user",JSON.encode{action=0})
end
end
@@ -137,23 +150,20 @@ function NET.getUserInfo(id,ifDetail)
},
})
end
function NET.storeUserInfo(res)
local user=USERS[res.uid]
function NET.storeUserInfo(d)
local user=USERS[d.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
USERS[d.uid]=user
end
user.uid=d.uid
user.username=d.username
user.motto=d.motto
user.avatar=d.avatar
--Get own name
if res.uid==USER.uid then
USER.username=res.username
if d.uid==USER.uid then
USER.username=d.username
FILE.save(USER,"conf/user","q")
end
@@ -173,13 +183,13 @@ function NET.fetchRoom()
})
end
end
function NET.createRoom()
if NET.lock("enterRoom",3)then
function NET.createRoom(roomType,name)
if NET.lock("enterRoom",1.26)then
WS.send("play",JSON.encode{
action=1,
data={
type="classic",
name=(USER.username or"???").."'s room",
type=roomType,
name=name,
password=nil,
config=dumpBasicConfig(),
}
@@ -187,7 +197,7 @@ function NET.createRoom()
end
end
function NET.enterRoom(roomID,password)
if NET.lock("enterRoom",3)then
if NET.lock("enterRoom",1.26)then
NET.rid=roomID
WS.send("play",JSON.encode{
action=2,
@@ -247,13 +257,27 @@ function NET.updateWS_app()
else
local res=_parse(message)
if res then
if VERSION_CODE>=res.lowest then
NET.allow_online=true
if res.type=="Connect"then
NET.connected=true
if VERSION.code>=res.lowest then
NET.allow_online=true
if USER.authToken then
NET.wsconn_user_token(USER.uid,USER.authToken)
end
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)
elseif res.action==0 then--Get new version info
--?
elseif res.action==1 then--Get notice
--?
elseif res.action==2 then--Register
LOG.print(res.data.message,300,COLOR.sky)
if SCN.cur=="register"then SCN.back()end
NET.unlock("register")
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
@@ -287,8 +311,6 @@ function NET.updateWS_user()
if res.uid then
USER.uid=res.uid
USER.authToken=res.authToken
WIDGET.active.email:clear()
WIDGET.active.password:clear()
FILE.save(USER,"conf/user","q")
SCN.back()
end
@@ -301,9 +323,8 @@ function NET.updateWS_user()
NET.accessToken=res.accessToken
LOG.print(text.accessSuccessed)
NET.wsconn_play()
NET.unlock("accessToken")
elseif res.action==1 then--Get userInfo
NET.storeUserInfo(res)
NET.storeUserInfo(res.data)
end
else
WS.alert("user")
@@ -333,6 +354,7 @@ function NET.updateWS_play()
if res.type=="Connect"then
SCN.go("net_menu")
NET.unlock("wsc_play")
NET.unlock("access_and_login")
elseif res.action==0 then--Fetch rooms
NET.roomList=res.roomList
NET.unlock("fetchRoom")
@@ -349,12 +371,11 @@ function NET.updateWS_play()
username=p.username,
sid=p.sid,
ready=p.ready,
conf=p.config,
config=p.config,
})
end
end
loadGame("netBattle",true,true)
NET.unlock("enterRoom")
else
--Load other players
ins(PLY_NET,{
@@ -362,9 +383,9 @@ function NET.updateWS_play()
username=d.username,
sid=d.sid,
ready=d.ready,
conf=d.config,
config=d.config,
})
SCN.socketRead("Join",res.data)
if SCN.socketRead then SCN.socketRead("Join",d)end
end
elseif res.action==3 then--Player leave
if not d.uid then
@@ -390,15 +411,15 @@ function NET.updateWS_play()
break
end
end
SCN.socketRead("Leave",res.data)
if SCN.socketRead then SCN.socketRead("Leave",d)end
end
elseif res.action==4 then--Player talk
SCN.socketRead("Talk",res.data)
if SCN.socketRead then SCN.socketRead("Talk",d)end
elseif res.action==5 then--Player change settings
if tostring(USER.uid)~=d.uid then
for i=1,#PLY_NET do
if PLY_NET[i].uid==d.uid then
PLY_NET[i].conf=d.config
PLY_NET[i].config=d.config
PLY_NET[i].p:setConf(d.config)
return
end
@@ -406,28 +427,35 @@ function NET.updateWS_play()
resetGameData("qn")
end
elseif res.action==6 then--One ready
for i=1,#PLY_NET do
if PLY_NET[i].uid==d.uid then
if PLY_NET[i].ready~=d.ready then
for i,p in next,PLY_NET do
if p.uid==d.uid then
if p.ready~=d.ready then
p.ready=d.ready
SFX.play("spin_0",.6)
if i==1 then
WIDGET.active.ready.color=COLOR[d.ready and"lY"or"lG"]
NET.unlock("ready")
elseif not PLY_NET[1].ready then
for j=2,#PLY_NET do
if not PLY_NET[j].ready then
break
elseif j==#PLY_NET then
SFX.play("blip_2",.5)
end
end
end
PLY_NET[i].ready=d.ready
SFX.play("reach",.6)
end
break
end
end
NET.unlock("ready")
elseif res.action==7 then--Ready
--?
SFX.play("reach",.6)
elseif res.action==8 then--Set
NET.rsid=d.rid
NET.wsconn_stream()
TASK.new(NET.updateWS_stream)
elseif res.action==9 then--Game finished
SCN.socketRead("Finish",res.data)
NET.wsclose_stream()
if SCN.socketRead then SCN.socketRead("Finish",d)end
end
else
WS.alert("play")
@@ -453,10 +481,11 @@ function NET.updateWS_stream()
else
local res=_parse(message)
if res then
local d=res.data
if res.type=="Connect"then
NET.unlock("wsc_stream")
elseif res.action==0 then--Game start
SCN.socketRead("Go",res.data)
SCN.socketRead("Go",d)
elseif res.action==1 then--Game finished
--?
elseif res.action==2 then--Player join
@@ -464,9 +493,15 @@ function NET.updateWS_stream()
elseif res.action==3 then--Player leave
--?
elseif res.action==4 then--Player died
--?
local uid=res.data.uid
for _,P in next,PLY_ALIVE do
if P.uid==uid then
P:lose(true)
break
end
end
elseif res.action==5 then--Receive stream
SCN.socketRead("Stream",res.data)
SCN.socketRead("Stream",d)
end
else
WS.alert("stream")

View File

@@ -498,7 +498,7 @@ return{
color=C.dSky,
},
{
name="George2503",
name="George2003",
font=25,
color=C.grey,
},
@@ -507,4 +507,9 @@ return{
font=25,
color=C.grey,
},
{
name="T7887库德里尔",
font=25,
color=C.grey,
},
}

View File

@@ -20,6 +20,7 @@ local seqGens={
end,
his4=function(P,seq0)
local len=#seq0
local his={0,0,0,0}
while true do
while #P.nextQueue<6 do
for n=1,4 do
@@ -27,8 +28,8 @@ local seqGens={
repeat
i=seq0[P:RND(len)]
j=j+1
until i~=seq0[1]and i~=seq0[2]and i~=seq0[3]and i~=seq0[4]or j==4
seq0[n]=i
until i~=his[1]and i~=his[2]and i~=his[3]and i~=his[4]or j==4
his[n]=i
P:getNext(i)
end
end

View File

@@ -234,11 +234,9 @@ local function loadGameEnv(P)--Load gameEnv
end
end
local function loadRemoteEnv(P,confStr)--Load gameEnv
local _,conf=pcall(love.data.decode,"string","base64",confStr)
if _ then
conf=JSON.decode(conf)
else
conf={}
confStr=JSON.decode(confStr)
if not confStr then
confStr={}
LOG.print("Bad conf from "..P.username.."#"..P.uid)
end
@@ -249,8 +247,8 @@ local function loadRemoteEnv(P,confStr)--Load gameEnv
for k,v in next,gameEnv0 do
if GAME.modeEnv[k]~=nil then
v=GAME.modeEnv[k] --Mode setting
elseif conf[k]~=nil then
v=conf[k] --Game setting
elseif confStr[k]~=nil then
v=confStr[k] --Game setting
elseif SETTING[k]~=nil then
v=SETTING[k] --Global setting
end
@@ -332,6 +330,7 @@ local function applyGameEnv(P)--Finish gameEnv processing
if ENV.clearFX==0 then ENV.clearFX=false end
if ENV.splashFX==0 then ENV.splashFX=false end
if ENV.shakeFX==0 then ENV.shakeFX=false end
if ENV.atkFX==0 then ENV.atkFX=false end
end
if ENV.ghost==0 then ENV.ghost=false end
if ENV.center==0 then ENV.center=false end
@@ -385,7 +384,7 @@ function PLY.newRemotePlayer(id,mini,data)
P.uid=data.uid
P.username=data.username
P.sid=data.sid
loadRemoteEnv(P,data.conf)
loadRemoteEnv(P,data.config)
applyGameEnv(P)
end

View File

@@ -97,7 +97,7 @@ end
function Player:createClearingFX(y,spd)
ins(self.clearFX,{y,0,spd})
end
function Player:createBeam(R,send,color)
function Player:createBeam(R,send,power,color)
local x1,y1,x2,y2
if self.mini then x1,y1=self.centerX,self.centerY
else x1,y1=self.x+(30*(self.curX+self.cur.sc[2])-30+15+150)*self.size,self.y+(600-30*(self.curY+self.cur.sc[1])+15)*self.size
@@ -110,7 +110,7 @@ function Player:createBeam(R,send,color)
local r,g,b=c[1]*2,c[2]*2,c[3]*2
local a=GAME.modeEnv.royaleMode and not(self.type=="human"or R.type=="human")and .2 or 1
SYSFX.newAttack(1-SETTING.atkFX*.1,x1,y1,x2,y2,int(send^.7*(4+SETTING.atkFX)),r,g,b,a*(SETTING.atkFX+2)*.0626)
SYSFX.newAttack(1-power*.1,x1,y1,x2,y2,int(send^.7*(4+power)),r,g,b,a*(power+2)*.0626)
end
--------------------------</FX>--------------------------
@@ -214,9 +214,9 @@ function Player:setRS(RSname)
end
function Player:setConf(confStr)
local _,conf=pcall(love.data.decode,"string","base64",confStr)
if _ then
for k,v in next,conf do
confStr=JSON.decode(confStr)
if confStr then
for k,v in next,confStr do
if not GAME.modeEnv[k]then
self.gameEnv[k]=v
end
@@ -643,7 +643,8 @@ function Player:hold(ifpre)
local ENV=self.gameEnv
if self.holdTime>0 and(ifpre or self.waiting==-1)then
if #self.holdQueue<ENV.holdCount and self.nextQueue[1]then--Skip
ins(self.holdQueue,self:getBlock(self.cur.id))
local C=self.cur
ins(self.holdQueue,self:getBlock(C.id,C.name,C.color))
local t=self.holdTime
self:popNext(true)
@@ -730,16 +731,16 @@ function Player:hold(ifpre)
end
end
function Player:getBlock(n)--Get a block(id=n) object
function Player:getBlock(id,name,color)--Get a block(id=n) object
local E=self.gameEnv
local dir=E.face[n]
local dir=E.face[id]
return{
id=n,
bk=BLOCKS[n][dir],
sc=SCS[n][dir],
id=id,
dir=dir,
name=n,
color=E.bone and 17 or E.skin[n],
bk=BLOCKS[id][dir],
sc=SCS[id][dir],
name=name or id,
color=E.bone and 17 or color or E.skin[id],
}
end
function Player:getNext(n)--Push a block(id=n) to nextQueue
@@ -1322,8 +1323,8 @@ do--Player.drop(self)--Place piece
if M>0 then
for i=1,M do
self:attack(self.atker[i],send,sendTime,generateLine(self:RND(10)))
if SETTING.atkFX>0 then
self:createBeam(self.atker[i],send,C.color)
if ENV.atkFX then
self:createBeam(self.atker[i],send,ENV.atkFX,C.color)
end
end
else
@@ -1338,8 +1339,8 @@ do--Player.drop(self)--Place piece
end
if T then
self:attack(T,send,sendTime,generateLine(self:RND(10)))
if SETTING.atkFX>0 then
self:createBeam(T,send,C.color)
if ENV.atkFX then
self:createBeam(T,send,ENV.atkFX,C.color)
end
end
end
@@ -1723,6 +1724,7 @@ function Player:win(result)
end
function Player:lose(force)
if self.result then return end
if self.type=="remote"and not force then self.waiting=1e99 return end
if self.life>0 and not force then
self.waiting=62
local h=#self.field

View File

@@ -373,13 +373,13 @@ function update.dead(P,dt)
end
function update.remote_alive(P,dt)
local frmStep=GAME.frame-P.stat.frame
frmStep=
for _=1,
frmStep<20 and 1 or
frmStep<45 and rnd(2)or
frmStep<90 and 2 or
frmStep<180 and rnd(2,3) or
3
repeat
do
local eventTime=P.stream[P.streamProgress]
if eventTime then--Normal state, event forward
if P.stat.frame==eventTime then--Event time, execute action, read next so don't update immediately
@@ -394,23 +394,21 @@ function update.remote_alive(P,dt)
local amount=int(event/0x100)%0x100
local time=int(event/0x10000)%0x10000
local line=int(event/0x100000000)%0x10000
local L=PLY_ALIVE
for i=1,#L do
if L[i].sid==sid then
P:attack(L[i],amount,time,line,true)
if SETTING.atkFX>0 then
P:createBeam(L[i],amount,P.cur.color)
for _,p in next,PLY_ALIVE do
if p.sid==sid then
P:attack(p,amount,time,line,true)
if P.gameEnv.atkFX then
P:createBeam(p,amount,P.gameEnv.atkFX,P.cur.color)
end
break
end
end
elseif event>0x1000000000000 then--Receiving lines
local L=PLY_ALIVE
local sid=event%0x100
for i=1,#L do
if L[i].sid==sid then
for _,p in next,PLY_ALIVE do
if p.sid==sid then
P:receive(
L[i],
p,
int(event/0x100)%0x100,--amount
int(event/0x10000)%0x10000,--time
int(event/0x100000000)%0x10000--line
@@ -422,11 +420,10 @@ function update.remote_alive(P,dt)
P.streamProgress=P.streamProgress+2
else--No event now, run one frame
update.alive(P,dt)
frmStep=frmStep-1
end
else--Pause state, no actions, quit loop
break
end
until frmStep<=0
end
end
return update

View File

@@ -293,14 +293,11 @@ function scene.draw()
for j=1,4 do
if cx~=j or cy~=i then
local N=board[i][j]
local C=mono and 3 or color
local C=mono and 1 or color
local back=backColor[C]
local front=frontColor[C]
gc.setColor(back[N])
gc.setColor(backColor[C][N])
gc.rectangle("fill",j*160+163,i*160-117,154,154,8)
gc.setColor(front[N])
gc.setColor(frontColor[C][N])
gc.rectangle("line",j*160+163,i*160-117,154,154,8)
if not mono then
gc.setColor(.1,.1,.1)

View File

@@ -128,33 +128,34 @@ local function squash(L)
local moved=false
while true do
p2=p1+1
while not L[p2]do
while not L[p2]and p2<5 do
p2=p2+1
if p2==5 then
p1=p1+1
if p1==4 then
return L[1],L[2],L[3],L[4],moved
end
break
end
end
if not L[p1]then--air←2
L[p1],L[p2]=L[p2],false
moved=true
elseif L[p1]==L[p2]then--2←2
L[p1],L[p2]=L[p1]+1,false
if L[p1]>maxTile then
freshMaxTile()
if p2==5 then
if p1==4 then
return L[1],L[2],L[3],L[4],moved
else
p1=p1+1
end
else
if not L[p1]then--air←2
L[p1],L[p2]=L[p2],false
moved=true
elseif L[p1]==L[p2]then--2←2
L[p1],L[p2]=L[p1]+1,false
if L[p1]>maxTile then
freshMaxTile()
end
L[p2]=false
p1=p1+1
moved=true
elseif p1+1~=p2 then--2←4
L[p1+1],L[p2]=L[p2],false
p1=p1+1
moved=true
else--2,4
p1=p1+1
end
L[p2]=false
p1=p1+1
moved=true
elseif p1+1~=p2 then--2←4
L[p1+1],L[p2]=L[p2],false
p1=p1+1
moved=true
else--2,4
p1=p1+1
end
end
end

View File

@@ -196,7 +196,7 @@ do--commands.help(arg)
details={
"Set background.",
"",
"Usage: setbg <classic|xmas|sprfes|zday>",
"Usage: setbg <classic|xmas|sprfes|zday1|zday2>",
},
},
theme={
@@ -204,7 +204,7 @@ do--commands.help(arg)
details={
"Load a theme.",
"",
"Usage: theme <classic|xmas|sprfes|zday>",
"Usage: theme <classic|xmas|sprfes|zday1|zday2>",
},
},
demo={
@@ -488,7 +488,7 @@ function commands.demo()
SCN.go("test","none")
end
do--commands.applet(name)
local appList={"15p","grid","pong","atoz","uttt","cube","2048","ten","tap","dtw","cannon","drppper","calc","reflect","polyforge"}
local appList={"15p","grid","pong","atoz","uttt","cube","2048","ten","tap","dtw","cannon","drp","calc","reflect","polyforge"}
local appScene={"app_15p","app_schulteG","app_pong","app_AtoZ","app_UTTT","app_cubefield","app_2048","app_ten","app_tap","app_dtw","app_cannon","app_dropper","app_calc","app_reflect","app_polyforge"}
function commands.applet(name)
if name=="-list"then
@@ -537,7 +537,7 @@ local function log_user(str)
log(noLog and"CHEATER."or tostring(str))
end
local userG={
_VERSION=VERSION_CODE,
_VERSION=VERSION.code,
assert=assert,error=error,
tonumber=tonumber,tostring=tostring,
select=select,next=next,

View File

@@ -104,7 +104,7 @@ end
function scene.sceneInit()
sure=0
penColor=1
penColor=-2
penMode=false
penX,penY=1,1
demo=false

View File

@@ -9,7 +9,7 @@ local scene={}
function scene.sceneInit()
BGcolor=rnd()>.026 and{.3,.5,.9}or{.62,.3,.926}
stateInfo=SYSTEM.."-"..VERSION_NAME.." scene:"..ERRDATA[#ERRDATA].scene
stateInfo=SYSTEM.."-"..VERSION.string.." scene:"..ERRDATA[#ERRDATA].scene
errorText=LOADED and text.errorMsg or"An error has occurred during loading.\nError info has been created, and you can send it to the author."
errorShot,errorInfo=ERRDATA[#ERRDATA].shot,ERRDATA[#ERRDATA].mes
if SETTING then SFX.fplay("error",SETTING.voc*.8 or 0)end

View File

@@ -1,13 +1,8 @@
local scene={}
local inited
function scene.sceneInit()
BG.set("cubes")
if not inited then
inited=true
WIDGET.active.texts:setTexts(require"parts.updateLog")
end
WIDGET.active.texts:setTexts(require"parts.updateLog")
if newVersionLaunch then
newVersionLaunch=false
end

View File

@@ -181,9 +181,6 @@ local loadingThread=coroutine.wrap(function()
TASK.new(NET.updateWS_user)
TASK.new(NET.updateWS_play)
NET.wsconn_app()
if USER.authToken then
NET.wsconn_user_token(USER.uid,USER.authToken)
end
while true do
if math.random()<.126 then

View File

@@ -13,7 +13,7 @@ local scene={}
scene.widgetList={
WIDGET.newText{name="title", x=80, y=50,font=70,align="L"},
-- WIDGET.newButton{name="register",x=1140, y=100,w=170,h=80,color="green",code=function()SCN.swapTo("register","swipeR")end},
WIDGET.newButton{name="register", x=1140, y=100,w=170,h=80,color="lY",code=function()SCN.swapTo("register","swipeR")end},
WIDGET.newInputBox{name="email", x=380, y=200,w=500,h=60,regex="[0-9A-Za-z@._-]"},
WIDGET.newInputBox{name="password", x=380, y=300,w=626,h=60,secret=true,regex="[ -~]"},
WIDGET.newKey{name="login", x=1140, y=540,w=170,h=80,font=40,code=login},

View File

@@ -2,7 +2,7 @@ local gc=love.graphics
local scene={}
local verName=SYSTEM.." "..VERSION_NAME
local verName=("%s %s %s"):format(SYSTEM,VERSION.string,VERSION.name)
local tipLength=760
local tip=gc.newText(getFont(30),"")
local scrollX--Tip scroll position
@@ -72,7 +72,10 @@ function scene.keyDown(key)
elseif key=="a"then
if testButton(3)then
if WS.status("user")=="running"then
if not NET.allow_online then
if not NET.connected then
TEXT.show(text.noInternet,640,450,60,"flicker")
SFX.play("finesseError")
elseif not NET.allow_online then
TEXT.show(text.needUpdate,640,450,60,"flicker")
SFX.play("finesseError")
else

View File

@@ -17,7 +17,7 @@ end
scene.widgetList={
WIDGET.newText{name="system", x=750,y=280,fText=SYSTEM,color="white",font=30,align="L"},
WIDGET.newText{name="version", x=950,y=280,fText=VERSION_NAME,color="white",font=30,align="L"},
WIDGET.newText{name="version", x=950,y=280,fText=VERSION.string,color="white",font=30,align="L"},
WIDGET.newButton{name="sprint", x=260,y=480,w=260,font=50,code=function()loadGame("sprint_40l",true)end},
WIDGET.newButton{name="marathon",x=640,y=480,w=260,font=50,code=function()loadGame("marathon_n",true)end},
WIDGET.newButton{name="setting",x=1000,y=400,w=120,fText="...",font=50,code=goScene"setting_game"},

View File

@@ -34,6 +34,7 @@ function scene.sceneInit()
upstreamProgress=1
end
scene.mouseDown=NULL
function scene.touchDown(x,y)
if noTouch or not playing then return end
@@ -245,26 +246,20 @@ function scene.draw()
else
for i=1,#PLY_NET do
local p=PLY_NET[i]
gc.setColor(1,1,1)
--Rectangle
gc.setLineWidth(4)
gc.rectangle("line",40,65+50*i,1200,50)
gc.setColor(COLOR[p.ready and"G"or"white"])
gc.setLineWidth(3)
gc.rectangle("line",40,67+50*i,800,42)
--Username
gc.setColor(1,1,1)
setFont(40)
gc.print(p.username,230,60+50*i)
gc.print(p.username,200,60+50*i)
--UID
gc.setColor(.5,.5,.5)
gc.print("#"..p.uid,90,60+50*i)
if p.ready then
gc.setColor(.4,1,.4)
else
gc.setColor(1,1,1)
end
gc.rectangle("fill",50,60+50*i+14,30,30)
gc.print("#"..p.uid,50,60+50*i)
end
end
--New message
@@ -276,10 +271,18 @@ function scene.draw()
end
scene.widgetList={
textBox,
WIDGET.newKey{name="ready",x=900,y=560,w=400,h=100,color="lG",font=40,code=pressKey"space",hide=function()
WIDGET.newKey{name="ready",x=900,y=560,w=400,h=100,color="lB",font=40,code=pressKey"space",hide=function()
return
playing or
not textBox.hide or
PLY_NET[1].ready or
NET.getlock("ready")
end},
WIDGET.newKey{name="cancel",x=900,y=560,w=400,h=100,color="grey",font=40,code=pressKey"space",hide=function()
return
playing or
not textBox.hide or
not PLY_NET[1].ready or
NET.getlock("ready")
end},
WIDGET.newKey{name="hideChat",fText="...",x=380,y=35,w=60,font=35,code=pressKey"\\"},

View File

@@ -1,4 +1,5 @@
local gc=love.graphics
local kb=love.keyboard
local NET=NET
local scrollPos,selected
@@ -29,7 +30,16 @@ function scene.keyDown(k)
end
elseif k=="n"then
if TIME()-lastCreateRoomTime>16.2 then
NET.createRoom()
NET.createRoom(
kb.isDown("1")and"solo"or
kb.isDown("2")and"classic"or
tonumber(USER.uid)<100 and(
kb.isDown("3")and"r49"or
kb.isDown("4")and"r99"or
kb.isDown("5")and"unlimited"
)or"solo",
(USER.username or"???").."'s room"
)
lastCreateRoomTime=TIME()
else
LOG.print(text.createRoomTooFast,"warn")
@@ -57,9 +67,6 @@ function scene.keyDown(k)
LOG.print("Can't enter private room now")
return
end
if NET.roomList[selected].start then
LOG.print("Can't enter room after start")
end
NET.enterRoom(NET.roomList[selected].rid)--,password
end
end

View File

@@ -1,41 +1,41 @@
local scene={}
function scene.keyDown(key)
if key=="return"then
local username= WIDGET.active.username.value
local email= WIDGET.active.email.value
local password= WIDGET.active.password.value
local password2=WIDGET.active.password2.value
if #username==0 then
LOG.print(text.noUsername)return
elseif not email:match("^[a-zA-Z0-9_]+@[a-zA-Z0-9_-]+%.[a-zA-Z0-9_]+$")then
LOG.print(text.wrongEmail)return
elseif #password==0 or #password2==0 then
LOG.print(text.noPassword)return
elseif password~=password2 then
LOG.print(text.diffPassword)return
end
--[[
JSON.encode{
username=username,
email=email,
password=password,
}
]]
elseif key=="escape"then
SCN.back()
else
WIDGET.keyPressed(key)
local function legalEmail(e)
e=SPLITSTR(e,"@")
if #e~=2 then return false end
if e[1]:sub(-1)=="."or e[2]:sub(-1)=="."then return false end
local e1,e2=SPLITSTR(e[1],"."),SPLITSTR(e[2],".")
if #e1*#e2==0 then return false end
for _,v in next,e1 do if #v==0 then return false end end
for _,v in next,e2 do if #v==0 then return false end end
return true
end
local function register()
local username= WIDGET.active.username.value
local email= WIDGET.active.email.value
local password= WIDGET.active.password.value
local password2=WIDGET.active.password2.value
if #username==0 then
LOG.print(text.noUsername)return
elseif not legalEmail(email)then
LOG.print(text.wrongEmail)return
elseif #password==0 or #password2==0 then
LOG.print(text.noPassword)return
elseif password~=password2 then
LOG.print(text.diffPassword)return
end
NET.register(username,email,password)
end
scene.widgetList={
WIDGET.newText{name="title", x=80, y=50,font=70,align="L"},
WIDGET.newButton{name="login", x=1140, y=100,w=170,h=80,color="green",code=function()SCN.swapTo("login","swipeL")end},
WIDGET.newButton{name="login", x=1140, y=100,w=170,h=80,color="lY",code=function()SCN.swapTo("login","swipeL")end},
WIDGET.newInputBox{name="username", x=380, y=200,w=500,h=60,regex="[0-9A-Za-z_]"},
WIDGET.newInputBox{name="email", x=380, y=300,w=626,h=60,regex="[0-9A-Za-z@._-]"},
WIDGET.newInputBox{name="email", x=380, y=300,w=626,h=60,regex="[0-9A-Za-z@._-]"},
WIDGET.newInputBox{name="password", x=380, y=400,w=626,h=60,secret=true,regex="[ -~]"},
WIDGET.newInputBox{name="password2", x=380, y=500,w=626,h=60,secret=true,regex="[ -~]"},
WIDGET.newInputBox{name="password2",x=380, y=500,w=626,h=60,secret=true,regex="[ -~]"},
WIDGET.newKey{name="register", x=1140, y=540,w=170,h=80,font=40,code=register},
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="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=SETval("block"), code=SETrev("block")},
WIDGET.newSwitch{name="smooth", x=340, y=210, disp=SETval("smooth"), code=SETrev("smooth")},
WIDGET.newSwitch{name="upEdge", x=340, y=270, disp=SETval("upEdge"), code=SETrev("upEdge")},
WIDGET.newSwitch{name="bagLine", x=340, y=330, disp=SETval("bagLine"), code=SETrev("bagLine")},
WIDGET.newSwitch{name="block", x=290, y=165, disp=SETval("block"), code=SETrev("block")},
WIDGET.newSwitch{name="smooth", x=290, y=215, disp=SETval("smooth"), code=SETrev("smooth")},
WIDGET.newSwitch{name="upEdge", x=290, y=265, disp=SETval("upEdge"), code=SETrev("upEdge")},
WIDGET.newSwitch{name="bagLine", x=290, y=315, disp=SETval("bagLine"), code=SETrev("bagLine")},
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=SETval("grid"),show="percent", code=SETsto("grid")},
WIDGET.newSlider{name="center", x=630, y=300,w=200,unit=1, disp=SETval("center"), code=SETsto("center")},
WIDGET.newSlider{name="ghost", x=600, y=180,w=200,unit=.6,disp=SETval("ghost"),show="percent",code=SETsto("ghost")},
WIDGET.newSlider{name="grid", x=600, y=240,w=200,unit=.4,disp=SETval("grid"),show="percent", code=SETsto("grid")},
WIDGET.newSlider{name="center", x=600, 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=SETval("lockFX"), code=SETsto("lockFX")},
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=SETval("moveFX"), code=SETsto("moveFX")},
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=SETval("splashFX"),code=SETsto("splashFX")},
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=SETval("atkFX"), code=SETsto("atkFX")},
WIDGET.newSlider{name="lockFX", x=250, y=375,w=373,unit=5, disp=SETval("lockFX"), code=SETsto("lockFX")},
WIDGET.newSlider{name="dropFX", x=250, y=420,w=373,unit=5, disp=SETval("dropFX"), code=SETsto("dropFX")},
WIDGET.newSlider{name="moveFX", x=250, y=465,w=373,unit=5, disp=SETval("moveFX"), code=SETsto("moveFX")},
WIDGET.newSlider{name="clearFX", x=250, y=510,w=373,unit=5, disp=SETval("clearFX"), code=SETsto("clearFX")},
WIDGET.newSlider{name="splashFX", x=250, y=555,w=373,unit=5, disp=SETval("splashFX"),code=SETsto("splashFX")},
WIDGET.newSlider{name="shakeFX", x=250, y=600,w=373,unit=5, disp=SETval("shakeFX"), code=SETsto("shakeFX")},
WIDGET.newSlider{name="atkFX", x=250, y=645,w=373,unit=5, disp=SETval("atkFX"), code=SETsto("atkFX")},
WIDGET.newSlider{name="frame", x=350, y=690,w=373,unit=10,
disp=function()
return SETTING.frameMul>35 and SETTING.frameMul/10 or SETTING.frameMul/5-4
@@ -37,20 +37,21 @@ scene.widgetList={
SETTING.frameMul=i<5 and 5*i+20 or 10*i
end},
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=SETval("score"), code=SETrev("score")},
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=SETval("highCam"),code=SETrev("highCam")},
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=SETval("fullscreen"), code=switchFullscreen},
WIDGET.newSwitch{name="bg", x=1100, y=540,font=35,disp=SETval("bg"),
WIDGET.newSwitch{name="text", x=1140, y=160,font=35,disp=SETval("text"), code=SETrev("text")},
WIDGET.newSwitch{name="score", x=1140, y=210,font=35,disp=SETval("score"), code=SETrev("score")},
WIDGET.newSwitch{name="warn", x=1140, y=260,font=35,disp=SETval("warn"), code=SETrev("warn")},
WIDGET.newSwitch{name="highCam", x=1140, y=310,font=35,disp=SETval("highCam"),code=SETrev("highCam")},
WIDGET.newSwitch{name="nextPos", x=1140, y=360,font=35,disp=SETval("nextPos"),code=SETrev("nextPos")},
WIDGET.newSwitch{name="fullscreen", x=1140, y=410,disp=SETval("fullscreen"), code=switchFullscreen},
WIDGET.newSwitch{name="power", x=1140, y=460,font=35,disp=SETval("powerInfo"),code=SETrev("powerInfo")},
WIDGET.newSwitch{name="clickFX", x=1140, y=510,font=35,disp=SETval("clickFX"),code=SETrev("clickFX")},
WIDGET.newSwitch{name="bg", x=1140, y=560,font=35,disp=SETval("bg"),
code=function()
BG.set("none")
SETTING.bg=not SETTING.bg
BG.set()
end},
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=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
WIDGET.newSwitch{name="clean", x=990, y=640,font=35,disp=SETval("cleanCanvas"),code=SETrev("cleanCanvas")},
WIDGET.newButton{name="back", x=1140, y=640,w=170,h=80,font=40,code=backScene},
}

View File

@@ -48,7 +48,7 @@ function scene.touchClick(x,y)
end
function scene.touchDown(x,y)
SYSFX.newRipple(.5,x,y,50)
push(("[touchDown] <%d: %d, %d>"):format(x,y))
push(("[touchDown] <%d, %d>"):format(x,y))
end
function scene.touchMove(x,y)
SYSFX.newRipple(.5,x,y,50)

View File

@@ -22,6 +22,56 @@ return SPLITSTR([=[
可选虚拟按键颜色; 工程编译到字节码; task-Z(新AI)
录像回放菜单; 跳帧开关; 教学关; 超60帧; 热更新
0.14.4: 日出 Sunrise
新增:
添加触摸/点击特效开关
新增BGM:super7th(用于master-ph模式)
新增BGM:vacuum(用于节日主题)
改动:
自定义场地默认使用智能画笔
对战房间的准备按钮颜色和文本会随状态改变
联网对战时禁用鼠标右键返回
添加触摸/点击特效开关
修改隐形模式BGM配置
更换催促等待提示音
不再接受过老版本的存档
修复:
玩家死亡消息以服务器为准,录像不同步不再影响结算
O块在变形后hold失去名字和颜色属性
master-ph错误
注册时部分合法邮箱格式会被判错
his序列模式算法错误
小程序2048出新格的逻辑错误
小程序15p盲打颜色配置错误
一个小程序入口名错误
0.14.3: 曙光 Morning Twilight
改动:
尝试进联网菜单的两步都完成前再次点击按钮无效
自动登录时机修改为ws-app连接成功并且版本是最新
微调玩家准备相关的交互
进房固定1.26秒cd
文本框控件不再有新消息提示音
修复:
修复test场景触屏点击报错
0.14.2: 破晓 Dawn
新增:
重新启用注册菜单
改动:
优化一些联网对战相关内容
攻击特效从全局改为玩家设置项一部分
修复:
一些联网对战问题
马拉松模式忘了删测试用代码
0.14.1: 拂晓 Daybreak
改动:
为了更好的游戏体验,手机只能开单挑房,电脑开多人房(不建议),特殊用户可以开更大的房
增加联网对战模式的垃圾行上涨速度
修复:
一些联网对战的bug
0.14.0: 地平线 The Horizon
新增:
重新开放联网对战测试!!!
@@ -31,9 +81,9 @@ return SPLITSTR([=[
新模式:Backfire(四个难度)
新背景:BlackHole(用于Backfire)
新增BGM:echo(用于Backfire), hang out(用于两个小程序)
调整自定义场地的ui可以看到鼠标不同按键对应画笔颜色
调整自定义场地的ui,可以看到鼠标不同按键对应画笔颜色
小程序DTW增加双押功能
新增绘制优化设置(手机开启可能加速,花屏可能关闭解决)
新增绘制优化设置(手机开启可能加速,电脑花屏关闭可能解决)
改动:
错误处理机制大升级,更不容易闪退(CC爆炸除外)
赞助名单移至staff场景并添加动画(已经在榜上的可以来定制颜色!)