Skip to content
Snippets Groups Projects
Commit bbf7d3ad authored by atm2g19's avatar atm2g19
Browse files

Battleships v1 functional

parent 6f70d54b
No related branches found
No related tags found
No related merge requests found
Showing
with 1209 additions and 35 deletions
dbconf.json
dst/
node_modules/
launch.json
log/
p5*
\ No newline at end of file
**/*.d.ts
**/*.zip
public/**/*.ts
public/**/tsconfig.json
\ No newline at end of file
......@@ -71,6 +71,14 @@
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
"integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw=="
},
"@types/multer": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.2.tgz",
"integrity": "sha512-pVcPwuC0FbVcLhopJHx8Ro3WSXjvVvEpJMfy+DFAL/3DwNYAQH+hf/Vq+PqoS5kM4mng7L/4upzXhP/12yWh4w==",
"requires": {
"@types/express": "4.17.3"
}
},
"@types/mysql": {
"version": "2.15.9",
"resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.9.tgz",
......@@ -128,6 +136,11 @@
"color-convert": "1.9.3"
}
},
"append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY="
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
......@@ -245,12 +258,49 @@
"concat-map": "0.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
"optional": true
},
"busboy": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"requires": {
"dicer": "0.2.5",
"readable-stream": "1.1.14"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.4",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
......@@ -325,6 +375,17 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"requires": {
"buffer-from": "1.1.1",
"inherits": "2.0.4",
"readable-stream": "2.3.7",
"typedarray": "0.0.6"
}
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
......@@ -400,6 +461,38 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.14",
"streamsearch": "0.1.2"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.4",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
......@@ -890,8 +983,7 @@
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"optional": true
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"minimist-options": {
"version": "3.0.2",
......@@ -906,7 +998,6 @@
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"optional": true,
"requires": {
"minimist": "1.2.5"
}
......@@ -916,6 +1007,21 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"multer": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz",
"integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==",
"requires": {
"append-field": "1.0.0",
"busboy": "0.2.14",
"concat-stream": "1.6.2",
"mkdirp": "0.5.4",
"object-assign": "4.1.1",
"on-finished": "2.3.0",
"type-is": "1.6.18",
"xtend": "4.0.2"
}
},
"mysql": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
......@@ -943,6 +1049,11 @@
"validate-npm-package-license": "3.0.4"
}
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
......@@ -1403,6 +1514,11 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"streamsearch": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
......@@ -1502,6 +1618,11 @@
"mime-types": "2.1.26"
}
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typescript": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
......@@ -1567,6 +1688,11 @@
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"yargs-parser": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
......
......@@ -11,10 +11,13 @@
"license": "ISC",
"dependencies": {
"@types/express": "^4.17.3",
"@types/multer": "^1.4.2",
"@types/mysql": "^2.15.9",
"@types/node": "^13.9.8",
"@types/socket.io": "^2.1.4",
"body-parser": "^1.19.0",
"express": "^4.17.1",
"multer": "^1.4.2",
"mysql": "^2.18.1",
"path": "^0.12.7",
"socket.io": "^2.3.0",
......
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
<script src="./game.js"></script>
</head>
<body>
<a href="./index.html">&lt_Back to games</a><br>
<div id="game">
<div id="me" style="float: left; padding: 10px;">
</div>
<div id="opponent" style="float: left;padding: 10px">
</div>
</div>
</body>
</html>
\ No newline at end of file
/// <reference path="../../../socket.io.d.ts"/>
/// <reference path="../../../p5.global-mode.d.ts"/>
let socket;
let gameID;
let username;
let game_password;
let cookies;
let canvas, battlecanvas;
let canvasContainer;
let ships = [{
x : 0,
y : 0,
rotation : "north",
size : 5,
},
{
x : 0,
y : 0,
rotation : "north",
size : 4,
},
{
x : 0,
y : 0,
rotation : "north",
size : 3,
},
{
x : 0,
y : 0,
rotation : "north",
size : 3,
},
{
x : 0,
y : 0,
rotation : "north",
size : 2,
}
];
const me = (sketch) => {
sketch.ships = ships;
sketch.placing_ship;
sketch.placed_ships = [];
sketch.shots = [];
sketch.setup = _setup.bind(sketch);
sketch.draw = _draw.bind(sketch);
sketch.drawGrid = _drawGrid.bind(sketch);
sketch.drawShip = _drawShip.bind(sketch);
sketch.checkCollisions = _checkCollisions.bind(sketch);
sketch.keyPressed = function (){
if(this.keyCode == 0x20){
this.placeShip();
}else if(this.keyCode == 0x52){
rotateShip(this.placing_ship);
}
}.bind(sketch);
sketch.placeShip = _placeShip.bind(sketch);
sketch.drawShot = _drawShot.bind(sketch);
}
const opponent = (sketch) => {
sketch.placed_ships = [];
sketch.shots = [];
sketch.setup = _battle_setup.bind(sketch);
sketch.draw = _draw.bind(sketch);
sketch.drawGrid = _drawGrid.bind(sketch);
sketch.drawShip = _drawShip.bind(sketch);
sketch.drawShot = _drawShot.bind(sketch);
// sketch.checkCollisions = _checkCollisions.bind(sketch);
sketch.fire = _fire.bind(sketch);
sketch.keyPressed = function(){
if(this.keyCode == 0x20){
this.fire();
}
}.bind(sketch);
}
new p5(me, "me");
function _setup(){
cookies = document.cookie
.split(';')
.reduce((res, c) => {
const [key, val] = c.trim().split('=').map(decodeURIComponent)
try {
return Object.assign(res, { [key]: JSON.parse(val) })
} catch (e) {
return Object.assign(res, { [key]: val })
}
}, {});
username = cookies.username;
game_password = cookies.game_password;
socket = io();
let params = this.getURLParams();
console.log(params);
if(!("id" in params)){
history.back();
return;
}else{
gameID = params.id;
}
let join_data = {
username : username,
password : game_password,
id : gameID,
}
socket.on("disconnect", console.log);
socket.emit('join', join_data);
socket.on("welcome", console.log);
socket.on("place", (data) => {
this.placed_ships = data;
this.ships = [];
this.placing_ship = null;
});
socket.on("battle", ()=>{
new p5(opponent, "opponent");
});
socket.on("shot", shot => {
console.log(shot);
this.shots.push(shot);
});
socket.onpacket(console.log);
let exit = ()=>{
socket.emit("exit");
};
let isIOS = navigator.userAgent.match(/iPad/i)|| navigator.userAgent.match(/iPhone/i);
let evtName = isIOS? "pagehide" : "beforeunload";
window.addEventListener(evtName, exit);
window.onbeforeunload = exit;
window.onunload = exit;
this.createCanvas(500, 500);
this.createElement("br");
let place = this.createButton("Place");
let rotate = this.createButton("Rotate");
place.mouseClicked(this.placeShip);
place.size(100, 30);
rotate.mouseClicked(()=>rotateShip(this.placing_ship));
rotate.size(100, 30);
this.createElement("br");
document.oncontextmenu = () => false;
this.placing_ship = this.ships.splice(0, 1)[0];
}
function _battle_setup(){
this.createCanvas(500, 500);
this.createElement("br");
let fire = this.createButton("Fire!");
fire.mouseClicked(this.fire);
fire.size(100, 30);
this.firing = {
x : 2,
y : 2,
hit : false,
};
socket.on("fire", ()=>{
this.firing = {
x : 0, y : 0, hit : false
}
});
socket.on("sunk", ship => {
this.placed_ships.push(ship);
})
socket.on("fired", (shot) => {
console.log(shot);
this.shots.pop();
if(shot){
if(shot.hit){
console.log("hit");
}else{
console.log("miss");
}
this.shots.push(shot);
}
})
// this.shots.push()
}
function _draw(){
let w = this.width/10;
let h = this.height/10;
this.background(100);
this.fill(0, 255, 0);
for(let ship of this.placed_ships){
this.drawShip(ship);
}
this.fill(255);
if(this.placing_ship){
if(this.checkCollisions(this.placing_ship))this.fill(255, 0, 0);
if(this.mouseX < this.width && this.mouseY < this.height){
this.placing_ship.x = this.floor(this.mouseX/w);
this.placing_ship.y = this.floor(this.mouseY/h);
}
this.placing_ship.hit = false;
this.drawShip(this.placing_ship);
}
for(let shot of this.shots){
this.stroke(255);
this.drawShot(shot);
}
this.stroke(0, 255, 0);
if(this.firing){
if(this.mouseX < this.width && this.mouseY < this.height){
this.firing.x = this.floor(this.mouseX/w);
this.firing.y = this.floor(this.mouseY/h);
}
this.firing.hit = false;
this.drawShot(this.firing)
}
this.drawGrid(10, 10);
}
function _drawGrid(x = 10, y = 10){
this.stroke(0);
this.strokeWeight(5);
for(let i = 0; i <= x; i++){
this.line(i*this.width/x, 0, i*this.width/x, this.height);
}
for(let j = 0; j <= y; j++){
this.line(0, j*this.height/y, this.width, j*this.height/y);
}
}
function _drawShip(ship, x = 10, y = 10){
let xCentreStart = (ship.x+0.5)*this.width/x;
let yCentreStart = (ship.y+0.5)*this.height/y;
let xCentreEnd, yCentreEnd;
xCentreEnd = xCentreStart;
yCentreEnd = yCentreStart;
let w = this.width/x;
let h = this.height/y;
switch(ship.rotation){
case "north":
yCentreEnd -= (ship.size-1)*h;
break;
case "east":
xCentreEnd += (ship.size-1)*w;
break;
case "south":
yCentreEnd += (ship.size-1)*h;
break;
case "west":
xCentreEnd -= (ship.size-1)*w;
break;
}
// fill(255);
this.noStroke();
this.ellipse(xCentreStart, yCentreStart, this.width/x-5);
this.ellipse(xCentreEnd, yCentreEnd, this.width/x-5);
this.rectMode(this.CENTER);
this.rect((xCentreStart+xCentreEnd)/2, (yCentreStart+yCentreEnd)/2, this.abs(xCentreEnd-xCentreStart) + (ship.rotation=="north" || ship.rotation=="south" ? w : 0), this.abs(yCentreEnd-yCentreStart) + (ship.rotation=="east" || ship.rotation=="west" ? w : 0));
}
function _drawShot(shot, x = 10, y = 10){
let w = this.width/x;
let h = this.height/y;
let xCentre = (shot.x+0.5)*w;
let yCentre = (shot.y+0.5)*h;
this.strokeWeight(5);
if(shot.hit == true){
this.stroke(255, 0, 0);
}
this.line(xCentre-w/2, yCentre-h/2, xCentre+w/2, yCentre+h/2);
this.line(xCentre+w/2, yCentre-h/2, xCentre-w/2, yCentre+h/2);
}
function _checkCollisions(ship){
let inx = 0, iny = 0;
switch(ship.rotation){
case "north":
iny = -1;
break;
case "east":
inx = +1;
break;
case "south":
iny = +1;
break;
case "west":
inx = -1;
break;
}
for(let i = 0; i < ship.size; i++){
let shipX = ship.x + inx*i;
let shipY = ship.y + iny*i;
if(shipX < 0 || shipX >= 10) return true;
if(shipY < 0 || shipY >= 10) return true;
for(let other_ship of this.placed_ships){
let oinx = 0, oiny = 0;
switch(other_ship.rotation){
case "north":
oiny = -1;
break;
case "east":
oinx = +1;
break;
case "south":
oiny = +1;
break;
case "west":
oinx = -1;
break;
}
for(let j = 0; j < other_ship.size; j++){
let oX = other_ship.x + oinx*j;
let oY = other_ship.y + oiny*j;
if(oX == shipX && oY == shipY) return true;
}
}
}
return false;
}
function _placeShip(){
if(this.placing_ship == null || this.checkCollisions(this.placing_ship) ) return;
this.placed_ships.push(Object.assign({}, this.placing_ship));
this.placing_ship = this.ships.splice(0, 1)[0];
if(this.placing_ship == null){
socket.emit("place", this.placed_ships);
console.log("All ships placed!");
}
}
function rotateShip(ship){
if(!ship)return;
switch(ship.rotation){
case "north":
ship.rotation = "east";
break;
case "east":
ship.rotation = "south";
break;
case "south":
ship.rotation = "west";
break;
case "west":
ship.rotation = "north";
break;
}
}
function _fire(){
if(!this.firing) return;
this.shots.push(this.firing);
socket.emit("fire", this.firing);
this.firing = null;
}
function mousePressed(e){
return;
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
// some code..
return;
}
e.preventDefault();
if(mouseButton == RIGHT){
rotateShip();
}else{
_placeShip();
}
console.log("mouse pressed");
}
......@@ -3,12 +3,13 @@
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
<script src="./battleships.js"></script>
<script src="../game_loader.js"></script>
</head>
<body>
<h1>
Battleships game
</h1>
<a href="../">&lt- Back to Games!</a><br><br>
<!-- <p>
Current running games: <br>
</!-->
......
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
<script src="./game.js"></script>
</head>
<body>
<a href="./index.html">&lt_Back to games</a><br>
<div id="game">
<div id="defend" style="float: left; padding: 10px;">
</div>
<div id="attack" style="float: left;padding: 10px">
</div>
</div>
</body>
</html>
\ No newline at end of file
/// <reference path="../../../p5.global-mode.d.ts" />
let builder = (sketch) => { return (p) => { for (let key in sketch)
if (typeof (sketch[key]) == "function")
p[key] = sketch[key].bind(p);
else
p[key] = sketch[key]; }; };
var rotation;
(function (rotation) {
rotation["NORTH"] = "north";
rotation["EAST"] = "east";
rotation["SOUTH"] = "south";
rotation["WEST"] = "west";
})(rotation || (rotation = {}));
const base = {
draw: function () {
this.background(100);
//draw ships
//draw shots
//draw grid
this.drawGrid();
},
drawGrid: function () {
this.strokeWeight(5);
this.stroke(0);
for (let i = 0; i <= this.x; i++) {
this.line(i * this.width / this.x, 0, i * this.width / this.x, this.height);
}
for (let i = 0; i <= this.y; i++) {
this.line(0, i * this.height / this.y, this.width, i * this.height / this.y);
}
},
drawShip: function (ship) {
}
};
const defend = {
...base,
x: 10,
y: 10,
setup: function () {
this.createCanvas(500, 500);
},
};
const attack = {
...base,
x: 10,
y: 10,
setup: function () {
this.createCanvas(500, 500);
}
};
const defender = new p5(builder(defend), "defend");
const attacker = new p5(builder(attack), "attack");
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
<script src="../game_loader.js"></script>
</head>
<body>
<h1>
Battleships 2.0 game
</h1>
<a href="../">&lt- Back to Games!</a><br><br>
<!-- <p>
Current running games: <br>
</!-->
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
<script src="../game_loader.js"></script>
</head>
<body>
<h1>
Cards against humanity Game!
</h1>
<a href="../">&lt- Back to Games!</a><br><br>
<!-- <p>
Current running games: <br>
</!-->
</body>
</html>
\ No newline at end of file
/// <reference path="../../../p5.global-mode.d.ts"/>
/// <reference path="../../p5.global-mode.d.ts"/>
let socket;
let GamesList;
let game;
function setup(){
noCanvas();
socket = io.connect("http://localhost:8080");
let newGame = createButton("New Game");
newGame.mouseClicked(createGame);
......@@ -14,6 +12,9 @@ function setup(){
refresh.mouseClicked(refreshList);
let path = getURLPath();
game = path[path.lastIndexOf("games")+1];
GamesList = createDiv();
createP("Current running games: ").parent(GamesList);
......@@ -25,22 +26,28 @@ function setup(){
function refreshList(){
let children = GamesList.child();
while(children.length > 0){
children[0].remove();
}
let path = getURLPath();
let game = path[path.lastIndexOf("games")+1];
fetch("/games/api/list/battleships")
fetch(`/games/api/list/${game}`)
.then(response => {
console.log(response);
// console.log(response);
return response.json();
})
.then(json => {
console.log(json);
for(let game of json){
createElement("li", `${JSON.stringify(game)}`).parent(GamesList);
// console.log(json);
let children = GamesList.child();
while(children.length > 0) children[0].remove();
for(let _game of json){
let child = createElement("li");
child.parent(GamesList);
child.html(JSON.stringify(_game));
let join_button = createButton("Join");
join_button.parent(child);
join_button.mouseClicked(joinGame.bind(_game));
// child.html(`<a href='/games/${game}/game.html?id=${_game.id}'>Join</a>`, true);
// createElement("li", `${JSON.stringify(game)}`).parent(GamesList);
}
})
.catch(err =>{
......@@ -48,6 +55,23 @@ function refreshList(){
});
}
function joinGame(){
if(document.cookie.indexOf("username") == -1){
let uname = prompt("You need to choose a username first!", "username");
document.cookie = `username=${uname}`;
return;
}
let password = "";
if(this.password_protected){
password = prompt("Please enter the password for this game.");
}
document.cookie = `game_password=${password}`;
location.assign(`/games/${game}/game.html?id=${this.id}`);
}
function createGame(){
let name = prompt("Please enter game name", "name");
......@@ -57,7 +81,7 @@ function createGame(){
password : password,
};
fetch("/games/api/create/battleships", {
fetch(`/games/api/create/${game}`, {
method : "POST",
body : JSON.stringify(data),
headers : {
......
......@@ -19,6 +19,11 @@
Battleships
</a>
</li>
<li>
<a href="./battleships_v2//">
Battleships v2
</a>
</li>
</p>
......
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
<script src="../game_loader.js"></script>
</head>
<body>
<h1>
#{TEMPLATE} Game!
</h1>
<a href="../">&lt- Back to Games!</a><br><br>
<!-- <p>
Current running games: <br>
</!-->
</body>
</html>
\ No newline at end of file
......@@ -36,7 +36,8 @@ function handled_error(err : express.Errback, req : express.Request, res : expre
res.status(500);
sendFile(`public/errors/500.html`, req, res, next);
console.log("SERVER ERROR")
console.log(err);
// next();
}
......
......@@ -4,6 +4,18 @@ interface DB {
};
interface game_data {
name : string,
players : string[],
[key : string] : any,
}
interface game {
id : number,
type_id : number,
data : game_data,
}
export interface QueryResults {
err? : mysql.MysqlError;
results? : any;
......@@ -19,12 +31,37 @@ export class GameDB{
});
}
query(sql : string, values? : any) : Promise<QueryResults>{
async query(sql : string, values? : any) : Promise<QueryResults>{
return new Promise((resolve, reject) => {
this.pool.query(sql, values, (err : mysql.MysqlError, results : any[], fields : mysql.FieldInfo[]) => {
if(err) reject(err);
resolve({err, results, fields} as QueryResults);
})
})
}
async getActiveGames(game : string | number) : Promise<game[]>{
let query : string
if(typeof(game) == 'number' || /^[0-9]+$/.test(game)){
query = `SELECT games.game_id, games.game_name FROM games WHERE games.game_id = ${game};`;
}else{
query = `SELECT games.game_id, games.game_name FROM games WHERE games.game_name = ${mysql.escape(game)};`;
}
let game_id = (await this.query(query)).results[0].game_id;
let query_results = await this.query(`SELECT active_game_id, active_game_type_id, game_id, data_value FROM active_games, game_data WHERE game_id = active_game_id AND active_game_type_id = ${game_id} AND data_key = 0;`);
let games : game[] = [];
for(let row of query_results.results){
let game : game = {
id : row.game_id,
type_id : row.active_game_type_id,
data : JSON.parse(row.data_value),
}
games.push(game);
}
return games;
}
}
\ No newline at end of file
......@@ -60,7 +60,8 @@ let socket;
function joinGame(socket : io.Socket, args : any){
console.log(`Join game request : ${args}`);
console.log(`Join game request : `);
console.log(args);
//check game id exists
......@@ -70,15 +71,21 @@ function joinGame(socket : io.Socket, args : any){
console.log(res.err);
return;
}
console.log(res.results);
// console.log(res.results);
if(res.results.length == 0){
socket.emit('disconnect', "Game does not exist");
console.log("disconnecting socket");
socket.disconnect(true);
return;
}
});
return getGame(res.results[0].active_game_type_id);
}).then(game => {
return game.join(socket, args);
}).catch(()=>{});
}
function API(req : express.Request, res : express.Response, next : express.NextFunction){
Games.query("delete from active_games where active_game_idle < (now()- INTERVAL 30 MINUTE) and active_game_id > 0;");
async function API(req : express.Request, res : express.Response, next : express.NextFunction){
await Games.query("delete from active_games where active_game_idle < (now()- INTERVAL 30 MINUTE) and active_game_id > 0;");
if(!/^\/games\/api\/.+/.test(req.path)) {
next();
return;
......@@ -129,12 +136,33 @@ function listGames(game : string, response : express.Response, next : express.Ne
//get all active games by game name/id
Games.getActiveGames(game)
.then(games => {
let data = [];
for(let game of games){
data.push({
name : game.data.name,
id : game.id,
players : game.data.players.length,
password : game.data.password,
})
}
response.type('application/json');
response.send(data);
response.end();
})
.catch(console.log)
.catch(next)
return;
console.log(`Listing games for : ${game}`);
let query : string
if(/^[0-9]+$/.test(game)){
query = `SELECT ${DB.active_games.active_game_id.column},${DB.game_data.data_value.column} FROM ${DB.active_games.table}, ${DB.game_data.table}, ${DB.games.table} WHERE ${DB.games.game_id.column} = ${game} AND ${DB.active_games.active_game_id.column} = ${DB.game_data.game_id.column};`
query = `SELECT ${DB.active_games.active_game_id.column},${DB.game_data.data_value.column} FROM ${DB.active_games.table}, ${DB.game_data.table}, ${DB.games.table} WHERE ${DB.games.game_id.column} = ${game} AND ${DB.active_games.active_game_id.column} = ${DB.game_data.game_id.column} AND ${DB.game_data.data_key.column} = 0;`
}else{
query = `SELECT ${DB.active_games.active_game_id.column},${DB.game_data.data_value.column} FROM ${DB.active_games.table}, ${DB.game_data.table}, ${DB.games.table} WHERE ${DB.games.game_name.column} = ${mysql.escape(game)} AND ${DB.active_games.active_game_id.column} = ${DB.game_data.game_id.column};`
query = `SELECT ${DB.active_games.active_game_id.column},${DB.game_data.data_value.column} FROM ${DB.active_games.table}, ${DB.game_data.table}, ${DB.games.table} WHERE ${DB.games.game_name.column} = ${mysql.escape(game)} AND ${DB.active_games.active_game_id.column} = ${DB.game_data.game_id.column} AND ${DB.game_data.data_key.column} = 0;`
}
Games.query(query)
......@@ -153,8 +181,14 @@ function listGames(game : string, response : express.Response, next : express.Ne
let row = results.results[key];
let data_value = JSON.parse(row.data_value);
data_value.id = row.active_game_id;
data.push({
name : data_value.name,
id : data_value.id,
players : data_value.players.length,
password_protected : data_value.password?true:false
})
debug(data_value);
data.push(data_value);
// data.push(data_value);
// data[row.active_game_id] = data_value;
}
// console.log(JSON.parse(res));
......@@ -176,15 +210,30 @@ function createGame(game : string ,req : express.Request, res : express.Response
next();
return;
}
return getGame(game).then((game : Game) => {
debug(`Creating game by Alex. CHANGE`);
console.log(req.body);
game.create(req.body.name, req.body.password).then(active_game_id => {
res.send(`Created new ${game.name} game by ${"Alex"} with id ${active_game_id}`);
res.end();
});
}).catch(next)
}
function getGame(game : string | number) : Promise<Game>{
let query : string
if(/^[0-9]+$/.test(game)){
if(typeof(game) == 'number' || /^[0-9]+$/.test(game)){
query = `SELECT ${DB.games.game_id.column}, ${DB.games.game_name.column} FROM ${DB.games.table} WHERE ${DB.games.game_id.column} = ${game};`;
}else{
query = `SELECT ${DB.games.game_id.column}, ${DB.games.game_name.column} FROM ${DB.games.table} WHERE ${DB.games.game_name.column} = ${mysql.escape(game)};`;
}
Games.query(query)
return Games.query(query)
.then(results => {
// console.log(query);
// console.log(results);
let game_id : number = results.results[0].game_id;
let game_name : string = results.results[0].game_name;
let game_prom : Promise<Game>;
......@@ -195,7 +244,7 @@ function createGame(game : string ,req : express.Request, res : express.Response
.then((_game : any) => {
let game : GameConstructor = _game.game;
loadedGames[game_id] = new game(Games);
console.log(loadedGames[game_id]);
// console.log(loadedGames[game_id]);
// game.init(Games);
resolve(loadedGames[game_id]);
}).catch(reject);
......@@ -205,20 +254,14 @@ function createGame(game : string ,req : express.Request, res : express.Response
resolve(loadedGames[game_id]);
})
}
game_prom.then((game : Game) => {
debug(`Creating game by Alex. CHANGE`);
console.log(req.body);
game.create(req.body.name, req.body.password).then(active_game_id => {
res.send(`Created new ${game_name} game by ${"Alex"} with id ${active_game_id}`);
res.end();
});
}).catch(err => {
//game does not exist
console.log(`Game ${game_name}:${game_id} does not exist!`);
next(500);
});
}).catch(next)
return game_prom;
}).catch((err)=>{
console.log("Server Error! Game not found!");
console.log(err);
return Promise.reject(500);
})
}
export {game_api};
\ No newline at end of file
import * as io from "socket.io";
import {Game, GameInitFunction, GameCreateFunction, GameDestroyFunction, GameConstructor} from "./game";
import { debug } from "../debug";
import { GameDB } from "../gamedb";
import { rejects } from "assert";
import { escape } from "mysql";
interface player {
socket : io.Socket;
game_id : number;
username : string;
};
enum rotation {
NORTH = "north",
EAST = "east",
SOUTH = "south",
WEST = "west",
}
interface ship {
x : number,
y : number,
rotation : rotation,
size : number,
}
interface shot {
x : number,
y : number,
hit : boolean,
}
const battleships : GameConstructor = class battleships implements Game{
public id : number = 1;
public name : string = "battleships";
public readonly id : number = 1;
public readonly name : string = "battleships";
protected db : GameDB;
protected players : player[] = [];
constructor(db_server : GameDB){
this.db = db_server;
......@@ -19,7 +48,7 @@ const battleships : GameConstructor = class battleships implements Game{
return new Promise<number>((resolve, reject) => {
this.db.query(`INSERT INTO active_games(active_game_type_id, active_game_idle) VALUES (${this.id}, now());`) //
.then(results => {
console.log(results.results);
// console.log(results.results);
resolve(results.results.insertId || -1);
let json_data : any = {name: creator, players : [], password : password};
if(password){
......@@ -28,7 +57,7 @@ const battleships : GameConstructor = class battleships implements Game{
return this.db.query(`INSERT INTO game_data(game_id, data_key, data_value) VALUES (${results.results.insertId}, 0, ?);`, JSON.stringify(json_data));
})
.then(results => {
console.log(results);
// console.log(results);
}).catch(err => {
console.log(err);
reject(err);
......@@ -40,6 +69,287 @@ const battleships : GameConstructor = class battleships implements Game{
destroy(){
}
join(socket : io.Socket, args : any) : Promise<boolean>{
console.log(`Joining battleships game`);
console.log(args);
socket.removeAllListeners();
//query to check if password correct etc, max number of players not reached etc
return this.db.query(`SELECT data_key, data_value FROM game_data WHERE game_id = ${args.id} AND data_key = 0;`)
.then(results => {
let row = results.results[0];
// console.log(row.data_value);
let json = JSON.parse(row.data_value);
// console.log(json);
if(json.password !== args.password){
socket.emit("disconnect", "Incorrect password");
socket.disconnect(true);
return false;
}
if(json.players.length >= 2){
socket.emit("disconnect", "Too many players");
socket.disconnect(true);
return false;
}
socket.emit("welcome", "Successfully joined game!");
console.log("Successfully joined game!");
json.players.push(args.username);
// console.log(json);
console.trace("JOINING USERS");
this.db.query(`UPDATE game_data SET data_value = ${escape(JSON.stringify(json))} WHERE game_id = ${args.id} AND data_key = 0;`)
.then(() => {
return this.db.query(`SELECT data_key, data_value FROM game_data WHERE game_id = ${args.id};`)
})
.then(results => {
//player number
console.log(results.results);
let json = JSON.parse(results.results.reduce((acc : any, cur : any) => cur.data_key == 0 ? cur : acc, null).data_value);
let player_number = json.players.indexOf(args.username);
debug(player_number)
let player_data = results.results.reduce((acc : any, cur : any) => cur.data_key == player_number+1 ? cur : acc, null);
debug(player_data);
let player_json = JSON.parse(player_data.data_value);
if(player_json){
debug(player_json);
socket.emit("place", player_json);
}
if(results.results.length >= 3){
socket.emit("battle");
}
}).catch(console.log);
socket.on("exit", () => {
this.leave(socket.id);
});
socket.on("place", (data : ship[]) => this.place(socket.id, data));
socket.on("fire", (data : shot) => this.fire(socket.id, data));
let player : player = {
socket : socket,
game_id : args.id,
username : args.username,
}
this.players.push(player);
return true;
})
// return Promise.resolve(true);
}
place(sock_id : string, ships : ship[]){
//check that all positions are valid and not intersecting
interface pos {x : number, y : number};
let taken : pos[] = [];
let valid : boolean = true;
for(let ship of ships){
let inx = 0, iny = 0;
switch(ship.rotation){
case "north":
iny = -1;
break;
case "east":
inx = +1;
break;
case "south":
iny = +1;
break;
case "west":
inx = -1;
break;
}
for(let i = 0; i < ship.size; i++){
let X = ship.x + i*inx;
let Y = ship.y + i*iny;
if(X < 0 || X >= 10 || Y < 0 || Y >= 10) valid = false;
let position : pos = {x : X, y : Y};
if(taken.reduce((taken, cur)=> cur == position? cur : taken, null)) valid = false;
taken.push(position);
}
}
if(valid){
let player = this.getPlayer(sock_id);
this.db.query(`SELECT data_value FROM game_data WHERE data_key = 0 AND game_id = ${player.game_id};`)
.then(results => {
let game_json = JSON.parse(results.results[0].data_value);
let player_no = game_json.players.indexOf(player.username);
return this.db.query(`INSERT INTO game_data (game_id, data_key, data_value) VALUES (${player.game_id}, ${player_no+1}, ${escape(JSON.stringify(ships))})`);
})
.then(results => {
if(results.err){
console.log(results.err);
}
//check if altered
// console.log(results);
//if both entries exist, BATTLE
return this.db.query(`SELECT data_key, data_value FROM game_data WHERE game_id = ${player.game_id};`)
})
.then(results => {
if(results.results.length >= 3){
let game_data = results.results[0];
let game_json = JSON.parse(game_data.data_value);
game_json.turn = 0;
//battle
//get both socket for game
let sockets : io.Socket[] = [];
for(let p of this.players){
if(p.game_id == player.game_id)
sockets.push(p.socket);
}
sockets.map(socket => {socket.emit("battle");});
this.db.query(`UPDATE game_data SET data_value=${escape(JSON.stringify(game_json))} WHERE data_key = 0 AND game_id = ${player.game_id};`)
this.db.query(`INSERT INTO game_data (game_id, data_key, data_value) VALUES (${player.game_id}, 3, "[]"), (${player.game_id}, 4, "[]")`)
}
})
}else{
}
}
fire(sock_id : string, shot : shot){
let player = this.getPlayer(sock_id);
shot.hit = false;
console.log(shot);
this.db.query(`SELECT * FROM game_data WHERE game_id = ${player.game_id};`)
.then(results => {
//check if player's move
let game_data = results.results.reduce((acc : any, cur : any) => {
if(cur.data_key == 0) return cur;
return acc;
});
let game_json = JSON.parse(game_data.data_value);
let player_number = game_json.players.indexOf(player.username);
if(game_json.turn != player_number) throw new Error("Not your turn!");
game_json.turn ++;
game_json.turn %= 2;
console.log(`Player ${game_json.turn}'s turn`);
console.log(game_json);
this.db.query(`UPDATE game_data SET data_value=${escape(JSON.stringify(game_json))} WHERE game_id = ${player.game_id} AND data_key = 0;`)
// .then(console.log);
//check if hit any of ships
let opponent_ships : ship[] = JSON.parse(results.results.reduce((acc : any, cur : any) => {
if(cur.data_key == game_json.turn+1)
return cur;
return acc;
}, null).data_value);
let idx = (game_json.turn+1)%2+3
let shots : shot[] = JSON.parse(results.results.reduce((acc : any, cur : any) => {
if(cur.data_key == idx){
return cur;
}
return acc;
}, null).data_value);
for(let ship of opponent_ships){
let inx = 0, iny = 0;
switch(ship.rotation){
case "north":
iny = -1;
break;
case "east":
inx = +1;
break;
case "south":
iny = +1;
break;
case "west":
inx = -1;
break;
}
let hits = ship.size-1;
for(let i = 0; i < ship.size; i++){
let X = ship.x + i*inx;
let Y = ship.y + i*iny;
if(shot.x == X && shot.y == Y){
//check if ship sunk
shot.hit = true;
console.log(shots);
}
for(let shot of shots){
if(shot.x == X && shot.y == Y && shot.hit)
hits--;
}
}
if(hits == 0){
player.socket.emit("sunk", ship);
console.log("SUNK");
}
}
if(shots.reduce((dup, s) => {
if(s.x == shot.x && s.y == shot.y) return true;
return dup;
}, false)){
}else{
shots.push(shot);
this.db.query(`UPDATE game_data SET data_value=${escape(JSON.stringify(shots))} WHERE game_id = ${player.game_id} AND data_key = ${idx};`);
}
return shot.hit;
})
.then(hit => {
shot.hit = hit;
console.log(`Hit? : ${hit}`);
player.socket.emit("fired", shot);
//get other player
let opponent = this.players.reduce((acc, cur) => {
if(cur != player && cur.game_id == player.game_id){
return cur;
}
return acc;
}, null);
if(opponent){
opponent.socket.emit("shot", shot);
opponent.socket.emit("fire");
}else{
debug(`MISSING OPPONENT`);
}
}).catch(e => {
console.log(e);
player.socket.emit("fired", null);
})
}
getPlayer(sock_id : string){
let player = this.players.reduce((correct, current) => {
if(current.socket.id == sock_id)
return current;
return correct;
}, null);
return player;
}
leave(sock_id : string){
let player = this.getPlayer(sock_id);
this.players = this.players.filter(p => p==player?0:1);
let game_id = player.game_id;
this.db.query(`SELECT data_key, data_value FROM game_data WHERE game_id = ${game_id} AND data_key = 0;`)
.then(results => {
let row = results.results[0];
let json = JSON.parse(row.data_value);
console.log(json);
let new_players = json.players.filter((p : any) => p==player.username?0:1);
json.players = new_players;
console.trace("REMOVING USERS");
console.log(json)
this.db.query(`UPDATE game_data SET data_value = ${escape(JSON.stringify(json))} WHERE game_id = ${game_id} AND data_key = 0;`)
});
}
}
export {battleships as game};
\ No newline at end of file
import * as mysql from "mysql"
import { GameDB } from "../gamedb";
import * as io from "socket.io"
export type GameInitFunction = (db_server : GameDB) => void;
export type GameCreateFunction = (creator : string, password? : string) => Promise<number>;
export type GameDestroyFunction = (game_id : number) => void;
export type GameJoinFunction = (socket : io.Socket, args : any) => Promise<boolean>;
export interface GameConstructor {
new (db_server : GameDB) : Game;
}
......@@ -12,6 +14,7 @@ export interface GameConstructor {
export interface Game{
create : GameCreateFunction;
destroy : GameDestroyFunction;
join : GameJoinFunction;
name : string;
id : number;
[key : string] : any;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment