From 7ea3166d63cc0e2b00a1b748ba72b88771c8fd7a Mon Sep 17 00:00:00 2001 From: bowen Date: Sun, 25 Jan 2026 03:35:01 -0500 Subject: [PATCH] added dynamic sanity, UI polishes --- frontend/src/App.css | 205 +++++++++++++++++++++---- frontend/src/App.tsx | 69 +++++---- frontend/src/components/EventModal.css | 6 +- frontend/src/components/EventModal.tsx | 5 +- frontend/src/components/HUD/HUD.css | 96 ++++++++---- frontend/src/components/HUD/HUD.tsx | 29 ++-- frontend/src/engine/buckets.ts | 1 - 7 files changed, 309 insertions(+), 102 deletions(-) diff --git a/frontend/src/App.css b/frontend/src/App.css index 94f8a13..a574a24 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -1,41 +1,40 @@ +/* Full-screen wrapper */ .fullscreen { width: 100vw; height: 100vh; - display: flex; align-items: center; justify-content: center; - } +/* Lil guy (centered character) */ .lil-guy-container { position: fixed; - /* This centers him exactly in the middle of the screen */ - top: 50%; + top: 50%; left: 50%; - transform: translate(-50%, 20%); - - - z-index: -5; + transform: translate(-50%, 20%); + z-index: 5; /* above background/pattern */ pointer-events: none; } .lil-guy { - width: 250px; /* Slightly smaller to fit the dorm better */ + width: 250px; height: auto; } +/* House background */ .house-background { - position: fixed; /* full screen and fixed so it doesn’t scroll */ + position: fixed; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; - z-index: -5; /* send behind everything */ - pointer-events: none; /* make clicks pass through */ + z-index: 0; /* behind everything */ + pointer-events: none; } +/* Dotted pattern overlay */ .pattern-overlay { position: fixed; top: 0; @@ -43,49 +42,193 @@ width: 100%; height: 100%; - /* Cutesy Pastel Blue */ - background-color: #d3c6b7; - - /* White Dotted Pattern */ - background-image: radial-gradient(circle, white 2px, transparent 2px); - background-size: 30px 30px; /* Adjust this for dot density */ - - /* Make it diagonal and slightly transparent so the house peeks through */ + background-color: #bdaf95; /* soft cream/beige */ + background-image: radial-gradient(circle, rgba(245, 244, 243, 0.5) 2px, transparent 2px); + background-size: 30px 30px; opacity: 0.6; - z-index: -8; /* Sits between House (-10) and Lil Guy (-5) */ + z-index: -10; /* above background but below character */ pointer-events: none; + + animation: backgroundMove 3s linear infinite; } -/* Optional: Make the dots float/move slowly */ @keyframes backgroundMove { from { background-position: 0 0; } to { background-position: 30px 30px; } } -.pattern-overlay { - animation: backgroundMove 3s linear infinite; -} - +/* Game container */ .game-container { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; min-height: 100vh; - padding-top: 20px; /* Give the stats some breathing room */ + padding-top: 20px; position: relative; } +/* Investment modal */ .investment-modal { - background: rgba(255, 255, 255, 0.8); /* Semi-transparent white */ + background: #fff4e6; /* soft cream */ padding: 20px; - border-radius: 15px; - margin-top: auto; /* Pushes the modal to the bottom */ + border-radius: 16px; + margin-top: auto; margin-bottom: 50px; z-index: 10; display: flex; gap: 15px; flex-wrap: wrap; justify-content: center; - box-shadow: 0 4px 15px rgba(0,0,0,0.1); + box-shadow: 0 6px 18px rgba(100, 60, 20, 0.25); + font-family: 'Upheavel', sans-serif; + color: #5b4636; /* muted brown text */ } + +/* Input labels */ +.investment-modal label { + display: flex; + flex-direction: column; + font-weight: 300; + font-size: 1.3rem; +} + +/* Input fields */ +.investment-modal input { + margin-top: 6px; + padding: 6px 10px; + border-radius: 8px; + border: 2px solid #d2b48c; + font-family: 'Upheavel', sans-serif; + font-size: 1rem; +} + +/* Buttons inside modal */ +.investment-modal .button-group button, +.upgrade-btn { + background-color: #d2b48c; + color: #fffaf0; + border: none; + border-radius: 12px; + padding: 8px 16px; + font-family: 'Upheavel', sans-serif; + font-size: 1rem; + cursor: pointer; + transition: transform 0.1s ease, background 0.2s ease; +} + +.investment-modal .button-group button:hover, +.upgrade-btn:hover { + transform: scale(1.05); + background-color: #a67c52; +} + +/* Retire / Advance button base */ +.advance-btn, +button.px-4 { + background-color: #d2b48c; + color: #fffaf0; + border: none; + border-radius: 12px; + padding: 10px 18px; + font-family: 'Upheavel', sans-serif; + font-size: 1rem; + cursor: pointer; + margin-top: 15px; + transition: transform 0.1s ease, background 0.2s ease; +} + +/* Hover / bounce only when enabled */ +.advance-btn:hover:not(:disabled), +button.px-4:hover:not(:disabled) { + transform: scale(1.05); + background-color: #a67c52; +} + +/* Disabled state */ +button:disabled, +button.px-4:disabled { + background-color: #b0a08c; /* muted beige-grey */ + color: #e0dcd2; /* faded cream text */ + cursor: not-allowed; + transform: none; /* no hover bounce */ + box-shadow: none; +} + + +/* HUD (left & right panels) */ +.hud-left, .hud-right { + background: #fff4e6; + border: 3px solid #d2b48c; + border-radius: 14px; + box-shadow: 0 4px 12px rgba(100,60,20,0.2); + color: #5b4636; + font-family: 'Upheavel', monospace; +} + +.hud-left { + position: absolute; + top: 10px; + left: 10px; + width: 220px; + padding: 16px; +} + +.hud-left h3 { color: #8b5e3c; margin-bottom: 10px; } +.hud-left ul { list-style: none; padding: 0; margin: 0; } +.hud-left li { margin-bottom: 6px; } + +.hud-right { + position: absolute; + top: 10px; + right: 10px; + width: 200px; + padding: 16px; + display: flex; + flex-direction: column; + gap: 16px; +} + +.hearts { display: flex; gap: 8px; } +.hearts img { width: 32px; height: auto; } + +.sanity-bar img { + width: 100%; + height: auto; + border-radius: 8px; + box-shadow: inset 0 2px 4px rgba(100,60,20,0.1); +} + +.retire-btn-container { + position: fixed; + top: 17%; /* vertically center relative to screen */ + left: 93%; /* adjust distance from left to sit next to house */ + transform: translateY(-50%); + z-index: 5; /* same as lil guy, above background/pattern */ +} + +.round-badge { + position: fixed; + top: 20px; + left: 50%; + transform: translateX(-50%); /* soft brown */ + color: #302a1f; /* cream text */ + font-family: 'Upheavel', sans-serif; + font-size: 2rem; + font-weight: bold; + padding: 8px 20px; + border-radius: 12px; + z-index: 20; + + opacity: 0; + animation: roundFade 1.5s ease forwards; +} + +@keyframes roundFade { + 0% { opacity: 0; transform: translateX(-50%) translateY(-20px); } + 10% { opacity: 1; transform: translateX(-50%) translateY(0); } + 90% { opacity: 1; transform: translateX(-50%) translateY(0); } + 100% { opacity: 0; transform: translateX(-50%) translateY(-20px); } +} + + diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4fbeb0c..09a4a4f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -38,9 +38,12 @@ function App() { const [career, setCareer] = useState(''); const [index, setIndex] = useState(''); const [insurance, setInsurance] = useState(''); + const [showRound, setShowRound] = useState(false); + const audioRef = useRef(null); const currentTrackRef = useRef(''); + const getGif = () => state.sanity >= 50 ? happy : state.sanity >= 25 ? neutral : sad; @@ -72,24 +75,38 @@ function App() { }, [state.sanity]); const handleInvestSubmit = (isUpgrade = false) => { - const investments: InvestmentData = {}; + const investments: InvestmentData = {}; - if (personal) investments.personal = parseFloat(personal); - if (career) investments.career = parseFloat(career); - if (index) investments.index = parseFloat(index); - if (insurance) investments.insurance = parseFloat(insurance); - if (isUpgrade) investments.upgradeHouse = true; + if (personal) investments.personal = parseFloat(personal); + if (career) investments.career = parseFloat(career); + if (index) investments.index = parseFloat(index); + if (insurance) investments.insurance = parseFloat(insurance); + if (isUpgrade) investments.upgradeHouse = true; + + nextRound(investments); + + // show round badge + setShowRound(true); + setTimeout(() => setShowRound(false), 1500); // show for 1.5s + + // Reset inputs + setPersonal(''); + setCareer(''); + setIndex(''); + setInsurance(''); +}; - nextRound(investments); - setPersonal(''); - setCareer(''); - setIndex(''); - setInsurance(''); - }; return ( <> + {showRound && ( +
+ Round {state.level} +
+)} + + +
+ +
-

Round {state.level} Investments

@@ -150,21 +177,11 @@ function App() { > Upgrade House {state.houseLevel >= 2 ? '(MAX)' : ''} +
+ - - - - - + )} diff --git a/frontend/src/components/EventModal.css b/frontend/src/components/EventModal.css index f39345e..ce1f558 100644 --- a/frontend/src/components/EventModal.css +++ b/frontend/src/components/EventModal.css @@ -50,7 +50,7 @@ /* Heading */ .event-content h2 { font-family: 'Upheavel', sans-serif; - font-size: 1.5rem; + font-size: 1.9rem; color: #8b5e3c; /* soft brown heading */ margin: 0; text-shadow: 1px 1px 2px rgba(255,255,255,0.6); @@ -59,7 +59,7 @@ /* Paragraph text */ .event-content p { font-family: 'Upheavel', sans-serif; - font-size: 1.1rem; + font-size: 1.4rem; margin: 0; line-height: 1.4; } @@ -67,7 +67,7 @@ /* Button */ .event-content button { font-family: 'Upheavel', sans-serif; - font-size: 1rem; + font-size: 1.3rem; background-color: #d2b48c; /* light brown */ color: #fffaf0; /* cream text */ border: none; diff --git a/frontend/src/components/EventModal.tsx b/frontend/src/components/EventModal.tsx index 8c80752..b65206e 100644 --- a/frontend/src/components/EventModal.tsx +++ b/frontend/src/components/EventModal.tsx @@ -12,10 +12,7 @@ export default function EventModal({ event, onContinue }: EventModalProps) { return (
- {event.name} +

{event.name}

{event.description}

diff --git a/frontend/src/components/HUD/HUD.css b/frontend/src/components/HUD/HUD.css index 5f41f18..30938d9 100644 --- a/frontend/src/components/HUD/HUD.css +++ b/frontend/src/components/HUD/HUD.css @@ -1,49 +1,72 @@ -/* HUD wrapper */ .hud { position: fixed; top: 0; left: 0; - width: 100vw; height: 100vh; - pointer-events: none; z-index: 10; - } + font-family: 'Upheavel', monospace; +} -/* da fucking left side of stats*/ +/* ---------------- Left panel ---------------- */ .hud-left { position: absolute; top: 10px; left: 10px; - - width: 220px; + width: 260px; padding: 16px; - background: #c5b49d; - border-radius: 12px; - - color: white; - font-family: monospace; + background: #fff4e6; + border: 3px solid #d2b48c; + border-radius: 16px; + color: #5b4636; font-size: 1.2rem; + box-shadow: 0 4px 12px rgba(100,60,20,0.2); +} + +.money-age { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +/* Fixed width for money so it doesn’t resize with more digits */ +.money { + font-size: 1.8rem; + font-weight: bold; + color: #8b5e3c; + white-space: nowrap; /* prevent wrapping */ + width: 140px; /* fixed width */ + text-overflow: ellipsis; /* gracefully clip if too long */ + overflow: hidden; } -.hud-left h3 { - margin-bottom: 10px; +/* Age badge stays consistent */ +.age { + font-size: 1.2rem; + background: #d2b48c; + color: #fffaf0; + padding: 4px 8px; + border-radius: 8px; + flex-shrink: 0; /* prevent shrinking */ } -.hud-left ul { + +/* Stats list */ +.stats-list { list-style: none; padding: 0; margin: 0; } -.hud-left li { +.stats-list li { margin-bottom: 6px; } -/* hp and sanity thing */ +/* ---------------- Right panel ---------------- */ .hud-right { position: absolute; top: 10px; @@ -51,29 +74,50 @@ width: 200px; padding: 16px; - - background: #c5b49d; - border-radius: 12px; - + background: #fff4e6; + border: 3px solid #d2b48c; + border-radius: 16px; display: flex; flex-direction: column; gap: 16px; + box-shadow: 0 4px 12px rgba(100,60,20,0.2); } -/* hp hearts */ +/* Hearts */ .hearts { display: flex; gap: 8px; } -/*hp heart size*/ .hearts img { width: 32px; height: auto; } -/* sanity bar */ -.sanity-bar img { +/* Sanity bar */ +.sanity-bar-wrapper { + position: relative; + width: 150px; + height: 24px; + border-radius: 8px; + overflow: hidden; +} + +.sanity-level { + position: absolute; + top: 0; + left: 0; + height: 100%; + background: linear-gradient(90deg, #eea546, #6b3af1); + transition: width 0.3s ease-in-out; + z-index: 0; +} + +.sanity-bar-img { + position: relative; width: 100%; - height: auto; + height: 100%; + z-index: 1; + display: block; + pointer-events: none; } diff --git a/frontend/src/components/HUD/HUD.tsx b/frontend/src/components/HUD/HUD.tsx index b0008ca..6c8a8f1 100644 --- a/frontend/src/components/HUD/HUD.tsx +++ b/frontend/src/components/HUD/HUD.tsx @@ -2,36 +2,43 @@ import './HUD.css'; import Heart from "../../assets/HEART.png"; import SanityBar from "../../assets/level.png"; -function HUD({ state }: { state: any }) { // <-- quick fix, no type errors +function HUD({ state }: { state: any }) { return (
- {/* left side */} + {/* Top-left panel: Money & age */}
-

Stats

-
    -
  • Age: {state.age}
  • -
  • Income: ${state.income}
  • -
  • Rent: ${state.rent}
  • +
    + {/* Money display: always integer, formatted with commas */} +
    ${Math.floor(state.total).toLocaleString()}
    + + {/* Age display: always integer */} +
    Age: {Math.floor(state.age)}
    +
    + +
      +
    • Income: ${Math.floor(state.income)}
    • +
    • Rent: ${Math.floor(state.rent)}
    • Food: ${state.food}
    • Insurance: ${state.insurance}
    • House Level: {state.houseLevel}
- {/* right side */} + {/* Top-right panel: HP & Sanity */}
{[...Array(state.lives)].map((_, i) => ( heart ))}
- -
- sanity bar + +
+ sanity bar
+
) } diff --git a/frontend/src/engine/buckets.ts b/frontend/src/engine/buckets.ts index a21845f..2435f2f 100644 --- a/frontend/src/engine/buckets.ts +++ b/frontend/src/engine/buckets.ts @@ -14,7 +14,6 @@ export function investPersonal(state: RoundData, amount: number): RoundData { return next } - export function investInsurance(state: RoundData, amount: number): RoundData { const next = structuredClone(state)