File size: 6,317 Bytes
e30257d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Import Three.js library (already included in index.html)
// const THREE = window.THREE;

class Background {
    constructor() {
        // Initialize core Three.js components
        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(
            75, // Field of view
            window.innerWidth / window.innerHeight, // Aspect ratio
            0.1, // Near plane
            1000 // Far plane
        );
        
        // Setup renderer with transparency and anti-aliasing
        this.renderer = new THREE.WebGLRenderer({
            canvas: document.querySelector('#webgl-background'),
            alpha: true,
            antialias: true
        });
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.renderer.setClearColor(0x0a0a0a, 1); // Dark background color

        // Initialize particle system properties
        this.particles = [];
        this.particleCount = 100;
        this.particleGeometry = new THREE.BufferGeometry();
        this.particleMaterial = new THREE.PointsMaterial({
            size: 2,
            color: 0xffffff,
            transparent: true,
            opacity: 0.5,
            blending: THREE.AdditiveBlending
        });

        // Set up camera position
        this.camera.position.z = 100;

        // Initialize the background
        this.init();

        // Bind event listeners
        this.bindEvents();
    }

    init() {
        // Create particle positions array
        const positions = new Float32Array(this.particleCount * 3);
        
        // Generate random positions for particles
        for (let i = 0; i < this.particleCount; i++) {
            const i3 = i * 3; // Index for x, y, z coordinates
            positions[i3] = (Math.random() - 0.5) * window.innerWidth;     // X coordinate
            positions[i3 + 1] = (Math.random() - 0.5) * window.innerHeight; // Y coordinate
            positions[i3 + 2] = (Math.random() - 0.5) * 500;               // Z coordinate
            
            // Store particle data for animation
            this.particles.push({
                velocity: (Math.random() - 0.5) * 0.2,
                baseX: positions[i3],
                baseY: positions[i3 + 1]
            });
        }

        // Set particle positions in geometry
        this.particleGeometry.setAttribute(
            'position',
            new THREE.BufferAttribute(positions, 3)
        );

        // Create particle system and add to scene
        this.particleSystem = new THREE.Points(
            this.particleGeometry,
            this.particleMaterial
        );
        this.scene.add(this.particleSystem);

        // Start animation loop
        this.animate();
    }

    // Handle window resize events
    bindEvents() {
        window.addEventListener('resize', () => {
            // Update camera aspect ratio and projection matrix
            this.camera.aspect = window.innerWidth / window.innerHeight;
            this.camera.updateProjectionMatrix();
            
            // Update renderer size
            this.renderer.setSize(window.innerWidth, window.innerHeight);
        });
    }

    // Animation loop for particle movement
    animate() {
        requestAnimationFrame(() => this.animate());

        const positions = this.particleGeometry.attributes.position.array;
        const time = Date.now() * 0.0005;

        // Update particle positions with wave-like motion
        for (let i = 0; i < this.particleCount; i++) {
            const i3 = i * 3;
            const particle = this.particles[i];

            // Create wave-like motion using sine waves
            positions[i3] = particle.baseX + Math.sin(time + i) * 2;
            positions[i3 + 1] = particle.baseY + Math.cos(time + i) * 2;
            
            // Add slight drift to z-position
            positions[i3 + 2] += particle.velocity;

            // Reset particles that drift too far
            if (Math.abs(positions[i3 + 2]) > 250) {
                positions[i3 + 2] = -250;
            }
        }

        // Mark particle positions for update
        this.particleGeometry.attributes.position.needsUpdate = true;

        // Add subtle camera movement
        this.camera.position.x = Math.sin(time) * 10;
        this.camera.position.y = Math.cos(time) * 10;
        this.camera.lookAt(this.scene.position);

        // Render the scene
        this.renderer.render(this.scene, this.camera);
    }

    // Method to add dramatic effects during game events
    addDramaticEffect(type) {
        switch(type) {
            case 'impostor_reveal':
                // Create a dramatic red flash effect
                this.particleMaterial.color.setHex(0xff0000);
                setTimeout(() => {
                    this.particleMaterial.color.setHex(0xffffff);
                }, 1000);
                break;
            
            case 'round_start':
                // Increase particle movement temporarily
                const originalVelocities = this.particles.map(p => p.velocity);
                this.particles.forEach(p => p.velocity *= 2);
                setTimeout(() => {
                    this.particles.forEach((p, i) => p.velocity = originalVelocities[i]);
                }, 2000);
                break;
            
            case 'voting':
                // Create a pulsing effect
                const pulseAnimation = () => {
                    this.particleMaterial.size = 2 + Math.sin(Date.now() * 0.005) * 1;
                };
                const pulseInterval = setInterval(pulseAnimation, 16);
                setTimeout(() => {
                    clearInterval(pulseInterval);
                    this.particleMaterial.size = 2;
                }, 3000);
                break;
        }
    }
}

// Initialize the background when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    const background = new Background();

    // Expose background instance for game events
    window.gameBackground = background;
});

// Export the Background class for potential module usage
export default Background;