diff --git a/Css/main.css b/Css/main.css index de7c29e..ac834f0 100644 --- a/Css/main.css +++ b/Css/main.css @@ -47,15 +47,15 @@ #text-container { position: absolute; height: 100%; width: 100%; font-family: 'FOT-RodinNTLGPro'; } -#text-container #title { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 20px; } +#text-container #title { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 20px; transition: opacity 0.3s; } -#text-container #diva { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 34px; } +#text-container #diva { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 34px; transition: opacity 0.3s; } #text-container #dialog-box { box-sizing: border-box; position: absolute; bottom: 0; text-align: left; width: 100%; height: 200px; } -#text-container #main-ui-img { width: 100%; } +#text-container #main-ui-img { width: 100%; transition: opacity 0.1s; } -#dialog-box { color: white; font-weight: bold; text-shadow: 1px 1px 6px black; } +#dialog-box { color: white; font-weight: bold; text-shadow: 1px 1px 6px black; transition: opacity 0.1s; } #dialog-box #character { position: absolute; top: -5px; left: 70px; font-size: 30px; } diff --git a/Js/Common.js b/Js/Common.js index 5b9fdf1..80c2d41 100644 --- a/Js/Common.js +++ b/Js/Common.js @@ -1,6 +1,6 @@ 'use strict'; -var rootUrl = `${window.location.protocol}//${window.location.host}/` +var rootUrl = `${window.location.protocol}//${window.location.host}/`; class commonFunctions { static getFileText(file) { @@ -37,10 +37,10 @@ class commonFunctions { } else if(!line) { return undefined; } else { - var split = line.split('\t'); - var newEntry = {}; + let split = line.split('\t'); + let newEntry = {}; for(let i = 0; i < split.length; ++i) { - var x = split[i]; + let x = split[i]; newEntry[headers[i]] = x; } return newEntry; @@ -61,4 +61,25 @@ class commonFunctions { return 0xFFFFFF; } } + + static convertUtageTextTags(text) { + text = text.replace(/|<\/speed>/g, ""); + text = text.replace("\\n", "
") + return text; + } + + static getAnchorFromCharPivot(pivot) { + let x = 0.5; + let y = 0.5; + let sp = pivot.split(" "); + for(let p of sp) { + if(p.startsWith("x=")) { + x = Number(p.substring(2)); + } else if(p.startsWith("y=")) { + y = Number(p.substring(2)); + y = 1 - y; + } + } + return {x, y}; + } } \ No newline at end of file diff --git a/Js/Player.js b/Js/Player.js index 27ebf3c..8075435 100644 --- a/Js/Player.js +++ b/Js/Player.js @@ -10,7 +10,8 @@ class Player { this.resolutionScale = 1; this.baseFps = 60; //I am assuming that PIXI is going to stay as keeping 60fps = delta1. this.blackBackSp = undefined; - this.currentCharacters = []; + this.currentCharacters = {}; + this.lastCharOffLayer = undefined; this.layers = {}; this.sprites = {}; this.currentCommand = undefined; @@ -19,6 +20,7 @@ class Player { this.waitTime = 0; this.lerpTargets = []; this.bgLayerName = "背景"; + this.defaultCharPattern = 'すまし'; this.titleWaitTime = 1; this.manualNext = false; this.hasMoreText = false; @@ -60,14 +62,17 @@ class Player { //Text case "": //Character Text - if(c.Arg1 && c.Arg2 && c.Arg2 != "" && c.Text && - this.utage.characterInfo[c.Arg1] && this.utage.characterInfo[c.Arg1][c.Arg2]) { - if(!this.loader.resources[`char|${c.Arg1}|${c.Arg2}`]) { - this.loader.add(`char|${c.Arg1}|${c.Arg2}`, this.utage.characterInfo[c.Arg1][c.Arg2].FileName); + let Arg2 = c.Arg2; + if(c.Arg1 && this.utage.characterInfo[c.Arg1] && !Arg2) { + Arg2 = this.defaultCharPattern; + } + if(this.utage.characterInfo[c.Arg1] && this.utage.characterInfo[c.Arg1][Arg2] && Arg2 && Arg2 != "") { + if(!this.loader.resources[`char|${c.Arg1}|${Arg2}`]) { + this.loader.add(`char|${c.Arg1}|${Arg2}`, this.utage.characterInfo[c.Arg1][Arg2].FileName); } - } else if(c.Arg1 && c.Arg2 && c.Arg2 != "" && - (!this.utage.characterInfo[c.Arg1] || !this.utage.characterInfo[c.Arg1][c.Arg2])) { - console.log(`Failed to get Character: ${c.Arg1}|${c.Arg2}`); + } else if(c.Arg1 && Arg2 && Arg2 != "" && + (!this.utage.characterInfo[c.Arg1] || !this.utage.characterInfo[c.Arg1][Arg2])) { + console.log(`Failed to get Character: ${c.Arg1}|${Arg2}`); } break; } @@ -107,7 +112,7 @@ class Player { parentContainer.addChild(cont); //center the position of the container then offset it by the value in the layer info let x = (((baseDimensions.width / 2) + Number(l.X)) * this.resolutionScale); - let y = (((baseDimensions.height / 2) + Number(l.Y)) * this.resolutionScale); + let y = (((baseDimensions.height / 2) - Number(l.Y)) * this.resolutionScale); //let x = (Number(l.X) * this.resolutionScale); //let y = (Number(l.Y) * this.resolutionScale); cont.position.set(x, y); @@ -129,7 +134,7 @@ class Player { onPixiProgress(loader, resource) { if(loader.progress < 100) { - this.text.titleText(true, `Loading Assets... ${loader.progress}%`); + this.text.titleText(true, `Loading Assets... ${loader.progress.toFixed(0)}%`); } else { this.text.titleText(false, ''); } @@ -174,44 +179,60 @@ class Player { } loopHandleLerps(deltaTime) { - //Loop through the lerp targets, modify the needed objects. If a object is at its 1 time state remove it from the list. - let toRemove = []; - for(let i = 0; i < this.lerpTargets.length; ++i) { - let l = this.lerpTargets[i]; - l.curTime += deltaTime; - let pos = l.curTime / l.time; - if(pos >= 1) { - pos = 1; - toRemove.push(i); + try { + //Loop through the lerp targets, modify the needed objects. If a object is at its 1 time state remove it from the list. + let toRemove = []; + for(let i = 0; i < this.lerpTargets.length; ++i) { + let l = this.lerpTargets[i]; + l.curTime += deltaTime; + let pos = l.curTime / l.time; + if(pos >= 1) { + pos = 1; + toRemove.push(i); + if(l.post === "destroy") { + debugger; + l.object.destroy(); + continue; + } + } + let newValue = commonFunctions.lerp(l.initV, l.finalV, pos); + let split = l.type.split("."); + switch(split.length) { + case 1: + l.object[split[0]] = newValue; + break; + case 2: + l.object[split[0]][split[1]] = newValue; + break; + default: + continue; + } } - var newValue = commonFunctions.lerp(l.initV, l.finalV, pos); - var split = l.type.split("."); - switch(split.length) { - case 1: - l.object[split[0]] = newValue; - break; - case 2: - l.object[split[0]][split[1]] = newValue; - break; - default: - continue; - } - } - for(let i = toRemove.length - 1; i > -1; --i) { - this.lerpTargets.splice(toRemove[i], 1); + for(let i = toRemove.length - 1; i > -1; --i) { + this.lerpTargets.splice(toRemove[i], 1); + } + } catch (error) { + console.log(error); } } processCommand(delta) { try { let cur = this.currentCommand; + if(this.checkIfAllOff()) { + this.text.dialogText(false, ""); + this.text.characterName(false, ""); + } else { + this.text.dialogText(true, ""); + this.text.characterName(true, ""); + } switch((cur.Command || "").toLowerCase()) { case "scenetitle01": this.waitTime = this.titleWaitTime * 1000; this.text.titleText(true, cur.Text); break; case "divaeffect": - this.waitTime = Number(cur.Arg5) * 1000; + this.waitTime = 1000//Number(cur.Arg5) * 1000; this.text.divaText(true, cur.Text); break; //FadeTo @@ -226,26 +247,38 @@ class Player { this.layers["bg|whiteFade"].sprite.tint = commonFunctions.getColorFromName(cur.Arg1); this.lerpTargets.push({type: 'alpha', object: this.layers["bg|whiteFade"].sprite, curTime: 0, time: this.waitTime, finalV: 0, initV: 1}); break; - case "bg": + case "bg": { let bgInfo = this.utage.textureInfo[cur.Arg1]; let container = this.layers[this.bgLayerName].container; - //clear the sprite for the bg currently in use. - for(var i = 0; i < container.children.length; ++i) { - let s = container.children[i]; - container.children[i].destroy(); + //If we have a fadetime we need to keep the old bg, fade its alpha out, then destroy it. + if(cur.Arg6) { + //I know im assuming a lot that there is already only one bg on the layer. + this.lerpTargets.push({type: 'alpha', object: container.children[0], curTime: 0, time: (Number(cur.Arg6) * 1000), finalV: 0, initV: 1, post: "destroy"}); + } else { + //clear the sprite for the bg currently in use. + for(let i = 0; i < container.children.length; ++i) { + container.children[i].destroy(); + } } container.visible = true; let sprite = new PIXI.Sprite(this.loader.resources[`bg|${cur.Arg1}`].texture); sprite.scale.set(Number(bgInfo.Scale), Number(bgInfo.Scale)); //center the bg sprite.anchor.set(0.5, 0.5); - container.addChild(sprite); + if(cur.Arg6) { + container.addChild(sprite); + sprite.alpha = 0 + this.lerpTargets.push({type: 'alpha', object: sprite, curTime: 0, time: (Number(cur.Arg6) * 1000), finalV: 1, initV: 0}); + } else { + container.addChild(sprite); + } break; + } case "wait": this.waitTime = Number(cur.Arg6) * 1000; break; case "waitinput": { - let time = Number(cur.Arg6) + let time = Number(cur.Arg6); if(time) { this.waitTime = time * 1000; } else { @@ -256,28 +289,28 @@ class Player { case "movecamera": { let time = Number(cur.Arg4); let scale = 1 + (1 - Number(cur.Arg3)); - var cont = this.layers["bg|mainparent"].container; + let cont = this.layers["bg|mainparent"].container; let x = this.center.x + -(Number(cur.Arg1)); let y = this.center.y + -(Number(cur.Arg2)); if(time) { this.waitTime = time * 1000; if(cont.scale.x !== scale) { this.lerpTargets.push({type: 'scale.x', object: cont, curTime: 0, - time: this.waitTime, finalV: scale, initV: cont.x }); + time: this.waitTime, finalV: scale, initV: cont.scale.x }); } if(cont.scale.y !== scale) { this.lerpTargets.push({type: 'scale.y', object: cont, curTime: 0, - time: this.waitTime, finalV: scale, initV: cont.y }); + time: this.waitTime, finalV: scale, initV: cont.scale.y }); } if(cont.position.x !== x) { this.lerpTargets.push({type: 'position.x', object: cont, curTime: 0, - time: this.waitTime, finalV: x, initV: cont.x }); + time: this.waitTime, finalV: x, initV: cont.position.x }); } if(cont.position.y !== y) { this.lerpTargets.push({type: 'position.y', object: cont, curTime: 0, - time: this.waitTime, finalV: y, initV: cont.y }); + time: this.waitTime, finalV: y, initV: cont.position.y }); } if(cur.Arg6 && cur.Arg6.toLowerCase() === "nowait") { this.waitTime = 0; @@ -288,6 +321,29 @@ class Player { } break; } + case "characteroff": { + for(let c of Object.keys(this.currentCharacters)) { + if(!this.currentCharacters[c]) { continue; } + let curChar = this.currentCharacters[c]; + if(curChar.charName === cur.Arg1) { + let time = Number(cur.Arg6) * 1000; + this.lastCharOffLayer = this.currentCharacters[c].layer; + this.lerpTargets.push({type: 'alpha', object: curChar.sprite, curTime: 0, time: time, finalV: 0, initV: 1, post: "destroy" }); + this.currentCharacters[c] = undefined; + break; + } + } + } + case "tween": + break; + case "bgm": + break; + case "stopbgm": + break; + case "se": + break; + case "shake": + break; default: this.processCommandOther(delta); break; @@ -299,7 +355,68 @@ class Player { //This should mostly be handling things like text processCommandOther(delta) { - if(this.currentCommand) + let cur = this.currentCommand; + //Character on screen + checkPutCharacterScreen.apply(this); + //Display text + checkPutText.apply(this); + + function checkPutCharacterScreen() { + if(!cur.Command && cur.Arg1 && this.utage.characterInfo[cur.Arg1]) { + if(!cur.Arg2) { + cur.Arg2 = this.defaultCharPattern; + } + let chr = this.utage.characterInfo[cur.Arg1][cur.Arg2]; + let lay = undefined; + let chlay = undefined; + if(cur.Arg3) { + lay = this.layers[cur.Arg3]; + chlay = this.currentCharacters[cur.Arg3]; + if(!lay) { return; } + } else { + lay = this.lastCharOffLayer; + if(!lay) { return; } + cur.Arg3 = lay.info.LayerName; + } + if(this.currentCharacters[cur.Arg3] && this.currentCharacters[cur.Arg3].charName === cur.Arg1) { + return; + } + //If the layer already has a character on it remove it. + if(chlay && (chlay.character.NameText !== chr.NameText || chlay.character.Pattern !== chr.Pattern)) { + this.lerpTargets.push({type: 'alpha', object: chlay.sprite, curTime: 0, time: 100, finalV: 0, initV: 1, post: "destroy" }); + this.currentCharacters[cur.Arg3] = undefined; + } + let sprite = new PIXI.Sprite(this.loader.resources[`char|${cur.Arg1}|${cur.Arg2}`].texture); + sprite.scale.set(Number(chr.Scale), Number(chr.Scale)); + let anchor = commonFunctions.getAnchorFromCharPivot(chr.Pivot); + sprite.anchor.set(anchor.x, anchor.y); + sprite.alpha = 0; + this.currentCharacters[cur.Arg3] = { layer: lay, character: chr, charName: cur.Arg1, sprite: sprite }; + this.lerpTargets.push({type: 'alpha', object: sprite, curTime: 0, time: 100, finalV: 1, initV: 0 }); + lay.container.addChild(sprite); + lay.container.visible = true; + } + } + + function checkPutText() { + if(!cur.Command && cur.Arg1 && cur.Text) { + if(cur.Arg2 && cur.Arg2.toLowerCase() === "") { + this.text.characterName(true, cur.Arg1); + this.text.dialogText(true, commonFunctions.convertUtageTextTags(cur.Text)); + } else { + let charName = ""; + for(let c of Object.keys(this.currentCharacters)) { + if(!this.currentCharacters[c]) { continue; } + if(this.currentCharacters[c].charName === cur.Arg1) { + this.text.characterName(true, this.currentCharacters[c].character.NameText); + this.text.dialogText(true, commonFunctions.convertUtageTextTags(cur.Text)); + break; + } + } + } + this.waitTime = 1000; + } + } } processEndCommand(delta) { @@ -315,6 +432,13 @@ class Player { this.currentCommand = undefined; } + checkIfAllOff() { + for(let c of Object.keys(this.currentCharacters)) { + if(this.currentCharacters[c]) { return false; } + } + return true; + } + onMainClick() { if(this.runEvent && this.manualNext) { if (!this.hasMoreText) { @@ -347,13 +471,13 @@ class Player { try { this.pixi.app.ticker.remove(this.onPixiTick, this); this.pixi.app.stage.children.forEach(function(child) { child.destroy(true, true, true); }); - Object.keys(PIXI.utils.TextureCache).forEach(function(texture) { - if(PIXI.utils.TextureCache[texture]) { - PIXI.utils.TextureCache[texture].destroy(true); + for(let tex of Object.keys(PIXI.utils.TextureCache)) { + if(PIXI.utils.TextureCache[tex]) { + PIXI.utils.TextureCache[tex].destroy(true); } - }); + } this.loader.reset(); - this.currentCharacters = []; + this.currentCharacters = {}; this.currentCommand = undefined; this.runEvent = false; this.secondTicker = 1000; diff --git a/Js/TextFunctions.js b/Js/TextFunctions.js index c061b88..fda419e 100644 --- a/Js/TextFunctions.js +++ b/Js/TextFunctions.js @@ -41,7 +41,7 @@ class TextFunctions { this.character.style = show ? "opacity: 1;" : "opacity: 0;"; } - dialog(show, text) { + dialogText(show, text) { if(text != undefined) { this.dialog.innerHTML = text; }