Spaces:
Running
Running
Add 1 files
Browse files- index.html +273 -98
index.html
CHANGED
|
@@ -56,6 +56,44 @@
|
|
| 56 |
position: relative;
|
| 57 |
height: 400px;
|
| 58 |
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
}
|
| 60 |
|
| 61 |
.rocket-3d {
|
|
@@ -65,6 +103,7 @@
|
|
| 65 |
bottom: 0;
|
| 66 |
left: 50%;
|
| 67 |
transform: translateX(-50%);
|
|
|
|
| 68 |
}
|
| 69 |
|
| 70 |
.flame {
|
|
@@ -150,7 +189,7 @@
|
|
| 150 |
100% { opacity: 1; }
|
| 151 |
}
|
| 152 |
|
| 153 |
-
/*
|
| 154 |
.launch-smoke {
|
| 155 |
position: absolute;
|
| 156 |
bottom: 0;
|
|
@@ -162,6 +201,7 @@
|
|
| 162 |
border-radius: 50%;
|
| 163 |
filter: blur(10px);
|
| 164 |
opacity: 0;
|
|
|
|
| 165 |
}
|
| 166 |
|
| 167 |
.launching .launch-smoke {
|
|
@@ -274,6 +314,7 @@
|
|
| 274 |
justify-content: center;
|
| 275 |
opacity: 0;
|
| 276 |
transform: scale(0);
|
|
|
|
| 277 |
}
|
| 278 |
|
| 279 |
.success-animate {
|
|
@@ -285,6 +326,50 @@
|
|
| 285 |
50% { transform: scale(1.2); opacity: 1; }
|
| 286 |
100% { transform: scale(1); opacity: 1; }
|
| 287 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
</style>
|
| 289 |
</head>
|
| 290 |
<body>
|
|
@@ -303,7 +388,7 @@
|
|
| 303 |
<div class="flex items-center space-x-4">
|
| 304 |
<div class="hidden md:flex items-center space-x-2">
|
| 305 |
<i class="fas fa-coins text-yellow-400"></i>
|
| 306 |
-
<span class="font-bold" id="funds">$
|
| 307 |
</div>
|
| 308 |
<div class="hidden md:flex items-center space-x-2">
|
| 309 |
<i class="fas fa-star text-blue-400"></i>
|
|
@@ -325,8 +410,11 @@
|
|
| 325 |
<div class="bg-gray-900 rounded-xl p-6 shadow-xl border border-gray-800">
|
| 326 |
<h2 class="orbitron text-xl text-blue-400 mb-4">ROCKET DESIGN</h2>
|
| 327 |
<div class="rocket-display flex justify-center items-end" id="rocket-display">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
<div class="rocket-3d" id="rocket-model">
|
| 329 |
-
<!-- Rocket parts will be added here by JavaScript -->
|
| 330 |
<div class="flame" id="rocket-flame"></div>
|
| 331 |
<div class="launch-smoke"></div>
|
| 332 |
</div>
|
|
@@ -477,47 +565,75 @@
|
|
| 477 |
}
|
| 478 |
}
|
| 479 |
|
| 480 |
-
// Rocket parts data
|
| 481 |
const rocketParts = {
|
| 482 |
firstStages: [
|
| 483 |
-
{ id: 'falcon9', name: 'Falcon 9', cost: 5000000, mass: 25000, thrust: 7607, height: 10,
|
| 484 |
-
|
| 485 |
-
{ id: '
|
| 486 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 487 |
],
|
| 488 |
secondStages: [
|
| 489 |
-
{ id: 'falcon9-upper', name: 'Falcon 9 Upper', cost: 2000000, mass: 5000, thrust: 934, height: 6,
|
| 490 |
-
|
| 491 |
-
{ id: '
|
| 492 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 493 |
],
|
| 494 |
fairings: [
|
| 495 |
-
{ id: 'standard', name: 'Standard Fairing', cost: 1000000, mass: 2000, height: 5,
|
| 496 |
-
|
| 497 |
-
{ id: '
|
| 498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 499 |
],
|
| 500 |
engines: [
|
| 501 |
-
{ id: 'merlin', name: 'Merlin', cost: 1000000, thrust: 845, isp: 282,
|
| 502 |
-
|
| 503 |
-
{ id: '
|
| 504 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
]
|
| 506 |
};
|
| 507 |
|
| 508 |
-
// Planets data
|
| 509 |
const destinations = [
|
| 510 |
-
{ id: 'leo', name: 'Low Earth Orbit', distance: 200, difficulty: 1,
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
{ id: '
|
| 514 |
-
|
| 515 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 516 |
];
|
| 517 |
|
| 518 |
// Game state
|
| 519 |
let gameState = {
|
| 520 |
-
funds:
|
| 521 |
reputation: 100,
|
| 522 |
currentRocket: {
|
| 523 |
firstStage: null,
|
|
@@ -582,7 +698,7 @@
|
|
| 582 |
partElement.dataset.partType = partType;
|
| 583 |
|
| 584 |
partElement.innerHTML = `
|
| 585 |
-
<div class="w-16 h-16
|
| 586 |
${part.image ? `<img src="${part.image}" alt="${part.name}" class="w-full h-full object-contain">` : '<i class="fas fa-rocket text-xl"></i>'}
|
| 587 |
</div>
|
| 588 |
<h3 class="font-bold text-center">${part.name}</h3>
|
|
@@ -669,22 +785,34 @@
|
|
| 669 |
// Add parts to the rocket model
|
| 670 |
if (gameState.currentRocket.firstStage) {
|
| 671 |
const firstStage = document.createElement('div');
|
| 672 |
-
firstStage.className = `first-stage
|
| 673 |
firstStage.style.height = `${gameState.currentRocket.firstStage.height * 10}px`;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 674 |
rocketModel.appendChild(firstStage);
|
| 675 |
}
|
| 676 |
|
| 677 |
if (gameState.currentRocket.secondStage) {
|
| 678 |
const secondStage = document.createElement('div');
|
| 679 |
-
secondStage.className = `second-stage
|
| 680 |
secondStage.style.height = `${gameState.currentRocket.secondStage.height * 10}px`;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 681 |
rocketModel.appendChild(secondStage);
|
| 682 |
}
|
| 683 |
|
| 684 |
if (gameState.currentRocket.fairing && gameState.currentRocket.fairing.id !== 'none') {
|
| 685 |
const fairing = document.createElement('div');
|
| 686 |
-
fairing.className = `fairing
|
| 687 |
fairing.style.height = `${gameState.currentRocket.fairing.height * 10}px`;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 688 |
rocketModel.appendChild(fairing);
|
| 689 |
}
|
| 690 |
}
|
|
@@ -754,6 +882,10 @@
|
|
| 754 |
|
| 755 |
const rocketModel = document.getElementById('rocket-model');
|
| 756 |
const rocketDisplay = document.getElementById('rocket-display');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 757 |
const countdownElement = document.getElementById('countdown');
|
| 758 |
const stageSeparation = document.getElementById('stage-separation');
|
| 759 |
const successMarker = document.getElementById('success-marker');
|
|
@@ -761,6 +893,14 @@
|
|
| 761 |
const launchButton = document.getElementById('launch-button');
|
| 762 |
const missionName = document.getElementById('mission-name').value || `Mission ${Math.floor(Math.random() * 1000)}`;
|
| 763 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 764 |
// Disable launch button during launch
|
| 765 |
launchButton.disabled = true;
|
| 766 |
launchButton.classList.remove('bg-green-600', 'hover:bg-green-700');
|
|
@@ -774,6 +914,7 @@
|
|
| 774 |
// Reset rocket position
|
| 775 |
rocketModel.style.bottom = '0';
|
| 776 |
rocketModel.style.transform = 'translateX(-50%)';
|
|
|
|
| 777 |
|
| 778 |
// Play launch sound
|
| 779 |
playSound('launch');
|
|
@@ -832,93 +973,117 @@
|
|
| 832 |
rocketModel.classList.add('rocket-ascent');
|
| 833 |
rocketModel.classList.remove('launch-shake');
|
| 834 |
|
| 835 |
-
//
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
//
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 847 |
setTimeout(() => {
|
| 848 |
-
|
| 849 |
-
|
|
|
|
|
|
|
|
|
|
| 850 |
|
| 851 |
setTimeout(() => {
|
| 852 |
-
|
|
|
|
| 853 |
|
| 854 |
setTimeout(() => {
|
| 855 |
-
updateConsole(
|
| 856 |
|
| 857 |
-
// Show
|
| 858 |
-
|
| 859 |
-
|
| 860 |
|
| 861 |
-
//
|
| 862 |
-
|
| 863 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 864 |
|
| 865 |
setTimeout(() => {
|
| 866 |
-
updateConsole(`>
|
| 867 |
-
|
| 868 |
-
|
|
|
|
|
|
|
| 869 |
|
| 870 |
-
//
|
| 871 |
-
gameState.
|
| 872 |
-
gameState.
|
| 873 |
|
| 874 |
-
|
| 875 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 876 |
}, 2000);
|
| 877 |
}, 2000);
|
| 878 |
-
},
|
| 879 |
-
},
|
| 880 |
-
}
|
| 881 |
-
|
| 882 |
-
|
| 883 |
-
|
| 884 |
-
const failureReason = getRandomFailureReason();
|
| 885 |
-
|
| 886 |
-
setTimeout(() => {
|
| 887 |
-
// Show explosion
|
| 888 |
-
explosion.style.left = rocketModel.style.left;
|
| 889 |
-
explosion.style.top = rocketModel.style.top;
|
| 890 |
-
explosion.classList.add('explode');
|
| 891 |
-
playSound('explosion');
|
| 892 |
-
|
| 893 |
-
// Hide rocket
|
| 894 |
-
rocketModel.style.opacity = '0';
|
| 895 |
-
|
| 896 |
-
updateConsole(`> WARNING: ${failureReason}`);
|
| 897 |
-
updateConsole("> Attempting to mitigate...");
|
| 898 |
|
| 899 |
setTimeout(() => {
|
| 900 |
-
|
| 901 |
-
|
|
|
|
|
|
|
|
|
|
| 902 |
|
| 903 |
-
//
|
| 904 |
-
|
| 905 |
-
|
|
|
|
|
|
|
| 906 |
|
| 907 |
setTimeout(() => {
|
| 908 |
-
updateConsole(
|
| 909 |
-
updateConsole(
|
| 910 |
-
updateConsole("> Preparing for next attempt");
|
| 911 |
|
| 912 |
-
//
|
| 913 |
-
|
| 914 |
-
|
| 915 |
|
| 916 |
-
|
| 917 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
}, 2000);
|
| 919 |
-
},
|
| 920 |
-
}
|
| 921 |
-
}
|
| 922 |
}, 1000);
|
| 923 |
}
|
| 924 |
}
|
|
@@ -1001,6 +1166,10 @@
|
|
| 1001 |
// Reset after launch
|
| 1002 |
function resetAfterLaunch() {
|
| 1003 |
const rocketModel = document.getElementById('rocket-model');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1004 |
const launchButton = document.getElementById('launch-button');
|
| 1005 |
const explosion = document.getElementById('explosion');
|
| 1006 |
const successMarker = document.getElementById('success-marker');
|
|
@@ -1014,6 +1183,12 @@
|
|
| 1014 |
stageSeparation.classList.remove('separate');
|
| 1015 |
countdownElement.classList.remove('countdown-animate');
|
| 1016 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1017 |
// Reset rocket position and visibility
|
| 1018 |
rocketModel.style.bottom = '0';
|
| 1019 |
rocketModel.style.transform = 'translateX(-50%)';
|
|
|
|
| 56 |
position: relative;
|
| 57 |
height: 400px;
|
| 58 |
overflow: hidden;
|
| 59 |
+
background: linear-gradient(to bottom, #000000 0%, #000428 100%);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.space-view {
|
| 63 |
+
position: absolute;
|
| 64 |
+
top: 0;
|
| 65 |
+
left: 0;
|
| 66 |
+
width: 100%;
|
| 67 |
+
height: 100%;
|
| 68 |
+
background: url('https://images.unsplash.com/photo-1506318137071-a8e06380a023?q=80&w=3000') no-repeat center center;
|
| 69 |
+
background-size: cover;
|
| 70 |
+
opacity: 0;
|
| 71 |
+
transition: opacity 1s ease;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
.space-view.active {
|
| 75 |
+
opacity: 1;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
.planet-arrival {
|
| 79 |
+
position: absolute;
|
| 80 |
+
top: 50%;
|
| 81 |
+
left: 50%;
|
| 82 |
+
transform: translate(-50%, -50%);
|
| 83 |
+
width: 200px;
|
| 84 |
+
height: 200px;
|
| 85 |
+
border-radius: 50%;
|
| 86 |
+
background-size: cover;
|
| 87 |
+
background-position: center;
|
| 88 |
+
box-shadow: 0 0 50px rgba(255, 255, 255, 0.5);
|
| 89 |
+
opacity: 0;
|
| 90 |
+
transition: all 1s ease;
|
| 91 |
+
z-index: 15;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
.planet-arrival.active {
|
| 95 |
+
opacity: 1;
|
| 96 |
+
transform: translate(-50%, -50%) scale(1.5);
|
| 97 |
}
|
| 98 |
|
| 99 |
.rocket-3d {
|
|
|
|
| 103 |
bottom: 0;
|
| 104 |
left: 50%;
|
| 105 |
transform: translateX(-50%);
|
| 106 |
+
z-index: 10;
|
| 107 |
}
|
| 108 |
|
| 109 |
.flame {
|
|
|
|
| 189 |
100% { opacity: 1; }
|
| 190 |
}
|
| 191 |
|
| 192 |
+
/* Launch effects */
|
| 193 |
.launch-smoke {
|
| 194 |
position: absolute;
|
| 195 |
bottom: 0;
|
|
|
|
| 201 |
border-radius: 50%;
|
| 202 |
filter: blur(10px);
|
| 203 |
opacity: 0;
|
| 204 |
+
z-index: 5;
|
| 205 |
}
|
| 206 |
|
| 207 |
.launching .launch-smoke {
|
|
|
|
| 314 |
justify-content: center;
|
| 315 |
opacity: 0;
|
| 316 |
transform: scale(0);
|
| 317 |
+
z-index: 25;
|
| 318 |
}
|
| 319 |
|
| 320 |
.success-animate {
|
|
|
|
| 326 |
50% { transform: scale(1.2); opacity: 1; }
|
| 327 |
100% { transform: scale(1); opacity: 1; }
|
| 328 |
}
|
| 329 |
+
|
| 330 |
+
.rocket-component {
|
| 331 |
+
width: 100%;
|
| 332 |
+
height: 100%;
|
| 333 |
+
background-size: contain;
|
| 334 |
+
background-repeat: no-repeat;
|
| 335 |
+
background-position: center;
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
.rocket-in-space {
|
| 339 |
+
position: absolute;
|
| 340 |
+
width: 100px;
|
| 341 |
+
height: 200px;
|
| 342 |
+
background-size: contain;
|
| 343 |
+
background-repeat: no-repeat;
|
| 344 |
+
background-position: center;
|
| 345 |
+
opacity: 0;
|
| 346 |
+
transition: all 1s ease;
|
| 347 |
+
z-index: 15;
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
.rocket-in-space.active {
|
| 351 |
+
opacity: 1;
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
.arrival-message {
|
| 355 |
+
position: absolute;
|
| 356 |
+
top: 70%;
|
| 357 |
+
left: 50%;
|
| 358 |
+
transform: translate(-50%, -50%);
|
| 359 |
+
background: rgba(0, 0, 0, 0.7);
|
| 360 |
+
padding: 20px;
|
| 361 |
+
border-radius: 10px;
|
| 362 |
+
text-align: center;
|
| 363 |
+
opacity: 0;
|
| 364 |
+
transition: opacity 1s ease;
|
| 365 |
+
z-index: 30;
|
| 366 |
+
width: 80%;
|
| 367 |
+
max-width: 500px;
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
.arrival-message.active {
|
| 371 |
+
opacity: 1;
|
| 372 |
+
}
|
| 373 |
</style>
|
| 374 |
</head>
|
| 375 |
<body>
|
|
|
|
| 388 |
<div class="flex items-center space-x-4">
|
| 389 |
<div class="hidden md:flex items-center space-x-2">
|
| 390 |
<i class="fas fa-coins text-yellow-400"></i>
|
| 391 |
+
<span class="font-bold" id="funds">$100,000,000</span>
|
| 392 |
</div>
|
| 393 |
<div class="hidden md:flex items-center space-x-2">
|
| 394 |
<i class="fas fa-star text-blue-400"></i>
|
|
|
|
| 410 |
<div class="bg-gray-900 rounded-xl p-6 shadow-xl border border-gray-800">
|
| 411 |
<h2 class="orbitron text-xl text-blue-400 mb-4">ROCKET DESIGN</h2>
|
| 412 |
<div class="rocket-display flex justify-center items-end" id="rocket-display">
|
| 413 |
+
<div class="space-view" id="space-view"></div>
|
| 414 |
+
<div class="planet-arrival" id="planet-arrival"></div>
|
| 415 |
+
<div class="rocket-in-space" id="rocket-in-space"></div>
|
| 416 |
+
<div class="arrival-message" id="arrival-message"></div>
|
| 417 |
<div class="rocket-3d" id="rocket-model">
|
|
|
|
| 418 |
<div class="flame" id="rocket-flame"></div>
|
| 419 |
<div class="launch-smoke"></div>
|
| 420 |
</div>
|
|
|
|
| 565 |
}
|
| 566 |
}
|
| 567 |
|
| 568 |
+
// Rocket parts data with actual images
|
| 569 |
const rocketParts = {
|
| 570 |
firstStages: [
|
| 571 |
+
{ id: 'falcon9', name: 'Falcon 9', cost: 5000000, mass: 25000, thrust: 7607, height: 10,
|
| 572 |
+
color: 'bg-white', image: 'https://www.spacex.com/static/images/falcon9/falcon9-1.png' },
|
| 573 |
+
{ id: 'falcon-heavy', name: 'Falcon Heavy', cost: 9000000, mass: 40000, thrust: 22819, height: 12,
|
| 574 |
+
color: 'bg-gray-300', image: 'https://www.spacex.com/static/images/falcon-heavy/falcon-heavy-1.png' },
|
| 575 |
+
{ id: 'starship', name: 'Starship', cost: 15000000, mass: 120000, thrust: 75000, height: 18,
|
| 576 |
+
color: 'bg-gray-400', image: 'https://www.spacex.com/static/images/starship/starship-1.png' },
|
| 577 |
+
{ id: 'nova', name: 'Nova', cost: 20000000, mass: 150000, thrust: 100000, height: 20,
|
| 578 |
+
color: 'bg-blue-200', image: 'https://www.nasa.gov/wp-content/uploads/2023/06/sls_artistconcept_0.jpg?w=1536' }
|
| 579 |
],
|
| 580 |
secondStages: [
|
| 581 |
+
{ id: 'falcon9-upper', name: 'Falcon 9 Upper', cost: 2000000, mass: 5000, thrust: 934, height: 6,
|
| 582 |
+
color: 'bg-white', image: 'https://www.spacex.com/static/images/falcon9/falcon9-upper-stage.png' },
|
| 583 |
+
{ id: 'falcon-heavy-upper', name: 'Falcon Heavy Upper', cost: 3000000, mass: 8000, thrust: 934, height: 8,
|
| 584 |
+
color: 'bg-gray-300', image: 'https://www.spacex.com/static/images/falcon-heavy/falcon-heavy-upper-stage.png' },
|
| 585 |
+
{ id: 'starship-upper', name: 'Starship Upper', cost: 5000000, mass: 15000, thrust: 3000, height: 12,
|
| 586 |
+
color: 'bg-gray-400', image: 'https://www.spacex.com/static/images/starship/starship-upper-stage.png' },
|
| 587 |
+
{ id: 'nova-upper', name: 'Nova Upper', cost: 7000000, mass: 20000, thrust: 5000, height: 14,
|
| 588 |
+
color: 'bg-blue-200', image: 'https://www.nasa.gov/wp-content/uploads/2023/06/sls_upperstage_0.jpg?w=1536' }
|
| 589 |
],
|
| 590 |
fairings: [
|
| 591 |
+
{ id: 'standard', name: 'Standard Fairing', cost: 1000000, mass: 2000, height: 5,
|
| 592 |
+
color: 'bg-white', image: 'https://www.spacex.com/static/images/falcon9/fairing.png' },
|
| 593 |
+
{ id: 'extended', name: 'Extended Fairing', cost: 1500000, mass: 3000, height: 7,
|
| 594 |
+
color: 'bg-gray-300', image: 'https://www.spacex.com/static/images/falcon-heavy/extended-fairing.png' },
|
| 595 |
+
{ id: 'heavy', name: 'Heavy Fairing', cost: 2000000, mass: 4000, height: 8,
|
| 596 |
+
color: 'bg-gray-400', image: 'https://www.spacex.com/static/images/starship/heavy-fairing.png' },
|
| 597 |
+
{ id: 'none', name: 'No Fairing', cost: 0, mass: 0, height: 0,
|
| 598 |
+
color: 'transparent', image: '' }
|
| 599 |
],
|
| 600 |
engines: [
|
| 601 |
+
{ id: 'merlin', name: 'Merlin', cost: 1000000, thrust: 845, isp: 282,
|
| 602 |
+
color: 'bg-gray-500', image: 'https://www.spacex.com/static/images/falcon9/merlin-engine.png' },
|
| 603 |
+
{ id: 'raptor', name: 'Raptor', cost: 2000000, thrust: 2000, isp: 330,
|
| 604 |
+
color: 'bg-gray-600', image: 'https://www.spacex.com/static/images/starship/raptor-engine.png' },
|
| 605 |
+
{ id: 'be-4', name: 'BE-4', cost: 2500000, thrust: 2400, isp: 340,
|
| 606 |
+
color: 'bg-blue-600', image: 'https://www.blueorigin.com/assets/engines/be4/be4-engine.jpg' },
|
| 607 |
+
{ id: 'rs-25', name: 'RS-25', cost: 3000000, thrust: 1860, isp: 366,
|
| 608 |
+
color: 'bg-red-600', image: 'https://www.nasa.gov/wp-content/uploads/2023/06/rs25-engine.jpg?w=1536' }
|
| 609 |
]
|
| 610 |
};
|
| 611 |
|
| 612 |
+
// Planets data with actual images
|
| 613 |
const destinations = [
|
| 614 |
+
{ id: 'leo', name: 'Low Earth Orbit', distance: 200, difficulty: 1,
|
| 615 |
+
image: 'https://science.nasa.gov/wp-content/uploads/2023/09/iss067e092866_large.jpg?w=1536',
|
| 616 |
+
arrivalImage: 'https://science.nasa.gov/wp-content/uploads/2023/09/earth-from-space.jpg?w=1536' },
|
| 617 |
+
{ id: 'moon', name: 'The Moon', distance: 384400, difficulty: 2,
|
| 618 |
+
image: 'https://science.nasa.gov/wp-content/uploads/2023/09/webb-southern-ring-nebula-1.jpg?w=1536',
|
| 619 |
+
arrivalImage: 'https://science.nasa.gov/wp-content/uploads/2023/09/moon-surface.jpg?w=1536' },
|
| 620 |
+
{ id: 'mars', name: 'Mars', distance: 225000000, difficulty: 3,
|
| 621 |
+
image: 'https://science.nasa.gov/wp-content/uploads/2023/09/pia25980-16.jpg?w=1536',
|
| 622 |
+
arrivalImage: 'https://science.nasa.gov/wp-content/uploads/2023/09/mars-surface.jpg?w=1536' },
|
| 623 |
+
{ id: 'jupiter', name: 'Jupiter', distance: 778000000, difficulty: 4,
|
| 624 |
+
image: 'https://science.nasa.gov/wp-content/uploads/2023/09/jupiter-1.jpg?w=1536',
|
| 625 |
+
arrivalImage: 'https://science.nasa.gov/wp-content/uploads/2023/09/jupiter-closeup.jpg?w=1536' },
|
| 626 |
+
{ id: 'saturn', name: 'Saturn', distance: 1400000000, difficulty: 5,
|
| 627 |
+
image: 'https://science.nasa.gov/wp-content/uploads/2023/09/saturn-1.jpg?w=1536',
|
| 628 |
+
arrivalImage: 'https://science.nasa.gov/wp-content/uploads/2023/09/saturn-rings.jpg?w=1536' },
|
| 629 |
+
{ id: 'pluto', name: 'Pluto', distance: 5900000000, difficulty: 6,
|
| 630 |
+
image: 'https://science.nasa.gov/wp-content/uploads/2023/09/pluto-1.jpg?w=1536',
|
| 631 |
+
arrivalImage: 'https://science.nasa.gov/wp-content/uploads/2023/09/pluto-surface.jpg?w=1536' }
|
| 632 |
];
|
| 633 |
|
| 634 |
// Game state
|
| 635 |
let gameState = {
|
| 636 |
+
funds: 100000000, // $100,000,000 initial balance
|
| 637 |
reputation: 100,
|
| 638 |
currentRocket: {
|
| 639 |
firstStage: null,
|
|
|
|
| 698 |
partElement.dataset.partType = partType;
|
| 699 |
|
| 700 |
partElement.innerHTML = `
|
| 701 |
+
<div class="w-16 h-16 rounded-full mb-2 flex items-center justify-center">
|
| 702 |
${part.image ? `<img src="${part.image}" alt="${part.name}" class="w-full h-full object-contain">` : '<i class="fas fa-rocket text-xl"></i>'}
|
| 703 |
</div>
|
| 704 |
<h3 class="font-bold text-center">${part.name}</h3>
|
|
|
|
| 785 |
// Add parts to the rocket model
|
| 786 |
if (gameState.currentRocket.firstStage) {
|
| 787 |
const firstStage = document.createElement('div');
|
| 788 |
+
firstStage.className = `first-stage w-16 mx-auto`;
|
| 789 |
firstStage.style.height = `${gameState.currentRocket.firstStage.height * 10}px`;
|
| 790 |
+
firstStage.style.backgroundImage = `url(${gameState.currentRocket.firstStage.image})`;
|
| 791 |
+
firstStage.style.backgroundSize = 'contain';
|
| 792 |
+
firstStage.style.backgroundRepeat = 'no-repeat';
|
| 793 |
+
firstStage.style.backgroundPosition = 'center';
|
| 794 |
rocketModel.appendChild(firstStage);
|
| 795 |
}
|
| 796 |
|
| 797 |
if (gameState.currentRocket.secondStage) {
|
| 798 |
const secondStage = document.createElement('div');
|
| 799 |
+
secondStage.className = `second-stage w-12 mx-auto`;
|
| 800 |
secondStage.style.height = `${gameState.currentRocket.secondStage.height * 10}px`;
|
| 801 |
+
secondStage.style.backgroundImage = `url(${gameState.currentRocket.secondStage.image})`;
|
| 802 |
+
secondStage.style.backgroundSize = 'contain';
|
| 803 |
+
secondStage.style.backgroundRepeat = 'no-repeat';
|
| 804 |
+
secondStage.style.backgroundPosition = 'center';
|
| 805 |
rocketModel.appendChild(secondStage);
|
| 806 |
}
|
| 807 |
|
| 808 |
if (gameState.currentRocket.fairing && gameState.currentRocket.fairing.id !== 'none') {
|
| 809 |
const fairing = document.createElement('div');
|
| 810 |
+
fairing.className = `fairing w-16 mx-auto rounded-t-lg`;
|
| 811 |
fairing.style.height = `${gameState.currentRocket.fairing.height * 10}px`;
|
| 812 |
+
fairing.style.backgroundImage = `url(${gameState.currentRocket.fairing.image})`;
|
| 813 |
+
fairing.style.backgroundSize = 'contain';
|
| 814 |
+
fairing.style.backgroundRepeat = 'no-repeat';
|
| 815 |
+
fairing.style.backgroundPosition = 'center';
|
| 816 |
rocketModel.appendChild(fairing);
|
| 817 |
}
|
| 818 |
}
|
|
|
|
| 882 |
|
| 883 |
const rocketModel = document.getElementById('rocket-model');
|
| 884 |
const rocketDisplay = document.getElementById('rocket-display');
|
| 885 |
+
const spaceView = document.getElementById('space-view');
|
| 886 |
+
const planetArrival = document.getElementById('planet-arrival');
|
| 887 |
+
const rocketInSpace = document.getElementById('rocket-in-space');
|
| 888 |
+
const arrivalMessage = document.getElementById('arrival-message');
|
| 889 |
const countdownElement = document.getElementById('countdown');
|
| 890 |
const stageSeparation = document.getElementById('stage-separation');
|
| 891 |
const successMarker = document.getElementById('success-marker');
|
|
|
|
| 893 |
const launchButton = document.getElementById('launch-button');
|
| 894 |
const missionName = document.getElementById('mission-name').value || `Mission ${Math.floor(Math.random() * 1000)}`;
|
| 895 |
|
| 896 |
+
// Reset space view elements
|
| 897 |
+
spaceView.classList.remove('active');
|
| 898 |
+
planetArrival.classList.remove('active');
|
| 899 |
+
rocketInSpace.classList.remove('active');
|
| 900 |
+
arrivalMessage.classList.remove('active');
|
| 901 |
+
planetArrival.style.backgroundImage = '';
|
| 902 |
+
rocketInSpace.style.backgroundImage = '';
|
| 903 |
+
|
| 904 |
// Disable launch button during launch
|
| 905 |
launchButton.disabled = true;
|
| 906 |
launchButton.classList.remove('bg-green-600', 'hover:bg-green-700');
|
|
|
|
| 914 |
// Reset rocket position
|
| 915 |
rocketModel.style.bottom = '0';
|
| 916 |
rocketModel.style.transform = 'translateX(-50%)';
|
| 917 |
+
rocketModel.style.opacity = '1';
|
| 918 |
|
| 919 |
// Play launch sound
|
| 920 |
playSound('launch');
|
|
|
|
| 973 |
rocketModel.classList.add('rocket-ascent');
|
| 974 |
rocketModel.classList.remove('launch-shake');
|
| 975 |
|
| 976 |
+
// Show space view after rocket leaves the screen
|
| 977 |
+
setTimeout(() => {
|
| 978 |
+
spaceView.classList.add('active');
|
| 979 |
+
|
| 980 |
+
// Show rocket in space
|
| 981 |
+
rocketInSpace.style.backgroundImage = `url(${gameState.currentRocket.firstStage.image})`;
|
| 982 |
+
rocketInSpace.style.left = '50%';
|
| 983 |
+
rocketInSpace.style.top = '50%';
|
| 984 |
+
rocketInSpace.style.transform = 'translate(-50%, -50%)';
|
| 985 |
+
rocketInSpace.classList.add('active');
|
| 986 |
+
|
| 987 |
+
// Random mission outcome
|
| 988 |
+
const isSuccess = Math.random() < successChance;
|
| 989 |
+
|
| 990 |
+
if (isSuccess) {
|
| 991 |
+
// Successful mission
|
| 992 |
setTimeout(() => {
|
| 993 |
+
updateConsole("> First stage separation successful");
|
| 994 |
+
|
| 995 |
+
// Show stage separation effect
|
| 996 |
+
stageSeparation.classList.add('separate');
|
| 997 |
+
playSound('separation');
|
| 998 |
|
| 999 |
setTimeout(() => {
|
| 1000 |
+
stageSeparation.classList.remove('separate');
|
| 1001 |
+
updateConsole("> Second stage ignition");
|
| 1002 |
|
| 1003 |
setTimeout(() => {
|
| 1004 |
+
updateConsole("> Payload deployment confirmed");
|
| 1005 |
|
| 1006 |
+
// Show destination planet
|
| 1007 |
+
planetArrival.style.backgroundImage = `url(${gameState.currentDestination.arrivalImage})`;
|
| 1008 |
+
planetArrival.classList.add('active');
|
| 1009 |
|
| 1010 |
+
// Show arrival message
|
| 1011 |
+
arrivalMessage.innerHTML = `
|
| 1012 |
+
<h3 class="orbitron text-xl text-green-400 mb-2">MISSION SUCCESS</h3>
|
| 1013 |
+
<p>${missionName} has successfully reached ${gameState.currentDestination.name}!</p>
|
| 1014 |
+
<p class="mt-2 text-sm">Payload delivered: ${gameState.currentPayload.type}</p>
|
| 1015 |
+
`;
|
| 1016 |
+
arrivalMessage.classList.add('active');
|
| 1017 |
|
| 1018 |
setTimeout(() => {
|
| 1019 |
+
updateConsole(`> Mission to ${gameState.currentDestination.name} successful!`);
|
| 1020 |
+
|
| 1021 |
+
// Show success marker
|
| 1022 |
+
successMarker.classList.add('success-animate');
|
| 1023 |
+
playSound('success');
|
| 1024 |
|
| 1025 |
+
// Calculate rewards
|
| 1026 |
+
const reputationGain = gameState.currentDestination.difficulty * 10;
|
| 1027 |
+
const financialReward = gameState.currentDestination.difficulty * 500000;
|
| 1028 |
|
| 1029 |
+
setTimeout(() => {
|
| 1030 |
+
updateConsole(`> Reputation increased by ${reputationGain}`);
|
| 1031 |
+
updateConsole(`> Financial reward: $${financialReward.toLocaleString()}`);
|
| 1032 |
+
updateConsole("> Ready for next mission");
|
| 1033 |
+
|
| 1034 |
+
// Update game state
|
| 1035 |
+
gameState.reputation += reputationGain;
|
| 1036 |
+
gameState.funds += financialReward - missionCost;
|
| 1037 |
+
|
| 1038 |
+
// Reset for next launch
|
| 1039 |
+
resetAfterLaunch();
|
| 1040 |
+
}, 2000);
|
| 1041 |
}, 2000);
|
| 1042 |
}, 2000);
|
| 1043 |
+
}, 1000);
|
| 1044 |
+
}, 3000);
|
| 1045 |
+
} else {
|
| 1046 |
+
// Failed mission
|
| 1047 |
+
const failureTime = 2000 + Math.random() * 3000;
|
| 1048 |
+
const failureReason = getRandomFailureReason();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1049 |
|
| 1050 |
setTimeout(() => {
|
| 1051 |
+
// Show explosion
|
| 1052 |
+
explosion.style.left = rocketInSpace.style.left;
|
| 1053 |
+
explosion.style.top = rocketInSpace.style.top;
|
| 1054 |
+
explosion.classList.add('explode');
|
| 1055 |
+
playSound('explosion');
|
| 1056 |
|
| 1057 |
+
// Hide rocket
|
| 1058 |
+
rocketInSpace.style.opacity = '0';
|
| 1059 |
+
|
| 1060 |
+
updateConsole(`> WARNING: ${failureReason}`);
|
| 1061 |
+
updateConsole("> Attempting to mitigate...");
|
| 1062 |
|
| 1063 |
setTimeout(() => {
|
| 1064 |
+
updateConsole("> Mission failure confirmed");
|
| 1065 |
+
updateConsole("> Investigating root cause");
|
|
|
|
| 1066 |
|
| 1067 |
+
// Calculate penalties
|
| 1068 |
+
const reputationLoss = gameState.currentDestination.difficulty * 5;
|
| 1069 |
+
const financialLoss = missionCost * 0.5;
|
| 1070 |
|
| 1071 |
+
setTimeout(() => {
|
| 1072 |
+
updateConsole(`> Reputation decreased by ${reputationLoss}`);
|
| 1073 |
+
updateConsole(`> Financial loss: $${financialLoss.toLocaleString()}`);
|
| 1074 |
+
updateConsole("> Preparing for next attempt");
|
| 1075 |
+
|
| 1076 |
+
// Update game state
|
| 1077 |
+
gameState.reputation = Math.max(0, gameState.reputation - reputationLoss);
|
| 1078 |
+
gameState.funds -= financialLoss;
|
| 1079 |
+
|
| 1080 |
+
// Reset for next launch
|
| 1081 |
+
resetAfterLaunch();
|
| 1082 |
+
}, 2000);
|
| 1083 |
}, 2000);
|
| 1084 |
+
}, failureTime);
|
| 1085 |
+
}
|
| 1086 |
+
}, 3000);
|
| 1087 |
}, 1000);
|
| 1088 |
}
|
| 1089 |
}
|
|
|
|
| 1166 |
// Reset after launch
|
| 1167 |
function resetAfterLaunch() {
|
| 1168 |
const rocketModel = document.getElementById('rocket-model');
|
| 1169 |
+
const spaceView = document.getElementById('space-view');
|
| 1170 |
+
const planetArrival = document.getElementById('planet-arrival');
|
| 1171 |
+
const rocketInSpace = document.getElementById('rocket-in-space');
|
| 1172 |
+
const arrivalMessage = document.getElementById('arrival-message');
|
| 1173 |
const launchButton = document.getElementById('launch-button');
|
| 1174 |
const explosion = document.getElementById('explosion');
|
| 1175 |
const successMarker = document.getElementById('success-marker');
|
|
|
|
| 1183 |
stageSeparation.classList.remove('separate');
|
| 1184 |
countdownElement.classList.remove('countdown-animate');
|
| 1185 |
|
| 1186 |
+
// Reset space view elements
|
| 1187 |
+
spaceView.classList.remove('active');
|
| 1188 |
+
planetArrival.classList.remove('active');
|
| 1189 |
+
rocketInSpace.classList.remove('active');
|
| 1190 |
+
arrivalMessage.classList.remove('active');
|
| 1191 |
+
|
| 1192 |
// Reset rocket position and visibility
|
| 1193 |
rocketModel.style.bottom = '0';
|
| 1194 |
rocketModel.style.transform = 'translateX(-50%)';
|