gameplay mechanics

This commit is contained in:
Evan Scamehorn
2025-12-02 14:40:18 -06:00
parent a3e057ef37
commit 68ca45f58e
8 changed files with 316 additions and 140 deletions

View File

@@ -2,18 +2,25 @@ export class UIManager {
constructor(routeManager) {
this.routeManager = routeManager;
// DOM Elements
// UI Elements
this.elCurrentLength = document.getElementById('current-length');
this.elCurrentCost = document.getElementById('current-cost'); // NEW
this.elCurrentRiders = document.getElementById('current-riders'); // NEW
this.elBudget = document.getElementById('val-budget'); // NEW
this.elDay = document.getElementById('val-day'); // NEW
this.elTotalRiders = document.getElementById('val-riders'); // NEW
this.elIncomeFloat = document.getElementById('income-float'); // NEW
this.elRouteList = document.getElementById('route-list');
this.elContainer = document.getElementById('ui-container');
this.btnSave = document.getElementById('btn-save');
this.btnDiscard = document.getElementById('btn-discard');
this.btnToggle = document.getElementById('ui-toggle');
this.btnZoning = document.getElementById('btn-zoning');
// We need a callback to main.js to actually change colors
this.onToggleZoning = null;
this.initListeners();
}
@@ -21,39 +28,56 @@ export class UIManager {
this.btnSave.addEventListener('click', () => {
this.routeManager.saveCurrentRoute();
this.renderRouteList();
this.updateStats(0);
});
this.btnDiscard.addEventListener('click', () => {
this.routeManager.clearCurrentRoute();
this.updateStats(0);
});
// Toggle Logic
this.btnToggle.addEventListener('click', () => {
this.elContainer.classList.toggle('hidden');
});
this.btnZoning.addEventListener('click', () => {
const isActive = this.btnZoning.classList.toggle('active');
this.btnZoning.style.background = isActive ? '#4B5563' : ''; // Darken when active
this.btnZoning.style.background = isActive ? '#4B5563' : '';
this.btnZoning.style.color = isActive ? 'white' : '';
if (this.onToggleZoning) {
this.onToggleZoning(isActive);
}
if (this.onToggleZoning) this.onToggleZoning(isActive);
});
}
updateStats(lengthInMeters) {
let text = "";
if (lengthInMeters > 1000) {
text = (lengthInMeters / 1000).toFixed(2) + " km";
} else {
text = Math.round(lengthInMeters) + " m";
}
this.elCurrentLength.textContent = text;
// Called by GameManager
updateGameStats(stats) {
this.elBudget.textContent = "$" + stats.budget.toLocaleString();
this.elDay.textContent = stats.day;
this.elTotalRiders.textContent = stats.totalRiders.toLocaleString();
}
showIncomeFeedback(amount) {
this.elIncomeFloat.textContent = "+ $" + amount.toLocaleString();
this.elIncomeFloat.style.opacity = 1;
this.elIncomeFloat.style.top = "40px";
// Reset animation
setTimeout(() => {
this.elIncomeFloat.style.opacity = 0;
this.elIncomeFloat.style.top = "60px";
}, 2000);
}
// Called by RouteManager on path change
updateDraftStats(stats) {
// Length
let lenText = stats.length > 1000
? (stats.length / 1000).toFixed(2) + " km"
: Math.round(stats.length) + " m";
this.elCurrentLength.textContent = lenText;
// Cost
this.elCurrentCost.textContent = "$" + stats.cost.toLocaleString();
// Ridership
this.elCurrentRiders.textContent = stats.ridership.toLocaleString() + " / day";
}
renderRouteList() {
@@ -63,26 +87,27 @@ export class UIManager {
routes.forEach((route, index) => {
const li = document.createElement('li');
let lenStr = route.length > 1000
? (route.length / 1000).toFixed(2) + " km"
: Math.round(route.length) + " m";
// Format Length
let lenStr = route.stats.length > 1000
? (route.stats.length / 1000).toFixed(1) + "km"
: Math.round(route.stats.length) + "m";
// Create Label
const span = document.createElement('span');
span.innerHTML = `<strong>Route ${index + 1}</strong> (${lenStr})`;
span.innerHTML = `
<strong>Route ${index + 1}</strong> <br>
<small>${lenStr} | ${route.stats.ridership} riders</small>
`;
li.appendChild(span);
// Edit Button
const btnEdit = document.createElement('button');
btnEdit.textContent = "Edit";
btnEdit.className = "btn-icon btn-edit";
btnEdit.onclick = () => {
this.routeManager.editSavedRoute(index);
this.renderRouteList(); // Re-render to remove it from list
this.renderRouteList();
};
li.appendChild(btnEdit);
// Delete Button
const btnDel = document.createElement('button');
btnDel.textContent = "✕";
btnDel.className = "btn-icon btn-del";