3d游戏引擎主要依赖direct12的独立跨平台实现代码2(Components1)

1.ComponentsCommon.h

#pragma once
#include "..\Common\CommonHeaders.h"
#include "..\Common\Id.h"
#include "..\EngineAPI\GameEntity.h"
/*
namespace primal::game_entity
{
    DEFINE_TYPED_ID(entity_id);


}
*/

2.Entity.cpp

#include "Entity.h"
#include "Script.h"
#include "Transform.h"

namespace primal::game_entity {
    
    namespace {
        utl::vector<transform::component>  transforms;
        utl::vector<script::component> scripts;
    
        utl::vector<id::generation_type> generations;
        utl::deque<entity_id> free_ids;
    
    }
    entity
    create(const entity_info info) 
    {
        assert(info.transform);
        if (!info.transform) return entity{};

        entity_id id;

        if (free_ids.size() > id::min_deleted_elements) 
        {
            id = free_ids.front();
            assert(!is_alive( id ));
            free_ids.pop_front();
            id = entity_id{ id::new_generation(id) };
            ++generations[id::index(id)];
        
        
        }
        else 
        {
            id = entity_id{ (id::id_type)generations.size() };
            //transforms.resize(generations.size());
            generations.push_back(0);
            transforms.emplace_back();
            scripts.emplace_back();
        
        
        
        }
        const entity new_entity{ id };
        const id::id_type index{ id::index(id) };

        //Create transform component

        assert(!transforms[index].is_valid());
        transforms[index] = transform::create(*info.transform, new_entity);
        if (!transforms[index].is_valid()) return {};

        //Create script component
        if (info.script && info.script->script_creator) 
        {
            assert(!scripts[index].is_valid());
            scripts[index] = script::create(*info.script, new_entity);
            assert(scripts[index].is_valid());
        
        
        }


        return new_entity;

    
    }
    void
        remove(entity_id id) 
    {
        //const entity_id id{ e.get_id() };
        const id::id_type index{ id::index(id) };
        assert(is_alive(id));
        
        if(scripts[index].is_valid())
        {
            script::remove(scripts[index]);
            scripts[index] = {};
        
        
        }


        
            transform::remove(transforms[index]);
            transforms[index] = {};
            free_ids.push_back(id);
        
        
    
    }
    bool is_alive(entity_id id) 
    {
        assert(id::is_valid(id));
        
        const id::id_type index{ id::index(id) };
        assert(index < generations.size());
        assert(generations[index] == id::generation(id));
        return (generations[index] == id::generation(id) && transforms[index].is_valid());
    
    }


    transform::component
        entity::transform() const 
    {
        assert(is_alive(_id));
        const id::id_type index{ id::index(_id) };
        return transforms[index];
    
    
    
    }
    script::component
        entity::script() const 
    {
        assert(is_alive(_id));
        const id::id_type index{ id::index(_id) };
        return scripts[index];
    
    
    }

}

3.Entity.h

#pragma once
#include "ComponentsCommon.h"

namespace primal 
{
#define INIT_INFO(component) namespace component {struct init_info;}
    INIT_INFO(transform);
    INIT_INFO(script);
#undef INIT_INFO
    namespace game_entity {
        struct entity_info
        {
            transform::init_info* transform{ nullptr };
            script::init_info* script{ nullptr };


        };
        entity create(const entity_info info);
        
        void remove(entity_id id);
        bool is_alive(entity_id id);
    }
}

4.Script.cpp

#include "Script.h"
#include "Entity.h"

namespace primal::script {
    namespace {
    
        utl::vector<detail::script_ptr> entity_scripts;
        utl::vector<id::id_type> id_mapping;

        utl::vector<id::generation_type> generations;
        utl::deque<script_id> free_ids;

        
        using script_registry = std::unordered_map<size_t, detail::script_creator>;

        script_registry&
            registery() 
        {

            static script_registry reg;
            return reg;
        
        }


        #ifdef USE_WITH_EDITOR

        utl::vector<std::string>&
            scripts_name() 
        {
            static utl::vector<std::string> names;
            return names;
            
        
        
        }
        #endif

        
    
    
    bool
        exists(script_id id) 
    {
    
        assert(id::is_valid(id));
        const id::id_type index{ id::index(id) };
        assert(index < generations.size() && id_mapping[index] < entity_scripts.size());
        assert(generations[index] == id::generation(id));
        return (generations[index] == id::generation(id)) &&
            entity_scripts[id_mapping[index]] &&
            entity_scripts[id_mapping[index]]->is_valid();
    
    }
    }


    namespace detail 
    {
    
        u8 register_script(size_t tag, script_creator func) 
        {
            bool result{ registery().insert(script_registry::value_type{tag,func}).second };
            assert(result);
            return result;
        
        
        
        }

        script_creator
            get_script_creator(size_t tag) 
        {
        
            auto script = primal::script::registery().find(tag);
            assert(script != primal::script::registery().end() && script->first == tag);
            return script->second;
        
        
        
        }

#ifdef USE_WITH_EDITOR
u8 
add_script_name(const char* name) 
{
    
    script_names().emplace_back(name);
    return true;


}

#endif
    
    
    
    
    }


    component
        create(init_info info, game_entity::entity entity){ 

        assert(entity.is_valid());
        assert(info.script_creator);

        script_id id{};

        if (free_ids.size() > id::min_deleted_elements) 
        {
            id = free_ids.front();
            assert(!exists(id));
            free_ids.pop_front();
            id = script_id{ id::new_generation(id) };
            ++generations[id::index(id)];
        
        
        }
        else 
        {
            id = script_id{ (id::id_type)id_mapping.size() };
            id_mapping.emplace_back();
            generations.push_back(0);
        
        
        }

        assert(id::is_valid(id));
        const id::id_type index{ (id::id_type)entity_scripts.size()};
        entity_scripts.emplace_back(info.script_creator(entity));
        assert(entity_scripts.back()->get_id() == entity.get_id());
        
        id_mapping[id::index(id)] = index;
        
        return component{id};
    
    }
    void remove(component c) 
    {
        assert(c.is_valid() && exists(c.get_id()));
        const script_id id{ c.get_id() };
        const id::id_type index{ id_mapping[id::index(id)] };
        const script_id last_id{ entity_scripts.back()->script().get_id() };
        utl::erase_unordered(entity_scripts, index);
        id_mapping[id::index(last_id)]  = index;
        id_mapping[id::index(id)] = id::invalid_id;
    
    
    }

    void update(float dt) 
    {
        for (auto& ptr : entity_scripts) 
        {
            ptr->update(dt);
        
        
        }
    
    }

}


#ifdef USE_WITH_EDITOR


#include <atlsafe.h>
extern "C" __declspec(dllexport)

LPSAFEARRY
get_script_names()
{
    const u32 size{ (u32)primal::script::script_names().size() };
    if (!size) return nullptr;
    CComSafeArray<BSTR> names(size);
    for (u32 i{ 0 }; i < size; ++i) 
    {
        names.SetAt(i, A2BSTR_EX(primal::script::script_names()[i].c_str()),false);
    
    
    }
    
    return names.Detach();


}


#endif

总引擎核心运行成功的代码截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Magnum Lehar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值