Keys to Move

Time to bring your hero to LIFE! 🎮 This is the moment where your game transforms from a static picture into an interactive experience. Player control is what separates games from movies - and you’re about to master it! By the end of this chapter, your hero will respond to your every command, moving smoothly through your tile-based world.

Try it! Use your arrow keys to move the red square around! ⬅️➡️⬆️⬇️

Notice how the hero changes color when moving and stays within the boundaries!

MODERN CHARACTER SETUP 🎨

Forget complex movie clips and keyframes! Modern game development uses much simpler, more powerful approaches. Let’s build a character system that’s both easier to understand and more flexible than the old Flash methods.

Enhanced Hero Object:

const hero = {
    // Position in tile coordinates
    tileX: 3,
    tileY: 2,
    
    // Pixel coordinates (calculated from tile position)
    x: 0,
    y: 0,
    
    // Movement properties
    speed: 2,              // How fast we move (pixels per frame)
    isMoving: false,       // Are we currently moving?
    direction: 'down',     // Which way are we facing?
    
    // Visual representation
    sprite: null,          // Our PixiJS sprite
    
    // Animation (we'll enhance this!)
    animationFrame: 0,
    animationSpeed: 0.2
};

Why this is better than Flash:

KEYBOARD INPUT: THE MODERN WAY 🎯

Step 1: Set Up Input Tracking

Modern games use event listeners to track keyboard input. This is much more reliable and flexible than Flash’s old Key.isDown method:

// Create an object to track which keys are currently pressed
const keys = {
    ArrowUp: false,
    ArrowDown: false,
    ArrowLeft: false,
    ArrowRight: false,
    // You can easily add more keys later!
    Space: false,
    KeyZ: false
};

// Listen for key presses
window.addEventListener('keydown', (event) => {
    if (keys.hasOwnProperty(event.code)) {
        keys[event.code] = true;
        event.preventDefault(); // Prevent browser scroll
    }
});

// Listen for key releases
window.addEventListener('keyup', (event) => {
    if (keys.hasOwnProperty(event.code)) {
        keys[event.code] = false;
        event.preventDefault();
    }
});

Why this rocks:

MOVEMENT LOGIC: CLEAN & POWERFUL 🚀

Step 2: Create the Movement System

Let’s create a clean movement system that’s easy to understand and modify:

function updateMovement() {
    let moved = false;
    let newDirection = hero.direction;
    
    // Check each direction
    if (keys.ArrowUp) {
        hero.tileY--;
        newDirection = 'up';
        moved = true;
    } else if (keys.ArrowDown) {
        hero.tileY++;
        newDirection = 'down';
        moved = true;
    } else if (keys.ArrowLeft) {
        hero.tileX--;
        newDirection = 'left';
        moved = true;
    } else if (keys.ArrowRight) {
        hero.tileX++;
        newDirection = 'right';
        moved = true;
    }
    
    // Update hero state
    if (moved) {
        hero.direction = newDirection;
        hero.isMoving = true;
        updateHeroPosition();  // Convert tile pos to pixels
    } else {
        hero.isMoving = false;
    }
    
    // Update visual direction (we'll enhance this!)
    updateHeroAppearance();
}

// Convert tile coordinates to pixel coordinates
function updateHeroPosition() {
    hero.x = (hero.tileX * TILE_SIZE) + (TILE_SIZE / 2);
    hero.y = (hero.tileY * TILE_SIZE) + (TILE_SIZE / 2);
    
    // Update sprite position
    hero.sprite.x = hero.x;
    hero.sprite.y = hero.y;
}

// Update hero appearance based on direction
function updateHeroAppearance() {
    // Simple visual feedback (you can make this more sophisticated!)
    if (hero.isMoving) {
        hero.sprite.tint = 0xffff00;  // Yellow when moving
    } else {
        hero.sprite.tint = 0xffffff;  // White when still
    }
}

Connect to the Game Loop:

// In PixiJS, add this to your ticker for 60fps updates
app.ticker.add(updateMovement);

What makes this awesome:

ADDING VISUAL DIRECTION 🎨

Make Your Hero Face the Right Way:

function updateHeroAppearance() {
    const sprite = hero.sprite;
    
    // Reset transformations
    sprite.scale.x = 1;
    sprite.rotation = 0;
    
    // Update visual based on direction
    switch (hero.direction) {
        case 'left':
            sprite.scale.x = -1;  // Flip horizontally
            break;
        case 'right':
            // Default orientation (no change needed)
            break;
        case 'up':
            sprite.rotation = -Math.PI / 2;  // Rotate 90° counter-clockwise
            break;
        case 'down':
            sprite.rotation = Math.PI / 2;   // Rotate 90° clockwise
            break;
    }
    
    // Movement feedback
    sprite.tint = hero.isMoving ? 0xffff00 : 0xffffff;
    
    // Optional: Add subtle scale animation when moving
    if (hero.isMoving) {
        const pulse = Math.sin(Date.now() * 0.01) * 0.05 + 1;
        sprite.scale.y = pulse;
    }
}

ADVANCED: SMOOTH MOVEMENT 🚀

Want buttery-smooth movement instead of tile-by-tile jumping?

function updateSmoothMovement() {
    let targetX = (hero.tileX * TILE_SIZE) + (TILE_SIZE / 2);
    let targetY = (hero.tileY * TILE_SIZE) + (TILE_SIZE / 2);
    
    // Smooth interpolation
    const lerpSpeed = 0.2;
    hero.x += (targetX - hero.x) * lerpSpeed;
    hero.y += (targetY - hero.y) * lerpSpeed;
    
    hero.sprite.x = hero.x;
    hero.sprite.y = hero.y;
}

🏆 MOVEMENT MASTERY ACHIEVED!

You’ve just built a complete movement system that rivals professional games! Your hero responds instantly to input, faces the right direction, and moves smoothly through your world.

What you’ve conquered:

Ready for the next challenge? Let’s add collision detection so your hero can’t walk through walls! Next: Hit the Wall