Spaces:
Running
Running
Add 1 files
Browse files- index.html +338 -67
index.html
CHANGED
@@ -53,11 +53,18 @@
|
|
53 |
|
54 |
.rocket-display {
|
55 |
perspective: 1000px;
|
|
|
|
|
|
|
56 |
}
|
57 |
|
58 |
.rocket-3d {
|
59 |
transform-style: preserve-3d;
|
60 |
transition: transform 0.5s ease;
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
.flame {
|
@@ -142,6 +149,142 @@
|
|
142 |
50% { opacity: 0.5; }
|
143 |
100% { opacity: 1; }
|
144 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
</style>
|
146 |
</head>
|
147 |
<body>
|
@@ -181,10 +324,17 @@
|
|
181 |
<!-- Rocket Display -->
|
182 |
<div class="bg-gray-900 rounded-xl p-6 shadow-xl border border-gray-800">
|
183 |
<h2 class="orbitron text-xl text-blue-400 mb-4">ROCKET DESIGN</h2>
|
184 |
-
<div class="rocket-display flex justify-center items-end
|
185 |
-
<div class="rocket-3d
|
186 |
<!-- Rocket parts will be added here by JavaScript -->
|
187 |
<div class="flame" id="rocket-flame"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
</div>
|
189 |
</div>
|
190 |
<div class="mt-6 grid grid-cols-3 gap-4">
|
@@ -206,7 +356,7 @@
|
|
206 |
<!-- Parts Selection -->
|
207 |
<div class="bg-gray-900 rounded-xl p-6 shadow-xl border border-gray-800">
|
208 |
<h2 class="orbitron text-xl text-blue-400 mb-4">ROCKET COMPONENTS</h2>
|
209 |
-
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
210 |
<!-- Parts will be added here by JavaScript -->
|
211 |
</div>
|
212 |
</div>
|
@@ -228,7 +378,7 @@
|
|
228 |
<div class="w-full bg-gray-800 rounded-full h-2.5 mb-4">
|
229 |
<div class="progress-bar rounded-full h-2.5" style="width: 100%"></div>
|
230 |
</div>
|
231 |
-
<div class="mission-control w-full bg-gray-800 rounded-lg p-4 h-48 overflow-y-auto">
|
232 |
<p class="console-text">> Welcome to SpaceX Simulator</p>
|
233 |
<p class="console-text">> Initializing systems...</p>
|
234 |
<p class="console-text">> Ready to build some rockets!</p>
|
@@ -397,7 +547,7 @@
|
|
397 |
|
398 |
// Render rocket parts selection
|
399 |
function renderParts() {
|
400 |
-
const partsContainer = document.
|
401 |
|
402 |
// First stages
|
403 |
rocketParts.firstStages.forEach(part => {
|
@@ -514,7 +664,7 @@
|
|
514 |
// Update rocket display
|
515 |
function updateRocketDisplay() {
|
516 |
const rocketModel = document.getElementById('rocket-model');
|
517 |
-
rocketModel.innerHTML = '<div class="flame" id="rocket-flame"></div>';
|
518 |
|
519 |
// Add parts to the rocket model
|
520 |
if (gameState.currentRocket.firstStage) {
|
@@ -603,17 +753,30 @@
|
|
603 |
if (!isReadyForLaunch()) return;
|
604 |
|
605 |
const rocketModel = document.getElementById('rocket-model');
|
606 |
-
const
|
607 |
-
const
|
|
|
|
|
|
|
608 |
const launchButton = document.getElementById('launch-button');
|
|
|
609 |
|
610 |
// Disable launch button during launch
|
611 |
launchButton.disabled = true;
|
612 |
launchButton.classList.remove('bg-green-600', 'hover:bg-green-700');
|
613 |
launchButton.classList.add('bg-gray-600', 'cursor-not-allowed');
|
614 |
|
615 |
-
//
|
616 |
-
rocketModel.classList.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
617 |
|
618 |
// Calculate mission success chance (simplified)
|
619 |
const rocketPower = (gameState.currentRocket.firstStage.thrust +
|
@@ -625,66 +788,158 @@
|
|
625 |
const missionCost = calculateMissionCost();
|
626 |
|
627 |
// Update mission control console
|
628 |
-
updateConsole(
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
// Random mission outcome
|
636 |
-
const isSuccess = Math.random() < successChance;
|
637 |
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
|
|
648 |
|
649 |
setTimeout(() => {
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
|
|
|
|
|
|
|
|
664 |
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
setTimeout(() => updateConsole("> Investigating root cause"), 7000);
|
669 |
|
670 |
-
//
|
671 |
-
const
|
672 |
-
const financialLoss = missionCost * 0.5;
|
673 |
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
682 |
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
688 |
}
|
689 |
|
690 |
// Calculate mission cost
|
@@ -720,8 +975,8 @@
|
|
720 |
|
721 |
// Update mission control console
|
722 |
function updateConsole(message) {
|
723 |
-
const consoleElement = document.
|
724 |
-
const blinkElement =
|
725 |
|
726 |
if (blinkElement) {
|
727 |
blinkElement.remove();
|
@@ -747,9 +1002,25 @@
|
|
747 |
function resetAfterLaunch() {
|
748 |
const rocketModel = document.getElementById('rocket-model');
|
749 |
const launchButton = document.getElementById('launch-button');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
750 |
|
751 |
-
//
|
752 |
-
|
753 |
|
754 |
// Re-enable launch button
|
755 |
launchButton.disabled = false;
|
|
|
53 |
|
54 |
.rocket-display {
|
55 |
perspective: 1000px;
|
56 |
+
position: relative;
|
57 |
+
height: 400px;
|
58 |
+
overflow: hidden;
|
59 |
}
|
60 |
|
61 |
.rocket-3d {
|
62 |
transform-style: preserve-3d;
|
63 |
transition: transform 0.5s ease;
|
64 |
+
position: absolute;
|
65 |
+
bottom: 0;
|
66 |
+
left: 50%;
|
67 |
+
transform: translateX(-50%);
|
68 |
}
|
69 |
|
70 |
.flame {
|
|
|
149 |
50% { opacity: 0.5; }
|
150 |
100% { opacity: 1; }
|
151 |
}
|
152 |
+
|
153 |
+
/* New launch effects */
|
154 |
+
.launch-smoke {
|
155 |
+
position: absolute;
|
156 |
+
bottom: 0;
|
157 |
+
left: 50%;
|
158 |
+
transform: translateX(-50%);
|
159 |
+
width: 200px;
|
160 |
+
height: 100px;
|
161 |
+
background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(200,200,200,0.5) 50%, rgba(100,100,100,0) 100%);
|
162 |
+
border-radius: 50%;
|
163 |
+
filter: blur(10px);
|
164 |
+
opacity: 0;
|
165 |
+
}
|
166 |
+
|
167 |
+
.launching .launch-smoke {
|
168 |
+
opacity: 1;
|
169 |
+
animation: smoke-expand 2s forwards;
|
170 |
+
}
|
171 |
+
|
172 |
+
@keyframes smoke-expand {
|
173 |
+
0% { transform: translateX(-50%) scale(0.5); opacity: 1; }
|
174 |
+
100% { transform: translateX(-50%) scale(3); opacity: 0; }
|
175 |
+
}
|
176 |
+
|
177 |
+
.launch-shake {
|
178 |
+
animation: shake 0.5s linear infinite;
|
179 |
+
}
|
180 |
+
|
181 |
+
@keyframes shake {
|
182 |
+
0% { transform: translateX(-50%) translateY(0); }
|
183 |
+
25% { transform: translateX(-50%) translateY(-2px) translateX(2px); }
|
184 |
+
50% { transform: translateX(-50%) translateY(0); }
|
185 |
+
75% { transform: translateX(-50%) translateY(2px) translateX(-2px); }
|
186 |
+
100% { transform: translateX(-50%) translateY(0); }
|
187 |
+
}
|
188 |
+
|
189 |
+
.rocket-ascent {
|
190 |
+
animation: rocket-fly 8s forwards;
|
191 |
+
}
|
192 |
+
|
193 |
+
@keyframes rocket-fly {
|
194 |
+
0% { bottom: 0; transform: translateX(-50%); }
|
195 |
+
20% { bottom: 20%; transform: translateX(-50%); }
|
196 |
+
40% { bottom: 40%; transform: translateX(-50%); }
|
197 |
+
60% { bottom: 60%; transform: translateX(-50%); }
|
198 |
+
80% { bottom: 80%; transform: translateX(-50%); }
|
199 |
+
100% { bottom: 120%; transform: translateX(-50%); }
|
200 |
+
}
|
201 |
+
|
202 |
+
.explosion {
|
203 |
+
position: absolute;
|
204 |
+
width: 300px;
|
205 |
+
height: 300px;
|
206 |
+
background: radial-gradient(circle, rgba(255,100,0,0.8) 0%, rgba(255,50,0,0) 70%);
|
207 |
+
border-radius: 50%;
|
208 |
+
filter: blur(20px);
|
209 |
+
opacity: 0;
|
210 |
+
transform: scale(0);
|
211 |
+
z-index: 10;
|
212 |
+
}
|
213 |
+
|
214 |
+
.explode {
|
215 |
+
animation: explosion 1s forwards;
|
216 |
+
}
|
217 |
+
|
218 |
+
@keyframes explosion {
|
219 |
+
0% { transform: scale(0); opacity: 1; }
|
220 |
+
100% { transform: scale(1); opacity: 0; }
|
221 |
+
}
|
222 |
+
|
223 |
+
.countdown {
|
224 |
+
position: absolute;
|
225 |
+
top: 50%;
|
226 |
+
left: 50%;
|
227 |
+
transform: translate(-50%, -50%);
|
228 |
+
font-size: 5rem;
|
229 |
+
color: white;
|
230 |
+
text-shadow: 0 0 10px red;
|
231 |
+
opacity: 0;
|
232 |
+
z-index: 20;
|
233 |
+
}
|
234 |
+
|
235 |
+
.countdown-animate {
|
236 |
+
animation: countdown 1s forwards;
|
237 |
+
}
|
238 |
+
|
239 |
+
@keyframes countdown {
|
240 |
+
0% { transform: translate(-50%, -50%) scale(0.5); opacity: 0; }
|
241 |
+
50% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
|
242 |
+
100% { transform: translate(-50%, -50%) scale(1); opacity: 0; }
|
243 |
+
}
|
244 |
+
|
245 |
+
.stage-separation {
|
246 |
+
position: absolute;
|
247 |
+
width: 100%;
|
248 |
+
height: 2px;
|
249 |
+
background: white;
|
250 |
+
opacity: 0.8;
|
251 |
+
z-index: 5;
|
252 |
+
transform: scaleX(0);
|
253 |
+
}
|
254 |
+
|
255 |
+
.separate {
|
256 |
+
animation: separate 0.5s forwards;
|
257 |
+
}
|
258 |
+
|
259 |
+
@keyframes separate {
|
260 |
+
0% { transform: scaleX(0); opacity: 0; }
|
261 |
+
100% { transform: scaleX(1); opacity: 0.8; }
|
262 |
+
}
|
263 |
+
|
264 |
+
.success-marker {
|
265 |
+
position: absolute;
|
266 |
+
top: 20px;
|
267 |
+
right: 20px;
|
268 |
+
width: 60px;
|
269 |
+
height: 60px;
|
270 |
+
background: rgba(0, 255, 0, 0.2);
|
271 |
+
border-radius: 50%;
|
272 |
+
display: flex;
|
273 |
+
align-items: center;
|
274 |
+
justify-content: center;
|
275 |
+
opacity: 0;
|
276 |
+
transform: scale(0);
|
277 |
+
}
|
278 |
+
|
279 |
+
.success-animate {
|
280 |
+
animation: success 1s forwards;
|
281 |
+
}
|
282 |
+
|
283 |
+
@keyframes success {
|
284 |
+
0% { transform: scale(0); opacity: 0; }
|
285 |
+
50% { transform: scale(1.2); opacity: 1; }
|
286 |
+
100% { transform: scale(1); opacity: 1; }
|
287 |
+
}
|
288 |
</style>
|
289 |
</head>
|
290 |
<body>
|
|
|
324 |
<!-- Rocket Display -->
|
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>
|
333 |
+
<div class="explosion" id="explosion"></div>
|
334 |
+
<div class="countdown" id="countdown"></div>
|
335 |
+
<div class="stage-separation" id="stage-separation"></div>
|
336 |
+
<div class="success-marker" id="success-marker">
|
337 |
+
<i class="fas fa-check-circle text-3xl text-green-500"></i>
|
338 |
</div>
|
339 |
</div>
|
340 |
<div class="mt-6 grid grid-cols-3 gap-4">
|
|
|
356 |
<!-- Parts Selection -->
|
357 |
<div class="bg-gray-900 rounded-xl p-6 shadow-xl border border-gray-800">
|
358 |
<h2 class="orbitron text-xl text-blue-400 mb-4">ROCKET COMPONENTS</h2>
|
359 |
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-4" id="parts-container">
|
360 |
<!-- Parts will be added here by JavaScript -->
|
361 |
</div>
|
362 |
</div>
|
|
|
378 |
<div class="w-full bg-gray-800 rounded-full h-2.5 mb-4">
|
379 |
<div class="progress-bar rounded-full h-2.5" style="width: 100%"></div>
|
380 |
</div>
|
381 |
+
<div class="mission-control w-full bg-gray-800 rounded-lg p-4 h-48 overflow-y-auto" id="mission-console">
|
382 |
<p class="console-text">> Welcome to SpaceX Simulator</p>
|
383 |
<p class="console-text">> Initializing systems...</p>
|
384 |
<p class="console-text">> Ready to build some rockets!</p>
|
|
|
547 |
|
548 |
// Render rocket parts selection
|
549 |
function renderParts() {
|
550 |
+
const partsContainer = document.getElementById('parts-container');
|
551 |
|
552 |
// First stages
|
553 |
rocketParts.firstStages.forEach(part => {
|
|
|
664 |
// Update rocket display
|
665 |
function updateRocketDisplay() {
|
666 |
const rocketModel = document.getElementById('rocket-model');
|
667 |
+
rocketModel.innerHTML = '<div class="flame" id="rocket-flame"></div><div class="launch-smoke"></div>';
|
668 |
|
669 |
// Add parts to the rocket model
|
670 |
if (gameState.currentRocket.firstStage) {
|
|
|
753 |
if (!isReadyForLaunch()) return;
|
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');
|
760 |
+
const explosion = document.getElementById('explosion');
|
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');
|
767 |
launchButton.classList.add('bg-gray-600', 'cursor-not-allowed');
|
768 |
|
769 |
+
// Clear previous animations
|
770 |
+
rocketModel.classList.remove('launching', 'launch-shake', 'rocket-ascent');
|
771 |
+
explosion.classList.remove('explode');
|
772 |
+
successMarker.classList.remove('success-animate');
|
773 |
+
|
774 |
+
// Reset rocket position
|
775 |
+
rocketModel.style.bottom = '0';
|
776 |
+
rocketModel.style.transform = 'translateX(-50%)';
|
777 |
+
|
778 |
+
// Play launch sound
|
779 |
+
playSound('launch');
|
780 |
|
781 |
// Calculate mission success chance (simplified)
|
782 |
const rocketPower = (gameState.currentRocket.firstStage.thrust +
|
|
|
788 |
const missionCost = calculateMissionCost();
|
789 |
|
790 |
// Update mission control console
|
791 |
+
updateConsole(`> Starting ${missionName} launch sequence...`);
|
792 |
+
|
793 |
+
// Countdown sequence
|
794 |
+
let count = 5;
|
795 |
+
const countdownInterval = setInterval(() => {
|
796 |
+
countdownElement.textContent = count;
|
797 |
+
countdownElement.classList.add('countdown-animate');
|
|
|
|
|
798 |
|
799 |
+
// Play countdown sound
|
800 |
+
playSound('countdown');
|
801 |
+
|
802 |
+
setTimeout(() => {
|
803 |
+
countdownElement.classList.remove('countdown-animate');
|
804 |
+
}, 900);
|
805 |
+
|
806 |
+
if (count === 0) {
|
807 |
+
clearInterval(countdownInterval);
|
808 |
+
countdownElement.textContent = 'LIFTOFF!';
|
809 |
+
countdownElement.classList.add('countdown-animate');
|
810 |
|
811 |
setTimeout(() => {
|
812 |
+
countdownElement.classList.remove('countdown-animate');
|
813 |
+
startLaunchSequence();
|
814 |
+
}, 1000);
|
815 |
+
}
|
816 |
+
|
817 |
+
count--;
|
818 |
+
}, 1000);
|
819 |
+
|
820 |
+
function startLaunchSequence() {
|
821 |
+
// Add launching effects
|
822 |
+
rocketModel.classList.add('launching', 'launch-shake');
|
823 |
+
|
824 |
+
// Update console
|
825 |
+
updateConsole("> Engine ignition...");
|
826 |
+
updateConsole("> All systems nominal");
|
827 |
+
|
828 |
+
setTimeout(() => {
|
829 |
+
updateConsole("> Liftoff! We have liftoff!");
|
830 |
|
831 |
+
// Start ascent animation
|
832 |
+
rocketModel.classList.add('rocket-ascent');
|
833 |
+
rocketModel.classList.remove('launch-shake');
|
|
|
834 |
|
835 |
+
// Random mission outcome
|
836 |
+
const isSuccess = Math.random() < successChance;
|
|
|
837 |
|
838 |
+
if (isSuccess) {
|
839 |
+
// Successful mission
|
840 |
+
setTimeout(() => {
|
841 |
+
updateConsole("> First stage separation successful");
|
842 |
+
|
843 |
+
// Show stage separation effect
|
844 |
+
stageSeparation.classList.add('separate');
|
845 |
+
playSound('separation');
|
846 |
+
|
847 |
+
setTimeout(() => {
|
848 |
+
stageSeparation.classList.remove('separate');
|
849 |
+
updateConsole("> Second stage ignition");
|
850 |
+
|
851 |
+
setTimeout(() => {
|
852 |
+
updateConsole("> Payload deployment confirmed");
|
853 |
+
|
854 |
+
setTimeout(() => {
|
855 |
+
updateConsole(`> Mission to ${gameState.currentDestination.name} successful!`);
|
856 |
+
|
857 |
+
// Show success marker
|
858 |
+
successMarker.classList.add('success-animate');
|
859 |
+
playSound('success');
|
860 |
+
|
861 |
+
// Calculate rewards
|
862 |
+
const reputationGain = gameState.currentDestination.difficulty * 10;
|
863 |
+
const financialReward = gameState.currentDestination.difficulty * 500000;
|
864 |
+
|
865 |
+
setTimeout(() => {
|
866 |
+
updateConsole(`> Reputation increased by ${reputationGain}`);
|
867 |
+
updateConsole(`> Financial reward: $${financialReward.toLocaleString()}`);
|
868 |
+
updateConsole("> Ready for next mission");
|
869 |
+
|
870 |
+
// Update game state
|
871 |
+
gameState.reputation += reputationGain;
|
872 |
+
gameState.funds += financialReward - missionCost;
|
873 |
+
|
874 |
+
// Reset for next launch
|
875 |
+
resetAfterLaunch();
|
876 |
+
}, 2000);
|
877 |
+
}, 2000);
|
878 |
+
}, 2000);
|
879 |
+
}, 1000);
|
880 |
+
}, 3000);
|
881 |
+
} else {
|
882 |
+
// Failed mission
|
883 |
+
const failureTime = 2000 + Math.random() * 3000;
|
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 |
+
updateConsole("> Mission failure confirmed");
|
901 |
+
updateConsole("> Investigating root cause");
|
902 |
+
|
903 |
+
// Calculate penalties
|
904 |
+
const reputationLoss = gameState.currentDestination.difficulty * 5;
|
905 |
+
const financialLoss = missionCost * 0.5;
|
906 |
+
|
907 |
+
setTimeout(() => {
|
908 |
+
updateConsole(`> Reputation decreased by ${reputationLoss}`);
|
909 |
+
updateConsole(`> Financial loss: $${financialLoss.toLocaleString()}`);
|
910 |
+
updateConsole("> Preparing for next attempt");
|
911 |
+
|
912 |
+
// Update game state
|
913 |
+
gameState.reputation = Math.max(0, gameState.reputation - reputationLoss);
|
914 |
+
gameState.funds -= financialLoss;
|
915 |
+
|
916 |
+
// Reset for next launch
|
917 |
+
resetAfterLaunch();
|
918 |
+
}, 2000);
|
919 |
+
}, 2000);
|
920 |
+
}, failureTime);
|
921 |
+
}
|
922 |
+
}, 1000);
|
923 |
+
}
|
924 |
+
}
|
925 |
+
|
926 |
+
// Play sound effects
|
927 |
+
function playSound(type) {
|
928 |
+
// In a real implementation, you would use the Web Audio API or preloaded audio elements
|
929 |
+
// This is a placeholder that would be replaced with actual sound effects
|
930 |
+
console.log(`Playing sound: ${type}`);
|
931 |
+
|
932 |
+
// For demonstration purposes, we'll just log the sound that would play
|
933 |
+
const sounds = {
|
934 |
+
'countdown': 'beep.mp3',
|
935 |
+
'launch': 'rocket_launch.mp3',
|
936 |
+
'separation': 'stage_separation.mp3',
|
937 |
+
'success': 'mission_success.mp3',
|
938 |
+
'explosion': 'explosion.mp3'
|
939 |
+
};
|
940 |
+
|
941 |
+
// In a real app, you would play the corresponding sound file
|
942 |
+
// new Audio(sounds[type]).play();
|
943 |
}
|
944 |
|
945 |
// Calculate mission cost
|
|
|
975 |
|
976 |
// Update mission control console
|
977 |
function updateConsole(message) {
|
978 |
+
const consoleElement = document.getElementById('mission-console');
|
979 |
+
const blinkElement = consoleElement.querySelector('.blink');
|
980 |
|
981 |
if (blinkElement) {
|
982 |
blinkElement.remove();
|
|
|
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');
|
1007 |
+
const stageSeparation = document.getElementById('stage-separation');
|
1008 |
+
const countdownElement = document.getElementById('countdown');
|
1009 |
+
|
1010 |
+
// Remove all animation classes
|
1011 |
+
rocketModel.classList.remove('launching', 'launch-shake', 'rocket-ascent');
|
1012 |
+
explosion.classList.remove('explode');
|
1013 |
+
successMarker.classList.remove('success-animate');
|
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%)';
|
1020 |
+
rocketModel.style.opacity = '1';
|
1021 |
|
1022 |
+
// Clear countdown text
|
1023 |
+
countdownElement.textContent = '';
|
1024 |
|
1025 |
// Re-enable launch button
|
1026 |
launchButton.disabled = false;
|