import { useRef, useMemo } from 'react';
import { useFrame } from '@react-three/fiber';
import { SpotLight, Text } from '@react-three/drei';
import * as THREE from 'three';
function DanceFloor() {
return (
);
}
function Balloons() {
const balloons = useMemo(() => {
const positions = [];
for (let i = 0; i < 15; i++) {
positions.push([
(Math.random() - 0.5) * 25,
2 + Math.random() * 8,
(Math.random() - 0.5) * 25
]);
}
return positions;
}, []);
return (
<>
{balloons.map((pos, i) => (
))}
>
);
}
function Confetti() {
const confettiRef = useRef();
const count = 250;
const positions = useMemo(() => {
const pos = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i += 3) {
pos[i] = (Math.random() - 0.5) * 30;
pos[i + 1] = Math.random() * 15;
pos[i + 2] = (Math.random() - 0.5) * 30;
}
return pos;
}, []);
const colors = useMemo(() => {
const cols = new Float32Array(count * 3);
const colorArray = [
[1, 0, 0], [0, 1, 0], [0, 0, 1],
[1, 1, 0], [1, 0, 1], [0, 1, 1]
];
for (let i = 0; i < count; i++) {
const color = colorArray[Math.floor(Math.random() * colorArray.length)];
cols[i * 3] = color[0];
cols[i * 3 + 1] = color[1];
cols[i * 3 + 2] = color[2];
}
return cols;
}, []);
useFrame((state) => {
if (confettiRef.current) {
confettiRef.current.rotation.y += 0.001;
const positions = confettiRef.current.geometry.attributes.position.array;
for (let i = 1; i < positions.length; i += 3) {
positions[i] -= 0.01;
if (positions[i] < 0) {
positions[i] = 15;
}
}
confettiRef.current.geometry.attributes.position.needsUpdate = true;
}
});
return (
);
}
function Person({ position, index, lookAt }) {
const groupRef = useRef();
const leftArmRef = useRef();
const rightArmRef = useRef();
// Randomize skin tones
const skinTones = ['#ffdbac', '#f1c27d', '#e0ac69', '#c68642', '#8d5524'];
const skinColor = skinTones[index % skinTones.length];
// More color variety for shirts
const shirtColors = [
'#ff6b6b', '#4ecdc4', '#45b7d1', '#f9ca24', '#6c5ce7',
'#a29bfe', '#fd79a8', '#00b894', '#e17055', '#74b9ff',
'#a29bfe', '#fd79a8', '#fdcb6e', '#e84393', '#00cec9'
];
const shirtColor = shirtColors[index % shirtColors.length];
useFrame(() => {
if (groupRef.current && lookAt) {
// Face the person they're talking to
const dx = lookAt[0] - position[0];
const dz = lookAt[2] - position[2];
groupRef.current.rotation.y = Math.atan2(dx, dz);
// Subtle idle animation - slight head/body movement
const t = Date.now() * 0.005;
const offset = index * 0.3;
groupRef.current.rotation.y += Math.sin(t * 0.05 + offset) * 0.05;
// Subtle arm gestures while talking
if (leftArmRef.current) {
leftArmRef.current.rotation.x = Math.sin(t * 1.7 + offset) * 0.1;
leftArmRef.current.rotation.z = Math.sin(t * 1.5 + offset) * 0.05;
}
if (rightArmRef.current) {
rightArmRef.current.rotation.x = Math.sin(t * 1.5 + offset + 1) * 0.1;
rightArmRef.current.rotation.z = Math.sin(t * 1.5 + offset + 1) * 0.05;
}
}
});
return (
{/* Head */}
{/* Torso */}
{/* Left Arm */}
{/* Right Arm */}
{/* Left Leg - standing still */}
{/* Right Leg - standing still */}
);
}
function People() {
// Create groups of people talking to each other - 80 total people
const groups = useMemo(() => {
const peopleGroups = [];
const groupCount = 180; // 30 groups
for (let g = 0; g < groupCount; g++) {
const groupAngle = (g / groupCount) * Math.PI * 3;
const groupRadius = 2 + Math.random() * 10; // Spread around the room
const groupCenter = [
Math.cos(groupAngle) * groupRadius,
0,
Math.sin(groupAngle) * groupRadius
];
// Vary group sizes to get close to 80 total (mostly groups of 3, some 2)
const peopleInGroup = g < 25 ? 3 : 2;
const group = [];
for (let p = 0; p < peopleInGroup; p++) {
const personAngle = (p / peopleInGroup) * Math.PI * 2;
const personRadius = 0.8;
const personPos = [
groupCenter[0] + Math.cos(personAngle) * personRadius,
0,
groupCenter[2] + Math.sin(personAngle) * personRadius
];
// Person they're looking at (next person in circle, or center)
const lookAtIndex = (p + 1) % peopleInGroup;
const lookAtPos = [
groupCenter[0] + Math.cos((lookAtIndex / peopleInGroup) * Math.PI * 2) * personRadius,
0,
groupCenter[2] + Math.sin((lookAtIndex / peopleInGroup) * Math.PI * 2) * personRadius
];
group.push({ position: personPos, lookAt: lookAtPos });
}
peopleGroups.push(...group);
}
return peopleGroups;
}, []);
return (
<>
{groups.map((person, i) => (
))}
>
);
}
function YouTubeBanner() {
// Create triangle geometry for play button
const triangleShape = useMemo(() => {
const shape = new THREE.Shape();
shape.moveTo(0, 0.4);
shape.lineTo(0.7, 0);
shape.lineTo(0, -0.4);
shape.lineTo(0, 0.4);
return shape;
}, []);
return (
{/* Red background */}
{/* White play button triangle */}
{/* YouTube text */}
YouTube
);
}
function DJ() {
const groupRef = useRef();
const leftArmRef = useRef();
const rightArmRef = useRef();
useFrame((state) => {
if (groupRef.current) {
const t = state.clock.elapsedTime;
// Subtle head bobbing to the beat
groupRef.current.position.y = Math.sin(t * 2) * 0.05;
// Arm movements - mixing/scratching
if (leftArmRef.current) {
leftArmRef.current.rotation.x = Math.sin(t * 3) * 0.2;
leftArmRef.current.rotation.z = Math.sin(t * 3) * 0.1;
}
if (rightArmRef.current) {
rightArmRef.current.rotation.x = Math.sin(t * 3 + 1) * 0.2;
rightArmRef.current.rotation.z = Math.sin(t * 3 + 1) * 0.1;
}
}
});
return (
{/* Head */}
{/* Headphones */}
{/* Torso */}
{/* Left Arm */}
{/* Right Arm */}
{/* Legs */}
{/* Shoes */}
);
}
function DJBooth() {
return (
{/* Bar base - larger and more prominent */}
{/* Bar top */}
{/* DJ equipment section - raised */}
{/* Equipment panel */}
{/* Control buttons - more prominent */}
{/* Bar stools */}
{/* Banner hanging from above - bigger and more prominent */}
{/* YouTube logo banner background */}
{/* Banner text - bigger */}
1 MILLION SUBSCRIBERS
{/* Rope/string to hang it */}
{/* Spotlight on the bar */}
);
}
function DJBoothSpotlight() {
const spotlightRef = useRef();
const targetRef = useRef();
useFrame(() => {
if (spotlightRef.current && targetRef.current) {
spotlightRef.current.target = targetRef.current;
}
});
return (
);
}
function Speakers() {
return (
<>
>
);
}
function ThePrimeagen() {
const groupRef = useRef();
const leftArmRef = useRef();
const rightArmRef = useRef();
useFrame((state) => {
if (groupRef.current) {
const t = state.clock.elapsedTime;
// Subtle animation
groupRef.current.rotation.y = Math.sin(t * 0.5) * 0.1;
if (leftArmRef.current) {
leftArmRef.current.rotation.x = Math.sin(t * 2) * 0.2;
}
if (rightArmRef.current) {
rightArmRef.current.rotation.x = -Math.sin(t * 2) * 0.2;
}
}
});
return (
{/* Head */}
{/* Beard */}
{/* Glasses */}
{/* Bridge */}
{/* Hoodie */}
{/* Hood */}
{/* Left Arm */}
{/* Right Arm */}
{/* Legs */}
{/* Shoes */}
);
}
function Scene() {
const spot1Ref = useRef();
const spot2Ref = useRef();
const spot3Ref = useRef();
const spot4Ref = useRef();
const spot5Ref = useRef();
useFrame((state) => {
const t = state.clock.elapsedTime;
if (spot1Ref.current) {
const phase = t * 0.6;
spot1Ref.current.target.position.x = Math.cos(phase) * 3;
spot1Ref.current.target.position.z = Math.sin(phase) * 3;
spot1Ref.current.target.position.y = 2.5 + Math.sin(t * 1.2) * 0.5;
}
if (spot2Ref.current) {
const phase = t * 0.6 + (Math.PI * 2 / 5);
spot2Ref.current.target.position.x = Math.cos(phase) * 3;
spot2Ref.current.target.position.z = Math.sin(phase) * 3;
spot2Ref.current.target.position.y = 2.5 + Math.sin(t * 1.2) * 0.5;
}
if (spot3Ref.current) {
const phase = t * 0.6 + (Math.PI * 4 / 5);
spot3Ref.current.target.position.x = Math.cos(phase) * 3;
spot3Ref.current.target.position.z = Math.sin(phase) * 3;
spot3Ref.current.target.position.y = 2.5 + Math.sin(t * 1.2) * 0.5;
}
if (spot4Ref.current) {
const phase = t * 0.6 + (Math.PI * 6 / 5);
spot4Ref.current.target.position.x = Math.cos(phase) * 3;
spot4Ref.current.target.position.z = Math.sin(phase) * 3;
spot4Ref.current.target.position.y = 2.5 + Math.sin(t * 1.2) * 0.5;
}
if (spot5Ref.current) {
const phase = t * 0.6 + (Math.PI * 8 / 5);
spot5Ref.current.target.position.x = Math.cos(phase) * 3;
spot5Ref.current.target.position.z = Math.sin(phase) * 3;
spot5Ref.current.target.position.y = 2.5 + Math.sin(t * 1.2) * 0.5;
}
});
return (
<>
>
);
}
export default Scene;