// https://stackoverflow.com/questions/25612452/html5-canvas-game-loop-delta-time-calculations // TODO: Need to fully figure out a 60FPS and also display FPS on top right let game = { fps : 60 // ?? ,time : 0.0 ,start : Date.now() ,frameDuration : 1000 / 60 // Target FPS 60? ,lagOffset : 0 ,player : false } startGame(); function startGame(){ // Create player createPlayerEntity(canvas.width/2, canvas.height/2); // Start game loop gameLoop(); } function gameLoop(){ // Check player exists (not dead/undefined by OOB) if(entities[game.player] === undefined || game.player === false){ console.log('gome'); return false; } setTimeout(() => { requestAnimationFrame(gameLoop, canvas); }, game.frameDuration); // Calcuate the time that has elapsed since the last frame let current = Date.now(); let elapsed = current - game.start; game.start = current; game.lagOffset += elapsed; // Update the frame if the lag counter is greater than or // equal to the frame duration while (game.lagOffset >= game.frameDuration){ gameUpdate(); game.lagOffset -= game.frameDuration; } // Calculate the lag offset and use it to render the sprites // var lagOffset = Math.round(game.lagOffset / game.frameDuration); // drawEntities(); // May need to pass lagOffset here to attempt to correct positions, etc. drawGame(); // Print the game version above everything printText(GAME_VERSION, 20, canvas.height - 20, 'left', 'alphabetic', 'normal', 'bold', '10', 'Arial', '#00000050' ); printText(elapsed, canvas.width - 20 - (ctx.measureText(elapsed).width), 20 + 10, // + 10 is pt font-size to get in right pos 'left', 'alphabetic', 'normal', 'bold', '10', 'Arial', '#00000090' ); } // All the game update logic function gameUpdate(){ calculatePlayerMovement(); calculateDirectionToPlayer(); updateMovement(); updateOOB(); if(MOUSE.down){ createBulkEntities(MOUSE.x, MOUSE.y); } } function calculatePlayerMovement(){ let speedNow = speed[game.player]; if(KEYPRESS.shift){ speedNow = speedNow * 5; } if(KEYPRESS.w){ position[game.player].y -= (1*speedNow); } if(KEYPRESS.s){ position[game.player].y += (1*speedNow); } if(KEYPRESS.a){ position[game.player].x -= (1*speedNow); } if(KEYPRESS.d){ position[game.player].x += (1*speedNow); } } function updateMovement(){ // Use the direction currently, but likely 'velocity' in the future for (const [entity] of Object.entries(direction)) { if(position[entity] === undefined){ continue; } if(direction[entity].x !== undefined){ if(direction[entity].x == 1){ position[entity].x += (1 * speed[entity]); } else if(direction[entity].x == -1){ position[entity].x -= (1 * speed[entity]); } } if(direction[entity].y !== undefined){ if(direction[entity].y == 1){ position[entity].y += (1 * speed[entity]); } else if(direction[entity].y == -1){ position[entity].y -= (1 * speed[entity]); } } } } function calculateDirectionToPlayer(){ // Enemies will W key towards the player as a hoard for (const [entity] of Object.entries(position)) { if(entity == game.player){ continue; } if(position[game.player].x > position[entity].x){ direction[entity].x = 1; } else{ direction[entity].x = -1; } if(position[game.player].y > position[entity].y){ direction[entity].y = 1; } else{ direction[entity].y = -1; } } } function updateOOB(){ for (const [entity] of Object.entries(position)) { // Remove the entity if it goes out of bounds if( position[entity].y >= canvas.height-50 || position[entity].y <= 50 || position[entity].x >= canvas.width-50 || position[entity].x <= 50 ){ deleteEntity(entity); } } } function deleteEntity(entity){ // Remove from each component // Definitely the most inefficient and janky way, but it does it if(position[entity] !== null){ delete position[entity]; } if(size[entity] !== null){ delete size[entity]; } if(team.good[entity] !== null){ delete team.good[entity]; } if(team.bad[entity] !== null){ delete team.bad[entity]; } if(team.allied[entity] !== null){ delete team.allied[entity]; } if(direction[entity] !== null){ delete direction[entity]; } // Finally remove the entity itself delete entities[entity]; entityLive--; // To keep track of how many active entities there are (just a count) } function drawGame(){ // Reset/clear all prior draws ctx.clearRect(0, 0, canvas.width, canvas.height); drawEntities(); // Draw 'temp' hitbox area (to visualise entity removal) drawRectangle(50,50,canvas.width-100,canvas.height-100,null,'#FFF'); } // Draw the game's entities function drawEntities(){ // Draw all entities (with size/position) for (const entity in size) { // If there's no position (or size), skip if(position[entity] === undefined){ continue; } // TEMP z-index draw to ensure player, etc. are drawn atop enemies (for now) // 0,1,2 TODO: WHY ISN'T IT WOKRIINNNGG for(let i = 0; i < 2; i++){ // JANK IF. Change to defensive when I can be bothered if((zindex[entity] === undefined && i === 0) || zindex[entity] === i){ // console.log(zindex[entity]); if(team.bad[entity] !== undefined){ // Draw pixels from imageCanvas drawEnemy(entity); } if(team.allied[entity] !== undefined){ // Draw pixels from imageCanvas drawAlly(entity); } // Player, temp if(team.good[entity] !== undefined){ // Draw pixels from imageCanvas drawPlayer(entity); } } } } } function createTestEntity(x,y){ entityCount++; entityLive++; // To keep track of how many active entities there are (just a count) entities[entityCount] = entityCount; position[entityCount] = {x: x, y: y}; size[entityCount] = {width: 16, height: 16}; if(MOUSE.button[0]){ team.bad[entityCount] = true; } else if(MOUSE.button[1]){ team.allied[entityCount] = true; } else if(MOUSE.button[2]){ // } direction[entityCount] = {x: 0, y: 0}; // 0,1 left,right/up,down zindex[entityCount] = 0; speed[entityCount] = .75; } function createBulkEntities(x,y){ let amount = 90; for(let i = 0; i < amount; i++){ createTestEntity( x+(Math.floor(Math.random() * 45)+1) ,y+Math.floor(Math.random() * 35)+1 ); } } function createPlayerEntity(x,y){ entityCount++; game.player = entityCount; // Set game.player to the player entity. TEMP entityLive++; // To keep track of how many active entities there are (just a count) entities[entityCount] = entityCount; position[entityCount] = {x: x, y: y}; size[entityCount] = {width: 16, height: 16}; team.good[entityCount] = true; direction[entityCount] = {x: 0, y: 0}; // 0,1 left,right/up,down zindex[entityCount] = 1; speed[entityCount] = 1.6; }