From 78b205fd3f4189ff353949c0426e59493b2e16c8 Mon Sep 17 00:00:00 2001 From: Alexander Bass Date: Thu, 23 Jun 2022 01:44:57 -0400 Subject: [PATCH] Good progress on UI and making this thing actually work. --- scripts/game.mjs | 19 +-- scripts/roomManager.mjs | 66 +++++---- scripts/server/netcode.mjs | 37 +++-- scripts/util.mjs | 6 + scripts/world/flagger.mjs | 6 +- scripts/world/generator.mjs | 16 +-- scripts/world/marker.mjs | 6 +- scripts/world/obfuscator.mjs | 4 +- scripts/world/placer.mjs | 8 +- scripts/world/revealer.mjs | 9 +- scripts/world/world.mjs | 27 ++-- test.mjs | 3 + www/fonts/moderndos.ttf | Bin 0 -> 32156 bytes www/fonts/moderndos.woff2 | Bin 0 -> 7948 bytes pixerif.woff2 => www/fonts/pixerif.woff2 | Bin Pixerif.ttf => www/fonts/pixserif.ttf | Bin www/game.html | 87 ++++++++++++ www/img/city.png | Bin 296 -> 0 bytes www/img/grass.png | Bin 264 -> 0 bytes www/img/hills.png | Bin 358 -> 0 bytes www/{ => img}/mine.png | Bin www/img/modes.png | Bin 0 -> 12400 bytes www/img/rock.png | Bin 292 -> 0 bytes www/img/sea.png | Bin 285 -> 0 bytes www/index.html | 69 +++------- www/scripts/display/draw.js | 14 +- www/scripts/display/html.js | 3 +- www/scripts/display/tileRenderer.js | 32 +++-- www/scripts/game/game.js | 5 +- www/scripts/interface/game/connection.js | 2 +- www/scripts/interface/game/html.js | 2 - www/scripts/interface/game/mouse.js | 1 - www/scripts/interface/game/picker.js | 52 ------- www/scripts/interface/mainmenu/menu.js | 20 ++- www/scripts/interface/mainmenu/picker.js | 40 ++++++ www/scripts/interface/scene.js | 1 - www/scripts/net/netcode.js | 3 +- www/style.css | 165 ++++++++++++++++++----- 38 files changed, 441 insertions(+), 262 deletions(-) create mode 100644 test.mjs create mode 100644 www/fonts/moderndos.ttf create mode 100644 www/fonts/moderndos.woff2 rename pixerif.woff2 => www/fonts/pixerif.woff2 (100%) rename Pixerif.ttf => www/fonts/pixserif.ttf (100%) create mode 100644 www/game.html delete mode 100644 www/img/city.png delete mode 100644 www/img/grass.png delete mode 100644 www/img/hills.png rename www/{ => img}/mine.png (100%) create mode 100644 www/img/modes.png delete mode 100644 www/img/rock.png delete mode 100644 www/img/sea.png delete mode 100644 www/scripts/interface/game/html.js delete mode 100644 www/scripts/interface/game/picker.js create mode 100644 www/scripts/interface/mainmenu/picker.js diff --git a/scripts/game.mjs b/scripts/game.mjs index 0e013b0..ba36f18 100644 --- a/scripts/game.mjs +++ b/scripts/game.mjs @@ -4,10 +4,10 @@ import {roomManager} from "./roomManager.mjs" import { World} from "./world/world.mjs" export class Game { - constructor(name) { - this.name = name; + constructor(id, options) { + this.id = id; this.players = []; - this.world = new World([16,16]) + this.world = new World(options) } addPlayer(id, name) { @@ -22,7 +22,7 @@ export class Game { this.players = this.players.filter(obj => obj.id != id); log.log("removed player - " + id) if (this.players.length < 1) { - roomManager.removeGame(this.name); + roomManager.removeGameByID(this.id); } } @@ -40,15 +40,4 @@ export class Game { } return names } - - getSettings() { - const settings = - { - mines: this.world.mines, - dimensions: this.world.dimensions, - name: this.name - } - return settings - - } } diff --git a/scripts/roomManager.mjs b/scripts/roomManager.mjs index 78414cd..112cd24 100644 --- a/scripts/roomManager.mjs +++ b/scripts/roomManager.mjs @@ -1,33 +1,31 @@ import {Game} from "./game.mjs" import * as log from "./log.mjs" +import * as util from "./util.mjs" import {IllegalAction} from "./server/illegalAction.mjs" class RoomManager { constructor(){ this.games = []; } - getGameByName(name, create) { - const game = this.games.filter(obj => obj.name == name)[0] - if (game === undefined && create) { - this.addGame(name); - // Oh no.... This cant be good code. - // Coming back to it two months later. Horrible, but I don't know how to fix it. Maybe I'll leave it as an ancient artifact. - return this.getGameByName(name); + getGameByID(id) { + const game = this.games.filter(obj => obj.id == id)[0] + if (game === undefined) { + return false } return game } - addGame(name, settings) { - const game = new Game(name, settings); + addGame(id, options) { + const game = new Game(id, options); this.games.push(game); return game } - removeGame(name) { - this.games = this.games.filter(obj => obj.name != name); - log.log("removed game - " + name) - // Broken? + removeGameByID(id) { + this.games = this.games.filter(obj => obj.id != id); + log.log("removed game - " + id) + } - getAllIDs() { + getAllPlayerIDs() { let ids = [] for (let i = 0; i < this.games.length; i++) { for (let j = 0; j < this.games[i].players.length; j++) { @@ -37,26 +35,44 @@ class RoomManager { return ids } - joinClientToGame(room, nick, id, client) { - if (this.getAllIDs().includes(id)) { + getAllGameIDs() { + let ids = [] + for (let i = 0; i < this.games.length; i++) { + ids.push(this.games[i].id) + } + return ids + } + + playerJoinGame(roomCode, playerName, playerID) { + // See if the client is already in a game + console.log(roomCode, playerName) + if (this.getAllPlayerIDs().includes(playerID)) { return new IllegalAction(id, 22) } - if (nick.length > 9) { - return new IllegalAction(id, 21) + if (!this.getAllGameIDs().includes(roomCode)) { + return new IllegalAction(id, 30) } - const game = this.getGameByName(room, true); - const player = game.addPlayer(id, nick); + const game = this.getGameByID(roomCode); + const player = game.addPlayer(playerID, playerName); + // See if player name is taken already if (player === false) { this.removeGame(game) return new IllegalAction(id, 20) } - - client.join(game.name) - client.game = game; - client.player = player - return true + return [game, player] } + playerCreateGame(options, playerName, playerID) { + if (this.getAllPlayerIDs().includes(playerID)) { + return new IllegalAction(id, 22) + } + console.log(options) + const id = util.createCode() + const game = this.addGame(id, options) + const player = game.addPlayer(playerID, playerName); + return [game, player] + + } } diff --git a/scripts/server/netcode.mjs b/scripts/server/netcode.mjs index 410c8e3..6e17c49 100644 --- a/scripts/server/netcode.mjs +++ b/scripts/server/netcode.mjs @@ -2,7 +2,6 @@ import {IllegalAction} from "./illegalAction.mjs" import * as log from "../log.mjs" import {roomManager} from "../roomManager.mjs" import {io} from "./io.mjs" -var oldWorld = 0 io.on('connection', function(client){ connected(client) @@ -12,34 +11,54 @@ io.on('connection', function(client){ function connected(client) { client.sync = function() { const tempWorld = client.game.world.obfuscate(); - io.to(client.game.name).emit('sync',{world: tempWorld}) + io.to(client.game.id).emit('sync',{world: tempWorld}) } client.sendMeta = function() { - const roomSettings = client.game.getSettings(); + const roomID = client.game.id const roomPlayers = client.game.players; // Dont send client id's to everyone, TODO - const metadata = {players: roomPlayers, settings: roomSettings} - io.to(client.game.name).emit('metadata', metadata) + const metadata = {players: roomPlayers, roomID: roomID} + io.to(client.game.id).emit('metadata', metadata) + + + + const id = client.game.id + client.emit('message', id) } client.game = ""; client.player = ""; client.on('disconnect', function(){ - if (!roomManager.getAllIDs().includes(client.id)) return new IllegalAction(client.id, 22) + if (!roomManager.getAllPlayerIDs().includes(client.id)) return new IllegalAction(client.id, 22) log.log(client.id + ' disconnected.', 'FgCyan') client.game.removePlayerByID(client.id) client.sendMeta(); }) client.on('joinGame', function(data){ - if(!roomManager.joinClientToGame(data.room, data.name, client.id, client)) return + const info = roomManager.playerJoinGame(data.room, data.name, client.id) + client.join(info[0].id) + client.game = info[0]; + client.player = info[1] client.sync() log.log(`${client.id} joined the game as ${data.name} requesting to join room: ${data.room}`, 'FgMagenta'); client.emit('inGame', true) client.sendMeta() }) + client.on('createGame', function(data){ + const info = roomManager.playerCreateGame(data.options, data.name, client.id) + client.join(info[0].id) + client.game = info[0]; + client.player = info[1] + + log.log(`${client.id} joined the game as ${data.name} `, 'FgMagenta'); + client.emit('inGame', true) + client.sync() + client.sendMeta() + }) + client.on('leaveGame', function(data){ log.log(client.id + ' disconnected.') @@ -49,8 +68,8 @@ function connected(client) { client.on('clickCanvas', function(data){ - if (!roomManager.getAllIDs().includes(client.id)) return new IllegalAction(client.id, 1) - client.game.world.click([data.tilePosition[0],data.tilePosition[1]], data.mode, client.player) + if (!roomManager.getAllPlayerIDs().includes(client.id)) return new IllegalAction(client.id, 1) + client.game.world.click(data.tilePosition[0],data.tilePosition[1], data.mode, client.player) client.sync() }) diff --git a/scripts/util.mjs b/scripts/util.mjs index 34f6929..c49079d 100644 --- a/scripts/util.mjs +++ b/scripts/util.mjs @@ -1,6 +1,12 @@ +import crypto from "crypto"; export function randomNumber(min, max) { return Math.floor(Math.random() * (max - min) + min); } export function clamp(number, min, max) { return Math.max(min, Math.min(number, max)); } + +export function createCode() { + const randomString = crypto.randomBytes(3).toString("hex").toUpperCase() + return randomString +} diff --git a/scripts/world/flagger.mjs b/scripts/world/flagger.mjs index e76946d..7fd95f1 100644 --- a/scripts/world/flagger.mjs +++ b/scripts/world/flagger.mjs @@ -1,6 +1,6 @@ -export function flag(data, location, player) { - let tile = data[location[0]][location[1]] +export function flag(x, y, data, player) { + let tile = data[x][y] if (!tile.mask || tile.color === 0) return data const color = player.color * 1 @@ -17,6 +17,6 @@ export function flag(data, location, player) { tile.flag = 0; } console.log(tile.flag) - data[location[0]][location[1]] = tile + data[x][y] = tile return data; } diff --git a/scripts/world/generator.mjs b/scripts/world/generator.mjs index 8652e68..c63e5de 100644 --- a/scripts/world/generator.mjs +++ b/scripts/world/generator.mjs @@ -14,22 +14,22 @@ const searchLoc = [-1,-1],[0,-1],[1,-1] ] -export function generate(world, avoidLocation){ +export function generate(avoidX, avoidY, world){ var minesPlanted = 0; - while (minesPlanted < world.mines || !(minesPlanted <= world.dimensions[0]*world.dimensions[1]-15)) { - const x = util.randomNumber(0,world.dimensions[0]) - const y = util.randomNumber(0,world.dimensions[1]) + while (minesPlanted < world.mines || !(minesPlanted <= world.width*world.height-15)) { + const x = util.randomNumber(0,world.width) + const y = util.randomNumber(0,world.height) var suitable = true; searchLoc.forEach(loc => { const tempx = x + loc[0] const tempy = y + loc[1] - if (tempx === avoidLocation[0] && tempy === avoidLocation[1]) { + if (tempx === avoidX && tempy === avoidX) { suitable = false; } }) - // console.log([x,y] + ":----:" + avoidLocation) - if (x == avoidLocation[0] && y == avoidLocation[1]) { suitable = false } - if (world.data[x][y].type == 5) { suitable = false } + + if (x == avoidX && y == avoidY) { suitable = false } + if (world.data[x][y].type == 5) { suitable = false } if (suitable) { world.data[x][y].type = 5 diff --git a/scripts/world/marker.mjs b/scripts/world/marker.mjs index d0805ae..7bff182 100644 --- a/scripts/world/marker.mjs +++ b/scripts/world/marker.mjs @@ -7,14 +7,14 @@ const searchLoc = // Place Numbers export function mark(world) { -for(let x = 0; x < world.dimensions[0]; x++){ - for(let y = 0; y < world.dimensions[1]; y++){ +for(let x = 0; x < world.width; x++){ + for(let y = 0; y < world.height; y++){ if (world.data[x][y].type === 1) { var counter = 0; searchLoc.forEach(location => { const tempx = x + location[0] const tempy = y + location[1] - if (tempx >= 0 && tempy >= 0 && tempx < world.dimensions[0] && tempy < world.dimensions[1]) { + if (tempx >= 0 && tempy >= 0 && tempx < world.width && tempy < world.height) { if (world.data[tempx][tempy].type === 5) { counter++; } diff --git a/scripts/world/obfuscator.mjs b/scripts/world/obfuscator.mjs index 68a8a38..d1cb45f 100644 --- a/scripts/world/obfuscator.mjs +++ b/scripts/world/obfuscator.mjs @@ -1,8 +1,8 @@ export function obfuscate(world) { let tempWorld = world; - for(let x = 0; x < tempWorld.dimensions[0]; x++){ - for(let y = 0; y < tempWorld.dimensions[1]; y++){ + for(let x = 0; x < tempWorld.width; x++){ + for(let y = 0; y < tempWorld.height; y++){ if (tempWorld.data[x][y].mask === true) { diff --git a/scripts/world/placer.mjs b/scripts/world/placer.mjs index c098042..b9eeaa2 100644 --- a/scripts/world/placer.mjs +++ b/scripts/world/placer.mjs @@ -1,14 +1,14 @@ import * as log from "../log.mjs" import * as revealer from "./revealer.mjs" -export function place(data, location, id) { - let tile = data[location[0]][location[1]]; +export function place(x, y, data) { + let tile = data[x][y]; if (tile.mask === true) { if (tile.mask && tile.flag === 0) { tile.mask = false; } - data[location[0]][location[1]] = tile; - revealer.reveal(data, location) + data[x][y] = tile; + revealer.reveal(x, y, data) } return data; } diff --git a/scripts/world/revealer.mjs b/scripts/world/revealer.mjs index 1cfed20..abbc3d8 100644 --- a/scripts/world/revealer.mjs +++ b/scripts/world/revealer.mjs @@ -6,15 +6,16 @@ const searchLoc = [-1,-1],[0,-1],[1,-1] ] -export function reveal(data, location) { - if (data[location[0]][location[1]].type !== 5) { +export function reveal(x, y, data) { + if (data[x][y].type !== 5) { var toSearch = []; var searchedLocations = []; - toSearch.push(location) + toSearch.push([x, y]) - if (data[location[0]][location[1]].type === 1) { + if (data[x][y].type === 1) { while (toSearch.length > 0) { + console.log("LoopReveal") const x = toSearch[0][0] const y = toSearch[0][1] searchedLocations.push(toSearch[0]) diff --git a/scripts/world/world.mjs b/scripts/world/world.mjs index a9b79dc..ed3d4d8 100644 --- a/scripts/world/world.mjs +++ b/scripts/world/world.mjs @@ -6,39 +6,40 @@ import * as flagger from "./flagger.mjs" import * as placer from "./placer.mjs" export class World { - constructor(dimensions = [32,32], mines = 30) { - this.mines = 200 - this.dimensions = dimensions; + constructor(options) { + this.mines = options.mines + this.width = options.width*1 + this.height = options.height*1 this.isGenerated = false; this.isObfuscated = false; this.isMarked = false; - this.data = Array.from(Array(this.dimensions[0]), () => new Array(this.dimensions[1])); - for (let x = 0; x < this.dimensions[0]; x++){ - for (let y = 0; y < this.dimensions[1]; y++){ + this.data = Array.from(Array(this.width), () => new Array(this.height)); + for (let x = 0; x < this.width; x++){ + for (let y = 0; y < this.height; y++){ this.data[x][y] = {type: 1, flag: 0, mask: true} } } } - click (location, mode, player) { + click (x, y, mode, player) { if (this.isGenerated) { if (mode === 2) { - this.data = flagger.flag(this.data, location, player) + this.data = flagger.flag(x, y, this.data, player) } if (mode === 0) { - this.data = placer.place(this.data, location, player) + this.data = placer.place(x, y, this.data, player) } } else { - this.generate(location).mark(); - this.data = placer.place(this.data, location, player) + this.generate(x, y).mark(); + this.data = placer.place(x, y, this.data, player) } } - generate(location) { + generate(x, y) { if (this.isGenerated) return log.log("Already Generated"); - return generator.generate(this, location); + return generator.generate(x, y, this); } mark() { diff --git a/test.mjs b/test.mjs new file mode 100644 index 0000000..7fc3b15 --- /dev/null +++ b/test.mjs @@ -0,0 +1,3 @@ +import * as util from "./scripts/util.mjs" + +console.log(util.createCode()) diff --git a/www/fonts/moderndos.ttf b/www/fonts/moderndos.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3cbc942d7e59bf1528a89b2fd7a2d778a709b306 GIT binary patch literal 32156 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 cDG2LLY>Osv}vF{3@(5>}u$7px;e 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 + + + + + + + + + + + + +
+

+ + + +
+ + + diff --git a/www/img/city.png b/www/img/city.png deleted file mode 100644 index 462b8bed92bc47db2f6776cd61a19a1750901ceb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAF%}28J29*~C-V}>VM%xNb!1@J z*w6hZkrl{S4DbnY&B(|&a^%RodGr3itZ!&&SigR~m@q?fa`OKNVPaxpKvjD)t2Y2C z?vfzC;Qw&I;N{Qw2`J22;1OBOz`%DHgc*Z~KYiQbEi)gy`DvnY c+iNGI^)l{xKR*Wl13H4i)78&qol`;+0314RYybcN diff --git a/www/img/grass.png b/www/img/grass.png deleted file mode 100644 index 4b44ca4d2385def6699886cb83a35165d341f3fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;{0X`wF;!SpP3ru466iH8W6D>DaJ`yc6&r{jo*8!-2v%n*=n1O-sFbFdq z&tH)O6s+-daSYKopBfM?)S$o-v*q90LWb8YVd5_gFaPZqS+Ml#IR)-RO->JQ_=sDw z+HDhP=HlmB{zld$NBMfyf$U&@pErBI2#W6xX_@bLB;td!N?vBs{OH(syr)XsR-azE z)lhw1c-Zt=@#q8c5IuBlF1KD$WczwkHi=$EYhPn%Y@1Kq*k>FVdQ&MBb@ E0OrtHBme*a diff --git a/www/img/hills.png b/www/img/hills.png deleted file mode 100644 index 9e2cfbc2cef61eafcc9e65b4dc7dd8c5faec592a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvVv3w_=LDln>KCb%9V!>9XfXGSZ{Cd`t|FVE?v4{!2)&r#v4F2oCO|{#S9F5 zhe4R}c>anMpx|{+7sn8d^RoWC^I8l9WR?V9GLq@b?)k&G&6Qs;=$1}KX}yE2*8jR| z&y!3yZ+p(TK>Cv1yW2l>O5le2(}* zmBhYN#{MA^T7i099~=TNORZm4;dGYe$AWJ)W=ZE{Ce2*%He0snS9Q({-uUTmVf*(V zuHF0pde(=W6GdIevz~Qp@)eidxU*B^Z|={yWl=qM-Y(1+-BEYzgYN?Q?^{I^_ck71 z_U3*10`Y{!uOcKT1v|uc{MooG>&VkZTeNMT%Ih@iAO9Hd`5)*-22WQ%mvv4FO#lOV Bm{kA( diff --git a/www/mine.png b/www/img/mine.png similarity index 100% rename from www/mine.png rename to www/img/mine.png diff --git a/www/img/modes.png b/www/img/modes.png new file mode 100644 index 0000000000000000000000000000000000000000..63da480ac2010327583d4494eb82ab02685f4bcc GIT binary patch literal 12400 zcmeI2p$fuK07c(KL4<)(#ISDh0}Lt?w=zVu8%+x)qgcdhu&j$|$^Y;ZjAp+;-}{KS zvv3ExVc6Nu;WjVJY!P<)9b-(GCh^LikMzz<4b{0bm0#UJFnF z*Z_>z0u%r?0OPd)1%M5}cr8EyU;{8-3s3;q0F19<0q49p7}FiP{{q0TTW@?7G3spq zemVtE0N4PG*8&s(HUQ(b00n>zz<4b{0bm0#UJHN&WZ&jJx!wluG17S!m$U8Z4-J18 Al>h($ literal 0 HcmV?d00001 diff --git a/www/img/rock.png b/www/img/rock.png deleted file mode 100644 index ff9e8ff50b2d4ac382bdf3809650cb113a74c1a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAF%}28J29*~C-V}>VM%xNb!1@J z*w6hZkrl`n4e$wZ1=8EMZ=W}B-o%L$8yXr43JQQC^4iiMqu5J={DS|30fUq`vl~!| zv%n*=n1O-s5C}7hYIrpO1zSB`978mM&-O?2H5&*pI|~*4S1x~3s*!cn-tA2?n?UAk z#r1-{DSJ2{IO~)XuqZCk(qNleB%EECtr(pvYGaxA#3Z)11F>8 Yr!;a*WSzqP2IwFLPgg&ebxsLQ08h+hu>b%7 diff --git a/www/img/sea.png b/www/img/sea.png deleted file mode 100644 index 0d196077f29961e43c9ad733d1813f6328592f46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 285 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6=10X`wF45F7KQ~oos{AUo_&MY)D&9tiwD8*Ue5n0T@z;_sg8IR|$NC65? z_jGX#(Kuh~e^K;^0!R0*hArF?@7OjhlfLpd-Ri);f3o&!4o)qhu5MxO8c!lOZrD6G zMVqCsch57EQ+%OpuXU1KuA0@F^t7<2n(yRy_#Bbv-m8AowD+Ob`={*B)tOg5e`d{_ zclzR-nrE`glRG}mD-t&Sl3F!u$-`(Ke?IZupRZ5io%+2#_LJ4DCGPr<<5kz3_*5pw b{()KOjpUmf7c>KbPGsbP0l+XkKgfC}c diff --git a/www/index.html b/www/index.html index 42a0e8e..ee101c8 100644 --- a/www/index.html +++ b/www/index.html @@ -1,53 +1,16 @@ - - - - - - - - - - - - - -
-

- - - -
- - - + + + + + + + + +
+

Multiplayer Minesweeper!

+

Up to 8 Players

+ Play Now! +
+ + + diff --git a/www/scripts/display/draw.js b/www/scripts/display/draw.js index e423c86..b2ad826 100644 --- a/www/scripts/display/draw.js +++ b/www/scripts/display/draw.js @@ -1,4 +1,3 @@ -import * as main from '../script.js'; import {tileArray} from './tileRenderer.js'; import { cursor } from '../interface/game/mouse.js' import { ctx} from './html.js'; @@ -9,23 +8,22 @@ renderTiles() } export function renderTiles() { // DRAW THE IMAGE TO THE CANVAS. + const width = game.world.width; + const height = game.world.height; + canvas.width = game.tileSize*width; + canvas.height = game.tileSize*height; let x, y = 0 - const gridSize = game.gridSize; const tileSize = game.tileSize; - for(x = 0; x < gridSize[0]; x++){ - for(y = 0; y < gridSize[1]; y++){ + for(x = 0; x < width; x++){ + for(y = 0; y < height; y++){ const xu = x*tileSize; const yu = y*tileSize; const tempWorld = game.world.data; - // Draw buildings ctx.drawImage(tileArray[tempWorld[x][y].type], xu,yu) - // Draw Structures const flag = tempWorld[x][y].flag - // console.log(flag) if (flag !== 0) { - // console.log("FALAG") ctx.drawImage(tileArray[flag + 7], xu,yu) } diff --git a/www/scripts/display/html.js b/www/scripts/display/html.js index ed16a9e..69a5634 100644 --- a/www/scripts/display/html.js +++ b/www/scripts/display/html.js @@ -3,8 +3,7 @@ import {game} from "../game/game.js" export var canvas = document.getElementById('canvas'); export var ctx = canvas.getContext('2d'); export var wrapper = document.getElementById('game'); -canvas.width = game.tileSize*game.gridSize[0]; -canvas.height = game.tileSize*game.gridSize[1]; + scaleEverythingGood() window.addEventListener('resize', scaleEverythingGood); diff --git a/www/scripts/display/tileRenderer.js b/www/scripts/display/tileRenderer.js index f328d07..cb1f0eb 100644 --- a/www/scripts/display/tileRenderer.js +++ b/www/scripts/display/tileRenderer.js @@ -1,20 +1,26 @@ import {game} from "/scripts/game/game.js" -export var tileArray = loadSprites(); -export function loadSprites() { - var tiles = []; - var spriteJank = document.getElementById('spriteJank'); - spriteJank.width = game.tileSize; - spriteJank.height = game.tileSize; - var ctxj = spriteJank.getContext('2d'); - var spriteSheet = new Image(); +export const tileArray = loadSprites('/img/mine.png', game.tileSize); +var counter = 0; - spriteSheet.src = '/mine.png' +export function loadSprites(path, tileSize) { + + let tiles = []; + let spriteJank = document.createElement("canvas"); + spriteJank.id = `spriteJank${counter}` + spriteJank.style = "display: none;" + spriteJank.width = tileSize; + spriteJank.height = tileSize; + document.body.appendChild(spriteJank); + let ctxj = spriteJank.getContext('2d'); + let spriteSheet = new Image(); + + spriteSheet.src = path spriteSheet.onload = function() { - const tileSize = game.tileSize; - for (let y = 0; y < 8; y++) { - for (let x = 0; x < 8; x++) { + + for (let y = 0; y < spriteSheet.height/tileSize; y++) { + for (let x = 0; x < spriteSheet.width/tileSize; x++) { ctxj.drawImage(spriteSheet, -x*tileSize,-y*tileSize) var tmp = new Image(); tmp.src = spriteJank.toDataURL(); @@ -24,5 +30,7 @@ export function loadSprites() { } } spriteJank.remove(); + return tiles; } +export const menuArray = loadSprites('/img/modes.png', 32) diff --git a/www/scripts/game/game.js b/www/scripts/game/game.js index 9ea27b2..378d24a 100644 --- a/www/scripts/game/game.js +++ b/www/scripts/game/game.js @@ -1,13 +1,12 @@ class Game { constructor(tileSize, gridSize, world, status) { this.tileSize = tileSize; - this.gridSize = gridSize; this.world = world; this.status = status; } reset() { - game = new Game(16, [16, 16], null, false); + game = new Game(16, null, false); } } -export var game = new Game(16, [16, 16]) +export var game = new Game(16, null, false) diff --git a/www/scripts/interface/game/connection.js b/www/scripts/interface/game/connection.js index e9fc134..c39b362 100644 --- a/www/scripts/interface/game/connection.js +++ b/www/scripts/interface/game/connection.js @@ -1,4 +1,4 @@ -import {statusElement} from "/scripts/interface/game/html.js" +const statusElement = document.getElementById("status") export function updateConnectionStatus(connection) { statusElement.textContent = `Server Connection: ${connection}` diff --git a/www/scripts/interface/game/html.js b/www/scripts/interface/game/html.js deleted file mode 100644 index 40bb2f5..0000000 --- a/www/scripts/interface/game/html.js +++ /dev/null @@ -1,2 +0,0 @@ -export let statusElement = document.getElementById("status") -export let buttonBar = document.getElementById("buttonBar") diff --git a/www/scripts/interface/game/mouse.js b/www/scripts/interface/game/mouse.js index 70d24a3..12b8c4c 100644 --- a/www/scripts/interface/game/mouse.js +++ b/www/scripts/interface/game/mouse.js @@ -1,6 +1,5 @@ import {game} from "../../game/game.js"; import { clickCanvas } from "/scripts/net/netcode.js"; -import { getButton } from "/scripts/interface/game/picker.js"; import { canvas } from "../../display/html.js" class Cursor { diff --git a/www/scripts/interface/game/picker.js b/www/scripts/interface/game/picker.js deleted file mode 100644 index 6843079..0000000 --- a/www/scripts/interface/game/picker.js +++ /dev/null @@ -1,52 +0,0 @@ -import {tileArray} from "/scripts/display/tileRenderer.js" -import {buttonBar} from "/scripts/interface/game/html.js" -var button = 0; - -function clickSelector(e) { - document.querySelectorAll('.button').forEach(item => { - item.style =""; - }) - event.target.style = "background: lightslategray;" - button = event.target.no - -} - -export function create() { -for(let i=0;i < 5;i++) { - let span = document.createElement('span') - span.className = "button" - let n; - switch (i) { - case (1): - n = 1 - break; - case (2): - n = 2 - break; - case (3): - n = 3 - break; - case (4): - n = 4 - break; - default: - n = 5 -}; - span.appendChild(tileArray[n]); - buttonBar.appendChild(span); - span.no = i; - span.addEventListener('click', e => { - clickSelector(e); - }); -}; -}; - -export function getButton() { - return button; -} - -export function destroy() { - while (buttonBar.lastChild) { - buttonBar.removeChild(buttonBar.lastChild) - } -} diff --git a/www/scripts/interface/mainmenu/menu.js b/www/scripts/interface/mainmenu/menu.js index dc1e8b2..3ca06f9 100644 --- a/www/scripts/interface/mainmenu/menu.js +++ b/www/scripts/interface/mainmenu/menu.js @@ -1,6 +1,10 @@ import * as status from "../../net/status.js" import {joinGame, createGame} from "/scripts/net/netcode.js" import { changeScene } from "/scripts/interface/scene.js" +import * as picker from "./picker.js" +import {tileArray, menuArray} from "/scripts/display/tileRenderer.js" + + function ID(id) { return document.getElementById(id) @@ -13,6 +17,8 @@ const createGameMenu = ID("createGame") ID("gotoCreate").addEventListener("click", e => { joinType.style.display = "none" createGameMenu.style.display = "" +picker.create("createGameSelectColorBar", tileArray, [8, 16]) +picker.create("createGameSelectModeBar", menuArray, [0,4], "wide") }) ID("gotoJoin").addEventListener("click", e => { @@ -29,7 +35,7 @@ ID("joinGameButton").addEventListener("click", e => { function join(event) { const roomCode = ID("joinGameCode").value const name = ID("joinGameUsername").value - if (room == '' || name == '' || status.get() == 'disconnected') return + if (roomCode == '' || name == '' || status.get() == 'disconnected') return joinGame({room: roomCode, name: name}) } @@ -37,6 +43,7 @@ function join(event) { ID("createRoomButton").addEventListener("click", e => { create(e) + picker.destroy("createGameSelectColorBar") }); function create(event) { @@ -45,14 +52,17 @@ function create(event) { const width = ID("createGameOptionsWidth").value const height = ID("createGameOptionsHeight").value if (name == '' || mines == '' || width == '' || height == '' || status.get() == 'disconnected') return - - const data = - { - name: name, + const options = { mines: mines, width: width, height: height } + const data = + { + name: name, + options: options + } + console.log(data) createGame(data) } diff --git a/www/scripts/interface/mainmenu/picker.js b/www/scripts/interface/mainmenu/picker.js new file mode 100644 index 0000000..203b96a --- /dev/null +++ b/www/scripts/interface/mainmenu/picker.js @@ -0,0 +1,40 @@ +function clickSelector(e, parentID) { + document.getElementById(parentID).querySelectorAll('.button').forEach(item => { + item.style =""; + item.active ="false"; + }) + event.target.style = "background: #4CAF50;" + event.target.active = "true" + +} + +export function getButton(parentID) { + document.getElementById(parentID).querySelectorAll('.button').forEach(item => { + if (item.active === "true") { + return item.no + } + }) +} + +export function create(parentID, spriteSheet, ranges, style = "") { +const buttonBar = document.getElementById(parentID); + +for(let i=0;i < ranges[1]-ranges[0];i++) { +let span = document.createElement('span') + span.className = `button ${style}` + const n = i + ranges[0] + span.appendChild(spriteSheet[n]); + buttonBar.appendChild(span); + span.no = i; + span.addEventListener('click', e => { + clickSelector(e, parentID); + }); +}; +}; + +export function destroy(parentID) { + const buttonBar = document.getElementById(parentID); + while (buttonBar.lastChild) { + buttonBar.removeChild(buttonBar.lastChild) + } +} diff --git a/www/scripts/interface/scene.js b/www/scripts/interface/scene.js index 7956496..89bd0a2 100644 --- a/www/scripts/interface/scene.js +++ b/www/scripts/interface/scene.js @@ -1,4 +1,3 @@ -import * as picker from "/scripts/interface/game/picker.js" export function changeScene(scene) { if (scene == "game") { diff --git a/www/scripts/net/netcode.js b/www/scripts/net/netcode.js index 5e8e6c3..1f44192 100644 --- a/www/scripts/net/netcode.js +++ b/www/scripts/net/netcode.js @@ -32,7 +32,7 @@ socket.on('disconnect', function(data){ socket.on('message', function(data) { const mess = document.getElementById("message") - mess.textContent = `Server Connection: ${connection}` + mess.textContent = `${data}` }) @@ -63,5 +63,6 @@ socket.on('inGame', function(data){ socket.on('sync', function (sync){ game.world = sync.world; + console.log(game.world) render() }) diff --git a/www/style.css b/www/style.css index 5665a15..103e620 100644 --- a/www/style.css +++ b/www/style.css @@ -1,16 +1,124 @@ +* { + font-family: pixserif; +} -/* #mydiv { - position: absolute; - cursor: move; - z-index: 10; - background: coral; - width: 30px; - height: 30px; - border: 1px solid #d3d3d3; -} */ - +h1, h2 { + margin: 0px; +} + +h1 { + font-size: 3em; +} + +h2 { + font-size: 2.5em; +} +h3 { + font-size: 2em; +} + +p, span, input, button, u { + font-size: 1.7em; +} + +hr { + border-color: white; + /* height: 3px; */ + border: none; + height: 3px; + background: white; + margin: 0px; + padding: 0px; +} + +.row { + padding: 20px; + display: flex; + justify-content:space-between; + align-items: center; +} + +.row > span { + margin-left: 20px; + margin-right: 20px; +} + +.leftRight { + display: flex; + justify-content: center; + flex-wrap: wrap; +} + +.centerBar { + width: 3px; + height: inherit; + background: white +} + +.right { + display: inline; + margin: 40px; + /* background: red; */ + +} + +.left { + display: inline; + margin: 40px; + /* background: red; */ +} + +.slider { + display: inline-block; + -webkit-appearance: none; + appearance: none; + height: 55px; + width: 300px; + background-color: lightgray; +} + +.slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 20px; + height: 60px; + background: #f1f8t6; + cursor: pointer; +} +.slider::-moz-range-thumb { + width: 20px; + height: 60px; + border-radius: 0px; + background: #f1f8t6; + cursor: pointer; +} + +input[type=button], button, .buttonLink { + width: 100%; + background-color: #4CAF50; + color: white; + padding: 14px 20px; + margin: 8px 0; + border: none; + cursor: pointer; } + + input[type=number], input[type=text] { + /* width: 100%; */ + width: 300px; + display: inline-block; + padding: 12px 20px; + margin: 3px 0; + border: none; + box-sizing: border-box; + background-color: lightgray; } +@font-face { + /* font-weight: 500; */ + font-family: "pixserif"; + src: url('fonts/moderndos.woff2') format('woff2'), + url('fonts/moderndos.ttf') format('truetype'); +} span.button > img { pointer-events: none; image-rendering: optimizeSpeed; /* STOP SMOOTHING, GIVE ME SPEED */ @@ -18,22 +126,29 @@ span.button > img { image-rendering: -o-crisp-edges; /* Opera */ image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */ image-rendering: pixelated; /* Chrome */ - -ms-interpolation-mode: nearest-neighbor; /* IE8+ */ width: 70px; height: 70px; - transform: translate(0, 8px); - border: 2px solid darkgray; - border-radius: 4px; + transform: translate(0, 10px); background: lightgray; } +span.button.wide { + width: 128px; + height: 128px; +} + +span.button.wide > img { + width: 108px; + height: 108px; +} + span.button { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; display: inline-block; - background: tan; + background: lightgray; width:90px; height:90px; margin: 5px 5px 5px 5px; @@ -111,25 +226,5 @@ body { text-align: center; background-color: #2c2f33; color: white; -font-variant: normal; -font-family: verdana; -} - -h1 { - font-size: 25pt; } -h2 { - font-size: 20pt; -} -p{ - /* font-size: 12pt; */ - /* text-align: left; */ - margin: 0; -} - -h4 { - font-size: 12pt; - padding: 0; - margin: 0; -}