Skip to content

Commit 4ca31b8

Browse files
committed
Add: sun texture
1 parent 79dcbbe commit 4ca31b8

10 files changed

Lines changed: 831 additions & 72 deletions

File tree

src/pages/home/.ipynb_checkpoints/Home-checkpoint.tsx

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,62 @@
1-
import { useEffect, useRef } from "react";
2-
import { main } from "./solarsystem.js";
31
import styles from "./Home.module.css";
4-
5-
function Home() {
6-
2+
import { useState, useEffect, useRef } from "react";
3+
import LevelComponent from "../../components/LevelComponent";
4+
import { main } from "./js/main.js";
5+
// import { main } from "./solarsystem.js";
6+
import { useMouseMoving } from "../../hooks/useMouseMoving.js";
7+
export default function Home() {
8+
const lvlNum = 4;
79
const canvasRef = useRef<HTMLCanvasElement | null>(null);
10+
const zoomOutRef = useRef<(() => void) | null>(null);
11+
12+
const [isVisible, setIsVisible] = useState(false);
13+
const [mountKey, setMountKey] = useState(0);
14+
const isMouseMoving = useMouseMoving(2500);
15+
const hideUI = isMouseMoving || isVisible;
16+
17+
const handleOpen = () => {
18+
setMountKey(k => k + 1);
19+
setIsVisible(true);
20+
};
21+
22+
const handleClose = () => {
23+
setIsVisible(false);
24+
zoomOutRef.current?.();
25+
};
826

927
useEffect(() => {
10-
1128
if (!canvasRef.current) return;
12-
13-
main(canvasRef.current);
14-
29+
const { zoomOut } = main(canvasRef.current, handleOpen);
30+
zoomOutRef.current = zoomOut;
1531
}, []);
1632

1733
return (
18-
<>
19-
<header>
34+
<div>
35+
<header style={{
36+
transition: "opacity 0.4s ease",
37+
opacity: hideUI ? 0 : 1,
38+
pointerEvents: hideUI ? "none" : "auto",
39+
}}
40+
>
2041
<div className={styles["header-brand"]}>
21-
<h1>Glorpython</h1>
42+
<h1>glorpython</h1>
2243
</div>
2344
</header>
24-
<canvas ref={canvasRef} className={styles.solarsystem}></canvas>
25-
</>
45+
<section className="relative w-full h-screen">
46+
{isVisible && (
47+
48+
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-[90vw] h-[90vh] z-50">
49+
<LevelComponent
50+
// key={mountKey}
51+
selectedLevel={1}
52+
onClose={() => handleClose()}
53+
54+
/>
55+
</div>
56+
57+
)}
58+
<canvas ref={canvasRef} className={styles.solarsystem}></canvas>
59+
</section>
60+
</div>
2661
);
2762
}
28-
29-
export default Home;

src/pages/home/.ipynb_checkpoints/solarsystem-checkpoint.js

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,21 @@ import * as THREE from "three";
33
const ZOOM_DIST = 5; // how close the camera gets (in planet radii + offset)
44
const TWEEN_SPEED = 0.07; // lerp factor for camera movement
55

6-
export function main(canvas) {
7-
6+
export function main(canvas, onPlanetFocus) {
7+
const loader = new THREE.TextureLoader();
88
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
99
renderer.setPixelRatio(window.devicePixelRatio);
1010
renderer.toneMapping = THREE.ACESFilmicToneMapping;
1111
renderer.toneMappingExposure = 2.0;
1212

13+
const createRepeatingTexture = (path, repeatX = 2, repeatY = 1) => {
14+
const tex = loader.load(path);
15+
tex.wrapS = THREE.RepeatWrapping;
16+
tex.wrapT = THREE.RepeatWrapping;
17+
tex.repeat.set(repeatX, repeatY);
18+
return tex;
19+
};
20+
1321
const fov = 45;
1422
const aspect = canvas.clientWidth / canvas.clientHeight;
1523
const near = 0.1;
@@ -37,20 +45,19 @@ export function main(canvas) {
3745
// Sun
3846
const sunGeo = new THREE.SphereGeometry(4.5, 64, 64);
3947
const sunMat = new THREE.MeshStandardMaterial({
40-
color: 0xe8ffff,
41-
emissive: 0x88ffee,
42-
emissiveIntensity: 3.2,
43-
roughness: 0.0,
44-
metalness: 0.0
48+
map: createRepeatingTexture('/textures/glorptest.png', 3, 3),
49+
emissiveMap: loader.load('/textures/suntexture.webp'), // same tex drives the glow
50+
emissive: 0x91ffaf,
51+
emissiveIntensity: 0.1,
4552
});
4653
const sun = new THREE.Mesh(sunGeo, sunMat);
4754
scene.add(sun);
4855

4956
// Planets
5057
const planetData = [
51-
{ radius: 1.1, orbitR: 14, speed: 0.8, tilt: 0.2, color: 0xff6644, emissive: 0x441100 },
52-
{ radius: 1.5, orbitR: 24, speed: 0.45, tilt: 0.35, color: 0x44aaff, emissive: 0x001133 },
53-
{ radius: 1.2, orbitR: 36, speed: 0.25, tilt: 0.15, color: 0x88dd55, emissive: 0x112200 },
58+
{ radius: 1.1, orbitR: 14, speed: 0.8, tilt: 0.2, color: 0xff6644, emissive: 0x441100, texture: '/textures/texture1.webp'},
59+
{ radius: 1.5, orbitR: 24, speed: 0.45, tilt: 0.35, color: 0x44aaff, emissive: 0x001133, texture: '/textures/texture2.webp' },
60+
{ radius: 1.2, orbitR: 36, speed: 0.25, tilt: 0.15, color: 0x88dd55, emissive: 0x112200, texture: '/textures/texture3.webp'},
5461
];
5562

5663
const planets = planetData.flatMap(d => {
@@ -72,9 +79,7 @@ export function main(canvas) {
7279
return [0, 1, 2].map(i => {
7380
const geo = new THREE.SphereGeometry(d.radius, 36, 36);
7481
const mat = new THREE.MeshStandardMaterial({
75-
color: d.color,
76-
emissive: d.emissive,
77-
emissiveIntensity: 1.0,
82+
map: loader.load(d.texture),
7883
roughness: 0.65,
7984
metalness: 0.05
8085
});
@@ -122,11 +127,23 @@ export function main(canvas) {
122127
const raycaster = new THREE.Raycaster();
123128
const pointer = new THREE.Vector2();
124129

125-
let paused = false; // are planets frozen?
126-
let focusedPlanet = null; // the planet object we zoomed into
127-
let cameraTarget = null; // THREE.Vector3 we're tweening toward
128-
let lookAtTarget = null; // THREE.Vector3 we're looking at
130+
let paused = false;
131+
let focusedPlanet = null;
132+
let cameraTarget = null;
133+
let lookAtTarget = null;
129134
let tweening = false;
135+
let popupFired = false;
136+
137+
// Zoom out — resets focus and starts the camera tween back to the initial position.
138+
// Called both by canvas clicks on empty space and externally (e.g. the ✕ button).
139+
function zoomOut() {
140+
console.log("Hi");
141+
focusedPlanet = null;
142+
paused = false;
143+
tweening = true;
144+
cameraTarget = initPos.clone();
145+
lookAtTarget = new THREE.Vector3(0, 0, 0);
146+
}
130147

131148
canvas.addEventListener('click', e => {
132149
const rect = canvas.getBoundingClientRect();
@@ -138,20 +155,16 @@ export function main(canvas) {
138155
const hits = raycaster.intersectObjects(meshes);
139156

140157
if (hits.length > 0) {
141-
// Clicked a planet — focus it
142158
const hit = hits[0];
143159
focusedPlanet = planets.find(p => p.mesh === hit.object);
144-
paused = true;
145-
tweening = true;
160+
paused = true;
161+
tweening = true;
162+
popupFired = false;
146163
} else {
147-
// Clicked empty space — release
148-
focusedPlanet = null;
149-
paused = false;
150-
tweening = true;
151-
cameraTarget = initPos.clone();
152-
lookAtTarget = new THREE.Vector3(0, 0, 0);
164+
zoomOut();
153165
}
154166
});
167+
155168
// ─────────────────────────────────────────────────────────────────────
156169

157170
function resizeRendererToDisplaySize(renderer) {
@@ -166,7 +179,6 @@ export function main(canvas) {
166179

167180
function render() {
168181

169-
// Advance planet orbits (only when not paused)
170182
planets.forEach(p => {
171183
if (!paused) {
172184
p.angle += p.speed * 0.008;
@@ -181,47 +193,30 @@ export function main(canvas) {
181193

182194
sun.rotation.y += 0.003;
183195

184-
185-
186-
187-
188-
189-
190-
// Update the camera target each frame while focused
191-
// (so the camera tracks the planet even mid-tween if it still moves slightly)
192196
if (focusedPlanet) {
193197
const pPos = focusedPlanet.mesh.position;
194-
// Position the camera slightly behind & above the planet relative to the origin
195198
const dir = pPos.clone().normalize();
196199
cameraTarget = pPos.clone().add(dir.multiplyScalar(focusedPlanet.radius + ZOOM_DIST));
197200
cameraTarget.y += focusedPlanet.radius * 0.8;
198201
lookAtTarget = pPos.clone();
199202
}
200203

201-
// Tween camera
202204
if (tweening && cameraTarget && lookAtTarget) {
203205
camera.position.lerp(cameraTarget, TWEEN_SPEED);
204206
currentLookAt.lerp(lookAtTarget, TWEEN_SPEED);
205207
camera.lookAt(currentLookAt);
206208

207-
// Stop tweening once close enough
208209
if (camera.position.distanceTo(cameraTarget) < 0.05) {
209210
tweening = false;
210211

211-
212-
213-
214-
215-
// POP UP HERE
216-
217-
218-
219-
220-
221-
212+
if (focusedPlanet && !popupFired) {
213+
popupFired = true;
214+
if (typeof onPlanetFocus === 'function') {
215+
onPlanetFocus();
216+
}
217+
}
222218
}
223219
} else if (!paused) {
224-
// Normal parallax behaviour
225220
currentOffset.x += (targetOffset.x - currentOffset.x) * 0.13;
226221
currentOffset.y += (targetOffset.y - currentOffset.y) * 0.13;
227222

@@ -234,11 +229,6 @@ export function main(canvas) {
234229
camera.lookAt(currentLookAt);
235230
}
236231

237-
238-
239-
240-
241-
242232
if (resizeRendererToDisplaySize(renderer)) {
243233
camera.aspect = canvas.clientWidth / canvas.clientHeight;
244234
camera.updateProjectionMatrix();
@@ -249,4 +239,6 @@ export function main(canvas) {
249239
}
250240

251241
requestAnimationFrame(render);
242+
243+
return { zoomOut };
252244
}

src/pages/home/Home.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import styles from "./Home.module.css";
22
import { useState, useEffect, useRef } from "react";
33
import LevelComponent from "../../components/LevelComponent";
4-
import { main } from "./solarsystem.js";
4+
import { main } from "./js/main.js";
5+
// import { main } from "./solarsystem.js";
56
import { useMouseMoving } from "../../hooks/useMouseMoving.js";
67
export default function Home() {
78
const lvlNum = 4;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import * as THREE from "three";
2+
3+
export function createCamera( canvas ) {
4+
5+
const fov = 45;
6+
const aspect = canvas.clientWidth / canvas.clientHeight;
7+
const near = 0.1;
8+
const far = 500;
9+
const basePosition = new THREE.Vector3(0, 40, 70);
10+
11+
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
12+
13+
camera.position.copy(basePosition);
14+
15+
return { camera, basePosition };
16+
17+
}
18+
19+
export function setupParallax( canvas ) {
20+
21+
// Mouse parallax
22+
const targetOffset = { x: 0, y: 0 };
23+
const currentOffset = { x: 0, y: 0 };
24+
25+
window.addEventListener('mousemove', e => {
26+
const rect = canvas.getBoundingClientRect();
27+
const nx = (e.clientX - rect.left) / rect.width - 0.5;
28+
const ny = (e.clientY - rect.top) / rect.height - 0.5;
29+
targetOffset.x = nx * 20;
30+
targetOffset.y = -ny * 20;
31+
});
32+
33+
window.addEventListener('mouseleave', () => {
34+
targetOffset.x = 0;
35+
targetOffset.y = 0;
36+
});
37+
38+
return { targetOffset, currentOffset };
39+
40+
}
41+
42+
export function setupFocus( canvas, camera, planets, basePosition ) {
43+
44+
const focus = {
45+
raycaster: new THREE.Raycaster(),
46+
pointer: new THREE.Vector2(),
47+
paused: false,
48+
focusedPlanet: null,
49+
cameraTarget: null,
50+
lookAtTarget: null,
51+
tweening: false,
52+
popupFired: false,
53+
};
54+
55+
canvas.addEventListener('click', e => {
56+
const rect = canvas.getBoundingClientRect();
57+
focus.pointer.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
58+
focus.pointer.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
59+
focus.raycaster.setFromCamera(focus.pointer, camera);
60+
61+
const meshes = planets.map(p => p.mesh);
62+
const hits = focus.raycaster.intersectObjects(meshes);
63+
64+
if (hits.length > 0) {
65+
focus.focusedPlanet = planets.find(p => p.mesh === hits[0].object);
66+
focus.paused = true;
67+
focus.tweening = true;
68+
focus.popupFired = false;
69+
}
70+
else {
71+
zoomOut();
72+
}
73+
});
74+
75+
function zoomOut() {
76+
focus.focusedPlanet = null;
77+
focus.paused = false;
78+
focus.tweening = true;
79+
focus.cameraTarget = basePosition.clone();
80+
focus.lookAtTarget = new THREE.Vector3(0, 0, 0);
81+
}
82+
83+
return { focus, zoomOut };
84+
85+
}
86+
87+
88+

0 commit comments

Comments
 (0)