colors and junk
This commit is contained in:
parent
a25fa4a94c
commit
da79c678ec
81
analyze_key_images.py
Normal file
81
analyze_key_images.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
from collections import Counter
|
||||||
|
import colorsys
|
||||||
|
|
||||||
|
def rgb_to_hex(rgb):
|
||||||
|
return '#{:02x}{:02x}{:02x}'.format(rgb[0], rgb[1], rgb[2])
|
||||||
|
|
||||||
|
def get_dominant_colors(image_path, num_colors=8):
|
||||||
|
try:
|
||||||
|
# Open image and convert to RGB
|
||||||
|
img = Image.open(image_path).convert('RGB')
|
||||||
|
|
||||||
|
# Resize image to make processing faster
|
||||||
|
img = img.resize((150, 150))
|
||||||
|
|
||||||
|
# Get colors
|
||||||
|
pixels = np.array(img)
|
||||||
|
pixels = pixels.reshape(-1, 3)
|
||||||
|
|
||||||
|
# Count most common colors
|
||||||
|
count = Counter(map(tuple, pixels))
|
||||||
|
most_common = count.most_common(num_colors)
|
||||||
|
|
||||||
|
# Convert to hex
|
||||||
|
return [rgb_to_hex(color) for color, count in most_common]
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing {image_path}: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
# List of key images to analyze
|
||||||
|
key_images = [
|
||||||
|
"/home/billy/code/viber/src/assets/logo.png",
|
||||||
|
"/home/billy/code/viber/src/assets/mouse.png",
|
||||||
|
"/home/billy/code/viber/src/assets/keyboard.png",
|
||||||
|
"/home/billy/code/viber/src/assets/monitor.png",
|
||||||
|
"/home/billy/code/viber/src/assets/data center.png",
|
||||||
|
"/home/billy/code/viber/src/assets/galaxy.png"
|
||||||
|
]
|
||||||
|
|
||||||
|
print("Key Image Analysis:\n")
|
||||||
|
|
||||||
|
for image_path in key_images:
|
||||||
|
image_name = image_path.split("/")[-1]
|
||||||
|
colors = get_dominant_colors(image_path)
|
||||||
|
|
||||||
|
print(f"{image_name}:")
|
||||||
|
for color in colors:
|
||||||
|
# Convert to RGB for displaying color names
|
||||||
|
h = color.lstrip('#')
|
||||||
|
r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
||||||
|
h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
|
||||||
|
|
||||||
|
# Determine color category
|
||||||
|
category = "unknown"
|
||||||
|
if s < 0.15:
|
||||||
|
if v < 0.15:
|
||||||
|
category = "black"
|
||||||
|
elif v > 0.85:
|
||||||
|
category = "white"
|
||||||
|
else:
|
||||||
|
category = "gray"
|
||||||
|
else:
|
||||||
|
if h < 0.05 or h > 0.95:
|
||||||
|
category = "red"
|
||||||
|
elif 0.05 <= h < 0.15:
|
||||||
|
category = "orange"
|
||||||
|
elif 0.15 <= h < 0.25:
|
||||||
|
category = "yellow"
|
||||||
|
elif 0.25 <= h < 0.5:
|
||||||
|
category = "green"
|
||||||
|
elif 0.5 <= h < 0.65:
|
||||||
|
category = "cyan"
|
||||||
|
elif 0.65 <= h < 0.75:
|
||||||
|
category = "blue"
|
||||||
|
elif 0.75 <= h < 0.95:
|
||||||
|
category = "purple"
|
||||||
|
|
||||||
|
print(f" {color} - {category} (HSV: {h*360:.1f}, {s*100:.1f}%, {v*100:.1f}%)")
|
||||||
|
print("")
|
||||||
155
color_analysis.py
Normal file
155
color_analysis.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
from collections import Counter
|
||||||
|
import colorsys
|
||||||
|
|
||||||
|
def rgb_to_hex(rgb):
|
||||||
|
return '#{:02x}{:02x}{:02x}'.format(rgb[0], rgb[1], rgb[2])
|
||||||
|
|
||||||
|
def get_dominant_colors(image_path, num_colors=5):
|
||||||
|
# Open image and convert to RGB
|
||||||
|
img = Image.open(image_path).convert('RGB')
|
||||||
|
|
||||||
|
# Resize image to make processing faster
|
||||||
|
img = img.resize((100, 100))
|
||||||
|
|
||||||
|
# Get colors
|
||||||
|
pixels = np.array(img)
|
||||||
|
pixels = pixels.reshape(-1, 3)
|
||||||
|
|
||||||
|
# Count most common colors
|
||||||
|
count = Counter(map(tuple, pixels))
|
||||||
|
most_common = count.most_common(num_colors)
|
||||||
|
|
||||||
|
# Convert to hex
|
||||||
|
return [rgb_to_hex(color) for color, count in most_common]
|
||||||
|
|
||||||
|
def get_color_stats(hex_color):
|
||||||
|
# Convert hex to RGB
|
||||||
|
h = hex_color.lstrip('#')
|
||||||
|
r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
||||||
|
|
||||||
|
# Convert RGB to HSV
|
||||||
|
h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
|
||||||
|
|
||||||
|
# Determine if color is dark or light
|
||||||
|
is_dark = v < 0.5
|
||||||
|
|
||||||
|
# Determine if color is vibrant
|
||||||
|
is_vibrant = s > 0.5 and v > 0.5
|
||||||
|
|
||||||
|
# Determine basic color category
|
||||||
|
if s < 0.15:
|
||||||
|
if v < 0.15:
|
||||||
|
category = "black"
|
||||||
|
elif v > 0.85:
|
||||||
|
category = "white"
|
||||||
|
else:
|
||||||
|
category = "gray"
|
||||||
|
else:
|
||||||
|
if h < 0.05 or h > 0.95:
|
||||||
|
category = "red"
|
||||||
|
elif 0.05 <= h < 0.15:
|
||||||
|
category = "orange"
|
||||||
|
elif 0.15 <= h < 0.25:
|
||||||
|
category = "yellow"
|
||||||
|
elif 0.25 <= h < 0.5:
|
||||||
|
category = "green"
|
||||||
|
elif 0.5 <= h < 0.65:
|
||||||
|
category = "cyan"
|
||||||
|
elif 0.65 <= h < 0.75:
|
||||||
|
category = "blue"
|
||||||
|
elif 0.75 <= h < 0.95:
|
||||||
|
category = "purple"
|
||||||
|
|
||||||
|
return {
|
||||||
|
"hex": hex_color,
|
||||||
|
"rgb": (r, g, b),
|
||||||
|
"hsv": (h*360, s*100, v*100),
|
||||||
|
"is_dark": is_dark,
|
||||||
|
"is_vibrant": is_vibrant,
|
||||||
|
"category": category
|
||||||
|
}
|
||||||
|
|
||||||
|
def analyze_assets(directory):
|
||||||
|
assets = []
|
||||||
|
|
||||||
|
# Find all PNG files
|
||||||
|
for file in os.listdir(directory):
|
||||||
|
if file.endswith('.png'):
|
||||||
|
assets.append(os.path.join(directory, file))
|
||||||
|
|
||||||
|
# Get color data
|
||||||
|
color_data = {}
|
||||||
|
all_colors = []
|
||||||
|
|
||||||
|
for asset in assets:
|
||||||
|
name = os.path.basename(asset)
|
||||||
|
dominant_colors = get_dominant_colors(asset)
|
||||||
|
color_data[name] = dominant_colors
|
||||||
|
all_colors.extend(dominant_colors)
|
||||||
|
|
||||||
|
# Count most common colors across all assets
|
||||||
|
color_counter = Counter(all_colors)
|
||||||
|
most_common_colors = color_counter.most_common(10)
|
||||||
|
|
||||||
|
# Get stats for most common colors
|
||||||
|
color_stats = [get_color_stats(color) for color, _ in most_common_colors]
|
||||||
|
|
||||||
|
# Find primary and accent colors
|
||||||
|
primary_colors = []
|
||||||
|
accent_colors = []
|
||||||
|
|
||||||
|
for stat in color_stats:
|
||||||
|
if stat["category"] not in ["black", "white", "gray"]:
|
||||||
|
if stat["is_vibrant"]:
|
||||||
|
accent_colors.append(stat)
|
||||||
|
else:
|
||||||
|
primary_colors.append(stat)
|
||||||
|
|
||||||
|
# Find background colors (darker colors)
|
||||||
|
background_colors = [stat for stat in color_stats if stat["is_dark"]]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"individual_assets": color_data,
|
||||||
|
"most_common_colors": [color for color, _ in most_common_colors],
|
||||||
|
"color_stats": color_stats,
|
||||||
|
"primary_colors": primary_colors[:3],
|
||||||
|
"accent_colors": accent_colors[:3],
|
||||||
|
"background_colors": background_colors[:3]
|
||||||
|
}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
assets_dir = "/home/billy/code/viber/src/assets"
|
||||||
|
results = analyze_assets(assets_dir)
|
||||||
|
|
||||||
|
print("Color Analysis Results:\n")
|
||||||
|
|
||||||
|
print("Most Common Colors:")
|
||||||
|
for color in results["most_common_colors"]:
|
||||||
|
print(f" {color}")
|
||||||
|
|
||||||
|
print("\nPrimary Colors:")
|
||||||
|
for color in results["primary_colors"]:
|
||||||
|
print(f" {color['hex']} - {color['category']}")
|
||||||
|
|
||||||
|
print("\nAccent Colors:")
|
||||||
|
for color in results["accent_colors"]:
|
||||||
|
print(f" {color['hex']} - {color['category']}")
|
||||||
|
|
||||||
|
print("\nBackground Colors:")
|
||||||
|
for color in results["background_colors"]:
|
||||||
|
print(f" {color['hex']} - {color['category']}")
|
||||||
|
|
||||||
|
print("\nDetailed Color Stats:")
|
||||||
|
for i, stat in enumerate(results["color_stats"][:5]):
|
||||||
|
print(f"Color {i+1}:")
|
||||||
|
print(f" Hex: {stat['hex']}")
|
||||||
|
print(f" RGB: {stat['rgb']}")
|
||||||
|
print(f" HSV: {stat['hsv']}")
|
||||||
|
print(f" Category: {stat['category']}")
|
||||||
|
print(f" Dark: {stat['is_dark']}")
|
||||||
|
print(f" Vibrant: {stat['is_vibrant']}")
|
||||||
|
print("")
|
||||||
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
18
src/App.tsx
18
src/App.tsx
@ -88,7 +88,7 @@ function App() {
|
|||||||
<ChakraProvider theme={theme}>
|
<ChakraProvider theme={theme}>
|
||||||
<Box
|
<Box
|
||||||
minH="100vh"
|
minH="100vh"
|
||||||
bg="gray.900"
|
bg="background.primary"
|
||||||
color="white"
|
color="white"
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
cursor={hasStarted ? "pointer" : "default"}
|
cursor={hasStarted ? "pointer" : "default"}
|
||||||
@ -130,14 +130,14 @@ function App() {
|
|||||||
size="2xl"
|
size="2xl"
|
||||||
>
|
>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent bg="gray.800" color="white" maxW="800px">
|
<ModalContent bg="background.secondary" color="white" maxW="800px">
|
||||||
<ModalHeader borderBottom="1px" borderColor="gray.700" pb={4}>
|
<ModalHeader borderBottom="1px" borderColor="brand.700" pb={4}>
|
||||||
Welcome to ClickerCorp™
|
Welcome to ClickerCorp™
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<ModalBody py={6}>
|
<ModalBody py={6}>
|
||||||
<VStack spacing={6} align="stretch">
|
<VStack spacing={6} align="stretch">
|
||||||
<Box>
|
<Box>
|
||||||
<Text fontSize="lg" fontWeight="bold" mb={2}>
|
<Text fontSize="lg" fontWeight="bold" mb={2} color="brand.300">
|
||||||
Employment Agreement
|
Employment Agreement
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="md" color="gray.300" lineHeight="1.6">
|
<Text fontSize="md" color="gray.300" lineHeight="1.6">
|
||||||
@ -149,7 +149,7 @@ function App() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fontSize="lg" fontWeight="bold" mb={2}>
|
<Text fontSize="lg" fontWeight="bold" mb={2} color="brand.300">
|
||||||
Controls & Operations
|
Controls & Operations
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="md" color="gray.300" lineHeight="1.6">
|
<Text fontSize="md" color="gray.300" lineHeight="1.6">
|
||||||
@ -158,13 +158,13 @@ function App() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fontSize="sm" color="gray.400" fontStyle="italic">
|
<Text fontSize="sm" color="brand.200" fontStyle="italic">
|
||||||
(Please note: This position is unpaid and offers exposure as compensation)
|
(Please note: This position is unpaid and offers exposure as compensation)
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
colorScheme="cyan"
|
colorScheme="brand"
|
||||||
isChecked={agreedToTerms}
|
isChecked={agreedToTerms}
|
||||||
onChange={(e) => setAgreedToTerms(e.target.checked)}
|
onChange={(e) => setAgreedToTerms(e.target.checked)}
|
||||||
>
|
>
|
||||||
@ -172,9 +172,9 @@ function App() {
|
|||||||
</Checkbox>
|
</Checkbox>
|
||||||
</VStack>
|
</VStack>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter borderTop="1px" borderColor="gray.700" pt={4}>
|
<ModalFooter borderTop="1px" borderColor="brand.700" pt={4}>
|
||||||
<Button
|
<Button
|
||||||
colorScheme="cyan"
|
colorScheme="brand"
|
||||||
isDisabled={!agreedToTerms}
|
isDisabled={!agreedToTerms}
|
||||||
onClick={handleStartGame}
|
onClick={handleStartGame}
|
||||||
w="full"
|
w="full"
|
||||||
|
|||||||
@ -104,11 +104,17 @@ export function BuildingButton({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
bg="gray.700"
|
bg="background.card"
|
||||||
p={4}
|
p={4}
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="gray.600"
|
borderColor="brand.700"
|
||||||
|
boxShadow="0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.24)"
|
||||||
|
transition="all 0.2s ease-in-out"
|
||||||
|
_hover={{
|
||||||
|
transform: "translateY(-2px)",
|
||||||
|
boxShadow: "0 6px 10px -1px rgba(0, 0, 0, 0.4), 0 4px 6px -1px rgba(0, 0, 0, 0.3)"
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<VStack align="stretch" spacing={2}>
|
<VStack align="stretch" spacing={2}>
|
||||||
{/* Image with overlapping title and stats */}
|
{/* Image with overlapping title and stats */}
|
||||||
@ -117,6 +123,8 @@ export function BuildingButton({
|
|||||||
<Box
|
<Box
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
|
borderWidth="2px"
|
||||||
|
borderColor="brand.800"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={buildingImages[buildingType as keyof typeof buildingImages]}
|
src={buildingImages[buildingType as keyof typeof buildingImages]}
|
||||||
@ -134,11 +142,12 @@ export function BuildingButton({
|
|||||||
top="0"
|
top="0"
|
||||||
left="0"
|
left="0"
|
||||||
p={2}
|
p={2}
|
||||||
bg="blackAlpha.700"
|
bg="background.cardOverlay"
|
||||||
borderTopLeftRadius="md"
|
borderTopLeftRadius="md"
|
||||||
borderBottomRightRadius="md"
|
borderBottomRightRadius="md"
|
||||||
|
boxShadow="0 1px 3px rgba(0,0,0,0.5)"
|
||||||
>
|
>
|
||||||
<Text fontWeight="bold" fontSize="md">{title}</Text>
|
<Text fontWeight="bold" fontSize="md" color="brand.200">{title}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Overlay for owned count */}
|
{/* Overlay for owned count */}
|
||||||
@ -147,11 +156,12 @@ export function BuildingButton({
|
|||||||
bottom="0"
|
bottom="0"
|
||||||
right="0"
|
right="0"
|
||||||
p={2}
|
p={2}
|
||||||
bg="blackAlpha.700"
|
bg="background.cardOverlay"
|
||||||
borderTopLeftRadius="md"
|
borderTopLeftRadius="md"
|
||||||
borderBottomRightRadius="md"
|
borderBottomRightRadius="md"
|
||||||
|
boxShadow="0 1px 3px rgba(0,0,0,0.5)"
|
||||||
>
|
>
|
||||||
<Text fontSize="sm">Owned: {formatNumber(owned)}</Text>
|
<Text fontSize="sm" color="brand.100">Owned: {formatNumber(owned)}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Level badge */}
|
{/* Level badge */}
|
||||||
@ -160,29 +170,32 @@ export function BuildingButton({
|
|||||||
top="0"
|
top="0"
|
||||||
right="0"
|
right="0"
|
||||||
p={2}
|
p={2}
|
||||||
bg="blue.700"
|
bg="brand.400"
|
||||||
borderTopRightRadius="md"
|
borderTopRightRadius="md"
|
||||||
borderBottomLeftRadius="md"
|
borderBottomLeftRadius="md"
|
||||||
|
boxShadow="0 1px 3px rgba(0,0,0,0.5)"
|
||||||
>
|
>
|
||||||
<Text fontSize="xs" fontWeight="bold">Level {level}</Text>
|
<Text fontSize="xs" fontWeight="bold" color="text.dark">Level {level}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Text fontSize="sm" color="gray.400">{description}</Text>
|
<Text fontSize="sm" color="text.secondary">{description}</Text>
|
||||||
<Box>
|
<Box p={2} bg="background.secondary" borderRadius="md">
|
||||||
<Flex justifyContent="space-between" alignItems="center" mb={1}>
|
<Flex justifyContent="space-between" alignItems="center" mb={1}>
|
||||||
<Text fontSize="sm" fontWeight="bold">Production:</Text>
|
<Text fontSize="sm" fontWeight="bold" color="brand.300">Production:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text fontSize="sm">Points: {formatNumber(pointsPerSecond * level)}/s per building</Text>
|
<Text fontSize="sm" color="text.primary">Points: {formatNumber(pointsPerSecond * level)}/s per building</Text>
|
||||||
<Text fontSize="sm">Total: {formatNumber(pointsPerSecond * level * owned)}/s</Text>
|
<Text fontSize="sm" color="text.primary">Total: {formatNumber(pointsPerSecond * level * owned)}/s</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<HStack spacing={2}>
|
<HStack spacing={2}>
|
||||||
<Button
|
<Button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
opacity={isDisabledStyle ? 0.4 : 1}
|
opacity={isDisabledStyle ? 0.4 : 1}
|
||||||
_hover={{ bg: 'blue.600', opacity: isDisabledStyle ? 0.4 : 1 }}
|
_hover={{ bg: 'brand.500', opacity: isDisabledStyle ? 0.4 : 1 }}
|
||||||
cursor={isDisabledStyle ? 'not-allowed' : 'pointer'}
|
cursor={isDisabledStyle ? 'not-allowed' : 'pointer'}
|
||||||
colorScheme="blue"
|
colorScheme="brand"
|
||||||
|
bg="brand.400"
|
||||||
|
color="text.dark"
|
||||||
size="sm"
|
size="sm"
|
||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
>
|
>
|
||||||
@ -192,11 +205,12 @@ export function BuildingButton({
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => upgradeBuilding(buildingType as keyof typeof buildingImages)}
|
onClick={() => upgradeBuilding(buildingType as keyof typeof buildingImages)}
|
||||||
opacity={!canUpgrade ? 0.4 : 1}
|
opacity={!canUpgrade ? 0.4 : 1}
|
||||||
_hover={{ bg: 'green.600', opacity: !canUpgrade ? 0.4 : 1 }}
|
_hover={{ bg: 'background.highlight', opacity: !canUpgrade ? 0.4 : 1 }}
|
||||||
cursor={!canUpgrade ? 'not-allowed' : 'pointer'}
|
cursor={!canUpgrade ? 'not-allowed' : 'pointer'}
|
||||||
colorScheme="green"
|
colorScheme="brand"
|
||||||
size="sm"
|
size="sm"
|
||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
|
variant="outline"
|
||||||
>
|
>
|
||||||
Upgrade ({formatNumber(upgradeCost)} points)
|
Upgrade ({formatNumber(upgradeCost)} points)
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -34,27 +34,28 @@ export function NextBuildingPreview() {
|
|||||||
return (
|
return (
|
||||||
<Tooltip label={`Requires level ${info.levelRequirement}`}>
|
<Tooltip label={`Requires level ${info.levelRequirement}`}>
|
||||||
<Box
|
<Box
|
||||||
bg="gray.800"
|
bg="background.card"
|
||||||
p={4}
|
p={4}
|
||||||
borderRadius="lg"
|
borderRadius="lg"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="gray.700"
|
borderColor="brand.800"
|
||||||
opacity={0.7}
|
opacity={0.7}
|
||||||
cursor="not-allowed"
|
cursor="not-allowed"
|
||||||
|
boxShadow="0 4px 6px -1px rgba(0, 0, 0, 0.2), 0 2px 4px -1px rgba(0, 0, 0, 0.14)"
|
||||||
>
|
>
|
||||||
<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">{info.title}</Text>
|
<Text fontWeight="bold" color="brand.200">{info.title}</Text>
|
||||||
<Badge colorScheme="red">Locked</Badge>
|
<Badge colorScheme="brand" bg="brand.400" color="text.dark">Locked</Badge>
|
||||||
</Box>
|
</Box>
|
||||||
<Text fontSize="sm" color="gray.400">{info.description}</Text>
|
<Text fontSize="sm" color="text.muted">{info.description}</Text>
|
||||||
<Box display="flex" justifyContent="space-between" alignItems="center">
|
<Box display="flex" justifyContent="space-between" alignItems="center">
|
||||||
<Text>Cost: {formatNumber(info.cost)} points</Text>
|
<Text color="text.secondary">Cost: {formatNumber(info.cost)} points</Text>
|
||||||
<Text>Level Required: {info.levelRequirement}</Text>
|
<Text color="brand.300">Level Required: {info.levelRequirement}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box p={2} bg="background.secondary" borderRadius="md">
|
||||||
<Text fontSize="sm">Production:</Text>
|
<Text fontSize="sm" color="brand.300">Production:</Text>
|
||||||
<Text fontSize="sm">Points: {formatNumber(info.production.points || 0)}/s</Text>
|
<Text fontSize="sm" color="text.secondary">Points: {formatNumber(info.production.points || 0)}/s</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</VStack>
|
</VStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -38,8 +38,8 @@ export function ResetButton() {
|
|||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
>
|
>
|
||||||
<AlertDialogOverlay>
|
<AlertDialogOverlay>
|
||||||
<AlertDialogContent bg="gray.800" color="white">
|
<AlertDialogContent bg="background.secondary" color="white">
|
||||||
<AlertDialogHeader fontSize="lg" fontWeight="bold">
|
<AlertDialogHeader fontSize="lg" fontWeight="bold" color="brand.300">
|
||||||
Reset Game
|
Reset Game
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export function ResetButton() {
|
|||||||
</AlertDialogBody>
|
</AlertDialogBody>
|
||||||
|
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<Button ref={cancelRef} onClick={onClose}>
|
<Button ref={cancelRef} onClick={onClose} colorScheme="brand" variant="outline">
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button colorScheme="red" onClick={handleReset} ml={3}>
|
<Button colorScheme="red" onClick={handleReset} ml={3}>
|
||||||
|
|||||||
@ -33,11 +33,11 @@ export function ResourceDisplay() {
|
|||||||
left={0}
|
left={0}
|
||||||
right={0}
|
right={0}
|
||||||
zIndex={100}
|
zIndex={100}
|
||||||
bg="gray.900"
|
bg="background.card"
|
||||||
py={2}
|
py={2}
|
||||||
borderBottom="1px"
|
borderBottom="1px"
|
||||||
borderColor="gray.700"
|
borderColor="brand.800"
|
||||||
shadow="lg"
|
boxShadow="0 2px 10px rgba(0,0,0,0.4)"
|
||||||
>
|
>
|
||||||
<Flex
|
<Flex
|
||||||
maxW="1200px"
|
maxW="1200px"
|
||||||
@ -60,6 +60,7 @@ export function ResourceDisplay() {
|
|||||||
h="100%"
|
h="100%"
|
||||||
w="auto"
|
w="auto"
|
||||||
objectFit="contain"
|
objectFit="contain"
|
||||||
|
filter="drop-shadow(0 2px 4px rgba(0,0,0,0.3))"
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@ -87,30 +88,31 @@ export function ResourceDisplay() {
|
|||||||
>
|
>
|
||||||
{/* Points */}
|
{/* Points */}
|
||||||
<Box textAlign="center" minW="120px">
|
<Box textAlign="center" minW="120px">
|
||||||
<Text fontSize="sm" fontWeight="bold">Points</Text>
|
<Text fontSize="sm" fontWeight="bold" color="brand.300">Points</Text>
|
||||||
<Text fontSize="md" fontWeight="bold">{formatNumber(Math.floor(points))}</Text>
|
<Text fontSize="md" fontWeight="bold" color="text.primary">{formatNumber(Math.floor(points))}</Text>
|
||||||
<Text fontSize="xs" color="green.400">+{formatNumber(pointsPerSecond)}/s</Text>
|
<Text fontSize="xs" color="text.secondary">+{formatNumber(pointsPerSecond)}/s</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider orientation="vertical" h="40px" />
|
<Divider orientation="vertical" h="40px" borderColor="brand.700" />
|
||||||
|
|
||||||
{/* Click Power with Upgrade Button */}
|
{/* Click Power with Upgrade Button */}
|
||||||
<Box textAlign="center" minW="120px">
|
<Box textAlign="center" minW="120px">
|
||||||
<Text fontSize="sm" fontWeight="bold">Click Power</Text>
|
<Text fontSize="sm" fontWeight="bold" color="brand.300">Click Power</Text>
|
||||||
<Flex justify="center" align="center" gap={1}>
|
<Flex justify="center" align="center" gap={1}>
|
||||||
<Text fontSize="md">{formatNumber(clickPower)}</Text>
|
<Text fontSize="md" color="text.primary">{formatNumber(clickPower)}</Text>
|
||||||
<Tooltip label={`Upgrade to level ${clickPower + 1} (${formatNumber(clickPowerUpgradeCost)} points)`}>
|
<Tooltip label={`Upgrade to level ${clickPower + 1} (${formatNumber(clickPowerUpgradeCost)} points)`}>
|
||||||
<Button
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
colorScheme="green"
|
colorScheme="brand"
|
||||||
variant="outline"
|
bg="brand.400"
|
||||||
|
color="text.dark"
|
||||||
p={1}
|
p={1}
|
||||||
height="20px"
|
height="20px"
|
||||||
minW="20px"
|
minW="20px"
|
||||||
onClick={() => buyUpgrade('clickPower')}
|
onClick={() => buyUpgrade('clickPower')}
|
||||||
opacity={canAffordUpgrade ? 1 : 0.4}
|
opacity={canAffordUpgrade ? 1 : 0.4}
|
||||||
cursor={canAffordUpgrade ? 'pointer' : 'not-allowed'}
|
cursor={canAffordUpgrade ? 'pointer' : 'not-allowed'}
|
||||||
_hover={{ bg: 'green.800', opacity: canAffordUpgrade ? 1 : 0.4 }}
|
_hover={{ bg: 'brand.500', opacity: canAffordUpgrade ? 1 : 0.4 }}
|
||||||
>
|
>
|
||||||
<AddIcon boxSize={2} />
|
<AddIcon boxSize={2} />
|
||||||
</Button>
|
</Button>
|
||||||
@ -118,27 +120,27 @@ export function ResourceDisplay() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider orientation="vertical" h="40px" />
|
<Divider orientation="vertical" h="40px" borderColor="brand.700" />
|
||||||
|
|
||||||
{/* Level */}
|
{/* Level */}
|
||||||
<Box textAlign="center" minW="80px">
|
<Box textAlign="center" minW="80px">
|
||||||
<Text fontSize="sm" fontWeight="bold">Level</Text>
|
<Text fontSize="sm" fontWeight="bold" color="brand.300">Level</Text>
|
||||||
<Text fontSize="md">{playerLevel}</Text>
|
<Text fontSize="md" color="text.primary">{playerLevel}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Progress to next level */}
|
{/* Progress to next level */}
|
||||||
<Tooltip label={`${formatNumber(pointsPerSecond)}/${formatNumber(nextLevelPPS)} PPS`}>
|
<Tooltip label={`${formatNumber(pointsPerSecond)}/${formatNumber(nextLevelPPS)} PPS`}>
|
||||||
<Box flex="1" maxW="300px">
|
<Box flex="1" maxW="300px">
|
||||||
<Flex justify="space-between" mb={1}>
|
<Flex justify="space-between" mb={1}>
|
||||||
<Text fontSize="xs" color="gray.400">Level {playerLevel}</Text>
|
<Text fontSize="xs" color="text.secondary">Level {playerLevel}</Text>
|
||||||
<Text fontSize="xs" color="gray.400">Level {playerLevel + 1}</Text>
|
<Text fontSize="xs" color="text.secondary">Level {playerLevel + 1}</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Progress
|
<Progress
|
||||||
value={progress}
|
value={progress}
|
||||||
colorScheme="green"
|
colorScheme="brand"
|
||||||
size="sm"
|
size="sm"
|
||||||
borderRadius="full"
|
borderRadius="full"
|
||||||
bg="gray.700"
|
bg="background.secondary"
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export function SoundToggleButton() {
|
|||||||
icon={<span>{soundOn ? '🔊' : '🔇'}</span>}
|
icon={<span>{soundOn ? '🔊' : '🔇'}</span>}
|
||||||
onClick={handleToggle}
|
onClick={handleToggle}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
colorScheme="cyan"
|
colorScheme="brand"
|
||||||
size="md"
|
size="md"
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
129
src/theme.ts
129
src/theme.ts
@ -1,22 +1,145 @@
|
|||||||
import { extendTheme } from '@chakra-ui/react'
|
import { extendTheme } from '@chakra-ui/react'
|
||||||
|
|
||||||
|
// Color palette based on asset analysis but with improved contrast
|
||||||
|
const colors = {
|
||||||
|
brand: {
|
||||||
|
// Main teal/cyan color found in assets
|
||||||
|
50: '#e3f9fb',
|
||||||
|
100: '#c5eef1',
|
||||||
|
200: '#a1e0e5',
|
||||||
|
300: '#7ad0d7',
|
||||||
|
400: '#51bec7',
|
||||||
|
500: '#29686c', // Our primary accent from analysis
|
||||||
|
600: '#1c5458', // Darker variant
|
||||||
|
700: '#183d3f', // From keyboard.png
|
||||||
|
800: '#113738', // From mouse.png
|
||||||
|
900: '#0f1e41', // From logo.png - more blue variant
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
primary: '#000101', // Almost black with slight cyan tint
|
||||||
|
secondary: '#0a141e', // Darker blue for better contrast
|
||||||
|
tertiary: '#122c2e', // Darker cyan for cards
|
||||||
|
card: '#112233', // Darker blue to contrast with teal images
|
||||||
|
highlight: '#1d4244', // For hover states and highlights
|
||||||
|
cardOverlay: 'rgba(17, 34, 51, 0.85)', // Semi-transparent overlay for text on images
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: '#ffffff',
|
||||||
|
secondary: '#a1e0e5', // Light brand color for secondary text
|
||||||
|
accent: '#51bec7', // Brighter cyan for accents and highlights
|
||||||
|
muted: '#718096', // For less important text
|
||||||
|
dark: '#0a141e', // Dark text for light backgrounds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const theme = extendTheme({
|
const theme = extendTheme({
|
||||||
config: {
|
config: {
|
||||||
initialColorMode: 'dark',
|
initialColorMode: 'dark',
|
||||||
useSystemColorMode: false,
|
useSystemColorMode: false,
|
||||||
},
|
},
|
||||||
|
colors,
|
||||||
styles: {
|
styles: {
|
||||||
global: {
|
global: {
|
||||||
body: {
|
body: {
|
||||||
bg: 'gray.900',
|
bg: colors.background.primary,
|
||||||
color: 'white',
|
color: colors.text.primary,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Button: {
|
Button: {
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
colorScheme: 'blue',
|
colorScheme: 'brand',
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
solid: {
|
||||||
|
bg: 'brand.500',
|
||||||
|
color: 'white',
|
||||||
|
_hover: {
|
||||||
|
bg: 'brand.600',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outline: {
|
||||||
|
borderColor: 'brand.300',
|
||||||
|
color: 'text.primary',
|
||||||
|
_hover: {
|
||||||
|
bg: 'background.highlight',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ghost: {
|
||||||
|
color: 'brand.300',
|
||||||
|
_hover: {
|
||||||
|
bg: 'background.highlight',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Box: {
|
||||||
|
variants: {
|
||||||
|
card: {
|
||||||
|
bg: 'background.card',
|
||||||
|
borderRadius: 'lg',
|
||||||
|
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.24)',
|
||||||
|
borderColor: 'brand.700',
|
||||||
|
borderWidth: '1px',
|
||||||
|
transition: 'all 0.2s ease-in-out',
|
||||||
|
_hover: {
|
||||||
|
transform: 'translateY(-2px)',
|
||||||
|
boxShadow: '0 6px 10px -1px rgba(0, 0, 0, 0.4), 0 4px 6px -1px rgba(0, 0, 0, 0.3)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Progress: {
|
||||||
|
baseStyle: {
|
||||||
|
filledTrack: {
|
||||||
|
bg: 'brand.400',
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
bg: 'background.highlight',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Tooltip: {
|
||||||
|
baseStyle: {
|
||||||
|
bg: 'background.secondary',
|
||||||
|
color: 'text.secondary',
|
||||||
|
borderColor: 'brand.700',
|
||||||
|
borderWidth: '1px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Heading: {
|
||||||
|
baseStyle: {
|
||||||
|
color: 'text.secondary',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Text: {
|
||||||
|
variants: {
|
||||||
|
accent: {
|
||||||
|
color: 'text.accent',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
color: 'text.secondary',
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
color: 'text.muted',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Modal: {
|
||||||
|
baseStyle: {
|
||||||
|
dialog: {
|
||||||
|
bg: 'background.secondary',
|
||||||
|
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.4)',
|
||||||
|
borderWidth: '1px',
|
||||||
|
borderColor: 'brand.700',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
color: 'text.secondary',
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
color: 'text.primary',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user