From 4e8209d25d5038de5563bac7c6a7f5b3c3f5e798 Mon Sep 17 00:00:00 2001 From: billy Date: Sun, 30 Mar 2025 13:03:37 -0400 Subject: [PATCH] Refactor App, ResourceDisplay, and gameStore components to streamline building information management. Removed hardcoded building data from App, centralized building info in gameStore, and adjusted ResourceDisplay calculations for click power. Enhanced overall code organization and maintainability. --- src/App.tsx | 78 +----- src/components/ResourceDisplay.tsx | 10 +- src/store/gameStore.ts | 375 ++++++++++++----------------- 3 files changed, 152 insertions(+), 311 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 6d0a114..95de417 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,5 @@ import { ResourceDisplay } from './components/ResourceDisplay' import { BuildingButton } from './components/BuildingButton' -import { MultiplierShop } from './components/MultiplierShop' import { NextBuildingPreview } from './components/NextBuildingPreview' import { ResetButton } from './components/ResetButton' import { useGameStore } from './store/gameStore' @@ -35,79 +34,6 @@ type BuildingId = 'mouseFarms' | 'keyboardFactories' | 'monitorDisplays' | 'offi type BuildingLevelKey = `${BuildingId}Level` -const BUILDING_INFO = { - mouseFarms: { - title: 'Mouse Farm', - description: 'A basic facility that produces computer mice. Each mouse farm generates points automatically.', - production: { points: 0.1 } - }, - keyboardFactories: { - title: 'Keyboard Factory', - description: 'Manufactures mechanical keyboards and generates tech parts. Essential for advanced upgrades.', - production: { techParts: 0.05 } - }, - monitorDisplays: { - title: 'Monitor Display', - description: 'High-resolution displays that generate both points and tech parts. A balanced production facility.', - production: { points: 0.2, techParts: 0.1 } - }, - serverRooms: { - title: 'Server Room', - description: 'A powerful facility that generates significant amounts of both resources. Requires proper cooling.', - production: { points: 1, techParts: 0.5 } - }, - dataCenters: { - title: 'Data Center', - description: 'The ultimate production facility. Generates massive amounts of resources but requires significant investment.', - production: { points: 5, techParts: 2 } - }, - dataCities: { - title: 'Data City', - description: 'A massive network of data centers spanning an entire city. Requires level 5 to unlock.', - production: { points: 25, techParts: 10 } - }, - dataCountries: { - title: 'Data Country', - description: 'A country-wide network of data cities. Requires level 10 to unlock.', - production: { points: 100, techParts: 40 } - }, - dataContinents: { - title: 'Data Continent', - description: 'A continent-spanning network of data countries. Requires level 20 to unlock.', - production: { points: 500, techParts: 200 } - }, - dataWorlds: { - title: 'Data World', - description: 'A world-wide network of data continents. Requires level 30 to unlock.', - production: { points: 2500, techParts: 1000 } - }, - dataMoons: { - title: 'Data Moon', - description: 'A moon-sized data processing facility. Requires level 40 to unlock.', - production: { points: 10000, techParts: 4000 } - }, - dataSolarSystems: { - title: 'Data Solar System', - description: 'A solar system-wide network of data moons. Requires level 50 to unlock.', - production: { points: 50000, techParts: 20000 } - }, - dataGalaxies: { - title: 'Data Galaxy', - description: 'A galaxy-spanning network of data solar systems. Requires level 60 to unlock.', - production: { points: 250000, techParts: 100000 } - }, - dataUniverses: { - title: 'Data Universe', - description: 'A universe-wide network of data galaxies. Requires level 70 to unlock.', - production: { points: 1000000, techParts: 400000 } - }, - dataGods: { - title: 'Data God', - description: 'The ultimate data processing entity. Requires level 80 to unlock.', - production: { points: 5000000, techParts: 2000000 } - } -} - function App() { const { points, @@ -184,7 +110,7 @@ function App() { onClick={() => useGameStore.getState().buyBuilding(building.id as BuildingId)} description={building.description} production={building.production} - buildingType={building.id} + buildingType={building.id!} levelRequirement={building.levelRequirement} /> ))} @@ -226,8 +152,6 @@ function App() { - - diff --git a/src/components/ResourceDisplay.tsx b/src/components/ResourceDisplay.tsx index c63be5a..dcbfdea 100644 --- a/src/components/ResourceDisplay.tsx +++ b/src/components/ResourceDisplay.tsx @@ -4,10 +4,7 @@ import logoImg from '../assets/logo.png' import { ResetButton } from './ResetButton' export function ResourceDisplay() { - const { points, pointsPerSecond, clickPower, getTotalMultiplier, activeMultipliers, playerLevel } = useGameStore() - - const totalMultiplier = getTotalMultiplier() - const actualClickPower = clickPower * totalMultiplier + const { points, pointsPerSecond, clickPower, playerLevel } = useGameStore() // Calculate progress to next level const currentLevelPPS = Math.pow(10, playerLevel - 1) @@ -91,10 +88,7 @@ export function ResourceDisplay() { {/* Click Power */} Click Power - {actualClickPower} - {activeMultipliers.length > 0 && ( - {totalMultiplier}x Active - )} + {clickPower} diff --git a/src/store/gameStore.ts b/src/store/gameStore.ts index 93b1a0c..bd02430 100644 --- a/src/store/gameStore.ts +++ b/src/store/gameStore.ts @@ -1,8 +1,9 @@ import { create } from 'zustand' import { persist } from 'zustand/middleware' -interface BuildingInfo { - id: string +// Building information interface +export interface BuildingInfo { + id?: string cost: number levelRequirement: number title: string @@ -58,12 +59,6 @@ interface GameState { // Production rates pointsPerSecond: number - // Special purchases - activeMultipliers: Array<{ - multiplier: number - endTime: number - }> - // Player level playerLevel: number @@ -73,14 +68,112 @@ interface GameState { buyUpgrade: (upgradeType: UpgradeType) => void resetGame: () => void tick: () => void - buyMultiplier: (duration: number, multiplier: number) => void upgradeBuilding: (buildingType: BuildingType) => void // New getter for available buildings getAvailableBuildings: () => BuildingInfo[] - - // Add getter for total multiplier - getTotalMultiplier: () => number +} + +// Building information with costs and requirements +export const BUILDING_INFO: Record> = { + mouseFarms: { + title: 'Mouse Farm', + description: 'A basic facility that produces computer mice. Each mouse farm generates points automatically.', + production: { points: 0.1 }, + cost: 10, + levelRequirement: 1 + }, + keyboardFactories: { + title: 'Keyboard Factory', + description: 'Manufactures mechanical keyboards and generates tech parts. Essential for advanced upgrades.', + production: { points: 0.2 }, + cost: 50, + levelRequirement: 1 + }, + monitorDisplays: { + title: 'Monitor Display', + description: 'High-resolution displays that generate both points and tech parts. A balanced production facility.', + production: { points: 0.2 }, + cost: 100, + levelRequirement: 1 + }, + serverRooms: { + title: 'Server Room', + description: 'A powerful facility that generates significant amounts of both resources. Requires proper cooling.', + production: { points: 5 }, + cost: 1000, + levelRequirement: 1 + }, + dataCenters: { + title: 'Data Center', + description: 'The ultimate production facility. Generates massive amounts of resources but requires significant investment.', + production: { points: 25 }, + cost: 5000, + levelRequirement: 5 + }, + dataCities: { + title: 'Data City', + description: 'A massive network of data centers spanning an entire city. Requires level 10 to unlock.', + production: { points: 100 }, + cost: 25000, + levelRequirement: 10 + }, + dataCountries: { + title: 'Data Country', + description: 'A country-wide network of data cities. Requires level 20 to unlock.', + production: { points: 500 }, + cost: 100000, + levelRequirement: 20 + }, + dataContinents: { + title: 'Data Continent', + description: 'A continent-spanning network of data countries. Requires level 30 to unlock.', + production: { points: 2500 }, + cost: 500000, + levelRequirement: 30 + }, + dataWorlds: { + title: 'Data World', + description: 'A world-wide network of data continents. Requires level 40 to unlock.', + production: { points: 10000 }, + cost: 2000000, + levelRequirement: 40 + }, + dataMoons: { + title: 'Data Moon', + description: 'A moon-sized data processing facility. Requires level 50 to unlock.', + production: { points: 50000 }, + cost: 10000000, + levelRequirement: 50 + }, + dataSolarSystems: { + title: 'Data Solar System', + description: 'A solar system-wide network of data moons. Requires level 60 to unlock.', + production: { points: 250000 }, + cost: 50000000, + levelRequirement: 60 + }, + dataGalaxies: { + title: 'Data Galaxy', + description: 'A galaxy-spanning network of data solar systems. Requires level 70 to unlock.', + production: { points: 1000000 }, + cost: 200000000, + levelRequirement: 70 + }, + dataUniverses: { + title: 'Data Universe', + description: 'A universe-wide network of data galaxies. Requires level 80 to unlock.', + production: { points: 5000000 }, + cost: 1000000000, + levelRequirement: 80 + }, + dataGods: { + title: 'Data God', + description: 'The ultimate data processing entity. Requires level 90 to unlock.', + production: { points: 25000000 }, + cost: 5000000000, + levelRequirement: 90 + } } const initialState = { @@ -118,7 +211,6 @@ const initialState = { autoClickers: 0, clickPower: 1, pointsPerSecond: 0, - activeMultipliers: [], playerLevel: 1, } @@ -179,34 +271,12 @@ const BUILDING_LEVEL_REQUIREMENTS = { dataGods: 90, } -// Special multiplier purchases -const MULTIPLIER_PURCHASES = [ - { duration: 30, multiplier: 2, cost: 100, name: '30s 2x Click Power' }, - { duration: 60, multiplier: 2, cost: 150, name: '1m 2x Click Power' }, - { duration: 30, multiplier: 3, cost: 250, name: '30s 3x Click Power' }, - { duration: 60, multiplier: 3, cost: 350, name: '1m 3x Click Power' }, - { duration: 30, multiplier: 5, cost: 500, name: '30s 5x Click Power' }, - { duration: 60, multiplier: 5, cost: 750, name: '1m 5x Click Power' }, -] - // Calculate upgrade cost based on current level const calculateUpgradeCost = (buildingType: BuildingType, currentLevel: number): number => { const baseCost = BUILDING_COSTS[buildingType] return Math.floor(baseCost * Math.pow(1.5, currentLevel - 1)) } -// Building costs and level requirements -export interface BuildingInfo { - cost: number - levelRequirement: number - title: string - description: string - production: { - points: number - } - id?: string -} - type BuildingType = keyof typeof BUILDING_COSTS type UpgradeType = 'autoClickers' | 'clickPower' @@ -227,9 +297,8 @@ export const useGameStore = create()( ...initialState, click: () => { - const { clickPower, autoClickers, getTotalMultiplier } = get() - const totalMultiplier = getTotalMultiplier() - const pointsPerClick = clickPower * (1 + autoClickers * 0.1) * totalMultiplier + const { clickPower, autoClickers } = get() + const pointsPerClick = clickPower * (1 + autoClickers * 0.1) set((state) => ({ points: state.points + pointsPerClick, })) @@ -253,217 +322,71 @@ export const useGameStore = create()( } }, + buyUpgrade: (upgradeType: UpgradeType) => { + const state = get() + + // Handle upgrade purchase + if (upgradeType === 'clickPower' && state.points >= 20) { + set((state) => ({ + points: state.points - 20, + clickPower: state.clickPower + 1 + })) + } + }, + upgradeBuilding: (buildingType: BuildingType) => { const state = get() const currentLevel = state[`${buildingType}Level` as keyof GameState] as number - const upgradeCost = calculateUpgradeCost(buildingType, currentLevel) + const cost = calculateUpgradeCost(buildingType, currentLevel) - if (state.points >= upgradeCost) { + if (state.points >= cost && state[buildingType] > 0) { set((state) => { + const newLevel = (state[`${buildingType}Level` as keyof GameState] as number) + 1 const rates = PRODUCTION_RATES[buildingType] const count = state[buildingType] - const newLevel = currentLevel + 1 + + // Calculate the new points per second + const oldProduction = rates.points * (newLevel - 1) * count + const newProduction = rates.points * newLevel * count + const productionDifference = newProduction - oldProduction return { - points: state.points - upgradeCost, + points: state.points - cost, [`${buildingType}Level`]: newLevel, - pointsPerSecond: state.pointsPerSecond + rates.points * count, + pointsPerSecond: state.pointsPerSecond + productionDifference, } }) } }, - - buyUpgrade: (upgradeType: UpgradeType) => { - const state = get() - const upgradeCosts: Record = { - autoClickers: 50, - clickPower: 20, - } - - const cost = upgradeCosts[upgradeType] - if (state.points >= cost) { - set((state) => ({ - points: state.points - cost, - [upgradeType]: state[upgradeType] + 1, - })) - } - }, - - buyMultiplier: (duration: number, multiplier: number) => { - const state = get() - const purchase = MULTIPLIER_PURCHASES.find( - p => p.duration === duration && p.multiplier === multiplier - ) - - if (purchase && state.points >= purchase.cost) { - const now = Date.now() - set((state) => ({ - points: state.points - purchase.cost, - activeMultipliers: [ - ...state.activeMultipliers, - { - multiplier, - endTime: now + duration * 1000 - } - ] - })) - } - }, - - tick: () => { - const state = get() - const now = Date.now() - - // Check for expired multipliers - const activeMultipliers = state.activeMultipliers.filter(m => m.endTime > now) - if (activeMultipliers.length !== state.activeMultipliers.length) { - set({ activeMultipliers }) - } - - // Update player level based on points per second - const newLevel = Math.floor(Math.log10(state.pointsPerSecond + 1)) + 1 - if (newLevel !== state.playerLevel) { - set({ playerLevel: newLevel }) - } - - // Calculate resources gained in this tick (1/10th of a second) - const pointsGained = state.pointsPerSecond / 10 - - set({ - points: state.points + pointsGained, - }) - }, - + resetGame: () => { set(initialState) }, - // Add new getter for available buildings - getAvailableBuildings: () => { + tick: () => { const state = get() - return getAvailableBuildings(state.playerLevel) + + // Add production from buildings + if (state.pointsPerSecond > 0) { + set((state) => ({ + points: state.points + state.pointsPerSecond / 10, // 10 ticks per second + })) + } + + // Update player level based on points per second + const playerLevel = Math.max(1, Math.floor(Math.log10(state.pointsPerSecond) + 1)) + if (playerLevel !== state.playerLevel) { + set({ playerLevel }) + } }, - // Add getter for total multiplier - getTotalMultiplier: () => { - const state = get() - const now = Date.now() - return state.activeMultipliers - .filter(m => m.endTime > now) - .reduce((total, m) => total + (m.multiplier - 1), 1) // Subtract 1 from each multiplier and add 1 at the end + getAvailableBuildings: () => { + const { playerLevel } = get() + return getAvailableBuildings(playerLevel) }, }), { - name: 'game-storage', + name: 'clicker-game', } ) -) - -// Building costs and level requirements -export const BUILDING_INFO: Record> = { - mouseFarms: { - cost: 10, - levelRequirement: 1, - title: 'Mouse Farm', - description: 'A basic facility that produces computer mice. Each mouse farm generates points automatically.', - production: { points: 0.1 } - }, - keyboardFactories: { - cost: 50, - levelRequirement: 1, - title: 'Keyboard Factory', - description: 'Manufactures mechanical keyboards. Generates points automatically.', - production: { points: 0.2 } - }, - monitorDisplays: { - cost: 100, - levelRequirement: 1, - title: 'Monitor Display', - description: 'High-resolution displays that generate points. A balanced production facility.', - production: { points: 0.2 } - }, - officeSpace: { - cost: 500, - levelRequirement: 1, - title: 'Office Space', - description: 'A productive workspace filled with computers. Generates a significant amount of points.', - production: { points: 1 } - }, - serverRooms: { - cost: 1000, - levelRequirement: 1, - title: 'Server Room', - description: 'A powerful facility that generates substantial amounts of points. Requires proper cooling.', - production: { points: 5 } - }, - dataCenters: { - cost: 5000, - levelRequirement: 5, - title: 'Data Center', - description: 'The ultimate production facility. Generates massive amounts of points but requires significant investment.', - production: { points: 25 } - }, - dataCities: { - cost: 25000, - levelRequirement: 10, - title: 'Data City', - description: 'A massive network of data centers spanning an entire city. Requires level 10 to unlock.', - production: { points: 100 } - }, - dataCountries: { - cost: 100000, - levelRequirement: 20, - title: 'Data Country', - description: 'A country-wide network of data cities. Requires level 20 to unlock.', - production: { points: 500 } - }, - dataContinents: { - cost: 500000, - levelRequirement: 30, - title: 'Data Continent', - description: 'A continent-spanning network of data countries. Requires level 30 to unlock.', - production: { points: 2500 } - }, - dataWorlds: { - cost: 2000000, - levelRequirement: 40, - title: 'Data World', - description: 'A world-wide network of data continents. Requires level 40 to unlock.', - production: { points: 10000 } - }, - dataMoons: { - cost: 10000000, - levelRequirement: 50, - title: 'Data Moon', - description: 'A moon-sized data processing facility. Requires level 50 to unlock.', - production: { points: 50000 } - }, - dataSolarSystems: { - cost: 50000000, - levelRequirement: 60, - title: 'Data Solar System', - description: 'A solar system-wide network of data moons. Requires level 60 to unlock.', - production: { points: 250000 } - }, - dataGalaxies: { - cost: 200000000, - levelRequirement: 70, - title: 'Data Galaxy', - description: 'A galaxy-spanning network of data solar systems. Requires level 70 to unlock.', - production: { points: 1000000 } - }, - dataUniverses: { - cost: 1000000000, - levelRequirement: 80, - title: 'Data Universe', - description: 'A universe-wide network of data galaxies. Requires level 80 to unlock.', - production: { points: 5000000 } - }, - dataGods: { - cost: 5000000000, - levelRequirement: 90, - title: 'Data God', - description: 'The ultimate data processing entity. Requires level 90 to unlock.', - production: { points: 25000000 } - } -} \ No newline at end of file +) \ No newline at end of file