I’m looking for a person who will help refine the code that displays the stars.
I recently saw the factorio update and their website – https://factorio.com/galaxy. I was interested in the concept of stars, namely how they are arranged. I tried to make similar stars myself, but it didn’t work out. I tried to use ChatGPT, but it doesn’t give out the right or poignant questions.
galaxy
Here is one example, as we see in the middle we have a square and the star itself is made using a square and highlights. I didn’t have any problems with the first one for rendering, but it doesn’t work very well with the second one. It is not entirely clear how to draw further.
import { useEffect, useRef, useState } from "react";
import Head from "next/head";
import styles from './star.module.css';
import starImage5 from '../public/star/5.png';
import starImage4 from '../public/star/4.png';
import starImage3 from '../public/star/3.png';
import starImage2 from '../public/star/2.png';
import starImage1 from '../public/star/1.png';
const generateRandomCoordinates = (numStars, offsetRange) => {
const coordinates = [];
const positions = [];
for (let i = 0; i < numStars; i++) {
const x = Math.random() * (offsetRange * 2) - offsetRange;
const y = Math.random() * (offsetRange * 2) - offsetRange;
coordinates.push(x);
positions.push(y);
}
return { coordinates, positions };
};
export default function Home() {
const canvasRef = useRef(null);
const [offset, setOffset] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const [lastMousePosition, setLastMousePosition] = useState({ x: 0, y: 0 });
const starData = {
colors: [...Array(100).keys()].map(() => Math.floor(Math.random() * 16777215)),
ids: [...Array(100).keys()].map(() => Math.floor(Math.random() * 1000000000)),
names: [...Array(100).keys()].map((_, i) => `Star ${i + 1}`),
};
const { coordinates, positions } = generateRandomCoordinates(100, 200);
useEffect(() => {
const images = [starImage1, starImage2, starImage3, starImage4, starImage5].map(src => {
const img = new Image();
img.src = src.src;
return img;
});
Promise.all(images.map(img => new Promise(resolve => img.onload = resolve)))
.then(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.imageSmoothingEnabled = false;
const drawStars = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const numStars = Math.min(starData.colors.length, coordinates.length, positions.length);
for (let index = 0; index < numStars; index++) {
const x = coordinates[index];
const y = positions[index];
const color = `#${starData.colors[index].toString(16).padStart(6, '0')}`;
const starX = x + offset.x + canvas.width / 2;
const starY = y + offset.y + canvas.height / 2;
const randomStarIndex = Math.floor(Math.random() * images.length);
const starImage = images[randomStarIndex];
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = starImage.width;
tempCanvas.height = starImage.height;
tempCtx.drawImage(starImage, 0, 0);
tempCtx.globalCompositeOperation = 'source-in';
tempCtx.fillStyle = color;
tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
const starSize = 16;
ctx.drawImage(tempCanvas, starX - starSize / 2, starY - starSize / 2, starSize, starSize);
}
};
drawStars();
const handleMouseMove = (event) => {
if (isDragging) {
const dx = event.clientX - lastMousePosition.x;
const dy = event.clientY - lastMousePosition.y;
setOffset(prev => ({
x: prev.x + dx,
y: prev.y + dy,
}));
setLastMousePosition({ x: event.clientX, y: event.clientY });
drawStars(); // Переотрисовываем звезды
}
};
const handleMouseDown = (event) => {
setIsDragging(true);
setLastMousePosition({ x: event.clientX, y: event.clientY });
};
const handleMouseUp = () => {
setIsDragging(false);
};
canvas.addEventListener("mousemove", handleMouseMove);
canvas.addEventListener("mousedown", handleMouseDown);
canvas.addEventListener("mouseup", handleMouseUp);
canvas.addEventListener("mouseleave", handleMouseUp);
return () => {
canvas.removeEventListener("mousemove", handleMouseMove);
canvas.removeEventListener("mousedown", handleMouseDown);
canvas.removeEventListener("mouseup", handleMouseUp);
canvas.removeEventListener("mouseleave", handleMouseUp);
};
});
}, [offset.x, offset.y]);
return (
<>
<div className={styles.imageContainer}>
<canvas ref={canvasRef} className={styles.pixelCanvas} />
</div>
</>
);
}
The developers themselves did it using Three.js
I tried to create highlights by applying layers on top, it didn’t work out very well
entersource code of the star
I also noticed the source code of the star on the site, through the developer console (Network)