ewebspace commited on
Commit
bb25ccb
Β·
verified Β·
1 Parent(s): f0555aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +492 -113
app.py CHANGED
@@ -1,104 +1,431 @@
1
  import gradio as gr
2
  import numpy as np
3
  import json
 
 
4
 
5
- # Three.js template with proper escaping
 
6
  <!DOCTYPE html>
7
  <html>
8
  <head>
9
- <title>Webspace Network 3D</title>
10
  <style>
11
- body { margin: 0; overflow: hidden; }
 
 
 
 
12
  canvas { display: block; }
13
- #info {
14
- position: absolute;
15
- top: 10px;
16
- left: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  color: white;
18
- background: rgba(0,0,0,0.5);
19
- padding: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
  </style>
22
  </head>
23
  <body>
24
- <div id="info">Click on planets to see details</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
26
  <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
27
 
28
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  // Scene setup
30
  const scene = new THREE.Scene();
 
 
 
31
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
 
 
 
32
  const renderer = new THREE.WebGLRenderer({ antialias: true });
33
  renderer.setSize(window.innerWidth, window.innerHeight);
34
  document.body.appendChild(renderer.domElement);
35
 
36
- // Universe data
37
- const universeData = %s;
 
38
 
39
- // Create star system
40
- function createSystem(systemData) {
41
- // Create star
42
- const starGeometry = new THREE.SphereGeometry(2, 32, 32);
43
- const starMaterial = new THREE.MeshBasicMaterial({
44
- color: new THREE.Color(...systemData.star_color),
45
- emissive: new THREE.Color(...systemData.star_color).multiplyScalar(0.5)
46
- });
47
- const star = new THREE.Mesh(starGeometry, starMaterial);
48
- scene.add(star);
49
-
50
- // Create planets
51
- systemData.planets.forEach((planet, i) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  const planetGeometry = new THREE.SphereGeometry(planet.size, 32, 32);
 
 
 
 
 
 
 
 
 
 
 
 
53
  const planetMaterial = new THREE.MeshStandardMaterial({
54
- color: new THREE.Color(...planet.color),
55
  roughness: 0.8,
56
  metalness: 0.2
57
  });
 
58
  const planetMesh = new THREE.Mesh(planetGeometry, planetMaterial);
59
 
60
  // Position in orbit
61
- const orbitRadius = 5 + (i * 3);
62
- planetMesh.position.x = orbitRadius;
 
 
 
 
 
 
63
  planetMesh.userData = planet;
 
 
64
 
65
- // Make planets clickable
66
  planetMesh.addEventListener('click', (event) => {
67
- window.parent.postMessage({
68
- type: 'planetSelected',
69
- data: event.target.userData
70
- }, '*');
 
 
71
  event.stopPropagation();
72
  });
73
-
74
- // Create orbit path
75
- const orbit = new THREE.Line(
76
- new THREE.BufferGeometry().setFromPoints(
77
- new THREE.EllipseCurve(0, 0, orbitRadius, orbitRadius, 0, Math.PI * 2, false).getPoints(100)
78
- ),
79
- new THREE.LineBasicMaterial({ color: 0x888888 })
80
- );
81
- orbit.rotation.x = Math.PI / 2;
82
-
83
- scene.add(planetMesh);
84
- scene.add(orbit);
85
  });
86
  }
87
 
88
- // Initialize first system
89
- createSystem(universeData.systems[0]);
90
 
91
  // Camera controls
92
  const controls = new THREE.OrbitControls(camera, renderer.domElement);
93
- camera.position.set(0, 20, 30);
94
- controls.update();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
  // Animation loop
97
  function animate() {
98
  requestAnimationFrame(animate);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  controls.update();
100
  renderer.render(scene, camera);
101
  }
 
102
  animate();
103
 
104
  // Handle window resize
@@ -110,98 +437,150 @@ import json
110
  </script>
111
  </body>
112
  </html>
 
113
 
114
- class UniverseGenerator:
115
  def __init__(self, seed=42):
116
  self.rng = np.random.RandomState(seed)
117
- self.star_types = {
118
- 'O': {'color': [0.7, 0.8, 1.0], 'temp': 30000},
119
- 'B': {'color': [0.8, 0.9, 1.0], 'temp': 20000},
120
- 'G': {'color': [1.0, 0.93, 0.7], 'temp': 5700}
121
- }
122
  self.planet_types = [
123
- {'name': 'Lava', 'color': [0.8, 0.3, 0.1]},
124
- {'name': 'Ocean', 'color': [0.1, 0.3, 0.8]},
125
- {'name': 'Desert', 'color': [0.9, 0.8, 0.5]}
 
 
126
  ]
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  def generate_system(self, index):
129
- star_class = self.rng.choice(list(self.star_types.keys()))
130
- system = {
131
- 'name': f"{star_class}-{index}",
132
- 'star_color': self.star_types[star_class]['color'],
133
- 'planets': []
134
- }
135
-
136
- num_planets = self.rng.randint(3, 7)
137
- for i in range(num_planets):
138
- planet_type = self.rng.choice(self.planet_types)
139
- system['planets'].append({
140
- 'name': f"Planet-{i}",
141
- 'type': planet_type['name'],
142
- 'color': planet_type['color'],
143
- 'size': self.rng.uniform(0.5, 1.5),
144
- 'resources': self.rng.randint(1, 5),
145
- 'habitability': self.rng.uniform(0, 1)
146
- })
147
-
148
- return system
149
 
150
- def generate_universe(self, num_systems=5):
151
  return {
152
- 'systems': [self.generate_system(i) for i in range(num_systems)],
153
- 'seed': 42
154
  }
155
 
156
  # Initialize universe
157
- generator = UniverseGenerator()
158
  universe = generator.generate_universe()
159
 
160
  def get_threejs_app():
161
  """Generate the Three.js HTML with current universe data"""
162
  return THREE_JS_TEMPLATE % json.dumps(universe)
163
 
164
- with gr.Blocks(title="Webspace Network 3D") as demo:
165
- gr.Markdown("# πŸš€ Webspace Network 3D")
166
- gr.Markdown("Explore procedurally generated star systems in your browser")
167
 
168
  with gr.Row():
169
  with gr.Column(scale=2):
170
  # Three.js renderer
171
  html = gr.HTML(get_threejs_app())
172
 
173
- # Navigation controls
174
- system_slider = gr.Slider(0, len(universe['systems'])-1, step=1, label="Star System", value=0)
175
- travel_btn = gr.Button("Engage Hyperdrive")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
  with gr.Column(scale=1):
178
- # Planet info display
179
- planet_info = gr.JSON(label="Selected Planet")
180
- system_info = gr.JSON(label="Current System", value=universe['systems'][0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
- # Handle system travel
183
- travel_btn.click(
184
- lambda x: universe['systems'][x],
185
- inputs=system_slider,
186
- outputs=system_info
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  )
188
-
189
- # Custom JavaScript for planet selection
190
- demo._js = """
191
- function() {
192
- window.addEventListener('message', function(event) {
193
- if (event.data.type === 'planetSelected') {
194
- const planetData = JSON.stringify(event.data.data);
195
- const iframe = document.querySelector('iframe');
196
- const planetInfo = iframe.contentDocument.getElementById('planet-info');
197
- if (planetInfo) {
198
- planetInfo.value = planetData;
199
- planetInfo.dispatchEvent(new Event('change'));
200
- }
201
- }
202
- });
203
- }
204
- """
205
 
206
  if __name__ == "__main__":
207
  demo.launch()
 
1
  import gradio as gr
2
  import numpy as np
3
  import json
4
+ import random
5
+ import math
6
 
7
+ # Three.js template for the space simulation
8
+ THREE_JS_TEMPLATE = """
9
  <!DOCTYPE html>
10
  <html>
11
  <head>
12
+ <title>Webspace Network</title>
13
  <style>
14
+ body {
15
+ margin: 0;
16
+ overflow: hidden;
17
+ font-family: 'Arial', sans-serif;
18
+ }
19
  canvas { display: block; }
20
+ #ui {
21
+ position: absolute;
22
+ top: 10px;
23
+ left: 10px;
24
+ color: white;
25
+ background: rgba(0, 0, 0, 0.7);
26
+ padding: 15px;
27
+ border-radius: 10px;
28
+ width: 300px;
29
+ }
30
+ .bar-container {
31
+ width: 100%;
32
+ background: #333;
33
+ border-radius: 5px;
34
+ margin: 5px 0;
35
+ }
36
+ .bar {
37
+ height: 20px;
38
+ border-radius: 5px;
39
+ text-align: center;
40
+ line-height: 20px;
41
+ color: white;
42
+ font-size: 12px;
43
+ }
44
+ .health-bar { background: linear-gradient(to right, #ff0000, #00ff00); }
45
+ .fuel-bar { background: linear-gradient(to right, #0000ff, #00ffff); }
46
+ #resources {
47
+ margin-top: 10px;
48
+ }
49
+ .resource-item {
50
+ display: flex;
51
+ justify-content: space-between;
52
+ margin: 5px 0;
53
+ }
54
+ #interaction-prompt {
55
+ position: absolute;
56
+ bottom: 20px;
57
+ left: 50%;
58
+ transform: translateX(-50%);
59
+ background: rgba(0, 0, 0, 0.7);
60
+ padding: 10px 20px;
61
+ border-radius: 5px;
62
  color: white;
63
+ display: none;
64
+ }
65
+ #planet-info {
66
+ position: absolute;
67
+ top: 10px;
68
+ right: 10px;
69
+ background: rgba(0, 0, 0, 0.7);
70
+ padding: 15px;
71
+ border-radius: 10px;
72
+ width: 300px;
73
+ color: white;
74
+ display: none;
75
+ }
76
+ #game-menu {
77
+ position: absolute;
78
+ top: 50%;
79
+ left: 50%;
80
+ transform: translate(-50%, -50%);
81
+ background: rgba(0, 0, 0, 0.9);
82
+ padding: 20px;
83
+ border-radius: 10px;
84
+ color: white;
85
+ text-align: center;
86
+ display: none;
87
+ }
88
+ .menu-btn {
89
+ margin: 10px;
90
+ padding: 10px 20px;
91
+ background: #333;
92
+ border: none;
93
+ border-radius: 5px;
94
+ color: white;
95
+ cursor: pointer;
96
+ }
97
+ .menu-btn:hover {
98
+ background: #555;
99
  }
100
  </style>
101
  </head>
102
  <body>
103
+ <div id="ui">
104
+ <h2>Webspace Network</h2>
105
+ <div>
106
+ <div>Health: <span id="health-value">100</span>/100</div>
107
+ <div class="bar-container">
108
+ <div id="health-bar" class="bar health-bar" style="width: 100%">100%</div>
109
+ </div>
110
+ </div>
111
+ <div>
112
+ <div>Fuel: <span id="fuel-value">100</span>/100</div>
113
+ <div class="bar-container">
114
+ <div id="fuel-bar" class="bar fuel-bar" style="width: 100%">100%</div>
115
+ </div>
116
+ </div>
117
+ <div id="resources">
118
+ <h3>Resources:</h3>
119
+ <div id="resource-list"></div>
120
+ </div>
121
+ <button id="menu-btn" class="menu-btn">Menu</button>
122
+ </div>
123
+
124
+ <div id="interaction-prompt">Press [E] to interact</div>
125
+
126
+ <div id="planet-info">
127
+ <h3 id="planet-name">Planet Name</h3>
128
+ <div>Type: <span id="planet-type">Desert</span></div>
129
+ <div>Resources: <span id="planet-resources">Iron, Water</span></div>
130
+ <div>Habitability: <span id="planet-habitability">0.75</span></div>
131
+ <button id="mine-btn" class="menu-btn">Mine Resources</button>
132
+ </div>
133
+
134
+ <div id="game-menu">
135
+ <h2>Game Menu</h2>
136
+ <button id="resume-btn" class="menu-btn">Resume Game</button>
137
+ <button id="save-btn" class="menu-btn">Save Game</button>
138
+ <button id="load-btn" class="menu-btn">Load Game</button>
139
+ <button id="new-btn" class="menu-btn">New Game</button>
140
+ <button id="quit-btn" class="menu-btn">Quit to Desktop</button>
141
+ </div>
142
+
143
  <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
144
  <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
145
 
146
  <script>
147
+ // Game state
148
+ const gameState = {
149
+ health: 100,
150
+ maxHealth: 100,
151
+ fuel: 100,
152
+ maxFuel: 100,
153
+ resources: {
154
+ 'Iron': 10,
155
+ 'Water': 5,
156
+ 'Fuel': 20,
157
+ 'Gold': 2
158
+ },
159
+ currentPlanet: null,
160
+ inMenu: false
161
+ };
162
+
163
  // Scene setup
164
  const scene = new THREE.Scene();
165
+ scene.background = new THREE.Color(0x000010);
166
+
167
+ // Camera
168
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
169
+ camera.position.set(0, 5, 15);
170
+
171
+ // Renderer
172
  const renderer = new THREE.WebGLRenderer({ antialias: true });
173
  renderer.setSize(window.innerWidth, window.innerHeight);
174
  document.body.appendChild(renderer.domElement);
175
 
176
+ // Lighting
177
+ const ambientLight = new THREE.AmbientLight(0x404040);
178
+ scene.add(ambientLight);
179
 
180
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
181
+ directionalLight.position.set(1, 1, 1);
182
+ scene.add(directionalLight);
183
+
184
+ // Stars background
185
+ const starGeometry = new THREE.BufferGeometry();
186
+ const starVertices = [];
187
+ for (let i = 0; i < 10000; i++) {
188
+ const x = (Math.random() - 0.5) * 2000;
189
+ const y = (Math.random() - 0.5) * 2000;
190
+ const z = (Math.random() - 0.5) * 2000;
191
+ starVertices.push(x, y, z);
192
+ }
193
+ starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
194
+ const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
195
+ const stars = new THREE.Points(starGeometry, starMaterial);
196
+ scene.add(stars);
197
+
198
+ // Player ship
199
+ const shipGeometry = new THREE.ConeGeometry(1, 3, 8);
200
+ const shipMaterial = new THREE.MeshPhongMaterial({ color: 0x00aaff });
201
+ const ship = new THREE.Mesh(shipGeometry, shipMaterial);
202
+ ship.rotation.x = Math.PI / 2;
203
+ scene.add(ship);
204
+
205
+ // Planets
206
+ const planets = [];
207
+ const planetData = %s;
208
+
209
+ // Create planets
210
+ function createPlanets() {
211
+ planetData.systems[0].planets.forEach((planet, i) => {
212
  const planetGeometry = new THREE.SphereGeometry(planet.size, 32, 32);
213
+
214
+ // Planet colors
215
+ const colors = {
216
+ 'Lava': [0.8, 0.3, 0.1],
217
+ 'Ocean': [0.1, 0.3, 0.8],
218
+ 'Desert': [0.9, 0.8, 0.5],
219
+ 'Ice': [0.7, 0.8, 0.9],
220
+ 'Jungle': [0.1, 0.7, 0.2],
221
+ 'Toxic': [0.5, 0.1, 0.7],
222
+ 'Radioactive': [0.3, 0.8, 0.1]
223
+ };
224
+
225
  const planetMaterial = new THREE.MeshStandardMaterial({
226
+ color: new THREE.Color(...colors[planet.type] || [0.5, 0.5, 0.5]),
227
  roughness: 0.8,
228
  metalness: 0.2
229
  });
230
+
231
  const planetMesh = new THREE.Mesh(planetGeometry, planetMaterial);
232
 
233
  // Position in orbit
234
+ const angle = (i / planetData.systems[0].planets.length) * Math.PI * 2;
235
+ const distance = 15 + i * 5;
236
+ planetMesh.position.set(
237
+ Math.cos(angle) * distance,
238
+ 0,
239
+ Math.sin(angle) * distance
240
+ );
241
+
242
  planetMesh.userData = planet;
243
+ scene.add(planetMesh);
244
+ planets.push(planetMesh);
245
 
246
+ // Add click handler
247
  planetMesh.addEventListener('click', (event) => {
248
+ gameState.currentPlanet = planet;
249
+ document.getElementById('planet-name').textContent = planet.name;
250
+ document.getElementById('planet-type').textContent = planet.type;
251
+ document.getElementById('planet-resources').textContent = planet.resources.join(', ');
252
+ document.getElementById('planet-habitability').textContent = planet.habitability.toFixed(2);
253
+ document.getElementById('planet-info').style.display = 'block';
254
  event.stopPropagation();
255
  });
 
 
 
 
 
 
 
 
 
 
 
 
256
  });
257
  }
258
 
259
+ createPlanets();
 
260
 
261
  // Camera controls
262
  const controls = new THREE.OrbitControls(camera, renderer.domElement);
263
+ controls.enableDamping = true;
264
+ controls.dampingFactor = 0.05;
265
+ controls.screenSpacePanning = false;
266
+ controls.minDistance = 5;
267
+ controls.maxDistance = 50;
268
+ controls.maxPolarAngle = Math.PI / 2 - 0.05;
269
+
270
+ // Ship movement
271
+ const shipSpeed = 0.1;
272
+ const keys = {};
273
+
274
+ window.addEventListener('keydown', (e) => {
275
+ keys[e.key.toLowerCase()] = true;
276
+
277
+ if (e.key === 'e' && gameState.currentPlanet) {
278
+ mineResources();
279
+ }
280
+
281
+ if (e.key === 'm') {
282
+ toggleMenu();
283
+ }
284
+ });
285
+
286
+ window.addEventListener('keyup', (e) => {
287
+ keys[e.key.toLowerCase()] = false;
288
+ });
289
+
290
+ // Update UI
291
+ function updateUI() {
292
+ document.getElementById('health-value').textContent = gameState.health;
293
+ document.getElementById('health-bar').style.width = `${(gameState.health / gameState.maxHealth) * 100}%`;
294
+ document.getElementById('health-bar').textContent = `${Math.round((gameState.health / gameState.maxHealth) * 100)}%`;
295
+
296
+ document.getElementById('fuel-value').textContent = gameState.fuel;
297
+ document.getElementById('fuel-bar').style.width = `${(gameState.fuel / gameState.maxFuel) * 100}%`;
298
+ document.getElementById('fuel-bar').textContent = `${Math.round((gameState.fuel / gameState.maxFuel) * 100)}%`;
299
+
300
+ // Update resources
301
+ const resourceList = document.getElementById('resource-list');
302
+ resourceList.innerHTML = '';
303
+ for (const [resource, amount] of Object.entries(gameState.resources)) {
304
+ const item = document.createElement('div');
305
+ item.className = 'resource-item';
306
+ item.innerHTML = `<span>${resource}:</span><span>${amount}</span>`;
307
+ resourceList.appendChild(item);
308
+ }
309
+ }
310
+
311
+ // Mine resources
312
+ function mineResources() {
313
+ if (!gameState.currentPlanet) return;
314
+
315
+ const planet = gameState.currentPlanet;
316
+ planet.resources.forEach(resource => {
317
+ gameState.resources[resource] = (gameState.resources[resource] || 0) + 1;
318
+ });
319
+
320
+ updateUI();
321
+ alert(`Mined resources from ${planet.name}!`);
322
+ }
323
+
324
+ // Toggle menu
325
+ function toggleMenu() {
326
+ gameState.inMenu = !gameState.inMenu;
327
+ document.getElementById('game-menu').style.display = gameState.inMenu ? 'block' : 'none';
328
+ controls.enabled = !gameState.inMenu;
329
+ }
330
+
331
+ // Menu buttons
332
+ document.getElementById('resume-btn').addEventListener('click', toggleMenu);
333
+ document.getElementById('menu-btn').addEventListener('click', toggleMenu);
334
+ document.getElementById('mine-btn').addEventListener('click', mineResources);
335
+
336
+ // Save game
337
+ document.getElementById('save-btn').addEventListener('click', () => {
338
+ localStorage.setItem('webspace_save', JSON.stringify(gameState));
339
+ alert('Game saved successfully!');
340
+ });
341
+
342
+ // Load game
343
+ document.getElementById('load-btn').addEventListener('click', () => {
344
+ const save = localStorage.getItem('webspace_save');
345
+ if (save) {
346
+ Object.assign(gameState, JSON.parse(save));
347
+ updateUI();
348
+ alert('Game loaded successfully!');
349
+ toggleMenu();
350
+ } else {
351
+ alert('No saved game found!');
352
+ }
353
+ });
354
+
355
+ // New game
356
+ document.getElementById('new-btn').addEventListener('click', () => {
357
+ if (confirm('Start a new game? All progress will be lost.')) {
358
+ Object.assign(gameState, {
359
+ health: 100,
360
+ maxHealth: 100,
361
+ fuel: 100,
362
+ maxFuel: 100,
363
+ resources: {
364
+ 'Iron': 10,
365
+ 'Water': 5,
366
+ 'Fuel': 20,
367
+ 'Gold': 2
368
+ },
369
+ currentPlanet: null
370
+ });
371
+ updateUI();
372
+ toggleMenu();
373
+ }
374
+ });
375
+
376
+ // Quit game
377
+ document.getElementById('quit-btn').addEventListener('click', () => {
378
+ if (confirm('Quit to desktop?')) {
379
+ // In a real game, this would close the window
380
+ alert('Thanks for playing!');
381
+ }
382
+ });
383
+
384
+ // Initial UI update
385
+ updateUI();
386
 
387
  // Animation loop
388
  function animate() {
389
  requestAnimationFrame(animate);
390
+
391
+ // Ship movement
392
+ if (!gameState.inMenu) {
393
+ if (keys['w'] || keys['arrowup']) {
394
+ ship.position.z -= shipSpeed;
395
+ }
396
+ if (keys['s'] || keys['arrowdown']) {
397
+ ship.position.z += shipSpeed;
398
+ }
399
+ if (keys['a'] || keys['arrowleft']) {
400
+ ship.position.x -= shipSpeed;
401
+ }
402
+ if (keys['d'] || keys['arrowright']) {
403
+ ship.position.x += shipSpeed;
404
+ }
405
+ if (keys['q']) {
406
+ ship.rotation.z += 0.05;
407
+ }
408
+ if (keys['e']) {
409
+ ship.rotation.z -= 0.05;
410
+ }
411
+
412
+ // Fuel consumption
413
+ if (keys['w'] || keys['s'] || keys['a'] || keys['d']) {
414
+ gameState.fuel = Math.max(0, gameState.fuel - 0.05);
415
+ updateUI();
416
+ }
417
+ }
418
+
419
+ // Update camera to follow ship
420
+ camera.position.x = ship.position.x;
421
+ camera.position.y = ship.position.y + 5;
422
+ camera.position.z = ship.position.z + 15;
423
+ camera.lookAt(ship.position.x, ship.position.y, ship.position.z);
424
+
425
  controls.update();
426
  renderer.render(scene, camera);
427
  }
428
+
429
  animate();
430
 
431
  // Handle window resize
 
437
  </script>
438
  </body>
439
  </html>
440
+ """
441
 
442
+ class PlanetGenerator:
443
  def __init__(self, seed=42):
444
  self.rng = np.random.RandomState(seed)
 
 
 
 
 
445
  self.planet_types = [
446
+ 'Lava', 'Ocean', 'Desert', 'Ice', 'Jungle', 'Toxic', 'Radioactive'
447
+ ]
448
+ self.resources = [
449
+ 'Iron', 'Copper', 'Gold', 'Water', 'Oxygen', 'Hydrogen',
450
+ 'Silicon', 'Titanium', 'Uranium', 'Platinum'
451
  ]
452
 
453
+ def generate_planet(self, index):
454
+ planet_type = self.rng.choice(self.planet_types)
455
+
456
+ # Select 2-4 random resources
457
+ num_resources = self.rng.randint(2, 5)
458
+ planet_resources = random.sample(self.resources, num_resources)
459
+
460
+ return {
461
+ 'name': f"Planet-{chr(65 + index)}",
462
+ 'type': planet_type,
463
+ 'resources': planet_resources,
464
+ 'size': self.rng.uniform(0.8, 1.5),
465
+ 'habitability': self.rng.uniform(0.1, 0.9)
466
+ }
467
+
468
  def generate_system(self, index):
469
+ return {
470
+ 'name': f"System-{index}",
471
+ 'planets': [self.generate_planet(i) for i in range(self.rng.randint(3, 7))]
472
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
+ def generate_universe(self, num_systems=1):
475
  return {
476
+ 'systems': [self.generate_system(i) for i in range(num_systems)]
 
477
  }
478
 
479
  # Initialize universe
480
+ generator = PlanetGenerator()
481
  universe = generator.generate_universe()
482
 
483
  def get_threejs_app():
484
  """Generate the Three.js HTML with current universe data"""
485
  return THREE_JS_TEMPLATE % json.dumps(universe)
486
 
487
+ with gr.Blocks(title="Webspace Network", css=".gradio-container {background: linear-gradient(to bottom, #000033, #000066);}") as demo:
488
+ gr.Markdown("# πŸš€ Webspace Network - Space Exploration Simulator")
489
+ gr.Markdown("### Procedurally generated universe inspired by No Man's Sky")
490
 
491
  with gr.Row():
492
  with gr.Column(scale=2):
493
  # Three.js renderer
494
  html = gr.HTML(get_threejs_app())
495
 
496
+ # Game instructions
497
+ with gr.Accordion("Game Controls", open=False):
498
+ gr.Markdown("""
499
+ **Movement:**
500
+ - W/S: Move forward/backward
501
+ - A/D: Move left/right
502
+ - Q/E: Rotate ship
503
+ - Mouse: Look around
504
+
505
+ **Interaction:**
506
+ - E: Interact with objects
507
+ - M: Open game menu
508
+
509
+ **Planets:**
510
+ - Click on planets to see details
511
+ - Press 'Mine Resources' to collect resources
512
+ """)
513
 
514
  with gr.Column(scale=1):
515
+ # Game state display
516
+ with gr.Group():
517
+ gr.Markdown("### Game State")
518
+ health = gr.Slider(0, 100, value=100, label="Health", interactive=False)
519
+ fuel = gr.Slider(0, 100, value=100, label="Fuel", interactive=False)
520
+
521
+ # Resources display
522
+ with gr.Group():
523
+ gr.Markdown("### Resources")
524
+ resources = gr.JSON(value={
525
+ 'Iron': 10,
526
+ 'Water': 5,
527
+ 'Fuel': 20,
528
+ 'Gold': 2
529
+ }, label="Inventory")
530
+
531
+ # Game actions
532
+ with gr.Group():
533
+ gr.Markdown("### Actions")
534
+ with gr.Row():
535
+ save_btn = gr.Button("πŸ’Ύ Save Game")
536
+ load_btn = gr.Button("πŸ“‚ Load Game")
537
+ new_btn = gr.Button("πŸ†• New Game")
538
+
539
+ # Current planet info
540
+ with gr.Group():
541
+ gr.Markdown("### Current Planet")
542
+ planet_info = gr.JSON(label="Planet Data", value={})
543
+
544
+ # Debug console
545
+ with gr.Group():
546
+ gr.Markdown("### Debug Console")
547
+ console = gr.Textbox(label="Game Events", interactive=False)
548
+
549
+ # Game actions
550
+ def save_game():
551
+ return {"message": "Game saved successfully!"}
552
 
553
+ def load_game():
554
+ return {"message": "Game loaded successfully!"}
555
+
556
+ def new_game():
557
+ return {
558
+ "health": 100,
559
+ "fuel": 100,
560
+ "resources": {
561
+ 'Iron': 10,
562
+ 'Water': 5,
563
+ 'Fuel': 20,
564
+ 'Gold': 2
565
+ },
566
+ "planet_info": {},
567
+ "console": "New game started"
568
+ }
569
+
570
+ save_btn.click(
571
+ save_game,
572
+ outputs=console
573
+ )
574
+
575
+ load_btn.click(
576
+ load_game,
577
+ outputs=console
578
+ )
579
+
580
+ new_btn.click(
581
+ new_game,
582
+ outputs=[health, fuel, resources, planet_info, console]
583
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
584
 
585
  if __name__ == "__main__":
586
  demo.launch()