宇宙船の惑星スイングバイ
シュミレーション
DeepSeekでjavascriptでシュミレーション作成
シュミレーションHTML(swinby.html)
スイングバイシュミレーション
スマホはswingbyiphoneから開いてください
DeepSeekを使ったシュミレーションのプログラムです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>宇宙船スイングバイシミュレーション</title>
<style>
canvas {
border: 1px solid black;
display: block;
margin: 0 auto;
}
#controls {
text-align: center;
margin-top: 10px;
}
button {
padding: 10px 20px;
font-size: 16px;
}
label {
font-size: 16px;
margin-right: 10px;
}
input[type="range"] {
width: 200px;
}
</style>
</head>
<body>
<canvas id="spaceCanvas" width="800" height="600"></canvas>
<div id="controls">
<button id="startButton">スタート</button>
<button id="stopButton">ストップ</button>
<button id="resetButton">リセット</button>
<div>
<label for="speedSlider">宇宙船の速度:</label>
<input type="range" id="speedSlider" min="0.1" max="5" step="0.1" value="2">
<span id="speedValue">2</span>
</div>
<div>
<label>実際の速度:</label>
<span id="actualSpeedValue">0</span>
</div>
</div>
<script>
const canvas = document.getElementById('spaceCanvas');
const ctx = canvas.getContext('2d');
// 中心の星(仮想的な中心点)の設定
const centerStar = {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 20,
mass: 100000
};
// 惑星の初期設定
const planet = {
x: canvas.width / 2 + 200, // 初期位置を中心から離す
y: canvas.height / 2,
radius: 20, // 惑星のサイズを小さくする
mass: 10000,
orbitRadius: 200, // 公転半径
orbitSpeed: 0.02, // 公転速度(ラジアン/フレーム)
angle: 0 // 公転角度
};
// 宇宙船の初期設定
const spaceship = {
x: 100,
y: 100,
radius: 5,
vx: 2, // 初期速度
vy: 0,
mass: 1
};
const G = 0.1; // 重力定数(シミュレーション用)
let animationId = null; // アニメーションIDを保持する変数
let isRunning = false; // アニメーションの実行状態を管理するフラグ
// 速度スライダーの要素を取得
const speedSlider = document.getElementById('speedSlider');
const speedValue = document.getElementById('speedValue');
const actualSpeedValue = document.getElementById('actualSpeedValue');
// スライダーの値が変更されたときのイベントリスナー
speedSlider.addEventListener('input', () => {
const speed = parseFloat(speedSlider.value);
spaceship.vx = speed; // 宇宙船の速度を更新
speedValue.textContent = speed; // 表示を更新
});
// 宇宙船をリセットする関数
function resetSpaceship() {
spaceship.x = 100;
spaceship.y = 100;
spaceship.vx = parseFloat(speedSlider.value);
spaceship.vy = 0;
}
// 宇宙船の速度を計算する関数
function calculateSpeed() {
return Math.sqrt(spaceship.vx * spaceship.vx + spaceship.vy * spaceship.vy);
}
// 惑星の公転を更新する関数
function updatePlanetOrbit() {
planet.angle += planet.orbitSpeed; // 公転角度を更新
planet.x = centerStar.x + Math.cos(planet.angle) * planet.orbitRadius; // X座標を更新
planet.y = centerStar.y + Math.sin(planet.angle) * planet.orbitRadius; // Y座標を更新
}
// アニメーションの更新
function update() {
// 惑星の公転を更新
updatePlanetOrbit();
// 惑星と宇宙船の距離を計算
const dx = planet.x - spaceship.x;
const dy = planet.y - spaceship.y;
const distance = Math.sqrt(dx * dx + dy * dy);
// 重力による加速度を計算
const force = (G * planet.mass) / (distance * distance);
const angle = Math.atan2(dy, dx);
const ax = force * Math.cos(angle);
const ay = force * Math.sin(angle);
// 宇宙船の速度を更新
spaceship.vx += ax;
spaceship.vy += ay;
// 宇宙船の位置を更新
spaceship.x += spaceship.vx;
spaceship.y += spaceship.vy;
// 画面外に出た場合の処理
if (spaceship.x < 0 || spaceship.x > canvas.width || spaceship.y < 0 || spaceship.y > canvas.height) {
resetSpaceship();
}
// 実際の速度を表示
actualSpeedValue.textContent = calculateSpeed().toFixed(2);
}
// 描画関数
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 中心の星を描画
ctx.beginPath();
ctx.arc(centerStar.x, centerStar.y, centerStar.radius, 0, Math.PI * 2);
ctx.fillStyle = 'yellow';
ctx.fill();
// 惑星を描画
ctx.beginPath();
ctx.arc(planet.x, planet.y, planet.radius, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
// 宇宙船を描画
ctx.beginPath();
ctx.arc(spaceship.x, spaceship.y, spaceship.radius, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
}
// アニメーションループ
function animate() {
update();
draw();
if (isRunning) {
animationId = requestAnimationFrame(animate);
}
}
// スタートボタンのイベントリスナー
document.getElementById('startButton').addEventListener('click', () => {
if (!isRunning) {
isRunning = true;
animate();
}
});
// ストップボタンのイベントリスナー
document.getElementById('stopButton').addEventListener('click', () => {
if (isRunning) {
isRunning = false;
cancelAnimationFrame(animationId);
}
});
// リセットボタンのイベントリスナー
document.getElementById('resetButton').addEventListener('click', () => {
resetSpaceship();
isRunning = false;
cancelAnimationFrame(animationId);
draw(); // リセット後の状態を描画
actualSpeedValue.textContent = calculateSpeed().toFixed(2); // 速度を更新
});
// 初期描画
draw();
actualSpeedValue.textContent = calculateSpeed().toFixed(2); // 初期速度を表示
</script>
</body>
</html>
スマホ対応(ChatGDP)で作りました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>宇宙船スイングバイシミュレーション</title>
<style>
canvas {
border: 1px solid black;
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}
#controls {
text-align: center;
margin-top: 10px;
}
button {
padding: 10px 20px;
font-size: 16px;
margin: 5px;
}
label {
font-size: 16px;
margin-right: 10px;
}
input[type="range"] {
width: 100%;
max-width: 200px;
}
</style>
</head>
<body>
<canvas id="spaceCanvas"></canvas>
<div id="controls">
<button id="startButton">スタート</button>
<button id="stopButton">ストップ</button>
<button id="resetButton">リセット</button>
<div>
<label for="speedSlider">宇宙船の速度:</label>
<input type="range" id="speedSlider" min="0.1" max="5" step="0.1" value="2">
<span id="speedValue">2</span>
</div>
<div>
<label>実際の速度:</label>
<span id="actualSpeedValue">0</span>
</div>
</div>
<script>
const canvas = document.getElementById('spaceCanvas');
const ctx = canvas.getContext('2d');
// 恒星
const centerStar = { x: 0, y: 0, radius: 20, mass: 100000 };
// 惑星
const planet = { x: 0, y: 0, radius: 15, mass: 10000, orbitRadius: 0, orbitSpeed: 0.02, angle: 0 };
// 宇宙船
const spaceship = { x: 100, y: 100, radius: 5, vx: 2, vy: 0, mass: 1 };
const G = 0.1; // 重力定数
let isRunning = false;
let animationId = null;
// キャンバスのリサイズ
function resizeCanvas() {
canvas.width = window.innerWidth * 0.9;
canvas.height = window.innerHeight * 0.7;
centerStar.x = canvas.width / 2;
centerStar.y = canvas.height / 2;
planet.orbitRadius = Math.min(canvas.width, canvas.height) * 0.3;
draw();
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// 惑星の公転を更新
function updatePlanetOrbit() {
planet.angle += planet.orbitSpeed;
planet.x = centerStar.x + Math.cos(planet.angle) * planet.orbitRadius;
planet.y = centerStar.y + Math.sin(planet.angle) * planet.orbitRadius;
}
// 宇宙船の速度を計算
function calculateSpeed() {
return Math.sqrt(spaceship.vx ** 2 + spaceship.vy ** 2);
}
// 宇宙船のリセット
function resetSpaceship() {
spaceship.x = 100;
spaceship.y = 100;
spaceship.vx = parseFloat(speedSlider.value);
spaceship.vy = 0;
}
// 物理計算
function update() {
updatePlanetOrbit();
const dx = planet.x - spaceship.x;
const dy = planet.y - spaceship.y;
const distance = Math.sqrt(dx ** 2 + dy ** 2);
// 重力の計算
if (distance > planet.radius) {
const force = (G * planet.mass) / (distance ** 2);
const angle = Math.atan2(dy, dx);
const ax = force * Math.cos(angle);
const ay = force * Math.sin(angle);
spaceship.vx += ax;
spaceship.vy += ay;
}
// 宇宙船の移動
spaceship.x += spaceship.vx;
spaceship.y += spaceship.vy;
// 画面外に出た場合の処理
if (spaceship.x < 0 || spaceship.x > canvas.width || spaceship.y < 0 || spaceship.y > canvas.height) {
resetSpaceship();
}
actualSpeedValue.textContent = calculateSpeed().toFixed(2);
}
// 描画
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 恒星
ctx.beginPath();
ctx.arc(centerStar.x, centerStar.y, centerStar.radius, 0, Math.PI * 2);
ctx.fillStyle = 'yellow';
ctx.fill();
// 惑星
ctx.beginPath();
ctx.arc(planet.x, planet.y, planet.radius, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
// 宇宙船
ctx.beginPath();
ctx.arc(spaceship.x, spaceship.y, spaceship.radius, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
}
// アニメーションループ
function animate() {
update();
draw();
if (isRunning) {
animationId = requestAnimationFrame(animate);
}
}
// UIイベント
document.getElementById('startButton').addEventListener('click', () => {
if (!isRunning) {
isRunning = true;
animate();
}
});
document.getElementById('stopButton').addEventListener('click', () => {
isRunning = false;
cancelAnimationFrame(animationId);
});
document.getElementById('resetButton').addEventListener('click', () => {
resetSpaceship();
isRunning = false;
cancelAnimationFrame(animationId);
draw();
actualSpeedValue.textContent = calculateSpeed().toFixed(2);
});
document.getElementById('speedSlider').addEventListener('input', () => {
spaceship.vx = parseFloat(speedSlider.value);
speedValue.textContent = speedSlider.value;
});
draw();
</script>
</body>
</html>

文字で読むよりシュミレーションで見る方がよくわかりますね。
チャットに「宇宙船が公転する惑星によるスイングバイのシュミレーションプログラムをJavascriptで作って。」と入力して作りました。
スタートボタンなど配置やスピードの変更などを追加しました。
AIは、全くエラー構文を作らずにプログラムを作っています。
ここまで、20分くらいでした。
ただDeepseekの回答が途切れることがありました。その都度、新規に始めて続けました。
チャットに入力する際、日本語は普通に使えますが漢字変換後の確定のためのエンターキーで送信されてしまうので注意が必要です。
スマホ版はDeepseekではうまくできませんでした。そこでChatGDPで作ってもらいました。作成速度は同じくらいですが、安定していました。


