super-mario / lib /engine /Physics.ts
asemxin
feat: reduce mobile control sensitivity for better touch experience
0c4f8d5
// Physics engine - handles movement, gravity, and forces
import { PlayerState, Enemy, KeyState } from './types';
import { GAME_CONFIG } from '../constants';
const { GRAVITY, FRICTION, MAX_FALL_SPEED, PLAYER_SPEED, PLAYER_JUMP_FORCE, MOBILE_PLAYER_SPEED, MOBILE_JUMP_FORCE } = GAME_CONFIG;
export class Physics {
private isMobile: boolean = false;
setMobileMode(isMobile: boolean): void {
this.isMobile = isMobile;
}
private getPlayerSpeed(): number {
return this.isMobile ? MOBILE_PLAYER_SPEED : PLAYER_SPEED;
}
private getJumpForce(): number {
return this.isMobile ? MOBILE_JUMP_FORCE : PLAYER_JUMP_FORCE;
}
applyGravity(entity: { vy: number; isFalling?: boolean }): void {
entity.vy += GRAVITY;
if (entity.vy > MAX_FALL_SPEED) {
entity.vy = MAX_FALL_SPEED;
}
}
applyFriction(entity: { vx: number }): void {
entity.vx *= FRICTION;
if (Math.abs(entity.vx) < 0.1) {
entity.vx = 0;
}
}
updatePlayerMovement(player: PlayerState, keys: KeyState): void {
const speed = this.getPlayerSpeed();
const jumpForce = this.getJumpForce();
// Horizontal movement
if (keys.left) {
player.vx = -speed;
player.facingRight = false;
} else if (keys.right) {
player.vx = speed;
player.facingRight = true;
} else {
this.applyFriction(player);
}
// Jump
if (keys.jump && !player.isJumping && !player.isFalling) {
player.vy = jumpForce;
player.isJumping = true;
}
// Apply gravity
this.applyGravity(player);
// Update position
player.x += player.vx;
player.y += player.vy;
// Check if falling
if (player.vy > 0) {
player.isFalling = true;
player.isJumping = false;
}
}
updateEnemyMovement(enemy: Enemy, levelWidth: number): void {
if (!enemy.isAlive) return;
// Apply gravity
this.applyGravity(enemy);
// Move in current direction
enemy.vx = enemy.direction * 1.5;
enemy.x += enemy.vx;
enemy.y += enemy.vy;
// Reverse direction at level boundaries
if (enemy.x <= 0 || enemy.x >= levelWidth - enemy.width) {
enemy.direction *= -1;
}
}
}