SC CODE: // Copyright 2024. Civilware. All rights reserved.
// TELA Decentralized Web Document (TELA-DOC-1)
Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "data4.js")
31 STORE("descrHdr", "Data file 4")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "data4.js")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "bdadf7c15644a8bb3be725e32235bbf4fe578f5a3c11bb29bd4438f9d52e6d6")
37 STORE("fileCheckS", "15bc571ec1b3ee63b94d4bffef978f8ad13439fa87131108957b75d7f7f0cd15")
100 RETURN 0
End Function
Function init() Uint64
10 IF EXISTS("owner") == 0 THEN GOTO 30
20 RETURN 1
30 STORE("owner", address())
50 STORE("docVersion", "1.0.0")
60 STORE("hash", HEX(TXID()))
70 STORE("likes", 0)
80 STORE("dislikes", 0)
100 RETURN 0
End Function
Function address() String
10 DIM s as String
20 LET s = SIGNER()
30 IF IS_ADDRESS_VALID(s) THEN GOTO 50
40 RETURN "anon"
50 RETURN ADDRESS_STRING(s)
End Function
Function Rate(r Uint64) Uint64
10 DIM addr as String
15 LET addr = address()
16 IF r < 100 && EXISTS(addr) == 0 && addr != "anon" THEN GOTO 30
20 RETURN 1
30 STORE(addr, ""+r+"_"+BLOCK_HEIGHT())
40 IF r < 50 THEN GOTO 70
50 STORE("likes", LOAD("likes")+1)
60 RETURN 0
70 STORE("dislikes", LOAD("dislikes")+1)
100 RETURN 0
End Function
/*let away=!1;window.addEventListener("blur",()=>{away=!0}),window.addEventListener("focus",()=>{away=!1});let keys={},input={turn:0,turretTurn:0,turretPitch:0,up:0,down:0,primaryFire:!1,secondaryFire:!1,dropMine:!1,toggleCamera:!1,analogTurn:0,analogForward:0,analogTurretX:0,analogTurretY:0,zoomIn:!1,zoomOut:!1};window.addEventListener("keydown",e=>{keys[e.code]=!0}),window.addEventListener("keyup",e=>{keys[e.code]=!1});let prevCamPressed=!1,prevZoomInPressed=!1,prevZoomOutPressed=!1,prevStartPressed=!1;function gatherInput(){input.turn=(keys.ArrowLeft?-1:0)+(keys.ArrowRight?1:0),input.up=keys.ArrowUp?1:0,input.down=keys.ArrowDown?1:0;let e=keys.KeyC,t=keys.KeyE,a=keys.KeyQ,r=keys.Escape;input.turretTurn=(keys.KeyA?-1:0)+(keys.KeyD?1:0),input.turretPitch=(keys.KeyS?1:0)+(keys.KeyW?-1:0);const n=navigator.getGamepads()[0];n&&(input.analogTurn=n.axes[0],input.up=n.axes[1]<-.2?-n.axes[1]:0,input.down=n.axes[1]>.2?n.axes[1]:0,input.turretTurn=n.axes[2],input.turretPitch=n.axes[3],input.primaryFire=n.buttons[7].pressed,input.secondaryFire=n.buttons[6].pressed,input.dropMine=n.buttons[2].pressed,e=n.buttons[3].pressed,a=n.buttons[4].pressed,t=n.buttons[5].pressed,r=n.buttons[9].pressed||r),input.toggleCamera=!(!e||prevCamPressed),input.zoomIn=!(!t||prevZoomInPressed),input.zoomOut=!(!a||prevZoomOutPressed),prevCamPressed=e,menu(r),prevStartPressed=r}function menu(e){if(e&&!prevStartPressed&&(game.state===STATE.PAUSED?game.state=STATE.PLAYING:game.state===STATE.PLAYING&&(game.state=STATE.PAUSED)),game.state!==STATE.PLAYING){if(game.state===STATE.WIN&&e&&!prevStartPressed)return currentLevel=1,resetGame(),newLevel(currentLevel),void(game.state=STATE.PLAYING);if(game.state===STATE.LEVELCOMPLETE&&4===currentLevel&&(game.state=STATE.WIN),game.state===STATE.LEVELCOMPLETE&&e&&!prevStartPressed){if(5===++currentLevel)return void(game.state=STATE.WIN);resetGame(),newLevel(currentLevel),game.state=STATE.PLAYING}if(game.state===STATE.TITLE&&Object.keys(keys).length>0){for(const e of Object.keys(keys))if(!0===keys[e])return;game.state=STATE.PLAYING}(input.down>.1||!0===input.down)&&(volume-=.01*input.down),(input.up>.1||!0===input.up)&&(volume+=.01*input.up),volume=Math.max(0,Math.min(1,volume))}}function resizeMap(){minimapSize=Math.min(uicanvas.width,uicanvas.height)/mapScaler,MAP_W=minimapSize,MAP_H=minimapSize,mapScaleX=MAP_W/(512*mapScaler),mapScaleZ=MAP_H/(512*mapScaler),mapOffsetX=uicanvas.width-MAP_W-20,mapOffsetZ=20}function renderHUD(e){if(renderMinimap(),ctx.setTransform(1,0,0,1,0,0),drawHealthBar(),game.state===STATE.LEVELCOMPLETE)drawHUDText("MISSION COMPLETE",uicanvas.width/2,40),drawHUDText("Press START or ESC to Continue",uicanvas.width/2,80);else if(game.state===STATE.PAUSED)drawHUDText("PAUSED",uicanvas.width/2,40),drawHUDText(`VOL ${100*volume|0}%`,uicanvas.width/2,80);else if(game.state===STATE.WIN)drawHUDText("YOU WIN!",uicanvas.width/2,40),drawHUDText("All Missions Completed.",uicanvas.width/2,80),drawHUDText("Press Start to Restart.",uicanvas.width/2,120);else if(game.state===STATE.TITLE){let t=ctx.createLinearGradient(0,0,0,uicanvas.height);t.addColorStop(0,"#151515"),t.addColorStop(1,"#303030"),ctx.fillStyle=t,ctx.fillRect(0,0,uicanvas.width,uicanvas.height),ctx.strokeStyle="rgba(255,255,255,0.05)";for(let e=0;e<uicanvas.width;e+=40)ctx.beginPath(),ctx.moveTo(e,0),ctx.lineTo(e,uicanvas.height),ctx.stroke();let a=.01*e|0,r="--------------",n=r.slice(a%r.length)+r.slice(0,a%r.length);drawHUDText(n,uicanvas.width/2,30);let i=.5*Math.sin(.003*e)+.5;drawHUDText(" FULL TANK 3D ",uicanvas.width/2,50,"28px",`rgba(255,255,255,${i})`,`rgba(0,255,0,${i})`),drawHUDText(n,uicanvas.width/2,66),Math.sin(.005*e)>0&&drawHUDText("Press Any Key to Begin",uicanvas.width/2,120)}}function mapX(e){return(e-game.player.x)*mapScaleX+MAP_W/2}function mapZ(e){return(e-game.player.z)*mapScaleZ+MAP_H/2}function renderMinimap(){ctx.save(),ctx.translate(mapOffsetX,mapOffsetZ),ctx.fillStyle="rgba(0,0,0,0.35)",ctx.strokeStyle="rgba(255,255,255,0.2)",ctx.fillRect(0,0,MAP_W,MAP_H),ctx.translate(MAP_W/2,MAP_H/2),ctx.rotate(-game.player.yaw+Math.PI),ctx.translate(-MAP_W/2,-MAP_H/2);for(const e in game.bases){const t=game.bases[e],a=mapX(t.x),r=mapZ(t.z);a<0||a>MAP_W||r<0||r>MAP_H||(ctx.fillStyle="rgba(255,0,0,0.5)",ctx.beginPath(),ctx.arc(a,r,4,0,2*Math.PI),ctx.fill())}ctx.fillStyle="red";for(const e of game.enemies){const t=mapX(e.x),a=mapZ(e.z);t<0||t>MAP_W||a<0||a>MAP_H||(ctx.beginPath(),ctx.arc(t,a,2,0,2*Math.PI),ctx.fill())}ctx.restore(),ctx.save(),ctx.translate(mapOffsetX+MAP_W/2,mapOffsetZ+MAP_H/2),ctx.fillStyle="cyan",ctx.beginPath(),ctx.moveTo(0,-6),ctx.lineTo(4,4),ctx.lineTo(-4,4),ctx.closePath(),ctx.fill(),ctx.restore()}function drawHealthBar(){const e=game.player.health/game.player.maxHealth;ctx.fillStyle="#222",ctx.fillRect(20,20,200,20),ctx.fillStyle=e>.5?"#4caf50":e>.25?"#ff9800":"#f44336",ctx.fillRect(20,20,200*e,20),ctx.strokeStyle="#000",ctx.lineWidth=1,ctx.strokeRect(20,20,200,20)}function drawHUDText(e,t,a,r="24px",n="white",i="black"){ctx.font=r+" Consolas",ctx.fillStyle=n,ctx.textAlign="center",ctx.textBaseline="middle",ctx.strokeStyle=i,ctx.lineWidth=2,ctx.strokeText(e,t,a),ctx.fillText(e,t,a)}window.addEventListener("keydown",e=>{"Space"===e.code&&(input.primaryFire=!0),"ShiftLeft"!==e.code&&"ShiftRight"!==e.code||(input.secondaryFire=!0),"Enter"!==e.code&&"KeyF"!==e.code||(input.dropMine=!0)}),window.addEventListener("keyup",e=>{"Space"===e.code&&(input.primaryFire=!1),"ShiftLeft"!==e.code&&"ShiftRight"!==e.code||(input.secondaryFire=!1),"Enter"!==e.code&&"KeyF"!==e.code||(input.dropMine=!1)});let audioCtx,volume=.5;function initAudio(){audioCtx=new(window.AudioContext||window.webkitAudioContext)}function sfxCannon(e){const t=audioCtx;let a=0;if(e!==game.player){const t=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(t,n);if(a=Math.min(r,120)/120,1===a)return}const n=volume*(1-a),r=Math.cos(camera.yaw),c=-Math.sin(camera.yaw);let o=(e.x-camera.x)*r+(e.z-camera.z)*c;o/=40,o=Math.max(-1,Math.min(1,o));const i=t.createStereoPanner();i.pan.value=o,i.connect(t.destination);const m=t.createOscillator(),s=t.createGain();m.type="square",m.frequency.setValueAtTime(500,t.currentTime),m.frequency.exponentialRampToValueAtTime(120,t.currentTime+.05),s.gain.setValueAtTime(.7*n,t.currentTime),s.gain.exponentialRampToValueAtTime(.001,t.currentTime+.07),m.connect(s).connect(i),m.start(),m.stop(t.currentTime+.07);const u=t.createBuffer(1,6e3,44100),l=u.getChannelData(0);for(let e=0;e<l.length;e++)l[e]=(2*Math.random()-1)*(1-e/l.length);const f=t.createBufferSource();f.buffer=u;const T=t.createGain();T.gain.setValueAtTime(.8*n,t.currentTime),T.gain.exponentialRampToValueAtTime(.001,t.currentTime+.12),f.connect(T).connect(i),f.start();const p=t.createBuffer(1,44100,44100),h=p.getChannelData(0);for(let e=0;e<h.length;e++)h[e]=(2*Math.random()-1)*Math.pow(1-e/h.length,2);const x=t.createBufferSource();x.buffer=p;const g=t.createGain();g.gain.setValueAtTime(.9*n,t.currentTime),g.gain.exponentialRampToValueAtTime(.001,t.currentTime+.6),x.connect(g).connect(i),x.start()}function sfxMachineGun(e){const t=audioCtx;let a=0;if(e!==game.player){const t=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(t,n);if(a=Math.min(r,120)/120,1===a)return}const n=volume*(1-a),r=Math.cos(camera.yaw),c=-Math.sin(camera.yaw);let o=(e.x-camera.x)*r+(e.z-camera.z)*c;o/=40,o=Math.max(-1,Math.min(1,o));const i=t.createStereoPanner();i.pan.value=o,i.connect(t.destination);const m=t.createOscillator(),s=t.createGain();m.type="square",m.frequency.setValueAtTime(900-300*a,t.currentTime),m.frequency.exponentialRampToValueAtTime(300-100*a,t.currentTime+.03),s.gain.setValueAtTime(.6*n,t.currentTime),s.gain.exponentialRampToValueAtTime(.001,t.currentTime+.04),m.connect(s).connect(i),m.start(),m.stop(t.currentTime+.04);const u=t.createBuffer(1,2e3,44100),l=u.getChannelData(0);for(let e=0;e<l.length;e++)l[e]=(2*Math.random()-1)*(1-e/l.length);const f=t.createBufferSource();f.buffer=u;const T=t.createGain();T.gain.setValueAtTime(.4*n,t.currentTime),T.gain.exponentialRampToValueAtTime(.001,t.currentTime+.05),f.connect(T).connect(i),f.start()}function sfxMine(){const e=audioCtx,t=e.createOscillator(),a=e.createGain();t.type="square",t.frequency.setValueAtTime(600,e.currentTime),t.frequency.exponentialRampToValueAtTime(80,e.currentTime+.1),a.gain.setValueAtTime(.3*volume,e.currentTime),a.gain.exponentialRampToValueAtTime(.001,e.currentTime+.1),t.connect(a).connect(e.destination),t.start(),t.stop(e.currentTime+.1)}function sfxExplosion(e){const t=audioCtx,a=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(a,n),c=Math.min(r/100,1);if(1===c)return;const o=volume*(1-c),i=Math.cos(camera.yaw),m=-Math.sin(camera.yaw);let s=(e.x-camera.x)*i+(e.z-camera.z)*m;s/=40,s=Math.max(-1,Math.min(1,s));const u=t.createStereoPanner();u.pan.value=s,u.connect(t.destination);const l=t.createBuffer(1,44100,44100),f=l.getChannelData(0);for(let e=0;e<f.length;e++)f[e]=(2*Math.random()-1)*(1-e/f.length);const T=t.createBufferSource();T.buffer=l;const p=t.createGain();p.gain.setValueAtTime(o,t.currentTime),p.gain.exponentialRampToValueAtTime(.01,t.currentTime+.5);const h=t.createOscillator();h.type="sine",h.frequency.setValueAtTime(40+10*Math.random(),t.currentTime);const x=t.createGain();x.gain.setValueAtTime(.7*o,t.currentTime),x.gain.exponentialRampToValueAtTime(.001,t.currentTime+.6);const g=t.createBufferSource();g.buffer=l;const y=t.createBiquadFilter();y.type="lowpass",y.frequency.value=300;const d=t.createGain();d.gain.setValueAtTime(.4*o,t.currentTime),d.gain.exponentialRampToValueAtTime(.001,t.currentTime+.7),T.connect(p).connect(u),h.connect(x).connect(u),g.connect(y).connect(d).connect(u),T.start(),h.start(),g.start(),h.stop(t.currentTime+.6),g.stop(t.currentTime+.7)}function sfxHit(e){const t=audioCtx;let a=0;if(e!==game.player){const t=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(t,n);if(a=Math.min(r,100)/100,1===a)return}const n=volume*(1-a),r=Math.cos(camera.yaw),c=-Math.sin(camera.yaw);let o=(e.x-camera.x)*r+(e.z-camera.z)*c;o/=40,o=Math.max(-1,Math.min(1,o));const i=t.createStereoPanner();i.pan.value=o,i.connect(t.destination);const m=t.createBuffer(1,3e3,44100),s=m.getChannelData(0);for(let e=0;e<s.length;e++)s[e]=(2*Math.random()-1)*(1-e/s.length);const u=t.createBufferSource();u.buffer=m;const l=t.createOscillator();l.type="sine",l.frequency.setValueAtTime(120+40*Math.random(),t.currentTime);const f=t.createOscillator();f.type="square",f.frequency.setValueAtTime(2e3+500*Math.random(),t.currentTime);const T=t.createGain();T.gain.setValueAtTime(.3*n,t.currentTime),T.gain.exponentialRampToValueAtTime(.001,t.currentTime+.05);const p=t.createBufferSource();p.buffer=m;const h=t.createBiquadFilter();h.type="highpass",h.frequency.value=3e3;const x=t.createGain();x.gain.setValueAtTime(.2*n,t.currentTime),x.gain.exponentialRampToValueAtTime(.001,t.currentTime+.06);const g=t.createGain();g.gain.setValueAtTime(.5*n,t.currentTime),g.gain.exponentialRampToValueAtTime(.001,t.currentTime+.08),u.connect(g),l.connect(g),f.connect(T),p.connect(h),h.connect(x),g.connect(i),T.connect(i),x.connect(i),u.start(),l.start(),f.start(),p.start(),l.stop(t.currentTime+.08),f.stop(t.currentTime+.05),p.stop(t.currentTime+.06)}function spawnTriangles(e,t=20,a=.1){for(let n=0;n<t;n++){const t=getRandomUnitVector(),n=5+10*Math.random(),r=createSparkMesh(),c={type:"tri",x:e.x,y:e.y,z:e.z,dx:t.x*n,dy:t.y*n,dz:t.z*n,scale:a+.1*Math.random(),rot:Math.random()*Math.PI*2,rotSpeed:10*(Math.random()-.5),life:.5+.5*Math.random(),mesh:new Mesh(gl,r.vertices,r.normals,r.colors)},o=new SceneObject(c.mesh);o.transform.x=c.x,o.transform.y=c.y,o.transform.z=c.z,o.transform.sx=c.scale,o.transform.sy=c.scale,o.transform.sz=c.scale,c.mesh=o,scene.push(o),game.particles.push(c)}}function createSparkMesh(){return{vertices:new Float32Array(triangleVertices),normals:new Float32Array(triangleNormals),colors:new Float32Array(sparkColors)}}const sparkColors=new Float32Array([.8,.5,.3,.8,.5,.3,.8,.5,.3]);function updateParticles(e){for(let t of game.particles)t.x+=t.dx*e,t.y+=t.dy*e,t.z+=t.dz*e,t.scale*=.9,t.rot+=t.rotSpeed*e,t.mesh.transform.x=t.x,t.mesh.transform.y=t.y,t.mesh.transform.z=t.z,t.mesh.transform.rx=t.rot,t.mesh.transform.ry=t.rot,t.mesh.transform.rz=t.rot,t.life-=e,t.life<=0&&(t.dead=!0);game.particles=game.particles.filter(e=>!e.dead||(scene.splice(scene.indexOf(e.mesh),1),!1))}function getRandomUnitVector(){let e=2*Math.random()-1,t=2*Math.random()-1,a=2*Math.random()-1;const n=Math.sqrt(e*e+t*t+a*a);return 0===n?getRandomUnitVector():{x:e/n,y:t/n,z:a/n}}*/ |
| SC Arguments: [Name:SC_ACTION Type:uint64 Value:'1' Name:SC_CODE Type:string Value:'// Copyright 2024. Civilware. All rights reserved.
// TELA Decentralized Web Document (TELA-DOC-1)
Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "data4.js")
31 STORE("descrHdr", "Data file 4")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "data4.js")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "bdadf7c15644a8bb3be725e32235bbf4fe578f5a3c11bb29bd4438f9d52e6d6")
37 STORE("fileCheckS", "15bc571ec1b3ee63b94d4bffef978f8ad13439fa87131108957b75d7f7f0cd15")
100 RETURN 0
End Function
Function init() Uint64
10 IF EXISTS("owner") == 0 THEN GOTO 30
20 RETURN 1
30 STORE("owner", address())
50 STORE("docVersion", "1.0.0")
60 STORE("hash", HEX(TXID()))
70 STORE("likes", 0)
80 STORE("dislikes", 0)
100 RETURN 0
End Function
Function address() String
10 DIM s as String
20 LET s = SIGNER()
30 IF IS_ADDRESS_VALID(s) THEN GOTO 50
40 RETURN "anon"
50 RETURN ADDRESS_STRING(s)
End Function
Function Rate(r Uint64) Uint64
10 DIM addr as String
15 LET addr = address()
16 IF r < 100 && EXISTS(addr) == 0 && addr != "anon" THEN GOTO 30
20 RETURN 1
30 STORE(addr, ""+r+"_"+BLOCK_HEIGHT())
40 IF r < 50 THEN GOTO 70
50 STORE("likes", LOAD("likes")+1)
60 RETURN 0
70 STORE("dislikes", LOAD("dislikes")+1)
100 RETURN 0
End Function
/*let away=!1;window.addEventListener("blur",()=>{away=!0}),window.addEventListener("focus",()=>{away=!1});let keys={},input={turn:0,turretTurn:0,turretPitch:0,up:0,down:0,primaryFire:!1,secondaryFire:!1,dropMine:!1,toggleCamera:!1,analogTurn:0,analogForward:0,analogTurretX:0,analogTurretY:0,zoomIn:!1,zoomOut:!1};window.addEventListener("keydown",e=>{keys[e.code]=!0}),window.addEventListener("keyup",e=>{keys[e.code]=!1});let prevCamPressed=!1,prevZoomInPressed=!1,prevZoomOutPressed=!1,prevStartPressed=!1;function gatherInput(){input.turn=(keys.ArrowLeft?-1:0)+(keys.ArrowRight?1:0),input.up=keys.ArrowUp?1:0,input.down=keys.ArrowDown?1:0;let e=keys.KeyC,t=keys.KeyE,a=keys.KeyQ,r=keys.Escape;input.turretTurn=(keys.KeyA?-1:0)+(keys.KeyD?1:0),input.turretPitch=(keys.KeyS?1:0)+(keys.KeyW?-1:0);const n=navigator.getGamepads()[0];n&&(input.analogTurn=n.axes[0],input.up=n.axes[1]<-.2?-n.axes[1]:0,input.down=n.axes[1]>.2?n.axes[1]:0,input.turretTurn=n.axes[2],input.turretPitch=n.axes[3],input.primaryFire=n.buttons[7].pressed,input.secondaryFire=n.buttons[6].pressed,input.dropMine=n.buttons[2].pressed,e=n.buttons[3].pressed,a=n.buttons[4].pressed,t=n.buttons[5].pressed,r=n.buttons[9].pressed||r),input.toggleCamera=!(!e||prevCamPressed),input.zoomIn=!(!t||prevZoomInPressed),input.zoomOut=!(!a||prevZoomOutPressed),prevCamPressed=e,menu(r),prevStartPressed=r}function menu(e){if(e&&!prevStartPressed&&(game.state===STATE.PAUSED?game.state=STATE.PLAYING:game.state===STATE.PLAYING&&(game.state=STATE.PAUSED)),game.state!==STATE.PLAYING){if(game.state===STATE.WIN&&e&&!prevStartPressed)return currentLevel=1,resetGame(),newLevel(currentLevel),void(game.state=STATE.PLAYING);if(game.state===STATE.LEVELCOMPLETE&&4===currentLevel&&(game.state=STATE.WIN),game.state===STATE.LEVELCOMPLETE&&e&&!prevStartPressed){if(5===++currentLevel)return void(game.state=STATE.WIN);resetGame(),newLevel(currentLevel),game.state=STATE.PLAYING}if(game.state===STATE.TITLE&&Object.keys(keys).length>0){for(const e of Object.keys(keys))if(!0===keys[e])return;game.state=STATE.PLAYING}(input.down>.1||!0===input.down)&&(volume-=.01*input.down),(input.up>.1||!0===input.up)&&(volume+=.01*input.up),volume=Math.max(0,Math.min(1,volume))}}function resizeMap(){minimapSize=Math.min(uicanvas.width,uicanvas.height)/mapScaler,MAP_W=minimapSize,MAP_H=minimapSize,mapScaleX=MAP_W/(512*mapScaler),mapScaleZ=MAP_H/(512*mapScaler),mapOffsetX=uicanvas.width-MAP_W-20,mapOffsetZ=20}function renderHUD(e){if(renderMinimap(),ctx.setTransform(1,0,0,1,0,0),drawHealthBar(),game.state===STATE.LEVELCOMPLETE)drawHUDText("MISSION COMPLETE",uicanvas.width/2,40),drawHUDText("Press START or ESC to Continue",uicanvas.width/2,80);else if(game.state===STATE.PAUSED)drawHUDText("PAUSED",uicanvas.width/2,40),drawHUDText(`VOL ${100*volume|0}%`,uicanvas.width/2,80);else if(game.state===STATE.WIN)drawHUDText("YOU WIN!",uicanvas.width/2,40),drawHUDText("All Missions Completed.",uicanvas.width/2,80),drawHUDText("Press Start to Restart.",uicanvas.width/2,120);else if(game.state===STATE.TITLE){let t=ctx.createLinearGradient(0,0,0,uicanvas.height);t.addColorStop(0,"#151515"),t.addColorStop(1,"#303030"),ctx.fillStyle=t,ctx.fillRect(0,0,uicanvas.width,uicanvas.height),ctx.strokeStyle="rgba(255,255,255,0.05)";for(let e=0;e<uicanvas.width;e+=40)ctx.beginPath(),ctx.moveTo(e,0),ctx.lineTo(e,uicanvas.height),ctx.stroke();let a=.01*e|0,r="--------------",n=r.slice(a%r.length)+r.slice(0,a%r.length);drawHUDText(n,uicanvas.width/2,30);let i=.5*Math.sin(.003*e)+.5;drawHUDText(" FULL TANK 3D ",uicanvas.width/2,50,"28px",`rgba(255,255,255,${i})`,`rgba(0,255,0,${i})`),drawHUDText(n,uicanvas.width/2,66),Math.sin(.005*e)>0&&drawHUDText("Press Any Key to Begin",uicanvas.width/2,120)}}function mapX(e){return(e-game.player.x)*mapScaleX+MAP_W/2}function mapZ(e){return(e-game.player.z)*mapScaleZ+MAP_H/2}function renderMinimap(){ctx.save(),ctx.translate(mapOffsetX,mapOffsetZ),ctx.fillStyle="rgba(0,0,0,0.35)",ctx.strokeStyle="rgba(255,255,255,0.2)",ctx.fillRect(0,0,MAP_W,MAP_H),ctx.translate(MAP_W/2,MAP_H/2),ctx.rotate(-game.player.yaw+Math.PI),ctx.translate(-MAP_W/2,-MAP_H/2);for(const e in game.bases){const t=game.bases[e],a=mapX(t.x),r=mapZ(t.z);a<0||a>MAP_W||r<0||r>MAP_H||(ctx.fillStyle="rgba(255,0,0,0.5)",ctx.beginPath(),ctx.arc(a,r,4,0,2*Math.PI),ctx.fill())}ctx.fillStyle="red";for(const e of game.enemies){const t=mapX(e.x),a=mapZ(e.z);t<0||t>MAP_W||a<0||a>MAP_H||(ctx.beginPath(),ctx.arc(t,a,2,0,2*Math.PI),ctx.fill())}ctx.restore(),ctx.save(),ctx.translate(mapOffsetX+MAP_W/2,mapOffsetZ+MAP_H/2),ctx.fillStyle="cyan",ctx.beginPath(),ctx.moveTo(0,-6),ctx.lineTo(4,4),ctx.lineTo(-4,4),ctx.closePath(),ctx.fill(),ctx.restore()}function drawHealthBar(){const e=game.player.health/game.player.maxHealth;ctx.fillStyle="#222",ctx.fillRect(20,20,200,20),ctx.fillStyle=e>.5?"#4caf50":e>.25?"#ff9800":"#f44336",ctx.fillRect(20,20,200*e,20),ctx.strokeStyle="#000",ctx.lineWidth=1,ctx.strokeRect(20,20,200,20)}function drawHUDText(e,t,a,r="24px",n="white",i="black"){ctx.font=r+" Consolas",ctx.fillStyle=n,ctx.textAlign="center",ctx.textBaseline="middle",ctx.strokeStyle=i,ctx.lineWidth=2,ctx.strokeText(e,t,a),ctx.fillText(e,t,a)}window.addEventListener("keydown",e=>{"Space"===e.code&&(input.primaryFire=!0),"ShiftLeft"!==e.code&&"ShiftRight"!==e.code||(input.secondaryFire=!0),"Enter"!==e.code&&"KeyF"!==e.code||(input.dropMine=!0)}),window.addEventListener("keyup",e=>{"Space"===e.code&&(input.primaryFire=!1),"ShiftLeft"!==e.code&&"ShiftRight"!==e.code||(input.secondaryFire=!1),"Enter"!==e.code&&"KeyF"!==e.code||(input.dropMine=!1)});let audioCtx,volume=.5;function initAudio(){audioCtx=new(window.AudioContext||window.webkitAudioContext)}function sfxCannon(e){const t=audioCtx;let a=0;if(e!==game.player){const t=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(t,n);if(a=Math.min(r,120)/120,1===a)return}const n=volume*(1-a),r=Math.cos(camera.yaw),c=-Math.sin(camera.yaw);let o=(e.x-camera.x)*r+(e.z-camera.z)*c;o/=40,o=Math.max(-1,Math.min(1,o));const i=t.createStereoPanner();i.pan.value=o,i.connect(t.destination);const m=t.createOscillator(),s=t.createGain();m.type="square",m.frequency.setValueAtTime(500,t.currentTime),m.frequency.exponentialRampToValueAtTime(120,t.currentTime+.05),s.gain.setValueAtTime(.7*n,t.currentTime),s.gain.exponentialRampToValueAtTime(.001,t.currentTime+.07),m.connect(s).connect(i),m.start(),m.stop(t.currentTime+.07);const u=t.createBuffer(1,6e3,44100),l=u.getChannelData(0);for(let e=0;e<l.length;e++)l[e]=(2*Math.random()-1)*(1-e/l.length);const f=t.createBufferSource();f.buffer=u;const T=t.createGain();T.gain.setValueAtTime(.8*n,t.currentTime),T.gain.exponentialRampToValueAtTime(.001,t.currentTime+.12),f.connect(T).connect(i),f.start();const p=t.createBuffer(1,44100,44100),h=p.getChannelData(0);for(let e=0;e<h.length;e++)h[e]=(2*Math.random()-1)*Math.pow(1-e/h.length,2);const x=t.createBufferSource();x.buffer=p;const g=t.createGain();g.gain.setValueAtTime(.9*n,t.currentTime),g.gain.exponentialRampToValueAtTime(.001,t.currentTime+.6),x.connect(g).connect(i),x.start()}function sfxMachineGun(e){const t=audioCtx;let a=0;if(e!==game.player){const t=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(t,n);if(a=Math.min(r,120)/120,1===a)return}const n=volume*(1-a),r=Math.cos(camera.yaw),c=-Math.sin(camera.yaw);let o=(e.x-camera.x)*r+(e.z-camera.z)*c;o/=40,o=Math.max(-1,Math.min(1,o));const i=t.createStereoPanner();i.pan.value=o,i.connect(t.destination);const m=t.createOscillator(),s=t.createGain();m.type="square",m.frequency.setValueAtTime(900-300*a,t.currentTime),m.frequency.exponentialRampToValueAtTime(300-100*a,t.currentTime+.03),s.gain.setValueAtTime(.6*n,t.currentTime),s.gain.exponentialRampToValueAtTime(.001,t.currentTime+.04),m.connect(s).connect(i),m.start(),m.stop(t.currentTime+.04);const u=t.createBuffer(1,2e3,44100),l=u.getChannelData(0);for(let e=0;e<l.length;e++)l[e]=(2*Math.random()-1)*(1-e/l.length);const f=t.createBufferSource();f.buffer=u;const T=t.createGain();T.gain.setValueAtTime(.4*n,t.currentTime),T.gain.exponentialRampToValueAtTime(.001,t.currentTime+.05),f.connect(T).connect(i),f.start()}function sfxMine(){const e=audioCtx,t=e.createOscillator(),a=e.createGain();t.type="square",t.frequency.setValueAtTime(600,e.currentTime),t.frequency.exponentialRampToValueAtTime(80,e.currentTime+.1),a.gain.setValueAtTime(.3*volume,e.currentTime),a.gain.exponentialRampToValueAtTime(.001,e.currentTime+.1),t.connect(a).connect(e.destination),t.start(),t.stop(e.currentTime+.1)}function sfxExplosion(e){const t=audioCtx,a=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(a,n),c=Math.min(r/100,1);if(1===c)return;const o=volume*(1-c),i=Math.cos(camera.yaw),m=-Math.sin(camera.yaw);let s=(e.x-camera.x)*i+(e.z-camera.z)*m;s/=40,s=Math.max(-1,Math.min(1,s));const u=t.createStereoPanner();u.pan.value=s,u.connect(t.destination);const l=t.createBuffer(1,44100,44100),f=l.getChannelData(0);for(let e=0;e<f.length;e++)f[e]=(2*Math.random()-1)*(1-e/f.length);const T=t.createBufferSource();T.buffer=l;const p=t.createGain();p.gain.setValueAtTime(o,t.currentTime),p.gain.exponentialRampToValueAtTime(.01,t.currentTime+.5);const h=t.createOscillator();h.type="sine",h.frequency.setValueAtTime(40+10*Math.random(),t.currentTime);const x=t.createGain();x.gain.setValueAtTime(.7*o,t.currentTime),x.gain.exponentialRampToValueAtTime(.001,t.currentTime+.6);const g=t.createBufferSource();g.buffer=l;const y=t.createBiquadFilter();y.type="lowpass",y.frequency.value=300;const d=t.createGain();d.gain.setValueAtTime(.4*o,t.currentTime),d.gain.exponentialRampToValueAtTime(.001,t.currentTime+.7),T.connect(p).connect(u),h.connect(x).connect(u),g.connect(y).connect(d).connect(u),T.start(),h.start(),g.start(),h.stop(t.currentTime+.6),g.stop(t.currentTime+.7)}function sfxHit(e){const t=audioCtx;let a=0;if(e!==game.player){const t=game.player.x-e.x,n=game.player.z-e.z,r=Math.hypot(t,n);if(a=Math.min(r,100)/100,1===a)return}const n=volume*(1-a),r=Math.cos(camera.yaw),c=-Math.sin(camera.yaw);let o=(e.x-camera.x)*r+(e.z-camera.z)*c;o/=40,o=Math.max(-1,Math.min(1,o));const i=t.createStereoPanner();i.pan.value=o,i.connect(t.destination);const m=t.createBuffer(1,3e3,44100),s=m.getChannelData(0);for(let e=0;e<s.length;e++)s[e]=(2*Math.random()-1)*(1-e/s.length);const u=t.createBufferSource();u.buffer=m;const l=t.createOscillator();l.type="sine",l.frequency.setValueAtTime(120+40*Math.random(),t.currentTime);const f=t.createOscillator();f.type="square",f.frequency.setValueAtTime(2e3+500*Math.random(),t.currentTime);const T=t.createGain();T.gain.setValueAtTime(.3*n,t.currentTime),T.gain.exponentialRampToValueAtTime(.001,t.currentTime+.05);const p=t.createBufferSource();p.buffer=m;const h=t.createBiquadFilter();h.type="highpass",h.frequency.value=3e3;const x=t.createGain();x.gain.setValueAtTime(.2*n,t.currentTime),x.gain.exponentialRampToValueAtTime(.001,t.currentTime+.06);const g=t.createGain();g.gain.setValueAtTime(.5*n,t.currentTime),g.gain.exponentialRampToValueAtTime(.001,t.currentTime+.08),u.connect(g),l.connect(g),f.connect(T),p.connect(h),h.connect(x),g.connect(i),T.connect(i),x.connect(i),u.start(),l.start(),f.start(),p.start(),l.stop(t.currentTime+.08),f.stop(t.currentTime+.05),p.stop(t.currentTime+.06)}function spawnTriangles(e,t=20,a=.1){for(let n=0;n<t;n++){const t=getRandomUnitVector(),n=5+10*Math.random(),r=createSparkMesh(),c={type:"tri",x:e.x,y:e.y,z:e.z,dx:t.x*n,dy:t.y*n,dz:t.z*n,scale:a+.1*Math.random(),rot:Math.random()*Math.PI*2,rotSpeed:10*(Math.random()-.5),life:.5+.5*Math.random(),mesh:new Mesh(gl,r.vertices,r.normals,r.colors)},o=new SceneObject(c.mesh);o.transform.x=c.x,o.transform.y=c.y,o.transform.z=c.z,o.transform.sx=c.scale,o.transform.sy=c.scale,o.transform.sz=c.scale,c.mesh=o,scene.push(o),game.particles.push(c)}}function createSparkMesh(){return{vertices:new Float32Array(triangleVertices),normals:new Float32Array(triangleNormals),colors:new Float32Array(sparkColors)}}const sparkColors=new Float32Array([.8,.5,.3,.8,.5,.3,.8,.5,.3]);function updateParticles(e){for(let t of game.particles)t.x+=t.dx*e,t.y+=t.dy*e,t.z+=t.dz*e,t.scale*=.9,t.rot+=t.rotSpeed*e,t.mesh.transform.x=t.x,t.mesh.transform.y=t.y,t.mesh.transform.z=t.z,t.mesh.transform.rx=t.rot,t.mesh.transform.ry=t.rot,t.mesh.transform.rz=t.rot,t.life-=e,t.life<=0&&(t.dead=!0);game.particles=game.particles.filter(e=>!e.dead||(scene.splice(scene.indexOf(e.mesh),1),!1))}function getRandomUnitVector(){let e=2*Math.random()-1,t=2*Math.random()-1,a=2*Math.random()-1;const n=Math.sqrt(e*e+t*t+a*a);return 0===n?getRandomUnitVector():{x:e/n,y:t/n,z:a/n}}*/'] |