35845-vm/assets/js/simulator.js
Flatlogic Bot 390ee703a3 simulator
2025-11-19 15:06:22 +00:00

142 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

document.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('simulationCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const launchButton = document.getElementById('launchButton');
const velocityInput = document.getElementById('velocity');
const resultMessage = document.getElementById('result-message');
// --- Параметры симуляции ---
const GRAVITY = 9.8; // Ускорение свободного падения (м/с^2)
const ESCAPE_VELOCITY = 11200; // Вторая космическая скорость (м/с)
const PIXELS_PER_METER = 0.005; // Масштаб: сколько пикселей в одном метре
const TIME_STEP = 2.0; // Шаг времени для симуляции (влияет на скорость анимации)
let rocket = {};
let animationFrameId;
let initialVelocity = 0;
function initializeRocket() {
return {
x: canvas.width / 2,
y: canvas.height - 45, // Позиция на холсте (пиксели)
width: 10,
height: 25,
// Физические свойства
y_meters: 0, // Высота в метрах
velocityY_meters_per_sec: 0, // Скорость в м/с
};
}
function drawEarth() {
ctx.fillStyle = '#2c5c23';
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height + canvas.height - 50, canvas.height, 0, Math.PI, true);
ctx.fill();
}
function drawRocket() {
ctx.fillStyle = '#d0d0d0';
ctx.beginPath();
ctx.moveTo(rocket.x, rocket.y - rocket.height / 2);
ctx.lineTo(rocket.x - rocket.width / 2, rocket.y + rocket.height / 2);
ctx.lineTo(rocket.x + rocket.width / 2, rocket.y + rocket.height / 2);
ctx.closePath();
ctx.fill();
}
function resetSimulation() {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
initialVelocity = 0;
rocket = initializeRocket();
resultMessage.innerHTML = ' ';
resultMessage.className = 'alert alert-secondary';
clearCanvas();
drawEarth();
drawRocket();
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function animate() {
// 1. Обновляем физику (пошаговая симуляция)
// Уменьшаем скорость под действием гравитации
rocket.velocityY_meters_per_sec -= GRAVITY * TIME_STEP;
// Обновляем высоту на основе новой скорости
rocket.y_meters += rocket.velocityY_meters_per_sec * TIME_STEP;
// 2. Обновляем позицию для отрисовки
const groundY = canvas.height - 45;
rocket.y = groundY - (rocket.y_meters * PIXELS_PER_METER);
// 3. Отрисовываем сцену
clearCanvas();
drawEarth();
drawRocket();
// 4. Проверяем условия завершения
const hasEscaped = initialVelocity >= ESCAPE_VELOCITY && rocket.y < -rocket.height;
const hasCrashed = rocket.y_meters <= 0 && initialVelocity < ESCAPE_VELOCITY;
if (hasEscaped) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
return;
}
if (hasCrashed) {
// Фиксируем ракету на земле
rocket.y_meters = 0;
rocket.y = groundY;
clearCanvas();
drawEarth();
drawRocket();
resultMessage.innerHTML = "<strong>Неудача.</strong> Ракета упала обратно на Землю.";
resultMessage.className = 'alert alert-danger';
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
return;
}
// Продолжаем анимацию
animationFrameId = requestAnimationFrame(animate);
}
launchButton.addEventListener('click', () => {
const velocityValue = parseFloat(velocityInput.value);
if (isNaN(velocityValue) || velocityValue < 0) {
resultMessage.innerHTML = 'Пожалуйста, введите положительное число.';
resultMessage.className = 'alert alert-warning';
return;
}
resetSimulation();
initialVelocity = velocityValue;
rocket.velocityY_meters_per_sec = initialVelocity;
if (initialVelocity >= ESCAPE_VELOCITY) {
resultMessage.innerHTML = "<strong>Успешный запуск!</strong> Ракета улетит в космос.";
resultMessage.className = 'alert alert-success';
} else {
resultMessage.innerHTML = "Запуск... Ракета должна упасть.";
resultMessage.className = 'alert alert-info';
}
if (!animationFrameId) {
animationFrameId = requestAnimationFrame(animate);
}
});
// Начальная отрисовка
resetSimulation();
});