ABOUT ME

Today
Yesterday
Total
  • GridManager
    카테고리 없음 2025. 4. 18. 16:26
    // ----------------------------------------
    // Entity 클래스 (기본)
    // ----------------------------------------
    class Entity {
    public:
        int id;
        float x, y;
        enum class Type { Player, Monster } type;
    
        int gridX = -1;
        int gridY = -1;
    
        Entity(int id, float x, float y, Type type)
            : id(id), x(x), y(y), type(type) {}
    };
    
    // ----------------------------------------
    // GridManager 확장 (시야 체크, 타입별 저장, broadcast)
    // ----------------------------------------
    #include <unordered_set>
    #include <vector>
    #include <cmath>
    #include <iostream>
    
    class GridManager {
    public:
        GridManager(int width, int height, int cellSize);
    
        void addEntity(Entity* entity);
        void moveEntity(Entity* entity, float newX, float newY);
        void removeEntity(Entity* entity);
    
        std::vector<Entity*> getEntitiesInViewRange(Entity* viewer, float range);
        void broadcastToNearby(float x, float y, float range, const std::string& msg);
        std::vector<Entity*> getEntitiesInAoEMask(float x, float y, float range, float dirDeg);
    
    private:
        struct Cell {
            std::unordered_set<Entity*> players;
            std::unordered_set<Entity*> monsters;
        };
    
        int width, height, cellSize;
        std::vector<std::vector<Cell>> grid;
    
        std::pair<int, int> getCellCoord(float x, float y);
        void enterCell(Entity* entity, int x, int y);
        void leaveCell(Entity* entity, int x, int y);
    };
    
    GridManager::GridManager(int width, int height, int cellSize)
        : width(width), height(height), cellSize(cellSize) {
        grid.resize(width, std::vector<Cell>(height));
    }
    
    std::pair<int, int> GridManager::getCellCoord(float x, float y) {
        return { static_cast<int>(x) / cellSize, static_cast<int>(y) / cellSize };
    }
    
    void GridManager::enterCell(Entity* entity, int x, int y) {
        if (x < 0 || x >= width || y < 0 || y >= height) return;
        if (entity->type == Entity::Type::Player)
            grid[x][y].players.insert(entity);
        else
            grid[x][y].monsters.insert(entity);
    }
    
    void GridManager::leaveCell(Entity* entity, int x, int y) {
        if (x < 0 || x >= width || y < 0 || y >= height) return;
        if (entity->type == Entity::Type::Player)
            grid[x][y].players.erase(entity);
        else
            grid[x][y].monsters.erase(entity);
    }
    
    void GridManager::addEntity(Entity* entity) {
        auto [cx, cy] = getCellCoord(entity->x, entity->y);
        entity->gridX = cx;
        entity->gridY = cy;
        enterCell(entity, cx, cy);
    }
    
    void GridManager::moveEntity(Entity* entity, float newX, float newY) {
        auto [newCX, newCY] = getCellCoord(newX, newY);
        if (newCX != entity->gridX || newCY != entity->gridY) {
            leaveCell(entity, entity->gridX, entity->gridY);
            enterCell(entity, newCX, newCY);
            entity->gridX = newCX;
            entity->gridY = newCY;
        }
        entity->x = newX;
        entity->y = newY;
    }
    
    void GridManager::removeEntity(Entity* entity) {
        leaveCell(entity, entity->gridX, entity->gridY);
    }
    
    std::vector<Entity*> GridManager::getEntitiesInViewRange(Entity* viewer, float range) {
        std::vector<Entity*> result;
        auto [cx, cy] = getCellCoord(viewer->x, viewer->y);
        int cells = static_cast<int>(std::ceil(range / cellSize));
    
        for (int dx = -cells; dx <= cells; ++dx) {
            for (int dy = -cells; dy <= cells; ++dy) {
                int x = cx + dx;
                int y = cy + dy;
                if (x < 0 || y < 0 || x >= width || y >= height) continue;
                for (auto* e : grid[x][y].players)
                    if (e != viewer) result.push_back(e);
                for (auto* e : grid[x][y].monsters)
                    result.push_back(e);
            }
        }
        return result;
    }
    
    void GridManager::broadcastToNearby(float x, float y, float range, const std::string& msg) {
        auto entities = getEntitiesInAoEMask(x, y, range, 0);
        for (auto* e : entities) {
            std::cout << "Broadcast to Entity " << e->id << ": " << msg << "\n";
        }
    }
    
    std::vector<Entity*> GridManager::getEntitiesInAoEMask(float x, float y, float range, float dirDeg) {
        std::vector<Entity*> result;
        auto [cx, cy] = getCellCoord(x, y);
        int cells = static_cast<int>(std::ceil(range / cellSize));
    
        float rangeSq = range * range;
        float dirRad = dirDeg * 3.1415926f / 180.0f;
    
        for (int dx = -cells; dx <= cells; ++dx) {
            for (int dy = -cells; dy <= cells; ++dy) {
                int nx = cx + dx;
                int ny = cy + dy;
                if (nx < 0 || ny < 0 || nx >= width || ny >= height) continue;
    
                for (auto* e : grid[nx][ny].players) {
                    float dx = e->x - x;
                    float dy = e->y - y;
                    float distSq = dx * dx + dy * dy;
                    if (distSq <= rangeSq) {
                        result.push_back(e);
                    }
                }
    
                for (auto* e : grid[nx][ny].monsters) {
                    float dx = e->x - x;
                    float dy = e->y - y;
                    float distSq = dx * dx + dy * dy;
                    if (distSq <= rangeSq) {
                        result.push_back(e);
                    }
                }
            }
        }
        return result;
    }
    
    // ----------------------------------------
    // SkillManager 예제: AoE 스킬 처리
    // ----------------------------------------
    class SkillManager {
    public:
        void useAoESkill(Entity* caster, GridManager& grid, float range, float dirDeg) {
            auto targets = grid.getEntitiesInAoEMask(caster->x, caster->y, range, dirDeg);
            for (Entity* t : targets) {
                std::cout << "Skill hit Entity " << t->id << "\n";
            }
            grid.broadcastToNearby(caster->x, caster->y, range, "Skill Effect Shown");
        }
    };
Designed by Tistory.