// Character Controls "clean version" with Trails...
// dynamically handle keys instead of explicitly
// checking each one
const keys = {}
document.addEventListener('keydown', e => {
e.preventDefault();
// store a boolean on the `keys` object
// to keep track of whick keys are down
keys[e.key] = true;
});
document.addEventListener('keyup', e => {
e.preventDefault();
keys[e.key] = false;
});
// setup motion
let x = 100;
let y = 300;
let vx = 4;
let vy = -10;
// put gravity in a variable
const GRAVITY = 1;
// replace "magic numbers" with constants
const FLOOR_BOUNCE = -.33;
const JUMP_POWER = 15;
const ARROW_VEL = 3;
const VX_DECAY = .8;
const TRAIL_NUM = 10;
const chars = [];
// store the size of the character
const charWidth = 50;
const charHeight = 80;
for (let i = 0; i < TRAIL_NUM; i++) {
// create the character
const char = document.createElement('div');
chars.push({ char, x, y });
Object.assign(char.style, {
position: 'absolute',
width: `${charWidth}px`,
height: `${charHeight}px`,
background: 'black',
// add border radius for no reason
borderTopLeftRadius: '20px',
borderTopRightRadius: '20px',
opacity: i === 0 ? 1 : .25 - (.25 / TRAIL_NUM) * i
});
document.body.appendChild(char);
}
const char = chars[0].char
function setLocs({ x, y }) {
for (let i = 0; i < TRAIL_NUM; i++) {
const char = chars[i];
if (x != null) char.x = x;
if (y != null) char.y = y;
}
}
// some bounds variables for the screen
let floor;
let screenRight;
let screenLeft;
// main loop
function loop() {
// we want to recalculate these
// so things work when the screen resizes
floor = innerHeight - 80;
screenRight = innerWidth + 50;
screenLeft = -charWidth;
// update the characters velocity
x += vx;
y += vy;
// handle floor and screen sides
if (y > floor) {
vy *= FLOOR_BOUNCE;
y = floor;
// @TODO set char xs
}
if (x > screenRight) {
x = screenLeft
setLocs({ x })
}
if (x < screenLeft) {
x = screenRight;
setLocs({ x })
}
// update the characters velocity with arrow keys
if (keys['ArrowRight']) {
vx += ARROW_VEL;
}
if (keys['ArrowLeft']) {
vx -= ARROW_VEL;
}
// character can only jump up when it is on the floor
if (keys['ArrowUp'] && y >= floor) {
vy -= JUMP_POWER;
}
if (keys['ArrowDown']) {
vy += ARROW_VEL;
}
vy += GRAVITY;
vx *= VX_DECAY
// update the characters styles
Object.assign(
char.style, {
// use template string instead of x + 'px'
left: `${x}px`,
top: `${y}px`
}
);
// update trails stuff
chars[0].x = x;
chars[0].y = y;
for (let i = 1; i < TRAIL_NUM; i++) {
const char = chars[i]
char.x += (chars[i - 1].x - char.x) / 4;
char.y += (chars[i - 1].y - char.y) / 4;
Object.assign(
chars[i].char.style, {
// use template string instead of x + 'px'
left: `${char.x}px`,
top: `${char.y}px`
}
);
}
requestAnimationFrame(loop);
}
loop();