|
|
import gradio as gr |
|
|
import json |
|
|
import random |
|
|
import math |
|
|
import numpy as np |
|
|
|
|
|
|
|
|
UNIVERSE_SEED = 42 |
|
|
RESOURCE_TYPES = ['Iron', 'Copper', 'Gold', 'Water', 'Oxygen', 'Hydrogen', 'Silicon', 'Titanium'] |
|
|
CIVILIZATION_STAGES = [ |
|
|
{"title": "I. Биологический", "color": "#00cc44", "desc": "Углеродно-водные формы жизни..."}, |
|
|
{"title": "II. Техногенный", "color": "#00aaff", "desc": "Промышленная и цифровая революция..."}, |
|
|
{"title": "III. Постбиологический", "color": "#ff7700", "desc": "Переход к цифровому существованию..."}, |
|
|
{"title": "IV. Космический", "color": "#aa55ff", "desc": "Межзвездные путешествия..."}, |
|
|
{"title": "V. Универсальный", "color": "#ffff00", "desc": "Слияние с космическим разумом..."} |
|
|
] |
|
|
|
|
|
|
|
|
class UniverseGenerator: |
|
|
def __init__(self, seed=UNIVERSE_SEED): |
|
|
self.rng = random.Random(seed) |
|
|
self.planet_types = ['Lava', 'Ocean', 'Desert', 'Ice', 'Jungle'] |
|
|
|
|
|
def generate_planet(self, index): |
|
|
return { |
|
|
'name': f"Planet-{chr(65 + index)}", |
|
|
'type': self.rng.choice(self.planet_types), |
|
|
'resources': self.rng.sample(RESOURCE_TYPES, self.rng.randint(2, 5)), |
|
|
'size': self.rng.uniform(0.8, 1.5), |
|
|
'habitability': round(self.rng.uniform(0.1, 0.9), 2) |
|
|
} |
|
|
|
|
|
def generate_system(self, index): |
|
|
return { |
|
|
'name': f"System-{index}", |
|
|
'planets': [self.generate_planet(i) for i in range(self.rng.randint(3, 6))] |
|
|
} |
|
|
|
|
|
def generate_universe(self): |
|
|
return { |
|
|
'systems': [self.generate_system(i) for i in range(3)], |
|
|
'civilization_stages': CIVILIZATION_STAGES |
|
|
} |
|
|
|
|
|
|
|
|
CIVILIZATION_TEMPLATE = """ |
|
|
<!DOCTYPE html> |
|
|
<html> |
|
|
<head> |
|
|
<title>Эволюция Цивилизаций</title> |
|
|
<style> |
|
|
body {{ |
|
|
margin: 0; |
|
|
overflow: hidden; |
|
|
background: #001133; |
|
|
color: white; |
|
|
font-family: Arial, sans-serif; |
|
|
}} |
|
|
#infoBox {{ |
|
|
position: absolute; |
|
|
top: 20px; |
|
|
left: 20px; |
|
|
max-width: 350px; |
|
|
background: rgba(0, 0, 20, 0.85); |
|
|
padding: 20px; |
|
|
border-radius: 15px; |
|
|
border: 1px solid #4a6fff; |
|
|
display: none; |
|
|
}} |
|
|
#title {{ |
|
|
position: absolute; |
|
|
top: 20px; |
|
|
width: 100%; |
|
|
text-align: center; |
|
|
font-size: 24px; |
|
|
color: #4fc3f7; |
|
|
text-shadow: 0 0 15px rgba(79, 195, 247, 0.8); |
|
|
pointer-events: none; |
|
|
}} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div id="title">ЭВОЛЮЦИЯ ЦИВИЛИЗАЦИЙ ВО ВСЕЛЕННОЙ</div> |
|
|
<div id="infoBox"> |
|
|
<h2 id="stageTitle"></h2> |
|
|
<p id="stageDesc"></p> |
|
|
</div> |
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.min.js"></script> |
|
|
|
|
|
<script> |
|
|
// Инициализация сцены |
|
|
const scene = new THREE.Scene(); |
|
|
scene.background = new THREE.Color(0x001122); |
|
|
const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 2000); |
|
|
const renderer = new THREE.WebGLRenderer({{ antialias: true }}); |
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
document.body.appendChild(renderer.domElement); |
|
|
|
|
|
// Настройка камеры и освещения |
|
|
camera.position.set(0, 15, 50); |
|
|
const controls = new THREE.OrbitControls(camera, renderer.domElement); |
|
|
controls.enableDamping = true; |
|
|
|
|
|
// Создание звездного поля |
|
|
const starGeometry = new THREE.BufferGeometry(); |
|
|
const starPositions = new Float32Array(5000 * 3); |
|
|
for (let i = 0; i < 5000; i++) {{ |
|
|
starPositions[i*3] = (Math.random() - 0.5) * 2000; |
|
|
starPositions[i*3+1] = (Math.random() - 0.5) * 2000; |
|
|
starPositions[i*3+2] = (Math.random() - 0.5) * 2000; |
|
|
}} |
|
|
starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3)); |
|
|
const stars = new THREE.Points(starGeometry, new THREE.PointsMaterial({{ color: 0xffffff, size: 1.5 }})); |
|
|
scene.add(stars); |
|
|
|
|
|
// Создание сфер цивилизаций |
|
|
const stages = {civilization_stages}; |
|
|
const spheres = []; |
|
|
|
|
|
stages.forEach((stage, i) => {{ |
|
|
const geometry = new THREE.SphereGeometry(4, 32, 32); |
|
|
const material = new THREE.MeshStandardMaterial({{ |
|
|
color: new THREE.Color(stage.color), |
|
|
emissive: new THREE.Color(stage.color), |
|
|
metalness: 0.7, |
|
|
roughness: 0.2 |
|
|
}}); |
|
|
|
|
|
const sphere = new THREE.Mesh(geometry, material); |
|
|
sphere.position.x = (i - stages.length/2) * 15; |
|
|
sphere.userData = stage; |
|
|
scene.add(sphere); |
|
|
spheres.push(sphere); |
|
|
}}); |
|
|
|
|
|
// Интерактивность |
|
|
const raycaster = new THREE.Raycaster(); |
|
|
const mouse = new THREE.Vector2(); |
|
|
const infoBox = document.getElementById("infoBox"); |
|
|
|
|
|
window.addEventListener("click", (event) => {{ |
|
|
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; |
|
|
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; |
|
|
|
|
|
raycaster.setFromCamera(mouse, camera); |
|
|
const intersects = raycaster.intersectObjects(spheres); |
|
|
|
|
|
if (intersects.length > 0) {{ |
|
|
const stage = intersects[0].object.userData; |
|
|
document.getElementById("stageTitle").textContent = stage.title; |
|
|
document.getElementById("stageDesc").textContent = stage.desc; |
|
|
infoBox.style.display = "block"; |
|
|
}} |
|
|
}}); |
|
|
|
|
|
// Анимация |
|
|
function animate() {{ |
|
|
requestAnimationFrame(animate); |
|
|
spheres.forEach((sphere, i) => {{ |
|
|
sphere.rotation.y += 0.01; |
|
|
sphere.rotation.x += 0.005; |
|
|
}}); |
|
|
controls.update(); |
|
|
renderer.render(scene, camera); |
|
|
}} |
|
|
animate(); |
|
|
|
|
|
// Адаптация под размер окна |
|
|
window.addEventListener("resize", () => {{ |
|
|
camera.aspect = window.innerWidth / window.innerHeight; |
|
|
camera.updateProjectionMatrix(); |
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
}}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
""" |
|
|
|
|
|
SPACE_EXPLORER_TEMPLATE = """ |
|
|
<!DOCTYPE html> |
|
|
<html> |
|
|
<head> |
|
|
<title>Космический Исследователь</title> |
|
|
<style> |
|
|
body {{ |
|
|
margin: 0; |
|
|
overflow: hidden; |
|
|
background: #000; |
|
|
font-family: Arial, sans-serif; |
|
|
}} |
|
|
#ui {{ |
|
|
position: absolute; |
|
|
top: 20px; |
|
|
left: 20px; |
|
|
color: white; |
|
|
background: rgba(0, 0, 0, 0.7); |
|
|
padding: 15px; |
|
|
border-radius: 10px; |
|
|
width: 300px; |
|
|
}} |
|
|
.bar-container {{ width: 100%; background: #333; border-radius: 5px; margin: 5px 0; }} |
|
|
.bar {{ height: 20px; border-radius: 5px; text-align: center; color: white; }} |
|
|
.health-bar {{ background: linear-gradient(to right, #ff0000, #00ff00); }} |
|
|
.fuel-bar {{ background: linear-gradient(to right, #0000ff, #00ffff); }} |
|
|
#planet-info {{ |
|
|
position: absolute; |
|
|
top: 20px; |
|
|
right: 20px; |
|
|
background: rgba(0, 0, 0, 0.7); |
|
|
padding: 15px; |
|
|
border-radius: 10px; |
|
|
color: white; |
|
|
display: none; |
|
|
}} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div id="ui"> |
|
|
<h3>Космический Корабль</h3> |
|
|
<div>Здоровье: <span id="health-value">100</span>/100</div> |
|
|
<div class="bar-container"><div id="health-bar" class="bar health-bar" style="width: 100%"></div></div> |
|
|
<div>Топливо: <span id="fuel-value">100</span>/100</div> |
|
|
<div class="bar-container"><div id="fuel-bar" class="bar fuel-bar" style="width: 100%"></div></div> |
|
|
</div> |
|
|
|
|
|
<div id="planet-info"> |
|
|
<h3 id="planet-name"></h3> |
|
|
<div>Тип: <span id="planet-type"></span></div> |
|
|
<div>Ресурсы: <span id="planet-resources"></span></div> |
|
|
</div> |
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.min.js"></script> |
|
|
|
|
|
<script> |
|
|
// Инициализация сцены |
|
|
const scene = new THREE.Scene(); |
|
|
scene.background = new THREE.Color(0x000010); |
|
|
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); |
|
|
const renderer = new THREE.WebGLRenderer({{ antialias: true }}); |
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
document.body.appendChild(renderer.domElement); |
|
|
|
|
|
// Освещение |
|
|
const ambientLight = new THREE.AmbientLight(0x404040); |
|
|
scene.add(ambientLight); |
|
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); |
|
|
directionalLight.position.set(1, 1, 1); |
|
|
scene.add(directionalLight); |
|
|
|
|
|
// Корабль игрока |
|
|
const shipGeometry = new THREE.ConeGeometry(1, 3, 8); |
|
|
const shipMaterial = new THREE.MeshPhongMaterial({{ color: 0x00aaff }}); |
|
|
const ship = new THREE.Mesh(shipGeometry, shipMaterial); |
|
|
ship.rotation.x = Math.PI / 2; |
|
|
scene.add(ship); |
|
|
|
|
|
// Планеты |
|
|
const planets = []; |
|
|
const universeData = {universe_data}; |
|
|
|
|
|
universeData.systems[0].planets.forEach((planet, i) => {{ |
|
|
const geometry = new THREE.SphereGeometry(planet.size, 32, 32); |
|
|
const material = new THREE.MeshStandardMaterial({{ |
|
|
color: new THREE.Color( |
|
|
planet.type === 'Lava' ? 0xff3300 : |
|
|
planet.type === 'Ocean' ? 0x0066ff : |
|
|
planet.type === 'Desert' ? 0xffcc00 : |
|
|
0x888888 |
|
|
), |
|
|
roughness: 0.8, |
|
|
metalness: 0.2 |
|
|
}}); |
|
|
|
|
|
const planetMesh = new THREE.Mesh(geometry, material); |
|
|
planetMesh.position.x = i * 15 - 30; |
|
|
planetMesh.userData = planet; |
|
|
scene.add(planetMesh); |
|
|
planets.push(planetMesh); |
|
|
}}); |
|
|
|
|
|
// Управление кораблем |
|
|
const keys = {{}}; |
|
|
window.addEventListener('keydown', (e) => keys[e.key.toLowerCase()] = true); |
|
|
window.addEventListener('keyup', (e) => keys[e.key.toLowerCase()] = false); |
|
|
|
|
|
// Анимация |
|
|
function animate() {{ |
|
|
requestAnimationFrame(animate); |
|
|
|
|
|
// Движение корабля |
|
|
if (keys['w']) ship.position.z -= 0.1; |
|
|
if (keys['s']) ship.position.z += 0.1; |
|
|
if (keys['a']) ship.position.x -= 0.1; |
|
|
if (keys['d']) ship.position.x += 0.1; |
|
|
|
|
|
// Обновление камеры |
|
|
camera.position.x = ship.position.x; |
|
|
camera.position.y = ship.position.y + 5; |
|
|
camera.position.z = ship.position.z + 15; |
|
|
camera.lookAt(ship.position); |
|
|
|
|
|
renderer.render(scene, camera); |
|
|
}} |
|
|
animate(); |
|
|
|
|
|
// Адаптация под размер окна |
|
|
window.addEventListener('resize', () => {{ |
|
|
camera.aspect = window.innerWidth / window.innerHeight; |
|
|
camera.updateProjectionMatrix(); |
|
|
renderer.setSize(window.innerWidth, window.innerHeight); |
|
|
}}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
""" |
|
|
|
|
|
|
|
|
def create_civilization_demo(): |
|
|
universe = UniverseGenerator().generate_universe() |
|
|
template = CIVILIZATION_TEMPLATE.replace("{civilization_stages}", json.dumps(universe["civilization_stages"])) |
|
|
return template |
|
|
|
|
|
def create_space_explorer_demo(): |
|
|
universe = UniverseGenerator().generate_universe() |
|
|
template = SPACE_EXPLORER_TEMPLATE.replace("{universe_data}", json.dumps(universe)) |
|
|
return template |
|
|
|
|
|
with gr.Blocks(title="Космические Игры", css=".gradio-container {background: #000033;}") as demo: |
|
|
gr.Markdown("# 🌌 Две Космические Игры") |
|
|
gr.Markdown("### Исследуйте эволюцию цивилизаций и космические просторы") |
|
|
|
|
|
with gr.Tabs(): |
|
|
with gr.TabItem("Эволюция Цивилизаций"): |
|
|
civ_html = gr.HTML(create_civilization_demo()) |
|
|
gr.Markdown(""" |
|
|
**Инструкции:** |
|
|
- Кликните на сферы, чтобы узнать о стадиях развития цивилизаций |
|
|
- Используйте мышь для вращения камеры |
|
|
""") |
|
|
|
|
|
with gr.TabItem("Космический Исследователь"): |
|
|
space_html = gr.HTML(create_space_explorer_demo()) |
|
|
gr.Markdown(""" |
|
|
**Управление:** |
|
|
- W/S: Движение вперед/назад |
|
|
- A/D: Движение влево/вправо |
|
|
- Мышь: Управление камерой |
|
|
""") |
|
|
|
|
|
gr.Markdown("### Общие игровые системы:") |
|
|
with gr.Accordion("Технические детали", open=False): |
|
|
gr.Markdown(""" |
|
|
**Общие компоненты:** |
|
|
1. **Генерация вселенной**: Процедурное создание планет и систем |
|
|
2. **Three.js рендеринг**: Реалистичное 3D отображение космоса |
|
|
3. **Интерактивные элементы**: Взаимодействие с объектами через UI |
|
|
4. **Физика движения**: Реалистичное управление космическим кораблем |
|
|
""") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |