Изменить 'wbld/orbits.html'
This commit is contained in:
519
wbld/orbits.html
519
wbld/orbits.html
@@ -1,312 +1,289 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Senthara Orbit, Rotation & Day/Night Visualization</title>
|
<title>Senthara Orbit, Rotation, Day/Night & Elliptical Orbits</title>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body { margin: 0; overflow: hidden; }
|
body { margin: 0; overflow: hidden; }
|
||||||
canvas { display: block; }
|
canvas { display: block; }
|
||||||
/* Style for the control panel */
|
/* Style for the control panel */
|
||||||
#controlPanel {
|
#controlPanel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
#controlPanel button, #controlPanel select {
|
#controlPanel button, #controlPanel select {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
color: black;
|
color: black;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
#controlPanel button:hover {
|
#controlPanel button:hover, #controlPanel select:hover {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
#controlPanel select:hover {
|
</style>
|
||||||
background-color: #ddd;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="controlPanel">
|
<div id="controlPanel">
|
||||||
<button id="playPauseButton">Play</button>
|
<button id="playPauseButton">Play</button>
|
||||||
<button id="rewindButton">Rewind</button>
|
<button id="rewindButton">Rewind</button>
|
||||||
<select id="speedSelect">
|
<select id="speedSelect">
|
||||||
<option value="1">x1</option>
|
<option value="1">x1</option>
|
||||||
<option value="2">x2</option>
|
<option value="2">x2</option>
|
||||||
<option value="5" selected>x5</option>
|
<option value="5" selected>x5</option>
|
||||||
<option value="10">x10</option>
|
<option value="10">x10</option>
|
||||||
<option value="100">x100</option>
|
<option value="100">x100</option>
|
||||||
<option value="1000">x1000</option>
|
<option value="1000">x1000</option>
|
||||||
<option value="1000">x1000</option>
|
<option value="10000">x10000</option>
|
||||||
<option value="10000">x10000</option>
|
<option value="100000">x100000</option>
|
||||||
<option value="100000">x100000</option>
|
<option value="1000000">x1000000</option>
|
||||||
<option value="1000000">x1000000</option>
|
</select>
|
||||||
</select>
|
</div>
|
||||||
</div>
|
<script>
|
||||||
|
// Helper: returns {x, y} for an elliptical orbit.
|
||||||
|
// a = semi-major axis, ecc = eccentricity, so semi-minor axis b = a*sqrt(1 - ecc^2).
|
||||||
|
// theta is a linear parameter based on simulation time (not the true anomaly, but sufficient for visualization).
|
||||||
|
function getEllipticalPosition(simTime, period, a, ecc) {
|
||||||
|
const theta = Phaser.Math.DegToRad((360 * (simTime % period)) / period - 90);
|
||||||
|
const b = a * Math.sqrt(1 - ecc * ecc);
|
||||||
|
return { x: a * Math.cos(theta), y: b * Math.sin(theta) };
|
||||||
|
}
|
||||||
|
|
||||||
<script>
|
// Function to calculate the current Senthara date from simulationTime (in days),
|
||||||
// Function to calculate the current Senthara date from simulationTime (in days)
|
// with an offset so that simulationTime=0 corresponds to "Autumn 36".
|
||||||
function getSentharaDate(simDays) {
|
function getSentharaDate(simDays) {
|
||||||
const offset = 134;
|
const offset = 134;
|
||||||
const X = Math.floor(simDays + offset);
|
const X = Math.floor(simDays + offset);
|
||||||
const year = Math.floor(X / 396) + 1;
|
const year = Math.floor(X / 396) + 1;
|
||||||
const dayOfYear = (X % 396) + 1;
|
const dayOfYear = (X % 396) + 1;
|
||||||
const seasonIndex = Math.floor((dayOfYear - 1) / 99);
|
const seasonIndex = Math.floor((dayOfYear - 1) / 99);
|
||||||
const dayOfSeason = dayOfYear - seasonIndex * 99;
|
const dayOfSeason = dayOfYear - seasonIndex * 99;
|
||||||
const seasons = ["Summer", "Autumn", "Winter", "Spring"];
|
const seasons = ["Summer", "Autumn", "Winter", "Spring"];
|
||||||
return `Year ${year} - ${seasons[seasonIndex]} ${dayOfSeason}`;
|
return `Year ${year} - ${seasons[seasonIndex]} ${dayOfSeason}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phaser configuration
|
// Phaser configuration (responsive)
|
||||||
const config = {
|
const config = {
|
||||||
type: Phaser.AUTO,
|
type: Phaser.AUTO,
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
height: window.innerHeight,
|
height: window.innerHeight,
|
||||||
backgroundColor: "#000000",
|
backgroundColor: "#000000",
|
||||||
scene: {
|
scene: {
|
||||||
preload: preload,
|
preload: preload,
|
||||||
create: create,
|
create: create,
|
||||||
update: update
|
update: update
|
||||||
},
|
},
|
||||||
scale: {
|
scale: {
|
||||||
mode: Phaser.Scale.RESIZE
|
mode: Phaser.Scale.RESIZE
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const game = new Phaser.Game(config);
|
const game = new Phaser.Game(config);
|
||||||
|
|
||||||
let globalGraphics;
|
let globalGraphics;
|
||||||
let dateText;
|
let dateText;
|
||||||
let simulationTime = 0;
|
let simulationTime = 0; // in days (simulation time)
|
||||||
let simulationSpeed = 5;
|
let simulationSpeed = 5; // speed multiplier
|
||||||
let isPlaying = false;
|
let isPlaying = false; // Start paused
|
||||||
let isRewinding = false;
|
let isRewinding = false; // Control forward/backward
|
||||||
|
|
||||||
// Orbital parameters (in days and relative units)
|
// Orbital periods (in days)
|
||||||
const planetPeriod = 396;
|
const planetPeriod = 396; // Senthara's orbital year around its star
|
||||||
const planetRotationPeriod = 1;
|
const planetRotationPeriod = 1; // Planet rotates fully in 1 day
|
||||||
const kerielPeriod = 27;
|
const kerielPeriod = 27;
|
||||||
const arkaenPeriod = 82;
|
const arkaenPeriod = 82;
|
||||||
const minianPeriod = 98;
|
const minianPeriod = 98;
|
||||||
|
|
||||||
// Orbital radii and eccentricities
|
// Eccentricity parameters (0 = circle; higher values = more elliptical)
|
||||||
let planetOrbitRadius, kerielOrbitRadius, arkaenOrbitRadius, minianOrbitRadius;
|
const planetEcc = 0.2; // Planet's orbit eccentricity
|
||||||
const planetEccentricity = 0.2; // Example eccentricity for Senthara
|
const kerielEcc = 0.05; // Moons tend to have near-circular orbits due to tidal locking
|
||||||
const kerielEccentricity = 0.1;
|
const arkaenEcc = 0.05;
|
||||||
const arkaenEccentricity = 0.15;
|
const minianEcc = 0.05;
|
||||||
const minianEccentricity = 0.05;
|
|
||||||
|
|
||||||
// Angle offsets
|
// Orbital radii (semi-major axes) (computed relative to window size)
|
||||||
let planetAngleOffset;
|
let planetOrbitRadius, kerielOrbitRadius, arkaenOrbitRadius, minianOrbitRadius;
|
||||||
let kerielAngleOffset;
|
|
||||||
let arkaenAngleOffset;
|
|
||||||
let minianAngleOffset;
|
|
||||||
|
|
||||||
// Containers
|
// Containers for the planet and the moons.
|
||||||
let planetContainer;
|
let planetContainer;
|
||||||
let kerielContainer, arkaenContainer, minianContainer;
|
let kerielContainer, arkaenContainer, minianContainer;
|
||||||
|
|
||||||
function preload() {
|
function preload() {
|
||||||
// No external assets are needed.
|
// No external assets are needed.
|
||||||
}
|
}
|
||||||
function create() {
|
|
||||||
globalGraphics = this.add.graphics();
|
|
||||||
dateText = this.add.text(10, game.scale.height - 30, "", { font: "20px Arial", fill: "#ffffff" });
|
|
||||||
|
|
||||||
recalcOrbitRadii();
|
function create() {
|
||||||
setRandomAngleOffsets();
|
globalGraphics = this.add.graphics();
|
||||||
|
|
||||||
planetContainer = this.add.container(0, 0);
|
dateText = this.add.text(10, game.scale.height - 30, "", {
|
||||||
let planetBody = this.add.graphics();
|
font: "20px Arial",
|
||||||
planetBody.fillStyle(0x00FF00, 1);
|
fill: "#ffffff"
|
||||||
planetBody.fillCircle(0, 0, 12);
|
});
|
||||||
planetBody.lineStyle(2, 0x000000, 1);
|
|
||||||
planetBody.beginPath();
|
|
||||||
planetBody.moveTo(0, 0);
|
|
||||||
planetBody.lineTo(12, 0);
|
|
||||||
planetBody.strokePath();
|
|
||||||
planetContainer.add(planetBody);
|
|
||||||
|
|
||||||
let nightOverlay = this.add.graphics();
|
recalcOrbitRadii();
|
||||||
nightOverlay.fillStyle(0x000000, 0.5);
|
|
||||||
nightOverlay.slice(0, 0, 12, 0, Math.PI, false);
|
|
||||||
nightOverlay.fillPath();
|
|
||||||
planetContainer.nightOverlay = nightOverlay;
|
|
||||||
planetContainer.add(nightOverlay);
|
|
||||||
|
|
||||||
kerielContainer = createMoonContainer(this, 6, 0xFF0000);
|
// Create container for Senthara (the planet)
|
||||||
arkaenContainer = createMoonContainer(this, 5, 0x0000FF);
|
planetContainer = this.add.container(0, 0);
|
||||||
minianContainer = createMoonContainer(this, 5, 0xFFFFFF);
|
// Planet body (green circle) with a marker line.
|
||||||
|
let planetBody = this.add.graphics();
|
||||||
|
planetBody.fillStyle(0x00FF00, 1);
|
||||||
|
planetBody.fillCircle(0, 0, 12);
|
||||||
|
planetBody.lineStyle(2, 0x000000, 1);
|
||||||
|
planetBody.beginPath();
|
||||||
|
planetBody.moveTo(0, 0);
|
||||||
|
planetBody.lineTo(12, 0);
|
||||||
|
planetBody.strokePath();
|
||||||
|
planetContainer.add(planetBody);
|
||||||
|
|
||||||
this.scale.on('resize', (gameSize) => {
|
// Night overlay for day/night cycle (semi-transparent half-circle)
|
||||||
recalcOrbitRadii();
|
let nightOverlay = this.add.graphics();
|
||||||
dateText.setPosition(10, gameSize.height - 30);
|
nightOverlay.fillStyle(0x000000, 0.5);
|
||||||
});
|
nightOverlay.slice(0, 0, 12, 0, Math.PI, false);
|
||||||
|
nightOverlay.fillPath();
|
||||||
|
planetContainer.nightOverlay = nightOverlay;
|
||||||
|
planetContainer.add(nightOverlay);
|
||||||
|
|
||||||
const playPauseButton = document.getElementById("playPauseButton");
|
// Create containers for each moon.
|
||||||
const rewindButton = document.getElementById("rewindButton");
|
kerielContainer = createMoonContainer(this, 6, 0xFF0000); // Keriel: red
|
||||||
const speedSelect = document.getElementById("speedSelect");
|
arkaenContainer = createMoonContainer(this, 5, 0x0000FF); // Arkaen: blue
|
||||||
|
minianContainer = createMoonContainer(this, 5, 0xFFFFFF); // Minian: white
|
||||||
|
|
||||||
playPauseButton.addEventListener("click", () => {
|
// UI Control Handlers
|
||||||
isPlaying = !isPlaying;
|
const playPauseButton = document.getElementById("playPauseButton");
|
||||||
playPauseButton.textContent = isPlaying ? "Pause" : "Play";
|
const rewindButton = document.getElementById("rewindButton");
|
||||||
if (isPlaying) isRewinding = false;
|
const speedSelect = document.getElementById("speedSelect");
|
||||||
});
|
|
||||||
|
|
||||||
rewindButton.addEventListener("click", () => {
|
playPauseButton.addEventListener("click", () => {
|
||||||
isRewinding = !isRewinding;
|
isPlaying = !isPlaying;
|
||||||
rewindButton.textContent = isRewinding ? "Forward" : "Rewind";
|
playPauseButton.textContent = isPlaying ? "Pause" : "Play";
|
||||||
if (isRewinding) isPlaying = false;
|
if (isPlaying) isRewinding = false;
|
||||||
playPauseButton.textContent = "Play";
|
});
|
||||||
});
|
|
||||||
|
|
||||||
speedSelect.addEventListener("change", () => {
|
rewindButton.addEventListener("click", () => {
|
||||||
simulationSpeed = parseFloat(speedSelect.value);
|
isRewinding = !isRewinding;
|
||||||
});
|
rewindButton.textContent = isRewinding ? "Forward" : "Rewind";
|
||||||
}
|
if(isRewinding) isPlaying = false;
|
||||||
function createMoonContainer(scene, radius, color) {
|
playPauseButton.textContent = "Play";
|
||||||
let moonContainer = scene.add.container(0, 0);
|
});
|
||||||
let moonBody = scene.add.graphics();
|
|
||||||
moonBody.fillStyle(color, 1);
|
|
||||||
moonBody.fillCircle(0, 0, radius);
|
|
||||||
moonBody.lineStyle(2, 0x000000, 1);
|
|
||||||
moonBody.beginPath();
|
|
||||||
moonBody.moveTo(0, 0);
|
|
||||||
moonBody.lineTo(radius, 0);
|
|
||||||
moonBody.strokePath();
|
|
||||||
moonContainer.add(moonBody);
|
|
||||||
return moonContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recalculate orbital radii based on the current window size.
|
speedSelect.addEventListener("change", () => {
|
||||||
function recalcOrbitRadii() {
|
simulationSpeed = parseFloat(speedSelect.value);
|
||||||
const minDim = Math.min(window.innerWidth, window.innerHeight);
|
});
|
||||||
planetOrbitRadius = minDim * 0.3;
|
|
||||||
kerielOrbitRadius = planetOrbitRadius * 0.25;
|
|
||||||
arkaenOrbitRadius = planetOrbitRadius * 0.35;
|
|
||||||
minianOrbitRadius = planetOrbitRadius * 0.45;
|
|
||||||
}
|
|
||||||
// Sets random angle offsets.
|
|
||||||
function setRandomAngleOffsets() {
|
|
||||||
planetAngleOffset = Phaser.Math.RND.between(0, 360);
|
|
||||||
kerielAngleOffset = Phaser.Math.RND.between(0, 360);
|
|
||||||
arkaenAngleOffset = Phaser.Math.RND.between(0, 360);
|
|
||||||
minianAngleOffset = Phaser.Math.RND.between(0, 360);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculates position on an ellipse.
|
this.scale.on('resize', (gameSize) => {
|
||||||
function calculateEllipsePosition(centerX, centerY, semiMajorAxis, eccentricity, period, time, angleOffset) {
|
recalcOrbitRadii();
|
||||||
const meanAnomaly = (2 * Math.PI * (time % period)) / period;
|
dateText.setPosition(10, gameSize.height - 30);
|
||||||
// Approximate eccentric anomaly using Newton-Raphson method
|
});
|
||||||
let eccentricAnomaly = approximateEccentricAnomaly(meanAnomaly, eccentricity);
|
}
|
||||||
|
|
||||||
// Calculate the true anomaly
|
// Helper function to create a moon container with a circular body and a marker.
|
||||||
const trueAnomaly = 2 * Math.atan2(
|
function createMoonContainer(scene, radius, color) {
|
||||||
Math.sqrt(1 + eccentricity) * Math.sin(eccentricAnomaly / 2),
|
let moonContainer = scene.add.container(0, 0);
|
||||||
Math.sqrt(1 - eccentricity) * Math.cos(eccentricAnomaly / 2)
|
let moonBody = scene.add.graphics();
|
||||||
);
|
moonBody.fillStyle(color, 1);
|
||||||
|
moonBody.fillCircle(0, 0, radius);
|
||||||
|
moonBody.lineStyle(2, 0x000000, 1);
|
||||||
|
moonBody.beginPath();
|
||||||
|
moonBody.moveTo(0, 0);
|
||||||
|
moonBody.lineTo(radius, 0);
|
||||||
|
moonBody.strokePath();
|
||||||
|
moonContainer.add(moonBody);
|
||||||
|
return moonContainer;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate distance from the center
|
// Recalculate orbital radii based on window size.
|
||||||
const distance = semiMajorAxis * (1 - eccentricity * Math.cos(eccentricAnomaly));
|
function recalcOrbitRadii() {
|
||||||
|
const minDim = Math.min(window.innerWidth, window.innerHeight);
|
||||||
|
planetOrbitRadius = minDim * 0.3; // semi-major axis for planet orbit
|
||||||
|
kerielOrbitRadius = planetOrbitRadius * 0.25;
|
||||||
|
arkaenOrbitRadius = planetOrbitRadius * 0.35;
|
||||||
|
minianOrbitRadius = planetOrbitRadius * 0.45;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate x and y coordinates, with angle offset
|
function update(time, delta) {
|
||||||
const x = centerX + distance * Math.cos(trueAnomaly + Phaser.Math.DegToRad(angleOffset));
|
// Advance or rewind simulation time.
|
||||||
const y = centerY + distance * Math.sin(trueAnomaly + Phaser.Math.DegToRad(angleOffset));
|
if (isPlaying) {
|
||||||
|
simulationTime += (delta * simulationSpeed) / 1000;
|
||||||
|
} else if (isRewinding) {
|
||||||
|
simulationTime -= (delta * simulationSpeed) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
return { x, y };
|
const centerX = game.scale.width / 2;
|
||||||
}
|
const centerY = game.scale.height / 2;
|
||||||
// Approximates the eccentric anomaly using the Newton-Raphson method.
|
|
||||||
function approximateEccentricAnomaly(meanAnomaly, eccentricity) {
|
|
||||||
let E = meanAnomaly; // Initial guess
|
|
||||||
let delta = 1;
|
|
||||||
|
|
||||||
// Iterate until the change is small enough (e.g., less than 0.0001)
|
globalGraphics.clear();
|
||||||
while (delta > 0.0001) {
|
|
||||||
let nextE = E - (E - eccentricity * Math.sin(E) - meanAnomaly) / (1 - eccentricity * Math.cos(E));
|
|
||||||
delta = Math.abs(nextE - E);
|
|
||||||
E = nextE;
|
|
||||||
}
|
|
||||||
return E;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(time, delta) {
|
// Draw the central star.
|
||||||
if (isPlaying) {
|
globalGraphics.fillStyle(0xFFFF00, 1);
|
||||||
simulationTime += (delta * simulationSpeed) / 1000;
|
globalGraphics.fillCircle(centerX, centerY, 20);
|
||||||
} else if (isRewinding) {
|
|
||||||
simulationTime -= (delta * simulationSpeed) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
const centerX = game.scale.width / 2;
|
// Draw the planet's elliptical orbital path around the star.
|
||||||
const centerY = game.scale.height / 2;
|
const bPlanet = planetOrbitRadius * Math.sqrt(1 - planetEcc * planetEcc);
|
||||||
|
globalGraphics.lineStyle(1, 0x555555, 1);
|
||||||
|
globalGraphics.strokeEllipse(centerX, centerY, 2 * planetOrbitRadius, 2 * bPlanet);
|
||||||
|
|
||||||
globalGraphics.clear();
|
// Get planet's position on its elliptical orbit.
|
||||||
globalGraphics.fillStyle(0xFFFF00, 1);
|
const planetPos = getEllipticalPosition(simulationTime, planetPeriod, planetOrbitRadius, planetEcc);
|
||||||
globalGraphics.fillCircle(centerX, centerY, 20);
|
const planetX = centerX + planetPos.x;
|
||||||
|
const planetY = centerY + planetPos.y;
|
||||||
|
|
||||||
// Calculate and draw Senthara's elliptical orbit
|
// Update planet container position.
|
||||||
const planetPos = calculateEllipsePosition(centerX, centerY, planetOrbitRadius, planetEccentricity, planetPeriod, simulationTime, planetAngleOffset);
|
planetContainer.x = planetX;
|
||||||
planetContainer.x = planetPos.x;
|
planetContainer.y = planetY;
|
||||||
planetContainer.y = planetPos.y;
|
// Planet rotates about its own axis with a 1-day period.
|
||||||
|
const planetRotationAngle = Phaser.Math.DegToRad((360 * (simulationTime % planetRotationPeriod)) / planetRotationPeriod);
|
||||||
|
planetContainer.rotation = planetRotationAngle;
|
||||||
|
|
||||||
const planetRotationAngle = Phaser.Math.DegToRad((360 * (simulationTime % planetRotationPeriod)) / planetRotationPeriod);
|
// Update night overlay so that the dark half covers the hemisphere away from the star.
|
||||||
planetContainer.rotation = planetRotationAngle;
|
const subsolarAngle = Phaser.Math.Angle.Between(planetX, planetY, centerX, centerY);
|
||||||
|
planetContainer.nightOverlay.rotation = subsolarAngle + Math.PI / 2 - planetContainer.rotation;
|
||||||
|
|
||||||
const subsolarAngle = Phaser.Math.Angle.Between(planetPos.x, planetPos.y, centerX, centerY);
|
// Draw moon orbital paths (elliptical) around Senthara.
|
||||||
planetContainer.nightOverlay.rotation = subsolarAngle + Math.PI / 2 - planetContainer.rotation;
|
// For each moon, compute semi-minor axis: b = a * sqrt(1 - ecc^2).
|
||||||
|
const bKeriel = kerielOrbitRadius * Math.sqrt(1 - kerielEcc * kerielEcc);
|
||||||
|
const bArkaen = arkaenOrbitRadius * Math.sqrt(1 - arkaenEcc * arkaenEcc);
|
||||||
|
const bMinian = minianOrbitRadius * Math.sqrt(1 - minianEcc * minianEcc);
|
||||||
|
globalGraphics.lineStyle(1, 0x888888, 1);
|
||||||
|
globalGraphics.strokeEllipse(planetX, planetY, 2 * kerielOrbitRadius, 2 * bKeriel);
|
||||||
|
globalGraphics.strokeEllipse(planetX, planetY, 2 * arkaenOrbitRadius, 2 * bArkaen);
|
||||||
|
globalGraphics.strokeEllipse(planetX, planetY, 2 * minianOrbitRadius, 2 * bMinian);
|
||||||
|
|
||||||
// Calculate and update moon positions (relative to Senthara, using elliptical orbits)
|
// Calculate and update moon positions relative to Senthara.
|
||||||
const kerielPos = calculateEllipsePosition(planetPos.x, planetPos.y, kerielOrbitRadius, kerielEccentricity, kerielPeriod, simulationTime, kerielAngleOffset);
|
// Keriel:
|
||||||
kerielContainer.x = kerielPos.x;
|
const kerielPos = getEllipticalPosition(simulationTime, kerielPeriod, kerielOrbitRadius, kerielEcc);
|
||||||
kerielContainer.y = kerielPos.y;
|
const kerielX = planetX + kerielPos.x;
|
||||||
kerielContainer.rotation = Phaser.Math.Angle.Between(kerielPos.x, kerielPos.y, planetPos.x, planetPos.y);
|
const kerielY = planetY + kerielPos.y;
|
||||||
|
kerielContainer.x = kerielX;
|
||||||
|
kerielContainer.y = kerielY;
|
||||||
|
kerielContainer.rotation = Phaser.Math.Angle.Between(kerielX, kerielY, planetX, planetY);
|
||||||
|
|
||||||
const arkaenPos = calculateEllipsePosition(planetPos.x, planetPos.y, arkaenOrbitRadius, arkaenEccentricity, arkaenPeriod, simulationTime, arkaenAngleOffset);
|
// Arkaen:
|
||||||
arkaenContainer.x = arkaenPos.x;
|
const arkaenPos = getEllipticalPosition(simulationTime, arkaenPeriod, arkaenOrbitRadius, arkaenEcc);
|
||||||
arkaenContainer.y = arkaenPos.y;
|
const arkaenX = planetX + arkaenPos.x;
|
||||||
arkaenContainer.rotation = Phaser.Math.Angle.Between(arkaenPos.x, arkaenPos.y, planetPos.x, planetPos.y);
|
const arkaenY = planetY + arkaenPos.y;
|
||||||
|
arkaenContainer.x = arkaenX;
|
||||||
|
arkaenContainer.y = arkaenY;
|
||||||
|
arkaenContainer.rotation = Phaser.Math.Angle.Between(arkaenX, arkaenY, planetX, planetY);
|
||||||
|
|
||||||
const minianPos = calculateEllipsePosition(planetPos.x, planetPos.y, minianOrbitRadius, minianEccentricity, minianPeriod, simulationTime, minianAngleOffset);
|
// Minian:
|
||||||
minianContainer.x = minianPos.x;
|
const minianPos = getEllipticalPosition(simulationTime, minianPeriod, minianOrbitRadius, minianEcc);
|
||||||
minianContainer.y = minianPos.y;
|
const minianX = planetX + minianPos.x;
|
||||||
minianContainer.rotation = Phaser.Math.Angle.Between(minianPos.x, minianPos.y, planetPos.x, planetPos.y);
|
const minianY = planetY + minianPos.y;
|
||||||
|
minianContainer.x = minianX;
|
||||||
|
minianContainer.y = minianY;
|
||||||
|
minianContainer.rotation = Phaser.Math.Angle.Between(minianX, minianY, planetX, planetY);
|
||||||
|
|
||||||
// Draw elliptical orbits (optional, for visualization)
|
// Update the Senthara calendar date text.
|
||||||
drawEllipticalOrbit(globalGraphics, centerX, centerY, planetOrbitRadius, planetEccentricity, planetAngleOffset);
|
dateText.setText(getSentharaDate(simulationTime));
|
||||||
drawEllipticalOrbit(globalGraphics, planetPos.x, planetPos.y, kerielOrbitRadius, kerielEccentricity, kerielAngleOffset);
|
}
|
||||||
drawEllipticalOrbit(globalGraphics, planetPos.x, planetPos.y, arkaenOrbitRadius, arkaenEccentricity, arkaenAngleOffset);
|
</script>
|
||||||
drawEllipticalOrbit(globalGraphics, planetPos.x, planetPos.y, minianOrbitRadius, minianEccentricity, minianAngleOffset);
|
|
||||||
|
|
||||||
dateText.setText(getSentharaDate(simulationTime));
|
|
||||||
}
|
|
||||||
// Helper function to draw an elliptical orbit using Phaser graphics.
|
|
||||||
function drawEllipticalOrbit(graphics, centerX, centerY, semiMajorAxis, eccentricity, angleOffset) {
|
|
||||||
const points = [];
|
|
||||||
const steps = 100; // Number of points to create a smooth curve
|
|
||||||
for (let i = 0; i <= steps; i++) {
|
|
||||||
const meanAnomaly = (2 * Math.PI * i) / steps;
|
|
||||||
const eccentricAnomaly = approximateEccentricAnomaly(meanAnomaly, eccentricity);
|
|
||||||
const trueAnomaly = 2 * Math.atan2(
|
|
||||||
Math.sqrt(1 + eccentricity) * Math.sin(eccentricAnomaly / 2),
|
|
||||||
Math.sqrt(1 - eccentricity) * Math.cos(eccentricAnomaly / 2)
|
|
||||||
);
|
|
||||||
const distance = semiMajorAxis * (1 - eccentricity * Math.cos(eccentricAnomaly));
|
|
||||||
const x = centerX + distance * Math.cos(trueAnomaly + Phaser.Math.DegToRad(angleOffset));
|
|
||||||
const y = centerY + distance * Math.sin(trueAnomaly + Phaser.Math.DegToRad(angleOffset));
|
|
||||||
points.push(new Phaser.Math.Vector2(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics.lineStyle(1, 0x888888, 1); // Set orbit line style
|
|
||||||
graphics.strokePoints(points, true); // Draw the ellipse
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user