mirror of
https://github.com/yuukiwww/taiko-web.git
synced 2024-10-07 16:48:31 +02:00
Merge pull request #34 from LoveEevee/new-songsel
Changed song selection screen
This commit is contained in:
commit
3fcec50b53
23
app.py
23
app.py
@ -69,6 +69,11 @@ def close_connection(exception):
|
||||
@app.route('/api/songs')
|
||||
def route_api_songs():
|
||||
songs = query_db('select * from songs where enabled = 1')
|
||||
raw_categories = query_db('select * from categories')
|
||||
categories = {}
|
||||
def_category = {'title': None, 'title_en': None}
|
||||
for cat in raw_categories:
|
||||
categories[cat[0]] = {'title': cat[1], 'title_en': cat[2]}
|
||||
songs_out = []
|
||||
for song in songs:
|
||||
osus = [osu for osu in os.listdir('public/songs/%s' % song[0]) if osu in ['easy.osu', 'normal.osu', 'hard.osu', 'oni.osu']]
|
||||
@ -77,13 +82,19 @@ def route_api_songs():
|
||||
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
|
||||
|
||||
songs_out.append(
|
||||
{'id': song[0], 'title': song[1], 'title_en': song[2], 'stars': {
|
||||
'easy': song[3], 'normal': song[4],
|
||||
'hard': song[5], 'oni': song[6]
|
||||
}, 'preview': preview}
|
||||
)
|
||||
songs_out.append({
|
||||
'id': song[0],
|
||||
'title': song[1],
|
||||
'title_en': song[2],
|
||||
'stars': [
|
||||
song[3], song[4], song[5], song[6]
|
||||
],
|
||||
'preview': preview,
|
||||
'category': category_out['title'],
|
||||
'category_en': category_out['title_en']
|
||||
})
|
||||
|
||||
return jsonify(songs_out)
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
<link rel="stylesheet" href="/src/css/main.css"/>
|
||||
<link rel="stylesheet" href="/src/css/loader.css">
|
||||
<link rel="stylesheet" href="/src/css/titlescreen.css">
|
||||
<link rel="stylesheet" href="/src/css/songselect.css">
|
||||
<link rel="stylesheet" href="/src/css/scoresheet.css">
|
||||
<link rel="stylesheet" href="/src/css/loadsong.css">
|
||||
<link rel="stylesheet" href="/src/css/game.css">
|
||||
|
@ -32,11 +32,13 @@
|
||||
font-family: TnT;
|
||||
font-size: 3.5vmin;
|
||||
border-radius: 1.5vmin;
|
||||
outline: none;
|
||||
}
|
||||
#pause-menu button:hover{
|
||||
border-color:#fa5d3a;
|
||||
#pause-menu button:hover,
|
||||
#pause-menu .window:not(:hover) button.selected{
|
||||
color:white;
|
||||
background:#0c6577;
|
||||
border-color:#fa5d3a;
|
||||
}
|
||||
#cursor{
|
||||
position: fixed;
|
||||
|
@ -188,3 +188,27 @@ kbd{
|
||||
#tutorial-end-button{
|
||||
font-size: 22pt;
|
||||
}
|
||||
@keyframes bgscroll{
|
||||
from{
|
||||
background-position: 0 0;
|
||||
}
|
||||
to{
|
||||
background-position: -30vmin 0;
|
||||
}
|
||||
}
|
||||
#song-select{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url("/assets/img/bg-pattern-1.png");
|
||||
background-size: 30vmin;
|
||||
animation: bgscroll 8s infinite linear;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#song-sel-canvas{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
@ -46,7 +46,8 @@
|
||||
left:23%;
|
||||
}
|
||||
|
||||
.scoresheet button:hover{
|
||||
.scoresheet button:hover,
|
||||
.scoresheet .bottom-part:not(:hover) button.selected{
|
||||
border-color:#fa5d3a;
|
||||
color:white;
|
||||
background:#0c6577;
|
||||
|
@ -1,167 +0,0 @@
|
||||
@keyframes bgscroll{
|
||||
from{
|
||||
background-position: 0 0;
|
||||
}
|
||||
to{
|
||||
background-position: -30vmin 0;
|
||||
}
|
||||
}
|
||||
#song-select{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url("/assets/img/bg-pattern-1.png");
|
||||
background-size: 30vmin;
|
||||
animation: bgscroll 8s infinite linear;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#song-container{
|
||||
width: 98%;
|
||||
height: 80%;
|
||||
padding: 5% 1% 1% 1%;
|
||||
text-align: center;
|
||||
}
|
||||
ul li{
|
||||
list-style: none;
|
||||
}
|
||||
.difficulties{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 303px;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
transition: opacity 0.1s;
|
||||
}
|
||||
.song.opened .difficulties{
|
||||
opacity: 1;
|
||||
transition: opacity 0.1s 0.2s;
|
||||
}
|
||||
.song-title-char{
|
||||
text-align: center;
|
||||
width: 45px;
|
||||
display: block;
|
||||
}
|
||||
.song-title-char::before{
|
||||
content: attr(alt);
|
||||
position: absolute;
|
||||
-webkit-text-stroke: 0.25em #000;
|
||||
z-index: -1;
|
||||
}
|
||||
.song-title{
|
||||
float: right;
|
||||
width: 45px;
|
||||
height: 100%;
|
||||
padding: 10px 2px;
|
||||
word-wrap: break-word;
|
||||
font-size: 22pt;
|
||||
color: white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
line-height: 28px;
|
||||
}
|
||||
.song-title-space{
|
||||
line-height: 25px;
|
||||
}
|
||||
.song{
|
||||
font-size: 14pt;
|
||||
width: 50px;
|
||||
margin-right: 15px;
|
||||
height: 100%;
|
||||
color: black;
|
||||
display: inline-block;
|
||||
background: rgba(255, 220, 47, 0.90);
|
||||
border: 7px outset #f4ae00;
|
||||
box-shadow: 2px 2px 10px black;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
.song:not(.opened):hover{
|
||||
background: rgba(255, 233, 125, 0.90);
|
||||
}
|
||||
.opened{
|
||||
width: 375px;
|
||||
}
|
||||
.difficulty{
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
width: 35px;
|
||||
height: 70%;
|
||||
border-radius: 5px;
|
||||
display: inline-block;
|
||||
margin: 5px;
|
||||
float: left;
|
||||
background: white;
|
||||
border: 10px solid #ae7a26;
|
||||
position: relative;
|
||||
}
|
||||
.difficulty .diffname{
|
||||
word-wrap: break-word;
|
||||
width: 20px;
|
||||
display: block;
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
font-size: 20pt;
|
||||
margin-left: 6px;
|
||||
white-space: normal;
|
||||
}
|
||||
.difficulty .stars{
|
||||
position: absolute;
|
||||
color: #f12b69;
|
||||
margin-left: -17px;
|
||||
width: 100%;
|
||||
bottom: 10px;
|
||||
}
|
||||
.difficulty:hover{
|
||||
border-color: #fa5d3a;
|
||||
color: white;
|
||||
background: #0c6577;
|
||||
}
|
||||
.difficulty:hover .diffname{
|
||||
-webkit-text-stroke-width: 1px;
|
||||
-webkit-text-stroke-color: black;
|
||||
}
|
||||
.difficulty:hover .stars{
|
||||
color: white;
|
||||
}
|
||||
.song.p2:not(.opened)::after,
|
||||
.difficulty.p2::after{
|
||||
content: "P2";
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
#songsel-help{
|
||||
float: right;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
color: black;
|
||||
padding: 15px;
|
||||
margin: 10px;
|
||||
font-size: 18px;
|
||||
border: 3px black solid;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.songsel-title-song,
|
||||
.songsel-title-difficulty{
|
||||
position: absolute;
|
||||
left: -300px;
|
||||
opacity: 0;
|
||||
margin: 20px;
|
||||
color: #fff;
|
||||
font-size: 7vmin;
|
||||
z-index: 1;
|
||||
transition: left 0s 0.2s, opacity 0.2s;
|
||||
}
|
||||
#song-select.difficulty-select .songsel-title-difficulty{
|
||||
left: 0;
|
||||
opacity: 1;
|
||||
transition: left 0.4s 0.2s, opacity 0.4s 0.2s;
|
||||
}
|
||||
#song-select:not(.difficulty-select) .songsel-title-song{
|
||||
left: 0;
|
||||
opacity: 1;
|
||||
transition: left 0.4s 0.2s, opacity 0.4s 0.2s;
|
||||
}
|
@ -32,7 +32,6 @@ var assets = {
|
||||
"don_anim_gogo.png",
|
||||
"don_anim_gogostart.png",
|
||||
"don_anim_clear.png",
|
||||
"don_anim_endclear.png",
|
||||
"fire_anim.png",
|
||||
"fireworks_anim.png"
|
||||
],
|
||||
|
@ -107,7 +107,6 @@ class Controller{
|
||||
this.view.togglePauseMenu()
|
||||
}
|
||||
gameEnded(){
|
||||
this.view.gameEnded()
|
||||
var score = this.getGlobalScore()
|
||||
var vp
|
||||
if(score.fail === 0){
|
||||
|
@ -351,8 +351,12 @@ class Game{
|
||||
}
|
||||
}
|
||||
getAccurateTime(){
|
||||
var currentDate = new Date()
|
||||
return currentDate.getTime() - this.startDate.getTime() - this.elapsedTimeSincePause
|
||||
if(this.isPaused()){
|
||||
return this.getElapsedTime().ms
|
||||
}else{
|
||||
var currentDate = new Date()
|
||||
return currentDate.getTime() - this.startDate.getTime() - this.elapsedTimeSincePause
|
||||
}
|
||||
}
|
||||
getCircles(){
|
||||
return this.songData.circles
|
||||
|
@ -1,16 +1,6 @@
|
||||
class Gamepad{
|
||||
constructor(keyboard){
|
||||
this.keyboard = keyboard
|
||||
this.game = this.keyboard.controller.game
|
||||
|
||||
var kbd = keyboard.getBindings()
|
||||
this.gameBtn = {}
|
||||
this.gameBtn[kbd["don_l"]] = ["u", "d", "l", "r"]
|
||||
this.gameBtn[kbd["don_r"]] = ["a", "b", "x", "y"]
|
||||
this.gameBtn[kbd["ka_l"]] = ["lb", "lt"]
|
||||
this.gameBtn[kbd["ka_r"]] = ["rb", "rt"]
|
||||
this.menuBtn = {}
|
||||
this.menuBtn[kbd["pause"]] = ["start"]
|
||||
constructor(bindings, callback){
|
||||
this.bindings = bindings
|
||||
this.b = {
|
||||
"a": 0,
|
||||
"b": 1,
|
||||
@ -31,15 +21,19 @@ class Gamepad{
|
||||
"guide": 16
|
||||
}
|
||||
this.btn = {}
|
||||
if(callback){
|
||||
this.interval = setInterval(() => {
|
||||
this.play(callback)
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
play(menuPlay){
|
||||
var ms = this.game.getAccurateTime()
|
||||
play(callback){
|
||||
if("getGamepads" in navigator){
|
||||
var gamepads = navigator.getGamepads()
|
||||
}else{
|
||||
return
|
||||
}
|
||||
var bindings = menuPlay ? this.menuBtn : this.gameBtn
|
||||
var bindings = this.bindings
|
||||
for(var i = 0; i < gamepads.length; i++){
|
||||
if(gamepads[i]){
|
||||
this.toRelease = {}
|
||||
@ -51,7 +45,7 @@ class Gamepad{
|
||||
for(var bind in bindings){
|
||||
for(var name in bindings[bind]){
|
||||
if(btnName === this.b[bindings[bind][name]]){
|
||||
this.checkButton(gamepads, btnName, bind, ms)
|
||||
this.checkButton(gamepads, btnName, bind, callback)
|
||||
break buttonSearch
|
||||
}
|
||||
}
|
||||
@ -62,7 +56,7 @@ class Gamepad{
|
||||
}
|
||||
}
|
||||
}
|
||||
checkButton(gamepads, btnName, keyCode, ms){
|
||||
checkButton(gamepads, btnName, keyCode, callback){
|
||||
var button = false
|
||||
|
||||
for(var i = 0; i < gamepads.length; i++){
|
||||
@ -77,7 +71,6 @@ class Gamepad{
|
||||
}
|
||||
}
|
||||
|
||||
var keys = this.keyboard.getKeys()
|
||||
var pressed = !this.btn[btnName] && button
|
||||
var released = this.btn[btnName] && !button
|
||||
|
||||
@ -88,19 +81,18 @@ class Gamepad{
|
||||
}
|
||||
|
||||
if(pressed){
|
||||
if(keys[keyCode]){
|
||||
this.keyboard.setKey(keyCode, false)
|
||||
}
|
||||
this.keyboard.setKey(keyCode, true, ms)
|
||||
|
||||
}else if(!button && keys[keyCode]){
|
||||
callback(true, keyCode)
|
||||
}else if(!button){
|
||||
if(released){
|
||||
this.toRelease[keyCode + "released"] = true
|
||||
}
|
||||
this.toRelease[keyCode]--
|
||||
if(this.toRelease[keyCode] === 0 && this.toRelease[keyCode + "released"]){
|
||||
this.keyboard.setKey(keyCode, false)
|
||||
callback(false, keyCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
clean(){
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,10 @@ class Keyboard{
|
||||
"ka_l": 67, // C
|
||||
"ka_r": 78, // N
|
||||
"pause": 81, // Q
|
||||
"back": 8 // Backspace
|
||||
"back": 8, // Backspace
|
||||
"previous": 38, // Up
|
||||
"next": 40, // Down
|
||||
"confirm": 13 // Enter
|
||||
}
|
||||
this.keys = {}
|
||||
this.waitKeyupScore = {}
|
||||
@ -19,7 +22,24 @@ class Keyboard{
|
||||
"don": -Infinity,
|
||||
"ka": -Infinity
|
||||
}
|
||||
this.gamepad = new Gamepad(this)
|
||||
|
||||
var gameBtn = {}
|
||||
gameBtn[this.kbd["don_l"]] = ["u", "d", "l", "r"]
|
||||
gameBtn[this.kbd["don_r"]] = ["a", "b", "x", "y"]
|
||||
gameBtn[this.kbd["ka_l"]] = ["lb", "lt"]
|
||||
gameBtn[this.kbd["ka_r"]] = ["rb", "rt"]
|
||||
this.gamepad = new Gamepad(gameBtn)
|
||||
|
||||
var menuBtn = {
|
||||
"cancel": ["a"],
|
||||
}
|
||||
menuBtn[this.kbd["confirm"]] = ["b"]
|
||||
menuBtn[this.kbd["previous"]] = ["u", "l", "lb", "lt"],
|
||||
menuBtn[this.kbd["next"]] = ["d", "r", "rb", "rt"]
|
||||
menuBtn[this.kbd["pause"]] = ["start"]
|
||||
this.gamepadMenu = new Gamepad(menuBtn)
|
||||
|
||||
|
||||
pageEvents.keyAdd(this, "all", "both", event => {
|
||||
if(event.keyCode === 8){
|
||||
// Disable back navigation when pressing backspace
|
||||
@ -48,7 +68,17 @@ class Keyboard{
|
||||
}
|
||||
checkGameKeys(){
|
||||
if(!this.controller.autoPlayEnabled){
|
||||
this.gamepad.play()
|
||||
var ms = this.game.getAccurateTime()
|
||||
this.gamepad.play((pressed, keyCode) => {
|
||||
if(pressed){
|
||||
if(this.keys[keyCode]){
|
||||
this.setKey(keyCode, false)
|
||||
}
|
||||
this.setKey(keyCode, true, ms)
|
||||
}else{
|
||||
this.setKey(keyCode, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
this.checkKeySound(this.kbd["don_l"], "don")
|
||||
this.checkKeySound(this.kbd["don_r"], "don")
|
||||
@ -57,10 +87,68 @@ class Keyboard{
|
||||
}
|
||||
checkMenuKeys(){
|
||||
if(!this.controller.multiplayer){
|
||||
this.gamepad.play(true)
|
||||
var moveMenu = 0
|
||||
var ms = this.game.getAccurateTime()
|
||||
this.gamepadMenu.play((pressed, keyCode) => {
|
||||
if(pressed){
|
||||
if(this.game.isPaused()){
|
||||
if(keyCode === "cancel"){
|
||||
return setTimeout(() => {
|
||||
this.controller.togglePauseMenu()
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
if(this.keys[keyCode]){
|
||||
this.setKey(keyCode, false)
|
||||
}
|
||||
this.setKey(keyCode, true, ms)
|
||||
}else{
|
||||
this.setKey(keyCode, false)
|
||||
}
|
||||
})
|
||||
this.checkKey(this.kbd["pause"], "menu", () => {
|
||||
this.controller.togglePauseMenu()
|
||||
for(var key in this.keyTime){
|
||||
this.keys[key] = null
|
||||
this.keyTime[key] = null
|
||||
}
|
||||
})
|
||||
var moveMenuMinus = () => {
|
||||
moveMenu = -1
|
||||
}
|
||||
var moveMenuPlus = () => {
|
||||
moveMenu = 1
|
||||
}
|
||||
var moveMenuConfirm = () => {
|
||||
if(this.game.isPaused()){
|
||||
setTimeout(() => {
|
||||
var selected = document.getElementsByClassName("selected")[0]
|
||||
if(selected){
|
||||
selected.click()
|
||||
}
|
||||
}, 200)
|
||||
for(var key in this.keyTime){
|
||||
this.keyTime[key] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
this.checkKey(this.kbd["previous"], "menu", moveMenuMinus)
|
||||
this.checkKey(this.kbd["ka_l"], "menu", moveMenuMinus)
|
||||
this.checkKey(this.kbd["next"], "menu", moveMenuPlus)
|
||||
this.checkKey(this.kbd["ka_r"], "menu", moveMenuPlus)
|
||||
this.checkKey(this.kbd["confirm"], "menu", moveMenuConfirm)
|
||||
this.checkKey(this.kbd["don_l"], "menu", moveMenuConfirm)
|
||||
this.checkKey(this.kbd["don_r"], "menu", moveMenuConfirm)
|
||||
if(moveMenu && this.game.isPaused()){
|
||||
assets.sounds["ka"].play()
|
||||
var selected = document.getElementsByClassName("selected")[0]
|
||||
selected.classList.remove("selected")
|
||||
var next = selected[(moveMenu === 1 ? "next" : "previous") + "ElementSibling"]
|
||||
if(!next){
|
||||
next = selected.parentNode[(moveMenu === 1 ? "first" : "last") + "ElementChild"]
|
||||
}
|
||||
next.classList.add("selected")
|
||||
}
|
||||
}
|
||||
if(this.controller.multiplayer !== 2){
|
||||
this.checkKey(this.kbd["back"], "menu", () => {
|
||||
|
@ -81,7 +81,9 @@ class Scoresheet{
|
||||
this.setResults(this.score, scoreCont)
|
||||
this.altText(this.elem("result-song", this.scoresheet), this.score.song)
|
||||
|
||||
pageEvents.once(this.elem("song-select", this.scoresheet), "click").then(() => {
|
||||
this.songSelect = this.elem("song-select", this.scoresheet)
|
||||
this.replay = this.elem("replay", this.scoresheet)
|
||||
pageEvents.once(this.songSelect, "click").then(() => {
|
||||
this.clean()
|
||||
assets.sounds["don"].play()
|
||||
this.controller.songSelection()
|
||||
@ -91,6 +93,16 @@ class Scoresheet{
|
||||
assets.sounds["don"].play()
|
||||
this.controller.restartSong()
|
||||
})
|
||||
pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this))
|
||||
this.gamepad = new Gamepad({
|
||||
"13": ["b", "start"],
|
||||
"37": ["l", "r", "lb", "lt", "rb", "rt"]
|
||||
}, (pressed, key) => {
|
||||
if(pressed){
|
||||
this.keyDown(false, key)
|
||||
}
|
||||
})
|
||||
|
||||
if(this.multiplayer && p2.results){
|
||||
var scoreCont2 = document.createElement("div")
|
||||
scoreCont2.classList.add("score-cont")
|
||||
@ -99,8 +111,27 @@ class Scoresheet{
|
||||
this.setResults(p2.results, scoreCont2)
|
||||
}
|
||||
}
|
||||
keyDown(event, code){
|
||||
if(!code){
|
||||
code = event.keyCode
|
||||
}
|
||||
var selected = this.elem("selected", this.scoresheet)
|
||||
if(code == 13 || code == 32 || code == 86 || code == 66){
|
||||
// Enter, Space, V, B
|
||||
selected.click()
|
||||
}else if(code == 37 || code == 39 || code == 67 || code == 78){
|
||||
// Left, Right, C, N
|
||||
selected.classList.remove("selected")
|
||||
var next = selected.nextElementSibling
|
||||
if(!next){
|
||||
next = selected.previousElementSibling
|
||||
}
|
||||
next.classList.add("selected")
|
||||
}
|
||||
}
|
||||
clean(){
|
||||
assets.sounds["bgm_result"].stop()
|
||||
pageEvents.keyRemove(this, "all")
|
||||
pageEvents.remove(window, "resize")
|
||||
}
|
||||
}
|
||||
|
@ -1,206 +1,1554 @@
|
||||
class SongSelect{
|
||||
constructor(){
|
||||
this.songs
|
||||
this.selectedSong = {
|
||||
"title": "",
|
||||
"folder": "",
|
||||
"difficulty": ""
|
||||
}
|
||||
this.previewId = 0
|
||||
this.diffNames={
|
||||
"easy": "かんたん",
|
||||
"normal": "ふつう",
|
||||
"hard": "むずかしい",
|
||||
"oni": "おに"
|
||||
}
|
||||
constructor(fromTutorial){
|
||||
loader.changePage("songselect")
|
||||
this.run()
|
||||
}
|
||||
startPreview(id, prvtime, switchedTo){
|
||||
this.endPreview()
|
||||
var startLoad = +new Date
|
||||
var currentId = this.previewId
|
||||
if(!switchedTo){
|
||||
snd.musicGain.fadeOut(0.4)
|
||||
this.canvas = document.getElementById("song-sel-canvas")
|
||||
this.ctx = this.canvas.getContext("2d")
|
||||
|
||||
this.songSkin = {
|
||||
"selected": {
|
||||
background: "#ffdb2c",
|
||||
border: ["#fff4b5", "#ffa600"],
|
||||
outline: "#000"
|
||||
},
|
||||
"back": {
|
||||
background: "#efb058",
|
||||
border: ["#ffe7bd", "#c68229"],
|
||||
outline: "#ad7723"
|
||||
},
|
||||
"random": {
|
||||
background: "#fa91ff",
|
||||
border: ["#ffdfff", "#b068b2"],
|
||||
outline: "#b221bb"
|
||||
},
|
||||
"tutorial": {
|
||||
background: "#9afbe1",
|
||||
border: ["#d6ffff", "#6bae9c"],
|
||||
outline: "#31ae94"
|
||||
},
|
||||
"J-POP": {
|
||||
sort: 0,
|
||||
background: "#219fbb",
|
||||
border: ["#7ec3d3", "#0b6773"],
|
||||
outline: "#005058"
|
||||
},
|
||||
"アニメ": {
|
||||
sort: 1,
|
||||
background: "#ff9700",
|
||||
border: ["#ffdb8c", "#e75500"],
|
||||
outline: "#9c4100"
|
||||
},
|
||||
"ボーカロイド": {
|
||||
sort: 2,
|
||||
background: "#def2ef",
|
||||
border: ["#f7fbff", "#79919f"],
|
||||
outline: "#5a6584"
|
||||
},
|
||||
"バラエティ": {
|
||||
sort: 3,
|
||||
background: "#8fd321",
|
||||
border: ["#f7fbff", "#587d0b"],
|
||||
outline: "#374c00"
|
||||
},
|
||||
"クラシック": {
|
||||
sort: 4,
|
||||
background: "#d1a016",
|
||||
border: ["#e7cf6b", "#9a6b00"],
|
||||
outline: "#734d00"
|
||||
},
|
||||
"ゲームミュージック": {
|
||||
sort: 5,
|
||||
background: "#9c72c0",
|
||||
border: ["#bda2ce", "#63407e"],
|
||||
outline: "#4b1c74"
|
||||
},
|
||||
"ナムコオリジナル": {
|
||||
sort: 6,
|
||||
background: "#ff5716",
|
||||
border: ["#ffa66b", "#b53000"],
|
||||
outline: "#9c2000"
|
||||
},
|
||||
"default": {
|
||||
sort: 7,
|
||||
background: "#ececec",
|
||||
border: ["#fbfbfb", "#8b8b8b"],
|
||||
outline: "#656565"
|
||||
}
|
||||
}
|
||||
var songObj = assets.songs.find(song => song.id == id)
|
||||
if(songObj.sound){
|
||||
this.preview = songObj.sound
|
||||
this.preview.gain = snd.previewGain
|
||||
this.previewLoaded(startLoad, prvtime, switchedTo)
|
||||
this.font = "TnT"
|
||||
|
||||
this.songs = []
|
||||
for(let song of assets.songs){
|
||||
this.songs.push({
|
||||
id: song.id,
|
||||
title: song.title,
|
||||
skin: this.songSkin[song.category || "default"],
|
||||
stars: song.stars,
|
||||
category: song.category,
|
||||
preview: song.preview || 0
|
||||
})
|
||||
}
|
||||
this.songs.sort((a, b) => {
|
||||
var sortA = this.songSkin[a.category || "default"].sort
|
||||
var sortB = this.songSkin[b.category || "default"].sort
|
||||
if(sortA === sortB){
|
||||
return a.id > b.id ? 1 : -1
|
||||
}else{
|
||||
return sortA > sortB ? 1 : -1
|
||||
}
|
||||
})
|
||||
this.songs.push({
|
||||
title: "もどる",
|
||||
skin: this.songSkin.back,
|
||||
action: "back"
|
||||
})
|
||||
this.songs.push({
|
||||
title: "ランダムに曲をえらぶ",
|
||||
skin: this.songSkin.random,
|
||||
action: "random"
|
||||
})
|
||||
this.songs.push({
|
||||
title: "あそびかた説明",
|
||||
skin: this.songSkin.tutorial,
|
||||
action: "tutorial"
|
||||
})
|
||||
this.songs.push({
|
||||
title: "もどる",
|
||||
skin: this.songSkin.back,
|
||||
action: "back"
|
||||
})
|
||||
|
||||
this.songAsset = {
|
||||
marginTop: 90,
|
||||
marginLeft: 18,
|
||||
width: 82,
|
||||
selectedWidth: 382,
|
||||
height: 452,
|
||||
border: 6,
|
||||
innerBorder: 8,
|
||||
letterBorder: 12
|
||||
}
|
||||
this.diffStar = new Path2D("M3 17 5 11 0 6h6l3-6 3 6h6l-5 5 2 6-6-3")
|
||||
this.longVowelMark = new Path2D("m1 5c2 3 1 17 .5 25 0 5 6 5 6.5 0C9 22 9 6 7 3 4-2-1 2 1 5")
|
||||
|
||||
this.diffIconPath = [[{w: 40, h: 33}, {
|
||||
fill: "#ff2803",
|
||||
d: new Path2D("m27 10c9-9 21 9 5 11 10 9-6 18-12 7C14 39-2 30 8 21-8 19 4 1 13 10 6-4 34-3 27 10Z")
|
||||
}, {
|
||||
fill: "#ffb910",
|
||||
noStroke: true,
|
||||
d: new Path2D("m12 15c5 1 7 0 8-4 1 4 3 5 8 4-4 3-4 5-2 8-4-4-8-4-12 0 2.2-3 2-5-2-8")
|
||||
}], [{w: 48, h: 31}, {
|
||||
fill: "#8daf51",
|
||||
d: new Path2D("m24 0c-3 0-4 3-5 6-2 6-2 11 0 17 0 0 1 4 5 8 4-4 5-8 5-8C31 17 31 12 29 6 28 3 27 0 24 0M37 2c4 3 7 6 8 8 2 4 3 6 2 13C43 21 39 18 39 18 35 15 32 12 30 8 27 0 32-2 37 2M11 2C7 5 4 8 3 10 1 14 0 16 1 23 5 21 9 18 9 18 13 15 16 12 18 8 21 0 16-2 11 2")
|
||||
}], [{w: 56, h: 37}, {
|
||||
fill: "#784439",
|
||||
d: new Path2D("m26 34v-2c-10 1-12 0-12-7 4-3 8-5 14-5 6 0 10 2 14 5 0 7-2 8-12 7V34Z")
|
||||
}, {
|
||||
fill: "#000",
|
||||
noStroke: true,
|
||||
d: new Path2D("m18 19v9h8v-9m4 9h8v-9h-8")
|
||||
}, {
|
||||
fill: "#414b2b",
|
||||
d: new Path2D("M8 26C3 26-3 21 2 11 6 5 11 4 18 10c0-6 4-10 10-10 6 0 10 4 10 10 7-6 12-5 16 1 5 10-1 15-6 15-5 0-10-7-20-7-10 0-15 7-20 7")
|
||||
}], [{w: 29, h: 27}, {
|
||||
fill: "#db1885",
|
||||
d: new Path2D("m18 9c1 3 4 4 7 3 0 4 1 11 4 16H0c3-5 4-12 4-16 3 1 6 0 7-3z")
|
||||
}, {
|
||||
fill: "#fff",
|
||||
d: new Path2D("m6 0.5-2 11c4 1.5 6-0.5 6.5-3zm17 0-4.5 8C19 11 21 13 25 11.5ZM5.5 17.5C4.5 23.5 9 25 11 22Zm18 0L18 22c2 3 6.5 1.5 5.5-4.5z")
|
||||
}]]
|
||||
this.regex = {
|
||||
comma: /[,.]/,
|
||||
ideographicComma: /[、。]/,
|
||||
apostrophe: /['']/,
|
||||
brackets: /[\((\))「」『』]/,
|
||||
tilde: /[\--~~]/,
|
||||
tall: /[bbddffh-lh-ltt0-90-9]/,
|
||||
uppercase: /[A-ZA-Z!!]/,
|
||||
lowercase: /[a-za-z・]/,
|
||||
latin: /[A-ZA-Z!!a-za-z・]/,
|
||||
smallHiragana: /[ぁぃぅぇぉっゃゅょァィゥェォッャュョ]/,
|
||||
hiragana: /[\u3040-\u30ff]/,
|
||||
todo: /[トド]/
|
||||
}
|
||||
|
||||
this.difficulty = ["かんたん", "ふつう", "むずかしい", "おに"]
|
||||
this.difficultyId = ["easy", "normal", "hard", "oni"]
|
||||
|
||||
this.selectedSong = 0
|
||||
this.selectedDiff = 0
|
||||
assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506)
|
||||
|
||||
if(fromTutorial || !"selectedSong" in localStorage){
|
||||
this.selectedSong = this.songs.findIndex(song => song.action === "tutorial")
|
||||
this.playBgm(true)
|
||||
}else{
|
||||
snd.previewGain.load("/songs/" + id + "/main.mp3").then(sound => {
|
||||
if(currentId == this.previewId){
|
||||
songObj.sound = sound
|
||||
this.preview = sound
|
||||
this.previewLoaded(startLoad, prvtime, switchedTo)
|
||||
if("selectedSong" in localStorage){
|
||||
this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length)
|
||||
}
|
||||
assets.sounds["song-select"].play()
|
||||
snd.musicGain.fadeOut()
|
||||
this.playBgm(false)
|
||||
}
|
||||
if("selectedDiff" in localStorage){
|
||||
this.selectedDiff = Math.min(Math.max(0, localStorage["selectedDiff"] |0), 4)
|
||||
}
|
||||
|
||||
this.previewId = 0
|
||||
this.state = {
|
||||
screen: fromTutorial ? "song" : "title",
|
||||
screenMS: this.getMS(),
|
||||
move: 0,
|
||||
moveMS: 0,
|
||||
moveHover: null,
|
||||
locked: true
|
||||
}
|
||||
this.songSelecting = {
|
||||
speed: 800,
|
||||
resize: 0.3,
|
||||
scrollDelay: 0.1
|
||||
}
|
||||
|
||||
this.startPreview(true)
|
||||
|
||||
this.pressedKeys = {}
|
||||
this.gamepad = new Gamepad({
|
||||
"13": ["b", "start"],
|
||||
"8": ["a"],
|
||||
"37": ["l", "lb", "lt"],
|
||||
"39": ["r", "rb", "rt"],
|
||||
"ctrl": ["y"],
|
||||
"shift": ["x"]
|
||||
})
|
||||
|
||||
this.startP2()
|
||||
this.redrawRunning = true
|
||||
this.redrawBind = this.redraw.bind(this)
|
||||
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))
|
||||
}
|
||||
|
||||
keyDown(event, code){
|
||||
if(code){
|
||||
var modifiers = {
|
||||
shift: this.pressedKeys["shift"],
|
||||
ctrl: this.pressedKeys["ctrl"]
|
||||
}
|
||||
}else{
|
||||
code = event.keyCode
|
||||
var modifiers = {
|
||||
shift: event.shiftKey,
|
||||
ctrl: event.ctrlKey
|
||||
}
|
||||
}
|
||||
if(code === "ctrl" && code === "shift"){
|
||||
return
|
||||
}
|
||||
var key = {
|
||||
confirm: code == 13 || code == 32 || code == 86 || code == 66,
|
||||
// Enter, Space, V, B
|
||||
cancel: code == 27 || code == 8,
|
||||
// Esc, Backspace
|
||||
left: code == 37 || code == 67,
|
||||
// Left, C
|
||||
right: code == 39 || code == 78
|
||||
// Right, N
|
||||
}
|
||||
if(key.cancel && event){
|
||||
event.preventDefault()
|
||||
}
|
||||
if(this.state.screen === "song"){
|
||||
if(key.confirm){
|
||||
this.toSelectDifficulty()
|
||||
}else if(key.cancel){
|
||||
this.toTitleScreen()
|
||||
}else if(key.left){
|
||||
this.moveToSong(-1)
|
||||
}else if(key.right){
|
||||
this.moveToSong(1)
|
||||
}
|
||||
}else if(this.state.screen === "difficulty"){
|
||||
if(key.confirm){
|
||||
if(this.selectedDiff === 0){
|
||||
this.toSongSelect()
|
||||
}else{
|
||||
this.toLoadSong(this.selectedDiff - 1, modifiers.shift, modifiers.ctrl)
|
||||
}
|
||||
}else if(key.cancel){
|
||||
this.toSongSelect()
|
||||
}else if(key.left){
|
||||
this.moveToDiff(-1)
|
||||
}else if(key.right){
|
||||
this.moveToDiff(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mouseDown(event){
|
||||
if(event.which !== 1){
|
||||
return
|
||||
}
|
||||
var mouse = this.mouseOffset(event)
|
||||
if(this.state.screen === "song"){
|
||||
var moveBy = this.songSelMouse(mouse.x, mouse.y)
|
||||
if(moveBy === 0){
|
||||
this.toSelectDifficulty()
|
||||
}else if(moveBy !== null){
|
||||
this.moveToSong(moveBy)
|
||||
}
|
||||
}else if(this.state.screen === "difficulty"){
|
||||
var moveBy = this.diffSelMouse(mouse.x, mouse.y)
|
||||
if(
|
||||
moveBy === 0
|
||||
|| mouse.x < 55 || mouse.x > 967
|
||||
|| mouse.y < 40 || mouse.y > 540
|
||||
){
|
||||
this.toSongSelect()
|
||||
}else if(moveBy !== null){
|
||||
this.toLoadSong(moveBy - 1, event.shiftKey, event.ctrlKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
mouseMove(event){
|
||||
var mouse = this.mouseOffset(event)
|
||||
if(this.state.screen === "song"){
|
||||
var moveTo = this.songSelMouse(mouse.x, mouse.y)
|
||||
if(moveTo === null && this.state.moveHover === 0 && !this.songs[this.selectedSong].stars){
|
||||
this.state.moveMS = this.getMS() - this.songSelecting.speed
|
||||
}
|
||||
this.state.moveHover = moveTo
|
||||
}else if(this.state.screen === "difficulty"){
|
||||
var moveTo = this.diffSelMouse(mouse.x, mouse.y)
|
||||
if(moveTo === null && this.state.moveHover === this.selectedDiff){
|
||||
this.state.moveMS = this.getMS() - 1000
|
||||
}
|
||||
this.state.moveHover = moveTo
|
||||
}
|
||||
}
|
||||
mouseOffset(event){
|
||||
return {
|
||||
x: (event.offsetX * this.pixelRatio - this.winW / 2) / this.ratio + 1024 / 2,
|
||||
y: (event.offsetY * this.pixelRatio - this.winH / 2) / this.ratio + 720 / 2
|
||||
}
|
||||
}
|
||||
|
||||
songSelMouse(x, y){
|
||||
if(this.state.locked === 0 && this.songAsset.marginTop <= y && y <= this.songAsset.marginTop + this.songAsset.height){
|
||||
x -= 1024 / 2
|
||||
var dir = x > 0 ? 1 : -1
|
||||
x = Math.abs(x)
|
||||
var selectedWidth = this.songAsset.selectedWidth
|
||||
if(!this.songs[this.selectedSong].stars){
|
||||
selectedWidth = this.songAsset.width
|
||||
}
|
||||
var moveBy = Math.ceil((x - selectedWidth / 2 - this.songAsset.marginLeft / 2) / (this.songAsset.width + this.songAsset.marginLeft)) * dir
|
||||
if(moveBy / dir > 0){
|
||||
return moveBy
|
||||
}else{
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
diffSelMouse(x, y){
|
||||
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
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
if(currentSong.stars[moveBy - 1]){
|
||||
return moveBy
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
moveToSong(moveBy){
|
||||
if(this.state.locked !== 1){
|
||||
var ms = this.getMS()
|
||||
if(this.songs[this.selectedSong].stars && this.state.locked === 0){
|
||||
this.state.moveMS = ms
|
||||
}else{
|
||||
this.state.moveMS = ms - this.songSelecting.speed * this.songSelecting.resize
|
||||
}
|
||||
this.state.move = moveBy
|
||||
this.state.lastMove = moveBy
|
||||
this.state.locked = 1
|
||||
this.state.moveHover = null
|
||||
|
||||
var lastMoveMul = Math.pow(Math.abs(moveBy), 1 / 4)
|
||||
var changeSpeed = this.songSelecting.speed * lastMoveMul
|
||||
var resize = changeSpeed * this.songSelecting.resize / lastMoveMul
|
||||
var scrollDelay = changeSpeed * this.songSelecting.scrollDelay
|
||||
var resize2 = changeSpeed - resize
|
||||
var scroll = resize2 - resize - scrollDelay * 2
|
||||
|
||||
var soundsDelay = Math.abs((scroll + resize) / moveBy)
|
||||
|
||||
for(var i = 0; i < Math.abs(moveBy) - 1; i++){
|
||||
assets.sounds["ka"].play((resize + i * soundsDelay) / 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
moveToDiff(moveBy){
|
||||
if(this.state.locked !== 1){
|
||||
this.state.move = moveBy
|
||||
this.state.moveMS = this.getMS() - 500
|
||||
this.state.locked = 1
|
||||
assets.sounds["ka"].play()
|
||||
}
|
||||
}
|
||||
toSelectDifficulty(){
|
||||
if(this.state.locked === 0){
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
if(currentSong.stars){
|
||||
this.state.screen = "difficulty"
|
||||
this.state.screenMS = this.getMS()
|
||||
this.state.locked = true
|
||||
this.state.moveHover = null
|
||||
|
||||
assets.sounds["don"].play()
|
||||
assets.sounds["song-select"].stop()
|
||||
assets.sounds["diffsel"].play(0.3)
|
||||
}else if(currentSong.action === "back"){
|
||||
this.clean()
|
||||
this.toTitleScreen()
|
||||
}else if(currentSong.action === "random"){
|
||||
assets.sounds["don"].play()
|
||||
this.state.locked = true
|
||||
do{
|
||||
var i = Math.floor(Math.random() * this.songs.length)
|
||||
}while(!this.songs[i].stars)
|
||||
var moveBy = i - this.selectedSong
|
||||
setTimeout(() => {
|
||||
this.moveToSong(moveBy)
|
||||
}, 200)
|
||||
}else if(currentSong.action === "tutorial"){
|
||||
this.toTutorial()
|
||||
}
|
||||
}
|
||||
}
|
||||
toSongSelect(){
|
||||
if(this.state.locked !== 1){
|
||||
this.state.screen = "song"
|
||||
this.state.screenMS = this.getMS()
|
||||
this.state.locked = true
|
||||
this.state.moveHover = null
|
||||
|
||||
assets.sounds["diffsel"].stop()
|
||||
assets.sounds["cancel"].play()
|
||||
}
|
||||
}
|
||||
toLoadSong(difficulty, shift, ctrl){
|
||||
this.clean()
|
||||
var selectedSong = this.songs[this.selectedSong]
|
||||
assets.sounds["diffsel"].stop()
|
||||
assets.sounds["don"].play()
|
||||
|
||||
localStorage["selectedSong"] = this.selectedSong
|
||||
localStorage["selectedDiff"] = difficulty + 1
|
||||
|
||||
new loadSong({
|
||||
"title": selectedSong.title,
|
||||
"folder": selectedSong.id,
|
||||
"difficulty": this.difficultyId[difficulty]
|
||||
}, shift, ctrl)
|
||||
}
|
||||
toTitleScreen(){
|
||||
assets.sounds["cancel"].play()
|
||||
this.clean()
|
||||
setTimeout(() => {
|
||||
new Titlescreen()
|
||||
}, 500)
|
||||
}
|
||||
toTutorial(){
|
||||
assets.sounds["don"].play()
|
||||
this.clean()
|
||||
setTimeout(() => {
|
||||
new Tutorial(true)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
redraw(){
|
||||
if(!this.redrawRunning){
|
||||
return
|
||||
}
|
||||
requestAnimationFrame(this.redrawBind)
|
||||
var ms = this.getMS()
|
||||
|
||||
this.gamepad.play((pressed, keyCode) => {
|
||||
if(pressed){
|
||||
if(!this.pressedKeys[keyCode]){
|
||||
this.pressedKeys[keyCode] = ms + 300
|
||||
this.keyDown(false, keyCode)
|
||||
}
|
||||
}else{
|
||||
this.pressedKeys[keyCode] = 0
|
||||
}
|
||||
})
|
||||
for(var key in this.pressedKeys){
|
||||
if(this.pressedKeys[key]){
|
||||
if(ms >= this.pressedKeys[key] + 50){
|
||||
this.keyDown(false, key)
|
||||
this.pressedKeys[key] = ms
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.redrawRunning){
|
||||
return
|
||||
}
|
||||
|
||||
var ctx = this.ctx
|
||||
var winW = innerWidth
|
||||
var winH = innerHeight
|
||||
if(winW / 32 > winH / 9){
|
||||
winW = winH / 9 * 32
|
||||
}else if(winH / 9 > winW / 16){
|
||||
winH = winW / 16 * 9
|
||||
}
|
||||
this.pixelRatio = window.devicePixelRatio || 1
|
||||
winW *= this.pixelRatio
|
||||
winH *= this.pixelRatio
|
||||
var ratioX = winW / 1280
|
||||
var ratioY = winH / 720
|
||||
var ratio = (ratioX < ratioY ? ratioX : ratioY)
|
||||
if(this.winW !== winW || this.winH !== winH){
|
||||
this.canvas.width = winW
|
||||
this.canvas.height = winH
|
||||
ctx.scale(ratio, ratio)
|
||||
this.canvas.style.width = (winW / this.pixelRatio) + "px"
|
||||
this.canvas.style.height = (winH / this.pixelRatio) + "px"
|
||||
}else if(!document.hasFocus()){
|
||||
return
|
||||
}else{
|
||||
ctx.clearRect(0, 0, winW / ratio, winH / ratio)
|
||||
}
|
||||
this.winW = winW
|
||||
this.winH = winH
|
||||
this.ratio = ratio
|
||||
winW /= ratio
|
||||
winH /= ratio
|
||||
|
||||
var frameTop = winH / 2 - 720 / 2
|
||||
var frameLeft = winW / 2 - 1280 / 2
|
||||
var songTop = frameTop + this.songAsset.marginTop
|
||||
var xOffset = 0
|
||||
var songSelMoving = false
|
||||
var screen = this.state.screen
|
||||
var selectedWidth = this.songAsset.width
|
||||
|
||||
if(screen === "title"){
|
||||
if(ms > this.state.screenMS + 1000){
|
||||
this.state.screen = "song"
|
||||
this.state.screenMS = ms + (ms - this.state.screenMS - 1000)
|
||||
this.state.moveMS = ms - this.songSelecting.speed * this.songSelecting.resize + (ms - this.state.screenMS)
|
||||
this.state.locked = 3
|
||||
this.state.lastMove = 1
|
||||
}else{
|
||||
this.state.moveMS = ms - this.songSelecting.speed * this.songSelecting.resize + (ms - this.state.screenMS - 1000)
|
||||
}
|
||||
}
|
||||
|
||||
if(screen === "title" || screen === "song"){
|
||||
this.drawLayeredText({
|
||||
text: "曲をえらぶ",
|
||||
fontSize: 48,
|
||||
fontFamily: this.font,
|
||||
x: frameLeft + 53,
|
||||
y: frameTop + 30,
|
||||
letterSpacing: 2
|
||||
}, [
|
||||
{x: -2, y: -2, outline: "#000", letterBorder: 22},
|
||||
{},
|
||||
{x: 2, y: 2, shadow: true},
|
||||
{x: -2, y: -2, outline: "#ff797b", letterBorder: 10},
|
||||
{x: 2, y: 2, outline: "#ad1516"},
|
||||
{outline: "#f70808"},
|
||||
{fill: "#fff"}
|
||||
])
|
||||
|
||||
var category = this.songs[this.selectedSong].category
|
||||
if(category){
|
||||
this.drawLayeredText({
|
||||
text: category,
|
||||
fontSize: 40,
|
||||
fontFamily: this.font,
|
||||
x: winW / 2,
|
||||
y: frameTop + 38,
|
||||
width: 255,
|
||||
center: true
|
||||
}, [
|
||||
{outline: this.songs[this.selectedSong].skin.outline, letterBorder: 12, shadow: true},
|
||||
{fill: "#fff"}
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
if(screen === "song"){
|
||||
if(this.songs[this.selectedSong].stars){
|
||||
selectedWidth = this.songAsset.selectedWidth
|
||||
}
|
||||
|
||||
var lastMoveMul = Math.pow(Math.abs(this.state.lastMove), 1 / 4)
|
||||
var changeSpeed = this.songSelecting.speed * lastMoveMul
|
||||
var resize = changeSpeed * this.songSelecting.resize / lastMoveMul
|
||||
var scrollDelay = changeSpeed * this.songSelecting.scrollDelay
|
||||
var resize2 = changeSpeed - resize
|
||||
var scroll = resize2 - resize - scrollDelay * 2
|
||||
var elapsed = ms - this.state.moveMS
|
||||
if(this.state.move && ms > this.state.moveMS + resize2 - scrollDelay){
|
||||
assets.sounds["ka"].play()
|
||||
this.selectedSong = this.mod(this.songs.length, this.selectedSong + this.state.move)
|
||||
this.state.move = 0
|
||||
this.state.locked = 2
|
||||
}
|
||||
if(this.state.moveMS && ms < this.state.moveMS + changeSpeed){
|
||||
xOffset = Math.min(scroll, Math.max(0, elapsed - resize - scrollDelay)) / scroll * (this.songAsset.width + this.songAsset.marginLeft)
|
||||
xOffset *= -this.state.move
|
||||
if(elapsed < resize){
|
||||
selectedWidth = this.songAsset.width + (((resize - elapsed) / resize) * (selectedWidth - this.songAsset.width))
|
||||
}else if(elapsed > resize2){
|
||||
this.playBgm(!this.songs[this.selectedSong].stars)
|
||||
this.state.locked = 1
|
||||
selectedWidth = this.songAsset.width + ((elapsed - resize2) / resize * (selectedWidth - this.songAsset.width))
|
||||
}else{
|
||||
songSelMoving = true
|
||||
selectedWidth = this.songAsset.width
|
||||
}
|
||||
}else{
|
||||
this.state.locked = 0
|
||||
}
|
||||
}else if(screen === "difficulty"){
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
if(this.state.locked){
|
||||
this.state.locked = 0
|
||||
}
|
||||
if(this.state.move){
|
||||
do{
|
||||
this.selectedDiff = this.mod(5, this.selectedDiff + this.state.move)
|
||||
}while(this.selectedDiff !== 0 && !currentSong.stars[this.selectedDiff - 1])
|
||||
this.state.move = 0
|
||||
}else if(!currentSong.stars[this.selectedDiff - 1]){
|
||||
this.selectedDiff = 0
|
||||
}
|
||||
}
|
||||
|
||||
if(songSelMoving){
|
||||
if(this.previewing !== null){
|
||||
this.endPreview()
|
||||
}
|
||||
}else if(screen !== "title" && ms > this.state.moveMS + 100){
|
||||
if(this.previewing !== this.selectedSong && "id" in this.songs[this.selectedSong]){
|
||||
this.startPreview()
|
||||
}
|
||||
}
|
||||
|
||||
if(screen === "title" || screen === "song"){
|
||||
for(var i = this.selectedSong - 1; ; i--){
|
||||
var highlight = 0
|
||||
if(i - this.selectedSong === this.state.moveHover){
|
||||
highlight = 1
|
||||
}
|
||||
var index = this.mod(this.songs.length, i)
|
||||
var _x = winW / 2 - (this.selectedSong - i) * (this.songAsset.width + this.songAsset.marginLeft) - selectedWidth / 2 + xOffset
|
||||
if(_x + this.songAsset.width + this.songAsset.marginLeft < 0){
|
||||
break
|
||||
}
|
||||
this.drawClosedSong({
|
||||
x: _x,
|
||||
y: songTop,
|
||||
song: this.songs[index],
|
||||
highlight: highlight
|
||||
})
|
||||
}
|
||||
for(var i = this.selectedSong + 1; ; i++){
|
||||
var highlight = 0
|
||||
if(i - this.selectedSong === this.state.moveHover){
|
||||
highlight = 1
|
||||
}
|
||||
var index = this.mod(this.songs.length, i)
|
||||
var currentSong = this.songs[index]
|
||||
var _x = winW / 2 + (i - this.selectedSong - 1) * (this.songAsset.width + this.songAsset.marginLeft) + this.songAsset.marginLeft + selectedWidth / 2 + xOffset
|
||||
if(_x > winW){
|
||||
break
|
||||
}
|
||||
this.drawClosedSong({
|
||||
x: _x,
|
||||
y: songTop,
|
||||
song: this.songs[index],
|
||||
highlight: highlight
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
var highlight = 0
|
||||
if(!currentSong.stars){
|
||||
highlight = 2
|
||||
}
|
||||
if(this.state.moveHover === 0){
|
||||
highlight = 1
|
||||
}
|
||||
var selectedSkin = this.songSkin.selected
|
||||
if(screen === "title" || this.state.locked === 3){
|
||||
selectedSkin = currentSong.skin
|
||||
highlight = 2
|
||||
}else if(songSelMoving){
|
||||
selectedSkin = currentSong.skin
|
||||
highlight = 0
|
||||
}
|
||||
var selectedHeight = this.songAsset.height
|
||||
if(screen === "difficulty"){
|
||||
selectedWidth = 912
|
||||
selectedHeight = 502
|
||||
highlight = 0
|
||||
}
|
||||
|
||||
this.drawSongFrame({
|
||||
x: winW / 2 - selectedWidth / 2 + xOffset,
|
||||
y: songTop + this.songAsset.height - selectedHeight,
|
||||
width: selectedWidth,
|
||||
height: selectedHeight,
|
||||
background: selectedSkin.background,
|
||||
border: selectedSkin.border,
|
||||
highlight: highlight,
|
||||
noCrop: screen === "difficulty",
|
||||
innerContent: (x, y, w, h) => {
|
||||
ctx.strokeStyle = "#000"
|
||||
if(screen === "title" || screen === "song"){
|
||||
var opened = ((selectedWidth - this.songAsset.width) / (this.songAsset.selectedWidth - this.songAsset.width))
|
||||
var songSel = true
|
||||
}else{
|
||||
this.drawLayeredText({
|
||||
text: "むずかしさをえらぶ",
|
||||
fontSize: 46,
|
||||
fontFamily: this.font,
|
||||
x: x - 144,
|
||||
y: y - 24,
|
||||
width: 280
|
||||
}, [
|
||||
{x: -2, y: -2, outline: "#000", letterBorder: 23},
|
||||
{shadow: true},
|
||||
{x: 2, y: 2},
|
||||
{x: -2, y: -2, outline: "#ff797b", letterBorder: 12},
|
||||
{x: 2, y: 2, outline: "#ad1516"},
|
||||
{outline: "#f70808"},
|
||||
{fill: "#fff"}
|
||||
])
|
||||
var opened = 1
|
||||
var songSel = false
|
||||
var _x = x + 62
|
||||
var _y = y + 67
|
||||
ctx.fillStyle = "#efb058"
|
||||
ctx.lineWidth = 5
|
||||
this.drawRoundedRect({
|
||||
x: _x - 28,
|
||||
y: _y,
|
||||
w: 56,
|
||||
h: 298,
|
||||
radius: 24
|
||||
})
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
ctx.fillStyle = "#f7d39c"
|
||||
ctx.beginPath()
|
||||
ctx.arc(_x, _y + 28, 20, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
this.drawDiffOptionsIcon({x: _x, y: _y + 28})
|
||||
|
||||
this.drawVerticalText({
|
||||
text: "もどる",
|
||||
x: _x,
|
||||
y: _y + 57,
|
||||
width: 56,
|
||||
height: 220,
|
||||
fill: "#fff",
|
||||
outline: "#000",
|
||||
letterBorder: 4,
|
||||
fontSize: 28,
|
||||
fontFamily: this.font,
|
||||
letterSpacing: 4
|
||||
})
|
||||
var highlight = 0
|
||||
if(this.state.moveHover === 0){
|
||||
highlight = 2
|
||||
}else if(this.selectedDiff === 0){
|
||||
highlight = 1
|
||||
}
|
||||
if(highlight){
|
||||
this.drawHighlight({
|
||||
x: _x - 32,
|
||||
y: _y - 3,
|
||||
w: 64,
|
||||
h: 304,
|
||||
animate: highlight === 1,
|
||||
opacity: highlight === 2 ? 0.8 : 1,
|
||||
radius: 24
|
||||
})
|
||||
if(this.selectedDiff === 0){
|
||||
this.drawDiffCursor({
|
||||
x: _x,
|
||||
y: _y - 45
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
for(var i = 0; currentSong.stars && i < 4; i++){
|
||||
if(currentSong.stars[i]){
|
||||
if(songSel){
|
||||
var _x = x + 33 + i * 60
|
||||
var _y = y + 120
|
||||
ctx.fillStyle = "#ff9f18"
|
||||
ctx.beginPath()
|
||||
ctx.arc(_x, _y + 22, 22, -Math.PI, 0)
|
||||
ctx.arc(_x, _y + 266, 22, 0, Math.PI)
|
||||
ctx.fill()
|
||||
this.drawDiffIcon({
|
||||
diff: i,
|
||||
x: _x,
|
||||
y: _y - 8,
|
||||
scale: 1,
|
||||
border: 6
|
||||
})
|
||||
}else{
|
||||
var _x = x + 402 + i * 100
|
||||
var _y = y + 87
|
||||
this.drawDiffIcon({
|
||||
diff: i,
|
||||
x: _x,
|
||||
y: _y - 12,
|
||||
scale: 1.4,
|
||||
border: 6.5,
|
||||
noFill: true
|
||||
})
|
||||
ctx.fillStyle = "#aa7023"
|
||||
ctx.lineWidth = 4.5
|
||||
ctx.fillRect(_x - 35.5, _y + 2, 71, 380)
|
||||
ctx.strokeRect(_x - 35.5, _y + 2, 71, 380)
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.lineWidth = 2.5
|
||||
ctx.fillRect(_x - 28, _y + 19, 56, 351)
|
||||
ctx.strokeRect(_x - 28, _y + 19, 56, 351)
|
||||
this.drawDiffIcon({
|
||||
diff: i,
|
||||
x: _x,
|
||||
y: _y - 12,
|
||||
scale: 1.4,
|
||||
border: 4.5
|
||||
})
|
||||
}
|
||||
this.drawVerticalText({
|
||||
text: this.difficulty[i],
|
||||
x: _x,
|
||||
y: songSel ? _y + 10 : _y + 23,
|
||||
width: songSel ? 44 : 56,
|
||||
height: songSel ? (i === 1 ? 66 : 88) : (i === 0 ? 130 : i === 1 ? 110 : 135),
|
||||
fill: "#000",
|
||||
fontSize: songSel ? 25 : (i === 2 ? 45 : 40),
|
||||
fontFamily: this.font
|
||||
})
|
||||
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]){
|
||||
ctx.fillStyle = songSel ? "#e97526" : "#e7e7e7"
|
||||
ctx.beginPath()
|
||||
ctx.arc(_x, yPos, songSel ? 4.5 : 5, 0, Math.PI * 2)
|
||||
ctx.fill()
|
||||
}else{
|
||||
ctx.save()
|
||||
ctx.fillStyle = songSel ? "#fff" : "#f72568"
|
||||
if(songSel){
|
||||
ctx.shadowColor = "#fff"
|
||||
ctx.shadowBlur = 10
|
||||
ctx.translate(_x - 9, yPos - 9)
|
||||
}else{
|
||||
ctx.translate(_x - 10.5, yPos - 9.5)
|
||||
ctx.scale(1.1, 1.1)
|
||||
}
|
||||
ctx.fill(this.diffStar)
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
if(i === currentSong.p2Cursor){
|
||||
this.drawDiffCursor({
|
||||
x: _x,
|
||||
y: _y - (songSel ? 45 : 65),
|
||||
two: true,
|
||||
side: songSel ? false : (currentSong.p2Cursor === this.selectedDiff - 1),
|
||||
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){
|
||||
highlight = 1
|
||||
}
|
||||
if(currentDiff === i){
|
||||
this.drawDiffCursor({
|
||||
x: _x,
|
||||
y: _y - 65,
|
||||
side: currentSong.p2Cursor === currentDiff
|
||||
})
|
||||
}
|
||||
if(highlight){
|
||||
this.drawHighlight({
|
||||
x: _x - 32,
|
||||
y: _y + 14,
|
||||
w: 64,
|
||||
h: 362,
|
||||
animate: highlight === 1,
|
||||
opacity: highlight === 2 ? 0.8 : 1
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.globalAlpha = 1 - Math.max(0, opened - 0.5) * 2
|
||||
ctx.fillStyle = selectedSkin.background
|
||||
ctx.fillRect(x,y,w,h)
|
||||
ctx.globalAlpha = 1
|
||||
var textX = Math.max(w - 37, w / 2)
|
||||
var textY = opened * 12 + (1 - opened) * 7
|
||||
this.drawVerticalText({
|
||||
text: currentSong.title,
|
||||
x: x + textX,
|
||||
y: y + textY,
|
||||
width: w,
|
||||
height: h - 35,
|
||||
fill: "#fff",
|
||||
outline: selectedSkin.outline,
|
||||
fontSize: 40,
|
||||
fontFamily: this.font
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if(songSelMoving){
|
||||
this.drawHighlight({
|
||||
x: winW / 2 - selectedWidth / 2,
|
||||
y: songTop,
|
||||
w: selectedWidth,
|
||||
h: selectedHeight,
|
||||
opacity: 0.8
|
||||
})
|
||||
}
|
||||
}
|
||||
previewLoaded(startLoad, prvtime, switchedTo){
|
||||
var endLoad = +new Date
|
||||
|
||||
drawRoundedRect(config){
|
||||
var ctx = this.ctx
|
||||
var x = config.x
|
||||
var y = config.y
|
||||
var w = config.w
|
||||
var h = config.h
|
||||
var r = config.radius
|
||||
ctx.beginPath()
|
||||
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
|
||||
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, 0)
|
||||
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 2)
|
||||
ctx.arc(x + r, y + h - r, r, Math.PI / 2, Math.PI)
|
||||
ctx.lineTo(x, y + r)
|
||||
}
|
||||
|
||||
drawClosedSong(config){
|
||||
config.width = this.songAsset.width
|
||||
config.height = this.songAsset.height
|
||||
config.background = config.song.skin.background
|
||||
config.border = config.song.skin.border
|
||||
config.outline = config.song.skin.outline
|
||||
config.text = config.song.title
|
||||
config.innerContent = (x, y, w, h) => {
|
||||
this.drawVerticalText({
|
||||
text: config.text,
|
||||
x: x + w / 2,
|
||||
y: y + 7,
|
||||
width: w,
|
||||
height: h - 35,
|
||||
fill: "#fff",
|
||||
outline: config.outline,
|
||||
fontSize: 40,
|
||||
fontFamily: this.font
|
||||
})
|
||||
}
|
||||
this.drawSongFrame(config)
|
||||
if(config.song.p2Cursor){
|
||||
this.drawDiffCursor({
|
||||
x: config.x + 48,
|
||||
y: config.y - 27,
|
||||
two: true,
|
||||
scale: 1,
|
||||
side: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
drawSongFrame(config){
|
||||
var ctx = this.ctx
|
||||
var x = config.x
|
||||
var y = config.y
|
||||
var w = config.width
|
||||
var h = config.height
|
||||
var border = this.songAsset.border
|
||||
var innerBorder = this.songAsset.innerBorder
|
||||
var allBorders = border + innerBorder
|
||||
var innerX = x + allBorders
|
||||
var innerY = y + allBorders
|
||||
var innerW = w - allBorders * 2
|
||||
var innerH = h - allBorders * 2
|
||||
|
||||
ctx.save()
|
||||
|
||||
ctx.shadowColor = "rgba(0, 0, 0, 0.5)"
|
||||
ctx.shadowBlur = 10
|
||||
ctx.shadowOffsetX = 5
|
||||
ctx.shadowOffsetY = 5
|
||||
ctx.fillStyle = "#000"
|
||||
ctx.fillRect(x, y, w, h)
|
||||
|
||||
ctx.restore()
|
||||
ctx.save()
|
||||
|
||||
{
|
||||
let _x = x + border
|
||||
let _y = y + border
|
||||
let _w = w - border * 2
|
||||
let _h = h - border * 2
|
||||
ctx.fillStyle = config.border[1]
|
||||
ctx.fillRect(_x, _y, _w, _h)
|
||||
ctx.fillStyle = config.border[0]
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(_x, _y)
|
||||
ctx.lineTo(_x + _w, _y)
|
||||
ctx.lineTo(_x + _w - innerBorder, _y + innerBorder)
|
||||
ctx.lineTo(_x + innerBorder, _y + _h - innerBorder)
|
||||
ctx.lineTo(_x, _y + _h)
|
||||
ctx.fill()
|
||||
}
|
||||
ctx.fillStyle = config.background
|
||||
ctx.fillRect(innerX, innerY, innerW, innerH)
|
||||
|
||||
ctx.save()
|
||||
|
||||
ctx.strokeStyle = "rgba(255, 255, 255, 0.3)"
|
||||
ctx.lineWidth = 3
|
||||
ctx.strokeRect(innerX, innerY, innerW, innerH)
|
||||
if(!config.noCrop){
|
||||
ctx.beginPath()
|
||||
ctx.rect(innerX, innerY, innerW, innerH)
|
||||
ctx.clip()
|
||||
}
|
||||
|
||||
config.innerContent(innerX, innerY, innerW, innerH)
|
||||
|
||||
ctx.restore()
|
||||
|
||||
if(config.highlight){
|
||||
this.drawHighlight({
|
||||
x: x,
|
||||
y: y,
|
||||
w: w,
|
||||
h: h,
|
||||
animate: config.highlight === 2,
|
||||
opacity: config.highlight === 1 ? 0.8 : 1
|
||||
})
|
||||
}
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
drawHighlight(config){
|
||||
var ctx = this.ctx
|
||||
ctx.save()
|
||||
var _x = config.x + 3.5
|
||||
var _y = config.y + 3.5
|
||||
var _w = config.w - 7
|
||||
var _h = config.h - 7
|
||||
var rect = () => {
|
||||
if(config.radius){
|
||||
this.drawRoundedRect({x: _x, y: _y, w: _w, h: _h, radius: config.radius})
|
||||
ctx.stroke()
|
||||
}else{
|
||||
ctx.strokeRect(_x, _y, _w, _h)
|
||||
}
|
||||
}
|
||||
if(config.animate){
|
||||
ctx.globalAlpha = this.fade((this.getMS() - this.state.moveMS) % 2000 / 2000)
|
||||
}else if(config.opacity){
|
||||
ctx.globalAlpha = config.opacity
|
||||
}
|
||||
ctx.strokeStyle = "rgba(255, 249, 1, 0.45)"
|
||||
ctx.lineWidth = 14
|
||||
rect()
|
||||
ctx.strokeStyle = "rgba(255, 249, 1, .8)"
|
||||
ctx.lineWidth = 8
|
||||
rect()
|
||||
ctx.strokeStyle = "#fff"
|
||||
ctx.lineWidth = 6
|
||||
rect()
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
fade(pos){
|
||||
if(pos < 0.5){
|
||||
pos = 1 - pos
|
||||
}
|
||||
return (1 - Math.cos(Math.PI * pos * 2)) / 2
|
||||
}
|
||||
|
||||
drawVerticalText(config){
|
||||
var ctx = this.ctx
|
||||
var inputText = config.text
|
||||
var mul = config.fontSize / 40
|
||||
var ura = false
|
||||
|
||||
if(inputText.endsWith(" (裏)")){
|
||||
inputText = inputText.slice(0, -4)
|
||||
ura = true
|
||||
}else if(inputText.endsWith("(裏)")){
|
||||
inputText = inputText.slice(0, -3)
|
||||
ura = true
|
||||
}
|
||||
var string = inputText.split("")
|
||||
var drawn = []
|
||||
|
||||
var r = this.regex
|
||||
for(let symbol of string){
|
||||
if(symbol === " "){
|
||||
// Space
|
||||
drawn.push({text: symbol, x: 0, y: 0, h: 18})
|
||||
}else if(symbol === "ー"){
|
||||
// Long-vowel mark
|
||||
drawn.push({svg: this.longVowelMark, x: -4, y: 5, h: 33, scale: [mul, mul]})
|
||||
}else if(r.comma.test(symbol)){
|
||||
// Comma, full stop
|
||||
drawn.push({text: symbol, x: 16, y: -7, h: 0, scale: [1.2, 0.7]})
|
||||
}else if(r.ideographicComma.test(symbol)){
|
||||
// Ideographic comma, full stop
|
||||
drawn.push({text: symbol, x: 16, y: -16, h: 18})
|
||||
}else if(r.apostrophe.test(symbol)){
|
||||
// Apostrophe
|
||||
drawn.push({text: ",", x: 20, y: -39, h: 0, scale: [1.2, 0.7]})
|
||||
}else if(r.brackets.test(symbol)){
|
||||
// Rotated brackets
|
||||
drawn.push({text: symbol, x: 0, y: -5, h: 25, rotate: true})
|
||||
}else if(r.tilde.test(symbol)){
|
||||
// Rotated hyphen, tilde
|
||||
if(symbol === "~"){
|
||||
symbol = "~"
|
||||
}
|
||||
drawn.push({text: symbol, x: 0, y: 2, h: 35, rotate: true})
|
||||
}else if(r.tall.test(symbol)){
|
||||
// Tall latin script lowercase, numbers
|
||||
drawn.push({text: symbol, x: 0, y: 4, h: 34, scale: [1.05, 0.9]})
|
||||
}else if(r.uppercase.test(symbol)){
|
||||
// Latin script upper case
|
||||
drawn.push({text: symbol, x: 0, y: 1, h: 31.5})
|
||||
}else if(r.lowercase.test(symbol)){
|
||||
// Latin script lower case
|
||||
drawn.push({text: symbol, x: 0, y: -1, h: 28, scale: [1.05, 0.9]})
|
||||
}else if(r.smallHiragana.test(symbol)){
|
||||
// Small hiragana, small katakana
|
||||
drawn.push({text: symbol, x: 0, y: -8, h: 25, right: true})
|
||||
}else if(r.hiragana.test(symbol)){
|
||||
// Hiragana, katakana
|
||||
drawn.push({text: symbol, x: 0, y: 5, h: 38, right: r.todo.test(symbol)})
|
||||
}else{
|
||||
// Kanji, other
|
||||
drawn.push({text: symbol, x: 0, y: 3, h: 39, right: true})
|
||||
}
|
||||
}
|
||||
|
||||
var drawnHeight = 0
|
||||
for(let symbol of drawn){
|
||||
if(config.letterSpacing){
|
||||
symbol.h += config.letterSpacing
|
||||
}
|
||||
drawnHeight += symbol.h * mul
|
||||
}
|
||||
|
||||
ctx.save()
|
||||
ctx.translate(config.x, config.y)
|
||||
|
||||
var scale = 1
|
||||
if(config.height){
|
||||
var height = config.height - (ura ? 52 * mul : 0)
|
||||
if(drawnHeight > height){
|
||||
scale = height / drawnHeight
|
||||
ctx.scale(1, scale)
|
||||
}
|
||||
}
|
||||
|
||||
if(ura){
|
||||
// Circled ura
|
||||
drawn.push({text: "裏", x: 0, y: 18, h: 52, ura: true, scale: [1, 1 / scale]})
|
||||
}
|
||||
|
||||
var actions = []
|
||||
if(config.outline){
|
||||
actions.push("stroke")
|
||||
}
|
||||
if(config.fill){
|
||||
actions.push("fill")
|
||||
}
|
||||
for(let action of actions){
|
||||
ctx.font = config.fontSize + "px " + config.fontFamily
|
||||
ctx.textBaseline = "top"
|
||||
if(action === "stroke"){
|
||||
ctx.strokeStyle = config.outline
|
||||
ctx.lineWidth = this.songAsset.letterBorder * mul
|
||||
ctx.lineJoin = "round"
|
||||
ctx.miterLimit = 1
|
||||
}else if(action === "fill"){
|
||||
ctx.fillStyle = config.fill
|
||||
}
|
||||
var offsetY = 0
|
||||
|
||||
for(let symbol of drawn){
|
||||
var saved = false
|
||||
var currentX = symbol.x
|
||||
if(symbol.right){
|
||||
currentX += 20 * mul
|
||||
}
|
||||
var currentY = offsetY + symbol.y * mul
|
||||
if(symbol.rotate || symbol.scale || symbol.svg || symbol.ura){
|
||||
saved = true
|
||||
ctx.save()
|
||||
|
||||
if(symbol.rotate){
|
||||
ctx.translate(currentX + 20 * mul, currentY + 20 * mul)
|
||||
ctx.rotate(Math.PI / 2)
|
||||
}else{
|
||||
ctx.translate(currentX, currentY)
|
||||
}
|
||||
if(symbol.scale){
|
||||
ctx.scale(symbol.scale[0], symbol.scale[1])
|
||||
ctx.lineWidth = ctx.lineWidth / symbol.scale[0]
|
||||
}
|
||||
currentX = 0
|
||||
currentY = 0
|
||||
}
|
||||
if(symbol.svg){
|
||||
ctx[action](symbol.svg)
|
||||
}else{
|
||||
if(symbol.right){
|
||||
ctx.textAlign = "right"
|
||||
}else{
|
||||
ctx.textAlign = "center"
|
||||
}
|
||||
if(symbol.ura){
|
||||
ctx.font = (30 * mul) + "px Meiryo"
|
||||
ctx.textBaseline = "center"
|
||||
ctx.beginPath()
|
||||
ctx.arc(currentX, currentY + (21.5 * mul), (18 * mul), 0, Math.PI * 2)
|
||||
if(action === "stroke"){
|
||||
ctx.fillStyle = config.outline
|
||||
ctx.fill()
|
||||
}else if(action === "fill"){
|
||||
ctx.strokeStyle = config.fill
|
||||
ctx.lineWidth = 2.5 * mul
|
||||
ctx.fillText(symbol.text, currentX, currentY)
|
||||
}
|
||||
ctx.stroke()
|
||||
}else{
|
||||
ctx[action + "Text"](symbol.text, currentX, currentY)
|
||||
}
|
||||
}
|
||||
offsetY += symbol.h * mul
|
||||
if(saved){
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
drawLayeredText(config, layers){
|
||||
var ctx = this.ctx
|
||||
var mul = config.fontSize / 40
|
||||
ctx.save()
|
||||
|
||||
var string = config.text.split("")
|
||||
var drawn = []
|
||||
|
||||
var r = this.regex
|
||||
for(let symbol of string){
|
||||
if(symbol === "-"){
|
||||
drawn.push({text: symbol, x: -4, y: 0, w: 28, scale: [0.8, 1]})
|
||||
}else if(r.latin.test(symbol)){
|
||||
// Latin script
|
||||
drawn.push({text: symbol, x: 0, y: 0, w: 32})
|
||||
}else if(r.smallHiragana.test(symbol)){
|
||||
// Small hiragana, small katakana
|
||||
drawn.push({text: symbol, x: 0, y: 0, w: 30})
|
||||
}else if(r.hiragana.test(symbol)){
|
||||
// Hiragana, katakana
|
||||
drawn.push({text: symbol, x: 0, y: 0, w: 35})
|
||||
}else{
|
||||
drawn.push({text: symbol, x: 0, y: 0, w: 39})
|
||||
}
|
||||
}
|
||||
|
||||
var drawnWidth = 0
|
||||
for(let symbol of drawn){
|
||||
if(config.letterSpacing){
|
||||
symbol.w += config.letterSpacing
|
||||
}
|
||||
drawnWidth += symbol.w
|
||||
}
|
||||
|
||||
ctx.translate(config.x, config.y)
|
||||
var scale = 1
|
||||
if(config.width && drawnWidth > config.width){
|
||||
scale = config.width / drawnWidth
|
||||
ctx.scale(scale, 1)
|
||||
}
|
||||
ctx.font = config.fontSize + "px " + config.fontFamily
|
||||
ctx.textBaseline = "top"
|
||||
ctx.textAlign = "center"
|
||||
|
||||
for(let layer of layers){
|
||||
var action = "strokeText"
|
||||
if(layer.outline){
|
||||
ctx.strokeStyle = layer.outline
|
||||
ctx.lineJoin = "round"
|
||||
ctx.miterLimit = 1
|
||||
}
|
||||
if(layer.letterBorder){
|
||||
ctx.lineWidth = layer.letterBorder
|
||||
}
|
||||
if(layer.fill){
|
||||
ctx.fillStyle = layer.fill
|
||||
action = "fillText"
|
||||
}
|
||||
if(layer.shadow){
|
||||
ctx.save()
|
||||
ctx.shadowColor = "rgba(0, 0, 0, 0.5)"
|
||||
ctx.shadowBlur = 3
|
||||
ctx.shadowOffsetX = 3
|
||||
ctx.shadowOffsetY = 3
|
||||
}
|
||||
var offsetX = 0
|
||||
for(let symbol of drawn){
|
||||
var saved = false
|
||||
var currentX = offsetX + symbol.x + (layer.x || 0) + symbol.w / 2
|
||||
var currentY = symbol.y + (layer.y || 0)
|
||||
if(config.center){
|
||||
currentX -= drawnWidth / 2
|
||||
}
|
||||
if(symbol.scale){
|
||||
saved = true
|
||||
ctx.save()
|
||||
ctx.translate(currentX, currentY)
|
||||
ctx.scale(symbol.scale[0], symbol.scale[1])
|
||||
currentX = 0
|
||||
currentY = 0
|
||||
}
|
||||
ctx[action](symbol.text, currentX, currentY)
|
||||
if(saved){
|
||||
ctx.restore()
|
||||
}
|
||||
offsetX += symbol.w * mul
|
||||
}
|
||||
if(layer.shadow){
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
drawDiffIcon(config){
|
||||
var ctx = this.ctx
|
||||
var scale = config.scale
|
||||
ctx.save()
|
||||
ctx.lineWidth = config.border
|
||||
ctx.strokeStyle = "#000"
|
||||
var icon = this.diffIconPath[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++){
|
||||
if(!icon[i].noStroke){
|
||||
ctx.stroke(icon[i].d)
|
||||
}
|
||||
}
|
||||
if(!config.noFill){
|
||||
for(var i = 1; i < icon.length; i++){
|
||||
ctx.fillStyle = icon[i].fill
|
||||
ctx.fill(icon[i].d)
|
||||
}
|
||||
}
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
drawDiffOptionsIcon(config){
|
||||
var ctx = this.ctx
|
||||
ctx.save()
|
||||
ctx.translate(config.x - 21, config.y - 21)
|
||||
|
||||
var drawLine = y => {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(12, y)
|
||||
ctx.arc(20.5, 25, 8.5, Math.PI, Math.PI * 2, true)
|
||||
ctx.lineTo(29, 18)
|
||||
ctx.stroke()
|
||||
}
|
||||
var drawTriangle = noFill => {
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(29, 5)
|
||||
ctx.lineTo(21, 19)
|
||||
ctx.lineTo(37, 19)
|
||||
ctx.closePath()
|
||||
if(!noFill){
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 12
|
||||
drawLine(9)
|
||||
ctx.lineWidth = 5
|
||||
drawTriangle(true)
|
||||
ctx.stroke()
|
||||
ctx.lineWidth = 7
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.strokeStyle = "#fff"
|
||||
drawLine(11)
|
||||
drawTriangle()
|
||||
ctx.translate(-1.5, -0.5)
|
||||
ctx.fillStyle = "#23a6e1"
|
||||
ctx.strokeStyle = "#23a6e1"
|
||||
ctx.globalCompositeOperation = "darken"
|
||||
drawLine(11)
|
||||
drawTriangle()
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
drawDiffCursor(config){
|
||||
var ctx = this.ctx
|
||||
ctx.save()
|
||||
if(config.scale){
|
||||
ctx.translate(config.x, config.y)
|
||||
ctx.scale(config.scale, config.scale)
|
||||
ctx.translate(-48, -64)
|
||||
}else{
|
||||
ctx.translate(config.x - 48, config.y - 64)
|
||||
}
|
||||
|
||||
ctx.fillStyle = config.two ? "#65cdcd" : "#ff411c"
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.lineWidth = 6
|
||||
ctx.beginPath()
|
||||
if(!config.side){
|
||||
var textX = config.two ? 20 : 17
|
||||
ctx.moveTo(48, 120)
|
||||
ctx.arc(48, 48.5, 45, Math.PI * 0.58, Math.PI * 0.42)
|
||||
}else if(config.two){
|
||||
var textX = 70
|
||||
ctx.moveTo(56, 115)
|
||||
ctx.arc(98, 48.5, 45, Math.PI * 0.75, Math.PI * 0.59)
|
||||
}else{
|
||||
var textX = -33
|
||||
ctx.moveTo(39, 115)
|
||||
ctx.arc(-2, 48.5, 45, Math.PI * 0.41, Math.PI * 0.25)
|
||||
}
|
||||
ctx.closePath()
|
||||
ctx.fill()
|
||||
ctx.stroke()
|
||||
this.drawLayeredText({
|
||||
text: config.two ? "2P" : "1P",
|
||||
fontSize: 43,
|
||||
fontFamily: this.font,
|
||||
x: textX,
|
||||
y: 26,
|
||||
width: 54,
|
||||
letterSpacing: -4
|
||||
}, [
|
||||
{outline: "#fff", letterBorder: 11},
|
||||
{fill: "#000"}
|
||||
])
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
startPreview(loadOnly){
|
||||
var currentSong = this.songs[this.selectedSong]
|
||||
var id = currentSong.id
|
||||
var prvTime = currentSong.preview
|
||||
this.endPreview(true)
|
||||
|
||||
if("id" in currentSong){
|
||||
var startLoad = this.getMS()
|
||||
if(loadOnly){
|
||||
var currentId = null
|
||||
}else{
|
||||
var currentId = this.previewId
|
||||
this.previewing = this.selectedSong
|
||||
}
|
||||
var songObj = assets.songs.find(song => song.id == id)
|
||||
|
||||
if(songObj.sound){
|
||||
if(!loadOnly){
|
||||
this.preview = songObj.sound
|
||||
this.preview.gain = snd.previewGain
|
||||
this.previewLoaded(startLoad, prvTime)
|
||||
}
|
||||
}else{
|
||||
snd.previewGain.load("/songs/" + id + "/main.mp3").then(sound => {
|
||||
if(currentId === this.previewId){
|
||||
songObj.sound = sound
|
||||
this.preview = sound
|
||||
this.previewLoaded(startLoad, prvTime)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
previewLoaded(startLoad, prvtime){
|
||||
var endLoad = this.getMS()
|
||||
var difference = endLoad - startLoad
|
||||
var minDelay = switchedTo ? 300 : 1000
|
||||
var minDelay = 300
|
||||
var delay = minDelay - Math.min(minDelay, difference)
|
||||
this.preview.playLoop(delay / 1000, false, prvtime / 1000)
|
||||
}
|
||||
endPreview() {
|
||||
endPreview(){
|
||||
this.previewId++
|
||||
this.previewing = null
|
||||
if(this.preview){
|
||||
this.preview.stop()
|
||||
}
|
||||
}
|
||||
run(){
|
||||
this.createCode()
|
||||
this.startP2()
|
||||
|
||||
this.songselHelp = document.getElementById("songsel-help")
|
||||
pageEvents.once(this.songselHelp, "click").then(() => {
|
||||
this.clean()
|
||||
assets.sounds["don"].play()
|
||||
new Tutorial()
|
||||
})
|
||||
this.diffElements = document.getElementsByClassName("difficulty")
|
||||
for(let difficulty of this.diffElements){
|
||||
pageEvents.once(difficulty, "click").then(this.onDifficulty.bind(this))
|
||||
}
|
||||
this.songElements = document.getElementsByClassName("song")
|
||||
for(let song of this.songElements){
|
||||
pageEvents.add(song, "click", this.onSong.bind(this))
|
||||
}
|
||||
this.songSelect = document.getElementById("song-select")
|
||||
}
|
||||
onDifficulty(event){
|
||||
this.clean()
|
||||
var target = event.currentTarget
|
||||
var song = target.parentNode.parentNode
|
||||
assets.sounds["don"].play()
|
||||
|
||||
this.selectedSong.difficulty = target.classList[1]
|
||||
this.selectedSong.title = song.dataset.title
|
||||
this.selectedSong.folder = song.dataset.songId
|
||||
|
||||
new loadSong(this.selectedSong, event.shiftKey, event.ctrlKey)
|
||||
}
|
||||
onSong(event){
|
||||
var target = event.currentTarget
|
||||
var opened = document.getElementsByClassName("opened")[0]
|
||||
if(!opened){
|
||||
this.startPreview(target.dataset.songId, target.dataset.preview)
|
||||
assets.sounds["don"].play()
|
||||
assets.sounds["song-select"].stop()
|
||||
assets.sounds["diffsel"].play(0.3)
|
||||
target.classList.add("opened")
|
||||
this.songSelect.classList.add("difficulty-select")
|
||||
}else if(opened == target){
|
||||
this.endPreview()
|
||||
playBgm(enabled){
|
||||
if(enabled && !this.bgmEnabled){
|
||||
this.bgmEnabled = true
|
||||
snd.musicGain.fadeIn(0.4)
|
||||
assets.sounds["diffsel"].stop()
|
||||
assets.sounds["cancel"].play()
|
||||
assets.sounds["song-select"].play(0.3)
|
||||
opened.classList.remove("opened")
|
||||
this.songSelect.classList.remove("difficulty-select")
|
||||
}else{
|
||||
this.startPreview(target.dataset.songId, target.dataset.preview, true)
|
||||
assets.sounds["ka"].play()
|
||||
opened.classList.remove("opened")
|
||||
target.classList.add("opened")
|
||||
}else if(!enabled && this.bgmEnabled){
|
||||
this.bgmEnabled = false
|
||||
snd.musicGain.fadeOut(0.4)
|
||||
}
|
||||
}
|
||||
createCode(){
|
||||
assets.sounds["bgm_songsel"].playLoop(0.1, false, 0, 1.442, 3.506)
|
||||
assets.sounds["song-select"].play(0.2)
|
||||
var songElements = [0]
|
||||
|
||||
assets.songs.forEach(song => {
|
||||
var songTitle = song.title
|
||||
var charElements = [0]
|
||||
var diffElements = [0]
|
||||
|
||||
for(var charIndex = 0; charIndex < songTitle.length; charIndex++){
|
||||
var ch = songTitle.charAt(charIndex)
|
||||
var cl = "song-title-char"
|
||||
if(ch == " "){
|
||||
ch = "\xa0"
|
||||
cl += " song-title-space"
|
||||
}else if(songTitle.charAt(charIndex + 1) == "'"){
|
||||
ch = ch + "'"
|
||||
cl += " song-title-apos"
|
||||
charIndex++
|
||||
}
|
||||
charElements.push(
|
||||
["span", {
|
||||
class: cl,
|
||||
alt: ch
|
||||
}, ch]
|
||||
)
|
||||
}
|
||||
for(var diff in this.diffNames){
|
||||
var diffName = diff
|
||||
var diffLevel = song.stars[diff]
|
||||
if (!diffLevel) {
|
||||
continue
|
||||
}
|
||||
var starsDisplay = [0]
|
||||
for(var star = 1; star <= diffLevel; star++){
|
||||
starsDisplay.push("\u2605")
|
||||
starsDisplay.push(["br"])
|
||||
}
|
||||
var diffTxt = this.diffNames[diffName]
|
||||
diffElements.push(
|
||||
["li", {
|
||||
class: "difficulty " + diffName
|
||||
},
|
||||
["span", {
|
||||
class: "diffname"
|
||||
}, diffTxt],
|
||||
["span", {
|
||||
class: "stars"
|
||||
}, starsDisplay]
|
||||
]
|
||||
)
|
||||
}
|
||||
songElements.push(
|
||||
["div", {
|
||||
id: "song-" + song.id,
|
||||
class: "song",
|
||||
"data-title": songTitle,
|
||||
"data-song-id": song.id,
|
||||
"data-preview": song.preview
|
||||
},
|
||||
["div", {
|
||||
class: /^[\x00-\xFF]*$/.test(songTitle) ? "song-title alpha-title" : "song-title"
|
||||
}, charElements],
|
||||
["ul", {
|
||||
class: "difficulties"
|
||||
}, diffElements]
|
||||
]
|
||||
)
|
||||
})
|
||||
element(
|
||||
document.getElementById("song-container"),
|
||||
songElements
|
||||
)
|
||||
}
|
||||
onusers(response){
|
||||
var oldP2Elements = document.getElementsByClassName("p2")
|
||||
for(var i = oldP2Elements.length; i--;){
|
||||
oldP2Elements[i].classList.remove("p2")
|
||||
}
|
||||
this.songs.forEach(song => {
|
||||
song.p2Cursor = null
|
||||
})
|
||||
if(response){
|
||||
response.forEach(idDiff => {
|
||||
var id = idDiff.id |0
|
||||
var diff = idDiff.diff
|
||||
if(diff in this.diffNames){
|
||||
var idElement = document.getElementById("song-" + id)
|
||||
if(idElement){
|
||||
idElement.classList.add("p2")
|
||||
var diffElement = idElement.getElementsByClassName("difficulty " + diff)[0]
|
||||
if(diffElement){
|
||||
diffElement.classList.add("p2")
|
||||
}
|
||||
}
|
||||
var diffId = this.difficultyId.indexOf(diff)
|
||||
if(diffId >= 0){
|
||||
var currentSong = this.songs.find(song => song.id === id)
|
||||
currentSong.p2Cursor = diffId
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -216,23 +1564,29 @@ class SongSelect{
|
||||
p2.open()
|
||||
}
|
||||
}
|
||||
|
||||
mod(length, index){
|
||||
return ((index % length) + length) % length
|
||||
}
|
||||
|
||||
getMS(){
|
||||
return +new Date
|
||||
}
|
||||
|
||||
clean(){
|
||||
assets.sounds["bgm_songsel"].stop()
|
||||
assets.sounds["song-select"].stop()
|
||||
assets.sounds["diffsel"].stop()
|
||||
if(!this.bgmEnabled){
|
||||
snd.musicGain.fadeIn()
|
||||
setTimeout(() => {
|
||||
snd.musicGain.fadeIn()
|
||||
}, 500)
|
||||
}
|
||||
this.redrawRunning = false
|
||||
this.endPreview()
|
||||
snd.musicGain.fadeIn()
|
||||
pageEvents.remove(p2, "message")
|
||||
for(let difficulty of this.diffElements){
|
||||
pageEvents.remove(difficulty, "click")
|
||||
}
|
||||
delete this.diffElements
|
||||
for(let song of this.songElements){
|
||||
pageEvents.remove(song, "click")
|
||||
}
|
||||
delete this.songElements
|
||||
pageEvents.remove(this.songselHelp, "click")
|
||||
delete this.songselHelp
|
||||
delete this.songSelect
|
||||
pageEvents.keyRemove(this, "all")
|
||||
pageEvents.remove(this.canvas, "mousemove")
|
||||
pageEvents.remove(this.canvas, "mousedown")
|
||||
delete this.ctx
|
||||
delete this.canvas
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,24 @@ class Titlescreen{
|
||||
constructor(){
|
||||
loader.changePage("titlescreen")
|
||||
this.titleScreen = document.getElementById("title-screen")
|
||||
pageEvents.keyOnce(this, 13, "down").then(this.goNext.bind(this))
|
||||
pageEvents.once(this.titleScreen, "click").then(this.goNext.bind(this))
|
||||
pageEvents.keyOnce(this, 13, "down").then(this.onPressed.bind(this))
|
||||
pageEvents.once(this.titleScreen, "click").then(this.onPressed.bind(this))
|
||||
assets.sounds["title"].play()
|
||||
this.gamepad = new Gamepad({
|
||||
"start": ["b", "x", "y", "start"],
|
||||
"a": ["a"]
|
||||
}, (pressed, key) => {
|
||||
if(pressed){
|
||||
this.onPressed()
|
||||
}
|
||||
})
|
||||
}
|
||||
goNext(){
|
||||
onPressed(){
|
||||
this.clean()
|
||||
assets.sounds["don"].play()
|
||||
setTimeout(this.goNext.bind(this), 500)
|
||||
}
|
||||
goNext(){
|
||||
if(localStorage.getItem("tutorial") !== "true"){
|
||||
new Tutorial()
|
||||
} else {
|
||||
@ -16,6 +27,7 @@ class Titlescreen{
|
||||
}
|
||||
}
|
||||
clean(){
|
||||
this.gamepad.clean()
|
||||
assets.sounds["title"].stop()
|
||||
pageEvents.keyRemove(this, 13)
|
||||
pageEvents.remove(this.titleScreen, "click")
|
||||
|
@ -1,19 +1,28 @@
|
||||
class Tutorial{
|
||||
constructor(){
|
||||
constructor(fromSongSel){
|
||||
this.fromSongSel = fromSongSel
|
||||
loader.changePage("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, "click").then(this.onEnd.bind(this))
|
||||
pageEvents.keyOnce(this, 13, "down").then(this.onEnd.bind(this))
|
||||
this.gamepad = new Gamepad({
|
||||
"confirm": ["start", "b"]
|
||||
}, this.onEnd.bind(this))
|
||||
}
|
||||
onEnd(){
|
||||
this.clean()
|
||||
assets.sounds["don"].play()
|
||||
localStorage.setItem("tutorial", "true")
|
||||
new SongSelect()
|
||||
setTimeout(() => {
|
||||
new SongSelect(this.fromSongSel)
|
||||
}, 500)
|
||||
}
|
||||
clean(){
|
||||
this.gamepad.clean()
|
||||
assets.sounds["bgm_setsume"].stop()
|
||||
pageEvents.remove(this.endButton, "click")
|
||||
pageEvents.keyRemove(this, 13)
|
||||
delete this.endButton
|
||||
}
|
||||
}
|
||||
|
@ -777,18 +777,6 @@ class View{
|
||||
don.setAnimationEnd(ms + length * don.speed, don.normalAnimation)
|
||||
}
|
||||
}
|
||||
gameEnded(){
|
||||
if(this.controller.getGlobalScore().hp >= 50){
|
||||
var don = this.assets.don
|
||||
don.setAnimation("endclear")
|
||||
var ms = this.controller.getElapsedTime().ms
|
||||
don.setAnimationStart(ms)
|
||||
var length = don.getAnimationLength("normal")
|
||||
don.setUpdateSpeed(this.beatInterval / (length / 4))
|
||||
var length = don.getAnimationLength("endclear")
|
||||
don.setAnimationEnd(ms + length * don.speed, don.normalAnimation)
|
||||
}
|
||||
}
|
||||
onmousemove(event){
|
||||
this.lastMousemove = this.controller.getElapsedTime().ms
|
||||
this.cursorHidden = false
|
||||
|
@ -55,7 +55,6 @@ class ViewAssets{
|
||||
}
|
||||
}
|
||||
this.don.addFrames("clear", 30, "don_anim_clear")
|
||||
this.don.addFrames("endclear", 22, "don_anim_endclear")
|
||||
this.don.normalAnimation()
|
||||
this.fire = this.createAsset("bar", frame => {
|
||||
var imgw = 360
|
||||
|
@ -3,7 +3,7 @@
|
||||
<canvas id="canvas"></canvas>
|
||||
<div id="pause-menu">
|
||||
<div class="window">
|
||||
<button type="button" id="continue-butt">Continue</button>
|
||||
<button type="button" id="continue-butt" class="selected">Continue</button>
|
||||
<button type="button" id="restart-butt">Restart</button>
|
||||
<button type="button" id="song-selection-butt">Song selection</button>
|
||||
</div>
|
||||
|
@ -33,7 +33,7 @@
|
||||
</div>
|
||||
<div class="bottom-part">
|
||||
<div class="gradient-overlay"></div>
|
||||
<button type="button" class="song-select">Song select</button>
|
||||
<button type="button" class="replay">Replay</button>
|
||||
<button type="button" class="song-select selected">Song select</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,3 @@
|
||||
<div id="song-select">
|
||||
<h2 alt="曲をえらぶ" class="stroke-main songsel-title-song">曲をえらぶ</h2>
|
||||
<h2 alt="むずかしさをえらぶ" class="stroke-main songsel-title-difficulty">むずかしさをえらぶ</h2>
|
||||
<div id="songsel-help">?</div>
|
||||
<div id="song-container"></div>
|
||||
<canvas id="song-sel-canvas"></canvas>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user