diff --git a/public/index.html b/public/index.html index c6524f9..e40cd8e 100644 --- a/public/index.html +++ b/public/index.html @@ -49,6 +49,7 @@ + diff --git a/public/src/css/titlescreen.css b/public/src/css/titlescreen.css index 95ef9b0..2d8efbb 100644 --- a/public/src/css/titlescreen.css +++ b/public/src/css/titlescreen.css @@ -24,7 +24,7 @@ height: auto; } .click-to-continue{ - position:absolute; + position: absolute; bottom: 10%; color: #fff; font-size: 8vmin; @@ -34,6 +34,8 @@ } .click-to-continue::before{ -webkit-text-stroke: 0.25em #f00; - filter: blur(0.3vmin); left: auto; } +#screen:not(.disable-blur) .click-to-continue::before{ + filter: blur(0.3vmin); +} diff --git a/public/src/js/canvasdraw.js b/public/src/js/canvasdraw.js index 41c0cc3..7786cb7 100644 --- a/public/src/js/canvasdraw.js +++ b/public/src/js/canvasdraw.js @@ -95,10 +95,13 @@ ctx.save() - ctx.shadowColor = "rgba(0, 0, 0, 0.5)" - ctx.shadowBlur = 10 - ctx.shadowOffsetX = 5 - ctx.shadowOffsetY = 5 + this.shadow({ + ctx: ctx, + fill: "rgba(0, 0, 0, 0.5)", + blur: 10, + x: 5, + y: 5 + }) ctx.fillStyle = "#000" ctx.fillRect(x, y, w, h) @@ -454,11 +457,14 @@ action = "fillText" } if(layer.shadow){ - ctx.save() - ctx.shadowOffsetX = layer.shadow[0] - ctx.shadowOffsetY = layer.shadow[1] - ctx.shadowBlur = layer.shadow[2] - ctx.shadowColor = "rgba(0, 0, 0, " + (1 / (layer.shadow[3] || 2)) + ")" + ctx.save() + this.shadow({ + ctx: ctx, + fill: "rgba(0, 0, 0, " + (1 / (layer.shadow[3] || 2)) + ")", + blur: layer.shadow[2], + x: layer.shadow[0], + y: layer.shadow[1] + }) } var offsetX = 0 for(let symbol of drawn){ @@ -625,8 +631,11 @@ ctx.save() ctx.fillStyle = config.songSel ? "#fff" : "#f72568" if(config.songSel){ - ctx.shadowColor = "#fff" - ctx.shadowBlur = 10 + this.shadow({ + ctx: ctx, + fill: "#fff", + blur: 10 + }) ctx.translate(config.x - 9, config.y - 9) }else{ ctx.translate(config.x - 10.5, config.y - 9.5) @@ -702,7 +711,9 @@ ctx.save() ctx.strokeStyle = "#fff" ctx.lineWidth = 35 - ctx.filter = "blur(1.5px)" + if(!disableBlur){ + ctx.filter = "blur(1.5px)" + } ctx.stroke(this.crownPath) ctx.restore() @@ -758,6 +769,24 @@ } } + shadow(config){ + if(!disableBlur){ + var ctx = config.ctx + if(config.fill){ + ctx.shadowColor = config.fill + } + if(config.blur){ + ctx.shadowBlur = config.blur + } + if(config.x){ + ctx.shadowOffsetX = config.x + } + if(config.y){ + ctx.shadowOffsetY = config.y + } + } + } + getMS(){ return +new Date } diff --git a/public/src/js/canvastest.js b/public/src/js/canvastest.js new file mode 100644 index 0000000..f9f3580 --- /dev/null +++ b/public/src/js/canvastest.js @@ -0,0 +1,144 @@ +class CanvasTest{ + constructor(){ + this.canvas = document.createElement("canvas") + var pixelRatio = window.devicePixelRatio || 1 + var width = innerWidth * pixelRatio + var height = innerHeight * pixelRatio + this.canvas.width = width + this.canvas.height = height + this.ctx = this.canvas.getContext("2d") + this.ctx.scale(pixelRatio, pixelRatio) + this.draw = new CanvasDraw() + this.font = "serif" + + this.songAsset = { + marginLeft: 18, + marginTop: 90, + width: 82, + height: 452, + border: 6, + innerBorder: 8 + } + } + blurPerformance(){ + return new Promise(resolve => { + requestAnimationFrame(() => { + var ctx = this.ctx + ctx.save() + var lastIteration = this.blurIteration() + var frameTime = [] + + for(var i = 0; i < 10; i++){ + lastIteration = lastIteration.then(ms => { + frameTime.push(ms) + return this.blurIteration() + }) + } + + lastIteration.then(() => { + ctx.restore() + resolve(frameTime.reduce((a, b) => a + b) / frameTime.length) + }) + }) + }) + } + blurIteration(){ + return new Promise(resolve => { + requestAnimationFrame(() => { + var startTime = +new Date + var ctx = this.ctx + ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) + + for(var x = 0; x < this.canvas.width; x += this.songAsset.width + this.songAsset.marginLeft){ + this.draw.songFrame({ + ctx: ctx, + x: x, + y: this.songAsset.marginTop, + width: this.songAsset.width, + height: this.songAsset.height, + border: this.songAsset.border, + innerBorder: this.songAsset.innerBorder, + background: "#efb058", + borderStyle: ["#ffe7bd", "#c68229"], + innerContent: () => {} + }) + } + + for(var i = 0; i < 2; i++){ + this.draw.layeredText({ + ctx: ctx, + text: "I am a text", + fontSize: 48, + fontFamily: this.font, + x: 23 + 300 * i, + y: 15 + }, [ + {x: -2, y: -2, outline: "#000", letterBorder: 22}, + {}, + {x: 2, y: 2, shadow: [2, 2, 7]}, + {x: 2, y: 2, outline: "#ad1516", letterBorder: 10}, + {x: -2, y: -2, outline: "#ff797b"}, + {outline: "#f70808"}, + {fill: "#fff", shadow: [-1, 1, 3, 1.5]} + ]) + } + resolve((+new Date) - startTime) + }) + }) + } + drawAllImages(){ + return new Promise(resolve => { + requestAnimationFrame(() => { + var ctx = this.ctx + ctx.save() + ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) + + for(var name in assets.image){ + ctx.drawImage(assets.image[name], 0, 0) + } + + var comboCount = 765 + var comboX = 100 + var comboY = 100 + var fontSize = 120 + this.ctx.font = "normal " + fontSize + "px TnT" + this.ctx.textAlign = "center" + this.ctx.strokeStyle = "#000" + this.ctx.lineWidth = fontSize / 10 + var glyph = this.ctx.measureText("0").width + var comboText = comboCount.toString().split("") + for(var i in comboText){ + var textX = comboX + glyph * (i - (comboText.length - 1) / 2) + if(comboCount >= 100){ + var grd = this.ctx.createLinearGradient( + textX - glyph * 0.2, + comboY - fontSize * 0.8, + textX + glyph * 0.2, + comboY - fontSize * 0.2 + ) + grd.addColorStop(0, "#f00") + grd.addColorStop(1, "#fe0") + this.ctx.fillStyle = grd + }else{ + this.ctx.fillStyle = "#fff" + } + this.strokeFillText(comboText[i], + textX, + comboY + ) + } + + ctx.restore() + resolve() + }) + }) + } + strokeFillText(text, x, y){ + this.ctx.strokeText(text, x, y) + this.ctx.fillText(text, x, y) + } + clean(){ + delete this.ctx + delete this.canvas + } +} diff --git a/public/src/js/keyboard.js b/public/src/js/keyboard.js index 057de33..2ff1188 100644 --- a/public/src/js/keyboard.js +++ b/public/src/js/keyboard.js @@ -34,8 +34,8 @@ class Keyboard{ "cancel": ["a"], } menuBtn[this.kbd["confirm"]] = ["b", "ls", "rs"] - menuBtn[this.kbd["previous"]] = ["u", "l", "lb", "lt"], - menuBtn[this.kbd["next"]] = ["d", "r", "rb", "rt"] + menuBtn[this.kbd["previous"]] = ["u", "l", "lb", "lt", "lsu", "lsl"], + menuBtn[this.kbd["next"]] = ["d", "r", "rb", "rt", "lsd", "lsr"] menuBtn[this.kbd["pause"]] = ["start"] this.gamepadMenu = new Gamepad(menuBtn) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index 2270925..2b6307b 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -3,6 +3,8 @@ class Loader{ this.callback = callback this.loadedAssets = 0 this.assetsDiv = document.getElementById("assets") + this.canvasTest = new CanvasTest() + p2 = new P2Connection() this.ajax("src/views/loader.html").then(this.run.bind(this)) } run(page){ @@ -70,8 +72,6 @@ class Loader{ assets.audioSfxLoud.forEach(name => { this.promises.push(this.loadSound(name, snd.sfxLoudGain)) }) - - p2 = new P2Connection() this.promises.push(this.ajax("/api/songs").then(songs => { assets.songs = JSON.parse(songs) @@ -84,13 +84,24 @@ class Loader{ })) }) + this.promises.push(this.canvasTest.blurPerformance().then(result => { + if(result > 1000 / 50){ + // Less than 50 fps with blur enabled + disableBlur = true + this.screen.classList.add("disable-blur") + } + })) + this.promises.forEach(promise => { promise.then(this.assetLoaded.bind(this)) }) Promise.all(this.promises).then(() => { - this.clean() - this.callback() + this.canvasTest.drawAllImages().then(() => { + this.canvasTest.clean() + this.clean() + this.callback() + }) }, this.errorMsg.bind(this)) }) @@ -122,7 +133,7 @@ class Loader{ } } changePage(name){ - document.getElementById("screen").innerHTML = assets.pages[name] + this.screen.innerHTML = assets.pages[name] } ajax(url, customRequest){ return new Promise((resolve, reject) => { diff --git a/public/src/js/main.js b/public/src/js/main.js index 19254a9..b78130e 100644 --- a/public/src/js/main.js +++ b/public/src/js/main.js @@ -24,6 +24,7 @@ function toggleFullscreen(){ var pageEvents = new PageEvents() var snd = {} var p2 +var disableBlur = false var loader = new Loader(() => { new Titlescreen() }) diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index 61d1fa4..f2ad090 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -2,22 +2,35 @@ class Titlescreen{ constructor(){ loader.changePage("titlescreen") this.titleScreen = document.getElementById("title-screen") - pageEvents.keyOnce(this, 13, "down").then(this.onPressed.bind(this)) - pageEvents.once(this.titleScreen, "mousedown").then(this.onPressed.bind(this)) + pageEvents.keyAdd(this, "all", "down", this.keyDown.bind(this)) + pageEvents.add(this.titleScreen, "mousedown", this.onPressed.bind(this)) pageEvents.once(this.titleScreen, "touchstart").then(this.onPressed.bind(this)) assets.sounds["title"].play() this.gamepad = new Gamepad({ - "start": ["a", "b", "x", "y", "start", "ls", "rs"] + "13": ["a", "b", "x", "y", "start", "ls", "rs"] }, pressed => { if(pressed){ this.onPressed() } }) } + keyDown(event, code){ + if(!code){ + code = event.keyCode + } + if(code == 13 || code == 32 || code == 86 || code == 66){ + // Enter, Space, V, B + this.onPressed() + } + } onPressed(event){ - if(event && event.type === "touchstart"){ - event.preventDefault() - this.touched = true + if(event){ + if(event.type === "touchstart"){ + event.preventDefault() + this.touched = true + }else if(event.type === "mousedown" && event.which !== 1){ + return + } } this.titleScreen.style.cursor = "auto" this.clean() @@ -34,7 +47,7 @@ class Titlescreen{ clean(){ this.gamepad.clean() assets.sounds["title"].stop() - pageEvents.keyRemove(this, 13) + pageEvents.keyRemove(this, "all") pageEvents.remove(this.titleScreen, "mousedown") pageEvents.remove(this.titleScreen, "touchstart") delete this.titleScreen diff --git a/public/src/js/view.js b/public/src/js/view.js index e60a3f0..0151369 100644 --- a/public/src/js/view.js +++ b/public/src/js/view.js @@ -325,7 +325,7 @@ class View{ this.ctx.strokeStyle = "#000" this.ctx.lineWidth = fontSize / 10 var glyph = this.ctx.measureText("0").width - var comboText = this.controller.getCombo().toString().split("") + var comboText = comboCount.toString().split("") for(var i in comboText){ var textX = comboX + glyph * (i - (comboText.length - 1) / 2) if(comboCount >= 100){ @@ -673,7 +673,7 @@ class View{ this.diffX, this.diffY, this.diffW, this.diffH ) - if(this.controller.autoPlayEnabled){ + if(this.controller.autoPlayEnabled && !this.controller.multiplayer){ this.ctx.drawImage(assets.image["badge_auto"], this.diffX + this.diffW * 0.71, this.diffY + this.diffH * 0.01, this.diffH * 0.3, this.diffH * 0.3