Created
January 3, 2023 06:09
-
-
Save H4ppy-04/92a37a6a890f883c935beb43c490200a to your computer and use it in GitHub Desktop.
Javascript canvas template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function randint(a=0, b) { | |
/* Return random whole number between a and b */ | |
return Math.floor(Math.random() * (b - a + 1)) + a; | |
} | |
function choice(list) { | |
/* Return positive integer to index list */ | |
index = Math.abs(Math.floor(Math.random() * (list.length - 0 + 1)) - 1); | |
return list[index]; | |
} | |
class Player { | |
/* Moveable entity with physics properties */ | |
constructor(canvas, ctx, px, py) { | |
/* px: position x | |
* py: position y | |
*/ | |
if (px === undefined) { | |
this.x = 0; | |
} if (px === undefined) { | |
this.y = 0; | |
} else { | |
this.x = px; | |
this.y = py; | |
} | |
// Define size of player | |
this.width = 10; | |
this.height = 10; | |
// gravity contant TODO seperate non-player consts | |
this.gravity = 2; // pixels / second^2 | |
// player velocity (relative to bidimensional axis) | |
this.vx = 0; | |
this.vy = 0; | |
// define constructor args | |
this.canvas = canvas; | |
this.ctx = ctx; | |
// define player color | |
this.color = "blue"; | |
} | |
update() { | |
// Push current ctx state to stack | |
// ctx.save(); | |
if (this.ctx.getTime() > 1000) { | |
// NOTE si = speed increment | |
let si = this.gravity * this.ctx.frame.timeInterval / 1000; | |
// increment velocity regulated by frametime | |
this.vy += si; | |
// set y position of player | |
this.y += this.vy * this.ctx.frame.timeInterval; | |
// Collission / border detection | |
if (this.y > this.canvas.height - this.height) { | |
this.y = this.canvas.height - this.height; | |
ctx.stop(); | |
} | |
} | |
// Refresh display | |
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); | |
} | |
draw() { | |
/* draw playre to canvas */ | |
this.ctx.beginPath(); | |
this.ctx.fillStyle = this.color; | |
// blit rect to this.canvas | |
this.ctx.fillRect(this.x, this.y, this.width, this.height); | |
} | |
} | |
class Cursor { | |
/* Mouse cursor position */ | |
constructor(canvas) { | |
// Cursor x and y position | |
this.x = 0; | |
this.y = 0; | |
// Primary display surface | |
this.canvas = canvas; | |
// Collision and rounding rect | |
this.rect = canvas.getBoundingClientRect(); | |
} | |
get mousePosition() { | |
// Returns rounded mouse pos (over rect) | |
return (this.x, this.y); | |
} | |
} | |
class Grid { | |
/* Grid manages object position definitions */ | |
constructor(canvas, ctx) { | |
this.canvas = canvas; | |
this.ctx = ctx; | |
this.width = this.canvas.width; | |
this.height = this.canvas.height; | |
} | |
draw() { | |
/* Draws black square grid onto this.canvas */ | |
for (let w=0; w<=this.width; w+=50) { | |
for (let h=0; h<=this.height; h+=50) { | |
this.drawLine(w-50, h-50, w, h); | |
} | |
} | |
} | |
drawLine(sx, sy, ex, ey) { | |
/* Makes drawing lines more comprehensible (for me) | |
* sx: starting x position | |
* sy: starting y position | |
* ex: ending x position | |
* ey: ending y position | |
*/ | |
this.ctx.moveTo(sx, sy); | |
this.ctx.lineTo(ex, ey); | |
// Fill line with ctx.fillStyle (default=black) | |
this.ctx.stroke(); | |
} | |
} | |
class Window { | |
/* Event and display manager class */ | |
constructor(canvasId) { | |
// entry & exit flag | |
this.active = true; | |
this.canvas = document.getElementById(canvasId); | |
this.ctx = this.canvas.getContext("2d"); | |
// Storing width and height prevents having to query | |
// canvas size every time it's requested as it's constant. | |
this.width = this.canvas.width; | |
this.height = this.canvas.height; | |
// Font is changeable and inits here. | |
this.font = "30px Arial"; | |
this.ctx.font = this.font; | |
// Instantiate cursor | |
this.cursor = new Cursor(this.canvas); | |
this.grid = new Grid(this.canvas, this.ctx); | |
// define fps and frame properties | |
this.frame = { | |
t: 0, // time | |
timeInterval: 0, // Interval between frames | |
st: 0, // start time | |
lt: 0, // last time | |
Frame: 0, // current frame | |
animating: false, // entry / exit flag | |
fps: 60 // frame allowance per 1000 ms | |
}; | |
// create player object at 250x250 (x,y) | |
this.player = new Player(this.canvas, this.ctx, 250, 250); | |
// request animation frame | |
window.requestAnimFrame = (function(callback) { | |
return window.requestAnimationFrame || function(callback) { | |
window.setTimeout(callback, 1000 / this.frame.fps); | |
}; | |
})(); | |
// Send any mouse movement to cursor as x & y. | |
// this.canvas.addEventListener( | |
// "mousemove", | |
// event => { | |
// this.cursor.x = Math.round(event.clientX - this.cursor.rect.left); | |
// this.cursor.y = Math.round(event.clientY - this.cursor.rect.top); | |
// }); | |
} | |
onLoad() { | |
// Toggle entry and exit flag | |
this.frame.animating = true; | |
// Create date for delatime | |
let date = new Date(); | |
// Get date (time specific) | |
let thisTime = date.getTime(); | |
// toggle entry flag | |
this.tick(); | |
} | |
tick() { | |
// Animate frames | |
if (this.frame.animating) { | |
// call update function | |
requestAnimationFrame(this.update); | |
}; | |
}; | |
update() { | |
console.debug(this.frame.Frame); | |
// Increment frame by 1 value | |
this.frame.Frame++; | |
// Create date for delatime | |
let date = new Date(); | |
// Get date (time specific) | |
let thisTime = date.getTime(); | |
// increment t with timeinterval | |
this.frame.t += this.frame.timeInterval; | |
// append deltatime | |
this.frame.lt = thisTime; | |
}; | |
}; | |
// on window load instantiate Window class | |
window.onload = function() { | |
const display = new Window("this_canvas"); // NOTE *args are relative to the canvas id. | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment