JustPaste
HomeCategoriesAboutDonateContactTerms of UsePrivacy Policy
JustPaste

Free online notepad — write and share instantly

Navigate

  • Home
  • Timeline
  • Categories

Info

  • About
  • Donate
  • Contact

Legal

  • Terms of Use
  • Privacy Policy

© 2026 JustPaste.app. All rights reserved.

Made with ♥ by JustPaste

64854 | JustPaste.app
11 days ago11 views
💻Technology

64854

<!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.

← Back to timeline