広い海で遊ぶゲーム。スペースキーを押すと発射。
カーソルキーで移動です。
import os
import webbrowser
from http.server import SimpleHTTPRequestHandler, HTTPServer
import threading
# HTMLコードを生成
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Car Game with Random Fire</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// シーン、カメラ、レンダラーの初期化
var scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // 空の色 (空色)
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);
// 地面(海の色に設定)
var groundGeometry = new THREE.PlaneGeometry(1000, 1000);
var groundMaterial = new THREE.MeshBasicMaterial({ color: 0x1e90ff });
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 広い範囲に島を配置
function createIsland(x, y, z) {
var islandGeometry = new THREE.CylinderGeometry(2, 5, 3, 32);
var islandMaterial = new THREE.MeshBasicMaterial({ color: 0x228B22 }); // 島の色 (緑色)
var island = new THREE.Mesh(islandGeometry, islandMaterial);
island.position.set(x, y, z);
scene.add(island);
}
// より広い範囲に多数の島をランダムに配置
for (var i = 0; i < 50; i++) {
createIsland(
Math.random() * 1000 - 500,
1.5, // 海面からの高さ
Math.random() * 1000 - 500
);
}
// 車の初期設定
var carGeometry = new THREE.BoxGeometry(1, 0.5, 2);
var carMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var car = new THREE.Mesh(carGeometry, carMaterial);
scene.add(car);
camera.position.set(0, 5, -10);
camera.lookAt(car.position);
// プロジェクタイル用変数
var projectiles = [];
var carSpeed = 0;
var carRotationSpeed = 0.05;
var moveForward = false;
var moveBackward = false;
var rotateLeft = false;
var rotateRight = false;
// キーボード入力処理
function onKeyDown(event) {
switch (event.code) {
case 'ArrowUp': moveForward = true; break;
case 'ArrowDown': moveBackward = true; break;
case 'ArrowLeft': rotateLeft = true; break;
case 'ArrowRight': rotateRight = true; break;
case 'Space': fireMassProjectiles(); break;
}
}
function onKeyUp(event) {
switch (event.code) {
case 'ArrowUp': moveForward = false; break;
case 'ArrowDown': moveBackward = false; break;
case 'ArrowLeft': rotateLeft = false; break;
case 'ArrowRight': rotateRight = false; break;
}
}
// 100発のプロジェクタイルを発射する関数
function fireMassProjectiles() {
for (var i = 0; i < 100; i++) {
var projectileGeometry = new THREE.SphereGeometry(0.2, 16, 16);
var projectileMaterial = new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff });
var projectile = new THREE.Mesh(projectileGeometry, projectileMaterial);
projectile.position.set(
car.position.x + Math.sin(car.rotation.y) * 2,
car.position.y + 0.5,
car.position.z + Math.cos(car.rotation.y) * 2
);
// ランダムな角度と距離を持つプロジェクタイルの速度を設定
var speed = Math.random() * 1.5 + 0.5;
var randomAngle = (Math.random() - 0.5) * 0.4;
var velocity = new THREE.Vector3(
Math.sin(car.rotation.y + randomAngle) * speed,
Math.random() * 0.5, // よりランダムな高さ
Math.cos(car.rotation.y + randomAngle) * speed
);
projectile.velocity = velocity;
scene.add(projectile);
projectiles.push(projectile);
}
}
// プロジェクタイルの更新処理
function updateProjectiles() {
for (var i = projectiles.length - 1; i >= 0; i--) {
var projectile = projectiles[i];
projectile.position.add(projectile.velocity);
projectile.velocity.y -= 0.01; // 重力
// 地面に落ちた場合の処理
if (projectile.position.y < 0) {
scene.remove(projectile);
projectiles.splice(i, 1);
}
}
}
// レンダリングと更新処理のループ関数
function animate() {
requestAnimationFrame(animate);
// 車の移動と回転
if (moveForward) carSpeed += 0.01;
if (moveBackward) carSpeed -= 0.01;
if (rotateLeft) car.rotation.y += carRotationSpeed;
if (rotateRight) car.rotation.y -= carRotationSpeed;
car.position.x += Math.sin(car.rotation.y) * carSpeed;
car.position.z += Math.cos(car.rotation.y) * carSpeed;
carSpeed *= 0.98;
// プロジェクタイルの更新
updateProjectiles();
// カメラの追従
camera.position.set(
car.position.x - Math.sin(car.rotation.y) * 5,
car.position.y + 2,
car.position.z - Math.cos(car.rotation.y) * 5
);
camera.lookAt(car.position);
renderer.render(scene, camera);
}
// イベントリスナーを設定
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
animate();
</script>
</body>
</html>
"""
# HTMLファイルとして保存
html_file = 'fire_simulation.html'
with open(html_file, 'w') as file:
file.write(html_content)
# サーバーをバックグラウンドで起動
def run_server():
server_address = ('', 8000)
httpd = HTTPServer(server_address, SimpleHTTPRequestHandler)
httpd.serve_forever()
# サーバーを別スレッドで実行
thread = threading.Thread(target=run_server)
thread.daemon = True
thread.start()
# デフォルトのブラウザでHTMLファイルを開く
webbrowser.open(f'http://localhost:8000/{html_file}')
# サーバー停止まで待機
try:
thread.join()
except KeyboardInterrupt:
print("Server stopped.")