css, hold, next, fix rotate

This commit is contained in:
Adrien MALINGREY 2019-10-25 17:56:13 +02:00
parent 8992f4d02b
commit 0f3ab4052e
4 changed files with 127 additions and 58 deletions

View File

@ -1,11 +1,51 @@
* { * {
background: #000;
padding: 0; padding: 0;
margin: 0; margin: 0;
color: white;
} }
canvas { body {
background: #000; background-image: url("../images/bg.jpg");
background-size: cover;
}
canvas {
display: block; display: block;
margin: 0 auto; flex-shrink: 0;
} }
.columns {
display: flex;
flex-direction: row;
justify-content: center;
}
.side {
flex-grow: 2;
}
.rows {
display: flex;
flex-direction: column;
margin: 5% 2%;
}
.hold {
max-width: 120px;
height: initial;
}
.stats {
margin: 10% 0;
}
.matrix {
max-width: 200px;
margin: 5% 2%;
border: 0.5px solid grey;
}
.next {
max-width: 120px;
margin: 5% 2%;
}

BIN
images/bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

View File

@ -8,6 +8,19 @@
<script type="text/javascript" src="js/webtris.js"></script> <script type="text/javascript" src="js/webtris.js"></script>
</head> </head>
<body> <body>
<canvas id="matrix" width="200" height="400">Votre navigateur ne supporte pas HTML5, veuillez le mettre à jour pour jouer.</canvas> <div class="columns">
<div class="side"></div>
<div class="rows">
<canvas id="hold" class="hold" width="120" height="120"></canvas>
<div class="stats">
SCORE: 123123123123<br/>
HIGH SCORE:<br/>
TIME:<br/>
</div>
</div>
<canvas id="matrix" class="matrix" width="200" height="400">Votre navigateur ne supporte pas HTML5, veuillez le mettre à jour pour jouer.</canvas>
<canvas id="next" class="next" width="120" height="400"></canvas>
<div class="side"></div>
</div>
</body> </body>
</html> </html>

View File

@ -2,7 +2,7 @@ Array.prototype.add = function(other) {
return this.map((x, i) => x + other[i]) return this.map((x, i) => x + other[i])
} }
Array.prototype.rotate = function(spin) { Array.prototype.rotate = function(spin) {
return [spin*pos[1], pos[0]] return [-spin*this[1], spin*this[0]]
} }
Array.prototype.sample = function() { Array.prototype.sample = function() {
return this.splice(Math.floor(Math.random()*this.length), 1)[0] return this.splice(Math.floor(Math.random()*this.length), 1)[0]
@ -10,10 +10,12 @@ Array.prototype.sample = function() {
const MINO_SIZE = 20 const MINO_SIZE = 20
const MATRIX_LINES = 20
const MATRIX_COLLUMNS = 10
const NEXT_PIECES = 5 const NEXT_PIECES = 5
const INIT_POSITION = [4, 0] const MATRIX_LINES = 20
const MATRIX_COLUMNS = 10
const HELD_PIECE_POSITION = [2, 2]
const FALLING_PIECE_POSITION = [4, 0]
const NEXT_PIECES_POSITIONS = Array.from({length: NEXT_PIECES}, (v, k) => [2, k*4+2])
const LOCK_DELAY = 500 const LOCK_DELAY = 500
const FALL_DELAY = 1000 const FALL_DELAY = 1000
const AUTOREPEAT_DELAY = 300 const AUTOREPEAT_DELAY = 300
@ -24,8 +26,8 @@ const MOVEMENT = {
DOWN: [0, 1] DOWN: [0, 1]
} }
const SPIN = { const SPIN = {
CW: -1, CW: 1,
CCW: 1 CCW: -1
} }
const T_SPIN = { const T_SPIN = {
NULL: "", NULL: "",
@ -50,7 +52,7 @@ const SCORES = [
shapes = [] shapes = []
class Tetromino { class Tetromino {
constructor() { constructor() {
this.pos = INIT_POSITION this.pos = FALLING_PIECE_POSITION
this.orientation = 0 this.orientation = 0
this.rotated_last = false this.rotated_last = false
this.rotation_point_5_used = false this.rotation_point_5_used = false
@ -66,7 +68,7 @@ class Tetromino {
[[0, 0], [ 1, 0], [ 1, -1], [0, 2], [ 1, 2]], [[0, 0], [ 1, 0], [ 1, -1], [0, 2], [ 1, 2]],
[[0, 0], [ 1, 0], [ 1, 1], [0, -2], [ 1, -2]], [[0, 0], [ 1, 0], [ 1, 1], [0, -2], [ 1, -2]],
[[0, 0], [-1, 0], [-1, -1], [0, 2], [-1, 2]], [[0, 0], [-1, 0], [-1, -1], [0, 2], [-1, 2]],
[[0, 0], [-1, 0], [-1, 1], [0, -2], [-1, -2]], [[0, 0], [-1, 0], [-1, 1], [0, 2], [-1, -2]],
], ],
} }
if (!shapes.lenght) if (!shapes.lenght)
@ -134,49 +136,57 @@ class Tetromino {
function draw_mino(context, x, y, color) { function draw_mino(context, x, y, color) {
context.fillStyle = color context.fillStyle = color
context.fillRect(x*MINO_SIZE, y*MINO_SIZE, MINO_SIZE, MINO_SIZE); context.fillRect(x*MINO_SIZE, y*MINO_SIZE, MINO_SIZE, MINO_SIZE)
context.strokeStyle = "rgba(255, 255, 255, 128)"; context.lineWidth = 0.5
context.strokeRect(x*MINO_SIZE, y*MINO_SIZE, MINO_SIZE, MINO_SIZE); context.strokeStyle = "white"
context.strokeRect(x*MINO_SIZE, y*MINO_SIZE, MINO_SIZE, MINO_SIZE)
} }
class Matrix { class Matrix {
constructor() { constructor(context) {
this.cells = Array.from(Array(MATRIX_COLLUMNS), y => Array(MATRIX_LINES)) this.context = context
this.cells = Array.from({length: MATRIX_COLUMNS}, (v, k) => Array(MATRIX_LINES))
} }
cell_is_occupied(x, y) { cell_is_occupied(x, y) {
return 0 <= x && x < MATRIX_COLLUMNS && y < MATRIX_LINES ? this.cells[x][y] : true return 0 <= x && x < MATRIX_COLUMNS && y < MATRIX_LINES ? this.cells[x][y] : true
} }
space_to_move(piece_pos, minoes_pos) { space_to_move(piece_pos, minoes_pos) {
for (const abs_mino_pos of minoes_pos.map(pos => pos.add(piece_pos))) { for (const pos of minoes_pos) {
if (this.cell_is_occupied(...abs_mino_pos)) if (this.cell_is_occupied(...pos.add(piece_pos)))
return false return false
} }
return true return true
} }
draw(context) { draw() {
// grid // grid
context.strokeStyle = "rgba(128, 128, 128, 128)"; const width = MATRIX_COLUMNS*MINO_SIZE
context.beginPath(); const height = MATRIX_LINES*MINO_SIZE
for (var x = 0; x <= MATRIX_COLLUMNS*MINO_SIZE; x += MINO_SIZE) { this.context.clearRect(0, 0, width, height)
context.moveTo(x, 0); this.context.strokeStyle = "rgba(128, 128, 128, 128)"
context.lineTo(x, matrixCanvas.height); this.context.lineWidth = 0.5
this.context.beginPath()
for (var x = 0; x <= width; x += MINO_SIZE) {
this.context.moveTo(x, 0);
this.context.lineTo(x, height);
} }
for (var y = 0; y <= MATRIX_LINES*MINO_SIZE; y += MINO_SIZE) { for (var y = 0; y <= height; y += MINO_SIZE) {
context.moveTo(0, y); this.context.moveTo(0, y);
context.lineTo(matrixCanvas.width, y); this.context.lineTo(width, y);
} }
context.stroke(); this.context.stroke()
// falling piece
falling_piece.draw(this.context)
} }
} }
function move(movement) { function move(movement) {
const test_pos = tetro.pos.add(movement) const test_pos = falling_piece.pos.add(movement)
if (matrix.space_to_move(test_pos, tetro.minoes_pos)) { if (matrix.space_to_move(test_pos, falling_piece.minoes_pos)) {
tetro.pos = test_pos falling_piece.pos = test_pos
return true return true
} }
else { else {
@ -185,14 +195,14 @@ function move(movement) {
} }
function rotate(spin) { function rotate(spin) {
const text_minoes_pos = tetro.minoes_pos.map(pos => [spin*pos[1], pos[0]]) const test_minoes_pos = falling_piece.minoes_pos.map(pos => pos.rotate(spin))
rotation_point = 0 rotation_point = 0
for (const movement of tetro.srs[spin==SPIN.CW?"CW":"CCW"][tetro.orientation]) { for (const movement of falling_piece.srs[spin==SPIN.CW?"CW":"CCW"][falling_piece.orientation]) {
const test_pos = [tetro.pos[0]+movement[0], tetro.pos[1]+movement[1]] const test_pos = falling_piece.pos.add(movement)
if (matrix.space_to_move(test_pos, text_minoes_pos)) { if (matrix.space_to_move(test_pos, test_minoes_pos)) {
tetro.pos = test_pos falling_piece.pos = test_pos
tetro.minoes_pos = text_minoes_pos falling_piece.minoes_pos = test_minoes_pos
tetro.orientation = (tetro.orientation - spin + 4) % 4 falling_piece.orientation = (falling_piece.orientation + spin + 4) % 4
break; break;
} }
rotation_point++ rotation_point++
@ -261,9 +271,9 @@ function autorepeat() {
} }
function keyDownHandler(e) { function keyDownHandler(e) {
if (e.key in actions) {
if (!pressedKeys.has(e.key)) { if (!pressedKeys.has(e.key)) {
pressedKeys.add(e.key) pressedKeys.add(e.key)
if (e.key in actions) {
action = actions[e.key] action = actions[e.key]
action() action()
if (repeatableActions.includes(action)) { if (repeatableActions.includes(action)) {
@ -284,8 +294,8 @@ function keyDownHandler(e) {
} }
function keyUpHandler(e) { function keyUpHandler(e) {
pressedKeys.delete(e.key)
if (e.key in actions) { if (e.key in actions) {
pressedKeys.delete(e.key)
action = actions[e.key] action = actions[e.key]
if (actionsToRepeat.includes(action)) { if (actionsToRepeat.includes(action)) {
actionsToRepeat.splice(actionsToRepeat.indexOf(action), 1) actionsToRepeat.splice(actionsToRepeat.indexOf(action), 1)
@ -302,18 +312,24 @@ function keyUpHandler(e) {
} }
function draw() { function draw() {
matrixContext.clearRect(0, 0, MATRIX_COLLUMNS*MINO_SIZE, MATRIX_LINES*MINO_SIZE); held_piece.draw(holdContext)
matrix.draw(matrixContext) matrix.draw()
tetro.draw(matrixContext) next_pieces.map(piece => piece.draw(nextContext))
requestAnimationFrame(draw) requestAnimationFrame(draw)
} }
window.onload = function() { window.onload = function() {
matrixCanvas = document.getElementById("matrix"); holdContext = document.getElementById("hold").getContext("2d")
matrixContext = matrixCanvas.getContext("2d"); matrixContext = document.getElementById("matrix").getContext("2d")
nextContext = document.getElementById("next").getContext("2d")
matrix = new Matrix() matrix = new Matrix(matrixContext)
tetro = new Tetromino() held_piece = new Tetromino()
held_piece.pos = HELD_PIECE_POSITION
falling_piece = new Tetromino()
falling_piece.pos = FALLING_PIECE_POSITION
next_pieces = Array.from({length: NEXT_PIECES}, (v, k) => new Tetromino())
next_pieces.map((piece, i, array) => piece.pos = NEXT_PIECES_POSITIONS[i])
document.addEventListener("keydown", keyDownHandler, false); document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false); document.addEventListener("keyup", keyUpHandler, false);