Skip to content

Commit 8235586

Browse files
committed
🎙️⛸️ ↝ [SSP-33 SSC-40 SSM-40]: Trying to build some shitty maps, but failing...about half
1 parent c81717b commit 8235586

File tree

10 files changed

+1196
-116
lines changed

10 files changed

+1196
-116
lines changed

app/scenes/earth/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import StructuresOnPlanet, {
1313
import AllAutomatonsOnActivePlanet from "@/components/Structures/Auto/AllAutomatons";
1414
import InventoryPage from "@/components/Inventory/Grid/Grid";
1515
import EnhancedWeatherEventsComponent from "@/components/enhanced-weather-events";
16-
import TopographicMap from "@/components/topographic-map";
16+
// import TopographicMap from "@/components/topographic-map";
1717

1818
const EarthView: React.FC = () => {
1919
const { activePlanet, updatePlanetLocation } = useActivePlanet();

app/tests/page.tsx

+106-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
"use client";
22

3-
import React, { useEffect, useState } from "react";
3+
import React, { useEffect, useRef, useMemo, useState } from "react";
44
import StarnetLayout from "@/components/Layout/Starnet";
5-
import ImageAnnotation from "@/components/Projects/(classifications)/Annotation";
6-
import InventoryPage from "@/components/Inventory/Grid/Grid";
7-
import TelescopeComponent from "@/constants/Structures/Telescope";
8-
import ZoodexComponent from "@/constants/Structures/Zoodex";
9-
import { CreateStructure } from "@/components/Structures/Build/CreateDedicatedStructure";
10-
import AllClassifications from "@/content/Starnet/YourClassifications";
5+
// import { TopographicMap } from "@/components/topographic-map";
116

127
export default function TestPage() {
138
return (
149
<StarnetLayout>
1510
<>
16-
<AllClassifications initialType="planet" />
11+
<div style={{ width: "100vw", height: "100vh" }}>
12+
<TopographicMap />
13+
</div>
1714
</>
1815
</StarnetLayout>
1916
);
@@ -30,4 +27,104 @@ export default function TestPage() {
3027
},
3128
]} />
3229
33-
*/
30+
*/
31+
32+
import { Canvas } from "@react-three/fiber";
33+
import * as THREE from "three";
34+
import { createNoise2D } from "simplex-noise";
35+
import alea from "alea";
36+
37+
// Topographic shaders
38+
const topographicVertexShader = `
39+
varying vec2 vUv;
40+
varying float vElevation;
41+
42+
void main() {
43+
vUv = uv;
44+
vElevation = position.z;
45+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
46+
}
47+
`;
48+
49+
const topographicFragmentShader = `
50+
varying vec2 vUv;
51+
varying float vElevation;
52+
uniform vec3 uBaseColor;
53+
uniform vec3 uContourColor;
54+
uniform float uBands;
55+
uniform float uContourWidth;
56+
57+
void main() {
58+
float elevation = vElevation;
59+
float bandedElevation = floor(elevation * uBands) / uBands;
60+
float nextBand = floor(elevation * uBands + 1.0) / uBands;
61+
float mixFactor = smoothstep(bandedElevation, nextBand, elevation);
62+
63+
float contourLine = 1.0 - smoothstep(0.0, uContourWidth, abs(mixFactor - 0.5));
64+
65+
vec3 finalColor = mix(uBaseColor, uContourColor, contourLine * 0.5);
66+
67+
gl_FragColor = vec4(finalColor, 1.0);
68+
}
69+
`;
70+
71+
type TerrainProps = {
72+
seed: number;
73+
heightScale: number;
74+
bands: number;
75+
baseColor: string;
76+
contourColor: string;
77+
};
78+
79+
const Terrain: React.FC<TerrainProps> = ({ seed, heightScale, bands, baseColor, contourColor }) => {
80+
const mesh = useRef<THREE.Mesh>(null); // Explicitly define mesh type
81+
const prng = useMemo(() => alea(seed), [seed]);
82+
const noise2D = useMemo(() => createNoise2D(prng), [prng]);
83+
84+
const geometry = useMemo(() => {
85+
const geo = new THREE.PlaneGeometry(20, 20, 200, 200);
86+
const positions = geo.attributes.position.array as Float32Array;
87+
88+
for (let i = 0; i < positions.length; i += 3) {
89+
const x = positions[i];
90+
const y = positions[i + 1];
91+
const noise = noise2D(x * 0.05, y * 0.05);
92+
positions[i + 2] = noise * heightScale;
93+
}
94+
95+
geo.computeVertexNormals();
96+
return geo;
97+
}, [noise2D, heightScale]);
98+
99+
const material = useMemo(() => {
100+
return new THREE.ShaderMaterial({
101+
vertexShader: topographicVertexShader,
102+
fragmentShader: topographicFragmentShader,
103+
uniforms: {
104+
uBaseColor: { value: new THREE.Color(baseColor) },
105+
uContourColor: { value: new THREE.Color(contourColor) },
106+
uBands: { value: bands },
107+
uContourWidth: { value: 0.1 },
108+
},
109+
});
110+
}, [baseColor, contourColor, bands]);
111+
112+
return (
113+
<mesh ref={mesh} geometry={geometry} material={material} rotation={[-Math.PI / 2, 0, 0]} />
114+
);
115+
};
116+
117+
const TopographicMap = () => {
118+
return (
119+
<Canvas>
120+
<ambientLight />
121+
<Terrain
122+
seed={42}
123+
heightScale={1}
124+
bands={40}
125+
baseColor="#F5F5DC" // Beige
126+
contourColor="#8B4513" // SaddleBrown
127+
/>
128+
</Canvas>
129+
);
130+
};

components/Inventory.tsx

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { useState } from 'react'
2+
import { Diamond, Zap, Gem, Rocket, Crown } from 'lucide-react'
3+
4+
type InventoryItem = {
5+
id: string
6+
name: string
7+
amount: number
8+
}
9+
10+
type Props = {
11+
inventory: InventoryItem[]
12+
}
13+
14+
export function Inventory({ inventory = [] }: Props) {
15+
const [hoveredItem, setHoveredItem] = useState<string | null>(null)
16+
17+
const getIcon = (name: string) => {
18+
switch (name) {
19+
case 'Iron':
20+
return <Diamond className="text-[#FFE3BA]" />
21+
case 'Copper':
22+
return <Zap className="text-[#FFE3BA]" />
23+
case 'Gold':
24+
return <Gem className="text-[#FFE3BA]" />
25+
case 'Titanium':
26+
return <Rocket className="text-[#FFE3BA]" />
27+
case 'Platinum':
28+
return <Crown className="text-[#FFE3BA]" />
29+
default:
30+
return <Diamond className="text-[#FFE3BA]" />
31+
}
32+
}
33+
34+
return (
35+
<div className="space-y-2">
36+
<h2 className="text-xl font-bold text-[#2C4F64]">Inventory</h2>
37+
<div className="flex space-x-4">
38+
{inventory.map(item => (
39+
<div
40+
key={item.id}
41+
className="relative flex items-center space-x-2 bg-gray-100 p-2 rounded-lg"
42+
onMouseEnter={() => setHoveredItem(item.id)}
43+
onMouseLeave={() => setHoveredItem(null)}
44+
>
45+
{getIcon(item.name)}
46+
<span className="font-bold">{item.amount}</span>
47+
{hoveredItem === item.id && (
48+
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 bg-[#2C4F64] text-white px-2 py-1 rounded text-sm whitespace-nowrap">
49+
{item.name}
50+
</div>
51+
)}
52+
</div>
53+
))}
54+
</div>
55+
</div>
56+
)
57+
}

components/Layout/Guide.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ const StructureMissionGuide = () => {
294294
<p className={`text-sm ${isCompleted ? 'text-green-400' : 'text-gray-400'}`}>
295295
{mission.description}
296296
</p>
297+
{mission.modalContent && (
298+
<Button variant="outline" className="mt-2">Action</Button>
299+
)}
297300
</div>
298301
</CardContent>
299302
</Card>

components/Topo.tsx

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { useEffect, useRef } from 'react'
2+
import { motion } from 'framer-motion'
3+
4+
type MineralDeposit = {
5+
id: string
6+
name: string
7+
amount: number
8+
position: { x: number; y: number }
9+
}
10+
11+
type Props = {
12+
deposits: MineralDeposit[]
13+
roverPosition: { x: number; y: number } | null
14+
selectedDeposit: MineralDeposit | null
15+
}
16+
17+
export function TopographicMap({ deposits = [], roverPosition, selectedDeposit }: Props) {
18+
const canvasRef = useRef<HTMLCanvasElement>(null)
19+
20+
useEffect(() => {
21+
const canvas = canvasRef.current
22+
if (!canvas) return
23+
24+
const ctx = canvas.getContext('2d')
25+
if (!ctx) return
26+
27+
// Draw topographic map (simplified version)
28+
ctx.fillStyle = '#f0f0f0'
29+
ctx.fillRect(0, 0, canvas.width, canvas.height)
30+
31+
// Draw contour lines
32+
ctx.strokeStyle = '#d0d0d0'
33+
for (let i = 0; i < canvas.height; i += 20) {
34+
ctx.beginPath()
35+
ctx.moveTo(0, i)
36+
ctx.lineTo(canvas.width, i)
37+
ctx.stroke()
38+
}
39+
40+
// Draw deposits
41+
deposits.forEach(deposit => {
42+
ctx.fillStyle = deposit.name === 'Iron' ? '#FFE3BA' : '#5FCBC3'
43+
ctx.beginPath()
44+
ctx.arc(deposit.position.x, deposit.position.y, Math.sqrt(deposit.amount) / 2, 0, 2 * Math.PI)
45+
ctx.fill()
46+
47+
// Add deposit name
48+
ctx.fillStyle = '#2C4F64'
49+
ctx.font = '12px Arial'
50+
ctx.textAlign = 'center'
51+
ctx.fillText(deposit.name, deposit.position.x, deposit.position.y + Math.sqrt(deposit.amount) / 2 + 20)
52+
})
53+
}, [deposits])
54+
55+
return (
56+
<div className="relative w-full h-[400px]">
57+
<canvas ref={canvasRef} className="w-full h-full" width={800} height={400} />
58+
{roverPosition && (
59+
<motion.div
60+
className="absolute w-4 h-4 bg-[#2C4F64] rounded-full"
61+
style={{ left: roverPosition.x, top: roverPosition.y }}
62+
animate={{ scale: [1, 1.2, 1] }}
63+
transition={{ repeat: Infinity, duration: 1 }}
64+
/>
65+
)}
66+
{selectedDeposit && (
67+
<div
68+
className="absolute w-6 h-6 border-2 border-[#5FCBC3] rounded-full"
69+
style={{ left: selectedDeposit.position.x - 12, top: selectedDeposit.position.y - 12 }}
70+
/>
71+
)}
72+
</div>
73+
)
74+
}

0 commit comments

Comments
 (0)