This commit is contained in:
billy 2025-03-30 03:47:35 -04:00
parent 4130297a22
commit 301c955058
3 changed files with 127 additions and 54 deletions

View File

@ -2,6 +2,7 @@ import { ResourceDisplay } from './components/ResourceDisplay'
import { BuildingButton } from './components/BuildingButton' import { BuildingButton } from './components/BuildingButton'
import { MultiplierShop } from './components/MultiplierShop' import { MultiplierShop } from './components/MultiplierShop'
import { NextBuildingPreview } from './components/NextBuildingPreview' import { NextBuildingPreview } from './components/NextBuildingPreview'
import { ResetButton } from './components/ResetButton'
import { useGameStore } from './store/gameStore' import { useGameStore } from './store/gameStore'
import { import {
ChakraProvider, ChakraProvider,
@ -11,7 +12,8 @@ import {
Text, Text,
VStack, VStack,
SimpleGrid, SimpleGrid,
Button Button,
Flex
} from '@chakra-ui/react' } from '@chakra-ui/react'
import theme from './theme' import theme from './theme'
import { useEffect } from 'react' import { useEffect } from 'react'
@ -138,8 +140,11 @@ function App() {
<Box pt="180px"> <Box pt="180px">
<Container maxW="container.xl"> <Container maxW="container.xl">
<VStack spacing={8}> <VStack spacing={8}>
<Box textAlign="center"> <Box textAlign="center" w="full">
<Heading as="h1" size="2xl" mb={4}>Clicker Clicker 2</Heading> <Flex justify="space-between" align="center" mb={4}>
<Heading as="h1" size="2xl">Clicker Clicker 2</Heading>
<ResetButton />
</Flex>
<Text fontSize="xl" color="yellow.400" mb={4}>Level {playerLevel}</Text> <Text fontSize="xl" color="yellow.400" mb={4}>Level {playerLevel}</Text>
</Box> </Box>

View File

@ -4,7 +4,8 @@ import {
VStack, VStack,
Text, Text,
Badge, Badge,
Tooltip Tooltip,
HStack
} from '@chakra-ui/react' } from '@chakra-ui/react'
import { useGameStore } from '../store/gameStore' import { useGameStore } from '../store/gameStore'
@ -15,10 +16,7 @@ interface BuildingButtonProps {
level: number level: number
onClick: () => void onClick: () => void
description: string description: string
production: { production: { points?: number }
points?: number
techParts?: number
}
buildingType: string buildingType: string
levelRequirement: number levelRequirement: number
} }
@ -34,58 +32,65 @@ export function BuildingButton({
buildingType, buildingType,
levelRequirement levelRequirement
}: BuildingButtonProps) { }: BuildingButtonProps) {
const { points, playerLevel } = useGameStore() const { points, playerLevel, upgradeBuilding } = useGameStore()
const canAfford = points >= cost const canAfford = points >= cost
const meetsLevelRequirement = playerLevel >= levelRequirement const meetsLevelRequirement = playerLevel >= levelRequirement
const isDisabled = !canAfford || !meetsLevelRequirement const isDisabled = !canAfford || !meetsLevelRequirement
const buttonContent = ( // Calculate upgrade cost
const calculateUpgradeCost = (currentLevel: number): number => {
return Math.floor(cost * Math.pow(1.5, currentLevel - 1))
}
const upgradeCost = calculateUpgradeCost(level)
const canUpgrade = points >= upgradeCost && owned > 0
const pointsPerSecond = production.points || 0
return (
<Box
bg="gray.700"
p={4}
borderRadius="lg"
border="1px"
borderColor="gray.600"
>
<VStack align="stretch" spacing={2}> <VStack align="stretch" spacing={2}>
<Box display="flex" justifyContent="space-between" alignItems="center"> <Box display="flex" justifyContent="space-between" alignItems="center">
<Text fontWeight="bold">{title}</Text> <Text fontWeight="bold">{title}</Text>
<Badge colorScheme={level > 1 ? 'green' : 'gray'}>Level {level}</Badge> <HStack>
<Text>Owned: {owned}</Text>
<Text>Level: {level}</Text>
</HStack>
</Box> </Box>
<Text fontSize="sm" color="gray.400">{description}</Text> <Text fontSize="sm" color="gray.400">{description}</Text>
<Box display="flex" justifyContent="space-between" alignItems="center">
<Text>Owned: {owned}</Text>
<Text>Cost: {cost} points</Text>
</Box>
<Box> <Box>
<Text fontSize="sm">Production:</Text> <Text fontSize="sm">Production:</Text>
{production.points && ( <Text fontSize="sm">Points: {(pointsPerSecond * level).toFixed(1)}/s per building</Text>
<Text fontSize="sm">Points: {production.points}/s</Text> <Text fontSize="sm">Total: {(pointsPerSecond * level * owned).toFixed(1)}/s</Text>
)}
{production.techParts && (
<Text fontSize="sm">Tech Parts: {production.techParts}/s</Text>
)}
</Box> </Box>
</VStack> <HStack spacing={2}>
)
return (
<Tooltip
label={
!meetsLevelRequirement
? `Requires level ${levelRequirement}`
: !canAfford
? 'Not enough points'
: ''
}
isDisabled={!isDisabled}
>
<Button <Button
onClick={onClick} onClick={onClick}
disabled={isDisabled} isDisabled={points < cost || playerLevel < levelRequirement}
bg="gray.700" colorScheme="blue"
_hover={{ bg: 'gray.600' }} size="sm"
_disabled={{ bg: 'gray.800' }} flexGrow={1}
p={4}
height="auto"
whiteSpace="normal"
textAlign="left"
> >
{buttonContent} Buy ({cost} points)
</Button>
<Tooltip label={owned === 0 ? "You need to own this building first" : ""}>
<Button
onClick={() => upgradeBuilding(buildingType as any)}
isDisabled={!canUpgrade}
colorScheme="green"
size="sm"
flexGrow={1}
>
Upgrade ({upgradeCost} points)
</Button> </Button>
</Tooltip> </Tooltip>
</HStack>
</VStack>
</Box>
) )
} }

View File

@ -0,0 +1,63 @@
import {
Button,
AlertDialog,
AlertDialogBody,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogContent,
AlertDialogOverlay,
useDisclosure
} from '@chakra-ui/react'
import React, { useRef } from 'react'
import { useGameStore } from '../store/gameStore'
export function ResetButton() {
const { resetGame } = useGameStore()
const { isOpen, onOpen, onClose } = useDisclosure()
const cancelRef = useRef<HTMLButtonElement>(null)
const handleReset = () => {
resetGame()
onClose()
}
return (
<>
<Button
onClick={onOpen}
colorScheme="red"
size="sm"
variant="outline"
>
Reset Game
</Button>
<AlertDialog
isOpen={isOpen}
leastDestructiveRef={cancelRef as React.RefObject<any>}
onClose={onClose}
>
<AlertDialogOverlay>
<AlertDialogContent bg="gray.800" color="white">
<AlertDialogHeader fontSize="lg" fontWeight="bold">
Reset Game
</AlertDialogHeader>
<AlertDialogBody>
Are you sure? You will lose all progress and start from the beginning.
</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose}>
Cancel
</Button>
<Button colorScheme="red" onClick={handleReset} ml={3}>
Reset
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
</>
)
}