small updates

This commit is contained in:
Evan Scamehorn
2025-12-04 13:08:07 -06:00
parent 8fc551ad68
commit f3cb583836
5 changed files with 88 additions and 35 deletions

View File

@@ -16,7 +16,7 @@
<!-- Floating Income Feedback --> <!-- Floating Income Feedback -->
<div id="income-float" <div id="income-float"
style="position:absolute; top:60px; left:220px; color:#10B981; font-weight:bold; font-size:20px; opacity:0; transition: all 1s ease-out; z-index:90; text-shadow:0 1px 2px white;"> style="position:absolute; top:60px; left:220px; color:#6AFF00; font-weight:bold; font-size:20px; opacity:0; transition: all 1s ease-out; z-index:90; text-shadow: 3px 3px 5px black;">
+$0</div> +$0</div>
<div id="ui-container"> <div id="ui-container">

View File

@@ -18,7 +18,13 @@ This project:
- Recall: each component can be only claimed by one group member - Recall: each component can be only claimed by one group member
- I created this project alone - I created this project alone
- I only claim to complete **game design** - I only claim to complete **user interaction**, including:
- Click to add route nodes
- Drag to edit route nodes
- A* pathfinding updates instantly on node movement
- UI provides immediate feedback on cost and ridership
- Multiple mapping layers to help plan out building routes
- Save/load system
- You only will grade me on that category - You only will grade me on that category
- All other categories you should score with a 1, as I do not claim to complete - All other categories you should score with a 1, as I do not claim to complete
them them

View File

@@ -288,7 +288,7 @@ export class RouteManager {
} }
}); });
const synergy = Math.min(totalPop, totalJobs); const synergy = Math.min(totalPop, totalJobs);
const GAME_BALANCE_MULTIPLIER = 5.0; const GAME_BALANCE_MULTIPLIER = 1.0;
return Math.floor(synergy * GAME_BALANCE_MULTIPLIER); return Math.floor(synergy * GAME_BALANCE_MULTIPLIER);
} }

View File

@@ -1,7 +1,7 @@
export class UIManager { export class UIManager {
constructor(routeManager) { constructor(routeManager) {
this.routeManager = routeManager; this.routeManager = routeManager;
this.gameManager = null; // Set via dependency injection in main.js if needed, or we just access logic differently this.gameManager = null;
// UI Elements // UI Elements
this.elCurrentLength = document.getElementById('current-length'); this.elCurrentLength = document.getElementById('current-length');
@@ -76,7 +76,7 @@ export class UIManager {
} }
}; };
reader.readAsText(file); reader.readAsText(file);
e.target.value = ''; // Reset so we can load same file again if needed e.target.value = '';
}); });
} }
@@ -116,43 +116,87 @@ export class UIManager {
routes.forEach((route, index) => { routes.forEach((route, index) => {
const li = document.createElement('li'); const li = document.createElement('li');
li.style.display = 'flex';
li.style.alignItems = 'center';
li.style.justifyContent = 'space-between';
li.style.padding = '8px 0';
li.style.borderBottom = '1px solid #eee';
// --- BADGE CONTAINER ---
// This holds both the visual badge and the invisible input on top of it
const badgeContainer = document.createElement('div');
badgeContainer.style.position = 'relative';
badgeContainer.style.width = '28px';
badgeContainer.style.height = '28px';
badgeContainer.style.marginRight = '10px';
// 1. The Visual Badge (Background)
const badge = document.createElement('div');
badge.textContent = (index + 1);
badge.style.width = '100%';
badge.style.height = '100%';
badge.style.backgroundColor = route.color;
badge.style.color = '#fff';
badge.style.fontWeight = 'bold';
badge.style.display = 'flex';
badge.style.alignItems = 'center';
badge.style.justifyContent = 'center';
badge.style.borderRadius = '4px';
badge.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
badge.style.textShadow = '0 1px 2px rgba(0,0,0,0.5)';
// 2. The Invisible Input (Overlay)
const colorInput = document.createElement('input');
colorInput.type = 'color';
colorInput.value = route.color || "#000000";
// Style to overlay exactly on top of the badge
colorInput.style.position = 'absolute';
colorInput.style.top = '0';
colorInput.style.left = '0';
colorInput.style.width = '100%';
colorInput.style.height = '100%';
colorInput.style.opacity = '0'; // Visually invisible
colorInput.style.cursor = 'pointer'; // Show pointer so user knows it's clickable
colorInput.style.border = 'none';
colorInput.style.padding = '0';
// Update logic
colorInput.addEventListener('input', (e) => {
const newColor = e.target.value;
badge.style.backgroundColor = newColor;
this.routeManager.updateRouteColor(index, newColor);
});
badgeContainer.appendChild(badge);
badgeContainer.appendChild(colorInput);
li.appendChild(badgeContainer);
// --- ROUTE INFO ---
let lenStr = route.stats.length > 1000 let lenStr = route.stats.length > 1000
? (route.stats.length / 1000).toFixed(1) + "km" ? (route.stats.length / 1000).toFixed(1) + "km"
: Math.round(route.stats.length) + "m"; : Math.round(route.stats.length) + "m";
// Color Picker const infoDiv = document.createElement('div');
const colorInput = document.createElement('input'); infoDiv.style.flex = '1';
colorInput.type = 'color'; infoDiv.style.display = 'flex';
colorInput.value = route.color || "#000000"; infoDiv.style.flexDirection = 'column';
colorInput.style.border = "none";
colorInput.style.width = "24px";
colorInput.style.height = "24px";
colorInput.style.cursor = "pointer";
colorInput.title = "Change Route Color";
colorInput.addEventListener('input', (e) => { infoDiv.innerHTML = `
this.routeManager.updateRouteColor(index, e.target.value); <span style="font-size:12px; font-weight:600; color:#333;">Line ${index + 1}</span>
}); <span style="font-size:11px; color:#666;">${lenStr} | ${route.stats.ridership} riders</span>
`;
const span = document.createElement('span'); // --- BUTTONS ---
span.innerHTML = ` const btnDiv = document.createElement('div');
<strong>Route ${index + 1}</strong> <br> btnDiv.style.display = 'flex';
<small>${lenStr} | ${route.stats.ridership} riders</small> btnDiv.style.gap = '4px';
`;
const detailsDiv = document.createElement('div');
detailsDiv.style.display = "flex";
detailsDiv.style.alignItems = "center";
detailsDiv.style.gap = "8px";
detailsDiv.appendChild(colorInput);
detailsDiv.appendChild(span);
li.appendChild(detailsDiv);
const btnEdit = document.createElement('button'); const btnEdit = document.createElement('button');
btnEdit.textContent = "Edit"; btnEdit.textContent = "";
btnEdit.className = "btn-icon btn-edit"; btnEdit.className = "btn-icon";
btnEdit.title = "Redraw Route";
btnEdit.style.padding = "4px 8px";
btnEdit.onclick = () => { btnEdit.onclick = () => {
this.routeManager.editSavedRoute(index); this.routeManager.editSavedRoute(index);
this.renderRouteList(); this.renderRouteList();
@@ -160,16 +204,19 @@ export class UIManager {
const btnDel = document.createElement('button'); const btnDel = document.createElement('button');
btnDel.textContent = "✕"; btnDel.textContent = "✕";
btnDel.className = "btn-icon btn-del"; btnDel.className = "btn-icon";
btnDel.title = "Delete Route";
btnDel.style.color = "#ef4444";
btnDel.style.padding = "4px 8px";
btnDel.onclick = () => { btnDel.onclick = () => {
this.routeManager.deleteSavedRoute(index); this.routeManager.deleteSavedRoute(index);
this.renderRouteList(); this.renderRouteList();
}; };
const btnDiv = document.createElement('div');
btnDiv.appendChild(btnEdit); btnDiv.appendChild(btnEdit);
btnDiv.appendChild(btnDel); btnDiv.appendChild(btnDel);
li.appendChild(infoDiv);
li.appendChild(btnDiv); li.appendChild(btnDiv);
this.elRouteList.appendChild(li); this.elRouteList.appendChild(li);

View File