mirror of
https://github.com/MaciejkaG/statki.git
synced 2024-11-29 22:52:55 +01:00
A lot of changes including design, backend setup etc.
This commit is contained in:
parent
b04d67a8cf
commit
c6275be106
60
index.js
Normal file
60
index.js
Normal file
@ -0,0 +1,60 @@
|
||||
import express from 'express';
|
||||
import { createServer } from 'node:http';
|
||||
import { Server } from 'socket.io';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import session from "express-session";
|
||||
import { engine } from 'express-handlebars';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const app = express();
|
||||
|
||||
app.engine('handlebars', engine());
|
||||
app.set('view engine', 'handlebars');
|
||||
app.set('views', './views');
|
||||
|
||||
const server = createServer(app);
|
||||
const io = new Server(server);
|
||||
|
||||
const sessionMiddleware = session({
|
||||
secret: uuidv4(),
|
||||
resave: true,
|
||||
saveUninitialized: true,
|
||||
});
|
||||
|
||||
app.use(sessionMiddleware);
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
io.engine.use(sessionMiddleware);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.render('index');
|
||||
});
|
||||
|
||||
app.get("/pvp", (req, res) => {
|
||||
res.render('pvp/index');
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(7777, () => {
|
||||
console.log('Server running at http://localhost:7777');
|
||||
});
|
1459
package-lock.json
generated
Normal file
1459
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "statki-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Backend do gry w statki",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/MaciejkaG/statki-backend.git"
|
||||
},
|
||||
"author": "Maciejka",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MaciejkaG/statki-backend/issues"
|
||||
},
|
||||
"homepage": "https://github.com/MaciejkaG/statki-backend#readme",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"express-handlebars": "^7.1.2",
|
||||
"express-session": "^1.17.3",
|
||||
"socket.io": "^4.7.2",
|
||||
"uuid": "^9.0.1",
|
||||
"uuid4": "^2.0.3"
|
||||
}
|
||||
}
|
165
public/assets/css/board.css
Normal file
165
public/assets/css/board.css
Normal file
@ -0,0 +1,165 @@
|
||||
:root {
|
||||
font-size: 20px;
|
||||
|
||||
|
||||
--field: rgb(201, 201, 201);
|
||||
--mark-line: rgb(136, 136, 136);
|
||||
--mark-spot: rgb(68, 68, 68);
|
||||
--mark-ship-valid: hsl(120, 100%, 80%);
|
||||
--mark-ship-invalid: hsl(0, 100%, 80%);
|
||||
--ship-valid: hsl(120, 70%, 55%);
|
||||
--ship-invalid: hsl(0, 70%, 55%);
|
||||
|
||||
--dynamic: rgb(83, 83, 245);
|
||||
--danger: rgb(243, 56, 56);
|
||||
--important: rgb(203, 50, 241);
|
||||
color: rgb(136, 136, 136)
|
||||
}
|
||||
|
||||
body {
|
||||
background: black;
|
||||
color: white;
|
||||
font-family: 'Lato', sans-serif;
|
||||
transition: opacity 0.3s ease;
|
||||
animation: fadeIn 1 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
.designerTag {
|
||||
position: fixed;
|
||||
bottom: 5px;
|
||||
left: 5px;
|
||||
color: rgb(0, 255, 0);
|
||||
font-size: 9px;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
z-index: 999;
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
}
|
||||
|
||||
.board {
|
||||
display: flex;
|
||||
grid-template-columns: auto auto auto;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-bottom: 0.4rem;
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
background-color: var(--field);
|
||||
width: 2rem;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 20%;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.field svg {
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.field.hit svg {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dynamic {
|
||||
color: var(--dynamic);
|
||||
}
|
||||
|
||||
.danger {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.important {
|
||||
color: var(--important);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.shapes h2, .shapes h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.shapes, .spaceFiller {
|
||||
width: 15rem;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.break {
|
||||
display: block;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.panelContainer {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.boardContainer {
|
||||
width: 25rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#secondaryBoard, #board {
|
||||
position: absolute;
|
||||
transition: transform 0.3s;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.ownBoardInfo {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
transform: translateX(75%) scale(0.3);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#board:not(.secondary), #secondaryBoard:not(.secondary) {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.controlsOwnBoard {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
@keyframes changingOut {
|
||||
from {transform: translateX(0);opacity:1;}
|
||||
to {transform: translateX(30%);opacity:0;}
|
||||
}
|
||||
|
||||
@keyframes changingIn {
|
||||
from {transform: translateX(-30%);opacity:0;}
|
||||
to {transform: translateX(0);opacity:1;}
|
||||
}
|
||||
|
||||
#selectedShip.changing {
|
||||
opacity: 0;
|
||||
animation: changingOut 1 0.2s ease;
|
||||
}
|
||||
|
||||
#selectedShip {
|
||||
animation: changingIn 1 0.2s ease;
|
||||
}
|
49
public/assets/js/battleships_lib.js
Normal file
49
public/assets/js/battleships_lib.js
Normal file
@ -0,0 +1,49 @@
|
||||
class Battleships {
|
||||
constructor(boardSize) {
|
||||
if (boardSize>0) {
|
||||
this.boardSize = boardSize;
|
||||
} else {
|
||||
throw new Error("Wrong boardSize for the 'Battleships' class");
|
||||
}
|
||||
}
|
||||
|
||||
generateDOMBoard(size) {
|
||||
let board = "";
|
||||
for (var i = 0; i < size; i++) {
|
||||
let row = "<div class=\"row\">";
|
||||
for (var n = 0; n < size; n++) {
|
||||
row += `<div class="field" data-pos-x="${i}" data-pos-y="${n}"><svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='none' viewBox='0 0 100 100'><path d='M100 0 L0 100 ' stroke='black' stroke-width='3'/><path d='M0 0 L100 100 ' stroke='black' stroke-width='3'/></svg></div>`;
|
||||
}
|
||||
row += "</div>";
|
||||
board += row;
|
||||
}
|
||||
|
||||
return board;
|
||||
}
|
||||
|
||||
getField(x, y) {
|
||||
if (0 < x && x <= this.boardSize && 0 < y && y <= this.boardSize) {
|
||||
return $(`#board .row:nth-child(${y}) .field:nth-child(${x})`);
|
||||
} else {
|
||||
throw new RangeError("getField position out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
getRow(row) {
|
||||
row = parseInt(row)+1
|
||||
if (row<=this.boardSize) {
|
||||
return $(`#board .row:nth-child(${row}) .field`);
|
||||
} else {
|
||||
throw new RangeError("getColumn position out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
getColumn(column) {
|
||||
column = parseInt(column)+1
|
||||
if (column<=this.boardSize) {
|
||||
return $(`#board .row .field:nth-child(${column})`);
|
||||
} else {
|
||||
throw new RangeError("getColumn position out of range.");
|
||||
}
|
||||
}
|
||||
}
|
13
public/assets/js/key_handling.js
Normal file
13
public/assets/js/key_handling.js
Normal file
@ -0,0 +1,13 @@
|
||||
document.addEventListener("keydown", (e) => {
|
||||
switch (e.code) {
|
||||
case "KeyB":
|
||||
switchBoards();
|
||||
break;
|
||||
case "KeyS":
|
||||
switchShips();
|
||||
break;
|
||||
case "KeyR":
|
||||
switchRotation();
|
||||
break;
|
||||
}
|
||||
});
|
225
public/assets/js/main.js
Normal file
225
public/assets/js/main.js
Normal file
@ -0,0 +1,225 @@
|
||||
const mapSize = 10;
|
||||
|
||||
const bsc = new Battleships(mapSize);
|
||||
|
||||
let board = bsc.generateDOMBoard(mapSize);
|
||||
$("#board").html(board);
|
||||
$("#secondaryBoard").html(board);
|
||||
|
||||
var previousRow = $(":not(*)");
|
||||
var previousColumn = $(":not(*)");
|
||||
var selectedShip = 0;
|
||||
var shipRotation = 0;
|
||||
var changedFields = [];
|
||||
|
||||
var hoveredField = null;
|
||||
|
||||
$("#board .field").hover(function () {
|
||||
hoveredField = this;
|
||||
// Pokaż "miarki"
|
||||
let posY = parseInt($(this).data("pos-x"));
|
||||
let posX = parseInt($(this).data("pos-y"));
|
||||
let row = bsc.getRow(posY);
|
||||
let column = bsc.getColumn(posX);
|
||||
|
||||
changedFields.push(row, column, $(this));
|
||||
|
||||
row.css("background", "rgb(136, 136, 136)");
|
||||
column.css("background", "rgb(136, 136, 136)");
|
||||
|
||||
$(this).css("background", "rgb(68, 68, 68)");
|
||||
|
||||
previousRow = row;
|
||||
previousColumn = column;
|
||||
|
||||
// Pokaż podgląd statku
|
||||
posX++;
|
||||
posY++;
|
||||
var fields = [];
|
||||
switch (shipRotation) {
|
||||
case 0:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX + i, posY]);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX, posY + i]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX - i, posY]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX, posY - i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var fieldElem;
|
||||
let failed = false;
|
||||
for (let i = 0; i < selectedShip+1; i++) {
|
||||
const field = fields[i];
|
||||
|
||||
try {
|
||||
fieldElem = bsc.getField(field[0], field[1]);
|
||||
} catch {
|
||||
if (!failed) {
|
||||
failed = true;
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
fieldElem.css("background", "rgb(255, 163, 163)");
|
||||
} else {
|
||||
fieldElem.css("background", "rgb(163, 255, 163)");
|
||||
}
|
||||
changedFields.push(fieldElem);
|
||||
}
|
||||
}, function () {
|
||||
hoveredField = null;
|
||||
// Wyłącz "miarki" po wyjściu kursora z pola (aby się nie duplikowały w przyszłości)
|
||||
changedFields.forEach(field => {
|
||||
field.css("background", "rgb(201, 201, 201)");
|
||||
});
|
||||
changedFields.length = 0;
|
||||
});
|
||||
|
||||
$("#board .field").on("click", function() {
|
||||
|
||||
});
|
||||
|
||||
var ownBoardIsActive = true;
|
||||
|
||||
function switchBoards() {
|
||||
if (ownBoardIsActive) { // Aktywna jest plansza użytkownika
|
||||
$("#secondaryBoard").removeClass("secondary");
|
||||
$("#board").addClass("secondary");
|
||||
$(".ownBoardInfo").css("opacity", 0);
|
||||
$(".controlsOwnBoard").css("opacity", 0.3);
|
||||
} else { // Aktywna jest plansza przeciwnika
|
||||
$("#board").removeClass("secondary");
|
||||
$("#secondaryBoard").addClass("secondary");
|
||||
$(".ownBoardInfo").css("opacity", 1);
|
||||
$(".controlsOwnBoard").css("opacity", 1);
|
||||
}
|
||||
|
||||
ownBoardIsActive = !ownBoardIsActive;
|
||||
}
|
||||
|
||||
function switchShips() {
|
||||
if (selectedShip===3) {
|
||||
selectedShip = 0;
|
||||
} else {
|
||||
selectedShip++;
|
||||
}
|
||||
|
||||
refreshBoardView();
|
||||
|
||||
$("#selectedShip").addClass("changing");
|
||||
|
||||
setTimeout(() => {
|
||||
switch (selectedShip) {
|
||||
case 0:
|
||||
$("#selectedShip").html("Jednomasztowiec");
|
||||
break;
|
||||
case 1:
|
||||
$("#selectedShip").html("Dwumasztowiec");
|
||||
break;
|
||||
case 2:
|
||||
$("#selectedShip").html("Trójmasztowiec");
|
||||
break;
|
||||
case 3:
|
||||
$("#selectedShip").html("Czteromasztowiec");
|
||||
break;
|
||||
}
|
||||
|
||||
$("#selectedShip").removeClass("changing");
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function switchRotation() {
|
||||
if (shipRotation === 3) {
|
||||
shipRotation = 0;
|
||||
} else {
|
||||
shipRotation++;
|
||||
}
|
||||
|
||||
refreshBoardView();
|
||||
}
|
||||
|
||||
function refreshBoardView() {
|
||||
if (hoveredField) {
|
||||
changedFields.forEach(field => {
|
||||
field.css("background", "rgb(201, 201, 201)");
|
||||
});
|
||||
changedFields.length = 0;
|
||||
|
||||
let posY = parseInt($(hoveredField).data("pos-x"));
|
||||
let posX = parseInt($(hoveredField).data("pos-y"));
|
||||
let row = bsc.getRow(posY);
|
||||
let column = bsc.getColumn(posX);
|
||||
|
||||
changedFields.push(row, column, $(hoveredField));
|
||||
|
||||
row.css("background", "rgb(136, 136, 136)");
|
||||
column.css("background", "rgb(136, 136, 136)");
|
||||
|
||||
$(hoveredField).css("background", "rgb(68, 68, 68)");
|
||||
|
||||
previousRow = row;
|
||||
previousColumn = column;
|
||||
|
||||
posX++;
|
||||
posY++;
|
||||
var fields = [];
|
||||
switch (shipRotation) {
|
||||
case 0:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX + i, posY]);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX, posY + i]);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX - i, posY]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (let i = 0; i < 4; i++) {
|
||||
fields.push([posX, posY - i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var fieldElem;
|
||||
let failed = false;
|
||||
for (let i = 0; i < selectedShip + 1; i++) {
|
||||
const field = fields[i];
|
||||
|
||||
try {
|
||||
fieldElem = bsc.getField(field[0], field[1]);
|
||||
} catch {
|
||||
if (!failed) {
|
||||
failed = true;
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
fieldElem.css("background", "rgb(255, 163, 163)");
|
||||
} else {
|
||||
fieldElem.css("background", "rgb(163, 255, 163)");
|
||||
}
|
||||
changedFields.push(fieldElem);
|
||||
}
|
||||
}
|
||||
}
|
0
public/assets/js/matchmaking.js
Normal file
0
public/assets/js/matchmaking.js
Normal file
47
views/game.handlebars
Normal file
47
views/game.handlebars
Normal file
@ -0,0 +1,47 @@
|
||||
<!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>
|
16
views/index-old.html
Normal file
16
views/index-old.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!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>
|
63
views/index.handlebars
Normal file
63
views/index.handlebars
Normal file
@ -0,0 +1,63 @@
|
||||
<!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>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>
|
||||
|
||||
<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>
|
1
views/layouts/main.handlebars
Normal file
1
views/layouts/main.handlebars
Normal file
@ -0,0 +1 @@
|
||||
{{{body}}}
|
83
views/pvp/create.handlebars
Normal file
83
views/pvp/create.handlebars
Normal file
@ -0,0 +1,83 @@
|
||||
<!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>
|
70
views/pvp/index.handlebars
Normal file
70
views/pvp/index.handlebars
Normal file
@ -0,0 +1,70 @@
|
||||
<!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>
|
86
views/pvp/join.handlebars
Normal file
86
views/pvp/join.handlebars
Normal file
@ -0,0 +1,86 @@
|
||||
<!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>
|
Loading…
Reference in New Issue
Block a user