Merge pull request #52 from LoveEevee/add-tja-support
Add .tja file support
This commit is contained in:
commit
1fdde6d4a8
1
.gitignore
vendored
1
.gitignore
vendored
@ -45,3 +45,4 @@ public/songs
|
||||
public/api
|
||||
taiko.db
|
||||
version.json
|
||||
public/index.html
|
||||
|
@ -10,9 +10,10 @@ 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 )
|
||||
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 "categories" ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `title_en` TEXT NOT NULL )
|
||||
|
||||
When inserting rows, leave any difficulty columns as NULL if you don't intend to add notecharts for them.
|
||||
When inserting song rows, leave any difficulty columns as NULL if you don't intend to add notecharts for them.
|
||||
|
||||
Each song's data is contained within a directory under `public/songs/`. For example:
|
||||
|
||||
|
31
app.py
31
app.py
@ -60,6 +60,26 @@ def get_osu_key(osu, section, key, default=None):
|
||||
return default
|
||||
|
||||
|
||||
def get_tja_preview(tja):
|
||||
tja_lines = open(tja, 'r').read().replace('\x00', '').split('\n')
|
||||
|
||||
for line in tja_lines:
|
||||
line = line.strip()
|
||||
if ':' in line:
|
||||
name, value = line.split(':', 1)
|
||||
if name.lower() == 'demostart':
|
||||
value = value.strip()
|
||||
try:
|
||||
value = float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
return int(value * 1000)
|
||||
elif line.lower() == '#start':
|
||||
break
|
||||
return 0
|
||||
|
||||
|
||||
@app.teardown_appcontext
|
||||
def close_connection(exception):
|
||||
db = getattr(g, '_database', None)
|
||||
@ -85,6 +105,13 @@ def route_api_songs():
|
||||
categories[cat[0]] = {'title': cat[1], 'title_en': cat[2]}
|
||||
songs_out = []
|
||||
for song in songs:
|
||||
type = song[9]
|
||||
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])
|
||||
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']]
|
||||
if osus:
|
||||
osud = parse_osu('public/songs/%s/%s' % (song[0], osus[0]))
|
||||
@ -102,7 +129,9 @@ def route_api_songs():
|
||||
],
|
||||
'preview': preview,
|
||||
'category': category_out['title'],
|
||||
'category_en': category_out['title_en']
|
||||
'category_en': category_out['title_en'],
|
||||
'type': type,
|
||||
'offset': song[10]
|
||||
})
|
||||
|
||||
return jsonify(songs_out)
|
||||
|
@ -8,8 +8,13 @@ class Controller{
|
||||
this.snd = this.multiplayer ? "_p" + this.multiplayer : ""
|
||||
|
||||
var backgroundURL = "/songs/" + this.selectedSong.folder + "/bg.png"
|
||||
var songParser = new ParseSong(songData)
|
||||
this.parsedSongData = songParser.getData()
|
||||
|
||||
if(selectedSong.type === "tja"){
|
||||
this.parsedSongData = new ParseTja(songData, selectedSong.difficulty, selectedSong.offset)
|
||||
}else{
|
||||
this.parsedSongData = new ParseOsu(songData, selectedSong.offset)
|
||||
}
|
||||
this.offset = this.parsedSongData.soundOffset
|
||||
|
||||
assets.songs.forEach(song => {
|
||||
if(song.id == this.selectedSong.folder){
|
||||
@ -168,9 +173,6 @@ class Controller{
|
||||
getBindings(){
|
||||
return this.keyboard.getBindings()
|
||||
}
|
||||
getSongData(){
|
||||
return this.game.getSongData()
|
||||
}
|
||||
getElapsedTime(){
|
||||
return this.game.elapsedTime
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ class Game{
|
||||
update(){
|
||||
// Main operations
|
||||
this.updateTime()
|
||||
this.checkTiming()
|
||||
this.updateCirclesStatus()
|
||||
this.checkPlays()
|
||||
// Event operations
|
||||
@ -277,6 +276,7 @@ class Game{
|
||||
var started = this.fadeOutStarted
|
||||
if(started){
|
||||
var ms = this.elapsedTime
|
||||
var musicDuration = this.controller.mainAsset.duration * 1000 - this.controller.offset
|
||||
if(this.musicFadeOut === 0){
|
||||
if(this.controller.multiplayer === 1){
|
||||
p2.send("gameresults", this.getGlobalScore())
|
||||
@ -286,10 +286,10 @@ class Game{
|
||||
this.controller.gameEnded()
|
||||
p2.send("gameend")
|
||||
this.musicFadeOut++
|
||||
}else if(this.musicFadeOut === 2 && (ms >= started + 8600 && ms >= this.controller.mainAsset.duration * 1000 + 250)){
|
||||
}else if(this.musicFadeOut === 2 && (ms >= started + 8600 && ms >= musicDuration + 250)){
|
||||
this.controller.displayResults()
|
||||
this.musicFadeOut++
|
||||
}else if(this.musicFadeOut === 3 && (ms >= started + 9600 && ms >= this.controller.mainAsset.duration * 1000 + 1250)){
|
||||
}else if(this.musicFadeOut === 3 && (ms >= started + 9600 && ms >= musicDuration + 1250)){
|
||||
this.controller.clean()
|
||||
if(this.controller.scoresheet){
|
||||
this.controller.scoresheet.startRedraw()
|
||||
@ -297,15 +297,8 @@ class Game{
|
||||
}
|
||||
}
|
||||
}
|
||||
checkTiming(){
|
||||
if(this.songData.timingPoints[this.currentTimingPoint + 1]){
|
||||
if(this.elapsedTime >= this.songData.timingPoints[this.currentTimingPoint + 1].start){
|
||||
this.currentTimingPoint++
|
||||
}
|
||||
}
|
||||
}
|
||||
playMainMusic(){
|
||||
var ms = this.elapsedTime
|
||||
var ms = this.elapsedTime + this.controller.offset
|
||||
if(!this.mainMusicPlaying && (!this.fadeOutStarted || ms < this.fadeOutStarted + 1600)){
|
||||
if(this.controller.multiplayer !== 2){
|
||||
this.mainAsset.play((ms < 0 ? -ms : 0) / 1000, false, Math.max(0, ms / 1000))
|
||||
@ -362,9 +355,6 @@ class Game{
|
||||
getCircles(){
|
||||
return this.songData.circles
|
||||
}
|
||||
getSongData(){
|
||||
return this.songData
|
||||
}
|
||||
updateCurrentCircle(){
|
||||
this.currentCircle++
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class loadSong{
|
||||
}, reject)
|
||||
}
|
||||
}))
|
||||
promises.push(loader.ajax(this.getOsuPath(this.selectedSong)).then(data => {
|
||||
promises.push(loader.ajax(this.getSongPath(this.selectedSong)).then(data => {
|
||||
this.songData = data.replace(/\0/g, "").split("\n")
|
||||
}))
|
||||
Promise.all(promises).then(() => {
|
||||
@ -50,8 +50,13 @@ class loadSong{
|
||||
alert("An error occurred, please refresh")
|
||||
})
|
||||
}
|
||||
getOsuPath(selectedSong){
|
||||
return "/songs/" + selectedSong.folder + "/" + selectedSong.difficulty + ".osu"
|
||||
getSongPath(selectedSong){
|
||||
var directory = "/songs/" + selectedSong.folder + "/"
|
||||
if(selectedSong.type === "tja"){
|
||||
return directory + "main.tja"
|
||||
}else{
|
||||
return directory + selectedSong.difficulty + ".osu"
|
||||
}
|
||||
}
|
||||
setupMultiplayer(){
|
||||
if(this.multiplayer){
|
||||
@ -70,15 +75,21 @@ class loadSong{
|
||||
this.selectedSong2 = {
|
||||
title: this.selectedSong.title,
|
||||
folder: this.selectedSong.folder,
|
||||
difficulty: event.value
|
||||
difficulty: event.value,
|
||||
type: this.selectedSong.type,
|
||||
offset: this.selectedSong.offset
|
||||
}
|
||||
loader.ajax(this.getOsuPath(this.selectedSong2)).then(data => {
|
||||
if(this.selectedSong.type === "tja"){
|
||||
p2.send("gamestart")
|
||||
}else{
|
||||
loader.ajax(this.getSongPath(this.selectedSong2)).then(data => {
|
||||
this.song2Data = data.replace(/\0/g, "").split("\n")
|
||||
p2.send("gamestart")
|
||||
}, () => {
|
||||
p2.send("gamestart")
|
||||
})
|
||||
}
|
||||
}
|
||||
}else if(event.type === "gamestart"){
|
||||
this.clean()
|
||||
loader.changePage("game")
|
||||
|
@ -1,5 +1,5 @@
|
||||
class ParseSong{
|
||||
constructor(fileContent){
|
||||
class ParseOsu{
|
||||
constructor(fileContent, offset){
|
||||
this.osu = {
|
||||
OFFSET: 0,
|
||||
MSPERBEAT: 1,
|
||||
@ -36,11 +36,13 @@ class ParseSong{
|
||||
}
|
||||
this.data = []
|
||||
for(let line of fileContent){
|
||||
line = line.trim().replace(/\/\/.*/, "")
|
||||
line = line.replace(/\/\/.*/, "").trim()
|
||||
if(line !== ""){
|
||||
this.data.push(line)
|
||||
}
|
||||
}
|
||||
this.offset = (offset || 0) * -1000
|
||||
this.soundOffset = 0
|
||||
this.beatInfo = {
|
||||
beatInterval: 0,
|
||||
lastBeatInterval: 0,
|
||||
@ -126,7 +128,7 @@ class ParseSong{
|
||||
this.difficulty.lastMultiplier = sliderMultiplier
|
||||
}
|
||||
timingPoints.push({
|
||||
start: start,
|
||||
start: start + this.offset,
|
||||
sliderMultiplier: sliderMultiplier,
|
||||
measure: parseInt(values[this.osu.METER]),
|
||||
gogoTime: parseInt(values[this.osu.KIAIMODE])
|
||||
@ -139,20 +141,18 @@ class ParseSong{
|
||||
var measureNumber = 0
|
||||
for(var i = 0; i<this.timingPoints.length; i++){
|
||||
if(this.timingPoints[i + 1]){
|
||||
var limit = this.timingPoints[i + 1].start
|
||||
var limit = this.timingPoints[i + 1].start - this.offset
|
||||
}else{
|
||||
var limit = this.circles[this.circles.length - 1].getMS()
|
||||
var limit = this.circles[this.circles.length - 1].getMS() - this.offset
|
||||
}
|
||||
for(var j = this.timingPoints[i].start; j <= limit; j += this.beatInfo.beatInterval){
|
||||
for(var start = this.timingPoints[i].start; start <= limit; start += this.beatInfo.beatInterval){
|
||||
if(measureNumber === 0){
|
||||
measures.push({
|
||||
ms: j,
|
||||
nb: measureNumber,
|
||||
ms: start + this.offset,
|
||||
speed: this.timingPoints[i].sliderMultiplier
|
||||
})
|
||||
measureNumber++
|
||||
if(measureNumber === this.timingPoints[i].measure + 1){
|
||||
measureNumber = 0
|
||||
}
|
||||
measureNumber = (measureNumber + 1) % (this.timingPoints[i].measure + 1)
|
||||
}
|
||||
}
|
||||
return measures
|
||||
@ -242,9 +242,14 @@ class ParseSong{
|
||||
var hitSound = parseInt(values[this.osu.HITSOUND])
|
||||
var beatLength = speed
|
||||
var lastMultiplier = this.difficulty.lastMultiplier
|
||||
if(circleID === 1 && start + this.offset < 0){
|
||||
var offset = start + this.offset
|
||||
this.soundOffset = offset
|
||||
this.offset -= offset
|
||||
}
|
||||
|
||||
for(var j = 0; j < this.timingPoints.length; j++){
|
||||
if(this.timingPoints[j].start > start){
|
||||
if(this.timingPoints[j].start - this.offset > start){
|
||||
break
|
||||
}
|
||||
speed = this.timingPoints[j].sliderMultiplier
|
||||
@ -258,11 +263,11 @@ class ParseSong{
|
||||
var requiredHits = Math.floor(Math.max(1, (endTime - start) / 1000 * hitMultiplier))
|
||||
circles.push(new Circle({
|
||||
id: circleID,
|
||||
start: start,
|
||||
start: start + this.offset,
|
||||
type: "balloon",
|
||||
txt: "ふうせん",
|
||||
speed: speed,
|
||||
endTime: endTime,
|
||||
endTime: endTime + this.offset,
|
||||
requiredHits: requiredHits,
|
||||
gogoTime: gogoTime
|
||||
}))
|
||||
@ -284,11 +289,11 @@ class ParseSong{
|
||||
}
|
||||
circles.push(new Circle({
|
||||
id: circleID,
|
||||
start: start,
|
||||
start: start + this.offset,
|
||||
type: type,
|
||||
txt: txt,
|
||||
speed: speed,
|
||||
endTime: endTime,
|
||||
endTime: endTime + this.offset,
|
||||
gogoTime: gogoTime
|
||||
}))
|
||||
|
||||
@ -318,7 +323,7 @@ class ParseSong{
|
||||
if(!emptyValue){
|
||||
circles.push(new Circle({
|
||||
id: circleID,
|
||||
start: start,
|
||||
start: start + this.offset,
|
||||
type: type,
|
||||
txt: txt,
|
||||
speed: speed,
|
||||
@ -334,16 +339,4 @@ class ParseSong{
|
||||
}
|
||||
return circles
|
||||
}
|
||||
getData(){
|
||||
return {
|
||||
generalInfo: this.generalInfo,
|
||||
metaData: this.metadata,
|
||||
editor: this.editor,
|
||||
beatInfo: this.beatInfo,
|
||||
difficulty: this.difficulty,
|
||||
timingPoints: this.timingPoints,
|
||||
circles: this.circles,
|
||||
measures: this.measures
|
||||
}
|
||||
}
|
||||
}
|
338
public/src/js/parsetja.js
Normal file
338
public/src/js/parsetja.js
Normal file
@ -0,0 +1,338 @@
|
||||
class ParseTja{
|
||||
constructor(file, difficulty, offset){
|
||||
this.data = []
|
||||
for(let line of file){
|
||||
line = line.replace(/\/\/.*/, "").trim()
|
||||
if(line !== ""){
|
||||
this.data.push(line)
|
||||
}
|
||||
}
|
||||
this.difficulty = difficulty
|
||||
this.offset = (offset || 0) * -1000
|
||||
this.soundOffset = 0
|
||||
this.noteTypes = [
|
||||
{name: false, txt: false},
|
||||
{name: "don", txt: "ドン"},
|
||||
{name: "ka", txt: "カッ"},
|
||||
{name: "daiDon", txt: "ドン(大)"},
|
||||
{name: "daiKa", txt: "カッ(大)"},
|
||||
{name: "drumroll", txt: "連打ーっ!!"},
|
||||
{name: "daiDrumroll", txt: "連打(大)ーっ!!"},
|
||||
{name: "balloon", txt: "ふうせん"},
|
||||
{name: false, txt: false},
|
||||
{name: "balloon", txt: "ふうせん"}
|
||||
]
|
||||
this.courseTypes = ["easy", "normal", "hard", "oni"]
|
||||
|
||||
this.metadata = this.parseMetadata()
|
||||
this.measures = []
|
||||
this.beatInfo = {}
|
||||
this.circles = this.parseCircles()
|
||||
}
|
||||
parseMetadata(){
|
||||
var metaNumbers = ["bpm", "offset"]
|
||||
var inSong = false
|
||||
var courses = {}
|
||||
var currentCourse = {}
|
||||
var courseName = this.difficulty
|
||||
for(var lineNum = 0; lineNum < this.data.length; lineNum++){
|
||||
var line = this.data[lineNum]
|
||||
|
||||
if(line.slice(0, 1) === "#"){
|
||||
|
||||
var name = line.slice(1).toLowerCase()
|
||||
if(name === "start" && !inSong){
|
||||
|
||||
inSong = true
|
||||
for(var name in currentCourse){
|
||||
if(!(courseName in courses)){
|
||||
courses[courseName] = {}
|
||||
}
|
||||
courses[courseName][name] = currentCourse[name]
|
||||
}
|
||||
courses[courseName].start = lineNum + 1
|
||||
courses[courseName].end = this.data.length
|
||||
|
||||
}else if(name === "end" && inSong){
|
||||
inSong = false
|
||||
courses[courseName].end = lineNum
|
||||
}
|
||||
|
||||
}else if(!inSong){
|
||||
|
||||
if(line.indexOf(":") > 0){
|
||||
|
||||
var [name, value] = this.split(line, ":")
|
||||
name = name.toLowerCase().trim()
|
||||
value = value.trim()
|
||||
|
||||
if(name === "course"){
|
||||
if(value in this.courseTypes){
|
||||
courseName = this.courseTypes[value]
|
||||
}else{
|
||||
courseName = value.toLowerCase()
|
||||
}
|
||||
}else if(name === "balloon"){
|
||||
value = value ? value.split(",").map(digit => parseInt(digit)) : []
|
||||
}else if(this.inArray(name, metaNumbers)){
|
||||
value = parseFloat(value)
|
||||
}
|
||||
|
||||
currentCourse[name] = value
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return courses
|
||||
}
|
||||
inArray(string, array){
|
||||
return array.indexOf(string) >= 0
|
||||
}
|
||||
split(string, delimiter){
|
||||
var index = string.indexOf(delimiter)
|
||||
if(index < 0){
|
||||
return [string, ""]
|
||||
}
|
||||
return [string.slice(0, index), string.slice(index + delimiter.length)]
|
||||
}
|
||||
parseCircles(){
|
||||
var meta = this.metadata[this.difficulty]
|
||||
var ms = (meta.offset || 0) * -1000 + this.offset
|
||||
var bpm = meta.bpm || 0
|
||||
if(bpm <= 0){
|
||||
bpm = 1
|
||||
}
|
||||
var scroll = 1
|
||||
var measure = 4
|
||||
this.beatInfo.beatInterval = 60000 / bpm
|
||||
var gogo = false
|
||||
var barLine = true
|
||||
|
||||
var balloonID = 0
|
||||
var balloons = meta.balloon || []
|
||||
|
||||
var lastDrumroll = false
|
||||
var branch = false
|
||||
var branchType
|
||||
var branchPreference = "m"
|
||||
|
||||
var currentMeasure = []
|
||||
var firstMeasure = true
|
||||
var firstNote = true
|
||||
var circles = []
|
||||
var circleID = 0
|
||||
|
||||
var pushMeasure = () => {
|
||||
if(barLine){
|
||||
var note = currentMeasure[0]
|
||||
if(note){
|
||||
var speed = note.bpm * note.scroll / 60
|
||||
}else{
|
||||
var speed = bpm * scroll / 60
|
||||
}
|
||||
this.measures.push({
|
||||
ms: ms,
|
||||
speed: speed
|
||||
})
|
||||
if(firstMeasure){
|
||||
firstMeasure = false
|
||||
var msPerMeasure = 60000 * measure / bpm
|
||||
for(var measureMs = ms - msPerMeasure; measureMs > 0; measureMs -= msPerMeasure){
|
||||
this.measures.push({
|
||||
ms: measureMs,
|
||||
speed: speed
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if(currentMeasure.length){
|
||||
for(var i = 0; i < currentMeasure.length; i++){
|
||||
var note = currentMeasure[i]
|
||||
if(firstNote && note.type){
|
||||
firstNote = false
|
||||
if(ms < 0){
|
||||
this.soundOffset = ms
|
||||
ms = 0
|
||||
}
|
||||
}
|
||||
note.start = ms
|
||||
if(note.endDrumroll){
|
||||
note.endDrumroll.endTime = ms
|
||||
}
|
||||
var msPerMeasure = 60000 * measure / bpm
|
||||
ms += msPerMeasure / currentMeasure.length
|
||||
}
|
||||
for(var i = 0; i < currentMeasure.length; i++){
|
||||
var note = currentMeasure[i]
|
||||
if(note.type){
|
||||
circleID++
|
||||
var circleObj = new Circle({
|
||||
id: circleID,
|
||||
start: note.start,
|
||||
type: note.type,
|
||||
txt: note.txt,
|
||||
speed: note.bpm * note.scroll / 60,
|
||||
gogoTime: note.gogo,
|
||||
endTime: note.endTime,
|
||||
requiredHits: note.requiredHits
|
||||
})
|
||||
if(lastDrumroll === note){
|
||||
lastDrumroll = circleObj
|
||||
}
|
||||
|
||||
circles.push(circleObj)
|
||||
}
|
||||
}
|
||||
}else{
|
||||
var msPerMeasure = 60000 * measure / bpm
|
||||
ms += msPerMeasure
|
||||
}
|
||||
}
|
||||
|
||||
for(var lineNum = meta.start; lineNum < meta.end; lineNum++){
|
||||
var line = this.data[lineNum]
|
||||
if(line.slice(0, 1) === "#"){
|
||||
|
||||
var line = line.slice(1).toLowerCase()
|
||||
var [name, value] = this.split(line, " ")
|
||||
|
||||
switch(name){
|
||||
case "gogostart":
|
||||
gogo = true
|
||||
break
|
||||
case "gogoend":
|
||||
gogo = false
|
||||
break
|
||||
case "bpmchange":
|
||||
bpm = parseFloat(value)
|
||||
break
|
||||
case "scroll":
|
||||
scroll = parseFloat(value)
|
||||
break
|
||||
case "branchstart":
|
||||
branch = true
|
||||
branchType = ""
|
||||
value = value.split(",")
|
||||
var forkType = value[0].toLowerCase()
|
||||
if(forkType === "r" || parseFloat(value[2]) <= 100){
|
||||
branchPreference = "m"
|
||||
}else if(parseFloat(value[1]) <= 100){
|
||||
branchPreference = "e"
|
||||
}else{
|
||||
branchPreference = "n"
|
||||
}
|
||||
break
|
||||
case "branchend":
|
||||
case "section":
|
||||
branch = false
|
||||
break
|
||||
case "n": case "e": case "m":
|
||||
branchType = name
|
||||
break
|
||||
case "measure":
|
||||
var [numerator, denominator] = value.split("/")
|
||||
measure = numerator / denominator * 4
|
||||
break
|
||||
case "delay":
|
||||
ms += (parseFloat(value) || 0) * 1000
|
||||
break
|
||||
case "barlineon":
|
||||
barLine = true
|
||||
break
|
||||
case "barlineoff":
|
||||
barLine = false
|
||||
break
|
||||
}
|
||||
|
||||
}else if(!branch || branch && branchType === branchPreference){
|
||||
|
||||
var string = line.split("")
|
||||
|
||||
for(let symbol of string){
|
||||
|
||||
var error = false
|
||||
switch(symbol){
|
||||
|
||||
case "0":
|
||||
currentMeasure.push({
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
})
|
||||
break
|
||||
case "1": case "2": case "3": case "4":
|
||||
var type = this.noteTypes[symbol]
|
||||
var circleObj = {
|
||||
type: type.name,
|
||||
txt: type.txt,
|
||||
gogo: gogo,
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
}
|
||||
if(lastDrumroll){
|
||||
circleObj.endDrumroll = lastDrumroll
|
||||
lastDrumroll = false
|
||||
}
|
||||
currentMeasure.push(circleObj)
|
||||
break
|
||||
case "5": case "6": case "7": case "9":
|
||||
var type = this.noteTypes[symbol]
|
||||
var circleObj = {
|
||||
type: type.name,
|
||||
txt: type.txt,
|
||||
gogo: gogo,
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
}
|
||||
if(lastDrumroll){
|
||||
circleObj.endDrumroll = lastDrumroll
|
||||
}
|
||||
if(symbol === "7" || symbol === "9"){
|
||||
var hits = balloons[balloonID]
|
||||
if(!hits || hits < 1){
|
||||
hits = 1
|
||||
}
|
||||
circleObj.requiredHits = hits
|
||||
balloonID++
|
||||
}
|
||||
lastDrumroll = circleObj
|
||||
currentMeasure.push(circleObj)
|
||||
break
|
||||
case "8":
|
||||
if(lastDrumroll){
|
||||
currentMeasure.push({
|
||||
endDrumroll: lastDrumroll,
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
})
|
||||
lastDrumroll = false
|
||||
}else{
|
||||
currentMeasure.push({
|
||||
bpm: bpm,
|
||||
scroll: scroll
|
||||
})
|
||||
}
|
||||
break
|
||||
case ",":
|
||||
pushMeasure()
|
||||
currentMeasure = []
|
||||
break
|
||||
default:
|
||||
error = true
|
||||
break
|
||||
|
||||
}
|
||||
if(error){
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
pushMeasure()
|
||||
if(lastDrumroll){
|
||||
lastDrumroll.endTime = ms
|
||||
}
|
||||
|
||||
return circles
|
||||
}
|
||||
}
|
@ -88,7 +88,9 @@ class SongSelect{
|
||||
skin: song.category in this.songSkin ? this.songSkin[song.category] : this.songSkin.default,
|
||||
stars: song.stars,
|
||||
category: song.category,
|
||||
preview: song.preview || 0
|
||||
preview: song.preview || 0,
|
||||
type: song.type,
|
||||
offset: song.offset
|
||||
})
|
||||
}
|
||||
this.songs.sort((a, b) => {
|
||||
@ -470,7 +472,9 @@ class SongSelect{
|
||||
"title": selectedSong.title,
|
||||
"folder": selectedSong.id,
|
||||
"difficulty": this.difficultyId[difficulty],
|
||||
"category": selectedSong.category
|
||||
"category": selectedSong.category,
|
||||
"type": selectedSong.type,
|
||||
"offset": selectedSong.offset
|
||||
}, shift, ctrl, touch)
|
||||
}
|
||||
toTitleScreen(){
|
||||
|
@ -48,7 +48,7 @@ class View{
|
||||
|
||||
this.drumroll = []
|
||||
|
||||
this.beatInterval = this.controller.getSongData().beatInfo.beatInterval
|
||||
this.beatInterval = this.controller.parsedSongData.beatInfo.beatInterval
|
||||
this.assets = new ViewAssets(this)
|
||||
|
||||
this.touch = -Infinity
|
||||
@ -216,13 +216,14 @@ class View{
|
||||
//this.drawTime()
|
||||
}
|
||||
updateDonFaces(){
|
||||
if(this.controller.getElapsedTime() >= this.nextBeat){
|
||||
var ms = this.controller.getElapsedTime()
|
||||
while(ms >= this.nextBeat){
|
||||
this.nextBeat += this.beatInterval
|
||||
if(this.controller.getCombo() >= 50){
|
||||
this.currentBigDonFace = (this.currentBigDonFace + 1) % 2
|
||||
this.currentDonFace = (this.currentDonFace + 1) % 2
|
||||
}
|
||||
else{
|
||||
var face = Math.floor(ms / this.beatInterval) % 2
|
||||
this.currentBigDonFace = face
|
||||
this.currentDonFace = face
|
||||
}else{
|
||||
this.currentBigDonFace = 1
|
||||
this.currentDonFace = 0
|
||||
}
|
||||
@ -289,16 +290,12 @@ class View{
|
||||
}
|
||||
}
|
||||
drawMeasures(){
|
||||
var measures = this.controller.getSongData().measures
|
||||
var measures = this.controller.parsedSongData.measures
|
||||
var currentTime = this.controller.getElapsedTime()
|
||||
|
||||
measures.forEach((measure, index)=>{
|
||||
var timeForDistance = this.posToMs(this.distanceForCircle, measure.speed)
|
||||
if(
|
||||
currentTime >= measure.ms - timeForDistance
|
||||
&& currentTime <= measure.ms + 350
|
||||
&& measure.nb == 0
|
||||
){
|
||||
if(currentTime >= measure.ms - timeForDistance && currentTime <= measure.ms + 350){
|
||||
this.drawMeasure(measure)
|
||||
}
|
||||
})
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
<script src="/src/js/assets.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/loadsong.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/parsesong.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/parseosu.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/titlescreen.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/scoresheet.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/songselect.js?{{version.commit_short}}"></script>
|
||||
@ -51,6 +51,7 @@
|
||||
<script src="/src/js/loader.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/canvastest.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/canvascache.js?{{version.commit_short}}"></script>
|
||||
<script src="/src/js/parsetja.js?{{version.commit_short}}"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
Loading…
Reference in New Issue
Block a user