mirror of
https://github.com/MaciejkaG/statki.git
synced 2024-11-30 03:42: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