SongSelect: Add ura difficulty

This commit is contained in:
LoveEevee 2018-10-12 21:04:28 +03:00
parent 6ccdc18ec6
commit f80565f25b
17 changed files with 141 additions and 70 deletions

View File

@ -10,7 +10,7 @@ Still in developement. Works best with Chrome.
Create a SQLite databse named `taiko.db` with the following schema:
CREATE TABLE "songs" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `title_en` TEXT, `easy` INTEGER, `normal` INTEGER, `hard` INTEGER, `oni` INTEGER, `enabled` INTEGER NOT NULL, `category` INTEGER, `type` TEXT , `offset` REAL NOT NULL )
CREATE TABLE "songs" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `title_en` TEXT, `easy` INTEGER, `normal` INTEGER, `hard` INTEGER, `oni` INTEGER, `ura` INTEGER, `enabled` INTEGER NOT NULL, `category` INTEGER, `type` TEXT , `offset` REAL NOT NULL )
CREATE TABLE "categories" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `title_en` TEXT NOT NULL )
When inserting song rows, leave any difficulty columns as NULL if you don't intend to add notecharts for them.

19
app.py
View File

@ -105,33 +105,34 @@ def route_api_songs():
categories[cat[0]] = {'title': cat[1], 'title_en': cat[2]}
songs_out = []
for song in songs:
type = song[9]
id = song[0]
type = song[10]
if type == "tja":
if os.path.isfile('public/songs/%s/main.tja' % song[0]):
preview = get_tja_preview('public/songs/%s/main.tja' % song[0])
if os.path.isfile('public/songs/%s/main.tja' % id):
preview = get_tja_preview('public/songs/%s/main.tja' % id)
else:
preview = 0
else:
osus = [osu for osu in os.listdir('public/songs/%s' % song[0]) if osu in ['easy.osu', 'normal.osu', 'hard.osu', 'oni.osu']]
osus = [osu for osu in os.listdir('public/songs/%s' % id) if osu in ['easy.osu', 'normal.osu', 'hard.osu', 'oni.osu']]
if osus:
osud = parse_osu('public/songs/%s/%s' % (song[0], osus[0]))
osud = parse_osu('public/songs/%s/%s' % (id, osus[0]))
preview = int(get_osu_key(osud, 'General', 'PreviewTime', 0))
else:
preview = 0
category_out = categories[song[8]] if song[8] in categories else def_category
category_out = categories[song[9]] if song[9] in categories else def_category
songs_out.append({
'id': song[0],
'id': id,
'title': song[1],
'title_en': song[2],
'stars': [
song[3], song[4], song[5], song[6]
song[3], song[4], song[5], song[6], song[7]
],
'preview': preview,
'category': category_out['title'],
'category_en': category_out['title_en'],
'type': type,
'offset': song[10]
'offset': song[11]
})
return jsonify(songs_out)

View File

@ -61,6 +61,7 @@
height: 50%;
text-align: center;
margin: auto;
overflow: hidden;
}
#touch-drum-img{
width: 100%;

View File

@ -13,6 +13,7 @@ body{
height: 100%;
background: #fe7839;
user-select: none;
touch-action: none;
}
#screen{
width: 100%;

View File

@ -508,7 +508,7 @@
ctx.save()
ctx.lineWidth = config.border
ctx.strokeStyle = "#000"
var icon = this.diffIconPath[config.diff]
var icon = this.diffIconPath[config.diff === 4 ? 3 : config.diff]
ctx.translate(config.x - icon[0].w * scale / 2, config.y - icon[0].h * scale / 2)
ctx.scale(scale, scale)
for(var i = 1; i < icon.length; i++){
@ -518,7 +518,11 @@
}
if(!config.noFill){
for(var i = 1; i < icon.length; i++){
if(config.diff === 4 && icon[i].fill === "#db1885"){
ctx.fillStyle = "#7135db"
}else{
ctx.fillStyle = icon[i].fill
}
ctx.fill(icon[i].d)
}
}

View File

@ -43,14 +43,12 @@ class Controller{
this.continueBtn = document.getElementById("continue-butt")
this.restartBtn = document.getElementById("restart-butt")
this.songSelBtn = document.getElementById("song-selection-butt")
pageEvents.add(this.continueBtn, "click", () => {
this.togglePauseMenu()
})
pageEvents.add(this.restartBtn, "click", () => {
pageEvents.add(this.continueBtn, ["click", "touchend"], this.togglePauseMenu.bind(this))
pageEvents.add(this.restartBtn, ["click", "touchend"], () => {
assets.sounds["don"].play()
this.restartSong()
})
pageEvents.add(this.songSelBtn, "click", () => {
pageEvents.add(this.songSelBtn, ["click", "touchend"], () => {
assets.sounds["don"].play()
this.songSelection()
})
@ -63,9 +61,6 @@ class Controller{
stopMainLoop(){
this.mainLoopRunning = false
this.mainAsset.stop()
if(this.syncWith){
this.syncWith.stopMainLoop()
}
}
mainLoop(){
if(this.mainLoopRunning){
@ -212,11 +207,11 @@ class Controller{
this.keyboard.clean()
this.view.clean()
pageEvents.remove(this.continueBtn, "click")
pageEvents.remove(this.continueBtn, ["click", "touchend"])
delete this.continueBtn
pageEvents.remove(this.restartBtn, "click")
pageEvents.remove(this.restartBtn, ["click", "touchend"])
delete this.restartBtn
pageEvents.remove(this.songSelBtn, "click")
pageEvents.remove(this.songSelBtn, ["click", "touchend"])
delete this.songSelBtn
}
}

View File

@ -12,6 +12,7 @@ class GameRules{
break
case "hard":
case "oni":
case "ura":
this.good = 3 / 2 * frame
this.ok = 9 / 2 * frame
this.bad = 13 / 2 * frame

View File

@ -6,6 +6,10 @@ class Loader{
this.canvasTest = new CanvasTest()
p2 = new P2Connection()
this.ajax("src/views/loader.html").then(this.run.bind(this))
pageEvents.add(root, ["touchstart", "touchmove", "touchend"], event => {
event.preventDefault()
})
}
run(page){
this.promises = []
@ -152,5 +156,6 @@ class Loader{
delete this.loaderPercentage
delete this.loaderProgress
delete this.promises
pageEvents.remove(root, "touchstart")
}
}

View File

@ -1,5 +1,4 @@
function toggleFullscreen(){
var root = document.documentElement
if("requestFullscreen" in root){
if(document.fullscreenElement){
document.exitFullscreen()
@ -20,6 +19,8 @@ function toggleFullscreen(){
}
}
}
var root = document.documentElement
var fullScreenSupported = "requestFullscreen" in root || "webkitRequestFullscreen" in root || "mozRequestFullScreen" in root
var pageEvents = new PageEvents()
var snd = {}

View File

@ -8,6 +8,10 @@ class PageEvents{
this.add(window, "mousemove", this.mouseEvent.bind(this))
}
add(target, type, callback){
if(Array.isArray(type)){
type.forEach(type => this.add(target, type, callback))
return
}
this.remove(target, type)
var addedEvent = this.allEvents.get(target)
if(!addedEvent){
@ -18,6 +22,10 @@ class PageEvents{
return target.addEventListener(type, callback)
}
remove(target, type){
if(Array.isArray(type)){
type.forEach(type => this.remove(target, type))
return
}
var addedEvent = this.allEvents.get(target)
if(addedEvent){
var callback = addedEvent.get(type)

View File

@ -22,7 +22,14 @@
{name: false, txt: false},
{name: "balloon", txt: "ふうせん"}
]
this.courseTypes = ["easy", "normal", "hard", "oni"]
this.courseTypes = {
"0": "easy",
"1": "normal",
"2": "hard",
"3": "oni",
"4": "ura",
"edit": "ura"
}
this.metadata = this.parseMetadata()
this.measures = []
@ -67,10 +74,11 @@
value = value.trim()
if(name === "course"){
value = value.toLowerCase()
if(value in this.courseTypes){
courseName = this.courseTypes[value]
}else{
courseName = value.toLowerCase()
courseName = value
}
}else if(name === "balloon"){
value = value ? value.split(",").map(digit => parseInt(digit)) : []

View File

@ -89,8 +89,7 @@ class Scoresheet{
this.winH = null
pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this))
pageEvents.add(this.canvas, "mousedown", this.mouseDown.bind(this))
pageEvents.add(this.canvas, "touchstart", this.mouseDown.bind(this))
pageEvents.add(this.canvas, ["mousedown", "touchstart"], this.mouseDown.bind(this))
}
redraw(){
@ -291,7 +290,8 @@ class Scoresheet{
}
var imgScale = 1.35
ctx.drawImage(assets.image["muzu_" + results.difficulty],
var diffImage = results.difficulty === "ura" ? "oni" : results.difficulty
ctx.drawImage(assets.image["muzu_" + diffImage],
276, 150, imgScale * 176, imgScale * 120
)
@ -670,8 +670,7 @@ class Scoresheet{
snd.musicGain.fadeIn()
this.redrawRunning = false
pageEvents.keyRemove(this, "all")
pageEvents.remove(this.canvas, "mousedown")
pageEvents.remove(this.canvas, "touchstart")
pageEvents.remove(this.canvas, ["mousedown", "touchstart"])
delete this.ctx
delete this.canvas
}

View File

@ -149,7 +149,7 @@ class SongSelect{
this.difficultyCache = new CanvasCache()
this.difficulty = ["かんたん", "ふつう", "むずかしい", "おに"]
this.difficultyId = ["easy", "normal", "hard", "oni"]
this.difficultyId = ["easy", "normal", "hard", "oni", "ura"]
this.selectedSong = 0
this.selectedDiff = 0
@ -181,6 +181,7 @@ class SongSelect{
screenMS: this.getMS(),
move: 0,
moveMS: 0,
ura: 0,
moveHover: null,
locked: true,
hasPointer: false
@ -210,12 +211,11 @@ class SongSelect{
this.redraw()
pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this))
pageEvents.add(this.canvas, "mousemove", this.mouseMove.bind(this))
pageEvents.add(this.canvas, "mousedown", this.mouseDown.bind(this))
pageEvents.add(this.canvas, "touchstart", this.mouseDown.bind(this))
if(touchEnabled){
pageEvents.add(this.canvas, ["mousedown", "touchstart"], this.mouseDown.bind(this))
if(touchEnabled && fullScreenSupported){
this.touchFullBtn = document.getElementById("touch-full-btn")
this.touchFullBtn.style.display = "block"
pageEvents.add(this.touchFullBtn, "click", toggleFullscreen)
pageEvents.add(this.touchFullBtn, "touchend", toggleFullscreen)
}
}
@ -306,6 +306,12 @@ class SongSelect{
|| mouse.y < 40 || mouse.y > 540
){
this.toSongSelect()
}else if(moveBy === 5){
this.state.ura = !this.state.ura
assets.sounds["ka"].play()
if(this.selectedDiff === 5 && !this.state.ura){
this.state.move = -1
}
}else if(moveBy !== null){
this.toLoadSong(moveBy - 1, shift, ctrl, touch)
}
@ -370,10 +376,10 @@ class SongSelect{
if(this.state.locked === 0){
if(100 < x && x < 160 && 120 < y && y < 420){
return 0
}else if(434 < x && x < 810 && 95 < y && y < 524){
var moveBy = Math.floor((x - 434) / ((810 - 434) / 4)) + 1
}else if(422 < x && x < 922 && 95 < y && y < 524){
var moveBy = Math.floor((x - 422) / ((922 - 422) / 5)) + 1
var currentSong = this.songs[this.selectedSong]
if(currentSong.stars[moveBy - 1]){
if(this.state.ura && moveBy === 4 || currentSong.stars[moveBy - 1]){
return moveBy
}
}
@ -425,6 +431,7 @@ class SongSelect{
this.state.screenMS = this.getMS()
this.state.locked = true
this.state.moveHover = null
this.state.ura = 0
assets.sounds["don"].play()
assets.sounds["song-select"].stop()
@ -468,6 +475,10 @@ class SongSelect{
localStorage["selectedSong"] = this.selectedSong
localStorage["selectedDiff"] = difficulty + 1
if(difficulty === 3 && this.state.ura){
difficulty = 4
}
new loadSong({
"title": selectedSong.title,
"folder": selectedSong.id,
@ -698,9 +709,28 @@ class SongSelect{
this.state.locked = 0
}
if(this.state.move){
var hasUra = currentSong.stars[4]
var previousSelection = this.selectedDiff
do{
this.selectedDiff = this.mod(5, this.selectedDiff + this.state.move)
}while(this.selectedDiff !== 0 && !currentSong.stars[this.selectedDiff - 1])
if(hasUra && this.state.move > 0){
this.selectedDiff += this.state.move
if(this.selectedDiff > 5){
this.state.ura = !this.state.ura
if(this.state.ura){
this.selectedDiff = previousSelection === 4 ? 5 : previousSelection
break
}else{
this.state.move = -1
}
}
}else{
this.selectedDiff = this.mod(6, this.selectedDiff + this.state.move)
}
}while(
this.selectedDiff !== 0 && !currentSong.stars[this.selectedDiff - 1]
|| this.selectedDiff === 4 && this.state.ura
|| this.selectedDiff === 5 && !this.state.ura
)
this.state.move = 0
}else if(!currentSong.stars[this.selectedDiff - 1]){
this.selectedDiff = 0
@ -904,7 +934,8 @@ class SongSelect{
}
}
for(var i = 0; currentSong.stars && i < 4; i++){
if(currentSong.stars[i]){
var currentUra = !songSel && i === 3 && this.state.ura
if(currentSong.stars[i] || currentUra){
if(songSel){
var _x = x + 33 + i * 60
var _y = y + 120
@ -943,7 +974,7 @@ class SongSelect{
ctx.strokeRect(_x - 28, _y + 19, 56, 351)
this.draw.diffIcon({
ctx: ctx,
diff: i,
diff: currentUra ? 4 : i,
x: _x,
y: _y - 12,
scale: 1.4,
@ -971,13 +1002,14 @@ class SongSelect{
fontFamily: this.font
})
})
var songStars = currentUra ? currentSong.stars[4] : currentSong.stars[i]
for(var j = 0; j < 10; j++){
if(songSel){
var yPos = _y + 113 + j * 17
}else{
var yPos = _y + 178 + j * 19.5
}
if(10 - j > currentSong.stars[i]){
if(10 - j > songStars){
ctx.fillStyle = songSel ? "#e97526" : "#e7e7e7"
ctx.beginPath()
ctx.arc(_x, yPos, songSel ? 4.5 : 5, 0, Math.PI * 2)
@ -992,6 +1024,10 @@ class SongSelect{
})
}
}
var currentDiff = this.selectedDiff - 1
if(this.selectedDiff === 5){
currentDiff = 3
}
if(i === currentSong.p2Cursor){
this.draw.diffCursor({
ctx: ctx,
@ -999,13 +1035,12 @@ class SongSelect{
x: _x,
y: _y - (songSel ? 45 : 65),
two: true,
side: songSel ? false : (currentSong.p2Cursor === this.selectedDiff - 1),
side: songSel ? false : (currentSong.p2Cursor === currentDiff),
scale: songSel ? 0.7 : 1
})
}
if(!songSel){
var highlight = 0
var currentDiff = this.selectedDiff - 1
if(this.state.moveHover - 1 === i){
highlight = 2
}else if(currentDiff === i){
@ -1035,6 +1070,17 @@ class SongSelect{
}
}
}
if(!songSel && currentSong.stars[4]){
var _x = x + 402 + 4 * 100
var _y = y + 258
ctx.fillStyle = "#e0be28"
ctx.beginPath()
ctx.moveTo(_x - 35, _y - 25)
ctx.lineTo(_x - 10, _y)
ctx.lineTo(_x - 35, _y + 25)
ctx.fill()
}
ctx.globalAlpha = 1 - Math.max(0, opened - 0.5) * 2
ctx.fillStyle = selectedSkin.background
ctx.fillRect(x, y, w, h)
@ -1066,8 +1112,6 @@ class SongSelect{
fontFamily: this.font
})
})
//ctx.fillStyle="#f00"
//ctx.fillRect(textX,textY,textW,textH)
}
})
@ -1212,6 +1256,9 @@ class SongSelect{
var id = idDiff.id |0
var diff = idDiff.diff
var diffId = this.difficultyId.indexOf(diff)
if(diffId > 3){
diffId = 3
}
if(diffId >= 0){
var currentSong = this.songs.find(song => song.id === id)
currentSong.p2Cursor = diffId
@ -1255,10 +1302,8 @@ class SongSelect{
this.redrawRunning = false
this.endPreview()
pageEvents.keyRemove(this, "all")
pageEvents.remove(this.canvas, "mousemove")
pageEvents.remove(this.canvas, "mousedown")
pageEvents.remove(this.canvas, "touchstart")
if(this.touchEnabled){
pageEvents.remove(this.canvas, ["mousemove", "mousedown", "touchstart"])
if(this.touchEnabled && fullScreenSupported){
pageEvents.remove(this.touchFullBtn, "click")
delete this.touchFullBtn
}

View File

@ -2,11 +2,7 @@
constructor(){
var AudioContext = window.AudioContext || window.webkitAudioContext
this.context = new AudioContext()
pageEvents.once(window, "click").then(() => {
if(this.context.state === "suspended"){
this.context.resume()
}
})
pageEvents.add(window, ["click", "touchend"], this.pageClicked.bind(this))
}
load(url, gain){
return loader.ajax(url, request => {
@ -48,6 +44,11 @@
source.connect(sound.gain.gainNode || this.context.destination)
return source
}
pageClicked(){
if(this.context.state === "suspended"){
this.context.resume()
}
}
}
class SoundGain{
constructor(soundBuffer, channel){

View File

@ -3,8 +3,7 @@ class Titlescreen{
loader.changePage("titlescreen")
this.titleScreen = document.getElementById("title-screen")
pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this))
pageEvents.add(this.titleScreen, "mousedown", this.onPressed.bind(this))
pageEvents.once(this.titleScreen, "touchstart").then(this.onPressed.bind(this))
pageEvents.add(this.titleScreen, ["mousedown", "touchstart"], this.onPressed.bind(this))
assets.sounds["title"].play()
this.gamepad = new Gamepad({
"13": ["a", "b", "x", "y", "start", "ls", "rs"]
@ -48,8 +47,7 @@ class Titlescreen{
this.gamepad.clean()
assets.sounds["title"].stop()
pageEvents.keyRemove(this, "all")
pageEvents.remove(this.titleScreen, "mousedown")
pageEvents.remove(this.titleScreen, "touchstart")
pageEvents.remove(this.titleScreen, ["mousedown", "touchstart"])
delete this.titleScreen
}
}

View File

@ -5,8 +5,7 @@ class Tutorial{
assets.sounds["bgm_setsume"].playLoop(0.1, false, 0, 1.054, 16.054)
this.endButton = document.getElementById("tutorial-end-button")
pageEvents.once(this.endButton, "mousedown").then(this.onEnd.bind(this))
pageEvents.once(this.endButton, "touchstart").then(this.onEnd.bind(this))
pageEvents.once(this.endButton, ["mousedown", "touchstart"]).then(this.onEnd.bind(this))
pageEvents.keyOnce(this, 13, "down").then(this.onEnd.bind(this))
this.gamepad = new Gamepad({
@ -29,7 +28,7 @@ class Tutorial{
clean(){
this.gamepad.clean()
assets.sounds["bgm_setsume"].stop()
pageEvents.remove(this.endButton, "click")
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
pageEvents.keyRemove(this, 13)
delete this.endButton
}

View File

@ -64,10 +64,13 @@ class View{
pageEvents.add(this.canvas.canvas, "touchstart", this.ontouch.bind(this))
this.touchFullBtn = document.getElementById("touch-full-btn")
pageEvents.add(this.touchFullBtn, "click", toggleFullscreen)
pageEvents.add(this.touchFullBtn, "touchend", toggleFullscreen)
if(!fullScreenSupported){
this.touchFullBtn.style.display = "none"
}
this.touchPauseBtn = document.getElementById("touch-pause-btn")
pageEvents.add(this.touchPauseBtn, "click", () => {
pageEvents.add(this.touchPauseBtn, "touchend", () => {
this.controller.togglePauseMenu()
})
}
@ -667,7 +670,8 @@ class View{
}
}
drawDifficulty(){
this.ctx.drawImage(assets.image["muzu_" + this.songDifficulty],
var diffImage = this.songDifficulty === "ura" ? "oni" : this.songDifficulty
this.ctx.drawImage(assets.image["muzu_" + diffImage],
this.diffX, this.diffY,
this.diffW, this.diffH
)
@ -946,15 +950,15 @@ class View{
}
clean(){
pageEvents.mouseRemove(this)
if(this.controller.multiplayer === 2){
if(this.controller.multiplayer === 2 && this.canvas){
this.canvas.canvas.parentNode.removeChild(this.canvas.canvas)
}else{
this.cursor.parentNode.removeChild(this.cursor)
}
if(this.touchEnabled){
pageEvents.remove(this.canvas.canvas, "touchstart")
pageEvents.remove(this.touchFullBtn, "click")
pageEvents.remove(this.touchPauseBtn, "click")
pageEvents.remove(this.touchFullBtn, "touchend")
pageEvents.remove(this.touchPauseBtn, "touchend")
this.gameDiv.classList.remove("touch-visible")
document.getElementById("version").classList.remove("version-hide")
delete this.touchDrumDiv