improve front page

This commit is contained in:
evanpelle
2024-08-17 20:56:11 -07:00
parent 0ea670d975
commit 19c826d944
13 changed files with 199 additions and 58 deletions
+4 -4
View File
@@ -22,11 +22,11 @@
* delete players when territories too small DONE 8/16/2024
* double attack add troops DONE 8/16/2024
* Have some time for spawning before game starts DONE 8/16/2024
* fix desync DONE 8/16/2024
* fix server memory leak DONE 8/16/2024
* only send delta turns on connect/reconnect DONE 8/17/2024
* Create separate game config dev vs prod
* improve front page, only one game at a time every 30s
* fix desync
* fix server memory leak
* Create separate game config dev vs prod DONE 8/17/2024
* improve front page, only one game at a time every 30s DONE 8/17/2024
* BUG: boats not going to destination, coast not being recognized
* BUG: boats freeze game on path calculation
* better algorithm for name render placement
+4 -3
View File
@@ -5,8 +5,9 @@
"build-dev": "webpack --config webpack.config.js --mode development",
"build-prod": "webpack --config webpack.config.js --mode production",
"start:client": "webpack serve --open --node-env development",
"start:server": "node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
"dev": "concurrently \"npm run start:client\" \"npm run start:server\"",
"start:server": "GAME_ENV=prod node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
"start:server-dev": "GAME_ENV=dev node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
"dev": "GAME_ENV=dev concurrently \"npm run start:client\" \"npm run start:server-dev\"",
"test": "jest"
},
"devDependencies": {
@@ -53,4 +54,4 @@
"zod": "^3.23.8"
},
"type": "module"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

+14
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

+48 -16
View File
@@ -7,6 +7,8 @@ import {GameID, Lobby, ServerMessage, ServerMessageSchema} from "../core/Schemas
import {loadTerrainMap} from "../core/TerrainMapLoader";
import {ClientGame, createClientGame} from "./ClientGame";
import {v4 as uuidv4} from 'uuid';
import backgroundImage from '../../resources/images/World.png';
// import WebSocket from 'ws';
@@ -52,17 +54,27 @@ class Client {
lobbies.forEach(lobby => {
const button = document.createElement('button');
button.textContent = `Join Lobby ${lobby.id} (${Math.floor((lobby.startTime - Date.now()) / 1000)}s)`;
button.className = 'lobby-button';
const nameElement = document.createElement('div');
nameElement.className = 'lobby-name';
nameElement.textContent = `Lobby ${lobby.id}`;
const timerElement = document.createElement('div');
timerElement.className = 'lobby-timer';
const timeRemaining = Math.max(0, Math.floor((lobby.startTime - Date.now()) / 1000));
timerElement.textContent = `Starts in: ${timeRemaining}s`;
const playerCountElement = document.createElement('div');
playerCountElement.className = 'player-count';
button.appendChild(nameElement);
button.appendChild(timerElement);
button.appendChild(playerCountElement);
button.onclick = () => this.joinLobby(lobby);
this.lobbiesContainer.appendChild(button);
});
// // Join first lobby
// if (!this.hasJoined && lobbies.length > 0) {
// this.hasJoined = true
// console.log(`joining lobby ${lobbies[0].id}`)
// this.joinLobby(lobbies[0].id)
// }
}
async fetchLobbies(): Promise<Lobby[]> {
@@ -81,16 +93,33 @@ class Client {
}
private async joinLobby(lobby: Lobby) {
clearInterval(this.lobbiesInterval)
this.lobbiesContainer.innerHTML = `Joining: ${lobby.id}`; // Clear existing lobbies
clearInterval(this.lobbiesInterval);
if (this.lobbiesContainer) {
// Clear existing content
this.lobbiesContainer.innerHTML = '';
// Ensure the container takes up the full height of the viewport
this.lobbiesContainer.style.display = 'flex';
this.lobbiesContainer.style.justifyContent = 'center';
this.lobbiesContainer.style.alignItems = 'center';
this.lobbiesContainer.style.minHeight = '100vh';
// Create and add the joining message
const joiningMessage = document.createElement('div');
joiningMessage.textContent = `Joining: ${lobby.id}`;
joiningMessage.className = 'joining-message';
this.lobbiesContainer.appendChild(joiningMessage);
}
this.terrainMap.then((map) => {
if (this.game != null) {
return
return;
}
// TODO make id more random, if two player join same millisecond get same id.
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), map)
this.game.join()
})
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), map);
this.game.join();
});
}
}
@@ -106,4 +135,7 @@ function getUsername(): string {
// Initialize the client when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new Client().initialize();
});
});
document.body.style.backgroundImage = `url(${backgroundImage})`;
+3 -3
View File
@@ -154,9 +154,9 @@ export class ClientGame {
}
private inputEvent(event: MouseDownEvent) {
if (this.turns.length < this.config.turnsUntilGameStart()) {
return
}
// if (this.turns.length < this.config.turnsUntilGameStart()) {
// return
// }
if (!this.isActive) {
return
}
+82 -27
View File
@@ -8,71 +8,126 @@
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0;
padding: 0;
min-height: 100vh;
background-color: #404040;
/* Dark grey background */
background-image: url('/resources/images/watercolor_worldmap.jpg');
background-size: cover;
background-position: center;
background-attachment: fixed;
background-blend-mode: overlay;
}
.content {
max-width: 1020px;
/* Allows for two 500px buttons side by side with some margin */
margin: 0 auto;
padding: 20px;
background-color: #f0f0f0;
position: relative;
}
h1 {
text-align: center;
color: #333;
color: #ffffff;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
font-size: 2.5em;
margin-bottom: 30px;
}
#username-container {
margin-bottom: 20px;
margin-bottom: 30px;
}
#username {
width: 100%;
padding: 10px;
font-size: 16px;
padding: 15px;
font-size: 18px;
border: 2px solid #007bff;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.8);
}
.lobby-button:hover {
background-color: rgba(0, 123, 255, 0.4);
transform: translateY(-5px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
}
.player-count {
font-size: 24px;
margin-top: 20px;
color: #aaddff;
}
#lobbies-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
}
.lobby-button {
height: 100px;
font-size: 18px;
width: 500px;
height: 500px;
font-size: 24px;
font-weight: bold;
border: 2px solid #007bff;
background-color: #ffffff;
color: #007bff;
border: 3px solid #007bff;
background-color: rgba(0, 123, 255, 0.2);
color: #ffffff;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
transition: background-color 0.3s, color 0.3s;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
padding: 20px;
text-align: center;
box-sizing: border-box;
}
.lobby-button:hover {
background-color: #007bff;
color: #ffffff;
background-color: rgba(0, 123, 255, 0.4);
transform: translateY(-5px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.4);
}
.lobby-name {
font-size: 36px;
margin-bottom: 20px;
}
.lobby-timer {
font-size: 28px;
margin-bottom: 20px;
}
.player-count {
font-size: 14px;
margin-top: 5px;
font-size: 24px;
color: #aaddff;
}
.joining-message {
font-size: 48px;
color: white;
text-align: center;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<h1>OpenFront (ALPHA)</h1>
<div id="username-container">
<input type="text" id="username" placeholder="Enter your username">
</div>
<div id="lobbies-container">
<!-- Lobby buttons will be inserted here by your existing JavaScript -->
<div class="content">
<h1>OpenFront (ALPHA)</h1>
<div id="username-container">
<input type="text" id="username" placeholder="Enter your username">
</div>
<div id="lobbies-container">
<!-- Lobby buttons will be inserted here by your existing JavaScript -->
</div>
</div>
<!-- Your existing script file -->
+5 -4
View File
@@ -4,12 +4,13 @@ import {devConfig} from "./DevConfig";
import {defaultConfig} from "./DefaultConfig";
export function getConfig(): Config {
if (process.env.GAME_ENV == 'prod') {
console.log('Using prod config')
return defaultConfig
} else {
// TODO: 'prod' not found in prod env
if (process.env.GAME_ENV == 'dev') {
console.log('Using dev config')
return devConfig
} else {
console.log('Using prod config')
return defaultConfig
}
}
+14 -1
View File
@@ -1,4 +1,17 @@
declare module '*.png' {
const content: string;
export default content;
}
}
declare module '*.jpg' {
const value: string;
export default value;
}
declare module '*.jpeg' {
const value: string;
export default value;
}
declare module '*.svg' {
const value: string;
export default value;
}
+21
View File
@@ -0,0 +1,21 @@
import {ClientID} from "../core/Schemas";
import {Client} from "./Client";
export class Lobby {
public clients: Map<ClientID, Client> = new Map()
private startGameTs: number
constructor(public readonly id: string, durationMs: number) {
this.startGameTs = Date.now() + durationMs
}
public addClient(client: Client) {
this.clients.set(client.id, client)
}
public isExpired(now: number): boolean {
return now > this.startGameTs
}
}
+4
View File
@@ -28,6 +28,10 @@ export default (env, argv) => {
generator: {
filename: 'images/[hash][ext][query]'
}
},
{
test: /\.svg$/,
type: 'asset/inline',
}
],
},