/** * CharacterController2D - Kinematic character with tight controls * * Why kinematic not dynamic: * - Physics forces feel floaty (acceleration, momentum) * - We want instant response (press right → move right) * - Still get collision detection from physics * * Game feel features: * - Coyote time (jump grace period) * - Jump buffering (early jump input) * - Variable jump height * - Acceleration curves * - Air control * * Common use case: 2D platformer character */ export class CharacterController2D extends RigidBody2D { constructor(name: any, options?: {}); activeCollisions: Set; collisionData: Map; onCollisionEnter: (other: any, pair: any) => void; onCollisionStay: (other: any, pair: any) => void; onCollisionExit: (other: any, pair: any) => void; speed: any; acceleration: any; friction: any; airAcceleration: any; airFriction: any; jumpForce: any; gravity: any; maxFallSpeed: any; jumpCutMultiplier: any; coyoteTime: any; jumpBufferTime: any; coyoteTimer: number; jumpBufferTimer: number; velocity: { x: number; y: number; }; grounded: boolean; wasGrounded: boolean; jumping: boolean; state: string; moveInput: number; jumpPressed: boolean; jumpHeld: boolean; jumpReleased: boolean; groundCheckDistance: number; wallCheckDistance: number; onJump: any; onLand: any; onWallHit: any; spriteNode: Sprite | AnimatedSprite; animatedSprite: any; collisionWidth: any; collisionHeight: any; collisionPaddingX: any; collisionPaddingY: any; debugDraw: any; debugColor: { r: number; g: number; b: number; }; /** * Setup sprite and auto-configure collision from sprite dimensions * * @param {Sprite|AnimatedSprite} sprite - Sprite to attach */ setupSprite(sprite: Sprite | AnimatedSprite): void; /** * Create collision box * * Uses collisionWidth/Height which are either: * - Auto-calculated from sprite * - Manually specified in options */ setupCollision(): void; /** * Setup animation state machine hooks * * Automatically plays animations based on controller state */ setupAnimations(animatedSprite: any): void; prevState: any; /** * Update animations based on state * * Called automatically in _process if sprite is AnimatedSprite */ updateAnimations(): void; /** * Map controller state to animation name * * Override this in subclasses for custom animation mappings */ getAnimationForState(state: any): any; /** * Manually check collisions using Matter.Query * * Since kinematic (static) bodies don't fire collision events with other static bodies, * we need to manually query the physics world */ checkCollisionsManually(): any; /** * Resolve collisions using manual query results */ resolveCollisions(): void; /** * Slide velocity along collision surface */ slideVelocity(normal: any, pushDir: any): void; /** * Check grounded using manual collision detection */ checkGrounded(): void; /** * Update game feel timers */ updateTimers(delta: any): void; handleCollisionEnter(other: any, pair: any): void; handleCollisionStay(other: any, pair: any): void; handleCollisionExit(other: any, pair: any): void; /** * Handle horizontal movement * * Features: * - Instant direction change (no momentum) * - Smooth acceleration to max speed * - Different air/ground acceleration */ handleMovement(delta: any): void; /** * Handle jump input with game feel tricks * * Coyote time: Can jump slightly after leaving platform * Jump buffer: Jump input remembered for short time * Variable height: Release jump early = shorter jump */ handleJump(delta: any): void; /** * Apply gravity */ applyGravity(delta: any): void; /** * Update state machine * * States: idle, walk, jump, fall * Used for animation selection */ updateState(): void; /** * Set move input from external system * * @param {number} direction - -1 (left), 0 (none), 1 (right) */ setMoveInput(direction: number): void; /** * Set jump input from external system * * @param {boolean} pressed - Jump pressed this frame * @param {boolean} held - Jump held * @param {boolean} released - Jump released this frame */ setJumpInput(pressed: boolean, held: boolean, released: boolean): void; } /** * InputController - bridges tessera.js InputMap to CharacterController2D * * Why separate: * - CharacterController doesn't know about input systems * - Can swap input sources (keyboard, gamepad, AI, replay) * - Easier to test (mock input) */ export class CharacterInputController { constructor(character: any, inputMap: any); character: any; inputMap: any; prevJumpHeld: boolean; /** * Update character from input - call every frame */ update(): void; } /** * TopDownController - 8-directional movement (no jumping) * * For: top-down action games, twin-stick shooters */ export class TopDownController extends RigidBody2D { constructor(name: any, options?: {}); speed: any; acceleration: any; friction: any; velocity: { x: number; y: number; }; moveInput: { x: number; y: number; }; canDash: any; dashSpeed: any; dashDuration: any; dashCooldown: any; isDashing: boolean; dashTimer: number; dashCooldownTimer: number; dashDirection: { x: number; y: number; }; handleMovement(delta: any): void; /** * Execute dash */ dash(): boolean; setMoveInput(x: any, y: any): void; } /** * TopDownInputController - for TopDownController */ export class TopDownInputController { constructor(character: any, inputMap: any); character: any; inputMap: any; prevDashHeld: boolean; update(): void; } import { RigidBody2D } from './physics.js'; import { Sprite } from './sprite.js'; import { AnimatedSprite } from './sprite.js';