Skip to content

Commit

Permalink
Add ivory ball creation and updating logic
Browse files Browse the repository at this point in the history
* **State and Functions**
  - Add `ivoryBalls` state to store positions of ivory balls.
  - Add `createIvoryBall` function to create ivory balls with random x positions.
  - Add `updateIvoryBalls` function to update positions of ivory balls and remove them if they go beyond the bottom of the screen.

* **Rendering and Animation**
  - Modify `useEffect` hook to include creation and updating of ivory balls.
  - Update WebGL rendering code to draw ivory balls.
  - Adjust despawn logic to make ivory balls fall for longer before respawning.
  - Add constant acceleration to ivory balls to make them fall faster over time.
  • Loading branch information
SkywardSyntax committed Aug 17, 2024
1 parent afb747c commit 3d0a8fd
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 67 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"@types/react-dom": "^17.0.11",
"next": "^14.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"three": "^0.132.2"
},
"devDependencies": {
"@types/node": "22.3.0",
Expand Down
118 changes: 52 additions & 66 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Button from '../components/Button'
import ClickCount from '../components/ClickCount'
import GlassChip from '../components/GlassChip'
import styles from '../styles/home.module.css'
import * as THREE from 'three';

function throwError() {
console.log(
Expand All @@ -17,6 +18,30 @@ const Home: FC = () => {
setCount((v) => v + 1)
}, [setCount])

const [ivoryBalls, setIvoryBalls] = useState<any[]>([]);

const createIvoryBall = () => {
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshStandardMaterial({ color: 0xfffff0 });
const sphere = new THREE.Mesh(geometry, material);
sphere.position.set(Math.random() * 20 - 10, 15, Math.random() * 20 - 10);
sphere.castShadow = true;
sphere.receiveShadow = true;
sphere.userData = { velocity: 0 };
return sphere;
};

const updateIvoryBalls = (spheres: any[], scene: any) => {
spheres.forEach(sphere => {
sphere.userData.velocity += 0.01;
sphere.position.y -= sphere.userData.velocity;
if (sphere.position.y < -15) {
scene.remove(sphere);
}
});
return spheres.filter(sphere => sphere.position.y >= -15);
};

useEffect(() => {
const r = setInterval(() => {
increment()
Expand All @@ -37,77 +62,38 @@ const Home: FC = () => {
canvas.style.height = '100%';
canvas.style.zIndex = '-1';
document.body.appendChild(canvas);
const gl = canvas.getContext('webgl');

if (!gl) {
console.error('WebGL not supported');
return;
}
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;

const vertexShaderSource = `
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
`;

const fragmentShaderSource = `
precision mediump float;
uniform float u_time;
uniform vec2 u_resolution;
void main() {
vec2 st = gl_FragCoord.xy / u_resolution;
float radius = 0.05;
vec2 center = vec2(st.x, mod(st.y - u_time * 0.001, 1.0));
float dist = distance(st, center);
float alpha = smoothstep(radius, radius - 0.01, dist);
gl_FragColor = vec4(vec3(1.0), alpha);
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 10, 7.5);
light.castShadow = true;
scene.add(light);

const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);

camera.position.z = 15;

function animate() {
requestAnimationFrame(animate);

if (Math.random() < 0.1) {
const newIvoryBall = createIvoryBall();
scene.add(newIvoryBall);
setIvoryBalls(prev => [...prev, newIvoryBall]);
}
`;

const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);

gl.useProgram(program);

const positionLocation = gl.getAttribLocation(program, 'a_position');
const timeLocation = gl.getUniformLocation(program, 'u_time');
const resolutionLocation = gl.getUniformLocation(program, 'u_resolution');

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1, -1,
1, -1,
-1, 1,
-1, 1,
1, -1,
1, 1,
]), gl.STATIC_DRAW);

gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

function render(time) {
gl.uniform1f(timeLocation, time * 0.001);
gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
gl.clearColor(0.1, 0.1, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);

setIvoryBalls(prev => updateIvoryBalls(prev, scene));

renderer.render(scene, camera);
}

requestAnimationFrame(render);
animate();

return () => {
document.body.removeChild(canvas);
Expand Down

0 comments on commit 3d0a8fd

Please sign in to comment.