Compare commits
28 Commits
pre0.16.5-
...
pre0.16.5-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b221c2eb5 | ||
|
|
ed45bebfa0 | ||
|
|
fa0bc3805f | ||
|
|
7710f0b70f | ||
|
|
0277ddadb5 | ||
|
|
88e23e32f5 | ||
|
|
8ab5b4a17a | ||
|
|
503dfd69ef | ||
|
|
ae61ec26c0 | ||
|
|
00bc24bd50 | ||
|
|
abd15d6307 | ||
|
|
c01ac546d1 | ||
|
|
af77221ba2 | ||
|
|
204f0938d3 | ||
|
|
ad39d1408c | ||
|
|
ed011173f6 | ||
|
|
491fcb5860 | ||
|
|
c2d5537d8d | ||
|
|
7d5037ae87 | ||
|
|
07d7714317 | ||
|
|
2cab97f37d | ||
|
|
d184778c9a | ||
|
|
9fd3b3008d | ||
|
|
71aa35b214 | ||
|
|
4443dc9d3e | ||
|
|
839e357301 | ||
|
|
ac56c5a415 | ||
|
|
36e3343341 |
54
.github/actions/upload-artifact/action.yml
vendored
54
.github/actions/upload-artifact/action.yml
vendored
@@ -1,54 +0,0 @@
|
||||
name: "upload artifact"
|
||||
description: "upload file with webdav"
|
||||
inputs:
|
||||
WEBDAV_USERNAME:
|
||||
required: true
|
||||
description: "webdav username"
|
||||
WEBDAV_PASSWORD:
|
||||
required: true
|
||||
description: "webdav password"
|
||||
ARTIFACT_TYPE:
|
||||
required: true
|
||||
description: "file build type"
|
||||
ARTIFACT_PLATFORM:
|
||||
required: true
|
||||
description: "file platform"
|
||||
ARTIFACT_NAME:
|
||||
required: true
|
||||
description: "file name"
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
- name: Install Webdav 4
|
||||
shell: bash
|
||||
run: |
|
||||
pip install webdav4
|
||||
- name: Update release
|
||||
shell: python
|
||||
run: |
|
||||
import re
|
||||
from webdav4.client import Client
|
||||
|
||||
client = Client(
|
||||
"http://mc.yuhao7370.top:5212/dav",
|
||||
auth=("${{ inputs.WEBDAV_USERNAME }}", "${{ inputs.WEBDAV_PASSWORD }}"),
|
||||
timeout=None,
|
||||
)
|
||||
if '${{ inputs.ARTIFACT_TYPE }}' == 'release':
|
||||
print('Removing previous ${{ inputs.ARTIFACT_PLATFORM }} release file...')
|
||||
for file in client.ls('Techmino distribution'):
|
||||
if re.search(r'(Techmino_a[0-9]+\.[0-9]+\.[0-9]_${{ inputs.ARTIFACT_PLATFORM }}.*)', file['name']):
|
||||
client.remove(file['name'])
|
||||
print('Uploading new ${{ inputs.ARTIFACT_PLATFORM }} release file...')
|
||||
client.upload_file("${{ inputs.ARTIFACT_NAME }}", 'Techmino distribution/${{ inputs.ARTIFACT_NAME }}')
|
||||
|
||||
if '${{ inputs.ARTIFACT_TYPE }}' == 'test':
|
||||
print('Removing previous ${{ inputs.ARTIFACT_PLATFORM }} test file...')
|
||||
for file in client.ls('Techmino Snapshot'):
|
||||
if re.search(r'(Techmino_pre[0-9]+\.[0-9]+\.[0-9]_[0-9a-z]{7}_${{ inputs.ARTIFACT_PLATFORM }}.*)', file['name']):
|
||||
client.remove(file['name'])
|
||||
print('Uploading new ${{ inputs.ARTIFACT_PLATFORM }} test file...')
|
||||
client.upload_file("${{ inputs.ARTIFACT_NAME }}", 'Techmino Snapshot/${{ inputs.ARTIFACT_NAME }}')
|
||||
48
.github/workflows/release.yml
vendored
48
.github/workflows/release.yml
vendored
@@ -56,14 +56,6 @@ jobs:
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Win64
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip
|
||||
|
||||
build-windows-x86:
|
||||
runs-on: windows-latest
|
||||
@@ -85,14 +77,6 @@ jobs:
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Win32
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -109,14 +93,6 @@ jobs:
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Linux
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -139,14 +115,6 @@ jobs:
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: Android
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk
|
||||
|
||||
build-macOS:
|
||||
runs-on: macos-10.15
|
||||
@@ -174,14 +142,6 @@ jobs:
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: MacOS
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg
|
||||
|
||||
build-iOS:
|
||||
runs-on: macos-latest
|
||||
@@ -216,14 +176,6 @@ jobs:
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.updateTitle }}
|
||||
files: Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: release
|
||||
ARTIFACT_PLATFORM: iOS
|
||||
ARTIFACT_NAME: Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa
|
||||
|
||||
Add-Release-note:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
55
.github/workflows/test.yml
vendored
55
.github/workflows/test.yml
vendored
@@ -49,20 +49,7 @@ jobs:
|
||||
with:
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows
|
||||
path: love
|
||||
- name: Pack Techmino
|
||||
run: 7z a -tzip .\Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows.zip .\love
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: Windows
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows.zip
|
||||
# - name: Upload artifact to server
|
||||
# run: |
|
||||
# curl --user "${{ secrets.WEBDAV_USERNAME }}:${{ secrets.WEBDAV_PASSWORD }}" -T Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows.zip http://mc.yuhao7370.top:5212/dav/Techmino%20Snapshots/ -v
|
||||
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: get-info
|
||||
@@ -80,16 +67,6 @@ jobs:
|
||||
with:
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux
|
||||
path: Techmino.AppImage
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino.AppImage Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux.AppImage
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: Linux
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux.AppImage
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -115,16 +92,6 @@ jobs:
|
||||
with:
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android
|
||||
path: Techmino_Snapshot.apk
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino_Snapshot.apk Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android.apk
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: Android
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android.apk
|
||||
|
||||
build-macOS:
|
||||
runs-on: macos-10.15
|
||||
@@ -152,16 +119,6 @@ jobs:
|
||||
with:
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS
|
||||
path: Techmino.dmg
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino.dmg Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS.dmg
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: MacOS
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS.dmg
|
||||
|
||||
build-iOS:
|
||||
runs-on: macos-latest
|
||||
@@ -195,13 +152,3 @@ jobs:
|
||||
with:
|
||||
name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS
|
||||
path: Techmino.ipa
|
||||
- name: Pack Techmino
|
||||
run: mv Techmino.ipa Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS.ipa
|
||||
- name: Upload artifact to server
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
WEBDAV_USERNAME: ${{ secrets.WEBDAV_USERNAME }}
|
||||
WEBDAV_PASSWORD: ${{ secrets.WEBDAV_PASSWORD }}
|
||||
ARTIFACT_TYPE: test
|
||||
ARTIFACT_PLATFORM: iOS
|
||||
ARTIFACT_NAME: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS.ipa
|
||||
|
||||
@@ -4,6 +4,7 @@ LOADED=false
|
||||
ERRDATA={}
|
||||
|
||||
--Pure lua modules (basic)
|
||||
MATH= require'Zframework.mathExtend'
|
||||
COLOR= require'Zframework.color'
|
||||
TABLE= require'Zframework.tableExtend'
|
||||
STRING= require'Zframework.stringExtend'
|
||||
|
||||
19
Zframework/mathExtend.lua
Normal file
19
Zframework/mathExtend.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
local MATH={}for k,v in next,math do MATH[k]=v end
|
||||
|
||||
local rnd=math.random
|
||||
|
||||
MATH.tau=2*math.pi
|
||||
|
||||
function MATH.sign(a)
|
||||
return a>0 and 1 or a<0 and -1 or 0
|
||||
end
|
||||
|
||||
function MATH.coin(a,b)
|
||||
if rnd()<.5 then
|
||||
return a
|
||||
else
|
||||
return b
|
||||
end
|
||||
end
|
||||
|
||||
return MATH
|
||||
@@ -1,5 +1,5 @@
|
||||
local type,rem=type,table.remove
|
||||
local rnd=math.random
|
||||
local int,rnd=math.floor,math.random
|
||||
|
||||
local sfxList={}
|
||||
local packSetting={}
|
||||
@@ -7,7 +7,7 @@ local Sources={}
|
||||
local volume=1
|
||||
local stereo=1
|
||||
|
||||
local noteName={
|
||||
local noteVal={
|
||||
C=1,c=1,
|
||||
D=3,d=3,
|
||||
E=5,e=5,
|
||||
@@ -16,10 +16,11 @@ local noteName={
|
||||
A=10,a=10,
|
||||
B=12,b=12,
|
||||
}
|
||||
local noteName={'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'}
|
||||
local function _getTuneHeight(tune)
|
||||
local octave=tonumber(tune:sub(-1,-1))
|
||||
if octave then
|
||||
local tuneHeight=noteName[tune:sub(1,1)]
|
||||
local tuneHeight=noteVal[tune:sub(1,1)]
|
||||
if tuneHeight then
|
||||
tuneHeight=tuneHeight+(octave-1)*12
|
||||
local s=tune:sub(2,2)
|
||||
@@ -79,21 +80,30 @@ function SFX.setStereo(v)
|
||||
stereo=v
|
||||
end
|
||||
|
||||
function SFX.playSample(pack,...)--vol-2, sampSet1, vol-3, sampSet2, vol-1
|
||||
function SFX.getNoteName(note)
|
||||
if note<1 then
|
||||
return'---'
|
||||
else
|
||||
note=note-1
|
||||
local octave=int(note/12)+1
|
||||
return noteName[note%12+1]..octave
|
||||
end
|
||||
end
|
||||
function SFX.playSample(pack,...)--vol-1, sampSet1, vol-2, sampSet2
|
||||
if ... then
|
||||
local arg={...}
|
||||
local vol
|
||||
if type(arg[#arg])=='number'then vol=rem(arg)end
|
||||
for i=1,#arg do
|
||||
if type(arg[i])=='number'then
|
||||
vol=arg[i]
|
||||
local a=arg[i]
|
||||
if type(a)=='number'and a<=1 then
|
||||
vol=a
|
||||
else
|
||||
local base=packSetting[pack].base
|
||||
local top=packSetting[pack].top
|
||||
local tune=_getTuneHeight(arg[i])--Absolute tune in number
|
||||
local tune=type(a)=='string'and _getTuneHeight(a)or a--Absolute tune in number
|
||||
local playTune=tune+rnd(-2,2)
|
||||
if playTune<base then--Too low notes
|
||||
playTune=base
|
||||
if playTune<=base then--Too low notes
|
||||
playTune=base+1
|
||||
elseif playTune>top then--Too high notes
|
||||
playTune=top
|
||||
end
|
||||
|
||||
@@ -63,9 +63,9 @@ function STRING.time(t)
|
||||
if t<60 then
|
||||
return format("%.3f\"",t)
|
||||
elseif t<3600 then
|
||||
return format("%d'%05.2f\"",int(t/60),t%60)
|
||||
return format("%d'%05.2f\"",int(t/60),int(t%60*100)/100)
|
||||
else
|
||||
return format("%d:%.2d'%05.2f\"",int(t/3600),int(t/60%60),t%60)
|
||||
return format("%d:%.2d'%05.2f\"",int(t/3600),int(t/60%60),int(t%60*100)/100)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -46,6 +46,18 @@ function TABLE.cover(new,old)
|
||||
end
|
||||
end
|
||||
|
||||
--For all things in new, push to old
|
||||
function TABLE.coverR(new,old)
|
||||
for k,v in next,new do
|
||||
if type(v)=='table'and type(old[k])=='table'then
|
||||
TABLE.coverR(v,old[k])
|
||||
else
|
||||
old[k]=v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--For all things in new if same type in old, push to old
|
||||
function TABLE.update(new,old)
|
||||
for k,v in next,new do
|
||||
@@ -90,6 +102,11 @@ function TABLE.find(t,val)
|
||||
for i=1,#t do if t[i]==val then return i end end
|
||||
end
|
||||
|
||||
--Retuen next value of [1~#]
|
||||
function TABLE.next(t,val)
|
||||
for i=1,#t do if t[i]==val then return t[i%#t+1]end end
|
||||
end
|
||||
|
||||
--Find value in whole table
|
||||
function TABLE.search(t,val)
|
||||
for k,v in next,t do if v==val then return k end end
|
||||
|
||||
2
main.lua
2
main.lua
@@ -205,7 +205,7 @@ Z.setOnQuit(destroyPlayers)
|
||||
TABLE.cover (FILE.load('conf/user')or{},USER)
|
||||
TABLE.cover (FILE.load('conf/unlock')or{},RANKS)
|
||||
TABLE.update(FILE.load('conf/settings')or{},SETTING)
|
||||
TABLE.update(FILE.load('conf/data')or{},STAT)
|
||||
TABLE.coverR(FILE.load('conf/data')or{},STAT)
|
||||
TABLE.cover (FILE.load('conf/key')or{},KEY_MAP)
|
||||
TABLE.cover (FILE.load('conf/virtualkey')or{},VK_ORG)
|
||||
|
||||
|
||||
@@ -353,8 +353,8 @@ do
|
||||
[21]={'+0+0','-1+0','-1+1','+0+1','-1+2','+0+2','-1-1','+1+0','+0-2','-1-2'},
|
||||
[32]={'+0+0','-1+0','-1+1','-1-1','+1+0','+0+2','-1+2','+0-2'},
|
||||
[23]={'+0+0','+1+0','+1-1','+1+1','-1+0','+0-2','+1-2','+0+2'},
|
||||
[02]={'+0+0','+0-1','+1-1','-1+0','+2-1'},
|
||||
[20]={'+0+0','+0+1','-1+1','+1+0','-2+1'},
|
||||
[02]={'+0+0','+0-1','-1-1','+1-1','-1+0','+2-1'},
|
||||
[20]={'+0+0','+0+1','+1+1','-1+1','+1+0','-2+1'},
|
||||
[13]={'+0+0','-1+0','-1-1','+0+1','-1-2'},
|
||||
[31]={'+0+0','+1+0','+1+1','+0-1','+1+2'},
|
||||
},--J5
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local gc_setColor=love.graphics.setColor
|
||||
return{
|
||||
das=16,arr=6,
|
||||
sddas=6,sdarr=6,
|
||||
@@ -18,12 +19,24 @@ return{
|
||||
mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210)
|
||||
mText(TEXTOBJ.speedLV,63,290)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
if P.modeData.drought>7 then
|
||||
if P.modeData.drought<=14 then
|
||||
gc_setColor(1,1,1,P.modeData.drought/7-1)
|
||||
else
|
||||
local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5
|
||||
gc_setColor(1,gb,gb)
|
||||
end
|
||||
setFont(50)
|
||||
mStr(P.modeData.drought,63,130)
|
||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
local D=P.modeData
|
||||
D.drought=P.lastPiece.id==7 and 0 or D.drought+1
|
||||
if P.stat.row>=D.target then
|
||||
if D.target==110 then
|
||||
P.gameEnv.drop,P.gameEnv.lock=5,5
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local gc_setColor=love.graphics.setColor
|
||||
return{
|
||||
das=16,arr=6,
|
||||
sddas=3,sdarr=3,
|
||||
@@ -15,9 +16,20 @@ return{
|
||||
mesDisp=function(P)
|
||||
setFont(75)
|
||||
local r=P.modeData.target/10
|
||||
mStr(r<11 and 18 or r<22 and r+8 or("%02x"):format(r*10-220),63,210)
|
||||
mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210)
|
||||
mText(TEXTOBJ.speedLV,63,290)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
if P.modeData.drought>7 then
|
||||
if P.modeData.drought<=14 then
|
||||
gc_setColor(1,1,1,P.modeData.drought/7-1)
|
||||
else
|
||||
local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5
|
||||
gc_setColor(1,gb,gb)
|
||||
end
|
||||
setFont(50)
|
||||
mStr(P.modeData.drought,63,130)
|
||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
local gc_setColor=love.graphics.setColor
|
||||
return{
|
||||
das=16,arr=6,
|
||||
sddas=1,sdarr=1,
|
||||
@@ -15,9 +16,20 @@ return{
|
||||
mesDisp=function(P)
|
||||
setFont(75)
|
||||
local r=P.modeData.target/10
|
||||
mStr(r==1 and 29 or("%02x"):format(r*10-20),63,210)
|
||||
mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210)
|
||||
mText(TEXTOBJ.speedLV,63,290)
|
||||
PLY.draw.drawProgress(P.stat.row,P.modeData.target)
|
||||
if P.modeData.drought>7 then
|
||||
if P.modeData.drought<=14 then
|
||||
gc_setColor(1,1,1,P.modeData.drought/7-1)
|
||||
else
|
||||
local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5
|
||||
gc_setColor(1,gb,gb)
|
||||
end
|
||||
setFont(50)
|
||||
mStr(P.modeData.drought,63,130)
|
||||
mDraw(MODES.drought_l.icon,63,200,nil,.5)
|
||||
end
|
||||
end,
|
||||
task=function(P)
|
||||
P.modeData.target=10
|
||||
|
||||
19
parts/eventsets/sprintEff_40.lua
Normal file
19
parts/eventsets/sprintEff_40.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
return{
|
||||
mesDisp=function(P)
|
||||
setFont(55)
|
||||
local r=40-P.stat.row
|
||||
if r<0 then r=0 end
|
||||
mStr(r,63,170)
|
||||
PLY.draw.drawTargetLine(P,r)
|
||||
setFont(45)
|
||||
mStr(("%.1f"):format(P.stat.atk),63,270)
|
||||
mText(TEXTOBJ.atk,63,323)
|
||||
mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,370)
|
||||
mText(TEXTOBJ.eff,63,423)
|
||||
end,
|
||||
hook_drop=function(P)
|
||||
if P.stat.row>=40 then
|
||||
P:win('finish')
|
||||
end
|
||||
end
|
||||
}
|
||||
@@ -16,9 +16,9 @@ return{
|
||||
if P.stat.frame/60>=warnTime[P.modeData.stage]then
|
||||
if P.modeData.stage<9 then
|
||||
P.modeData.stage=P.modeData.stage+1
|
||||
SFX.play('ready',.7+P.modeData.stage*.03)
|
||||
playReadySFX(3,.7+P.modeData.stage*.03)
|
||||
else
|
||||
SFX.play('start')
|
||||
playReadySFX(0,.7+P.modeData.stage*.03)
|
||||
P:win('finish')
|
||||
return
|
||||
end
|
||||
|
||||
@@ -206,34 +206,30 @@ function playClearSFX(cc)
|
||||
end
|
||||
end
|
||||
end
|
||||
function playReadySFX(i)
|
||||
function playReadySFX(i,vol)
|
||||
if i==3 then
|
||||
Snd('bass','A3')
|
||||
Snd('lead','A4')
|
||||
Snd('bass','A3',vol)
|
||||
Snd('lead','A4',vol)
|
||||
elseif i==2 then
|
||||
Snd('bass','F3')
|
||||
Snd('lead','A4')
|
||||
Snd('lead','D5')
|
||||
Snd('bass','F3',vol)
|
||||
Snd('lead','A4',vol)
|
||||
Snd('lead','D5',vol)
|
||||
elseif i==1 then
|
||||
Snd('bass','G3')
|
||||
Snd('lead','B4')
|
||||
Snd('lead','E5')
|
||||
Snd('bass','G3',vol)
|
||||
Snd('lead','B4',vol)
|
||||
Snd('lead','E5',vol)
|
||||
elseif i==0 then
|
||||
Snd('bass','A3')
|
||||
Snd('lead','A4')
|
||||
Snd('lead','E5')
|
||||
Snd('lead','A5')
|
||||
Snd('bass','A3',vol)
|
||||
Snd('lead','A4',vol)
|
||||
Snd('lead','E5',vol)
|
||||
Snd('lead','A5',vol)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--Game
|
||||
function coin(a,b)
|
||||
if rnd()<.5 then
|
||||
return a
|
||||
else
|
||||
return b
|
||||
end
|
||||
function getItem(itemName,amount)
|
||||
STAT.item[itemName]=STAT.item[itemName]+(amount or 1)
|
||||
end
|
||||
function generateLine(hole)
|
||||
return 1023-2^(hole-1)
|
||||
@@ -275,9 +271,11 @@ function freshDate(mode)
|
||||
if STAT.date~=date then
|
||||
STAT.date=date
|
||||
STAT.todayTime=0
|
||||
getItem('zTicket',1)
|
||||
if not mode:find'q'then
|
||||
MES.new('info',text.newDay)
|
||||
end
|
||||
saveStats()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -726,6 +726,10 @@ do--Userdata tables
|
||||
spin=(function()local L={}for i=1,29 do L[i]={0,0,0,0,0,0,0}end return L end)(),
|
||||
pc=0,hpc=0,b2b=0,b3b=0,score=0,
|
||||
lastPlay='sprint_10l',--Last played mode ID
|
||||
item=setmetatable({},{__index=function(self,k)
|
||||
self[k]=0
|
||||
return 0
|
||||
end}),
|
||||
date=false,
|
||||
todayTime=0,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ return{
|
||||
{"Translator Note 1",
|
||||
"",
|
||||
"help",
|
||||
"This translation of the TetroDictionary is provided by me, User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text.\n\nCorrected by C₂₉H₂₅N₃O₅.\n\nTo view the list of contributors or make contributions, feel free to visit the GitHub page.",
|
||||
"This translation of the TetroDictionary is provided by me, User670 (Discord: User670#9501).\n\nThe translation may not completely reflect the contents of the original Chinese text.\n\nCorrected by C₂₉H₂₅N₃O₅ (Discord: C29H25N3O5#1606).\n\nTo view the list of contributors or make contributions, feel free to visit the GitHub page.",
|
||||
"https://github.com/26F-Studio/Techmino/blob/main/parts/language/dict_en.lua",
|
||||
},
|
||||
{"Official Website",
|
||||
@@ -16,7 +16,7 @@ return{
|
||||
{"To New Players",
|
||||
"guide newbie noob",
|
||||
"help",
|
||||
"To new players that want to get better at the game:\n\tTwo principles:\n\t1. find a version with good controls (e.g. Techmino, Tetr.io, Tetris Online, Jstris, Tetr.js). Do not use those version used for programming practice.\n\t2. Build foundations in your skills (stable Techrashes using next queue to aid decisions), don't go for fancy T-Spins from the start.\n\n\tTwo main techniques:\n\t1. familiarize yourself with spawn locations of pieces, and the controls to move the piece into each location\n\t2. Plan ahead of where to put the pieces\nWe recommend that you read this article titled \"Words to newbies from a Tetris Pro\" (Click \"Open URL\". In Simplified Chinese)",
|
||||
"To new players that want to get better at the game:\n\tTwo principles:\n\t1. find a version with good controls (e.g. Techmino, Tetr.io, Tetris Online, Jstris, Tetr.js). Do not use those version used for programming practice.\n\t2. Build foundations in your skills (stable Techrashes using next queue to aid decisions), don't go for fancy T-Spins from the start.\n\n\tTwo main techniques:\n\t1. familiarize yourself with spawn locations of pieces, and the controls to move the piece into each location\n\t2. Plan ahead of where to put the pieces\nHere is a article written by a well-known player in Chinese Tetris community talking about advices to new players. Click the globe if you can read simplified Chinese.",
|
||||
"https://bilibili.com/read/cv2352939",
|
||||
},
|
||||
{"Learning T-spins",
|
||||
@@ -65,7 +65,7 @@ return{
|
||||
{"Communities",
|
||||
"community communities",
|
||||
"org",
|
||||
"Join Tetris communities and talk with other players!\n\nChina: [QQ] Tetris Research: 112897780\nGlobal: [Discord] Hard Drop: discord.gg/harddrop (click \"Open URL\").",
|
||||
"Join Tetris communities and talk with other players!\n\nChina: [QQ] Tetris Research: 112897780\nGlobal: [Discord] Hard Drop: discord.gg/harddrop (click the globe icon to open).",
|
||||
"https://discord.gg/harddrop"
|
||||
},
|
||||
{"Mew",
|
||||
@@ -77,7 +77,7 @@ return{
|
||||
{"Tetris OL Servers",
|
||||
"tetrisonline servers",
|
||||
"org",
|
||||
"Google \"Tetris Online Poland\" for the Poland server.\nClick \"Open URL\" for information about the Tetris Online Study server.",
|
||||
"Google \"Tetris Online Poland\" for the Poland server.\nClick on the globe icon for information about the Tetris Online Study server.",
|
||||
"http://teatube.ltd/tos",
|
||||
},
|
||||
|
||||
@@ -660,7 +660,18 @@ return{
|
||||
{"Topping out",
|
||||
"die death topout toppingout",
|
||||
"term",
|
||||
"Modern Tetris games have three different conditions in which the player tops out:\n1. Block out: when a piece spawned overlaps with the existing blocks in the field;\n2. Lock out: when a piece locks entirely above the skyline;\n3. Garbage out: when the stack exceeds 40 lines in height (often due to incoming garbage).\nTechmino does not check for locking out and garbage out.",
|
||||
"Modern Tetris games have three different conditions in which the player tops out:\n1. Block out: when a piece spawned overlaps with the existing blocks in the field;\n2. Lock out: when a piece locks entirely above the skyline;\n3. Top out: when the stack exceeds 40 lines in height (often due to incoming garbage).\nTechmino does not check for locking out and topping out.",
|
||||
},
|
||||
{"Buffer zone",
|
||||
"buffer zone above super invisible disappear",
|
||||
"term",
|
||||
"Refers to 21st-40th lines above the visible field. Because the blocks in the field could go over the visible field (this usually happens when multiple garbage lines come in) so the buffer zone was created so those blocks could go back to the field when garbage lines are cleared. Also, the buffer zone is usually located at 21st-40th lines because this is sufficient for most cases. Refer to \"Vanish Zone\" to learn more.",
|
||||
},
|
||||
{"Vanish zone",
|
||||
"vanish zone disappear gone cut die",
|
||||
"term",
|
||||
"Refers to the area located above the 40th line. This is usually realised by combining c4w and multiple garbage lines. In many games, when any block reaches the vanish zone, the game is terminated immediately.\nHowever, this area can have different behaviours in different games. Some games are flawed because the game could crash when the blocks enter the vanish zone (e.g. Tetris Online). Wierd behaviours could also happen when the blocks enter the vanish zone (you can refer to this video, click on the globe icon to open the link).\n\nFurthermore, the vanish zone in Jstris is located above the 22nd line, and any blocks locked above the 21st line will disappear. ",
|
||||
"https://youtu.be/z4WtWISkrdU",
|
||||
},
|
||||
{"Falling speed",
|
||||
"fallingspeed",
|
||||
|
||||
@@ -4,7 +4,7 @@ return{
|
||||
{"新人须知",
|
||||
"新人须知 xinren new noob readme",
|
||||
"help",
|
||||
"致想深入玩下去的新人:\n\n\t两大根本原则:\n\t\t1. 选手感好的版本(Tech/Tetr.io/Jstris/TOP/Tetr.js),别用编程练习渣版本\n\t\t2. 踏实打好基础(预判next稳定消四等),别总想着炫酷T旋,对未来发展没好处。\n\t两大主要技巧:\n\t\t1. 熟悉初始位置以及到各个位置的初始操作;\n\t\t2. 提前计算好下一块能放哪。\n\n推荐阅读专栏《给TOP新人的几点建议》\n\n[点击右下角按钮打开链接]",
|
||||
"致想深入玩下去的新人:\n\n\t两大根本原则:\n\t\t1. 选手感好的版本(Tech/Tetr.io/Jstris/TOP/Tetr.js),别用编程练习渣版本\n\t\t2. 踏实打好基础(预判next稳定消四等),别总想着炫酷T旋,对未来发展没好处。\n\t两大主要技巧:\n\t\t1. 熟悉初始位置以及到各个位置的初始操作;\n\t\t2. 提前计算好下一块能放哪。\n\n推荐阅读专栏《给TOP新人的几点建议》\n\n[点击右下角地球按钮打开链接]",
|
||||
"https://bilibili.com/read/cv2352939",
|
||||
},
|
||||
{"关于T-spin学习",
|
||||
@@ -685,7 +685,18 @@ return{
|
||||
{"死亡判定",
|
||||
"死亡判定 die death siwang",
|
||||
"term",
|
||||
"现代方块普遍使用的死亡判定:\n1. 新出现的方块和场地方块有重叠(窒息,Top Out)(c4w比s4w强的原因,因为被打进18行都不会窒息);\n2. 方块锁定时完全在场地的外面(Block Out);\n3. 场地内现存方块总高度大于40。部分游戏可能没有这条判定,而是会自动“切除”场地内所有高度大于40的部分(Vanish Zone)。\n\n注:本游戏使用的死亡判定不包含上述的第二条和第三条。",
|
||||
"现代方块普遍使用的死亡判定:\n1. 新出现的方块和场地方块有重叠(窒息,Block Out)(c4w比s4w强的原因,因为被打进18行都不会窒息);\n2. 方块锁定时完全在场地的外面(Lock Out);\n3. 场地内现存方块总高度大于40。(超高,Top Out)\n\n注:本游戏使用的死亡判定不包含上述的第二条和第三条。",
|
||||
},
|
||||
{"缓冲区",
|
||||
"缓冲区 buffer zone huanchongqu",
|
||||
"term",
|
||||
"(不是所有游戏都有这个概念)指10×20可见场地之上的21~40行。因为垃圾行顶起后两边堆高的方块可能会超出屏幕,消行后这些方块要重新回到场地内所以需要保存下来,由于程序上要求场地尺寸有限(部分游戏可以无限),故设定为40,一般都够用。\n\n另见“消失区”词条。",
|
||||
},
|
||||
{"消失区",
|
||||
"消失区 vanish zone xiaoshiqu",
|
||||
"term",
|
||||
"在缓冲区的基础上,指比40行缓冲区还高的区域。\n标准的死亡判定涉及了这个概念,在垃圾行升起后如果场地上有任何方块超出了40高的缓冲区(也就是达到了消失区)时游戏直接结束。\n但事实上这块区域在不同游戏中表现不同,甚至有设计者考虑不周导致方块挪到40行以上,但是程序没考虑导致方块接触消失区直接报错闪退的游戏。通常出现在玩家堆了c4w然后被打入大量垃圾行时才会考虑这个概念。其他游戏中方块进入消失区可能直接导致游戏结束,也有可能会出现一些奇怪的bug(附带链接是ppt的复制40行无限ren视频)。\n\n另,Jstris中22行及以上可以理解为消失区,锁定在21行之外的格子会消失。",
|
||||
"https://www.bilibili.com/video/BV1ZE411Y7GD",
|
||||
},
|
||||
{"下落速度",
|
||||
"下落速度 重力 drop speed zhongli gravity",
|
||||
|
||||
@@ -749,7 +749,7 @@ return{
|
||||
['sprintEff']= {"Sprint", "Efficiency", "Send more attack in 40lines!"},
|
||||
['zen']= {'Zen', "200", "A 200-line run without a time limit"},
|
||||
['ultra']= {'Ultra', "EXTRA", "A 2-minute score attack"},
|
||||
['infinite']= {'infinite', "", "Just a sandbox"},
|
||||
['infinite']= {"Infinite", "", "Just a sandbox"},
|
||||
['infinite_dig']= {"Infinite: Dig", "", "Dig-diggin'-dug"},
|
||||
['marathon_inf']= {"Marathon", "INFINITE", "Infinite marathon."},
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
return{
|
||||
env={
|
||||
drop=60,lock=60,
|
||||
eventSet='checkLine_40',
|
||||
eventSet='sprintEff_40',
|
||||
bg='bg2',bgm='race',
|
||||
},
|
||||
score=function(P)return{P.stat.atk/P.stat.row,P.stat.time}end,
|
||||
|
||||
@@ -578,7 +578,7 @@ function Player:changeAtk(R)
|
||||
self.atking=false
|
||||
end
|
||||
end
|
||||
function Player:freshBlock(mode)--string mode: push/move/fresh/newBlock
|
||||
function Player:freshBlock(mode,ifTele)--string mode: push/move/fresh/newBlock
|
||||
local ENV=self.gameEnv
|
||||
--Fresh ghost
|
||||
if(mode=='move'or mode=='newBlock'or mode=='push')and self.cur then
|
||||
@@ -643,7 +643,7 @@ function Player:freshBlock(mode)--string mode: push/move/fresh/newBlock
|
||||
end
|
||||
|
||||
--Play sound if touch ground
|
||||
if mode=='move'then
|
||||
if mode=='move'and not ifTele then
|
||||
self:checkTouchSound()
|
||||
end
|
||||
end
|
||||
@@ -2600,10 +2600,11 @@ function Player:act_insLeft(auto)
|
||||
while not self:ifoverlap(self.cur.bk,self.curX-1,self.curY)do
|
||||
self:createMoveFX('left')
|
||||
self.curX=self.curX-1
|
||||
self:freshBlock('move')
|
||||
self:freshBlock('move',true)
|
||||
end
|
||||
if self.curX~=x0 then
|
||||
self.spinLast=false
|
||||
self:checkTouchSound()
|
||||
end
|
||||
if self.gameEnv.shakeFX then
|
||||
self.swingOffset.vx=-1.5
|
||||
@@ -2624,10 +2625,11 @@ function Player:act_insRight(auto)
|
||||
while not self:ifoverlap(self.cur.bk,self.curX+1,self.curY)do
|
||||
self:createMoveFX('right')
|
||||
self.curX=self.curX+1
|
||||
self:freshBlock('move')
|
||||
self:freshBlock('move',true)
|
||||
end
|
||||
if self.curX~=x0 then
|
||||
self.spinLast=false
|
||||
self:checkTouchSound()
|
||||
end
|
||||
if self.gameEnv.shakeFX then
|
||||
self.swingOffset.vx=1.5
|
||||
|
||||
@@ -611,6 +611,16 @@ local commands={}do
|
||||
scene='app_arithmetic',
|
||||
description="Arithmetic"
|
||||
},
|
||||
{
|
||||
code="piano",
|
||||
scene='app_piano',
|
||||
description="A simple keyboard piano"
|
||||
},
|
||||
{
|
||||
code="spin",
|
||||
scene='app_spin',
|
||||
description="???"
|
||||
},
|
||||
}
|
||||
commands.app={
|
||||
code=function(name)
|
||||
|
||||
@@ -7,7 +7,6 @@ local setFont,mStr=FONT.set,GC.mStr
|
||||
local int,rnd,abs=math.floor,math.random,math.abs
|
||||
local max,min=math.max,math.min
|
||||
local ins,rem=table.insert,table.remove
|
||||
local function sign(a)return a>0 and 1 or a<0 and -1 or 0 end
|
||||
|
||||
local levels={
|
||||
{c=6,r=3,color=3},
|
||||
@@ -289,7 +288,7 @@ function scene.update(dt)
|
||||
if state==1 then
|
||||
time=TIME()-startTime
|
||||
comboTime=max(comboTime-dt,0)
|
||||
score1=score1+sign(score-score1)+int((score-score1)*.1+.5)
|
||||
score1=score1+MATH.sign(score-score1)+int((score-score1)*.1+.5)
|
||||
end
|
||||
|
||||
if sure>0 then sure=sure-dt end
|
||||
|
||||
53
parts/scenes/app_piano.lua
Normal file
53
parts/scenes/app_piano.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
local gc=love.graphics
|
||||
local kb=love.keyboard
|
||||
|
||||
local instList={'lead','bell','bass'}
|
||||
local keys={
|
||||
['1']=61,['2']=63,['3']=65,['4']=66,['5']=68,['6']=70,['7']=72,['8']=73,['9']=75,['0']=77,['-']=78,['=']=80,['backspace']=82,
|
||||
['q']=49,['w']=51,['e']=53,['r']=54,['t']=56,['y']=58,['u']=60,['i']=61,['o']=63,['p']=65,['[']=66,[']']=68,['\\']=70,
|
||||
['a']=37,['s']=39,['d']=41,['f']=42,['g']=44,['h']=46,['j']=48,['k']=49,['l']=51,[';']=53,["'"]=54,['return']=56,
|
||||
['z']=25,['x']=27,['c']=29,['v']=30,['b']=32,['n']=34,['m']=36,[',']=37,['.']=39,['/']=41,
|
||||
}
|
||||
local inst
|
||||
local offset
|
||||
|
||||
local scene={}
|
||||
|
||||
function scene.sceneInit()
|
||||
inst='lead'
|
||||
offset=0
|
||||
end
|
||||
|
||||
function scene.touchDown(x,y,k)
|
||||
--TODO
|
||||
end
|
||||
scene.mouseDown=scene.touchDown
|
||||
|
||||
function scene.keyDown(key,isRep)
|
||||
if not isRep and keys[key]then
|
||||
local note=keys[key]+offset
|
||||
if kb.isDown('lshift','rshift')then note=note+1 end
|
||||
if kb.isDown('lctrl','rctrl')then note=note-1 end
|
||||
SFX.playSample(inst,note)
|
||||
TEXT.show(SFX.getNoteName(note),math.random(150,1130),math.random(140,500),60,'score',.8)
|
||||
elseif key=='tab'then
|
||||
inst=TABLE.next(instList,inst)
|
||||
elseif key=='lalt'then
|
||||
offset=math.max(offset-1,-12)
|
||||
elseif key=='ralt'then
|
||||
offset=math.min(offset+1,12)
|
||||
elseif key=='escape'then
|
||||
SCN.back()
|
||||
end
|
||||
end
|
||||
|
||||
function scene.draw()
|
||||
setFont(30)
|
||||
gc.print(inst,40,60)
|
||||
gc.print(offset,40,100)
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene},
|
||||
}
|
||||
return scene
|
||||
48
parts/scenes/app_spin.lua
Normal file
48
parts/scenes/app_spin.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
local spinner=require'parts/spinner'.new({
|
||||
{font=45,disp=CHAR.icon.retry_spin,item='zTicket',amount=1,freq=30},
|
||||
{font=60,disp=CHAR.mino.Z,item='Zfrag',amount=1,freq=10},
|
||||
{font=60,disp=CHAR.mino.S,item='Sfrag',amount=1,freq=10},
|
||||
{font=60,disp=CHAR.mino.J,item='Jfrag',amount=1,freq=10},
|
||||
{font=60,disp=CHAR.mino.L,item='Lfrag',amount=1,freq=10},
|
||||
{font=60,disp=CHAR.mino.T,item='Tfrag',amount=1,freq=10},
|
||||
{font=60,disp=CHAR.mino.O,item='Ofrag',amount=1,freq=10},
|
||||
{font=60,disp=CHAR.mino.I,item='Ifrag',amount=1,freq=10},
|
||||
},function(item,amount)
|
||||
getItem(item,amount)
|
||||
saveStats()
|
||||
end)
|
||||
|
||||
local scene={}
|
||||
|
||||
function scene.keyDown(key,isRep)
|
||||
if isRep then return end
|
||||
if key=='space'or key=='return'then
|
||||
if STAT.item.zTicket>0 then
|
||||
if spinner:start()then
|
||||
STAT.item.zTicket=STAT.item.zTicket-1
|
||||
saveStats()
|
||||
end
|
||||
else
|
||||
MES.new('info',"Not enough zTicket")
|
||||
end
|
||||
elseif key=='escape'then
|
||||
SCN.back()
|
||||
end
|
||||
end
|
||||
|
||||
function scene.update(dt)
|
||||
spinner:update(dt)
|
||||
end
|
||||
|
||||
function scene.draw()
|
||||
setFont(40)
|
||||
love.graphics.print("zTickets: "..STAT.item.zTicket,90,80)
|
||||
spinner:draw(640,360)
|
||||
end
|
||||
|
||||
scene.widgetList={
|
||||
WIDGET.newButton{name="spin", x=1140,y=360,w=120,font=60,fText=CHAR.icon.retry_spin,code=pressKey"space"},
|
||||
WIDGET.newButton{name="back", x=1140,y=640,w=170,h=80,font=60,fText=CHAR.icon.back,code=backScene},
|
||||
}
|
||||
return scene
|
||||
@@ -14,9 +14,9 @@ local widgetX0={
|
||||
}
|
||||
local enterConsole=coroutine.wrap(function()
|
||||
while true do
|
||||
Snd('bell',.6,'A4',.7,'E5',1,coin('A5','B5'))YIELD()
|
||||
Snd('bell',.6,'A4',.7,'F5',1,coin('C6','D6'))YIELD()
|
||||
Snd('bell',.6,'A4',.7,'G5',1,coin('E6','G6'))YIELD()
|
||||
Snd('bell',.6,'A4',.7,'E5',1,MATH.coin('A5','B5'))YIELD()
|
||||
Snd('bell',.6,'A4',.7,'F5',1,MATH.coin('C6','D6'))YIELD()
|
||||
Snd('bell',.6,'A4',.7,'G5',1,MATH.coin('E6','G6'))YIELD()
|
||||
Snd('bell',.6,'A4',.7,'A5',1,'A6')SFX.play('ren_mega')SCN.go('app_console')YIELD()
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -63,6 +63,11 @@ function scene.keyDown(key,isRep)
|
||||
SCN.swapTo('launchpad','none')
|
||||
elseif key=="escape"then
|
||||
SCN.back()
|
||||
elseif #key==1 and key:find'[0-9a-z]'then
|
||||
for _=1,#bgmList do
|
||||
selected=selected%#bgmList+1
|
||||
if bgmList[selected]:sub(1,1)==key then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
112
parts/spinner.lua
Normal file
112
parts/spinner.lua
Normal file
@@ -0,0 +1,112 @@
|
||||
local gc=love.graphics
|
||||
|
||||
local Spinner={
|
||||
data={},
|
||||
totalFreq=0,
|
||||
|
||||
spinning=false,
|
||||
angle=0,
|
||||
angV=0,
|
||||
|
||||
chosen=false,
|
||||
light=0,
|
||||
}
|
||||
Spinner.__index=Spinner
|
||||
function Spinner:start()
|
||||
if not self.spinning then
|
||||
self.spinning=true
|
||||
self.angle=MATH.tau*math.random()
|
||||
self.angV=.62+.26*math.random()
|
||||
return true
|
||||
end
|
||||
end
|
||||
function Spinner:update(dt)
|
||||
if self.spinning then
|
||||
self.angle=(self.angle+self.angV*dt*60)%MATH.tau
|
||||
local dV=
|
||||
self.angV>.26 and .0026 or
|
||||
self.angV>.12 and .0012 or
|
||||
self.angV>.04 and .0004 or
|
||||
.0001
|
||||
self.angV=self.angV-dV*dt*60
|
||||
if self.angV<=0 then
|
||||
self.angV=0
|
||||
self.spinning=false
|
||||
local freq=self.angle%MATH.tau/MATH.tau*self.totalFreq
|
||||
for i=1,#self.data do
|
||||
local D=self.data[i]
|
||||
freq=freq-D.freq
|
||||
if freq<=0 then
|
||||
self.chosen=D
|
||||
self.light=1
|
||||
if D.item then
|
||||
self.hook_stop(D.item,D.amount)
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.light>0 then
|
||||
self.light=self.light-dt
|
||||
end
|
||||
end
|
||||
end
|
||||
function Spinner:draw(x,y)
|
||||
gc.push('transform')
|
||||
gc.translate(x,y)
|
||||
|
||||
--Draw circle
|
||||
gc.setColor(1,1,1)
|
||||
gc.setLineWidth(3)
|
||||
gc.circle('line',0,0,300)
|
||||
|
||||
--Draw areas
|
||||
gc.setLineWidth(1)
|
||||
local freq=0
|
||||
for i=1,#self.data do
|
||||
gc.line(10,0,290,0)
|
||||
local D=self.data[i]
|
||||
freq=freq+D.freq
|
||||
if D==self.chosen then
|
||||
gc.setColor(1,1,1,.5*self.light)
|
||||
gc.arc('fill','pie',0,0,300,0,-D.freq*MATH.tau/self.totalFreq)
|
||||
gc.setColor(1,1,1)
|
||||
end
|
||||
local dAng=-MATH.tau*D.freq/self.totalFreq
|
||||
gc.rotate(dAng*.5)
|
||||
if D.amount>0 then
|
||||
setFont(D.font)
|
||||
if D.amount==1 then
|
||||
mStr(D.disp,170,-D.font*.7)
|
||||
else
|
||||
mStr(D.disp.."x"..D.amount,170,-D.font*.7)
|
||||
end
|
||||
end
|
||||
gc.rotate(dAng*.5)
|
||||
end
|
||||
|
||||
gc.pop()
|
||||
|
||||
--Draw target pin
|
||||
gc.setLineWidth(2)
|
||||
gc.setColor(1,.3,.3)
|
||||
gc.line(x,y,x+200*math.cos(self.angle),y-200*math.sin(self.angle))
|
||||
end
|
||||
function Spinner.new(data,hook_stop)
|
||||
local self={}
|
||||
setmetatable(self,Spinner)
|
||||
|
||||
local sum=0
|
||||
for i=1,#data do
|
||||
sum=sum+data[i].freq
|
||||
if not data[i].font then data[i].font=30 end
|
||||
end
|
||||
self.data=data
|
||||
self.totalFreq=sum
|
||||
self.hook_stop=hook_stop
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return Spinner
|
||||
@@ -1,18 +1,15 @@
|
||||
return[=[
|
||||
未来模式:
|
||||
任务树; 大爆炸; 拼方形; 限高无尽挖掘; 连击练习; 极简教程/考试
|
||||
未来小游戏:
|
||||
Tetro-1010(四/五连块, 2C2N, 若干回合改变重力方向); Tetra-link(桌游)
|
||||
噗哟; 泡泡龙; 求合体; 坦克大战; 扫雷; 接水管; 数字记忆; 听声记忆
|
||||
Tetro-1010(2C2N, 重力); Tetra-link(桌游)
|
||||
噗哟; 泡泡龙; 求合体; 坦克大战; 扫雷; 接水管; 记忆
|
||||
其他未来内容:
|
||||
组队战; 实时统计数据可视化; 教学关; 从录像继续
|
||||
重做模式选择UI; 重做模组UI; 加速下落; spike相关统计数据
|
||||
支持更多手柄; 场地格边缘线; 模式数据分析; 高级自定义序列
|
||||
等级系统; 成就系统; Domain状态; 手势操作; C2连击; 特殊控件(虚拟摇杆等)
|
||||
方块位移/旋转动画; 更细节的DAS选项; 拓展主题系统; 无用货币
|
||||
等级系统; 成就系统; 手势操作; C2连击; 特殊控件(虚拟摇杆等)
|
||||
方块位移/旋转动画; 更细节的DAS选项; 拓展主题系统
|
||||
可调攻击系统; 更多消除方式; 可调场地宽度; 新联网游戏场景切换逻辑
|
||||
工程编译到字节码; task-Z(新AI)
|
||||
收集向抽奖; 自适应UI; 多方块
|
||||
工程编译到字节码; task-Z(新AI); 自适应UI; 多方块
|
||||
|
||||
0.16.5: 新世界 New World
|
||||
新增:
|
||||
@@ -23,21 +20,29 @@ return[=[
|
||||
新BGM:peak(暂未使用)
|
||||
新BGM:1989(用于经典模式,by C₂₉H₂₅N₃O₅)
|
||||
删除节奏模式(之后会有全新音游模式)
|
||||
音乐室输入首字母自动跳转
|
||||
移除模式标题的颜色
|
||||
改动:
|
||||
移动音效改为触地音效,在方块因重力或旋转触地时也会播放
|
||||
新增piano小程序(目前只支持键盘操作)
|
||||
再调整场地晃动的阻力,看起来更舒服
|
||||
TRS的J5和L5新增一个180度踢墙
|
||||
重做全局颜色表(by C₂₉H₂₅N₃O₅)
|
||||
经典模式添加干旱计数器 #452
|
||||
重新安排一些模式的BGM
|
||||
堆积模式移出地图,修改规则可以消超过20行
|
||||
堆积模式移出地图,修改规则可以消超过20行 #449
|
||||
只在更新后触发自动转换以旧版本模式名存储的数据
|
||||
再次更换字体
|
||||
代码:
|
||||
播放乐器采样更自然并允许超过音源范围
|
||||
添加数学扩展模块
|
||||
添加死亡事件触发器
|
||||
修复:
|
||||
堆积模式超级消除有时报错
|
||||
词典导出词条保留了替换敏感词的特殊字符
|
||||
修改准备音效后ultra倒计时声音不见了
|
||||
0arr时自动移动时声音特别响
|
||||
时间转换函数可能输出1分60 #451
|
||||
堆积模式超级消除有时报错
|
||||
|
||||
0.16.4: 虫洞 Wormhole
|
||||
新增:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
return{
|
||||
["apkCode"]=398,
|
||||
["apkCode"]=400,
|
||||
["code"]=1605,
|
||||
["string"]="V0.16.5",
|
||||
["room"]="ver A-0",
|
||||
|
||||
Reference in New Issue
Block a user