<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Rocket Empire 3D</title>
<style>
*{box-sizing:border-box}
html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#08101d;color:#fff;font-family:Tahoma,Arial,sans-serif}
body{user-select:none}
#game{position:fixed;inset:0}
canvas{display:block;width:100%;height:100%}
#ui{
position:fixed;inset:0;pointer-events:none;
}
.top{
position:absolute;top:14px;left:14px;right:14px;
display:flex;justify-content:space-between;align-items:flex-start;
gap:12px
}
.card{
background:rgba(8,15,30,.82);
border:1px solid rgba(120,180,255,.25);
box-shadow:0 12px 35px rgba(0,0,0,.35);
backdrop-filter:blur(12px);
border-radius:18px;
padding:12px 16px;
}
.stats{display:flex;gap:18px;flex-wrap:wrap}
.stat b{display:block;font-size:17px}
.stat span{font-size:11px;color:#91a6c5}
.money{color:#ffd34d}
#altitude{
position:absolute;
top:105px;
left:50%;
transform:translateX(-50%);
text-align:center;
display:none;
}
#altitude .num{font-size:38px;font-weight:900;text-shadow:0 3px 15px #000}
#altitude small{color:#a9c7ef}
#menu{
position:absolute;
right:18px;
bottom:18px;
width:330px;
pointer-events:auto;
}
.tabs{display:flex;gap:7px;margin-bottom:8px}
.tab{
flex:1;border:0;border-radius:12px;padding:11px 5px;
background:#14243c;color:#9eb4d2;cursor:pointer;font-weight:bold
}
.tab.active{background:#2577ff;color:white}
.panel{
display:none;
background:rgba(8,15,30,.91);
border:1px solid rgba(120,180,255,.24);
border-radius:18px;
padding:14px;
box-shadow:0 15px 45px rgba(0,0,0,.5);
}
.panel.active{display:block}
.panel h2{margin:0 0 10px;font-size:18px}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.item{
background:#101d31;border:1px solid #213754;border-radius:13px;
padding:10px
}
.item strong{display:block;font-size:13px}
.item small{display:block;color:#8096b7;margin:4px 0 8px}
.buy{
width:100%;border:0;border-radius:9px;padding:8px;
background:#1e63d6;color:#fff;font-weight:bold;cursor:pointer
}
.buy:disabled{background:#263449;color:#65758d}
.level{
color:#5db0ff;font-size:11px
}
#rocketInfo{
position:absolute;
left:18px;
bottom:18px;
width:270px;
pointer-events:auto
}
.bar{
height:8px;background:#17263c;border-radius:99px;overflow:hidden;margin-top:5px
}
.bar i{display:block;height:100%;width:100%;background:#39d98a}
.row{
display:flex;justify-content:space-between;font-size:12px;
margin:5px 0;color:#9db1cc
}
#launchHelp{
position:absolute;
left:50%;
bottom:24px;
transform:translateX(-50%);
background:rgba(5,12,24,.78);
padding:10px 17px;border-radius:14px;
font-size:12px;color:#bcd0ed;
display:block
}
.key{
display:inline-block;background:#253750;color:#fff;
border-radius:6px;padding:3px 7px;margin:0 2px;font-weight:bold
}
#flightEnd{
position:absolute;inset:0;
background:rgba(3,8,18,.68);
display:none;
align-items:center;justify-content:center;
pointer-events:auto
}
.result{
width:min(430px,90vw);
background:rgba(10,19,35,.96);
border:1px solid #31537d;
border-radius:24px;
padding:25px;text-align:center;
box-shadow:0 20px 80px #000
}
.result h1{margin:0 0 15px}
.big{font-size:42px;font-weight:900;color:#61b5ff}
.result button{
border:0;background:#2478ff;color:white;
border-radius:12px;padding:12px 30px;font-weight:bold;
font-size:15px;cursor:pointer;margin-top:15px
}
#toast{
position:absolute;top:80px;right:50%;
transform:translateX(50%) translateY(-20px);
opacity:0;transition:.25s;
background:#13233a;border:1px solid #31547c;
padding:10px 18px;border-radius:12px;
font-size:13px
}
#toast.show{opacity:1;transform:translateX(50%) translateY(0)}
@media(max-width:800px){
#menu{width:285px}
#rocketInfo{width:220px}
.stats{gap:9px}
.stat b{font-size:14px}
}
</style>
</head>
<body>
<div id="game"></div>
<div id="ui">
<div class="top">
<div class="card stats">
<div class="stat"><span>سرمایه</span><b class="money" id="money">25,000</b></div>
<div class="stat"><span>سوخت</span><b id="fuel">0</b></div>
<div class="stat"><span>رکورد</span><b id="record">0 m</b></div>
<div class="stat"><span>پروازها</span><b id="flights">0</b></div>
</div>
<div class="card">
<b>🚀 ROCKET EMPIRE</b><br>
<span style="font-size:11px;color:#8fa8ca">مرکز فرماندهی موشک</span>
</div>
</div>
<div id="altitude">
<div class="num"><span id="alt">0</span> متر</div>
<small>ارتفاع فعلی</small>
</div>
<div id="rocketInfo" class="card">
<b>وضعیت موشک</b>
<div class="row"><span>بدنه</span><span id="bodyLv">سطح 1</span></div>
<div class="row"><span>موتور</span><span id="engineLv">سطح 1</span></div>
<div class="row"><span>مخزن</span><span id="tankLv">سطح 1</span></div>
<div class="row"><span>باله</span><span id="finLv">سطح 1</span></div>
<div class="row"><span>سوخت</span><span id="fuelText">0 / 100</span></div>
<div class="bar"><i id="fuelBar"></i></div>
</div>
<div id="menu">
<div class="tabs">
<button class="tab active" data-tab="hangar">آشیانه</button>
<button class="tab" data-tab="shop">مغازه</button>
<button class="tab" data-tab="factory">کارخانه</button>
<button class="tab" data-tab="records">رکوردها</button>
</div>
<div class="panel active" id="hangar">
<h2>🛠️ آشیانه موشک</h2>
<div class="grid">
<div class="item">
<strong>بدنه</strong>
<small>ظرفیت و استحکام بیشتر</small>
<button class="buy" onclick="upgrade('body')">ارتقا <span id="bodyCost">2500</span> 💰</button>
</div>
<div class="item">
<strong>موتور</strong>
<small>قدرت پرتاب بیشتر</small>
<button class="buy" onclick="upgrade('engine')">ارتقا <span id="engineCost">3500</span> 💰</button>
</div>
<div class="item">
<strong>مخزن</strong>
<small>سوخت بیشتر</small>
<button class="buy" onclick="upgrade('tank')">ارتقا <span id="tankCost">2800</span> 💰</button>
</div>
<div class="item">
<strong>بالهها</strong>
<small>کنترل بهتر در پرواز</small>
<button class="buy" onclick="upgrade('fins')">ارتقا <span id="finCost">1800</span> 💰</button>
</div>
</div>
</div>
<div class="panel" id="shop">
<h2>🏪 مغازه مواد اولیه</h2>
<div class="grid">
<div class="item"><strong>آهن</strong><small id="iron">25 واحد</small><button class="buy" onclick="buyMat('iron',10,300)">+10 | 300 💰</button></div>
<div class="item"><strong>فولاد</strong><small id="steel">8 واحد</small><button class="buy" onclick="buyMat('steel',5,500)">+5 | 500 💰</button></div>
<div class="item"><strong>آلومینیوم</strong><small id="aluminum">15 واحد</small><button class="buy" onclick="buyMat('aluminum',10,450)">+10 | 450 💰</button></div>
<div class="item"><strong>تیتانیوم</strong><small id="titanium">2 واحد</small><button class="buy" onclick="buyMat('titanium',2,900)">+2 | 900 💰</button></div>
<div class="item"><strong>مایع پایه</strong><small id="liquid">50 لیتر</small><button class="buy" onclick="buyMat('liquid',25,250)">+25 | 250 💰</button></div>
<div class="item"><strong>آلیاژ ویژه</strong><small>برای ارتقاهای آینده</small><button class="buy" onclick="buyMat('steel',10,900)">+10 | 900 💰</button></div>
</div>
</div>
<div class="panel" id="factory">
<h2>🏭 کارخانه سوخت</h2>
<div class="item">
<strong>سوخت استاندارد</strong>
<small>10 مایع پایه → 18 واحد سوخت بازی</small>
<button class="buy" onclick="makeFuel()">تولید سوخت</button>
</div>
<div style="height:8px"></div>
<div class="item">
<strong>سوخت تقویتشده</strong>
<small>20 مایع + 2 فولاد → 45 واحد سوخت</small>
<button class="buy" onclick="makeBoostFuel()">تولید تقویتشده</button>
</div>
</div>
<div class="panel" id="records">
<h2>🏆 رکوردها</h2>
<div class="item">
<strong>بیشترین ارتفاع</strong>
<div style="font-size:30px;margin-top:8px;color:#61b5ff" id="recordBig">0 متر</div>
</div>
<div style="height:8px"></div>
<div class="item">
<strong>درآمد کل پروازها</strong>
<div style="font-size:20px;margin-top:7px;color:#ffd34d" id="earned">0 💰</div>
</div>
</div>
</div>
<div id="launchHelp">
<span class="key">SPACE</span> پرتاب
<span class="key">A</span><span class="key">D</span> کنترل
<span class="key">ESC</span> پایان پرواز
</div>
<div id="flightEnd">
<div class="result">
<h1>🚀 پرواز به پایان رسید</h1>
<div class="big" id="resultHeight">0 m</div>
<div style="color:#9eb3d1;margin-top:4px">ارتفاع نهایی</div>
<div style="margin-top:15px">درآمد این پرواز</div>
<div style="font-size:25px;color:#ffd34d;font-weight:bold" id="resultMoney">+0 💰</div>
<button onclick="closeResult()">ادامه</button>
</div>
</div>
<div id="toast"></div>
</div>
<script>
/* =========================================================
موتور سهبعدی سبک داخلی
بدون فایل خارجی، بدون لودینگ و بدون کتابخانه خارجی
========================================================= */
const canvas=document.createElement("canvas");
canvas.style.position="absolute";
canvas.style.inset="0";
document.getElementById("game").appendChild(canvas);
const gl=canvas.getContext("webgl",{antialias:true});
if(!gl){
document.body.innerHTML="<div style='padding:30px;color:white'>مرورگر شما WebGL را پشتیبانی نمیکند.</div>";
throw new Error("WebGL unavailable");
}
const vs=`
attribute vec3 a;
uniform mat4 mvp;
varying float z;
void main(){
vec4 p=mvp*vec4(a,1.0);
gl_Position=p;
z=p.z;
}`;
const fs=`
precision mediump float;
uniform vec4 color;
varying float z;
void main(){
float fog=clamp((z+25.0)/45.0,0.0,0.75);
vec3 sky=vec3(0.025,0.07,0.14);
vec3 c=mix(color.rgb,sky,fog);
gl_FragColor=vec4(c,color.a);
}`;
function shader(type,src){
const s=gl.createShader(type);
gl.shaderSource(s,src);
gl.compileShader(s);
return s;
}
const program=gl.createProgram();
gl.attachShader(program,shader(gl.VERTEX_SHADER,vs));
gl.attachShader(program,shader(gl.FRAGMENT_SHADER,fs));
gl.linkProgram(program);
gl.useProgram(program);
const apos=gl.getAttribLocation(program,"a");
const umvp=gl.getUniformLocation(program,"mvp");
const ucolor=gl.getUniformLocation(program,"color");
function matIdentity(){
return [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];
}
function mul(a,b){
let o=new Array(16);
for(let c=0;c<4;c++)for(let r=0;r<4;r++)
o[c*4+r]=a[r]*b[c*4]+a[4+r]*b[c*4+1]+a[8+r]*b[c*4+2]+a[12+r]*b[c*4+3];
return o;
}
function perspective(fov,aspect,n,f){
const t=1/Math.tan(fov/2);
return [t/aspect,0,0,0,0,t,0,0,0,0,(f+n)/(n-f),-1,0,0,(2*f*n)/(n-f),0];
}
function translate(x,y,z){
let m=matIdentity();m[12]=x;m[13]=y;m[14]=z;return m;
}
function scale(x,y,z){
let m=matIdentity();m[0]=x;m[5]=y;m[10]=z;return m;
}
function rotateY(a){
let c=Math.cos(a),s=Math.sin(a);
return [c,0,-s,0,0,1,0,0,s,0,c,0,0,0,0,1];
}
function rotateX(a){
let c=Math.cos(a),s=Math.sin(a);
return [1,0,0,0,0,c,s,0,0,-s,c,0,0,0,0,1];
}
function cameraMatrix(pos,look){
let dx=look[0]-pos[0],dy=look[1]-pos[1],dz=look[2]-pos[2];
let len=Math.hypot(dx,dy,dz);dx/=len;dy/=len;dz/=len;
let up=[0,1,0];
let rx=up[1]*dz-up[2]*dy;
let ry=up[2]*dx-up[0]*dz;
let rz=up[0]*dy-up[1]*dx;
let rl=Math.hypot(rx,ry,rz);rx/=rl;ry/=rl;rz/=rl;
let ux=dy*rz-dz*ry,uy=dz*rx-dx*rz,uz=dx*ry-dy*rx;
return [
rx,ux,-dx,0,
ry,uy,-dy,0,
rz,uz,-dz,0,
-(rx*pos[0]+ry*pos[1]+rz*pos[2]),
-(ux*pos[0]+uy*pos[1]+uz*pos[2]),
dx*pos[0]+dy*pos[1]+dz*pos[2],1
];
}
const cube=[
-1,-1,-1, 1,-1,-1, 1,1,-1,-1,1,-1,
-1,-1,1, 1,-1,1, 1,1,1,-1,1,1
];
const indices=[
0,1,2,0,2,3,4,6,5,4,7,6,
0,4,5,0,5,1,2,6,7,2,7,3,
0,3,7,0,7,4,1,5,6,1,6,2
];
const vb=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vb);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(cube),gl.STATIC_DRAW);
const ib=gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,ib);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(indices),gl.STATIC_DRAW);
function drawCube(x,y,z,sx,sy,sz,color,rot=0){
let model=mul(translate(x,y,z),mul(rotateY(rot),scale(sx,sy,sz)));
let mvp=mul(proj,mul(view,model));
gl.uniformMatrix4fv(umvp,false,new Float32Array(mvp));
gl.uniform4fv(ucolor,new Float32Array(color));
gl.bindBuffer(gl.ARRAY_BUFFER,vb);
gl.enableVertexAttribArray(apos);
gl.vertexAttribPointer(apos,3,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,ib);
gl.drawElements(gl.TRIANGLES,36,gl.UNSIGNED_SHORT,0);
}
function drawPyramid(x,y,z,r,h,color){
let verts=[
0,h/2,0,-r,-h/2,-r,r,-h/2,-r,r,-h/2,r,-r,-h/2,r
];
let ids=[0,1,2,0,2,3,0,3,4,0,4,1,1,4,3,1,3,2];
let b=gl.createBuffer(),e=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,b);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(verts),gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,e);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(ids),gl.STATIC_DRAW);
let model=translate(x,y,z);
gl.uniformMatrix4fv(umvp,false,new Float32Array(mul(proj,mul(view,model))));
gl.uniform4fv(ucolor,new Float32Array(color));
gl.enableVertexAttribArray(apos);
gl.vertexAttribPointer(apos,3,gl.FLOAT,false,0,0);
gl.drawElements(gl.TRIANGLES,18,gl.UNSIGNED_SHORT,0);
}
let proj,view;
const state={
money:25000,
fuel:0,
record:0,
flights:0,
earned:0,
iron:25,
steel:8,
aluminum:15,
titanium:2,
liquid:50,
body:1,
engine:1,
tank:1,
fins:1
};
try{
const old=JSON.parse(localStorage.getItem("rocketEmpire3D"));
if(old)Object.assign(state,old);
}catch(e){}
function save(){
localStorage.setItem("rocketEmpire3D",JSON.stringify(state));
}
function fmt(n){return Math.floor(n).toLocaleString("en-US")}
function updateUI(){
money.textContent=fmt(state.money);
fuel.textContent=fmt(state.fuel);
record.textContent=fmt(state.record)+" m";
flights.textContent=state.flights;
iron.textContent=state.iron+" واحد";
steel.textContent=state.steel+" واحد";
aluminum.textContent=state.aluminum+" واحد";
titanium.textContent=state.titanium+" واحد";
liquid.textContent=state.liquid+" لیتر";
bodyLv.textContent="سطح "+state.body;
engineLv.textContent="سطح "+state.engine;
tankLv.textContent="سطح "+state.tank;
finLv.textContent="سطح "+state.fins;
recordBig.textContent=fmt(state.record)+" متر";
earned.textContent=fmt(state.earned)+" 💰";
fuelText.textContent=fmt(state.fuel)+" / "+fuelCapacity();
fuelBar.style.width=Math.min(100,state.fuel/fuelCapacity()*100)+"%";
bodyCost.textContent=fmt(2500*state.body);
engineCost.textContent=fmt(3500*state.engine);
tankCost.textContent=fmt(2800*state.tank);
finCost.textContent=fmt(1800*state.fins);
}
function fuelCapacity(){return 100+(state.tank-1)*45}
function toast(t){
toastEl.textContent=t;
toastEl.classList.add("show");
clearTimeout(toast.timer);
toast.timer=setTimeout(()=>toastEl.classList.remove("show"),1800);
}
const toastEl=document.getElementById("toast");
function buyMat(type,amount,cost){
if(state.money<cost)return toast("پول کافی نیست 💰");
state.money-=cost;
state[type]+=amount;
save();updateUI();
toast("خرید انجام شد ✓");
}
function makeFuel(){
if(state.liquid<10)return toast("مایع پایه کافی نیست");
state.liquid-=10;
state.fuel=Math.min(fuelCapacity(),state.fuel+18);
save();updateUI();
toast("۱۸ واحد سوخت تولید شد ⛽");
}
function makeBoostFuel(){
if(state.liquid<20||state.steel<2)return toast("مواد کافی نیست");
state.liquid-=20;
state.steel-=2;
state.fuel=Math.min(fuelCapacity(),state.fuel+45);
save();updateUI();
toast("۴۵ واحد سوخت تقویتشده تولید شد 🔥");
}
function upgrade(type){
let cost={body:2500*state.body,engine:3500*state.engine,tank:2800*state.tank,fins:1800*state.fins}[type];
if(state.money<cost)return toast("پول کافی نیست");
state.money-=cost;
state[type]++;
save();updateUI();
toast("موشک ارتقا پیدا کرد 🚀");
}
document.querySelectorAll(".tab").forEach(b=>{
b.onclick=()=>{
document.querySelectorAll(".tab").forEach(x=>x.classList.remove("active"));
document.querySelectorAll(".panel").forEach(x=>x.classList.remove("active"));
b.classList.add("active");
document.getElementById(b.dataset.tab).classList.add("active");
};
});
/* ==============================
محیط سهبعدی
================================ */
let rocket={
x:0,y:2,z:0,
vx:0,vy:0,vz:0,
angle:0,
active:false,
height:0,
fuel:0,
smoke:[],
trail:[],
launchTime:0
};
function buildWorld(){
// زمین
drawCube(0,-1.8,0,22,1.5,22,[0.08,.14,.19,1]);
// سکوی پرتاب
drawCube(0,-.15,0,3,.15,3,[.25,.29,.34,1]);
drawCube(0,.05,0,2.3,.08,2.3,[.1,.38,.65,1]);
// برج
drawCube(-4,4,0,.25,4,.25,[.24,.29,.34,1]);
drawCube(4,4,0,.25,4,.25,[.24,.29,.34,1]);
drawCube(0,7,0,4,.15,.15,[.35,.4,.46,1]);
for(let y=1;y<7;y+=1.2)
drawCube(0,y,0,4,.07,.07,[.22,.27,.33,1]);
// ساختمانها
for(let i=0;i<8;i++){
let x=-15+(i%4)*10;
let z=8+Math.floor(i/4)*8;
let h=2+(i%3);
drawCube(x,h/2,z,2,h,2,[.10,.17,.25,1]);
drawCube(x,h+.25,z,2.1,.12,2.1,[.18,.25,.34,1]);
}
// جاده
drawCube(0,-.05,8,2,.03,14,[.035,.045,.06,1]);
for(let z=-4;z<20;z+=3)
drawCube(0,.01,z,.12,.02,1,[.8,.7,.25,1]);
}
function drawRocket(){
let x=rocket.x,y=rocket.y,z=rocket.z;
drawCube(x,y,z,0.75,2.0,0.75,[.72,.76,.82,1],rocket.angle);
// نوارهای بدنه
drawCube(x,y+.65,z,.79,.09,.79,[.18,.55,.95,1],rocket.angle);
drawCube(x,y-.55,z,.8,.09,.8,[.18,.55,.95,1],rocket.angle);
// پنجره
drawCube(
x+Math.sin(rocket.angle)*.77,
y+.55,
z+Math.cos(rocket.angle)*.77,
.18,.28,.04,
[.04,.2,.35,1],
rocket.angle
);
// دماغه
drawPyramid(x,y+2.55,z,.8,1.1,[.8,.83,.88,1]);
// بالهها
drawCube(x-1.0,y-.9,z,.38,.7,.12,[.9,.2,.18,1],rocket.angle);
drawCube(x+1.0,y-.9,z,.38,.7,.12,[.9,.2,.18,1],rocket.angle);
// موتور
drawCube(x,y-2.25,z,.58,.45,.58,[.18,.2,.23,1],rocket.angle);
if(rocket.active){
let power=.7+Math.random()*.35;
drawPyramid(x,y-3.05,z,.55,1.9*power,[1,.32,.03,1]);
drawPyramid(x,y-3.35,z,.28,1.6*power,[1,.8,.12,1]);
}
}
/* ذرات دود */
function drawSmoke(){
for(let i=0;i<rocket.smoke.length;i++){
let p=rocket.smoke[i];
p.y-=.012;
p.x+=(Math.random()-.5)*.008;
p.z+=(Math.random()-.5)*.008;
p.s*=1.002;
drawCube(p.x,p.y,p.z,p.s,p.s,p.s,[.48,.5,.52,.5]);
}
rocket.smoke=rocket.smoke.filter(p=>p.y>rocket.y-18);
}
let keys={};
addEventListener("keydown",e=>{
keys[e.code]=true;
if(e.code==="Space"){
e.preventDefault();
if(!rocket.active)launch();
}
if(e.code==="Escape"&&rocket.active)endFlight();
});
addEventListener("keyup",e=>keys[e.code]=false);
function launch(){
if(state.fuel<12){
toast("حداقل ۱۲ واحد سوخت لازم است ⛽");
return;
}
rocket.active=true;
rocket.x=0;
rocket.y=2;
rocket.z=0;
rocket.vx=0;
rocket.vy=0;
rocket.vz=0;
rocket.angle=0;
rocket.height=0;
rocket.fuel=state.fuel;
rocket.smoke=[];
rocket.launchTime=performance.now();
state.fuel-=12;
document.getElementById("altitude").style.display="block";
document.getElementById("menu").style.display="none";
document.getElementById("rocketInfo").style.display="none";
document.getElementById("launchHelp").innerHTML=
'<span class="key">A</span><span class="key">D</span> هدایت | <span class="key">ESC</span> فرود اضطراری';
updateUI();
toast("پرتاب! 🚀");
}
function endFlight(){
if(!rocket.active)return;
rocket.active=false;
let h=Math.max(0,Math.floor(rocket.height));
let income=Math.floor(h*0.8)+500;
if(h>state.record)state.record=h;
state.money+=income;
state.earned+=income;
state.flights++;
resultHeight.textContent=fmt(h)+" m";
resultMoney.textContent="+"+fmt(income)+" 💰";
flightEnd.style.display="flex";
save();updateUI();
}
function closeResult(){
flightEnd.style.display="none";
altitude.style.display="none";
menu.style.display="block";
rocketInfo.style.display="block";
launchHelp.innerHTML='<span class="key">SPACE</sp⚠️Content was pasted as plain text and auto-formatted as a code block. Use the Code Block button in the editor for proper formatting.