From 22dcfe21da368519645056f3c648eddbaec4c4dd Mon Sep 17 00:00:00 2001 From: blueSparrow2000 Date: Fri, 9 Feb 2024 10:54:07 +0900 Subject: [PATCH] Plane design: more transparent --- gun infos.xlsx | Bin 22145 -> 22601 bytes public/frontend.js | 105 ++++++++++++++++++++++----------------------- src/backend.js | 46 ++++++++++++++------ 3 files changed, 84 insertions(+), 67 deletions(-) diff --git a/gun infos.xlsx b/gun infos.xlsx index 00c78bfc32cc17df1a973baa327550815214f39f..b488f0c359f4f862bee3c9f90eafab7ebb89ebb1 100644 GIT binary patch delta 15470 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 G_&)&p_RvxQ delta 14806 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 { - if (CheckOnBoard()){ - return - } shootCheck(event) }) - // periodically request backend server setInterval(()=>{ if (keys.f.pressed){ @@ -472,10 +465,6 @@ setInterval(()=>{ //socket.emit('keydown',{keycode:'KeyG'}) } - if (CheckOnBoard()){// player cannot do anything below - return - } - if (keys.digit1.pressed){ socket.emit('keydown',{keycode:'Digit1'}) } @@ -509,6 +498,8 @@ setInterval(()=>{ } else{ // builtin socket.emit('playermousechange', {x:cursorX,y:cursorY}) // report mouseposition every TICK, not immediately } + + },TICKRATE) @@ -536,7 +527,7 @@ function reloadGun(){ const GUNRELOADRATE = gunInfoFrontEnd[currentGunName].reloadTime if (currentGunName==='flareGun'){ // not reloadable - console.log("flaregun cannot be reloaded") + //console.log("flaregun cannot be reloaded") return } @@ -699,10 +690,7 @@ socket.on('interact',({backEndItems,backEndVehicles})=>{ // manual takeoff if (frontEndPlayer.onBoard){ // take off! - playerdeathsound.play() // sounds like this! - socket.emit('takeOff') - frontEndPlayer.onBoard = false return } @@ -1274,7 +1262,7 @@ function loop(){ ///////////////////////////////// PLAYERS ///////////////////////////////// canvas.fillStyle = 'white' // canvas.strokeStyle = 'black' // same stroke style with projectiles - if (frontEndPlayer && !frontEndPlayer.onBoard){ // draw myself in the center + if (!frontEndPlayer.onBoard){ // draw myself in the center const currentHoldingItem = getCurItem(frontEndPlayer) frontEndPlayer.displayAttribute(canvas, camX, camY, currentHoldingItem) if (gunInfoFrontEnd){ @@ -1305,7 +1293,7 @@ function loop(){ // This loop is for displaying health & name canvas.lineWidth = 8 - if (frontEndPlayer && !frontEndPlayer.onBoard){ // draw myself in the center + if (!frontEndPlayer.onBoard){ // draw myself in the center frontEndPlayer.displayHealth(canvas, camX, camY, centerX , centerY - PLAYERRADIUS*2) } @@ -1338,40 +1326,7 @@ function loop(){ - // ADVANCED PLANTS (OPAQUE) - canvas.save(); - canvas.globalAlpha = 0.8; - for (let row = chunkInfo.rowNum-sightChunk;row < chunkInfo.rowNum + sightChunk+1;row++){ - for (let col = chunkInfo.colNum-sightChunk;col < chunkInfo.colNum + sightChunk+1 ;col++){ - if (row < 0 || col < 0 || row >= groundMap.length || col >= groundMap[0].length){ - continue - } - const { id } = decalMap[row][col] ?? {id:undefined}; - const imageRow = parseInt(id / TILES_IN_ROW); - const imageCol = id % TILES_IN_ROW; - if (130 <= id && id <= 134){ // grass - opacity - canvas.drawImage(mapImage, - imageCol * TILE_SIZE, - imageRow * TILE_SIZE, - TILE_SIZE,TILE_SIZE, - col*TILE_SIZE - camX, - row*TILE_SIZE - camY, - TILE_SIZE,TILE_SIZE - ); - } else if (id===107){ // overhanges (roofs) - opacity but not clear as house - canvas.drawImage(mapImage, - imageCol * TILE_SIZE, - imageRow * TILE_SIZE, - TILE_SIZE,TILE_SIZE, - col*TILE_SIZE - camX, - row*TILE_SIZE - camY, - TILE_SIZE,TILE_SIZE - ); - } - } - } - canvas.restore(); - // ADVANCED PLANTS + // ADVANCED NON OPAC for (let row = chunkInfo.rowNum-sightChunk;row < chunkInfo.rowNum + sightChunk+1;row++){ @@ -1411,16 +1366,58 @@ function loop(){ // ADVANCED NON OPAC + // GLOBAL ALPHA CHANGES + canvas.save(); + // ADVANCED PLANTS (OPAQUE) + canvas.globalAlpha = 0.8; + + for (let row = chunkInfo.rowNum-sightChunk;row < chunkInfo.rowNum + sightChunk+1;row++){ + for (let col = chunkInfo.colNum-sightChunk;col < chunkInfo.colNum + sightChunk+1 ;col++){ + if (row < 0 || col < 0 || row >= groundMap.length || col >= groundMap[0].length){ + continue + } + const { id } = decalMap[row][col] ?? {id:undefined}; + const imageRow = parseInt(id / TILES_IN_ROW); + const imageCol = id % TILES_IN_ROW; + if (130 <= id && id <= 134){ // grass - opacity + canvas.drawImage(mapImage, + imageCol * TILE_SIZE, + imageRow * TILE_SIZE, + TILE_SIZE,TILE_SIZE, + col*TILE_SIZE - camX, + row*TILE_SIZE - camY, + TILE_SIZE,TILE_SIZE + ); + } else if (id===107){ // overhanges (roofs) - opacity but not clear as house + canvas.drawImage(mapImage, + imageCol * TILE_SIZE, + imageRow * TILE_SIZE, + TILE_SIZE,TILE_SIZE, + col*TILE_SIZE - camX, + row*TILE_SIZE - camY, + TILE_SIZE,TILE_SIZE + ); + } + } + } + // ADVANCED PLANTS + // Air strike + // canvas.globalAlpha = 0.9; for (const id in frontEndAirstrikes){ const frontEndAirstrike = frontEndAirstrikes[id] if (frontEndPlayer.IsVisible(chunkInfo,getChunk(frontEndAirstrike.x,frontEndAirstrike.y),sightChunk+3) ){ canvas.drawImage(planeImage,frontEndAirstrike.x - camX - 384, frontEndAirstrike.y - camY - 558) - } } + canvas.restore(); + // GLOBAL ALPHA CHANGES + + + + if (frontEndPlayer.onBoard){ // show text message canvas.fillText('Press F to take off!', centerX - 110, centerY + PLAYERRADIUS*2) } @@ -1458,8 +1455,8 @@ document.querySelector('#usernameForm').addEventListener('submit', (event) => { resetKeys() listen = true // initialize the semaphore updateSightChunk(0) // scope to 0 - const playerX = TILE_SIZE*2 //MAPWIDTH * Math.random() - const playerY = MAPHEIGHT/2 //MAPHEIGHT * Math.random() + const playerX = MAPWIDTH * Math.random() //TILE_SIZE*2 // + const playerY = MAPHEIGHT * Math.random() //MAPHEIGHT/2 // const playerColor = `hsl(${Math.random()*360},100%,70%)` const myUserName = document.querySelector('#usernameInput').value diff --git a/src/backend.js b/src/backend.js index 885ac72..cb8777d 100644 --- a/src/backend.js +++ b/src/backend.js @@ -412,11 +412,11 @@ if (GROUNDITEMFLAG){ makeNdropItem('placeable', 'mine' ,getCoordTilesCenter({row:1,col:46}),onground=true,variantNameGiven='') } - for (let i=0;i<4;i++){ + for (let i=0;i<1;i++){ makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:24,col:3}),onground=true,variantNameGiven='green')// variant should be red,green etc. - makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:25,col:3}),onground=true,variantNameGiven='red')// variant should be red,green etc. - makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:26,col:3}),onground=true,variantNameGiven='yellow')// variant should be red,green etc. - makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:27,col:3}),onground=true,variantNameGiven='white')// variant should be red,green etc. + makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:14,col:5}),onground=true,variantNameGiven='red')// variant should be red,green etc. + makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:27,col:3}),onground=true,variantNameGiven='yellow')// variant should be red,green etc. + makeNdropItem('gun', 'flareGun', getCoordTilesCenter({row:37,col:5}),onground=true,variantNameGiven='white')// variant should be red,green etc. } // MAKE HOUSES @@ -694,27 +694,33 @@ async function main(){ // aux function for shoot function shootProjectile(angle,currentGun,startDistance){ - if (!backEndPlayers[socket.id]) return // player not defined const gunName = currentGun for (let i=0;i< gunInfo[currentGun].num;i++){ addProjectile(angle,currentGun,socket.id, backEndPlayers[socket.id],startDistance) } } - socket.on('shoot', ({angle,currentGun,startDistance=0,currentHoldingItemId=0})=>{ + socket.on('shoot', ({angle,currentGun,startDistance=0,currentHoldingItemId=0})=>{ // NOTE: reload does not use socket!!! + if (!backEndPlayers[socket.id]) return // player not defined + if (backEndPlayers[socket.id].onBoard){return} // cannot shoot if on board + if (currentHoldingItemId>0){ // decrease ammo let thisGun = backEndItems[currentHoldingItemId] - if (thisGun.iteminfo.ammo>0){ - if (thisGun.name==='flareGun'){ + if (thisGun.name==='flareGun'){ + if (thisGun.iteminfo.ammo>0){ thisGun.iteminfo.ammo = 0 } + shootProjectile(angle,currentGun,startDistance) + }else{ // not a flare gun, then ammo is not important shootProjectile(angle,currentGun,startDistance) } }else{ // on vehicle turret etc. shootProjectile(angle,currentGun,startDistance) } - + // shootProjectile(angle,currentGun,startDistance) + + } ) @@ -908,6 +914,7 @@ function onBoardCheck(player){ return player.onBoard } +let ServerTime = 0 let GLOBALCLOCK = 0 // backend ticker - update periodically server info to clients setInterval(() => { @@ -918,6 +925,19 @@ setInterval(() => { spawnEnemies() } GLOBALCLOCK = 0 // init + + // print entity object's lengths + console.log(`[ Entity amount check ${ServerTime} ]`) + console.log( + "Players ",Object.keys(backEndPlayers).length, + "\nEnemies ",Object.keys(backEndEnemies).length, + "\nProjectiles ",Object.keys(backEndProjectiles).length, + "\nItems ",Object.keys(backEndItems).length, + "\nVehicles ",Object.keys(backEndVehicles).length, + "\nObjects ",Object.keys(backEndObjects).length, + "\nAirstrikes ",Object.keys(backEndAirstrikes).length, + "\nSoundRequests ",Object.keys(backEndSoundRequest).length ) + ServerTime += 1 } // red zone? @@ -1903,14 +1923,14 @@ function explosion(location,BLASTNUM,playerID=0,shockWave=false){ // const AIRSTRIKE_TYPE_DICT = {'red':'bomb','green':'supply','white':'transport', 'yellow':'vehicle request'} -const STRIKE_INTERVAL_COEF = 15 +const STRIKE_INTERVAL_COEF = 10 const PLANE_PICKUP_RADIUS = 256 // plane rad is 384 function spawnAirstrike(location, callerID, signalColor='green'){ // currently only makes cars airstrikeId++ const x = location.x - let speed = Math.min( ((MAPHEIGHT - location.y)/MAPHEIGHT)*6+2 , 5) // 1~4 + let speed = Math.min( ((MAPHEIGHT - location.y)/MAPHEIGHT)*6+2 , 5) // 2~5 const y = MAPHEIGHT-1 // goes up const signal = AIRSTRIKE_TYPE_DICT[signalColor] @@ -1919,7 +1939,7 @@ function spawnAirstrike(location, callerID, signalColor='green'){ // currently o let strikeNumber = 1 if (signal==='bomb'){ - speed = 8 // fly fast and bomber (same speed as B2) + speed = 12 // fly fast and bomber (same speed as B2) strikeNumber = 16 strike_Y_level = Math.round(location.y + (strikeNumber/2)*speed*STRIKE_INTERVAL_COEF) } else if(signal==='transport'){ @@ -2009,8 +2029,8 @@ function safeTakeOff(airstrikeID){ passenger.strikeID = -1 airstrike.onBoard = false NONitemBorderUpdate(passenger) + pushSoundRequest({x:airstrike.x,y:airstrike.y},'takeoff',TILE_SIZE*3, duration=1) } - pushSoundRequest({x:airstrike.x,y:airstrike.y},'takeoff',TILE_SIZE*3, duration=1) }