create single player modal

This commit is contained in:
evanpelle
2024-10-12 12:32:40 -07:00
parent 6eaa14da73
commit cecbe8c313
5 changed files with 139 additions and 17 deletions
+24 -4
View File
@@ -12,14 +12,13 @@ import './UsernameInput';
import './styles.css';
import {UsernameInput} from "./UsernameInput";
import {SinglePlayerModal} from "./SinglePlayerModal";
const usernameKey: string = 'username';
class Client {
private terrainMap: Promise<TerrainMap>
private game: ClientGame
@@ -44,10 +43,23 @@ class Client {
this.terrainMap = loadTerrainMap()
this.ip = getClientIP()
document.addEventListener('join-lobby', this.handleJoinLobby.bind(this));
document.addEventListener('leave-lobby', this.handleLeaveLobby.bind(this));
document.addEventListener('single-player', this.handleSinglePlayer.bind(this));
const singlePlayerButton = document.getElementById('single-player');
const modal = document.querySelector('single-player-modal') as SinglePlayerModal;
if (singlePlayerButton && modal instanceof SinglePlayerModal) {
singlePlayerButton.addEventListener('click', () => {
modal.open();
});
}
}
private async handleJoinLobby(event: CustomEvent) {
const lobby = event.detail
const lobby = event.detail.lobby
console.log(`joining lobby ${lobby.id}`)
const [terrainMap, clientIP] = await Promise.all([
this.terrainMap,
@@ -70,8 +82,16 @@ class Client {
g.stop();
});
}
}
private async handleLeaveLobby(event: CustomEvent) {
this.game.stop()
this.game = null
}
private async handleSinglePlayer(event: CustomEvent) {
alert('coming soon')
}
}
async function getClientIP(timeoutMs: number = 1000): Promise<string | null> {
const controller = new AbortController();
+19 -10
View File
@@ -8,6 +8,8 @@ export class PublicLobby extends LitElement {
@state() private isLobbyHighlighted: boolean = false;
private lobbiesInterval: number | null = null;
private currLobby: Lobby = null
static styles = css`
/* Add your styles here, based on your existing CSS */
.lobby-button {
@@ -91,25 +93,32 @@ export class PublicLobby extends LitElement {
return html`
<button
@click=${() => this.joinLobby(lobby)}
@click=${() => this.lobbyClicked(lobby)}
class="lobby-button ${this.isLobbyHighlighted ? 'highlighted' : ''}"
>
<div class="lobby-name">Game ${lobby.id.substring(0, 3)}</div>
<div class="lobby-timer">Starts in: ${timeRemaining}s</div>
<div class="player-count">Players: ${lobby.numClients}</div>
</button>
${this.lobbies.length > 1 ? html`
<div id="next-game">Next Game: ${this.lobbies[1].id.substring(0, 3)}</div>
` : ''}
`;
}
private joinLobby(lobby: Lobby) {
private lobbyClicked(lobby: Lobby) {
this.isLobbyHighlighted = !this.isLobbyHighlighted;
this.dispatchEvent(new CustomEvent('join-lobby', {
detail: lobby,
bubbles: true,
composed: true
}));
if (this.currLobby == null) {
this.currLobby = lobby
this.dispatchEvent(new CustomEvent('join-lobby', {
detail: {lobby: lobby},
bubbles: true,
composed: true
}));
} else {
this.dispatchEvent(new CustomEvent('leave-lobby', {
detail: {lobby: this.currLobby},
bubbles: true,
composed: true
}));
this.currLobby = null
}
}
}
+93
View File
@@ -0,0 +1,93 @@
import {LitElement, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
@customElement('single-player-modal')
export class SinglePlayerModal extends LitElement {
@state() private isModalOpen = false;
static styles = css`
.modal-overlay {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: white;
margin: 15% auto;
padding: 20px;
border-radius: 8px;
width: 80%;
max-width: 500px;
text-align: center; /* Center the content inside the modal */
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #007bff; /* Changed to blue */
color: white;
border: none;
border-radius: 4px;
transition: background-color 0.3s;
display: inline-block; /* Ensures the button takes only necessary width */
margin-top: 20px; /* Adds some space above the button */
}
button:hover {
background-color: #0056b3; /* Darker blue for hover state */
}
`;
render() {
return html`
<div class="modal-overlay" style="display: ${this.isModalOpen ? 'block' : 'none'}">
<div class="modal-content">
<span class="close" @click=${this.close}>&times;</span>
<h2>Start Single Player Game</h2>
<button @click=${this.startGame}>Start Game</button>
</div>
</div>
`;
}
public open() {
this.isModalOpen = true;
}
public close() {
this.isModalOpen = false;
}
private startGame() {
console.log('Starting single player game...');
this.dispatchEvent(new CustomEvent('single-player', {
detail: {todo: "TODO"},
bubbles: true,
composed: true
}));
this.close();
}
}
+1 -1
View File
@@ -57,7 +57,6 @@
<public-lobby></public-lobby>
</div>
</div>
<h3 id="next-game" class="invisible"> </h3>
</div>
<div id="customMenu">
@@ -68,6 +67,7 @@
<div id="app"></div>
<div id="radialMenu" class="radial-menu"></div>
<single-player-modal></single-player-modal>
<emoji-table></emoji-table>
<leader-board></leader-board>
+2 -2
View File
@@ -9,10 +9,10 @@ export const devConfig = new class extends DefaultConfig {
return 40
}
gameCreationRate(): number {
return 2 * 1000
return 20 * 1000
}
lobbyLifetime(): number {
return 2 * 1000
return 20 * 1000
}
turnIntervalMs(): number {
return 100