Skip to content

Instantly share code, notes, and snippets.

@LemoNode
Created February 4, 2020 15:37
Show Gist options
  • Save LemoNode/1bfba6772b89db2ca4265248e680b43e to your computer and use it in GitHub Desktop.
Save LemoNode/1bfba6772b89db2ca4265248e680b43e to your computer and use it in GitHub Desktop.
2d game platformer
<head>
<meta charset="utf-8">
<title>Hello</title>
<style>
canvas {
background: #ddd;
outline: none;
}
</style>
</head>
<body onload="main()">
<canvas tabindex="1" width="640" height="480"></canvas>
<script>
// canvas
const canvas = {
dom: document.querySelector("canvas"),
ctx: document.querySelector("canvas").getContext("2d"),
width: 640,
height: 480,
};
// keyboard
const button = {
flags: {},
pressed: {},
released: {},
down: {},
pull: () => {},
};
button.pull = () => {
for (var i = 0; i < Object.keys(button.pressed).length; i++) {
if (button.pressed[Object.keys(button.pressed)[i]]) {
button.pressed[Object.keys(button.pressed)[i]] = false;
}
}
for (var i = 0; i < Object.keys(button.released).length; i++) {
if (button.released[Object.keys(button.released)[i]]) {
button.released[Object.keys(button.released)[i]] = false;
}
}
}
canvas.dom.onkeydown = e => {
button.down[e.key] = true;
button.pressed[e.key] = true;
if (button.pressed[e.key] && button.flags[e.key]) {
button.pressed[e.key] = false;
}
if (!button.flags[e.key]) {
button.flags[e.key] = true;
}
}
canvas.dom.onkeyup = e => {
button.down[e.key] = false;
button.released[e.key] = true;
button.flags[e.key] = false;
}
// init
const world = {
pos: {x: 0, y: 0},
lerp: {x: 0, y: 0},
gravity: .9,
friction: .9,
};
const hero = {
pos: {x: 0, y: 0},
lerp: {x: 0, y: 0},
size: {x: 20, y: 20},
color: "steelblue",
speed: 6,
velocity: 0,
jump: 125,
on: {
ground: false, ceiling: false,
wall_right: false, wall_left: false
},
};
const blocks = [
{pos: {x: -100, y: 460}, size: {x: 600, y: 20}},
{pos: {x: -50, y: 0}, size: {x: 20, y: 460}},
{pos: {x: 620, y: 0}, size: {x: 20, y: 460}},
{pos: {x: 250, y: 390}, size: {x: 100, y: 20}},
{pos: {x: 250, y: 290}, size: {x: 100, y: 20}},
{pos: {x: 450, y: 350}, size: {x: 100, y: 20}},
{pos: {x: 350, y: 150}, size: {x: 100, y: 100}},
];
var scale = 0.001;
var scale_mod = 0.001;
// aabb
aabb_detect = (a, b) => {
var right = (a.lerp.x + a.size.x) - b.pos.x;
var left = a.lerp.x - (b.pos.x + b.size.x);
var top = a.lerp.y - (b.pos.y + b.size.y);
var bottom = (a.lerp.y + a.size.y) - b.pos.y;
if (right >= 0 && top <= 0 && left <= 0 && bottom >= 0) {
var abs_r = Math.abs(right);
var abs_l = Math.abs(left);
var abs_t = Math.abs(top);
var abs_b = Math.abs(bottom);
if (abs_r < abs_l && abs_r < abs_t && abs_r < abs_b) {
a.pos.x -= right;
a.lerp.x -= right;
world.pos.x += right;
a.on.right_wall = true;
} else if (abs_t < abs_l && abs_t < abs_r && abs_t < abs_b) {
a.pos.y -= top;
a.lerp.y -= top;
world.pos.y += top;
a.on.ceiling = true;
} else if (abs_l < abs_t && abs_l < abs_r && abs_l < abs_b) {
a.pos.x -= left;
a.lerp.x -= left;
world.pos.x += left;
a.on.left_wall = true;
} else if (abs_b < abs_t && abs_b < abs_r && abs_b < abs_l) {
a.pos.y -= bottom;
a.lerp.y -= bottom;
world.pos.y += bottom;
a.on.ground = true;
}
}
}
// input
input = () => {
if (button.down["ArrowLeft"]) {
hero.pos.x -= hero.speed;
world.pos.x += hero.speed;
}
if (button.down["ArrowRight"]) {
hero.pos.x += hero.speed;
world.pos.x -= hero.speed;
}
if (button.pressed[" "] && hero.on.ground) {
hero.pos.y -= hero.jump;
world.pos.y += hero.jump;
}
if (button.pressed["w"]) {
scale_mod = 0.0015;
}
if (button.released["w"]) {
scale_mod = 0.001;
}
button.pull();
}
// update
update = () => {
hero.on.ground = false;
hero.on.right_wall = false;
hero.on.left_wall = false;
hero.on.ceiling_wall = false;
hero.lerp.x += (hero.pos.x - hero.lerp.x) * .5;
hero.lerp.y += (hero.pos.y - hero.lerp.y) * .1;
world.lerp.x += (world.pos.x - world.lerp.x) * .05;
world.lerp.y += (world.pos.y - world.lerp.y) * .05;
for (var i = 0; i < blocks.length; i++) {
aabb_detect(hero, blocks[i]);
}
if (hero.on.ground || hero.on.celing) {
hero.velocity = 0;
}
if (!hero.on.ground) {
hero.velocity += world.gravity;
hero.velocity *= world.friction;
hero.pos.y += hero.velocity;
world.pos.y -= hero.velocity;
}
scale += (scale_mod - scale) * .1;
}
// draw
draw = () => {
canvas.ctx.clearRect(0, 0, canvas.width, canvas.height);
draw.hero();
draw.blocks();
}
draw.hero = () => {
canvas.ctx.fillStyle = hero.color;
let x_pos = hero.lerp.x + world.lerp.x;
let y_pos = hero.lerp.y + world.lerp.y;
let x_size = hero.size.x;
let y_size = hero.size.y;
draw.render(x_pos, y_pos, x_size, y_size);
}
draw.blocks = () => {
canvas.ctx.fillStyle = "#333";
for (let i = 0; i < blocks.length; i++) {
let x_pos = blocks[i].pos.x + world.lerp.x;
let y_pos = blocks[i].pos.y + world.lerp.y;
let x_size = blocks[i].size.x;
let y_size = blocks[i].size.y;
draw.render(x_pos, y_pos, x_size, y_size);
}
}
draw.render = (x_pos, y_pos, x_size, y_size) => {
x_pos *= canvas.width * scale;
x_pos += canvas.width * .5;
y_pos *= canvas.width * scale;
y_pos += canvas.height * .5;
x_size *= canvas.width * scale;
y_size *= canvas.width * scale;
canvas.ctx.fillRect(x_pos, y_pos, x_size, y_size);
}
// start of program
main = () => {
canvas.dom.focus();
loop = (t) => {
input();
update();
draw();
requestAnimationFrame(loop);
}
return requestAnimationFrame(t => loop(t))
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment