about summary refs log blame commit diff stats
path: root/html/rogue/js/player.js
blob: 3c1c3834f6102bc46e4451fa21c78204038f9613 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                                          
                                                                                          
                  
    




                                       
                            

                    
 


                                                           
                                                                          

      










                                                          






                                                            
      
 






























                                                               
 

                                   
                                                                                  
                           




                                                                             

                                                  

                                                                              






                                                    
 













                                                                     





                                                    


                                            
                                     
                


                                                             






                                                    
 




                                        
 





                                                                                           
 





                                                     
 



                                                                                       
        
                              
                                   
                                                                                                 












                                                                 
// Player state and controls
const player = {
    position: { q: 0, r: 0 },    // Current hex position
    target: null,                 // Target hex to move to
    path: [],                     // Array of hex coordinates to follow
    movementProgress: 0,          // Progress of current movement (0 to 1)
    moveSpeed: Config.player.MOVE_SPEED,              // Movement speed (0 to 1 per frame)
    inventory: [],
    
    // Initialize player
    init() {
        this.position = { q: 0, r: 0 };
        this.target = null;
        this.path = [];
        this.inventory = [];
        return this;
    },

    // Check if a hex coordinate is within grid bounds
    isValidHex(hex) {
        const halfGrid = Math.floor(HexGrid.GRID_SIZE / 2);
        return Math.abs(hex.q) <= halfGrid && Math.abs(hex.r) <= halfGrid;
    },

    // Get neighbors that share an edge with the given hex
    getEdgeNeighbors(hex) {
        const directions = [
            {q: 1, r: 0},   // East
            {q: 0, r: 1},   // Southeast
            {q: -1, r: 1},  // Southwest
            {q: -1, r: 0},  // West
            {q: 0, r: -1},  // Northwest
            {q: 1, r: -1}   // Northeast
        ];
        
        // Only return neighbors that are within grid bounds
        return directions
            .map(dir => ({
                q: hex.q + dir.q,
                r: hex.r + dir.r
            }))
            .filter(hex => this.isValidHex(hex));
    },

    // Find path from current position to target
    findPath(targetHex) {
        const start = this.position;
        const goal = targetHex;
        
        // Simple breadth-first search
        const queue = [[start]];
        const visited = new Set();
        const key = hex => `${hex.q},${hex.r}`;
        visited.add(key(start));
        
        while (queue.length > 0) {
            const path = queue.shift();
            const current = path[path.length - 1];
            
            if (current.q === goal.q && current.r === goal.r) {
                return path;
            }
            
            const neighbors = this.getEdgeNeighbors(current);
            for (const neighbor of neighbors) {
                const neighborKey = key(neighbor);
                if (!visited.has(neighborKey)) {
                    visited.add(neighborKey);
                    queue.push([...path, neighbor]);
                }
            }
        }
        
        return null; // No path found
    },

    // Start moving to a target hex
    moveTo(targetHex) {
        // Only start new movement if we're not already moving and target is valid
        if (!this.target) {
            // Check if target is within grid bounds
            if (!this.isValidHex(targetHex)) {
                return; // Ignore movement request if target is out of bounds
            }

            const path = this.findPath(targetHex);
            if (path) {
                // Filter out any path points that would go out of bounds
                this.path = path.slice(1).filter(hex => this.isValidHex(hex));
                if (this.path.length > 0) {
                    this.target = this.path.shift();
                    this.movementProgress = 0;
                }
            }
        }
    },

    // Add item to inventory
    addToInventory(item) {
        this.inventory.push(item);
    },

    // Check for and collect items
    checkForItems() {
        const item = Items.getItem(this.position.q, this.position.r);
        if (item) {
            Items.removeItem(this.position.q, this.position.r);
            this.addToInventory(item);
        }
    },

    // Update player position
    update() {
        if (this.target) {
            this.movementProgress += this.moveSpeed;
            
            if (this.movementProgress >= 1) {
                this.position = this.target;
                this.target = null;
                this.movementProgress = 0;
                this.hasMoved = true;
                
                // Check for items when reaching new position
                this.checkForItems();
                
                if (this.path.length > 0) {
                    this.target = this.path.shift();
                    this.movementProgress = 0;
                }
            }
        }
    },

    // Get current interpolated position
    getCurrentPosition() {
        if (!this.target) {
            return this.position;
        }

        // Interpolate between current position and target
        return {
            q: this.position.q + (this.target.q - this.position.q) * this.movementProgress,
            r: this.position.r + (this.target.r - this.position.r) * this.movementProgress
        };
    },

    // Draw the player
    draw(ctx, hexToPixel, camera, HEX_SIZE) {
        const currentPos = this.getCurrentPosition();
        const pixelPos = hexToPixel(currentPos);
        const screenX = pixelPos.x - camera.x;
        const screenY = pixelPos.y - camera.y;

        ctx.fillStyle = Config.colors.PLAYER;
        ctx.beginPath();
        ctx.arc(screenX, screenY, HEX_SIZE * Config.player.SIZE_RATIO, 0, Math.PI * 2);
        ctx.fill();
        
        // Draw path if needed
        if (this.path.length > 0) {
            ctx.strokeStyle = Config.colors.PLAYER + '4D'; // 30% opacity version of player color
            ctx.beginPath();
            let lastPos = this.target || this.position;
            this.path.forEach(point => {
                const from = hexToPixel(lastPos);
                const to = hexToPixel(point);
                ctx.moveTo(from.x - camera.x, from.y - camera.y);
                ctx.lineTo(to.x - camera.x, to.y - camera.y);
                lastPos = point;
            });
            ctx.stroke();
        }
    }
};