update win condtion: 80% non fallout tiles

This commit is contained in:
Evan
2025-02-01 12:05:11 -08:00
parent d009ef925c
commit 7a2f4210ed
11 changed files with 275 additions and 216 deletions
+34
View File
@@ -0,0 +1,34 @@
import { GameView } from '../../../core/game/GameView';
import { TransformHandler } from '../TransformHandler';
import { Layer } from './Layer';
export class SpawnTimer implements Layer {
constructor(private game: GameView, private transformHandler: TransformHandler) { }
init() {
}
tick() {
}
shouldTransform(): boolean {
return false
}
renderLayer(context: CanvasRenderingContext2D) {
if (!this.game.inSpawnPhase()) {
return
}
const barHeight = 15;
const barBackgroundWidth = this.transformHandler.width();
const ratio = this.game.ticks() / this.game.config().numSpawnPhaseTurns()
// Draw bar background
context.fillStyle = 'rgba(0, 0, 0, 0.5)';
context.fillRect(0, 0, barBackgroundWidth, barHeight);
context.fillStyle = 'rgba(0, 128, 255, 0.7)';
context.fillRect(0, 0, barBackgroundWidth * ratio, barHeight);
}
}
-184
View File
@@ -1,184 +0,0 @@
import { EventBus } from "../../../core/EventBus";
import { WinEvent } from "../../../core/execution/WinCheckExecution";
import { Player } from "../../../core/game/Game";
import { ClientID } from "../../../core/Schemas";
import { Layer } from "./Layer";
import { TransformHandler } from "../TransformHandler";
import { consolex } from "../../../core/Consolex";
import { GameView } from "../../../core/game/GameView";
interface MenuOption {
label: string;
action: () => void;
}
export class UILayer implements Layer {
private exitButton: HTMLButtonElement;
private winModal: HTMLElement | null = null;
private customMenu = document.getElementById('customMenu');
constructor(
private eventBus: EventBus,
private game: GameView,
private clientID: ClientID,
private transformHandler: TransformHandler
) {
}
renderLayer(context: CanvasRenderingContext2D) {
if (!this.game.inSpawnPhase()) {
return
}
const barHeight = 15;
const barBackgroundWidth = this.transformHandler.width();
const ratio = this.game.ticks() / this.game.config().numSpawnPhaseTurns()
// Draw bar background
context.fillStyle = 'rgba(0, 0, 0, 0.5)';
context.fillRect(0, 0, barBackgroundWidth, barHeight);
context.fillStyle = 'rgba(0, 128, 255, 0.7)';
context.fillRect(0, 0, barBackgroundWidth * ratio, barHeight);
}
shouldTransform(): boolean {
return false
}
tick() {
}
init() {
this.createWinModal()
this.initRightClickMenu()
this.eventBus.on(WinEvent, (e) => this.onWinEvent(e))
}
initRightClickMenu() {
if (!this.customMenu) {
consolex.error('Custom menu not found');
return;
}
document.addEventListener('click', () => {
this.customMenu!.style.display = 'none';
});
const menuItems = this.customMenu.querySelectorAll('li');
menuItems.forEach(item => {
item.addEventListener('click', () => {
alert(`You clicked: ${item.textContent}`);
this.customMenu!.style.display = 'none';
});
});
}
createWinModal() {
consolex.log("Creating win modal");
this.winModal = document.createElement('div');
this.winModal.style.cssText = `
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border: 2px solid black;
border-radius: 10px;
z-index: 2000;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
`;
const content = document.createElement('div');
const title = document.createElement('h2');
title.textContent = 'Game Over';
title.id = 'winTitle';
title.style.marginTop = '0';
const message = document.createElement('p');
message.id = 'winMessage';
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex';
buttonContainer.style.justifyContent = 'space-between';
buttonContainer.style.marginTop = '20px';
const exitButton = document.createElement('button');
exitButton.textContent = 'Exit Game';
exitButton.onclick = () => this.exitGame();
this.styleButton(exitButton);
const continueButton = document.createElement('button');
continueButton.textContent = 'Keep Playing';
continueButton.onclick = () => this.closeWinModal();
this.styleButton(continueButton);
buttonContainer.appendChild(exitButton);
buttonContainer.appendChild(continueButton);
content.appendChild(title);
content.appendChild(message);
content.appendChild(buttonContainer);
this.winModal.appendChild(content);
document.body.appendChild(this.winModal);
consolex.log("Win modal appended to body");
}
styleButton(button: HTMLButtonElement) {
button.style.cssText = `
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
background-color: #4A90E2;
color: white;
border: none;
border-radius: 5px;
transition: background-color 0.3s;
`;
button.onmouseover = () => button.style.backgroundColor = '#3A7BCE';
button.onmouseout = () => button.style.backgroundColor = '#4A90E2';
}
onWinEvent(event: WinEvent) {
consolex.log(`${event.winner.name()} won the game!!}`)
this.showWinModal(event.winner)
}
showWinModal(winner: Player) {
if (this.winModal) {
const message = this.winModal.querySelector('#winMessage');
if (message) {
message.textContent = `${winner.name()} won the game!`;
}
const title = this.winModal.querySelector('#winTitle')
if (winner.clientID() == this.clientID) {
title.textContent = 'You Won!!!'
} else {
title.textContent = 'You Lost!!!'
}
this.winModal.style.display = 'block';
}
}
closeWinModal() {
if (this.winModal) {
this.winModal.style.display = 'none';
}
}
exitGame() {
this.closeWinModal();
window.location.reload();
}
}
+167
View File
@@ -0,0 +1,167 @@
import { LitElement, html, css } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { Player } from '../../../core/game/Game';
import { ClientID } from '../../../core/Schemas';
import { GameView, PlayerView } from '../../../core/game/GameView';
import { Layer } from './Layer';
import { GameUpdateType } from '../../../core/game/GameUpdates';
@customElement('win-modal')
export class WinModal extends LitElement implements Layer {
public clientID: ClientID
public game: GameView
private winner: PlayerView
@state()
isVisible = false
static styles = css`
:host {
display: block;
}
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(30, 30, 30, 0.7);
padding: 25px;
border-radius: 10px;
z-index: 9999;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
backdrop-filter: blur(5px);
color: white;
width: 300px;
transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
}
.modal.visible {
display: block;
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translate(-50%, -48%);
}
to {
opacity: 1;
transform: translate(-50%, -50%);
}
}
h2 {
margin: 0 0 15px 0;
font-size: 24px;
text-align: center;
color: white;
}
p {
margin: 0 0 20px 0;
text-align: center;
background-color: rgba(0, 0, 0, 0.3);
padding: 10px;
border-radius: 5px;
}
.button-container {
display: flex;
justify-content: space-between;
gap: 10px;
}
button {
flex: 1;
padding: 12px;
font-size: 16px;
cursor: pointer;
background: rgba(0, 150, 255, 0.6);
color: white;
border: none;
border-radius: 5px;
transition: background-color 0.2s ease, transform 0.1s ease;
}
button:hover {
background: rgba(0, 150, 255, 0.8);
transform: translateY(-1px);
}
button:active {
transform: translateY(1px);
}
@media (max-width: 768px) {
.modal {
width: 90%;
max-width: 300px;
padding: 20px;
}
h2 {
font-size: 20px;
}
button {
padding: 10px;
font-size: 14px;
}
}
`;
render() {
if (!this.winner) return null;
const isWinner = this.winner.clientID() === this.clientID;
const title = isWinner ? 'You Won!!!' : 'You Lost!!!';
const message = `${this.winner.name()} won the game!`;
return html`
<div class="modal ${this.isVisible ? 'visible' : ''}">
<h2>${title}</h2>
<p>${message}</p>
<div class="button-container">
<button @click=${this._handleExit}>Exit Game</button>
<button @click=${this._handleContinue}>Keep Playing</button>
</div>
</div>
`;
}
show(winner: PlayerView) {
this.winner = winner;
this.isVisible = true;
this.requestUpdate();
}
hide() {
this.isVisible = false;
this.requestUpdate();
}
private _handleExit() {
this.hide();
window.location.reload();
}
private _handleContinue() {
this.hide();
}
init() { }
tick() {
this.game.updatesSinceLastTick()[GameUpdateType.WinUpdate]
.forEach(wu => this.show(this.game.playerBySmallID(wu.winnerID) as PlayerView))
}
renderLayer(context: CanvasRenderingContext2D) {
}
shouldTransform(): boolean {
return false
}
}