This commit is contained in:
Adrien MALINGREY 2019-11-01 02:39:44 +01:00
parent bfe422bbdd
commit 5de5f03b3c
10 changed files with 304 additions and 129 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
db_info.txt db_connect.php

View File

@ -17,7 +17,7 @@
* { * {
color: white; color: white;
font-family: 'Share Tech'; font-family: 'Share Tech';
font-size: 1em; font-size: 3vmin;
} }
body { body {
@ -27,9 +27,9 @@ body {
} }
h1 { h1 {
font-size: 50px; font-size: 5vmin;
margin: 20px; margin: 2vmin;
text-shadow: 3px 2px rgb(153, 145, 175); text-shadow: 3px 2px rgba(153, 145, 175, 0.5);
text-align: center; text-align: center;
} }
@ -56,60 +56,84 @@ a:active {
#actions { #actions {
display: grid; display: grid;
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
grid-gap: 20px; grid-gap: 2vmin;
margin: 40px auto; margin: 4vmin auto;
width: 550px; width: 100vmin;
justify-items: left; justify-items: left;
} }
#play { #button-link {
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
margin: 30px; margin: 3vmin;
} }
#grid { #container {
position: relative; position: relative;
display: grid; display: grid;
grid-template-columns: 120px 200px 120px; width: 72vmin;
grid-gap: 20px; grid-template-columns: 18vmin 30vmin 18vmin;
grid-gap: 3vmin;
margin: auto; margin: auto;
width: 480px;
} }
table { table {
table-layout: fixed; table-layout: fixed;
border-spacing: 0; border-spacing: 0;
width: 0;
height: 0;
} }
td { th {
font-weight: normal;
}
th, td {
border: 1px solid transparent; border: 1px solid transparent;
padding: 0; padding: 0;
width: 20px; border-style: outset;
height: 20px;
} }
#hold { #hold {
grid-column: 1; grid-column: 1;
grid-row: 1; grid-row: 1;
width: 120px; width: 18vmin;
height: 120px; height: 18vmin;
justify-self: end;
} }
#matrix { #matrix {
grid-column: 2; grid-column: 2;
grid-row: 1 / 3; grid-row: 1 / 3;
width: 200px; width: 30vmin;
height: 480px; height: 72vmin;
} }
#next { #next {
grid-column: 3; grid-column: 3;
grid-row: 1 / 3; grid-row: 1 / 3;
width: 120px; width: 18vmin;
height: 480px; height: 72vmin;
}
#stats {
grid-column: 1;
grid-row: 2;
height: 0;
width: 18vmin;
justify-self: end;
}
.name {
font-family: 'Share Tech';
text-align: left;
font-size: 2.5vmin;
color: white;
}
.value {
font-family: 'Share Tech Mono';
text-align: right;
font-size: 2.5vmin;
color: white;
} }
.invisible-row { .invisible-row {
@ -119,17 +143,17 @@ td {
.visible-row { .visible-row {
background-color: transparent; background-color: transparent;
border-color: rgba(128, 128, 128, 0.5); border-color: rgba(128, 128, 128, 0.3);
border-style: inset; border-style: inset;
} }
.tetromino-I { .tetromino-I {
background-color: rgb(153, 255, 255); background-color: rgb(153, 255, 230);
border-color: white; border-color: white;
} }
.tetromino-J { .tetromino-J {
background-color: rgb(153, 255, 255); background-color: rgb(153, 204, 255);
border-color: white; border-color: white;
} }
@ -179,31 +203,29 @@ td {
border-style: solid; border-style: solid;
} }
#stats {
grid-column: 1;
grid-row: 2;
height: 0;
width: 120px;
}
.stat-label {
font-family: 'Share Tech';
text-align: left;
}
.stat-value {
font-family: 'Share Tech Mono';
text-align: right;
}
#message { #message {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
color: white; color: white;
font-size: 19px; font-size: 3vmin;
text-shadow: 1px 1px black; text-shadow: 1px 1px black;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
}
#leaderboard {
min-width: 25%;
margin: auto;
text-align: center;
border-top: 1px solid white;
caption-side: top;
}
.player {
font-family: 'Share Tech';
text-align: center;
font-size: 2.5vmin;
color: white;
} }

View File

@ -5,31 +5,42 @@
<title>Webtris</title> <title>Webtris</title>
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" type="text/css" href="css/style.css" /> <link rel="stylesheet" type="text/css" href="css/style.css" />
<script type="text/javascript" src="js/index.js"></script> <script type="text/javascript" src="js/webtris.js"></script>
</head> </head>
<body> <body>
<h1>WEBTRIS</h1> <h1>WEBTRIS</h1>
<div id="actions"> <div id="container">
<?php <?php
function addButton($action, $label) { function echoTable($id, $rows, $columns) {
?> echo " <table id='$id'>\n";
<div><?=$label?></div> for ($y = 0; $y < $rows; $y++) {
<button type="button" onclick="changeKey(this, '<?=$action?>')"> echo " <tr>";
<script>getKey("<?=$action?>")</script> for ($x = 0; $x < $columns; $x++) {
</button> echo "<td></td>";
<?php } }
addButton("moveLeft", "GAUCHE"); echo "</tr>\n";
addButton("moveRight", "DROITE"); }
addButton("softDrop", "CHUTE LENTE"); echo " </table>\n";
addButton("hardDrop", "CHUTE RAPIDE"); }
addButton("rotateCW", "ROTATION HORAIRE"); echoTable("hold", 6, 6);
addButton("rotateCCW", "ROTATE INVERSE"); echoTable("matrix", 24, 10);
addButton("hold", "GARDE"); echoTable("next", 24, 6);
addButton("pause", "PAUSE");
?> ?>
<table id="stats">
<tr><th class="name">SCORE</th><td class="value" id="score">0</td></tr>
<tr><th class="name">RECORD</th><td class="value" id="highScore">0</td></tr>
<tr><th class="name">TEMPS</th><td class="value" id="time">00:00</td></tr>
<tr><th class="name">NIVEAU</th><td class="value" id="level">0</td></tr>
<tr><th class="name">OBJECTIF</th><td class="value" id="goal">0</td></tr>
<tr><th class="name">LIGNES</th><td class="value" id="clearedLines">0</td></tr>
</table>
<div id="message"></div>
</div> </div>
<div id="play"> <div id="button-link">
<a href="webtris.php">JOUER</a> <a href="options.php" target="_blank">OPTIONS</a>
</div>
<div id="button-link">
<a href="index.php">REJOUER</a>
</div> </div>
</body> </body>
</html> </html>

20
intop10.php Normal file
View File

@ -0,0 +1,20 @@
<?php
include "db_connect.php";
if (isset($_POST['score'])) {
try {
$db = new PDO("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=utf8", $DB_USER, $DB_PASSWORD);
} catch (Exception $e) {
die('Erreur : ' . $e->getMessage());
}
$query = $db->prepare('SELECT player, score FROM `leaderboard` ORDER BY score DESC LIMIT 10;');
$entryScore = $query->fetch();
$query->closeCursor();
$score = (int) $_POST['score'];
if ($score > $entryScore)
echo "true";
else
echo "false";
} else {
header($_SERVER["SERVER_PROTOCOL"] . " 405 Method Not Allowed", true, 405);
}
?>

View File

@ -86,6 +86,7 @@ const actionsDefaultKeys = {
hold: "c", hold: "c",
pause: "Escape", pause: "Escape",
} }
const RETRIES = 3
var actions = {} var actions = {}
@ -442,15 +443,10 @@ function fallingPhase() {
} }
function lockPhase() { function lockPhase() {
if (!move(MOVEMENT.DOWN)) { move(MOVEMENT.DOWN)
matrix.piece.locked = true
if (!scheduler.timeoutTasks.has(lockDown))
scheduler.setTimeout(lockDown, stats.lockDelay)
matrix.draw()
}
} }
function move(movement, testMinoesPos=matrix.piece.minoesPos) { function move(movement, testMinoesPos=matrix.piece.minoesPos, hardDrop=false) {
const testPos = matrix.piece.pos.add(movement) const testPos = matrix.piece.pos.add(movement)
if (matrix.spaceToMove(testMinoesPos.translate(testPos))) { if (matrix.spaceToMove(testMinoesPos.translate(testPos))) {
matrix.piece.pos = testPos matrix.piece.pos = testPos
@ -459,14 +455,21 @@ function move(movement, testMinoesPos=matrix.piece.minoesPos) {
matrix.piece.rotatedLast = false matrix.piece.rotatedLast = false
if (matrix.spaceToMove(matrix.piece.minoesPos.translate(matrix.piece.pos.add(MOVEMENT.DOWN)))) if (matrix.spaceToMove(matrix.piece.minoesPos.translate(matrix.piece.pos.add(MOVEMENT.DOWN))))
fallingPhase() fallingPhase()
else { else if (!hardDrop) {
matrix.piece.locked = true matrix.piece.locked = true
scheduler.clearTimeout(lockDown) scheduler.clearTimeout(lockDown)
scheduler.setTimeout(lockDown, stats.lockDelay) scheduler.setTimeout(lockDown, stats.lockDelay)
} }
matrix.draw() if (!hardDrop)
matrix.draw()
return true return true
} else { } else {
if (movement == MOVEMENT.DOWN) {
matrix.piece.locked = true
if (!scheduler.timeoutTasks.has(lockDown))
scheduler.setTimeout(lockDown, stats.lockDelay)
matrix.draw()
}
return false return false
} }
} }
@ -489,9 +492,11 @@ function rotate(spin) {
function lockDown(){ function lockDown(){
scheduler.clearInterval(lockPhase) scheduler.clearInterval(lockPhase)
if (matrix.piece.minoesAbsPos.every(pos => pos.y < MATRIX_INVISIBLE_ROWS)) if (matrix.piece.minoesAbsPos.every(pos => pos[1] < MATRIX_INVISIBLE_ROWS)) {
game_over() matrix.piece.locked = false
else { matrix.draw()
gameOver()
} else {
matrix.piece.minoesAbsPos.forEach(pos => matrix.lockedMinoes[pos[1]][pos[0]] = matrix.piece.shape) matrix.piece.minoesAbsPos.forEach(pos => matrix.lockedMinoes[pos[1]][pos[0]] = matrix.piece.shape)
// T-Spin detection // T-Spin detection
@ -541,10 +546,48 @@ function gameOver() {
scheduler.clearTimeout(lockDown) scheduler.clearTimeout(lockDown)
scheduler.clearInterval(clock) scheduler.clearInterval(clock)
var info = `GAME OVER\nScore : ${stats.score}`
if (stats.score == stats.highScore) { if (stats.score == stats.highScore) {
alert("Bravo !\nVous avez battu votre précédent record.")
localStorage.setItem('highScore', stats.highScore) localStorage.setItem('highScore', stats.highScore)
} info += "\nBravo ! Vous avez battu votre précédent record."
} else
var info = `GAME OVER\nScore : ${stats.score}`
var XHR = new XMLHttpRequest()
var FD = new FormData()
FD.append("score", stats.score)
XHR.addEventListener('load', function(event) {
if (event.target.responseText == "true") {
var player = prompt(info + "\nBravo ! Vous êtes dans le Top 10.\nEntrez votre nom pour publier votre score :" , localStorage.getItem("name") || "")
if (player.length) {
localStorage.setItem("player", player)
postScore(player, stats.score)
}
} else {
alert(info)
}
})
XHR.addEventListener('error', function(event) {
alert(info)
})
XHR.open('POST', 'intop10.php')
XHR.send(FD)
}
function postScore(player, score) {
var XHR = new XMLHttpRequest()
var FD = new FormData()
FD.append("player", player)
FD.append("score", stats.score)
XHR.addEventListener('load', function(event) {
open("leaderboard.php")
})
XHR.addEventListener('error', function(event) {
if (confirm('Erreur de connexion.\nRéessayer ?'))
postScore(player, score)
})
XHR.open('POST', 'publish.php')
XHR.send(FD)
} }
function autorepeat() { function autorepeat() {
@ -615,7 +658,8 @@ function hardDrop() {
for (matrix.trail.height = 0; move(MOVEMENT.DOWN); matrix.trail.height++) { for (matrix.trail.height = 0; move(MOVEMENT.DOWN); matrix.trail.height++) {
stats.score += 2 stats.score += 2
} }
while (move(MOVEMENT.DOWN)) {} while (move(MOVEMENT.DOWN, matrix.piece.minoesPos, true)) {}
matrix.draw()
lockDown() lockDown()
scheduler.setTimeout(clearTrail, ANIMATION_DELAY) scheduler.setTimeout(clearTrail, ANIMATION_DELAY)
} }
@ -655,9 +699,9 @@ function pause() {
scheduler.clearTimeout(lockDown) scheduler.clearTimeout(lockDown)
scheduler.clearTimeout(autorepeat) scheduler.clearTimeout(autorepeat)
scheduler.clearInterval(clock) scheduler.clearInterval(clock)
hold.draw() holdQueue.draw()
matrix.draw() matrix.draw()
next.draw() nextQueue.draw()
} }
function resume() { function resume() {

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webtris</title>
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<body>
<h1>WEBTRIS</h1>
<table id="leaderboard">
<caption>MEILLEURS SCORES</caption>
<?php
include "db_connect.php";
try {
$db = new PDO("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=utf8", $DB_USER, $DB_PASSWORD);
} catch (Exception $e) {
die('Erreur : ' . $e->getMessage());
}
$top10 = $db->query('SELECT player, score FROM `leaderboard` ORDER BY score DESC LIMIT 10;');
for ($i = 1; $row = $top10->fetch(); $i++) {
echo ' <tr><th class="name">' . $i . '<td class="player">' . $row['player'] . '</td><td class="value">' . $row['score'] . "</td></tr>\n";
}
$top10->closeCursor();
?>
</table>
</body>
</html>

32
options.php Normal file
View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webtris</title>
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script type="text/javascript" src="js/index.js"></script>
</head>
<body>
<h1>WEBTRIS</h1>
<div id="actions">
<?php
function addButton($action, $label) {
?>
<div><?=$label?></div>
<button type="button" onclick="changeKey(this, '<?=$action?>')">
<script>getKey("<?=$action?>")</script>
</button>
<?php }
addButton("moveLeft", "GAUCHE");
addButton("moveRight", "DROITE");
addButton("softDrop", "CHUTE LENTE");
addButton("hardDrop", "CHUTE RAPIDE");
addButton("rotateCW", "ROTATION HORAIRE");
addButton("rotateCCW", "ROTATE INVERSE");
addButton("hold", "GARDE");
addButton("pause", "PAUSE");
?>
</div>
</body>
</html>

14
publish.php Normal file
View File

@ -0,0 +1,14 @@
<?php
include "db_connect.php";
if (isset($_POST['player']) && isset($_POST['score'])) {
try {
$db = new PDO("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=utf8", $DB_USER, $DB_PASSWORD);
} catch (Exception $e) {
die('Erreur : ' . $e->getMessage());
}
$query = $db->prepare('INSERT INTO `leaderboard` (`player`, `score`) VALUES (:player, :score);');
$query->execute(array("player" => strip_tags($_POST['player']), "score" => (int) $_POST['score']));
} else {
header($_SERVER["SERVER_PROTOCOL"] . " 405 Method Not Allowed", true, 405);
}
?>

View File

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webtris</title>
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script type="text/javascript" src="js/webtris.js"></script>
</head>
<body>
<h1>WEBTRIS</h1>
<div id="grid">
<?php
function echoTable($id, $rows, $columns) {
echo " <table id='$id'>\n";
echo " <tbody>\n";
for ($y = 0; $y < $rows; $y++) {
echo " <tr>";
for ($x = 0; $x < $columns; $x++) {
echo "<td></td>";
}
echo "</tr>\n";
}
echo " </tbody>\n";
echo " </table>\n";
}
echoTable("hold", 6, 6);
echoTable("matrix", 24, 10);
echoTable("next", 24, 6);
?>
<table id="stats">
<tbody>
<tr><td class="stat-label">SCORE</td><td class="stat-value" id="score">0</td></tr>
<tr><td class="stat-label">RECORD</td><td class="stat-value" id="highScore">0</td></tr>
<tr><td class="stat-label">TEMPS</td><td class="stat-value" id="time">00:00</td></tr>
<tr><td class="stat-label">NIVEAU</td><td class="stat-value" id="level">0</td></tr>
<tr><td class="stat-label">OBJECTIF</td><td class="stat-value" id="goal">0</td></tr>
<tr><td class="stat-label">LIGNES</td><td class="stat-value" id="clearedLines">0</td></tr>
</tbody>
</table>
<div id="message"></div>
</div>
<div id="play">
<a href="webtris.html">REJOUER</a>
</div>
</body>
</html>

51
webtris.sql Normal file
View File

@ -0,0 +1,51 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `webtris`
--
-- --------------------------------------------------------
--
-- Table structure for table `leaderboard`
--
CREATE TABLE `leaderboard` (
`id` int(11) NOT NULL,
`player` varchar(20) NOT NULL,
`score` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `leaderboard`
--
ALTER TABLE `leaderboard`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `leaderboard`
--
ALTER TABLE `leaderboard`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;