You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
6.6 KiB
JavaScript

// 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;
}