[gemini] Re-implement Rune Ring (Portal-Tethered) (#476) #496

Merged
claude merged 1 commits from gemini/issue-476 into main 2026-03-25 03:06:53 +00:00

60
app.js
View File

@@ -821,6 +821,33 @@ function createPortal(config) {
light.position.set(0, 3.5, 1);
group.add(light);
// Rune Ring (Portal-tethered)
const runeCount = 8;
const runeRingRadius = 4.5;
const runes = [];
for (let i = 0; i < runeCount; i++) {
const angle = (i / runeCount) * Math.PI * 2;
const runeGeo = new THREE.BoxGeometry(0.3, 0.8, 0.1);
const runeMat = new THREE.MeshStandardMaterial({
color: portalColor,
emissive: portalColor,
emissiveIntensity: 0.8,
transparent: true,
opacity: 0.7,
roughness: 0.2,
metalness: 0.5,
});
const rune = new THREE.Mesh(runeGeo, runeMat);
rune.position.set(
Math.cos(angle) * runeRingRadius,
4,
Math.sin(angle) * runeRingRadius
);
rune.rotation.y = angle + Math.PI / 2;
group.add(rune);
runes.push(rune);
}
// Label
const labelCanvas = document.createElement('canvas');
labelCanvas.width = 512;
@@ -860,7 +887,8 @@ function createPortal(config) {
ring,
swirl,
pSystem,
light
light,
runes
};
}
@@ -986,20 +1014,7 @@ function createAmbientStructures() {
scene.add(crystal);
});
for (let i = 0; i < 5; i++) {
const angle = (i / 5) * Math.PI * 2;
const r = 10;
const geo = new THREE.OctahedronGeometry(0.4, 0);
const mat = new THREE.MeshStandardMaterial({
color: NEXUS.colors.primary,
emissive: NEXUS.colors.primary,
emissiveIntensity: 0.5,
});
const stone = new THREE.Mesh(geo, mat);
stone.position.set(Math.cos(angle) * r, 5 + Math.sin(i * 1.3) * 1.5, Math.sin(angle) * r);
stone.name = 'runestone_' + i;
scene.add(stone);
}
const coreGeo = new THREE.IcosahedronGeometry(0.6, 2);
const coreMat = new THREE.MeshPhysicalMaterial({
@@ -1427,6 +1442,12 @@ function gameLoop() {
positions[i * 3 + 1] += Math.sin(elapsed + i) * 0.002;
}
portal.pSystem.geometry.attributes.position.needsUpdate = true;
// Animate runes
portal.runes.forEach((rune, i) => {
rune.position.y = 4 + Math.sin(elapsed * 2 + i * 0.5) * 0.2;
rune.rotation.z = elapsed * 0.8 + i;
});
});
// Animate Vision Points
@@ -1463,14 +1484,7 @@ function gameLoop() {
dustParticles.rotation.y = elapsed * 0.01;
}
for (let i = 0; i < 5; i++) {
const stone = scene.getObjectByName('runestone_' + i);
if (stone) {
stone.position.y = 5 + Math.sin(elapsed * 0.8 + i * 1.3) * 0.8;
stone.rotation.y = elapsed * 0.5 + i;
stone.rotation.x = elapsed * 0.3 + i * 0.7;
}
}
const core = scene.getObjectByName('nexus-core');
if (core) {