import http.server
import socketserver
import tempfile
import webbrowser
html_content = """
<!DOCTYPE html>
<html>
<head>
<title>ロケット打ち上げシミュレーション</title>
<style>
body {
margin: 0;
overflow: hidden;
color: white;
font-size: 24px;
text-align: center;
background-color: black;
}
#altitude {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
}
#startMessage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
color: yellow;
font-size: 36px;
}
</style>
</head>
<body>
<div id="altitude">Altitude: 0 m</div>
<div id="startMessage">Press SPACE to Start</div>
<script src="https://cdn.jsdelivr.net/npm/three@0.139.2/build/three.min.js"></script>
<script>
// シーン、カメラ、レンダラーの設定
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 背景色を空の青色に設定
scene.background = new THREE.Color(0x87CEEB);
// 地面を作成
var groundGeometry = new THREE.PlaneGeometry(1000, 1000);
var groundMaterial = new THREE.MeshBasicMaterial({ color: 0x228B22 });
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -0.5;
scene.add(ground);
// 発射台を作成
var platformGeometry = new THREE.BoxGeometry(2, 0.5, 2);
var platformMaterial = new THREE.MeshBasicMaterial({ color: 0x808080 });
var platform = new THREE.Mesh(platformGeometry, platformMaterial);
platform.position.y = 0;
scene.add(platform);
// ロケットを作成
var rocketGeometry = new THREE.CylinderGeometry(0.2, 0.2, 2, 32);
var rocketMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
var rocket = new THREE.Mesh(rocketGeometry, rocketMaterial);
rocket.position.y = 1.25;
scene.add(rocket);
// ロケットの炎を作成
var flameGeometry = new THREE.ConeGeometry(0.3, 0.5, 32);
var flameMaterial = new THREE.MeshBasicMaterial({ color: 0xffa500 });
var flame = new THREE.Mesh(flameGeometry, flameMaterial);
flame.position.y = -1.25;
flame.rotation.x = Math.PI;
rocket.add(flame);
// 変数の初期化
var rocketVelocity = 0.1; // ロケットの初速度
var gravity = -0.01; // 重力加速度
var altitude = 0; // 高度
var engineStartTime; // エンジンが開始された時間
var engineRunning = false; // エンジンが動いているかどうか
var landing = false; // 着陸中かどうか
camera.position.z = 5;
// 四角い箱をランダムに10個配置
for (var i = 0; i < 10; i++) {
var boxGeometry = new THREE.BoxGeometry(1, 1, 1);
var boxMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
var box = new THREE.Mesh(boxGeometry, boxMaterial);
box.position.set(Math.random() * 20 - 10, 0.5, Math.random() * 20 - 10); // ランダムに配置
scene.add(box);
}
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
// スペースキーが押されるまでエンジンを動かさない
if (!engineRunning) {
return;
}
var elapsedTime = (Date.now() - engineStartTime) / 1000; // エンジン開始からの経過時間
// 打ち上げフェーズ (10秒間)
if (elapsedTime <= 10) {
altitude += rocketVelocity;
rocket.position.y += rocketVelocity;
}
// 着陸フェーズ
else if (altitude > 0) {
flame.visible = false; // 炎を消す
rocketVelocity += gravity; // 重力を適用
altitude += rocketVelocity;
rocket.position.y += rocketVelocity;
// ロケットが地面に到達したら停止
if (rocket.position.y <= 1.25) {
rocketVelocity = 0;
rocket.position.y = 1.25;
landing = true;
}
}
// 高度を表示
document.getElementById("altitude").textContent = "Altitude: " + Math.max(0, Math.round(altitude * 10)) + " m";
camera.position.y = rocket.position.y; // カメラをロケットに追従させる
camera.lookAt(rocket.position);
renderer.render(scene, camera); // シーンをレンダリング
}
// スペースキーが押されたときにエンジンをスタートさせる
document.addEventListener('keydown', function(event) {
if (event.code === 'Space' && !engineRunning) {
engineRunning = true;
engineStartTime = Date.now(); // エンジン開始時間を記録
document.getElementById("startMessage").style.display = 'none'; // スタートメッセージを隠す
}
});
animate(); // アニメーションを開始
</script>
</body>
</html>
"""
with tempfile.NamedTemporaryFile(delete=False, suffix=".html") as temp_html:
temp_html.write(html_content.encode("utf-8"))
temp_html.flush()
webbrowser.open(f"file://{temp_html.name}")
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
# ローカルサーバーを起動してHTMLを提供
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"Serving at port {PORT}")
httpd.serve_forever()