import { WORLD } from "./config.js"; const GRAVITY = 0.32; const JUMP_VELOCITY = -10.5; const HORIZONTAL_ACCELERATION = 0.65; const HORIZONTAL_FRICTION = 0.86; const MAX_HORIZONTAL_SPEED = 7; export function createPlayer({ x = 0, y = 0, radius = 18 } = {}) { return { position: { x, y }, previousPosition: { x, y }, velocity: { x: 0, y: 0 }, radius, wasReset: false, }; } export function updatePlayer(player, keys, platforms) { player.wasReset = false; player.previousPosition.x = player.position.x; player.previousPosition.y = player.position.y; const xDirection = Number(keys.has("arrowright") || keys.has("d")) - Number(keys.has("arrowleft") || keys.has("a")); player.velocity.x += xDirection * HORIZONTAL_ACCELERATION; player.velocity.x *= HORIZONTAL_FRICTION; player.velocity.x = Math.max(-MAX_HORIZONTAL_SPEED, Math.min(MAX_HORIZONTAL_SPEED, player.velocity.x)); player.velocity.y += GRAVITY; player.position.x += player.velocity.x; player.position.y += player.velocity.y; wrapPlayerHorizontally(player); bounceOnPlatforms(player, platforms); resetIfPlayerFalls(player, platforms); } export function placePlayerOnPlatform(player, platform) { player.position.x = platform.x + platform.width / 2; player.position.y = platform.y - player.radius; player.previousPosition.x = player.position.x; player.previousPosition.y = player.position.y; player.velocity.x = 0; player.velocity.y = JUMP_VELOCITY; } function wrapPlayerHorizontally(player) { if (player.position.x < -player.radius) { player.position.x = WORLD.width + player.radius; } if (player.position.x > WORLD.width + player.radius) { player.position.x = -player.radius; } } function bounceOnPlatforms(player, platforms) { if (player.velocity.y <= 0) { return; } const previousBottom = player.previousPosition.y + player.radius; const currentBottom = player.position.y + player.radius; for (const platform of platforms) { const isCrossingTop = previousBottom <= platform.y && currentBottom >= platform.y; const isOverPlatform = player.position.x + player.radius >= platform.x && player.position.x - player.radius <= platform.x + platform.width; if (isCrossingTop && isOverPlatform) { player.position.y = platform.y - player.radius; player.velocity.y = JUMP_VELOCITY; return; } } } function resetIfPlayerFalls(player, platforms) { if (player.position.y - player.radius <= WORLD.height) { return; } placePlayerOnPlatform(player, platforms[0]); player.wasReset = true; } export function drawPlayer(p, player, camera) { const localX = player.position.x - camera.x; const localY = player.position.y - camera.y; p.push(); p.noStroke(); p.fill(52, 152, 219); p.circle(localX, localY, player.radius * 2); p.fill(255); p.circle(localX + player.radius * 0.35, localY - player.radius * 0.25, player.radius * 0.35); p.pop(); } export function drawWorldPlayer(p, player, area) { p.push(); p.noStroke(); p.fill(96, 165, 250); p.circle( area.x + player.position.x * area.scale, area.y + player.position.y * area.scale, Math.max(5, player.radius * 2 * area.scale), ); p.pop(); }