Skip to content

Commit

Permalink
🎙️⛸️ ↝ [SSP-33 SSC-40 SSM-40]: Trying to build some shitty maps, but …
Browse files Browse the repository at this point in the history
…failing...about half
  • Loading branch information
Gizmotronn committed Nov 19, 2024
1 parent c81717b commit 8235586
Show file tree
Hide file tree
Showing 10 changed files with 1,196 additions and 116 deletions.
2 changes: 1 addition & 1 deletion app/scenes/earth/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import StructuresOnPlanet, {
import AllAutomatonsOnActivePlanet from "@/components/Structures/Auto/AllAutomatons";
import InventoryPage from "@/components/Inventory/Grid/Grid";
import EnhancedWeatherEventsComponent from "@/components/enhanced-weather-events";
import TopographicMap from "@/components/topographic-map";
// import TopographicMap from "@/components/topographic-map";

const EarthView: React.FC = () => {
const { activePlanet, updatePlanetLocation } = useActivePlanet();
Expand Down
115 changes: 106 additions & 9 deletions app/tests/page.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
"use client";

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

export default function TestPage() {
return (
<StarnetLayout>
<>
<AllClassifications initialType="planet" />
<div style={{ width: "100vw", height: "100vh" }}>
<TopographicMap />
</div>
</>
</StarnetLayout>
);
Expand All @@ -30,4 +27,104 @@ export default function TestPage() {
},
]} />
*/
*/

import { Canvas } from "@react-three/fiber";
import * as THREE from "three";
import { createNoise2D } from "simplex-noise";
import alea from "alea";

// Topographic shaders
const topographicVertexShader = `
varying vec2 vUv;
varying float vElevation;
void main() {
vUv = uv;
vElevation = position.z;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;

const topographicFragmentShader = `
varying vec2 vUv;
varying float vElevation;
uniform vec3 uBaseColor;
uniform vec3 uContourColor;
uniform float uBands;
uniform float uContourWidth;
void main() {
float elevation = vElevation;
float bandedElevation = floor(elevation * uBands) / uBands;
float nextBand = floor(elevation * uBands + 1.0) / uBands;
float mixFactor = smoothstep(bandedElevation, nextBand, elevation);
float contourLine = 1.0 - smoothstep(0.0, uContourWidth, abs(mixFactor - 0.5));
vec3 finalColor = mix(uBaseColor, uContourColor, contourLine * 0.5);
gl_FragColor = vec4(finalColor, 1.0);
}
`;

type TerrainProps = {
seed: number;
heightScale: number;
bands: number;
baseColor: string;
contourColor: string;
};

const Terrain: React.FC<TerrainProps> = ({ seed, heightScale, bands, baseColor, contourColor }) => {
const mesh = useRef<THREE.Mesh>(null); // Explicitly define mesh type
const prng = useMemo(() => alea(seed), [seed]);
const noise2D = useMemo(() => createNoise2D(prng), [prng]);

const geometry = useMemo(() => {
const geo = new THREE.PlaneGeometry(20, 20, 200, 200);
const positions = geo.attributes.position.array as Float32Array;

for (let i = 0; i < positions.length; i += 3) {
const x = positions[i];
const y = positions[i + 1];
const noise = noise2D(x * 0.05, y * 0.05);
positions[i + 2] = noise * heightScale;
}

geo.computeVertexNormals();
return geo;
}, [noise2D, heightScale]);

const material = useMemo(() => {
return new THREE.ShaderMaterial({
vertexShader: topographicVertexShader,
fragmentShader: topographicFragmentShader,
uniforms: {
uBaseColor: { value: new THREE.Color(baseColor) },
uContourColor: { value: new THREE.Color(contourColor) },
uBands: { value: bands },
uContourWidth: { value: 0.1 },
},
});
}, [baseColor, contourColor, bands]);

return (
<mesh ref={mesh} geometry={geometry} material={material} rotation={[-Math.PI / 2, 0, 0]} />
);
};

const TopographicMap = () => {
return (
<Canvas>
<ambientLight />
<Terrain
seed={42}
heightScale={1}
bands={40}
baseColor="#F5F5DC" // Beige
contourColor="#8B4513" // SaddleBrown
/>
</Canvas>
);
};
57 changes: 57 additions & 0 deletions components/Inventory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useState } from 'react'
import { Diamond, Zap, Gem, Rocket, Crown } from 'lucide-react'

type InventoryItem = {
id: string
name: string
amount: number
}

type Props = {
inventory: InventoryItem[]
}

export function Inventory({ inventory = [] }: Props) {
const [hoveredItem, setHoveredItem] = useState<string | null>(null)

const getIcon = (name: string) => {
switch (name) {
case 'Iron':
return <Diamond className="text-[#FFE3BA]" />
case 'Copper':
return <Zap className="text-[#FFE3BA]" />
case 'Gold':
return <Gem className="text-[#FFE3BA]" />
case 'Titanium':
return <Rocket className="text-[#FFE3BA]" />
case 'Platinum':
return <Crown className="text-[#FFE3BA]" />
default:
return <Diamond className="text-[#FFE3BA]" />
}
}

return (
<div className="space-y-2">
<h2 className="text-xl font-bold text-[#2C4F64]">Inventory</h2>
<div className="flex space-x-4">
{inventory.map(item => (
<div
key={item.id}
className="relative flex items-center space-x-2 bg-gray-100 p-2 rounded-lg"
onMouseEnter={() => setHoveredItem(item.id)}
onMouseLeave={() => setHoveredItem(null)}
>
{getIcon(item.name)}
<span className="font-bold">{item.amount}</span>
{hoveredItem === item.id && (
<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">
{item.name}
</div>
)}
</div>
))}
</div>
</div>
)
}
3 changes: 3 additions & 0 deletions components/Layout/Guide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ const StructureMissionGuide = () => {
<p className={`text-sm ${isCompleted ? 'text-green-400' : 'text-gray-400'}`}>
{mission.description}
</p>
{mission.modalContent && (
<Button variant="outline" className="mt-2">Action</Button>
)}
</div>
</CardContent>
</Card>
Expand Down
74 changes: 74 additions & 0 deletions components/Topo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useEffect, useRef } from 'react'
import { motion } from 'framer-motion'

type MineralDeposit = {
id: string
name: string
amount: number
position: { x: number; y: number }
}

type Props = {
deposits: MineralDeposit[]
roverPosition: { x: number; y: number } | null
selectedDeposit: MineralDeposit | null
}

export function TopographicMap({ deposits = [], roverPosition, selectedDeposit }: Props) {
const canvasRef = useRef<HTMLCanvasElement>(null)

useEffect(() => {
const canvas = canvasRef.current
if (!canvas) return

const ctx = canvas.getContext('2d')
if (!ctx) return

// Draw topographic map (simplified version)
ctx.fillStyle = '#f0f0f0'
ctx.fillRect(0, 0, canvas.width, canvas.height)

// Draw contour lines
ctx.strokeStyle = '#d0d0d0'
for (let i = 0; i < canvas.height; i += 20) {
ctx.beginPath()
ctx.moveTo(0, i)
ctx.lineTo(canvas.width, i)
ctx.stroke()
}

// Draw deposits
deposits.forEach(deposit => {
ctx.fillStyle = deposit.name === 'Iron' ? '#FFE3BA' : '#5FCBC3'
ctx.beginPath()
ctx.arc(deposit.position.x, deposit.position.y, Math.sqrt(deposit.amount) / 2, 0, 2 * Math.PI)
ctx.fill()

// Add deposit name
ctx.fillStyle = '#2C4F64'
ctx.font = '12px Arial'
ctx.textAlign = 'center'
ctx.fillText(deposit.name, deposit.position.x, deposit.position.y + Math.sqrt(deposit.amount) / 2 + 20)
})
}, [deposits])

return (
<div className="relative w-full h-[400px]">
<canvas ref={canvasRef} className="w-full h-full" width={800} height={400} />
{roverPosition && (
<motion.div
className="absolute w-4 h-4 bg-[#2C4F64] rounded-full"
style={{ left: roverPosition.x, top: roverPosition.y }}
animate={{ scale: [1, 1.2, 1] }}
transition={{ repeat: Infinity, duration: 1 }}
/>
)}
{selectedDeposit && (
<div
className="absolute w-6 h-6 border-2 border-[#5FCBC3] rounded-full"
style={{ left: selectedDeposit.position.x - 12, top: selectedDeposit.position.y - 12 }}
/>
)}
</div>
)
}
Loading

0 comments on commit 8235586

Please sign in to comment.