Created
February 4, 2020 15:37
-
-
Save LemoNode/1bfba6772b89db2ca4265248e680b43e to your computer and use it in GitHub Desktop.
2d game platformer
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
<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