kinesis19 / Cyber_Hunter

Project: Cyber Hunter
1 stars 0 forks source link

Player 사망 처리 이벤트 구현하기 #2

Open kinesis19 opened 4 weeks ago

kinesis19 commented 4 weeks ago

기능 소개

Player의 hp가 0 이하일 때 사망 처리 이벤트 구현하기

kinesis19 commented 3 weeks ago

Description

현재 stopEnemySpawn()가 실행 되어도 stop 직전의 Interval가 한 번 실행 되어서 Player의 hp가 0 이하일 때 바로 stop이 안 되는 현상이 발생됨.

Source Code

Enemy.js

class Enemy{
    constructor(object, player, hp, dmg, dropExp){
        this.object = object;
        this.player = player;

        // Enemy Health
        this.health = hp;
        // Enemy move Vector
        this.moveVector = new THREE.Vector3();
        // Enemy move speed
        this.speed = 0.02;
        // Define the radius for collision
        this.radius = 1; // Setting the radius of Enemy

        this.damage = dmg;

        this.dropExp = dropExp;
    }
    update(dt, enemyList) {
        const direction = new THREE.Vector3().subVectors(this.player.position, this.object.position);
        direction.y = 0;

        if (direction.length() > 0.1) {
            direction.normalize();
            this.moveVector.copy(direction).multiplyScalar(this.speed);
            const newPosition = this.object.position.clone().add(this.moveVector);

            // Check for potential collisions before moving
            let collision = false;
            for (let other of enemyList) {
                if (other !== this && newPosition.distanceTo(other.object.position) < (this.radius + other.radius)) {
                    collision = true;
                    break;
                }
            }

            if (!collision) {
                this.object.position.add(this.moveVector);
            }

            // Enemy lookAt Player, But position Y is staying current position
            const lookAtPosition = new THREE.Vector3(this.player.position.x, this.object.position.y, this.player.position.z);
            this.object.lookAt(lookAtPosition);
        }
    }

    dispose() {
        WORLD.remove(this.object);
    }
}

GLOBAL.enemyList = [];
let spawnInterval = null; // Save spawn Interval ID
let listenersInitialized = false; // Check listener is Initialized

function Start(){
    REDBRICK.Signal.addListener("CHECK_ENEMY_HIT", function(params) {
        for(let i = 0; i < GLOBAL.enemyList.length; i++){
            const dist = GLOBAL.enemyList[i].object.position.distanceTo(params.bullet.object.position);

            if(dist < 5){
                params.bullet.life = 0;
                GLOBAL.enemyList[i].health -= GLOBAL.player.atk;
            }

            // Enemy Kill Processing
            if(GLOBAL.enemyList[i].health <= 0){ 
                GLOBAL.playerKillCount = GLOBAL.playerKillCount + 1;
                GLOBAL.player.addExp(GLOBAL.enemyList[i].dropExp);

                REDBRICK.Signal.send("UPDATE_NEXT_ROUND");

                GLOBAL.enemyList[i].dispose();
                GLOBAL.enemyList.splice(i, 1);
                i--;
            }
        }
    })

    setupSignalListeners(); // Setup Signal Listeners 
    startEnemySpawn(); // Start Enemy spawn
}

function setupSignalListeners() {
    if (listenersInitialized) return;

    REDBRICK.Signal.addListener("GAME_RESTART", () => {
        stopEnemySpawn();
        resetPlayerState();
        PLAYER.changePlayerSpeed(1);
        startEnemySpawn();
    });

    listenersInitialized = true;
}

function startEnemySpawn() {
    spawnInterval = setInterval(() => {
        if (GLOBAL.player.hp <= 0) {
            PLAYER.changePlayerSpeed(0);
            stopEnemySpawn();
            return;
        }
        spawnEnemyRandomly();
    }, GLOBAL.mobSpawnSpeed);
}

function stopEnemySpawn() {
    if (spawnInterval) {
        clearInterval(spawnInterval);
        spawnInterval = null;
    }
}

const enemyObject = WORLD.getObject("Enemy");

function spawnEnemyRandomly() {
    const areas = {
        'AreaA': { xRange: [PLAYER.position.x - 20, PLAYER.position.x - 30], zRange: [PLAYER.position.z - 20, PLAYER.position.z - 30], y: 2 },
        'AreaB': { xRange: [PLAYER.position.x + 20, PLAYER.position.x + 30], zRange: [PLAYER.position.z - 20, PLAYER.position.z - 30], y: 2 },
        'AreaC': { xRange: [PLAYER.position.x - 20, PLAYER.position.x - 30], zRange: [PLAYER.position.z + 20, PLAYER.position.z + 30], y: 2 },
        'AreaD': { xRange: [PLAYER.position.x + 20, PLAYER.position.x + 30], zRange: [PLAYER.position.z + 20, PLAYER.position.z + 30], y: 2 }
    };

    // Select a random area
    const areaKeys = Object.keys(areas);
    const randomArea = areas[areaKeys[Math.floor(Math.random() * areaKeys.length)]];

    // Random position within the selected area
    const x = Math.random() * (randomArea.xRange[1] - randomArea.xRange[0]) + randomArea.xRange[0];
    const z = Math.random() * (randomArea.zRange[1] - randomArea.zRange[0]) + randomArea.zRange[0];
    const y = randomArea.y;

    const clone = enemyObject.clone();
    clone.position.set(x, y, z);
    WORLD.add(clone);

    const enemy = new Enemy(clone, PLAYER, 10, 5, 1);
    GLOBAL.enemyList.push(enemy);
}
kinesis19 commented 3 weeks ago

player의 사망 처리 시스템은 Enemy.js에서 분기 처리를 진행함: 9d0fc40

UI를 띄우고, restart 하는 기능은 사수분들께서 보내주시는 UI 받으면 진행할 예정임.

그동안 스킬 선택 시스템 구현하기.