From 3ffc786989f5c822f5c887a6dc1fab44673d19e3 Mon Sep 17 00:00:00 2001 From: Mal Date: Mon, 24 Feb 2020 00:19:21 +0100 Subject: [PATCH] TextBox implemented and cleaning. --- index.html | 7 +- js/FrameRateMeasurer.js | 2 - js/TextBox.js | 106 +++++++++++++++++++++++ js/TextLine.js | 87 +++++++++++++++++++ js/UrlParam.js | 1 - js/module.js | 25 +++++- tilorswift/js/dialog/DialogNewTerrain.js | 1 - 7 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 js/TextBox.js create mode 100644 js/TextLine.js diff --git a/index.html b/index.html index f2f7846..14c2407 100644 --- a/index.html +++ b/index.html @@ -4,11 +4,16 @@ Mr. Crocs Adventures diff --git a/js/FrameRateMeasurer.js b/js/FrameRateMeasurer.js index 8240713..97d3533 100644 --- a/js/FrameRateMeasurer.js +++ b/js/FrameRateMeasurer.js @@ -79,8 +79,6 @@ export default class FrameRateMeasurer } ); - console.log(this.frameDurations); - return closestDistance.frameRate; } } \ No newline at end of file diff --git a/js/TextBox.js b/js/TextBox.js new file mode 100644 index 0000000..1eedfe3 --- /dev/null +++ b/js/TextBox.js @@ -0,0 +1,106 @@ +import TextLine from "./TextLine.js"; + +export default class TextBox +{ + constructor(text, width, context) + { + this.text = text; + this.width = width; + this.colorText = 'red'; + this.colorShadow = 'black'; + this.colorBorder = 'black'; + this.hasShadow = false; + this.hasBorder = false; + this.font = 'Silkscreen'; + this.textSize = 32; + this.alignment = 0; + this.verticalAlignment = 'top'; + this.lines = []; + + this.updateLines(width, context); + } + + updateLines(width, context) + { + context.font = this.textSize + 'px ' + this.font; + this.lines = this.getLinesForWidth(this.text, context, width) + } + + animate(msForChar = 100) + { + let milliseconds = 0; + + for (let l = 0; l < this.lines.length; l++) { + this.lines[l].chars = 0; + setTimeout( + () => { + this.lines[l].animate(msForChar); + }, milliseconds + ); + + milliseconds += this.lines[l].text.length * msForChar; + } + } + + draw(context, x, y) + { + if (this.verticalAlignment === 'bottom') { + let currentHeight = y; + + for (let l = this.lines.length - 1; l >= 0; l--) { + if (this.lines[l].chars > 0) { + this.lines[l].draw(context, x, currentHeight); + currentHeight -= this.textSize; + } + } + + return; + } + + this.lines.forEach( + (line, index) => { + line.draw(context, x, y + this.textSize * index); + } + ) + } + + getLinesForWidth(text, context, width) + { + let words = text.split(' '); + let lines = []; + let buffer = words[0]; + + for (let w = 1; w < words.length; w++) { + let bufferNew = buffer === '' ? words[w] : buffer + ' ' + words[w]; + + if (context.measureText(bufferNew).width > width) { + lines.push(this.getLine(buffer)); + bufferNew = words[w]; + } + + buffer = bufferNew; + } + + if (buffer !== '') { + lines.push(this.getLine(buffer)); + } + + return lines; + } + + getLine(text) + { + let line = new TextLine(text); + + line.font = this.font; + line.size = this.textSize; + line.colorText = this.colorText; + line.colorShadow = this.colorShadow; + line.alignment = this.alignment; + line.hasShadow = this.hasShadow; + line.hasBorder = this.hasBorder; + line.colorBorder = this.colorBorder; + + return line; + } +} \ No newline at end of file diff --git a/js/TextLine.js b/js/TextLine.js new file mode 100644 index 0000000..a7e8adb --- /dev/null +++ b/js/TextLine.js @@ -0,0 +1,87 @@ +export default class TextLine +{ + constructor(text) + { + this.LEFT = 0; + this.CENTER = 1; + this.RIGHT = 2; + this.text = text; + this.estimatedTextWidth = null; + this.colorText = 'red'; + this.colorShadow = 'black'; + this.colorBorder = 'black'; + this.font = 'sans-serif'; + this.alphaText = 1.0; + this.size = 32; + this.alignment = this.LEFT; + this.chars = this.text.length; + this.hasShadow = false; + this.hasBorder = false; + } + + animate(msPerChar = 100) + { + this.chars = 0; + + let process = setInterval( + () => { + this.chars++; + + if (this.chars === this.text.length) { + clearInterval(process); + } + }, msPerChar + ); + } + + draw(context, x, y) + { + context.font = this.size + 'px ' + this.font; + context.globalAlpha = this.alphaText; + + if (this.estimatedTextWidth === null) { + this.estimatedTextWidth = Math.ceil(context.measureText(this.text).width); + } + + switch (this.alignment) { + case this.LEFT: + break; + case this.CENTER: + x -= this.estimatedTextWidth * 0.5; + break; + case this.RIGHT: + x -= this.estimatedTextWidth; + break; + } + + this.drawShadow(context, x, y); + + let text = this.text; + + if (this.chars !== null && this.chars < this.text.length) { + text = this.text.substr(0, this.chars); + } + + context.fillStyle = this.colorText; + context.fillText(text, x, y + this.size); + + this.drawBorder(context, x, y, text); + } + + drawBorder(context, x, y, text) + { + if (this.hasBorder) { + context.strokeStyle = this.colorBorder; + context.strokeWidth = '1px'; + context.strokeText(text, x, y + this.size); + } + } + + drawShadow(context, x, y) + { + if (this.hasShadow) { + context.fillStyle = this.colorShadow; + context.fillText(this.text.substr(0, this.chars), x + 2, y + this.size + 2); + } + } +} \ No newline at end of file diff --git a/js/UrlParam.js b/js/UrlParam.js index fbdde6f..08236ac 100644 --- a/js/UrlParam.js +++ b/js/UrlParam.js @@ -3,7 +3,6 @@ export default class UrlParam constructor() { this.url = document.location.toString(); - console.log(this.url); this.params = UrlParam.getParamsFromUrl(this.url); } diff --git a/js/module.js b/js/module.js index 0c3ae7a..18f0113 100644 --- a/js/module.js +++ b/js/module.js @@ -12,6 +12,7 @@ import ImageLoader from "./ImageLoader.js"; import Level from "./Level.js"; import InterfaceEvent from "./events/InterfaceEvent.js"; import UrlParam from "./UrlParam.js"; +import TextBox from "./TextBox.js"; function MainLoop(timestamp) { @@ -101,11 +102,14 @@ function MainLoop(timestamp) /* Drawing */ if (timestamp - lastRendered >= frameDuration) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); - architecture.draw(context, camera); mrCroc.draw(context, camera); gisela.draw(context, camera); + if (gameFinished) { + textBoxGameFinished.draw(context, window.innerWidth * 0.5, window.innerHeight - 100); + } + lastRendered = timestamp; } @@ -118,8 +122,7 @@ function MainLoop(timestamp) KeyJump.pressed = false; lastTimestamp = undefined; lastRendered = undefined; - - alert('Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."'); + textBoxGameFinished.animate(); } window.requestAnimationFrame(MainLoop); @@ -153,6 +156,7 @@ let mrCroc, gisela, architecture; let camera = new Camera(); let gameFinished = false; let hasPlayerLeftArchitecture = false; +let textBoxGameFinished; let KeyLeft = new Key('ArrowLeft'); let KeyRight = new Key('ArrowRight'); @@ -192,6 +196,20 @@ window.addEventListener( ); context = canvas.getContext('2d'); + textBoxGameFinished = new TextBox( + 'Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."', + window.innerWidth - 40, + context + ); + textBoxGameFinished.font = 'Silkscreen'; + textBoxGameFinished.verticalAlignment = 'bottom'; + textBoxGameFinished.alignment = 1; + textBoxGameFinished.hasShadow = true; + textBoxGameFinished.textSize = 48; + textBoxGameFinished.hasBorder = true; + textBoxGameFinished.colorText = 'yellow'; + textBoxGameFinished.colorBorder = 'black'; + textBoxGameFinished.updateLines(window.innerWidth - 40, context); architecture = RetroArchitecture.createFromData(level); camera.borderRight = architecture.columns * architecture.tileWidth; @@ -206,7 +224,6 @@ window.addEventListener( window.addEventListener( InterfaceEvent.FRAME_RATE_MEASURED, (event) => { - console.log(event); fps = event.frameRate; frameDuration = 1000 / fps; window.requestAnimationFrame(MainLoop); diff --git a/tilorswift/js/dialog/DialogNewTerrain.js b/tilorswift/js/dialog/DialogNewTerrain.js index cc3051b..244079b 100644 --- a/tilorswift/js/dialog/DialogNewTerrain.js +++ b/tilorswift/js/dialog/DialogNewTerrain.js @@ -31,7 +31,6 @@ export default class DialogNewTerrain extends Dialog TilorswiftEvent.TILESET_SELECTED, (event) => { this.terrainIndex = event.tilesetIndex; - console.log(event.tilesetIndex); } ); }