mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
create single player modal
This commit is contained in:
+24
-4
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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}>×</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();
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user