Multiple cool changes, added own SPA framework

This commit is contained in:
MaciejkaG 2024-01-06 21:09:41 +01:00
parent c6275be106
commit c2975bedc9
14 changed files with 332 additions and 373 deletions

View File

@ -34,22 +34,15 @@ app.get("/", (req, res) => {
res.render('index');
});
app.get("/pvp", (req, res) => {
res.render('pvp/index');
app.get("/*", (req, res) => {
res.redirect("/?path=" + req.originalUrl);
});
app.get("/pvp/join", (req, res) => {
res.render('pvp/join');
});
app.get("/pvp/create", (req, res) => {
res.render('pvp/create');
});
io.on('connection', (socket) => {
const session = socket.request.session;
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
});

View File

@ -5,7 +5,8 @@
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node ."
},
"repository": {
"type": "git",

View File

@ -93,6 +93,7 @@ h1,h2,h3,h4,h5,h6 {
display: flex;
justify-content: center;
text-align: center;
transition: 0.15s opacity;
}
.shapes h2, .shapes h3 {

133
public/assets/css/main.css Normal file
View File

@ -0,0 +1,133 @@
.container {
display: none;
}
/* index */
#mainMenuView .modes {
display: flex;
gap: 2rem;
}
#mainMenuView .modes div {
height: 10rem;
width: 10rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
cursor: pointer;
transition: all 0.3s;
}
#mainMenuView .modes div:hover {
background: white;
color: black;
}
/* PvP/index */
#pvpMenuView .modes {
display: flex;
gap: 2rem;
}
#pvpMenuView .modes div {
height: 10rem;
width: 10rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
cursor: pointer;
transition: all 0.3s;
}
#pvpMenuView .modes div:hover {
background: white;
color: black;
}
/* PvP/create */
#pvpCreateView .modes {
display: flex;
gap: 2rem;
}
#pvpCreateView .modes div {
height: 17rem;
width: 15rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
padding: 1rem 3rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
#pvpCreateView input, #pvpCreateView button {
background: black;
color: white;
border-radius: 15px;
border: 1px solid white;
font-size: 1.5rem;
text-align: center;
padding: 0.5rem 2rem;
outline: none;
transition: opacity 0.2s;
}
#pvpCreateView button {
cursor: pointer;
font-size: 1rem;
transition: all 0.3s;
}
#pvpCreateView button:hover {
background: white;
color: black;
}
/* PvP/join */
#pvpJoinView .modes {
display: flex;
gap: 2rem;
}
#pvpJoinView .modes div {
height: 7rem;
width: 15rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
padding: 2rem 3rem;
}
#pvpJoinView form {
display: flex;
flex-direction: column;
gap: 2rem;
}
#pvpJoinView form input {
background: black;
color: white;
border-radius: 15px;
border: 1px solid white;
font-size: 1.5rem;
text-align: center;
padding: 0.5rem 2rem;
outline: none;
}
#pvpJoinView form input[type=submit] {
cursor: pointer;
font-size: 1rem;
transition: all 0.3s;
}
#pvpJoinView form input[type=submit]:hover {
background: white;
color: black;
}

View File

@ -0,0 +1,2 @@
const socket = io();

View File

@ -0,0 +1,44 @@
var activeView;
function switchView(viewContainerId, useReplaceState=false) {
$(`.container`).css("opacity", 0);
setTimeout(() => {
$(`.container`).css("display", "none");
$(`.container#${viewContainerId}`).css({"display": "flex", "opacity": "1"});
let path = $(`.container#${viewContainerId}`).data("path");
let title = $(`.container#${viewContainerId}`).data("title");
if (useReplaceState) {
history.replaceState(null, "", path ? path : "/");
} else {
history.pushState(null, title ? title : "Statki", path ? path : "/");
}
activeView = viewContainerId;
}, 150);
}
const initialURLParams = new URLSearchParams(window.location.search);
const initialPath = initialURLParams.get('path');
window.addEventListener("load", () => {
if (initialPath != null) {
let elem = document.querySelector(`.container[data-path="${initialPath}"]`);
if (elem != null) {
switchView(elem.id, true);
activeView = elem.id;
}
} else {
switchView("mainMenuView");
activeView = "mainMenuView";
}
});
addEventListener("popstate", (event) => {
event.preventDefault();
let elem = document.querySelector(`.container[data-path="${window.location.pathname}"]`);
if (elem != null) {
switchView(elem.id, true);
}
});

View File

@ -1,47 +0,0 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statki</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Poppins:ital,wght@0,600;1,600&family=Roboto+Mono:ital@0;1&display=swap" rel="stylesheet"> <link rel="stylesheet" href="assets/css/board.css">
</head>
<body>
<div class="container">
<div>
<h1>Statki</h1>
<div class="panelContainer">
<div class="shapes">
<div class="ownBoardInfo">
<h3>Wybrany statek</h3>
<h2 class="dynamic" id="selectedShip">Jednomasztowiec</h2>
<h3>Dostępne: <span class="dynamic danger">1</span></h3>
</div>
<span class="break"></span>
<h2>Sterowanie</h2>
<h3 class="controlsOwnBoard"><span class="important">S</span> Zmiana statku</h3>
<h3 class="controlsOwnBoard"><span class="important">R</span> Obrót statku</h3>
<h3><span class="important">B</span> Zamiana planszy</h3>
<span class="break"></span>
<h3>Ruch: <span class="dynamic">Przeciwnik</span></h3>
<h2 class="important">∞</h2>
</div>
<div class="boardContainer">
<div id="board" oncontextmenu="return false;"></div>
<div id="secondaryBoard" class="secondary" oncontextmenu="return false;"></div>
</div>
<div class="spaceFiller"></div>
</div>
<span class="designerTag">Designed by Maciejka</span>
</div>
</div>
<script src="/assets/js/battleships_lib.js"></script>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/key_handling.js"></script>
</body>
</html>

View File

@ -1,16 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
</head>
<body>
<h1>Test</h1>
<script>
const socket = io();
</script>
</body>
</html>

View File

@ -1,63 +1,130 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statki</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Poppins:ital,wght@0,600;1,600&family=Roboto+Mono:ital@0;1&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/css/board.css">
<style>
.modes {
display: flex;
gap: 2rem;
}
<div class="container" id="loadingView" data-title="Statki" data-path="/">
.modes div {
height: 10rem;
width: 10rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
cursor: pointer;
transition: all 0.3s;
}
</div>
.modes div:hover {
background: white;
color: black;
}
</style>
</head>
<body>
<div class="container">
<div>
<h1>Statki</h1>
<h2>Wybierz tryb gry</h2>
<div class="modes">
<div id="pvp">
<h2>PvP</h2>
<p>Graj przeciwko innemu graczowi</p>
</div>
<div>
<h2 id="ai">Vs. AI</h2>
<p>Graj przeciwko komputerowi</p>
</div>
<div class="container" id="mainMenuView" data-title="Statki" data-path="/">
<div>
<h1>Statki</h1>
<h2>Wybierz tryb gry</h2>
<div class="modes">
<div id="pvpMenuButton">
<h2>PvP</h2>
<p>Graj przeciwko innemu graczowi</p>
</div>
<div>
<h2 id="ai">Vs. AI</h2>
<p>Graj przeciwko komputerowi</p>
</div>
<span class="designerTag">Designed by Maciejka</span>
<script>
$("#pvp").on("click", function() {
$("body").css("opacity", "0");
setTimeout(() => {
window.location.href = "pvp";
}, 300);
});
</script>
</div>
</div>
</body>
</html>
</div>
<div class="container" id="pvpMenuView" data-title="Statki / PvP" data-path="/pvp">
<div>
<h1>Statki</h1>
<h2>PvP</h2>
<div class="modes">
<div id="createGameButton">
<h2>Stwórz</h2>
<p>Stwórz własny pokój</p>
</div>
<div onclick="switchView('gameView')">
<h2>Dołącz</h2>
<p>Dołącz do czyjegoś pokoju poprzez kod</p>
</div>
</div>
</div>
</div>
<div class="container" id="pvpCreateView" data-title="Statki / PvP / Stwórz" data-path="/pvp/create">
<div>
<h1>Statki</h1>
<h2>PvP / Stwórz</h2>
<div class="modes">
<div>
<h2>Kod pokoju:</h2>
<input type="text" maxlength="6" readonly value="123456">
<h3>Oczekiwanie na gracza...</h3>
<button>Opuść pokój</button>
</div>
</div>
</div>
</div>
<div class="container" id="pvpJoinView" data-title="Statki / PvP / Dołącz" data-path="/pvp/join">
<div>
<h1>Statki</h1>
<h2>PvP / Dołącz</h2>
<div class="modes">
<div>
<form action="/api/joinme" id="pvpJoinForm">
<input type="text" maxlength="6" id="pvpJoinCode" placeholder="Kod pokoju">
<input type="submit" value="Dołącz">
</form>
</div>
</div>
</div>
</div>
<div class="container" id="gameView" data-title="Statki / Gra" data-path="/game">
<div>
<h1>Statki</h1>
<div class="panelContainer">
<div class="shapes">
<div class="ownBoardInfo">
<h3>Wybrany statek</h3>
<h2 class="dynamic" id="selectedShip">Jednomasztowiec</h2>
<h3>Dostępne: <span class="dynamic danger">1</span></h3>
</div>
<span class="break"></span>
<h2>Sterowanie</h2>
<h3 class="controlsOwnBoard"><span class="important">S</span> Zmiana statku</h3>
<h3 class="controlsOwnBoard"><span class="important">R</span> Obrót statku</h3>
<h3><span class="important">B</span> Zamiana planszy</h3>
<span class="break"></span>
<h3>Ruch: <span class="dynamic">Przeciwnik</span></h3>
<h2 class="important">∞</h2>
</div>
<div class="boardContainer">
<div id="board" oncontextmenu="return false;"></div>
<div id="secondaryBoard" class="secondary" oncontextmenu="return false;"></div>
</div>
<div class="spaceFiller"></div>
</div>
</div>
<script src="/assets/js/battleships_lib.js"></script>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/key_handling.js"></script>
</div>
<script src="/assets/js/socket.js"></script>
<script src="/assets/js/spa_lib.js"></script>
<script>
$("#createGameButton").on("click", function () {
$("#pvpCreateView .modes input").css("filter", "blur(20px)");
$("#pvpCreateView .modes").css("pointer-events", "none");
switchView("pvpCreateView");
});
$("#pvpMenuButton").on("click", function () {
socket.emit("check pvp eligibility", (response) => {
if (response.status) {
}
});
switchView('pvpMenuView')
});
const form = document.getElementById('pvpJoinForm');
const input = document.getElementById('pvpJoinCode');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value && input.value.length === 6) {
socket.emit('join game', input.value);
input.value = '';
}
});
</script>

View File

@ -1 +1,21 @@
{{{body}}}
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statki</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Poppins:ital,wght@0,600;1,600&family=Roboto+Mono:ital@0;1&display=swap" rel="stylesheet">
<script src="https://cdn.socket.io/4.7.3/socket.io.min.js"></script>
<link rel="stylesheet" href="/assets/css/board.css">
<link rel="stylesheet" href="/assets/css/main.css">
</head>
<body>
<span class="designerTag">Designed by Maciejka</span>
{{{body}}}
</body>
</html>

View File

@ -1,83 +0,0 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statki</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Poppins:ital,wght@0,600;1,600&family=Roboto+Mono:ital@0;1&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/css/board.css">
<style>
.modes {
display: flex;
gap: 2rem;
}
.modes div {
height: 17rem;
width: 15rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
padding: 1rem 3rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
input, button {
background: black;
color: white;
border-radius: 15px;
border: 1px solid white;
font-size: 1.5rem;
text-align: center;
padding: 0.5rem 2rem;
outline: none;
}
button {
cursor: pointer;
font-size: 1rem;
transition: all 0.3s;
}
button:hover {
background: white;
color: black;
}
</style>
</head>
<body>
<div class="container">
<div>
<h1>Statki</h1>
<h2>PvP / Stwórz</h2>
<div class="modes">
<div>
<h2>Kod pokoju:</h2>
<input type="text" maxlength="6" readonly value="123456">
<h3>Oczekiwanie na gracza...</h3>
<button>Opuść pokój</button>
</div>
</div>
<span class="designerTag">Designed by Maciejka</span>
<script>
const form = document.getElementById('form');
const input = document.getElementById('input');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value && input.value.length===6) {
socket.emit('join game', input.value);
input.value = '';
}
});
</script>
</div>
</div>
</body>
</html>

View File

@ -1,70 +0,0 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statki</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Poppins:ital,wght@0,600;1,600&family=Roboto+Mono:ital@0;1&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/css/board.css">
<style>
.modes {
display: flex;
gap: 2rem;
}
.modes div {
height: 10rem;
width: 10rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
cursor: pointer;
transition: all 0.3s;
}
.modes div:hover {
background: white;
color: black;
}
</style>
</head>
<body>
<div class="container">
<div>
<h1>Statki</h1>
<h2>PvP</h2>
<div class="modes">
<div id="create">
<h2>Stwórz</h2>
<p>Stwórz własny pokój</p>
</div>
<div id="join">
<h2>Dołącz</h2>
<p>Dołącz do czyjegoś pokoju poprzez kod</p>
</div>
</div>
<span class="designerTag">Designed by Maciejka</span>
<script>
$("#create").on("click", function() {
$("body").css("opacity", "0");
setTimeout(() => {
window.location.href = "/pvp/create";
}, 300);
});
$("#join").on("click", function() {
$("body").css("opacity", "0");
setTimeout(() => {
window.location.href = "/pvp/join";
}, 300);
});
</script>
</div>
</div>
</body>
</html>

View File

@ -1,86 +0,0 @@
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Statki</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&family=Poppins:ital,wght@0,600;1,600&family=Roboto+Mono:ital@0;1&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/css/board.css">
<style>
.modes {
display: flex;
gap: 2rem;
}
.modes div {
height: 7rem;
width: 15rem;
background: black;
border: solid 1px white;
border-radius: 15px;
user-select: none;
padding: 2rem 3rem;
}
form {
display: flex;
flex-direction: column;
gap: 2rem;
}
form input {
background: black;
color: white;
border-radius: 15px;
border: 1px solid white;
font-size: 1.5rem;
text-align: center;
padding: 0.5rem 2rem;
outline: none;
}
form input[type=submit] {
cursor: pointer;
font-size: 1rem;
transition: all 0.3s;
}
form input[type=submit]:hover {
background: white;
color: black;
}
</style>
</head>
<body>
<div class="container">
<div>
<h1>Statki</h1>
<h2>PvP / Dołącz</h2>
<div class="modes">
<div>
<form action="/api/joinme" id="form">
<input type="text" maxlength="6" id="input" placeholder="Kod pokoju">
<input type="submit" value="Dołącz">
</form>
</div>
</div>
<span class="designerTag">Designed by Maciejka</span>
<script>
const form = document.getElementById('form');
const input = document.getElementById('input');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value && input.value.length===6) {
socket.emit('join game', input.value);
input.value = '';
}
});
</script>
</div>
</div>
</body>
</html>