JernejHabjan / fuzzy-waddle

Game development with Phaser and networking available on https://fuzzy-waddle.onrender.com and https://jernejhabjan.github.io/fuzzy-waddle
https://fuzzy-waddle.onrender.com
MIT License
0 stars 0 forks source link

FOV #76

Open JernejHabjan opened 1 year ago

JernejHabjan commented 1 year ago

https://blog.ourcade.co/posts/2020/phaser3-mrpas-fov-field-of-view-algorithm-roguelike-dungeon-crawler/

JernejHabjan commented 2 weeks ago

Something like this

class VisibilityManager {
    constructor(scene, tilemap, actors) {
        this.scene = scene;
        this.tilemap = tilemap;
        this.actors = actors;
        this.playerActors = [];
        this.enemyActors = [];

        // Set up event listeners
        this.scene.events.on('actorCreated', this.handleActorCreated, this);
        this.scene.events.on('actorRemoved', this.handleActorRemoved, this);
        this.scene.events.on('actorMoved', this.handleActorMoved, this);

        // Initialize visibility
        this.updateVisibility();
    }

    updateVisibility() {
        // Clear all visibility
        this.clearVisibility();

        // Update visibility based on player and enemy actors
        this.updatePlayerVisibility();
        this.updateEnemyVisibility();
    }

    clearVisibility() {
        // Hide all tiles and enemy buildings
        this.tilemap.forEachTile(tile => {
            tile.visible = false;
        });
        this.actors.forEach(actor => {
            if (actor.owner === 'enemy') {
                actor.setVisible(false);
            }
        });
    }

    updatePlayerVisibility() {
        this.playerActors.forEach(actor => {
            if (actor.hasVisionComponent) {
                const visionRange = actor.visionRange;
                this.tilemap.forEachTile(tile => {
                    if (this.isInVisionRange(actor, tile)) {
                        tile.visible = true;
                    }
                });
                this.actors.forEach(otherActor => {
                    if (otherActor !== actor && this.isInVisionRange(actor, otherActor)) {
                        otherActor.setVisible(true);
                    }
                });
            }
        });
    }

    updateEnemyVisibility() {
        const canSeeEnemy = (enemyActor) => {
            return this.playerActors.some(playerActor => this.isInVisionRange(playerActor, enemyActor));
        };

        this.actors.forEach(actor => {
            if (actor.owner === 'enemy') {
                actor.setVisible(canSeeEnemy(actor));
            }
        });
    }

    isInVisionRange(actor, target) {
        const distance = Phaser.Math.Distance.Between(actor.x, actor.y, target.x, target.y);
        return distance <= actor.visionRange;
    }

    handleActorCreated(actor) {
        // Add actor to appropriate list and update visibility
        if (actor.owner === 'player') {
            this.playerActors.push(actor);
        } else if (actor.owner === 'enemy') {
            this.enemyActors.push(actor);
        }
        this.updateVisibility();
    }

    handleActorRemoved(actor) {
        // Remove actor from list and update visibility
        if (actor.owner === 'player') {
            this.playerActors = this.playerActors.filter(a => a !== actor);
        } else if (actor.owner === 'enemy') {
            this.enemyActors = this.enemyActors.filter(a => a !== actor);
        }
        this.updateVisibility();
    }

    handleActorMoved(actor) {
        // Update visibility after movement
        this.updateVisibility();
    }
}

// Usage:
// Assuming `scene`, `tilemap`, and `actors` are already defined
const visibilityManager = new VisibilityManager(scene, tilemap, actors);