Create build menu

This commit is contained in:
Evan
2024-11-02 21:40:03 -07:00
parent e77bb5e118
commit c3c3c27c73
6 changed files with 191 additions and 14 deletions
+3 -7
View File
@@ -171,24 +171,20 @@
* add troop max DONE 10/31/2024
* rewrite EventsDisplay DONE 11/1/2024
* update Mena NPC locations DONE 11/1/2024
* fix name rendering
* use twitter emojis
* create build menu
* NPC has relations
* fix name rendering
* use twitter emojis
* private game shows how many players joined
* optimize sendBoat function
* NPC more likely to accept alliance fewer alliance player has
* better NPC relation logic
* surface NPC relations
* use SVGs for icons
* block user inputs if too far behind server
* BUG: FakeHuman don't be enemy if don't share border (or send boat)
* store cookies
* Load terrain dataImage in background
* BUG: half encircle Antartica causes capture
* improve front page (make map larger?)
* Add additional maps
* REFACTOR: give terranullius an ID, game.player() returns terranullius
* REFACTOR: ocean is considered TerraNullius ?
* Make icons svgs
testing webhook
+1
View File
@@ -0,0 +1 @@
<svg class="svg-icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M968.533333 808.533333L578.133333 418.133333c38.4-98.133333 17.066667-215.466667-61.866666-294.4-85.333333-85.333333-213.333333-102.4-315.733334-53.333333l185.6 185.6-130.133333 130.133333-185.6-185.6C21.333333 302.933333 38.4 430.933333 123.733333 516.266667c78.933333 78.933333 196.266667 100.266667 294.4 61.866666l390.4 390.4c17.066667 17.066667 44.8 17.066667 59.733334 0l100.266666-100.266666c17.066667-14.933333 17.066667-42.666667 0-59.733334z" /></svg>

After

Width:  |  Height:  |  Size: 658 B

+9 -1
View File
@@ -13,6 +13,7 @@ import { EmojiTable } from "./layers/radial/EmojiTable";
import { Leaderboard } from "./layers/Leaderboard";
import { ControlPanel } from "./layers/ControlPanel";
import { UIState } from "./UIState";
import { BuildMenu } from "./layers/radial/BuildMenu";
export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus: EventBus, clientID: ClientID): GameRenderer {
@@ -20,10 +21,17 @@ export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus:
const uiState = { attackRatio: 20 }
// TODO maybe append this to dcoument instead of querying for them?
const emojiTable = document.querySelector('emoji-table') as EmojiTable;
if (!emojiTable || !(emojiTable instanceof EmojiTable)) {
console.error('EmojiTable element not found in the DOM');
}
const buildMenu = document.querySelector('build-menu') as BuildMenu;
if (!buildMenu || !(buildMenu instanceof BuildMenu)) {
console.error('BuildMenu element not found in the DOM')
}
buildMenu.game = game
buildMenu.eventBus = eventBus
const leaderboard = document.querySelector('leader-board') as Leaderboard;
if (!emojiTable || !(leaderboard instanceof Leaderboard)) {
@@ -55,7 +63,7 @@ export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus:
new NameLayer(game, game.config().theme(), transformHandler, clientID),
new UILayer(eventBus, game, clientID, transformHandler),
eventsDisplay,
new RadialMenu(eventBus, game, transformHandler, clientID, emojiTable as EmojiTable, uiState),
new RadialMenu(eventBus, game, transformHandler, clientID, emojiTable as EmojiTable, buildMenu, uiState),
leaderboard,
controlPanel,
]
@@ -0,0 +1,168 @@
import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { EventBus } from '../../../../core/EventBus';
import { Cell, Game, Player } from '../../../../core/game/Game';
import { SendNukeIntentEvent } from '../../../Transport';
interface BuildItem {
id: string;
name: string;
icon: string;
cost: number;
buildTime: number;
}
const buildTable: BuildItem[][] = [
[
{ id: 'missile', name: 'Missile', icon: '🚀', cost: 100, buildTime: 5 },
{ id: 'battleship', name: 'Battleship', icon: '🚢', cost: 500, buildTime: 20 }
]
];
@customElement('build-menu')
export class BuildMenu extends LitElement {
public game: Game;
public eventBus: EventBus
private myPlayer: Player
private clickedCell: Cell
static styles = css`
:host {
display: block;
}
.build-menu {
position: fixed;
top: 50%;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
background-color: #1E1E1E;
padding: 15px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 95vw;
max-height: 95vh;
overflow-y: auto;
}
.build-row {
display: flex;
justify-content: center;
width: 100%;
}
.build-button {
width: 120px;
height: 120px;
border: 2px solid #444;
background-color: #2C2C2C;
color: white;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 8px;
padding: 10px;
}
.build-button:hover {
background-color: #3A3A3A;
transform: scale(1.05);
border-color: #666;
}
.build-button:active {
background-color: #4A4A4A;
transform: scale(0.95);
}
.build-icon {
font-size: 40px;
margin-bottom: 5px;
}
.build-name {
font-size: 14px;
font-weight: bold;
margin-bottom: 5px;
}
.build-cost {
font-size: 12px;
color: #FFD700;
}
.hidden {
display: none !important;
}
@media (max-width: 600px) {
.build-button {
width: 100px;
height: 100px;
margin: 5px;
}
.build-icon {
font-size: 32px;
}
.build-name {
font-size: 12px;
}
.build-cost {
font-size: 10px;
}
}
@media (max-width: 400px) {
.build-button {
width: 80px;
height: 80px;
margin: 3px;
}
.build-icon {
font-size: 28px;
}
}
`;
@state()
private _hidden = true;
public onBuildSelected: (item: BuildItem) => void = () => {
this.eventBus.emit(new SendNukeIntentEvent(this.myPlayer, this.clickedCell, null))
this.hideMenu()
};
render() {
return html`
<div class="build-menu ${this._hidden ? 'hidden' : ''}">
${buildTable.map(row => html`
<div class="build-row">
${row.map(item => html`
<button class="build-button" @click=${() => this.onBuildSelected(item)}>
<span class="build-icon">${item.icon}</span>
<span class="build-name">${item.name}</span>
<span class="build-cost">${item.cost} 💰</span>
</button>
`)}
</div>
`)}
</div>
`;
}
hideMenu() {
this._hidden = true;
this.requestUpdate();
}
showMenu(player: Player, clickedCell: Cell) {
this.myPlayer = player
this.clickedCell = clickedCell
this._hidden = false;
this.requestUpdate();
}
get isVisible() {
return !this._hidden;
}
}
@@ -15,9 +15,10 @@ import targetIcon from '../../../../../resources/images/TargetIconWhite.png';
import emojiIcon from '../../../../../resources/images/EmojiIconWhite.png';
import disabledIcon from '../../../../../resources/images/DisabledIcon.png';
import donateIcon from '../../../../../resources/images/DonateIconWhite.png';
import nukeIcon from '../../../../../resources/images/NukeIconWhite.png';
import buildIcon from '../../../../../resources/images/BuildIcon.svg';
import { EmojiTable } from "./EmojiTable";
import { UIState } from "../../UIState";
import { BuildMenu } from "./BuildMenu";
enum Slot {
@@ -25,7 +26,7 @@ enum Slot {
Boat,
Target,
Emoji,
Nuke,
Build,
}
export class RadialMenu implements Layer {
@@ -38,7 +39,7 @@ export class RadialMenu implements Layer {
[Slot.Boat, { name: "boat", disabled: true, action: () => { }, color: null, icon: null }],
[Slot.Target, { name: "target", disabled: true, action: () => { } }],
[Slot.Emoji, { name: "emoji", disabled: true, action: () => { } }],
[Slot.Nuke, { name: "nuke", disabled: true, action: () => { } }],
[Slot.Build, { name: "build", disabled: true, action: () => { } }],
]);
private readonly menuSize = 190;
@@ -55,6 +56,7 @@ export class RadialMenu implements Layer {
private transformHandler: TransformHandler,
private clientID: ClientID,
private emojiTable: EmojiTable,
private buildMenu: BuildMenu,
private uiState: UIState
) { }
@@ -230,8 +232,8 @@ export class RadialMenu implements Layer {
return
}
this.activateMenuElement(Slot.Nuke, "#ebe250", nukeIcon, () => {
this.eventBus.emit(new SendNukeIntentEvent(myPlayer, this.clickedCell, null))
this.activateMenuElement(Slot.Build, "#ebe250", buildIcon, () => {
this.buildMenu.showMenu(myPlayer, this.clickedCell)
})
if (tile.hasOwner()) {
@@ -358,6 +360,7 @@ export class RadialMenu implements Layer {
private onPointerUp(event: MouseUpEvent) {
this.hideRadialMenu()
this.emojiTable.hideTable()
this.buildMenu.hideMenu()
}
private showRadialMenu(x: number, y: number) {
+1
View File
@@ -74,6 +74,7 @@
<leader-board></leader-board>
<control-panel></control-panel>
<events-display></events-display>
<build-menu></build-menu>
<script>
window.addEventListener('DOMContentLoaded', (event) => {