Commit 28b837fb authored by Bui's avatar Bui Committed by GitHub

Merge branch 'master' into cat-jump

parents 750dc662 ce4d8ce3
......@@ -16,14 +16,6 @@
width: 100%;
height: 100%;
}
#cursor{
position: fixed;
width: 1px;
height: 1px;
cursor: none;
pointer-events: none;
z-index: 1;
}
#touch-drum{
display: none;
position: absolute;
......
......@@ -158,8 +158,7 @@ kbd{
.setting-box:first-child{
margin-top: 0;
}
.settings-outer .view-content:not(:hover) .setting-box.selected,
.view-outer:not(.settings-outer) .setting-box.selected,
.view-content:not(:hover) .setting-box.selected,
.setting-box:hover{
background: #ffb547;
animation: 2s linear border-pulse infinite;
......@@ -177,7 +176,6 @@ kbd{
overflow: hidden;
}
.view-content:not(:hover) .setting-box.selected .setting-name,
.view-outer:not(.settings-outer) .setting-box.selected .setting-name,
.setting-box:hover .setting-name,
.setting-box:hover #gamepad-value{
color: #fff;
......@@ -193,6 +191,8 @@ kbd{
border-radius: 0.2em;
padding: 0.5em;
box-sizing: border-box;
overflow: hidden;
white-space: nowrap;
}
.setting-value.selected{
width: calc(50% + 0.2em);
......@@ -215,27 +215,26 @@ kbd{
background: rgba(0, 0, 0, 0.5);
z-index: 1;
}
#settings-gamepad{
#settings-gamepad,
#settings-latency{
display: none;
}
#settings-gamepad .view{
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 574px;
height: 428px;
max-height: calc(100vh - 14em + 88px);
width: 29.9em;
max-width: 100vw;
}
#settings-gamepad .setting-box{
height: auto;
overflow: hidden;
}
#gamepad-bg,
#gamepad-buttons{
background-size: 20.53em;
}
#gamepad-bg{
position: relative;
width: 550px;
height: 317px;
width: 20.53em;
height: 11.83em;
max-height: none;
background-repeat: no-repeat;
text-align: center;
......@@ -244,11 +243,11 @@ kbd{
}
#gamepad-buttons{
position: absolute;
left: 141px;
top: 120px;
width: 282px;
height: 131px;
background-position: 0 -318px;
left: 5.26em;
top: 4.48em;
width: 10.52em;
height: 4.89em;
background-position: 0 -11.87em;
background-repeat: no-repeat;
pointer-events: none;
}
......@@ -259,3 +258,36 @@ kbd{
#gamepad-value::before{
left: auto;
}
#settings-latency .view{
width: 30em;
}
#settings-latency .setting-value{
position: relative;
}
.setting-value:not(.selected) .latency-buttons{
display: none;
}
.setting-value .latency-buttons{
position: absolute;
top: 0;
right: 0;
bottom: 0;
padding: 0;
}
.latency-buttons span{
display: inline-block;
width: 2em;
height: 100%;
text-align: center;
background-color: #c3862a;
color: #fff;
line-height: 2em;
outline: none;
}
.latency-buttons span:hover,
.latency-buttons span:active{
background-color: #946013;
}
.left-buttons .taibtn{
z-index: 1;
}
......@@ -29,23 +29,30 @@
this.endButton.innerText = strings.tutorial.ok
this.endButton.setAttribute("alt", strings.tutorial.ok)
this.items = []
var versionUrl = gameConfig._version.url
this.getLink(this.linkIssues).href = versionUrl + "issues"
this.items.push(this.linkIssues)
var contactEmail = gameConfig.email
if (typeof contactEmail === 'string') {
this.hasEmail = typeof contactEmail === "string"
if(this.hasEmail){
this.linkEmail.setAttribute("alt", contactEmail)
this.getLink(this.linkEmail).href = "mailto:" + contactEmail
this.getLink(this.linkEmail).text = contactEmail
} else {
this.linkEmail.style.display = "none"
this.getLink(this.linkEmail).innerText = contactEmail
this.items.push(this.linkEmail)
}else{
this.linkEmail.parentNode.removeChild(this.linkEmail)
}
pageEvents.add(this.linkIssues, ["click", "touchend"], this.linkButton.bind(this))
pageEvents.add(this.linkEmail, ["click", "touchend"], this.linkButton.bind(this))
if(this.hasEmail){
pageEvents.add(this.linkEmail, ["click", "touchend"], this.linkButton.bind(this))
}
pageEvents.add(this.endButton, ["mousedown", "touchstart"], this.onEnd.bind(this))
this.items = [this.linkIssues, this.linkEmail, this.endButton]
this.selected = 2
this.items.push(this.endButton)
this.selected = this.items.length - 1
this.keyboard = new Keyboard({
confirm: ["enter", "space", "don_l", "don_r"],
......@@ -146,6 +153,8 @@
}
}
diag.push("Language: " + strings.id + userLangStr)
var latency = settings.getItem("latency")
diag.push("Audio Latency: " + (latency.audio > 0 ? "+" : "") + latency.audio.toString() + "ms, Video Latency: " + (latency.video > 0 ? "+" : "") + latency.video.toString() + "ms")
var errorObj = {}
if(localStorage["lastError"]){
try{
......@@ -195,7 +204,9 @@
}
var issueBody = strings.about.issueTemplate + "\n\n\n\n" + diag
this.getLink(this.linkEmail).href += "?body=" + encodeURIComponent(issueBody.replace(/\n/g, "<br>\r\n"))
if(this.hasEmail){
this.getLink(this.linkEmail).href += "?body=" + encodeURIComponent(issueBody.replace(/\n/g, "<br>\r\n"))
}
return diag
}
......@@ -214,7 +225,9 @@
this.keyboard.clean()
this.gamepad.clean()
pageEvents.remove(this.linkIssues, ["click", "touchend"])
pageEvents.remove(this.linkEmail, ["click", "touchend"])
if(this.hasEmail){
pageEvents.remove(this.linkEmail, ["click", "touchend"])
}
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
if(this.textarea){
pageEvents.remove(this.textarea, ["focus", "blur"])
......
......@@ -91,26 +91,8 @@ var assets = {
"se_ka.wav",
"se_pause.wav",
"se_jump.wav",
"v_combo_50_meka.wav",
"v_combo_100_meka.wav",
"v_combo_200_meka.wav",
"v_combo_300_meka.wav",
"v_combo_400_meka.wav",
"v_combo_500_meka.wav",
"v_combo_600_meka.wav",
"v_combo_700_meka.wav",
"v_combo_800_meka.wav",
"v_combo_900_meka.wav",
"v_combo_1000_meka.wav",
"v_combo_1100_meka.wav",
"v_combo_1200_meka.wav",
"v_combo_1300_meka.wav",
"v_combo_1400_meka.wav",
"v_combo_over1500_meka.wav",
"se_calibration.wav",
"v_fullcombo_meka.wav",
"v_renda_meka.wav",
"v_results.wav",
"v_sanka.wav",
"v_songsel.wav",
......@@ -128,23 +110,6 @@ var assets = {
"se_results_countup.wav",
"se_results_crown.wav",
"v_combo_50.wav",
"v_combo_100.wav",
"v_combo_200.wav",
"v_combo_300.wav",
"v_combo_400.wav",
"v_combo_500.wav",
"v_combo_600.wav",
"v_combo_700.wav",
"v_combo_800.wav",
"v_combo_900.wav",
"v_combo_1000.wav",
"v_combo_1100.wav",
"v_combo_1200.wav",
"v_combo_1300.wav",
"v_combo_1400.wav",
"v_combo_over1500.wav",
"v_fullcombo.wav",
"v_renda.wav",
"v_results_fullcombo.wav",
......
class CanvasCache{
constructor(w, h, scale){
constructor(noSmoothing, w, h, scale){
this.noSmoothing = noSmoothing
if(w){
this.resize(w, h, scale)
}
......@@ -11,6 +12,9 @@ class CanvasCache{
this.map = new Map()
this.canvas = document.createElement("canvas")
this.ctx = this.canvas.getContext("2d")
if(this.noSmoothing){
this.ctx.imageSmoothingEnabled = false
}
}
this.scale = scale
this.x = 0
......
class CanvasDraw{
constructor(){
constructor(noSmoothing){
this.diffStarPath = new Path2D(vectors.diffStar)
this.longVowelMark = new Path2D(vectors.longVowelMark)
......@@ -68,7 +68,8 @@
emCap: /[MWMW]/,
rWidth: /[abdfIjo-rtvabdfIjo-rtv]/,
lWidth: /[ilil]/,
ura: /\s*[\(][\)]$/
ura: /\s*[\(][\)]$/,
cjk: /[\u3040-ゞ゠-ヾ一-\u9ffe]/
}
var numbersFull = "0123456789"
......@@ -78,10 +79,12 @@
this.numbersFullToHalf[numbersFull[i]] = numbersHalf[i]
this.numbersFullToHalf[numbersHalf[i]] = numbersHalf[i]
}
this.wrapOn = [" ", "\n", "%s"]
this.stickySymbols = "!,.:;?~‐–‼、。々〜ぁぃぅぇぉっゃゅょァィゥェォッャュョ・ーヽヾ!:;?"
this.songFrameCache = new CanvasCache()
this.diffStarCache = new CanvasCache()
this.crownCache = new CanvasCache()
this.songFrameCache = new CanvasCache(noSmoothing)
this.diffStarCache = new CanvasCache(noSmoothing)
this.crownCache = new CanvasCache(noSmoothing)
this.tmpCanvas = document.createElement("canvas")
this.tmpCtx = this.tmpCanvas.getContext("2d")
......@@ -818,6 +821,163 @@
ctx.restore()
}
wrappingText(config){
var ctx = config.ctx
var inputText = config.text.toString()
var words = []
var start = 0
var substituteIndex = 0
while(start < inputText.length){
var character = inputText.slice(start, start + 1)
if(words.length !== 0){
var previous = words[words.length - 1]
if(!previous.substitute && previous !== "\n" && this.stickySymbols.indexOf(character) !== -1){
words[words.length - 1] += character
start++
continue
}
}
var index = Infinity
var currentIndex = inputText.slice(start).search(this.regex.cjk)
if(currentIndex !== -1){
index = start + currentIndex
var on = inputText.charAt(index)
}
for(var i = 0; i < this.wrapOn.length; i++){
var currentIndex = inputText.indexOf(this.wrapOn[i], start)
if(currentIndex !== -1 && currentIndex < index){
var on = this.wrapOn[i]
index = currentIndex
}
}
if(index === Infinity){
if(start !== inputText.length){
words.push(inputText.slice(start, inputText.length))
}
break
}
var end = index + (on === " " ? 1 : 0)
if(start !== end){
words.push(inputText.slice(start, end))
}
if(on === "%s" && config.substitute){
words.push({
substitute: true,
index: substituteIndex,
width: config.substitute(config, substituteIndex, true) || 0
})
substituteIndex++
}else if(on !== " "){
words.push(on)
}
start = index + on.length
}
ctx.save()
var bold = this.bold(config.fontFamily)
ctx.font = bold + config.fontSize + "px " + config.fontFamily
ctx.textBaseline = config.baseline || "top"
ctx.textAlign = "left"
ctx.fillStyle = config.fill
var lineHeight = config.lineHeight || config.fontSize
var x = 0
var y = 0
var totalW = 0
var totalH = 0
var line = ""
var toDraw = []
var lastWidth = 0
var addToDraw = obj => {
toDraw.push(obj)
if(x + lastWidth > totalW){
totalW = x + lastWidth
}
if(y + lineHeight > totalH){
totalH = y + lineHeight
}
}
var recenter = () => {
if(config.textAlign === "center"){
for(var j in toDraw){
if(toDraw[j].y === y){
toDraw[j].x += (config.width - x - lastWidth) / 2
}
}
}
}
for(var i in words){
var skip = words[i].substitute || words[i] === "\n"
if(!skip){
var currentWidth = ctx.measureText(line + words[i]).width
}
if(skip || (x !== 0 || line) && x + currentWidth > config.width){
if(line){
addToDraw({
text: line,
x: x, y: y
})
}
if(words[i].substitute){
line = ""
var currentWidth = words[i].width
if(x + lastWidth + currentWidth > config.width){
recenter()
x = 0
y += lineHeight
lastWidth = 0
}
addToDraw({
substitute: true,
index: words[i].index,
x: x + lastWidth, y: y
})
x += lastWidth + currentWidth
lastWidth = currentWidth
}else{
recenter()
x = 0
y += lineHeight
line = words[i] === "\n" ? "" : words[i]
lastWidth = ctx.measureText(line).width
}
}else{
line += words[i]
lastWidth = currentWidth
}
}
if(line){
addToDraw({
text: line,
x: x, y: y
})
recenter()
}
var addX = 0
var addY = 0
if(config.verticalAlign === "middle"){
addY = ((config.height || 0) - totalH) / 2
}
for(var i in toDraw){
var x = config.x + toDraw[i].x + addX
var y = config.y + toDraw[i].y + addY
if(toDraw[i].text){
ctx.fillText(toDraw[i].text, x, y)
}else if(toDraw[i].substitute){
ctx.save()
ctx.translate(x, y)
config.substitute(config, toDraw[i].index)
ctx.restore()
}
}
ctx.restore()
}
diffIcon(config){
var ctx = config.ctx
var scale = config.scale
......
......@@ -7,6 +7,16 @@ class Controller{
this.touchEnabled = touchEnabled
this.snd = this.multiplayer ? "_p" + this.multiplayer : ""
this.calibrationMode = selectedSong.folder === "calibration"
this.audioLatency = 0
this.videoLatency = 0
if(!this.calibrationMode){
var latency = settings.getItem("latency")
if(!autoPlayEnabled){
this.audioLatency = Math.round(latency.audio) || 0
}
this.videoLatency = Math.round(latency.video) || 0 + this.audioLatency
}
if(this.multiplayer !== 2){
loader.changePage("game", false)
}
......@@ -17,19 +27,41 @@ class Controller{
this.parsedSongData = new ParseOsu(songData, selectedSong.difficulty, selectedSong.stars, selectedSong.offset)
}
this.offset = this.parsedSongData.soundOffset
var maxCombo = this.parsedSongData.circles.filter(circle => ["don", "ka", "daiDon", "daiKa"].indexOf(circle.type) > -1 && (!circle.branch || circle.branch.name == "master")).length
if (maxCombo >= 50) {
var comboVoices = ["v_combo_50"].concat([...Array(Math.floor(maxCombo/100)).keys()].map(i => "v_combo_" + (i + 1)*100))
var promises = []
comboVoices.forEach(name => {
if (!assets.sounds[name + "_p1"]) {
promises.push(loader.loadSound(name + ".wav", snd.sfxGain).then(sound => {
assets.sounds[name + "_p1"] = assets.sounds[name].copy(snd.sfxGainL)
assets.sounds[name + "_p2"] = assets.sounds[name].copy(snd.sfxGainR)
}))
}
})
Promise.all(promises)
}
assets.songs.forEach(song => {
if(song.id == this.selectedSong.folder){
this.mainAsset = song.sound
this.volume = song.volume || 1
}
})
if(this.calibrationMode){
this.volume = 1
}else{
assets.songs.forEach(song => {
if(song.id == this.selectedSong.folder){
this.mainAsset = song.sound
this.volume = song.volume || 1
}
})
}
this.game = new Game(this, this.selectedSong, this.parsedSongData)
this.view = new View(this)
this.mekadon = new Mekadon(this, this.game)
this.keyboard = new GameInput(this)
this.drumSounds = settings.getItem("latency").drumSounds
this.playedSounds = {}
}
run(syncWith){
......@@ -72,8 +104,8 @@ class Controller{
}
stopMainLoop(){
this.mainLoopRunning = false
if(this.mainAsset){
this.mainAsset.stop()
if(this.game.mainAsset){
this.game.mainAsset.stop()
}
if(this.multiplayer !== 2){
clearInterval(this.gameInterval)
......@@ -90,13 +122,18 @@ class Controller{
if(this.game.musicFadeOut < 3){
this.keyboard.checkMenuKeys()
}
if(this.calibrationMode){
this.game.calibration()
}
if(!this.game.isPaused()){
this.keyboard.checkGameKeys()
if(ms < 0){
this.game.updateTime()
}else{
this.game.update()
if(!this.calibrationMode){
this.game.update()
}
if(!this.mainLoopRunning){
return
}
......@@ -137,7 +174,7 @@ class Controller{
if(Math.round(score.gauge / 2) - 1 >= 25){
if(score.bad === 0){
vp = "fullcombo"
this.playSoundMeka("v_fullcombo", 1.350)
this.playSound("v_fullcombo", 1.350)
}else{
vp = "clear"
}
......@@ -158,7 +195,11 @@ class Controller{
if(!fadeIn){
this.clean()
}
new SongSelect(false, fadeIn, this.touchEnabled)
if(this.calibrationMode){
new SettingsView(this.touchEnabled, false, null, "latency")
}else{
new SongSelect(false, fadeIn, this.touchEnabled)
}
}
restartSong(){
this.clean()
......@@ -166,20 +207,24 @@ class Controller{
new LoadSong(this.selectedSong, false, true, this.touchEnabled)
}else{
new Promise(resolve => {
var songObj = assets.songs.find(song => song.id === this.selectedSong.folder)
if(songObj.chart){
var reader = new FileReader()
var promise = pageEvents.load(reader).then(event => {
this.songData = event.target.result.replace(/\0/g, "").split("\n")
resolve()
})
if(this.selectedSong.type === "tja"){
reader.readAsText(songObj.chart, "sjis")
if(this.calibrationMode){
resolve()
}else{
var songObj = assets.songs.find(song => song.id === this.selectedSong.folder)
if(songObj.chart && songObj.chart !== "blank"){
var reader = new FileReader()
var promise = pageEvents.load(reader).then(event => {
this.songData = event.target.result.replace(/\0/g, "").split("\n")
resolve()
})
if(this.selectedSong.type === "tja"){
reader.readAsText(songObj.chart, "sjis")
}else{
reader.readAsText(songObj.chart)
}
}else{
reader.readAsText(songObj.chart)
resolve()
}
}else{
resolve()
}
}).then(() => {
var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled)
......@@ -187,25 +232,21 @@ class Controller{
})
}
}
playSound(id, time){
playSound(id, time, noSnd){
if(!this.drumSounds && (id === "neiro_1_don" || id === "neiro_1_ka" || id === "se_don" || id === "se_ka")){
return
}
var ms = Date.now() + (time || 0) * 1000
if(!(id in this.playedSounds) || ms > this.playedSounds[id] + 30){
assets.sounds[id + this.snd].play(time)
assets.sounds[id + (noSnd ? "" : this.snd)].play(time)
this.playedSounds[id] = ms
}
}
playSoundMeka(soundID, time){
var meka = ""
if(this.autoPlayEnabled && !this.multiplayer){
meka = "_meka"
}
this.playSound(soundID + meka, time)
}
togglePause(){
togglePause(forcePause, pauseMove, noSound){
if(this.multiplayer === 1){
this.syncWith.game.togglePause()
this.syncWith.game.togglePause(forcePause, pauseMove, noSound)
}
this.game.togglePause()
this.game.togglePause(forcePause, pauseMove, noSound)
}
getKeys(){
return this.keyboard.getKeys()
......
This diff is collapsed.
......@@ -94,7 +94,7 @@ class GameInput{
}
}
checkMenuKeys(){
if(!this.controller.multiplayer && !this.locked){
if(!this.controller.multiplayer && !this.locked && this.controller.view.pauseOptions.length !== 0){
var moveMenu = 0
var ms = this.game.getAccurateTime()
this.gamepadMenu.play((pressed, name) => {
......@@ -146,7 +146,7 @@ class GameInput{
this.checkKey("don_l", "menu", moveMenuConfirm)
this.checkKey("don_r", "menu", moveMenuConfirm)
if(moveMenu && this.game.isPaused()){
assets.sounds["se_ka"].play()
this.controller.playSound("se_ka", 0, true)
this.controller.view.pauseMove(moveMenu)
}
}
......@@ -197,11 +197,19 @@ class GameInput{
return
}
this.keyTime[name] = ms
var calibrationState = this.game.calibrationState
var calibration = calibrationState && !this.game.paused
if(name == "don_l" || name == "don_r"){
this.checkKeySound(name, "don")
if(calibration){
this.game.calibrationHit(ms)
}else{
this.checkKeySound(name, "don")
}
this.keyboardEvents++
}else if(name == "ka_l" || name == "ka_r"){
this.checkKeySound(name, "ka")
if(!calibration){
this.checkKeySound(name, "ka")
}
this.keyboardEvents++
}
}else{
......
......@@ -35,14 +35,20 @@ class LoadSong{
var song = this.selectedSong
var id = song.folder
var promises = []
assets.sounds["v_start"].play()
if(song.folder !== "calibration"){
assets.sounds["v_start"].play()
var songObj = assets.songs.find(song => song.id === id)
}else{
var songObj = {
"music": "muted",
"chart": "blank"
}
}
song.songBg = this.randInt(1, 5)
song.songStage = this.randInt(1, 3)
song.donBg = this.randInt(1, 6)
var songObj = assets.songs.find(song => song.id === id)
if(song.songSkin && song.songSkin.name){
var imgLoad = []
for(var type in song.songSkin){
......@@ -117,14 +123,18 @@ class LoadSong{
}
}))
if(songObj.chart){
var reader = new FileReader()
promises.push(pageEvents.load(reader).then(event => {
this.songData = event.target.result.replace(/\0/g, "").split("\n")
}))
if(song.type === "tja"){
reader.readAsText(songObj.chart, "sjis")
if(songObj.chart === "blank"){
this.songData = ""
}else{
reader.readAsText(songObj.chart)
var reader = new FileReader()
promises.push(pageEvents.load(reader).then(event => {
this.songData = event.target.result.replace(/\0/g, "").split("\n")
}))
if(song.type === "tja"){
reader.readAsText(songObj.chart, "sjis")
}else{
reader.readAsText(songObj.chart)
}
}
}else{
promises.push(loader.ajax(this.getSongPath(song)).then(data => {
......
......@@ -25,6 +25,7 @@
"A": {name: "daiDon", txt: strings.note.daiDon},
"B": {name: "daiKa", txt: strings.note.daiKa}
}
this.noteTypes_ex = strings.ex_note;
this.courseTypes = {
"0": "easy",
"1": "normal",
......@@ -122,7 +123,7 @@
return [string.slice(0, index), string.slice(index + delimiter.length)]
}
parseCircles(){
var meta = this.metadata[this.difficulty]
var meta = this.metadata[this.difficulty] || {}
var ms = (meta.offset || 0) * -1000 + this.offset
var bpm = Math.abs(meta.bpm) || 120
var scroll = 1
......@@ -148,7 +149,32 @@
var circles = []
var circleID = 0
var regexAZ = /[A-Z]/
var isAllDon = (note_chain, start_pos) => {
for (var i = start_pos; i < note_chain.length; ++i) {
var note = note_chain[i];
if (note && note.type !== "don" && note.type !== "daiDon") {
return false;
}
}
return true;
}
var checkChain = (note_chain, measure_length, is_last) => {
//console.log(note_chain, measure_length, is_last);
/*if (measure_length >= 24) {
for (var note of note_chain) {
note.text = this.noteTypes_ex[note.type][0];
}
} else { */
var alldon_pos = null;
for (var i = 0; i < note_chain.length - (is_last ? 1 : 0); ++i) {
var note = note_chain[i];
if (alldon_pos === null && is_last && isAllDon(note_chain, i)) {
alldon_pos = i;
}
note.text = this.noteTypes_ex[note.type][alldon_pos != null ? (i - alldon_pos) % 2 : 0];
}
//}
}
var pushMeasure = () => {
var note = currentMeasure[0]
if(note){
......@@ -183,9 +209,11 @@
var msPerMeasure = 60000 * measure / note.bpm
ms += msPerMeasure / currentMeasure.length
}
for(var i = 0; i < currentMeasure.length; i++){
var note_chain = [];
for (var i = 0; i < currentMeasure.length; i++){
//console.log(note_chain.length);
var note = currentMeasure[i]
if(note.type){
if (note.type) {
circleID++
var circleObj = new Circle({
id: circleID,
......@@ -200,13 +228,30 @@
branch: currentBranch,
section: note.section
})
if(lastDrumroll === note){
if (note.type === "don" || note.type === "ka" || note.type === "daiDon" || note.type === "daiKa") {
note_chain.push(circleObj);
} else {
if (note_chain.length > 1 && currentMeasure.length >= 8) {
checkChain(note_chain, currentMeasure.length, false);
}
note_chain = [];
}
if (lastDrumroll === note) {
lastDrumroll = circleObj
}
circles.push(circleObj)
} else if (!(currentMeasure.length >= 24 && (!currentMeasure[i + 1] || currentMeasure[i + 1].type))
&& !(currentMeasure.length >= 48 && (!currentMeasure[i + 2] || currentMeasure[i + 2].type || !currentMeasure[i + 3] || currentMeasure[i + 3].type))) {
if (note_chain.length > 1 && currentMeasure.length >= 8) {
checkChain(note_chain, currentMeasure.length, true);
}
note_chain = [];
}
}
if (note_chain.length > 1 && currentMeasure.length >= 8) {
checkChain(note_chain, currentMeasure.length, false);
}
}else{
var msPerMeasure = 60000 * measure / bpm
ms += msPerMeasure
......
......@@ -10,6 +10,14 @@ class Scoresheet{
this.canvas = document.getElementById("canvas")
this.ctx = this.canvas.getContext("2d")
var resolution = settings.getItem("resolution")
var noSmoothing = resolution === "low" || resolution === "lowest"
if(noSmoothing){
this.ctx.imageSmoothingEnabled = false
}
if(resolution === "lowest"){
this.canvas.style.imageRendering = "pixelated"
}
this.game = document.getElementById("game")
this.fadeScreen = document.createElement("div")
......@@ -28,8 +36,8 @@ class Scoresheet{
this.frame = 1000 / 60
this.numbers = "001122334455667788900112233445".split("")
this.draw = new CanvasDraw()
this.canvasCache = new CanvasCache()
this.draw = new CanvasDraw(noSmoothing)
this.canvasCache = new CanvasCache(noSmoothing)
this.keyboard = new Keyboard({
confirm: ["enter", "space", "esc", "don_l", "don_r"]
......@@ -105,7 +113,7 @@ class Scoresheet{
if(!p2.session){
this.state.screen = "scoresShown"
this.state.screenMS = this.getMS()
assets.sounds["neiro_1_don"].play()
this.controller.playSound("neiro_1_don", 0, true)
}
}
toSongsel(fromP2){
......@@ -114,7 +122,7 @@ class Scoresheet{
this.state.screen = "fadeOut"
this.state.screenMS = this.getMS()
if(!fromP2){
assets.sounds["neiro_1_don"].play()
this.controller.playSound("neiro_1_don", 0, true)
}
}
}
......
This diff is collapsed.
......@@ -5,6 +5,14 @@ class SongSelect{
loader.changePage("songselect", false)
this.canvas = document.getElementById("song-sel-canvas")
this.ctx = this.canvas.getContext("2d")
var resolution = settings.getItem("resolution")
var noSmoothing = resolution === "low" || resolution === "lowest"
if(noSmoothing){
this.ctx.imageSmoothingEnabled = false
}
if(resolution === "lowest"){
this.canvas.style.imageRendering = "pixelated"
}
this.songSkin = {
"selected": {
......@@ -209,13 +217,13 @@ class SongSelect{
}]
this.optionsList = [strings.none, strings.auto, strings.netplay]
this.draw = new CanvasDraw()
this.songTitleCache = new CanvasCache()
this.selectTextCache = new CanvasCache()
this.categoryCache = new CanvasCache()
this.difficultyCache = new CanvasCache()
this.sessionCache = new CanvasCache()
this.currentSongCache = new CanvasCache()
this.draw = new CanvasDraw(noSmoothing)
this.songTitleCache = new CanvasCache(noSmoothing)
this.selectTextCache = new CanvasCache(noSmoothing)
this.categoryCache = new CanvasCache(noSmoothing)
this.difficultyCache = new CanvasCache(noSmoothing)
this.sessionCache = new CanvasCache(noSmoothing)
this.currentSongCache = new CanvasCache(noSmoothing)
this.difficulty = [strings.easy, strings.normal, strings.hard, strings.oni]
this.difficultyId = ["easy", "normal", "hard", "oni", "ura"]
......@@ -236,6 +244,9 @@ class SongSelect{
fromTutorial = false
}
this.drumSounds = settings.getItem("latency").drumSounds
this.playedSounds = {}
var songIdIndex = -1
if(fromTutorial){
this.selectedSong = this.songs.findIndex(song => song.action === fromTutorial)
......@@ -254,7 +265,7 @@ class SongSelect{
}else if((!p2.session || fadeIn) && "selectedSong" in localStorage){
this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length - 1)
}
assets.sounds[songIdIndex !== -1 ? "v_diffsel" : "v_songsel"].play()
this.playSound(songIdIndex !== -1 ? "v_diffsel" : "v_songsel")
snd.musicGain.fadeOut()
this.playBgm(false)
}
......@@ -453,7 +464,7 @@ class SongSelect{
window.open(this.songs[this.selectedSong].maker.url)
}else if(moveBy === this.diffOptions.length + 4){
this.state.ura = !this.state.ura
assets.sounds["se_ka"].play()
this.playSound("se_ka")
if(this.selectedDiff === this.diffOptions.length + 4 && !this.state.ura){
this.state.move = -1
}
......@@ -581,7 +592,7 @@ class SongSelect{
var soundsDelay = Math.abs((scroll + resize) / moveBy)
for(var i = 0; i < Math.abs(moveBy) - 1; i++){
assets.sounds["se_ka"].play((resize + i * soundsDelay) / 1000)
this.playSound("se_ka", (resize + i * soundsDelay) / 1000)
}
this.pointer(false)
}
......@@ -605,7 +616,7 @@ class SongSelect{
this.state.move = moveBy
this.state.moveMS = this.getMS() - 500
this.state.locked = 1
assets.sounds["se_ka"].play()
this.playSound("se_ka")
}
}
......@@ -636,15 +647,15 @@ class SongSelect{
this.selectedDiff = this.diffOptions.length + 3
}
assets.sounds["se_don"].play()
this.playSound("se_don")
assets.sounds["v_songsel"].stop()
assets.sounds["v_diffsel"].play(0.3)
this.playSound("v_diffsel", 0.3)
pageEvents.send("song-select-difficulty", currentSong)
}else if(currentSong.action === "back"){
this.clean()
this.toTitleScreen()
}else if(currentSong.action === "random"){
assets.sounds["se_don"].play()
this.playSound("se_don")
this.state.locked = true
do{
var i = Math.floor(Math.random() * this.songs.length)
......@@ -681,7 +692,7 @@ class SongSelect{
this.state.moveHover = null
assets.sounds["v_diffsel"].stop()
assets.sounds["se_cancel"].play()
this.playSound("se_cancel")
}
this.clearHash()
pageEvents.send("song-select-back")
......@@ -690,7 +701,7 @@ class SongSelect{
this.clean()
var selectedSong = this.songs[this.selectedSong]
assets.sounds["v_diffsel"].stop()
assets.sounds["se_don"].play()
this.playSound("se_don")
try{
if(assets.customSongs){
......@@ -729,7 +740,7 @@ class SongSelect{
}
toOptions(moveBy){
if(!p2.session){
assets.sounds["se_ka"].play()
this.playSound("se_ka")
this.selectedDiff = 1
do{
this.state.options = this.mod(this.optionsList.length, this.state.options + moveBy)
......@@ -738,7 +749,7 @@ class SongSelect{
}
toTitleScreen(){
if(!p2.session){
assets.sounds["se_cancel"].play()
this.playSound("se_cancel")
this.clean()
setTimeout(() => {
new Titlescreen()
......@@ -746,21 +757,21 @@ class SongSelect{
}
}
toTutorial(){
assets.sounds["se_don"].play()
this.playSound("se_don")
this.clean()
setTimeout(() => {
new Tutorial(true)
}, 500)
}
toAbout(){
assets.sounds["se_don"].play()
this.playSound("se_don")
this.clean()
setTimeout(() => {
new About(this.touchEnabled)
}, 500)
}
toSettings(){
assets.sounds["se_don"].play()
this.playSound("se_don")
this.clean()
setTimeout(() => {
new SettingsView(this.touchEnabled)
......@@ -775,7 +786,7 @@ class SongSelect{
}else{
localStorage["selectedSong"] = this.selectedSong
assets.sounds["se_don"].play()
this.playSound("se_don")
this.clean()
setTimeout(() => {
new Session(this.touchEnabled)
......@@ -786,7 +797,7 @@ class SongSelect{
if(assets.customSongs){
assets.customSongs = false
assets.songs = assets.songsDefault
assets.sounds["se_don"].play()
this.playSound("se_don")
this.clean()
setTimeout(() => {
new SongSelect("browse", false, this.touchEnabled)
......@@ -1014,6 +1025,7 @@ class SongSelect{
var resize2 = changeSpeed - resize
var scroll = resize2 - resize - scrollDelay * 2
var elapsed = ms - this.state.moveMS
if(this.state.catJump || (this.state.move && ms > this.state.moveMS + resize2 - scrollDelay)){
var isJump = this.state.catJump
var previousSelectedSong = this.selectedSong
......@@ -2116,6 +2128,17 @@ class SongSelect{
}
}
playSound(id, time){
if(!this.drumSounds && (id === "se_don" || id === "se_ka" || id === "se_cancel")){
return
}
var ms = Date.now() + (time || 0) * 1000
if(!(id in this.playedSounds) || ms > this.playedSounds[id] + 30){
assets.sounds[id].play(time)
this.playedSounds[id] = ms
}
}
getMS(){
return Date.now()
}
......
......@@ -50,6 +50,22 @@
daiDrumroll: "連打(大)ーっ!!",
balloon: "ふうせん"
}
this.ex_note = {
don: [
"",
""
],
ka: [
""
],
daiDon: [
"ドン(大)",
"ドン(大)"
],
daiKa: [
"カッ(大)"
]
}
this.combo = "コンボ"
this.clear = "クリア"
this.good = ""
......@@ -127,11 +143,42 @@
b: "タイプB",
c: "タイプC"
},
latency: {
name: "Latency",
value: "Audio: %s, Video: %s",
calibration: "Latency Calibration",
audio: "Audio",
video: "Video",
drumSounds: "Drum Sounds"
},
on: "オン",
off: "オフ",
default: "既定値にリセット",
ok: "OK"
}
this.calibration = {
title: "Latency Calibration",
ms: "%sms",
back: "Back to Settings",
retryPrevious: "Retry Previous",
start: "Start",
finish: "Finish",
audioHelp: {
title: "Audio Latency Calibration",
content: "Listen to a sound playing in the background.\n\nHit the surface of the drum (%s or %s) as you hear it!",
contentAlt: "Listen to a sound playing in the background.\n\nHit the surface of the drum as you hear it!"
},
audioComplete: "Audio Latency Calibration completed!",
videoHelp: {
title: "Video Latency Calibration",
content: "This time there will be no sounds.\n\nInstead, watch for notes blinking on the circle-shaped frame, hit the drum as they appear!"
},
videoComplete: "Video Latency Calibration completed!",
results: {
title: "Latency Calibration Results",
content: "Audio latency: %s\nVideo latency: %s\n\nYou can configure these latency values in the settings."
}
}
this.browserSupport = {
browserWarning: "サポートされていないブラウザを実行しています (%s)",
details: "詳しく",
......@@ -195,6 +242,22 @@ function StringsEn(){
daiDrumroll: "DRUM ROLLー!!",
balloon: "Balloon"
}
this.ex_note = {
don: [
"Do",
"Do"
],
ka: [
"Ka"
],
daiDon: [
"DON",
"DON"
],
daiKa: [
"KA"
]
}
this.combo = "Combo"
this.clear = "Clear"
this.good = "GOOD"
......@@ -272,11 +335,42 @@ function StringsEn(){
b: "Type B",
c: "Type C"
},
latency: {
name: "Latency",
value: "Audio: %s, Video: %s",
calibration: "Latency Calibration",
audio: "Audio",
video: "Video",
drumSounds: "Drum Sounds"
},
on: "On",
off: "Off",
default: "Reset to Defaults",
ok: "OK"
}
this.calibration = {
title: "Latency Calibration",
ms: "%sms",
back: "Back to Settings",
retryPrevious: "Retry Previous",
start: "Start",
finish: "Finish",
audioHelp: {
title: "Audio Latency Calibration",
content: "Listen to a sound playing in the background.\n\nHit the surface of the drum (%s or %s) as you hear it!",
contentAlt: "Listen to a sound playing in the background.\n\nHit the surface of the drum as you hear it!"
},
audioComplete: "Audio Latency Calibration completed!",
videoHelp: {
title: "Video Latency Calibration",
content: "This time there will be no sounds.\n\nInstead, watch for notes blinking on the circle-shaped frame, hit the drum as they appear!"
},
videoComplete: "Video Latency Calibration completed!",
results: {
title: "Latency Calibration Results",
content: "Audio latency: %s\nVideo latency: %s\n\nYou can configure these latency values in the settings."
}
}
this.browserSupport = {
browserWarning: "You are running an unsupported browser (%s)",
details: "Details...",
......@@ -340,6 +434,22 @@ function StringsCn(){
daiDrumroll: "连打(大)ー!!",
balloon: "气球"
}
this.ex_note = {
don: [
"",
""
],
ka: [
""
],
daiDon: [
"咚(大)",
"咚(大)"
],
daiKa: [
"咔(大)"
]
}
this.combo = "连段"
this.clear = "通关"
this.good = ""
......@@ -417,11 +527,42 @@ function StringsCn(){
b: "类型B",
c: "类型C"
},
latency: {
name: "Latency",
value: "Audio: %s, Video: %s",
calibration: "Latency Calibration",
audio: "Audio",
video: "Video",
drumSounds: "Drum Sounds"
},
on: "",
off: "",
default: "重置为默认值",
ok: "确定"
}
this.calibration = {
title: "Latency Calibration",
ms: "%sms",
back: "Back to Settings",
retryPrevious: "Retry Previous",
start: "Start",
finish: "Finish",
audioHelp: {
title: "Audio Latency Calibration",
content: "Listen to a sound playing in the background.\n\nHit the surface of the drum (%s or %s) as you hear it!",
contentAlt: "Listen to a sound playing in the background.\n\nHit the surface of the drum as you hear it!"
},
audioComplete: "Audio Latency Calibration completed!",
videoHelp: {
title: "Video Latency Calibration",
content: "This time there will be no sounds.\n\nInstead, watch for notes blinking on the circle-shaped frame, hit the drum as they appear!"
},
videoComplete: "Video Latency Calibration completed!",
results: {
title: "Latency Calibration Results",
content: "Audio latency: %s\nVideo latency: %s\n\nYou can configure these latency values in the settings."
}
}
this.browserSupport = {
browserWarning: "You are running an unsupported browser (%s)",
details: "Details...",
......@@ -485,6 +626,22 @@ function StringsTw(){
daiDrumroll: "連打(大)ー!!",
balloon: "氣球"
}
this.ex_note = {
don: [
"",
""
],
ka: [
""
],
daiDon: [
"咚(大)",
"咚(大)"
],
daiKa: [
"咔(大)"
]
}
this.combo = "連段"
this.clear = "通關"
this.good = ""
......@@ -562,11 +719,42 @@ function StringsTw(){
b: "類型B",
c: "類型C"
},
latency: {
name: "Latency",
value: "Audio: %s, Video: %s",
calibration: "Latency Calibration",
audio: "Audio",
video: "Video",
drumSounds: "Drum Sounds"
},
on: "",
off: "",
default: "重置為默認值",
ok: "確定"
}
this.calibration = {
title: "Latency Calibration",
ms: "%sms",
back: "Back to Settings",
retryPrevious: "Retry Previous",
start: "Start",
finish: "Finish",
audioHelp: {
title: "Audio Latency Calibration",
content: "Listen to a sound playing in the background.\n\nHit the surface of the drum (%s or %s) as you hear it!",
contentAlt: "Listen to a sound playing in the background.\n\nHit the surface of the drum as you hear it!"
},
audioComplete: "Audio Latency Calibration completed!",
videoHelp: {
title: "Video Latency Calibration",
content: "This time there will be no sounds.\n\nInstead, watch for notes blinking on the circle-shaped frame, hit the drum as they appear!"
},
videoComplete: "Video Latency Calibration completed!",
results: {
title: "Latency Calibration Results",
content: "Audio latency: %s\nVideo latency: %s\n\nYou can configure these latency values in the settings."
}
}
this.browserSupport = {
browserWarning: "You are running an unsupported browser (%s)",
details: "Details...",
......@@ -630,6 +818,22 @@ function StringsKo(){
daiDrumroll: "연타(대)ー!!",
balloon: "풍선"
}
this.ex_note = {
don: [
"",
""
],
ka: [
""
],
daiDon: [
"쿵(대)",
"쿵(대)"
],
daiKa: [
"딱(대)"
]
}
this.combo = "콤보"
this.clear = "클리어"
this.good = "얼쑤"
......@@ -707,11 +911,42 @@ function StringsKo(){
b: "타입 B",
c: "타입 C"
},
latency: {
name: "Latency",
value: "Audio: %s, Video: %s",
calibration: "Latency Calibration",
audio: "Audio",
video: "Video",
drumSounds: "Drum Sounds"
},
on: "",
off: "오프",
default: "기본값으로 재설정",
ok: "확인"
}
this.calibration = {
title: "Latency Calibration",
ms: "%sms",
back: "Back to Settings",
retryPrevious: "Retry Previous",
start: "Start",
finish: "Finish",
audioHelp: {
title: "Audio Latency Calibration",
content: "Listen to a sound playing in the background.\n\nHit the surface of the drum (%s or %s) as you hear it!",
contentAlt: "Listen to a sound playing in the background.\n\nHit the surface of the drum as you hear it!"
},
audioComplete: "Audio Latency Calibration completed!",
videoHelp: {
title: "Video Latency Calibration",
content: "This time there will be no sounds.\n\nInstead, watch for notes blinking on the circle-shaped frame, hit the drum as they appear!"
},
videoComplete: "Video Latency Calibration completed!",
results: {
title: "Latency Calibration Results",
content: "Audio latency: %s\nVideo latency: %s\n\nYou can configure these latency values in the settings."
}
}
this.browserSupport = {
browserWarning: "You are running an unsupported browser (%s)",
details: "Details...",
......
This diff is collapsed.
......@@ -7,8 +7,8 @@
<div id="link-issues" class="taibtn stroke-sub link-btn" alt="Issues">
<a target="_blank">Issues</a>
</div>
<div id="link-email" class="taibtn stroke-sub link-btn" alt="taiko@bui.pm">
<a href="mailto:taiko@bui.pm">taiko@bui.pm</a>
<div id="link-email" class="taibtn stroke-sub link-btn">
<a></a>
</div>
</div>
<div class="view-end-button taibtn stroke-sub selected"></div>
......
......@@ -11,5 +11,4 @@
<div id="touch-buttons">
<div id="touch-full-btn"></div><div id="touch-pause-btn"></div>
</div>
<div id="cursor"></div>
</div>
......@@ -20,5 +20,15 @@
<div class="view-end-button taibtn stroke-sub selected"></div>
</div>
</div>
<div class="view-outer shadow-outer" id="settings-latency">
<div class="view">
<div class="view-title stroke-sub"></div>
<div class="view-content"></div>
<div class="left-buttons">
<div id="latency-default" class="taibtn stroke-sub"></div>
</div>
<div class="view-end-button taibtn stroke-sub"></div>
</div>
</div>
</div>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment