diff --git a/css/style.css b/css/style.css index 3a2a65c..ee3ea41 100644 --- a/css/style.css +++ b/css/style.css @@ -43,7 +43,7 @@ a { font-size: 1em; border-style: outset; border-width: 2px; - border-radius: 5px; + border-radius: 3px; color: black; background-color: white; padding: 5px; @@ -69,20 +69,22 @@ a:active { } #grid { + position: relative; display: grid; - grid-template-columns: 6fr 10fr 6fr; + grid-template-columns: 120px 200px 120px; grid-gap: 20px; margin: auto; - width: 550px; + width: 480px; } table { table-layout: fixed; border-spacing: 0; + width: 0; } td { - border: 1px outset transparent; + border: 1px solid transparent; } #hold { @@ -152,7 +154,7 @@ td { border-color: white; } -.locked-mino { +.locked-piece { background-color: white; border-color: white; } @@ -163,22 +165,21 @@ td { } .trail { - background-color: rgba(255, 255, 255, 0.5); - border-color: rgba(255, 255, 255, 0.5); + background-color: rgba(255, 255, 255, 0.4); + border-color: rgba(255, 255, 255, 0.4); } .ghost { - background-color: rgba(255, 255, 255, 0.5); - border-color: rgba(128, 128, 128, 0.5); + background-color: rgba(255, 255, 255, 0.4); + border-color: rgba(255, 255, 255, 0.3); border-style: inset; } #stats { grid-column: 1; grid-row: 2; - width: 0; height: 0; - table-layout: auto; + width: 120px; } .stat-label { @@ -189,4 +190,16 @@ td { .stat-value { font-family: 'Share Tech Mono'; text-align: right; +} + +#message { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-size: 19px; + text-shadow: 1px 1px black; + text-align: center; + font-weight: bold; } \ No newline at end of file diff --git a/js/webtris.js b/js/webtris.js index 72c8dcb..a51b801 100644 --- a/js/webtris.js +++ b/js/webtris.js @@ -27,7 +27,7 @@ const MATRIX_INVISIBLE_ROWS = 4 const MATRIX_COLUMNS = 10 const NEXT_ROWS = 24 const NEXT_COLUMNS = 6 -const LOCKED_CLASS = "locked-mino" +const LOCKED_PIECE_CLASS = "locked-piece" const INVISIBLE_ROW_CLASS = "invisible-row" const VISIBLE_ROW_CLASS = "visible-row" const CLEARED_LINE_CLASS = "cleared-line" @@ -202,10 +202,10 @@ class Tetromino { class MinoesTable { constructor(id, rows, columns) { - this.table = document.getElementById(id) this.rows = rows this.columns = columns this.piece = null + this.table = document.getElementById(id) for (var y=0; y < rows; y++) { var row = this.table.insertRow() for (var x=0; x < columns; x++) { @@ -218,9 +218,9 @@ class MinoesTable { this.table.rows[y].cells[x].className = className } - drawPiece(piece, className=null) { - if (!className) className = piece.className - piece.minoesAbsPos.forEach(pos => this.table.rows[pos[1]].cells[pos[0]].className = piece.shape) + drawPiece(piece) { + var className = piece.locked ? LOCKED_PIECE_CLASS : piece.shape + piece.minoesAbsPos.forEach(pos => this.drawMino(...pos, className)) } clearTable() { @@ -250,16 +250,11 @@ class Matrix extends MinoesTable { super("matrix", MATRIX_ROWS, MATRIX_COLUMNS) this.lockedMinoes = Array.from(Array(MATRIX_ROWS+3), row => Array(MATRIX_COLUMNS)) this.piece = null - this.linesCleared = [] + this.clearedLines = [] this.trail = { minoesPos: [], height: 0 } - /*this.context.textAlign = "center" - this.context.textBaseline = "center" - this.context.font = "27px 'Share Tech', sans-serif" - this.centerX = this.width / 2 - this.centerY = this.height / 2*/ } cellIsOccupied(x, y) { @@ -275,7 +270,7 @@ class Matrix extends MinoesTable { if (state == STATE.PAUSED) { for (var y=0; y < this.rows; y++) { for (var x=0; x < this.columns; x++) { - if (this.linesCleared.includes(y)) var className = CLEARED_LINE_CLASS + if (this.clearedLines.includes(y)) var className = CLEARED_LINE_CLASS else { if (y < MATRIX_INVISIBLE_ROWS) var className = INVISIBLE_ROW_CLASS else var className = VISIBLE_ROW_CLASS @@ -288,7 +283,7 @@ class Matrix extends MinoesTable { for (var x=0; x < this.columns; x++) { var className = this.lockedMinoes[y][x] if (!className) { - if (this.linesCleared.includes(y)) className = CLEARED_LINE_CLASS + if (this.clearedLines.includes(y)) className = CLEARED_LINE_CLASS else { if (y < MATRIX_INVISIBLE_ROWS) className = INVISIBLE_ROW_CLASS else className = VISIBLE_ROW_CLASS @@ -306,44 +301,14 @@ class Matrix extends MinoesTable { } //ghost - if (!this.piece.locked) { + if (!this.piece.locked && state != STATE.GAME_OVER) { for (var ghost = this.piece.ghost; this.spaceToMove(ghost.minoesAbsPos); ghost.pos[1]++) {} ghost.pos[1]-- this.drawPiece(ghost) } - var className = this.piece.locked ? LOCKED_CLASS : this.piece.className - this.drawPiece(this.piece, this.piece.locked ? LOCKED_CLASS : this.piece.className) + this.drawPiece(this.piece) } - - // text - /*var texts = [] - switch(state) { - case STATE.PLAYING: - if (tempTexts.length) - texts = tempTexts[0] - break - case STATE.PAUSED: - texts = ["PAUSED"] - break - case STATE.GAME_OVER: - texts = ["GAME", "OVER"] - } - if (texts.length) { - this.context.save() - this.context.shadowColor = "black" - this.context.shadowOffsetX = 1 - this.context.shadowOffsetY = 1 - this.context.shadowBlur = 2 - this.context.fillStyle = "white" - if (texts.length == 1) - this.context.fillText(texts[0], this.centerX, this.centerY) - else { - this.context.fillText(texts[0], this.centerX, this.centerY - 20) - this.context.fillText(texts[1], this.centerX, this.centerY + 20) - } - this.context.restore() - }*/ } } @@ -370,11 +335,16 @@ timeFormat = new Intl.DateTimeFormat("fr-FR", { class Stats { constructor () { - this.div = document.getElementById("stats-values") + this.scoreCell = document.getElementById("score") + this.highScoreCell = document.getElementById("highScore") + this.timeCell = document.getElementById("time") + this.levelCell = document.getElementById("level") + this.goalCell = document.getElementById("goal") + this.clearedLinesCell = document.getElementById("clearedLines") this._score = 0 this.highScore = localStorage.getItem('highScore') || 0 this.goal = 0 - this.linesCleared = 0 + this.clearedLines = 0 this.startTime = Date.now() this.pauseTime = 0 this.combo = -1 @@ -388,8 +358,10 @@ class Stats { set score(score) { this._score = score + this.scoreCell.innerHTML = this._score if (score > this.highScore) this.highScore = score + this.highScoreCell.innerHTML = this.highScore } newLevel(level=null) { @@ -397,53 +369,51 @@ class Stats { this.level = level else this.level++ - printTempTexts(["LEVEL", this.level]) + this.levelCell.innerHTML = this.level + printTempTexts(`LEVEL
${this.level}`) this.goal += 5 * this.level + this.goalCell.innerHTML = this.goal if (this.level <= 20) this.fallPeriod = 1000 * Math.pow(0.8 - ((this.level - 1) * 0.007), this.level - 1) if (this.level > 15) this.lockDelay = 500 * Math.pow(0.9, this.level - 15) } - lockDown(tSpin, linesCleared) { + lockDown(tSpin, clearedLines) { var patternName = [] var patternScore = 0 var combo_score = 0 if (tSpin) patternName.push(tSpin) - if (linesCleared) { - patternName.push(SCORES[linesCleared].linesClearedName) + if (clearedLines) { + patternName.push(SCORES[clearedLines].linesClearedName) this.combo++ } else this.combo = -1 - if (linesCleared || tSpin) { - this.linesCleared += linesCleared - patternScore = SCORES[linesCleared][tSpin] + if (clearedLines || tSpin) { + this.clearedLines += clearedLines + this.clearedLinesCell.innerHTML = clearedLines + patternScore = SCORES[clearedLines][tSpin] this.goal -= patternScore + this.goalCell.innerHTML = this.goal patternScore *= 100 * this.level patternName = patternName.join("\n") } if (this.combo >= 1) - combo_score = (linesCleared == 1 ? 20 : 50) * this.combo * this.level + combo_score = (clearedLines == 1 ? 20 : 50) * this.combo * this.level this.score += patternScore + combo_score if (patternScore) - printTempTexts([patternName, patternScore]) + printTempTexts(`${patternName}
${patternScore}`) if (combo_score) - printTempTexts([`COMBO x${this.combo}`, combo_score]) + printTempTexts(`COMBO x${this.combo}
${combo_score}`) } - print() { - this.div.innerHTML = `${this.score}
- ${this.highScore}
- ${timeFormat(Date.now() - this.startTime)}
-
- ${this.level}
- ${this.goal}
- ${this.linesCleared}` + printTime() { + this.timeCell.innerHTML = timeFormat(Date.now() - this.startTime) } } @@ -523,7 +493,7 @@ function lockDown(){ if (matrix.piece.minoesAbsPos.every(pos => pos.y < MATRIX_INVISIBLE_ROWS)) game_over() else { - matrix.piece.minoesAbsPos.forEach(pos => matrix.lockedMinoes[pos[1]][pos[0]] = matrix.piece.className) + matrix.piece.minoesAbsPos.forEach(pos => matrix.lockedMinoes[pos[1]][pos[0]] = matrix.piece.shape) // T-Spin detection var tSpin = T_SPIN.NONE @@ -540,16 +510,16 @@ function lockDown(){ } // Complete lines - matrix.linesCleared = [] + matrix.clearedLines = [] matrix.lockedMinoes.forEach((row, y) => { - if (row.filter(mino => mino.length).length == MATRIX_COLUMNS) { + if (row.filter(lockedMino => lockedMino.length).length == MATRIX_COLUMNS) { matrix.lockedMinoes.splice(y, 1) matrix.lockedMinoes.unshift(Array(MATRIX_COLUMNS)) - matrix.linesCleared.push(y) + matrix.clearedLines.push(y) } }) - stats.lockDown(tSpin, matrix.linesCleared.length) + stats.lockDown(tSpin, matrix.clearedLines.length) requestAnimationFrame(draw) scheduler.setTimeout(clearLinesCleared, ANIMATION_DELAY) @@ -561,12 +531,13 @@ function lockDown(){ } function clearLinesCleared() { - matrix.linesCleared = [] + matrix.clearedLines = [] requestAnimationFrame(draw) } function gameOver() { state = STATE.GAME_OVER + messageDiv.innerHTML = "GAME
OVER" scheduler.clearInterval(lockPhase) scheduler.clearTimeout(lockDown) scheduler.clearInterval(clock) @@ -681,6 +652,7 @@ function hold() { function pause() { state = STATE.PAUSED stats.pauseTime = Date.now() - stats.startTime + messageDiv.innerHTML = "PAUSED" scheduler.clearInterval(lockPhase) scheduler.clearTimeout(lockDown) scheduler.clearTimeout(autorepeat) @@ -690,6 +662,7 @@ function pause() { function resume() { state = STATE.PLAYING stats.startTime = Date.now() - stats.pauseTime + messageDiv.innerHTML = "" scheduler.setTimeout(lockPhase, stats.fallPeriod) if (matrix.piece.locked) scheduler.setTimeout(lockDown, stats.lockDelay) @@ -699,34 +672,39 @@ function resume() { function printTempTexts(texts) { tempTexts.push(texts) + messageDiv.innerHTML = tempTexts[0] if (!scheduler.intervalTasks.has(delTempTexts)) scheduler.setInterval(delTempTexts, TEMP_TEXTS_DELAY) } function delTempTexts(self) { - if (tempTexts.length) + if (tempTexts.length) tempTexts.shift() - else + if (tempTexts.length) + messageDiv.innerHTML = tempTexts[0] + else { scheduler.clearInterval(delTempTexts) -} - -function clock() { - //stats.print() + messageDiv.innerHTML = "" + } } function draw() { holdQueue.draw() matrix.draw() nextQueue.draw() - //stats.print() } function getKey(action) { return localStorage.getItem(action) || actionsDefaultKeys[action] } +function clock() { + stats.printTime() +} + window.onload = function() { tempTexts = [] + messageDiv = document.getElementById("message") holdQueue = new HoldQueue() stats = new Stats() diff --git a/webtris.html b/webtris.html index 9a449b0..74ee857 100644 --- a/webtris.html +++ b/webtris.html @@ -23,6 +23,7 @@ LIGNES0 +
REJOUER