feat: tactical icons, follow-camera orbit, and ship info panel
This commit is contained in:
@@ -293,62 +293,6 @@ function createStarSparkleTexture(documentRef: Document): THREE.CanvasTexture {
|
||||
return texture;
|
||||
}
|
||||
|
||||
function createMilkyWayTexture(documentRef: Document): THREE.CanvasTexture {
|
||||
const canvas = documentRef.createElement("canvas");
|
||||
canvas.width = 1024;
|
||||
canvas.height = 256;
|
||||
const context = canvas.getContext("2d");
|
||||
if (!context) {
|
||||
throw new Error("Unable to create milky way texture");
|
||||
}
|
||||
|
||||
const background = context.createLinearGradient(0, 0, 1024, 0);
|
||||
background.addColorStop(0, "rgba(0,0,0,0)");
|
||||
background.addColorStop(0.1, "rgba(150,110,255,0.08)");
|
||||
background.addColorStop(0.32, "rgba(120,210,255,0.14)");
|
||||
background.addColorStop(0.5, "rgba(255,240,220,0.28)");
|
||||
background.addColorStop(0.68, "rgba(255,165,210,0.16)");
|
||||
background.addColorStop(0.88, "rgba(115,155,255,0.08)");
|
||||
background.addColorStop(1, "rgba(0,0,0,0)");
|
||||
context.fillStyle = background;
|
||||
context.fillRect(0, 0, 1024, 256);
|
||||
|
||||
for (let index = 0; index < 220; index += 1) {
|
||||
const x = THREE.MathUtils.randFloat(0, 1024);
|
||||
const y = 128 + THREE.MathUtils.randFloatSpread(78);
|
||||
const radiusX = THREE.MathUtils.randFloat(40, 180);
|
||||
const radiusY = THREE.MathUtils.randFloat(8, 28);
|
||||
const alpha = THREE.MathUtils.randFloat(0.025, 0.09);
|
||||
const hue = THREE.MathUtils.randFloat(0.52, 0.76);
|
||||
const color = new THREE.Color().setHSL(hue, THREE.MathUtils.randFloat(0.25, 0.6), THREE.MathUtils.randFloat(0.72, 0.9));
|
||||
const puff = context.createRadialGradient(x, y, 0, x, y, radiusX);
|
||||
puff.addColorStop(0, `rgba(${Math.round(color.r * 255)},${Math.round(color.g * 255)},${Math.round(color.b * 255)},${alpha})`);
|
||||
puff.addColorStop(0.55, `rgba(${Math.round(color.r * 255)},${Math.round(color.g * 255)},${Math.round(color.b * 255)},${alpha * 0.45})`);
|
||||
puff.addColorStop(1, "rgba(0,0,0,0)");
|
||||
context.save();
|
||||
context.translate(x, y);
|
||||
context.scale(1, radiusY / radiusX);
|
||||
context.fillStyle = puff;
|
||||
context.beginPath();
|
||||
context.arc(0, 0, radiusX, 0, Math.PI * 2);
|
||||
context.fill();
|
||||
context.restore();
|
||||
}
|
||||
|
||||
for (let index = 0; index < 540; index += 1) {
|
||||
const x = THREE.MathUtils.randFloat(0, 1024);
|
||||
const y = 128 + THREE.MathUtils.randFloatSpread(54);
|
||||
const alpha = THREE.MathUtils.randFloat(0.12, 0.65);
|
||||
const size = THREE.MathUtils.randFloat(0.8, 2.4);
|
||||
context.fillStyle = `rgba(255,255,255,${alpha})`;
|
||||
context.fillRect(x, y, size, size);
|
||||
}
|
||||
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
}
|
||||
|
||||
function sampleBackdropStarColor(): THREE.Color {
|
||||
const roll = Math.random();
|
||||
if (roll < 0.1) {
|
||||
@@ -595,39 +539,6 @@ export function createNebulaClouds(texture: THREE.Texture): THREE.Sprite[] {
|
||||
});
|
||||
}
|
||||
|
||||
export function createMilkyWayBand(documentRef: Document): THREE.Group {
|
||||
const radius = 33800;
|
||||
const texture = createMilkyWayTexture(documentRef);
|
||||
const root = new THREE.Group();
|
||||
const planeNormal = new THREE.Vector3(0.24, 0.92, -0.3).normalize();
|
||||
const tangent = new THREE.Vector3().crossVectors(planeNormal, new THREE.Vector3(0, 0, 1));
|
||||
if (tangent.lengthSq() < 1e-6) {
|
||||
tangent.set(1, 0, 0);
|
||||
}
|
||||
tangent.normalize();
|
||||
const bitangent = new THREE.Vector3().crossVectors(planeNormal, tangent).normalize();
|
||||
|
||||
for (let index = 0; index < 8; index += 1) {
|
||||
const angle = (index / 8) * Math.PI * 2;
|
||||
const direction = tangent.clone().multiplyScalar(Math.cos(angle)).add(bitangent.clone().multiplyScalar(Math.sin(angle)));
|
||||
const sprite = new THREE.Sprite(new THREE.SpriteMaterial({
|
||||
map: texture,
|
||||
transparent: true,
|
||||
opacity: index % 2 === 0 ? 0.22 : 0.15,
|
||||
depthWrite: false,
|
||||
blending: THREE.AdditiveBlending,
|
||||
color: index % 3 === 0 ? "#ffd3f1" : index % 3 === 1 ? "#c8d8ff" : "#ffffff",
|
||||
fog: false,
|
||||
}));
|
||||
sprite.position.copy(direction.multiplyScalar(radius));
|
||||
sprite.scale.set(16500, 4300 + (index % 3) * 800, 1);
|
||||
sprite.material.rotation = angle + Math.PI / 2;
|
||||
root.add(sprite);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
export function createTacticalIcon(documentRef: Document, color: string, size: number): SceneNode {
|
||||
const canvas = documentRef.createElement("canvas");
|
||||
canvas.width = 64;
|
||||
@@ -657,6 +568,38 @@ export function createTacticalIcon(documentRef: Document, color: string, size: n
|
||||
return createSceneNode(sprite);
|
||||
}
|
||||
|
||||
export function createShipTacticalIcon(documentRef: Document, color: string, size: number): SceneNode {
|
||||
const canvas = documentRef.createElement("canvas");
|
||||
canvas.width = 128;
|
||||
canvas.height = 96;
|
||||
const context = canvas.getContext("2d");
|
||||
if (!context) {
|
||||
throw new Error("Unable to create ship tactical icon");
|
||||
}
|
||||
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
context.strokeStyle = color;
|
||||
context.fillStyle = "rgba(7, 16, 30, 0.7)";
|
||||
context.lineWidth = 5;
|
||||
|
||||
context.beginPath();
|
||||
context.arc(34, 48, 18, 0, Math.PI * 2);
|
||||
context.stroke();
|
||||
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
const sprite = new THREE.Sprite(new THREE.SpriteMaterial({
|
||||
map: texture,
|
||||
transparent: true,
|
||||
depthWrite: false,
|
||||
depthTest: false,
|
||||
color: "#ffffff",
|
||||
}));
|
||||
sprite.center.set(0.28, 0.5);
|
||||
sprite.scale.set(size * 1.7, size * 1.275, 1);
|
||||
sprite.visible = false;
|
||||
return createSceneNode(sprite);
|
||||
}
|
||||
|
||||
|
||||
export function createStarDot(documentRef: Document, color: string): SceneNode {
|
||||
const canvas = documentRef.createElement("canvas");
|
||||
|
||||
Reference in New Issue
Block a user