Skip to content

Instantly share code, notes, and snippets.

@LemoNode
Last active June 11, 2020 12:21
Show Gist options
  • Save LemoNode/4228ae3de3398c8cb39a2ae8cb7f6a9f to your computer and use it in GitHub Desktop.
Save LemoNode/4228ae3de3398c8cb39a2ae8cb7f6a9f to your computer and use it in GitHub Desktop.
Simple collision detection / reaction for intersecting rectangles
<head>
<title>Collision</title>
<style>
canvas {
border: 1px solid #333;
}
</style>
</head>
<body onload="main();">
<canvas tabindex="1" width="640" height="480"></canvas>
<script>
const dom = document.querySelector("canvas");
const ctx = dom.getContext("2d");
const hero = {
x: 206,
y: 200-26,
x_lerp: 206,
y_lerp: 200-26,
w: 25,
h: 25,
speed: 5,
color: "steelblue",
vel_x: null,
vel_y: null,
};
const blocks = [
{x: 100, y: 150, w: 50, h: 50, n: {t: true, b: true, l: true, r: false}},
{x: 155, y: 150, w: 50, h: 50, n: {t: false, b: true, l: false, r: true}},
{x: 205, y: 200, w: 50, h: 50, n: {t: true, b: false, l: true, r: true}},
{x: 205, y: 255, w: 50, h: 50, n: {t: false, b: true, l: true, r: true}},
];
const keys = {
curr: null,
all: [],
down: {},
pressed: {},
released: {},
init: () => {
dom.onkeydown = e => {
keys.curr = e.key;
if (!keys.pressed[e.key] && !keys.down[e.key]) {
keys.pressed[e.key] = true;
}
keys.all.push(e.key);
keys.down[e.key] = true;
}
dom.onkeyup = e => {
keys.down[e.key] = false;
keys.released[e.key] = true;
}
},
scan: key => {
let arr = keys.all;
for (let i = 0; i < arr.length; i++) {
keys.pressed[arr[i]] ? keys.pressed[arr[i]] = false : 0;
keys.released[arr[i]] ? keys.released[arr[i]] = false : 0;
}
},
};
lerp = (obj, speed) => {
obj.x_lerp += (obj.x - obj.x_lerp) * speed;
obj.y_lerp += (obj.y - obj.y_lerp) * speed;
}
collision = (a, b) => {
let d1x = a.x_lerp - (b.x + b.w);
let d2x = b.x - (a.x_lerp + a.w);
let d1y = a.y_lerp - (b.y + b.h);
let d2y = b.y - (a.y_lerp + a.h);
if (d1x >= 0 || d2x >= 0)
return false;
if (d1y >= 0 || d2y >= 0)
return false;
let i = Math.min(Math.abs(d1x),Math.abs(d1y),Math.abs(d2x),Math.abs(d2y));
if (i == Math.abs(d1y) && a.vel_y != 0 && b.n.b) {
a.y = b.y + b.h;
a.y_lerp = a.y;
} else if (i == Math.abs(d2y) && a.vel_y != 0) {
a.y = b.y - a.h;
a.y_lerp = a.y;
} else if (i == Math.abs(d1x) && a.vel_x != 0 && b.n.r) {
a.x = b.x + b.w;
a.x_lerp = a.x;
} else if (i == Math.abs(d2x) && a.vel_x != 0) {
a.x = b.x - a.w;
a.x_lerp = a.x;
}
return true;
}
init = () => {
keys.init();
dom.focus();
}
input = () => {
if (keys.down["ArrowUp"]) {
hero.y -= hero.speed;
}
if (keys.down["ArrowDown"]) {
hero.y += hero.speed;
}
if (keys.down["ArrowLeft"]) {
hero.x -= hero.speed;
}
if (keys.down["ArrowRight"]) {
hero.x += hero.speed;
}
keys.scan(keys.curr);
}
update = () => {
lerp(hero, .15);
hero.vel_x = Math.floor(Math.abs(hero.x - hero.x_lerp));
hero.vel_y = Math.floor(Math.abs(hero.y - hero.y_lerp));
let react = false;
for (block of blocks) {
if (collision(hero, block)) {
react = true;
}
}
}
draw = () => {
ctx.clearRect(0, 0, dom.width, dom.height);
ctx.fillStyle = "#999";
for (block of blocks) {
ctx.fillRect(block.x, block.y, block.w, block.h);
}
ctx.fillStyle = hero.color;
ctx.fillRect(hero.x_lerp, hero.y_lerp, hero.w, hero.h);
}
main = () => {
init();
let loop = dt => {
input();
update();
draw();
requestAnimationFrame(loop);
}
return requestAnimationFrame(dt => loop(dt))
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment