File size: 9,665 Bytes
8035141
 
 
 
 
985632d
8035141
 
 
85be50c
8035141
85be50c
 
8035141
985632d
 
 
 
 
 
 
 
 
 
8a3c54c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242cb26
 
 
 
 
 
 
 
 
 
8035141
 
 
985632d
 
 
8a3c54c
 
 
242cb26
 
 
 
985632d
85be50c
 
 
 
 
 
 
 
 
242cb26
 
 
 
 
 
985632d
 
85be50c
 
 
 
 
 
 
8035141
8a3c54c
 
 
985632d
 
 
 
8a3c54c
 
 
 
 
 
 
 
 
 
 
 
 
 
985632d
85be50c
 
 
 
 
 
 
 
 
 
985632d
 
8a3c54c
985632d
 
 
 
 
 
 
8a3c54c
 
242cb26
 
 
 
8a3c54c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985632d
85be50c
 
8035141
85be50c
 
 
 
985632d
 
 
85be50c
985632d
 
 
 
 
 
 
85be50c
985632d
 
85be50c
8035141
985632d
8035141
985632d
 
 
 
 
 
 
 
 
 
8035141
985632d
 
 
 
242cb26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8035141
985632d
242cb26
985632d
85be50c
242cb26
985632d
85be50c
985632d
8035141
 
242cb26
 
 
 
 
 
 
 
 
 
 
 
85be50c
985632d
85be50c
 
 
 
 
985632d
85be50c
 
 
 
8035141
 
85be50c
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Harmonies Game 3D - Dynamic Simulation</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
        canvas {
            display: block;
        }
        .hud {
            position: absolute;
            top: 10px;
            left: 10px;
            background: rgba(0, 0, 0, 0.5);
            color: white;
            padding: 10px;
            border-radius: 5px;
            font-family: Arial, sans-serif;
        }
        .sidebar {
            position: absolute;
            top: 0;
            right: 0;
            width: 200px;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 10px;
            overflow-y: auto;
            font-family: Arial, sans-serif;
        }
        .character {
            margin-bottom: 10px;
            padding: 5px;
            border: 1px solid white;
            border-radius: 5px;
        }
        .timer {
            position: absolute;
            top: 10px;
            right: 10px;
            background: rgba(0, 0, 0, 0.5);
            color: white;
            padding: 10px;
            border-radius: 5px;
            font-family: Arial, sans-serif;
        }
    </style>
</head>
<body>
    <div class="hud" id="hud">
        <p>Current Type: <span id="currentType">Swan 🦢</span></p>
    </div>
    <div class="sidebar" id="sidebar">
        <h3>Population Stats</h3>
    </div>
    <div class="timer" id="timer">
        <p>Simulation Time: <span id="simulationTime">0</span> seconds</p>
        <p>Epoch: <span id="epoch">1</span></p>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
    <script>
        // Initialize scene, camera, and renderer
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // Timer variables
        let simulationTime = 0;
        let epoch = 1;
        const timerElement = document.getElementById('simulationTime');
        const epochElement = document.getElementById('epoch');

        // Game board parameters
        const boardSize = 50; // Gigantic board
        const tileSize = 1;
        const tiles = [];
        const tileTypes = [
            { type: 'water', color: 0x87ceeb },
            { type: 'forest', color: 0x228b22 },
            { type: 'grass', color: 0x98fb98 }
        ];

        // Sidebar for stats
        const sidebar = document.getElementById('sidebar');

        // Particle system for motion simulation
        const particleSystem = new THREE.Group();
        scene.add(particleSystem);

        // Generate random character stats
        function generateCharacter() {
            const names = ["Swift Feather", "Bold Antler", "Mighty Claw", "Gentle Leaf", "Shadow Pelt"];
            return {
                name: names[Math.floor(Math.random() * names.length)],
                attack: Math.floor(Math.random() * 10) + 1,
                hitPoints: Math.floor(Math.random() * 50) + 10,
                strength: Math.floor(Math.random() * 10) + 1,
                intelligence: Math.floor(Math.random() * 10) + 1,
                wisdom: Math.floor(Math.random() * 10) + 1,
                charisma: Math.floor(Math.random() * 10) + 1,
            };
        }

        // Create tiles and particles
        for (let x = 0; x < boardSize; x++) {
            for (let z = 0; z < boardSize; z++) {
                const tileType = tileTypes[Math.floor(Math.random() * tileTypes.length)];
                const geometry = new THREE.BoxGeometry(tileSize, 0.1, tileSize);
                const material = new THREE.MeshBasicMaterial({ color: tileType.color });
                const tile = new THREE.Mesh(geometry, material);
                tile.position.set(x - boardSize / 2, 0, z - boardSize / 2);
                tile.userData = { type: tileType.type, occupied: false };
                scene.add(tile);
                tiles.push(tile);

                // Add particles for motion simulation
                const particleGeometry = new THREE.SphereGeometry(0.2, 16, 16);
                const particleMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
                const particle = new THREE.Mesh(particleGeometry, particleMaterial);
                particle.position.set(
                    x - boardSize / 2 + Math.random(),
                    0.2,
                    z - boardSize / 2 + Math.random()
                );
                particle.userData = {
                    direction: new THREE.Vector3(Math.random(), 0, Math.random()).normalize(),
                    rotation: new THREE.Vector3(0, Math.random() * 2 * Math.PI, 0),
                    accelerate: Math.random() * 0.05 + 0.01,
                    brake: 0.02,
                    reverse: -0.02,
                    stats: generateCharacter(),
                };

                // Add stats to the sidebar
                const characterDiv = document.createElement('div');
                characterDiv.className = 'character';
                characterDiv.innerHTML = `
                    <strong>${particle.userData.stats.name}</strong><br>
                    Attack: ${particle.userData.stats.attack}<br>
                    HP: ${particle.userData.stats.hitPoints}<br>
                    Strength: ${particle.userData.stats.strength}<br>
                    Intelligence: ${particle.userData.stats.intelligence}<br>
                    Wisdom: ${particle.userData.stats.wisdom}<br>
                    Charisma: ${particle.userData.stats.charisma}<br>
                `;
                sidebar.appendChild(characterDiv);

                particleSystem.add(particle);
            }
        }

        // Add light
        const light = new THREE.AmbientLight(0xffffff, 0.8);
        scene.add(light);

        // HUD for displaying the current type
        const hud = document.getElementById('hud');
        const currentTypeDisplay = document.getElementById('currentType');

        // Current type with emoji
        const animalTypes = [
            { name: 'Swan', emoji: '🦢' },
            { name: 'Deer', emoji: '🦌' },
            { name: 'Bear', emoji: '🐻' }
        ];
        let currentTypeIndex = 0;

        function updateCurrentType() {
            currentTypeDisplay.textContent = `${animalTypes[currentTypeIndex].name} ${animalTypes[currentTypeIndex].emoji}`;
        }

        updateCurrentType();

        // Handle key presses to switch types
        window.addEventListener('keydown', (event) => {
            if (event.key === 'ArrowRight') {
                currentTypeIndex = (currentTypeIndex + 1) % animalTypes.length;
                updateCurrentType();
            } else if (event.key === 'ArrowLeft') {
                currentTypeIndex = (currentTypeIndex - 1 + animalTypes.length) % animalTypes.length;
                updateCurrentType();
            }
        });

        // Particle motion simulation
        function updateParticles() {
            particleSystem.children.forEach(particle => {
                const direction = particle.userData.direction;
                const position = particle.position;

                // Move particle
                position.add(direction.multiplyScalar(particle.userData.accelerate));

                // Detect collisions and adjust behavior
                particleSystem.children.forEach(otherParticle => {
                    if (particle !== otherParticle) {
                        const distance = position.distanceTo(otherParticle.position);
                        if (distance < 0.5) {
                            // Reverse direction on collision
                            direction.negate();
                            particle.userData.accelerate = particle.userData.reverse;
                        }
                    }
                });

                // Gradually brake
                if (particle.userData.accelerate > 0) {
                    particle.userData.accelerate -= particle.userData.brake;
                    if (particle.userData.accelerate < 0) {
                        particle.userData.accelerate = 0;
                    }
                }

                // Bounce off edges of the board
                if (position.x < -boardSize / 2 || position.x > boardSize / 2) {
                    direction.x = -direction.x;
                }
                if (position.z < -boardSize / 2 || position.z > boardSize / 2) {
                    direction.z = -direction.z;
                }
            });
        }

        // Timer update function
        function updateTimer() {
            simulationTime++;
            timerElement.textContent = simulationTime;
            if (simulationTime % 10 === 0) {
                epoch++;
                epochElement.textContent = epoch;
            }
        }

        setInterval(updateTimer, 1000);

        // Set camera position
        camera.position.set(0, 50, 50);
        camera.lookAt(0, 0, 0);

        // Animation loop
        function animate() {
            requestAnimationFrame(animate);
            updateParticles();
            renderer.render(scene, camera);
        }

        animate();
    </script>
</body>
</html>