一个单机棋盘式半即时解谜RPG的开发与反思、2

无人机地面站链路全解析:数传、AP、4G/5G 与 RTK 差分接入原理及排查实践 本文系统梳理了无人机地面站与飞控的通讯链路架构,涵盖数传电台、WiFi AP及蜂窝(4G/5G)三种接入方式的工作原理与排查流程。重点强调物理层(波特率、供电、天线)、MAVLink层(心跳、SYSID、协议版本)和应用层(端口、心跳保活、网络配置)的逐层排查逻辑。对比分析了AP与蜂窝链路在延迟、覆盖、多机支持等方面的优劣,提出“专用链路控实时、AP传数据、蜂窝远监控”的组合使用策略,并指出共性风险如省电模式、NAT超时等需统一防范。 阅读详情

接上篇

在本系列第一篇文章中,我介绍了这个项目的Json、Lua相关设计,这篇文章中将会对基础库RJCBLib进行详细介绍。我将相关的头文件给出以供参考。

RJCBLib库包含功能(2016-3-6):

GenericValue : 通用类型。

Singleton<> : 提供单例支持。

ObjectManager<> : 提供对象管理功能,继承自Sigleton<>。

JsonBuffer : 提供对Json数据的管理,结合了cocos2d中提供的RapidJson,继承自ObjectManager<>。

LuaObject : 实现了对Lua的支持,继承自此类可以使用Lua功能。

KVObject : 以Key/Value的方式管理对象属性,可以直接解析RapidJson对象。

Matrix<> : 通过矩阵的方式管理对象。

基本定义

typedef const char* const FUNC_RETURN_TYPE;
typedef const char* FUNC_RETURN_TYPE_W;
FUNC_RETURN_TYPE FUNC_RETURN_VALUE_SUCCESS = "SUCCESS";
FUNC_RETURN_TYPE FUNC_RETURN_VALUE_FAILURE = "FAILURE";
FUNC_RETURN_TYPE FUNC_RETURN_VALUE_FOUND = "FOUND";
FUNC_RETURN_TYPE FUNC_RETURN_VALUE_NOT_FOUND = "NOT FOUND";
FUNC_RETURN_TYPE FUNC_RETURN_VALUE_EXISTED = "EXISTED";

//将某个类型转换为字符串,存在效率问题,不建议在帧中使用
template<typename T>
inline std::string to_string(const T &arg) { std::stringstream ss;ss << arg; std::string t;ss >> t;return t; }

//对常用类型进行了封装,你需要提前知道这个类的实例究竟该解释为什么类型
struct GenericValue
{
    GenericValue()
    {
    }
    GenericValue(std::string String)
    {
        this->String = String;
    }
    GenericValue(int Int)
    {
        this->Int = Int;
    }
    GenericValue(bool Bool)
    {
        this->Bool = Bool;
    }
    GenericValue(double Double)
    {
        this->Double = Double;
    }
    std::string String;
    int Int;
    bool Bool;
    double Double;
};

定义了函数返回值、GenericValue是对基本类型的封装。

单例支持

通过模板实现了单例:

template<typename ClassSelfType>
class Singleton
{
public:
    static ClassSelfType* getInstance()
    {
        if (RJCBLib::Singleton<ClassSelfType>::instance == nullptr)
        {

            RJCBLib::Singleton<ClassSelfType>::instance = new ClassSelfType();
            dynamic_cast<RJCBLib::Singleton<ClassSelfType>*>(RJCBLib::Singleton<ClassSelfType>::instance)->init();
        }
        return RJCBLib::Singleton<ClassSelfType>::instance;
    }
    ~Singleton()
    {}

protected:
    Singleton()
    {}
    virtual void init()//如果被单例的类override了这个函数,那么它将会在第一次创建单例的时候被调用
    {

    }
private:

    static ClassSelfType* instance;//单例的对象指针

    template<typename classSelfType>
    class Automatic//自动释放类,待测试
    {
    private:
        Automatic() { 

        }
        ~Automatic() { 

            delete RJCBLib::Singleton<classSelfType>::instance;
        }
    };
    static Automatic<ClassSelfType> automatic;
    static int a;
};
template<typename ClassSelfType> ClassSelfType *RJCBLib::Singleton<ClassSelfType>::instance = nullptr;

如何使用:

class A : public RJCBLib::Sigleton<A>
{

};
--------------
A* instance = A::getInstance();

在继承这个模板的时候将继承类A自身传入这个模板,会为A生成一个基类Sigleton<A>。A的单例被创建时会调用虚函数Sigleton<A>::init,可以在A中重写这个虚函数以实现初始化的相关工作。Automatic内部类实现了单例的自动释放。

对象管理

继承自Sigleton<>与cocos2d::Map<>。

template<typename ClassSelfType, typename KeyType, typename ValueType_MustBePointerToRef>
class ObjectManager : private cocos2d::Map<KeyType, ValueType_MustBePointerToRef>, public RJCBLib::Singleton<ClassSelfType>
{
public:
    //获取被管理KV的数量
    SSIZE_T size()
    {
        return Map<KeyType, ValueType_MustBePointerToRef>::size();
    }
    //清空所有KV
    RJCBLib::FUNC_RETURN_TYPE clear()
    {
        Map<KeyType, ValueType_MustBePointerToRef>::clear();
        return RJCBLib::FUNC_RETURN_VALUE_SUCCESS;
    }
    //插入一个KV,K应未被使用过
    RJCBLib::FUNC_RETURN_TYPE insert(KeyType key, ValueType_MustBePointerToRef value)
    {
        if (this->has(key) == RJCBLib::FUNC_RETURN_VALUE_FOUND)
        {
            return RJCBLib::FUNC_RETURN_VALUE_EXISTED;
        }
        Map<KeyType, ValueType_MustBePointerToRef>::insert(key, value);
        return RJCBLib::FUNC_RETURN_VALUE_SUCCESS;
    }
    //获取指定K的V
    RJCBLib::FUNC_RETURN_TYPE get(KeyType key, ValueType_MustBePointerToRef &outValue)
    {
        auto ite = Map<KeyType, ValueType_MustBePointerToRef>::find(key);
        if (ite == Map<KeyType, ValueType_MustBePointerToRef>::end())
        {
            outValue = nullptr;
            return RJCBLib::FUNC_RETURN_VALUE_NOT_FOUND;
        }
        outValue = (*ite).second;
        return RJCBLib::FUNC_RETURN_VALUE_SUCCESS;
    }
    //移除指定K所对应的KV
    RJCBLib::FUNC_RETURN_TYPE remove(KeyType key)
    {
        if (Map<KeyType, ValueType_MustBePointerToRef>::find(key) == Map<KeyType, ValueType_MustBePointerToRef>::end())
        {
            return RJCBLib::FUNC_RETURN_VALUE_NOT_FOUND;
        }
        Map<KeyType, ValueType_MustBePointerToRef>::erase(key);
        return RJCBLib::FUNC_RETURN_VALUE_SUCCESS;
    }
    //是否包含某个K
    RJCBLib::FUNC_RETURN_TYPE has(KeyType key)
    {
        if (Map<KeyType, ValueType_MustBePointerToRef>::find(key) == Map<KeyType, ValueType_MustBePointerToRef>::end())
        {
            return RJCBLib::FUNC_RETURN_VALUE_NOT_FOUND;
        }
        return RJCBLib::FUNC_RETURN_VALUE_FOUND;
    }
    //返回cocos2d::Map的begin迭代器
    auto begin()
    {
        return Map<KeyType, ValueType_MustBePointerToRef>::begin();
    }
    //返回cocos2d::Map的end迭代器
    auto end()
    {
        return Map<KeyType, ValueType_MustBePointerToRef>::end();
    }

    virtual ~ObjectManager() {}
protected:
    ObjectManager() {}
};

如何使用:

class A : public RJCBLib::ObjectManager<A,std::string,std::string>
{
};
------------
把它当做单例的Map用吧。

A继承自ObjectManager,传入三个模板类型:A自身(因为继承自Sigleton<>)、Key类型、被管理者类型。实际上A就是一个单例的Map。

Json数据管理

继承自ObjectManager<>。

class JsonBufferDocumentBox : public cocos2d::Ref
{
public:
    static JsonBufferDocumentBox *create();
    rapidjson::Document& operator*();
    rapidjson::Document* operator->();
private:
    JsonBufferDocumentBox();
    ~JsonBufferDocumentBox();
    rapidjson::Document* document;
};

class JsonBuffer : public RJCBLib::ObjectManager<JsonBuffer,std::string, JsonBufferDocumentBox*>
{   
public:
    JsonBuffer();
    FUNC_RETURN_TYPE parseFile(std::string key, std::string filePath);
    FUNC_RETURN_TYPE parseString(std::string key, std::string data);
};

辅助类JsonBufferDocumentBox封装了rapidjson::Document,因为它继承自cocos2d::ref,所以可以对它进行内存管理,这也是cocos2d::Map<>要求的。
JsonBuffer继承自ObjectManager<>,提供了两个函数分别解析字符串和文件,解析后的内容和可以通过基类ObjectManager<JsonBuffer,KeyType,ValueType>的方法获取。

Lua支持

我没有使用cocos2d自带的Lua功能而是根据需要自己实现了Lua接口相关的工作。尚有很多不足(如线程安全)有待修改,也请读者多提宝贵意见。

#define MAKE_LUA_FUNCTION_NAME(_LUA_ID) (std::string("UpdateFunction")+_LUA_ID)
class LuaObject
{
private:
    //唯一标识的id,在lua虚拟机中不同的对象会通过这个id区别
    static unsigned int _lua_id;
    //是否已被初始化
    bool isInited;
    //
    std::string realFunctionName;
    //生成新的LuaID
    inline unsigned int generateLuaID()
    {
        ++_lua_id;
        return _lua_id;
    }
    //当前活动的LuaObject,因为会有许多LuaObject,这个变量用于和Lua虚拟机交互
    static LuaObject * currentLuaObject;
protected:
    LuaObject();
    virtual ~LuaObject();

    //override这个函数,返回脚本文件路径
    virtual std::string getLuaScriptFilePath() = 0;

    //文件中Update函数的名字
    virtual std::string getUpdateFunctionName() = 0;

    //override这个函数,lua虚拟机查询String时会被调用
    virtual std::string LuaObjectGetString(std::string key) = 0;

    //override这个函数,lua虚拟机查询Int时会被调用
    virtual int LuaObjectGetInt(std::string key) = 0;

    //override这个函数,lua虚拟机查询Double时会被调用
    virtual double LuaObjectGetDouble(std::string key) = 0;

    //override这个函数,lua虚拟机查询Bool时会被调用
    virtual bool LuaObjectGetBool(std::string key) = 0;

    //override这个函数,lua虚拟机设置String时会被调用
    virtual void LuaObjectSetString(std::string key, std::string value) = 0;

    //override这个函数,lua虚拟机设置Int时会被调用
    virtual void LuaObjectSetInt(std::string key, int value) = 0;

    //override这个函数,lua虚拟机设置Bool时会被调用
    virtual void LuaObjectSetBool(std::string key, bool value) = 0;

    //override这个函数,lua虚拟机设置Double时会被调用
    virtual void LuaObjectSetDouble(std::string key, double value) = 0;

    //虚拟机回调的日志函数
    static int Log(lua_State *L);

    //虚拟机回调的获取String函数
    static int StringGet(lua_State *L);

    //虚拟机回调的获取Int函数
    static int IntGet(lua_State *L);

    //虚拟机回调的获取Bool函数
    static int BoolGet(lua_State *L);

    //虚拟机回调的获取Double函数
    static int DoubleGet(lua_State *L);

    //虚拟机回调的设置String函数
    static int StringSet(lua_State *L);

    //虚拟机回调的设置Bool函数
    static int IntSet(lua_State *L);

    //虚拟机回调的设置Bool函数
    static int BoolSet(lua_State *L);

    //虚拟机回调的设置Double函数
    static int DoubleSet(lua_State *L);

    /*
    初始化这个LuaObject
    :
    注册虚拟机回调函数(static *Set, static *Get,static Log)
    执行脚本文件
    重命名update函数(使其在虚拟机中全局唯一)
    */
    void initLuaObject();
public:
    static cocos2d::LuaEngine *luaEngine;

    //外部发起lua事件调用时应调用这个函数,state会被传入虚拟机(通过 IN_STATE__ 获取),可以override这个函数来扩展功能
    virtual void Do(std::string state);

    //设置虚拟机的全局String
    void setGlobalString(std::string key, std::string value);

    //设置虚拟机的全局Int
    void setGlobalInt(std::string key, int value);

    //设置虚拟机的全局Bool
    void setGlobalBool(std::string key, bool value);

    //设置虚拟机的全局Double
    void setGlobalDouble(std::string key, double value);
};

如何使用:

class A : public RJCBLib::LuaObject
{
private:
    virtual std::string getLuaScriptFilePath() override;
    virtual std::string getUpdateFunctionName() override;
    virtual std::string LuaObjectGetString(std::string key) override;
    virtual int LuaObjectGetInt(std::string key) override;
    virtual bool LuaObjectGetBool(std::string key) override;
    virtual double LuaObjectGetDouble(std::string key) override;
    virtual void LuaObjectSetString(std::string key, std::string value) override;
    virtual void LuaObjectSetInt(std::string key, int value) override;
    virtual void LuaObjectSetBool(std::string key, bool value) override;
    virtual void LuaObjectSetDouble(std::string key, double value) override;
};

LuaObject作为基类使用,也是和Lua脚本交互的接口。每个对象对应一个回调函数(如Update),在不同事件触发时对其传入不同字符串,这样脚本就可以进行判断。脚本通过一些注册的全局函数用来和LuaObject交互,在执行脚本时LuaObject也会维护静态的当前LuaObject实例,这样就可以知道脚本获取的属性是哪个是哪个实例的。
A继承自LuaObject,override了一些方法:

获取Lua脚本路径
std::string getLuaScriptFilePath()

获取回调函数名
std::string getUpdateFunctionName()

返回属性给Lua脚本
std::string LuaObjectGetString(std::string key)
int LuaObjectGetInt(std::string key)
bool LuaObjectGetBool(std::string key)
double LuaObjectGetDouble(std::string key)

Lua脚本设置属性到这个类
void LuaObjectSetString(std::string key, std::string value)
void LuaObjectSetInt(std::string key, int value)
void LuaObjectSetBool(std::string key, bool value)
void LuaObjectSetDouble(std::string key, double value)

在Lua中使用这些全局函数:

获取当前对象属性
rjcblib_getstring
rjcblib_getint
rjcblib_getbool
rjcblib_getdouble

设置当前对象属性
rjcblib_setstring
rjcblib_setint
rjcblib_setbool
rjcblib_setdouble

通过cocos2d打印日志
rjcblib_log

KVObject

这个类通过std::map<>管理属性,提供灵活的属性变更能力,能够直接将Json数据解析。

class KVObject
{
public:
    std::map<std::string, int> *intKV;
    std::map<std::string, std::string> *stringKV;
    std::map<std::string, bool> *boolKV;
    std::map<std::string, double> *doubleKV;
    KVObject();
    ~KVObject();

    //查询是否包含KEY,T - 支持类型
    template<typename T>
    bool hasValue(std::string key)
    {
        do
        {
            if (typeid(T) == typeid(std::string))
            {
                if (stringKV->find(key) == stringKV->end())
                    break;
            }
            if (typeid(T) == typeid(int))
            {
                if (intKV->find(key) == intKV->end())
                    break;
            }
            if (typeid(T) == typeid(bool))
            {
                if (boolKV->find(key) == boolKV->end())
                    break;

            }
            if (typeid(T) == typeid(double))
            {
                if (doubleKV->find(key) == doubleKV->end())
                    break;
            }
            return true;
        } while (false);

        return false;
    }

    //直接获取值,KEY应是存在的,T - 支持类型
    template<typename T>
    void getValueDirect(std::string key, GenericValue& out)
    {
        if (typeid(T) == typeid(std::string))
        {
            out.String = stringKV->at(key);
        }
        if (typeid(T) == typeid(int))
        {
            out.Int = intKV->at(key);
        }
        if (typeid(T) == typeid(bool))
        {
            out.Bool = boolKV->at(key);
        }
        if (typeid(T) == typeid(double))
        {
            out.Double = doubleKV->at(key);
        }
    }

    //获取值,检测KEY是否存在,T - 支持类型
    template<typename T>
    FUNC_RETURN_TYPE getValue(std::string key,GenericValue & out)
    {

        auto hasvalue = hasValue<T>(key);
        if (!hasvalue)
            return FUNC_RETURN_VALUE_NOT_FOUND;
        getValueDirect<T>(key, out);
        return FUNC_RETURN_VALUE_SUCCESS;
    }

    //直接设置值,KEY应是存在的, T - 支持类型
    template<typename T>
    void setValueDirect(std::string key, const GenericValue& in)
    {
        if (typeid(T) == typeid(std::string))
        {
            stringKV->at(key) = in.String;
        }
        if (typeid(T) == typeid(int))
        {
            intKV->at(key) = in.Int;
        }
        if (typeid(T) == typeid(bool))
        {
            boolKV->at(key) = in.Bool;
        }
        if (typeid(T) == typeid(double))
        {
            doubleKV->at(key) = in.Double;
        }
    }

    //直接插入值,KEY应是不存在的, T - 支持类型
    template<typename T>
    void insertValueDirect(std::string key, const GenericValue& in)
    {
        if (typeid(T) == typeid(std::string))
        {
            stringKV->insert(std::pair<std::string, std::string>(key, in.String));
        }
        if (typeid(T) == typeid(int))
        {
            intKV->insert(std::pair<std::string,int>(key,in.Int));
        }
        if (typeid(T) == typeid(bool))
        {
            boolKV->insert(std::pair<std::string,bool>(key,in.Bool));
        }
        if (typeid(T) == typeid(double))
        {
            doubleKV->insert(std::pair<std::string,double>(key,in.Double));
        }
    }

    //设置值,检测KEY是否存在, T - 支持类型
    template<typename T>
    FUNC_RETURN_TYPE setValue(std::string key, const GenericValue& in)
    {
        auto ret = hasValue<T>(key);
        if (!ret)
            insertValueDirect<T>(key, in);
        else
            setValueDirect<T>(key, in);
        return FUNC_RETURN_VALUE_SUCCESS;
    }

    /*
    解析RapidjsonGenericValue
    RapidjsonGenericValueSelfType - RapidjsonGenericValue的类型
    示例:
    obj.parseRapidjsonGenericValue<decltype(arg)>(arg)
    */
    template<typename RapidjsonGenericValueSelfType>
    void parseRapidjsonGenericValue(RapidjsonGenericValueSelfType &gv)
    {
        if (!gv.IsObject())
        {
            return;
        }

        for (auto ite = gv.MemberBegin();ite != gv.MemberEnd();ite++)
        {
            if (ite->value.IsInt())
            {
                intKV->insert(std::pair<std::string, int>(ite->name.GetString(), ite->value.GetInt()));
            }
            if (ite->value.IsString())
            {
                stringKV->insert(std::pair<std::string,std::string>(ite->name.GetString(), ite->value.GetString()));
            }
            if (ite->value.IsBool())
            {
                boolKV->insert(std::pair<std::string,bool>(ite->name.GetString(), ite->value.GetBool()));
            }
            if (ite->value.IsDouble())
            {
                doubleKV->insert(std::pair<std::string, double>(ite->name.GetString(), ite->value.GetDouble()));
            }
        }
    }
};

如何使用:

这个类目前(2016-3-6)支持`int`、`bool`、`double`、`std::string`类型的属性管理,存取方法需要传入对应的类型作为模板参数如`instance.getValue<int>(key,out)`,相关方法在代码中均有说明。

矩阵对象管理

通过矩阵的方式管理二维对象:

template<typename DataType_MustBeTypeOnRef>
class Matrix
{
private:
    Matrix() :data(nullptr), height(0), width(0)
    {

    }
    DataType_MustBeTypeOnRef*** data;
public:
    int height;
    int width;
    static Matrix<DataType_MustBeTypeOnRef>* create()
    {
        auto t = new Matrix<DataType_MustBeTypeOnRef>();
        return t;
    }

    bool init(int height, int width)
    {
        this->height = height;
        this->width = width;
        data = new DataType_MustBeTypeOnRef**[height];
        for (int y = 0;y < height;y++)
        {
            data[y] = new DataType_MustBeTypeOnRef*[width];
            for (int x = 0;x < width;x++)
            {
                data[y][x] = nullptr;
            }
        }
        return true;
    }
    inline void set(int y, int x, DataType_MustBeTypeOnRef* data)
    {
        this->data[y][x] = data;
        data->retain();
    }
    inline DataType_MustBeTypeOnRef* get(int y, int x)
    {
        return this->data[y][x];
    }
    inline void remove(int y, int x)
    {
        if (this->data[y][x] != nullptr)
        {
            this->data[y][x]->release();
            this->data[y][x] = nullptr;
        }
    }
    virtual ~Matrix()
    {
        if (data != nullptr)
        {
            for (int y = 0;y < height;y++)
            {
                for (int x = 0;x < width;x++)
                {
                    remove(y, x);
                }
                delete[] data[y];
                data[y] = nullptr;
            }
            delete[] data;
            data = nullptr;
        }
    }
};

如何使用:

Matrix<Object>* matrix = Matrix<Object>::create();
matrix.init(10,10);
set..
get..
remove..
delete matrix;

注意Object类型须继承自cocos2d::ref,Matrix<>会进行内存管理。

基于ZYNQ7020芯片(黑金开发板AX7020)之AXI-FULL DDR的PL与PS交互操作。 在该工程中我们使用了PS端的串口接收功能,PS端串口接收和发送分别有一个64字节的FIFO,但是因为串口接收阈值设置为16,所以固定接收16个字节数据后才会发生中断。此测试工程得到以前知识的总结和各大网友的支持,只希望可以为学习的你更进一步,大家一起学习才是真的开心。加油,国产芯片之路。 阅读详情

相关推荐

从Datasheet到可用的Verilog模块:手把手教你为N25Q128 SPI Flash写状态机驱动

本文详细介绍了如何从Datasheet到实现可用的Verilog模块,手把手教你为N25Q128 SPI Flash编写状态机驱动。文章涵盖SPI Flash的核心工作机制、数据手册解析方法、Verilog状态机设计实践以及调试与性能优化技巧,特别适合FPGA开发者和硬件设计工程师参考。

weixin_30596023的博客 176

一个单机棋盘式半即时解谜RPG的开发与反思、1

前言过年这几天写了几篇Angular2的开发笔记,算是有点“不务正业”,这次为大家带来我正在参与开发的一款游戏。这个小的系列大概有三、四篇组成,随着项目进展我会把这个坑填上。系列的内容是从程序的角度观察和反思这个游戏,包括它构建的基本思想和设计、编码过程中遇到的困难、重构来降低复杂度等。这个项目目前仅依赖于cocos2d,实际上他就是使用cocos2d来作为引擎的。需要说明的是,这个系列记述的是软件的开

ruojianll的博客 928

故障排查:OpenClaw 更新后 feishu 插件路径失效的解决方法

OpenClaw 更新后 feishu 插件路径失效的解决方法发现问题→ Gateway 启动失败,报插件路径错误定位原因→ OpenClaw 目录结构变化,→解决问题→ 更新为正确的路径验证修复→ 使用确认一切正常。

刘一说的IT专栏 1305

一个单机棋盘式半即时解谜RPG的开发与反思、3

综述游戏核心部分目前完成了Json数据载入、Lua调用、大地图的显示、玩家移动、墙壁阻断这些内容。结构为GBase(基础设施:数据类、实例类、宏定义)、Logic(主要逻辑实现)、UI(用户接口)。GBase-helper: GGameLoader , GManager , GObject GBase-data: GItem , GMap , GPackage GBase-instance: GIn

ruojianll的博客 1057

解锁PyCharm+Deepseek:本地部署AI编程超能力

在本次探索中,我们成功地在 PyCharm 中实现了 DeepSeek 的本地化部署,这一过程虽然涉及多个步骤,但每一步都为我们开启 AI 编程大门奠定了基础。从安装最新版 PyCharm,确保我们拥有一个功能强大且兼容性良好的开发环境,到注册 DeepSeek 账号并获取 API Key,这是连接我们与强大 AI 能力的关键纽带。接着,在 PyCharm 中安装 Continue 插件并进行精细配置,让 DeepSeek 能够深度融入我们的编程流程。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 5548

10、犹豫双模糊TOPSIS算法:原理与实例解析

本文介绍了犹豫双模糊TOPSIS算法的基本原理与应用步骤,结合中国四家纺织公司的案例,详细解析了从构建犹豫双模糊决策矩阵、归一化处理、专家信息聚合,到确定正负理想解、计算距离与相对贴近度系数的完整决策流程。该方法有效应对决策者在评价过程中的犹豫性,适用于财务评估、项目选择等复杂多属性决策场景,具有较强的实用性和推广价值。

yhn45678901的博客 122

【Lua 进阶系列】从调用栈查询到 Hook(钩子):一文理解 Lua 虚拟机的事件回调机制

本文深入解析 Lua 的 Hook 机制,揭示其如何在不修改业务代码的前提下,实现函数调用追踪、行级监控与执行控制。通过对比 debug.getinfo() 和 traceback() 的主动查询局限,引出 Hook 的自动触发优势——基于虚拟机执行事件(call/return/line/count),结合 debug.sethook() 实现解耦式调试。文章以 Reactor 模型类比,阐明 Hook 的事件驱动本质,并梳理注册对象(线程)、监听内容与回调分发逻辑,为工程化调试提供高效方案。

努力努力再努力wz的博客 742

使用verilog设计实现QR分解

QR(正交三角)分解法是求一般矩阵全部特征值的最有效并广泛应用的方法,一般矩阵先经过正交相似变化成为Hessenberg矩阵,然后再应用QR方法求特征值和特征向量。 使用verilog对QR实现方法进行设计并进行功能仿真: 如下: 顶层模块代码: module TOP( H1R, H1I, H2R, H2I, H3R, H3I, H4R, H4I, clk, rst_n, Y1R, Y1I, Y2R, Y2I, X1R, X1I, X2R, X2I ); parameter width = 16; // I

QQ_778132974的博客 2150

Lua 热更新不生效:改完文件线上仍是旧逻辑,package.loaded 与 upvalue 重绑定详解

写法 1 只让"自己手里那份"变新,其他持有者停在旧版本,因为它们的槽没有被改过。运行期累积在表上的字段在写法 1 下会一起消失,因为新表是重新执行模块体造出来的,模块体里没有这些字段。写法 2 改的是同一张表,所有持有者同时看到新代码,新表里没有的字段不会覆盖老表上的。写法 2 解决的是一个 VM 内部多处引用的问题,不解决跨服务一次性生效的问题。函数对象没换,但它每次调用都去读槽,所以槽一改,行为就变。写法 1 换掉的是槽里装的东西,老表还在,只是没人指向它。写法 2 不碰槽,改的是表里面的字段。

m0_74234485的博客 272

ORB-SLAM2算法4之KITTI开源数据集运行ORB-SLAM2生成轨迹并用evo工具评估轨迹

ORB-SLAM2算法1 已成功编译安装ORB-SLAM2到本地,本篇目的是用KITTI开源数据来运行ORB-SLAM2,并生成轨迹,最后用evo评估工具来评估ORB-SLAM2生成的轨迹和真值轨迹。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 2326

LangGraph教程8:LangGraph流式处理

流式处理可显著提升基于LLM应用的响应性。LangGraph支持两种流式模式:values模式返回每一步的完整结果,适合需要完整上下文处理的场景;updates模式仅返回增量变化,适用于实时更新需求。示例代码展示了如何用create_react_agent实现这两种模式,其中values模式完整记录处理流程,updates模式逐步输出结果。通过异步迭代输出流,开发者可以灵活选择适合应用场景的流式处理方式。

Cachel Wood的博客 620

【Lua进阶系列】Lua 面向对象编程:从 Table 到类:构造函数、继承、多态、多继承与封装

Lua虽无原生class语法,但通过Table、函数、元表(__index)与闭包等机制,可实现封装、继承与多态。核心思想是:用Table表示对象,将状态与方法分离;利用__index实现公共方法共享;通过元表链支持继承与重写;结合闭包隐藏私有状态。最终,以灵活组合原生特性,构建出完整的面向对象模型。

努力努力再努力wz的博客 604

论deepseek软件底层原理

如处理医学文本时,将任务分配给擅长医学知识处理的专家,避免通用模块处理的低效性,极大提升计算效率与任务处理的针对性。教师模型复杂且强大,学生模型结构简单。协作处理:多模块协作时,建立数据流通与交互机制,各模块按顺序或并行处理数据,不断传递与更新中间结果,共同完成复杂任务。(一)输入处理与任务判断 输入预处理:接收输入数据,如用户文本提问,首先进行清洗,去除噪声数据、特殊字符等。任务分类:通过MoE架构“路由器”,依据输入数据特征,判断任务所属领域与类型,如文本分类、情感分析等,为后续处理模块选择提供依据。

欢乐打代码! 2738

Skynet 热更新三条通道:clearcache、inject、injectcode 的粒度与代价

从日志里找出报错时的服务地址和文件行号,确认要改的是哪个服务里的哪个模块。还有一个容易忽略的限制:它收集的是「函数的 upvalue 里的 table」。在 A 里执行一次模块 reload,A 变,B 不变——B 是另一个 VM,它那份表从头到尾没被碰过。局部变量在栈帧上,不挂在任何函数的 upvalue 里,收集不到。在 skynet 里做热更,先要分清"没生效"是哪一层断的:文件没被读到、模块没重新 require、还是补丁没送到目标服务。要一次覆盖全部服务,只有重启进程,或者把每个服务都执行一遍。

m0_74234485的博客 245

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【政安晨】嵌入式AI开发实践 —— ESP-Claw 深度拆解:把 AI Agent 塞进 $5 芯片,它是怎么“看见“并“握住“硬件的

最近一个月,我几乎把 Espressif 新推的 ESP-Mosaico 开发板(2026-10-20 发布,基于全新 RISC-V 双核 ESP32-S31)和它背后的 ESP-Claw 智能体框架翻了三遍——官网、GitHub 全部 6 个仓库、ESP-Claw 官方文档,外加 arXiv 上端侧 Agent 的几篇论文。ESP-Claw 不是"在 ESP32 上跑大模型",而是把大模型当成一个会下棋但棋力不稳的对手——能算的地方绝不让它算,不能算的地方只许它走一个格。

政安晨——致力于AI人工智能数字互动领域 336

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Redis Lua 原子限流:Lua 脚本、竞态条件与并发控制

Lua是轻量级可嵌入脚本语言,Redis内置Lua5.1解释器,支持通过EVAL或SCRIPTLOAD执行脚本,实现多命令原子操作。利用redis.call()调用Redis命令,结合KEYS和ARGV传参,可将读取、判断、更新等操作封装为原子逻辑,有效避免限流中的竞态条件。固定窗口限流通过Lua脚本实现计数与过期控制,保证操作连续性。但脚本不可回滚,需避免复杂逻辑;执行时间过长会阻塞Redis,且需满足Cluster哈希槽约束。实际应用中还需考虑故障降级策略。

Joy T的博客 131

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【Lua 进阶系列】从 C++ 对象到 Lua 变量:一文理解 userdata、Lua 栈与元表绑定机制

本文从游戏服务端分层架构出发,解析 Lua 中 userdata 的设计意义。尽管 Lua 有 Table 可模拟对象,但 userdata 专为承载 C/C++ 自定义数据而生,实现 Lua 与原生代码间高效、安全的数据交互。通过 TValue 与 Udata 机制,区分 Full 与 Light userdata,结合元表实现面向对象调用,既保留性能优势,又提升封装性。最终揭示:userdata 是连接脚本层与宿主层的关键桥梁。

努力努力再努力wz的博客 188

【Lua进阶系列】Lua 调试机制详解:从虚拟机调用栈、错误传播到 debug 库

本文深入解析 Lua 调试机制的底层原理,强调调试并非重新执行程序,而是利用虚拟机已维护的运行时状态与编译阶段保留的调试信息。通过分析函数调用栈、字节码与源码行号映射关系,揭示 debug 库函数(如 getinfo、getlocal、traceback)如何读取调用链与局部变量。同时说明错误传播机制及 pcall/xpcall 的保护作用,并指出剥离调试信息虽可减小文件体积,但会削弱调试能力。核心在于理解:调试是基于虚拟机运行时状态与编译辅助信息的协同结果。

努力努力再努力wz的博客 269

【Lua进阶系列】从全局环境到 _ENV:理解全局变量解析、环境隔离与闭包生命周期

本文深入解析Lua为何无需定义即可直接调用print、table.insert等函数。核心在于:Lua运行时维护默认全局环境表,标准库通过C API注册为函数值,供所有Chunk共享。多个脚本共用同一环境,实现全局变量互通;而局部变量受词法作用域保护。通过_ENV机制,可灵活切换执行环境,提升模块化与安全性。最终,全局访问本质是环境表的键值查找,遵循表的读写规则。

努力努力再努力wz的博客 456

在多线程与多协程环境下驯服 Lua 虚拟机

在C++多协程环境下安全运行Lua,需遵循“线程绑定、栈隔离、重入保护”三铁律。通过lua_newthread创建协程专属栈,配合luaL_ref管理生命周期,确保主虚拟机不受干扰。禁止复用lua_State,避免闭包污染;沙盒环境应通过lua_setupvalue隔离_ENV;优化GC参数并主动触发垃圾回收,缓解高并发下的内存压力。最终实现万级并发下微秒级延迟的稳定脚本执行,打造高性能、可扩展的Lua底座。

draracle的巢穴 305

快速上手:如何调用大模型

本文介绍了如何通过HTTP请求或OpenAI SDK调用阿里云百炼平台的大模型。重点讲解了使用Postman和Python代码调用qwen3-max模型的方法,强调需配置API Key与base_url(https://dashscope.aliyuncs.com/compatible-mode/v1),并推荐将API Key设为环境变量以保障安全。同时说明OpenAI库可通过兼容模式调用第三方模型,最后演示了大模型无记忆特性及通过维护对话历史实现“记忆”的实践方法。

2301_80002260的博客 178

Python22-MCP-PostMan调试-Streamable

Python22-MCP-PostMan调试-Streamable

感谢所有乐于奉献的人,在此不一一具名 141

Python21-MCP代码修正

Python21-MCP代码修正

感谢所有乐于奉献的人,在此不一一具名 207

使用redis实现分布式锁(面试千题)

redis实现分布式锁

qq_40358025的博客 221

Postman 自动给 Claude Code、Codex、Cursor 装插件怎么查和卸载:本机实测 5 处痕迹(Postman 12.34)

Postman 桌面版升级时会自动给 Claude Code、Codex、Cursor 装插件。本文在 macOS 上实测 Postman 12.34 留下的 5 处痕迹:日志记录、Claude Code 插件和 SessionStart 指令、Codex 配置、Cursor 插件目录、Postman CLI,给出只读自查脚本和逐个卸载命令。

u011831527的博客 532

gta5传承版fivem ai陪玩 成功部署经验

仅启动 mapmanager、spawnmanager、basic-gamemode 还不够,需要包含有效出生点的 map 资源。FiveM Lua 与单机 ScriptHookV 的 API、加载方式不同,不能直接把资源复制进游戏目录。多个 3 秒心跳可能在同一条 LLM 请求期间同时进入,需串行处理并在锁内重判是否到期,避免连说几句。没有候选框时,记事本输入后 Ctrl+V 是临时绕法,不代表已修复系统输入法显示。保存源码与经验,忽略许可证、密钥、游戏文件、缓存、日志与第三方二进制。

brepnet uvnet 164
上一篇: 一个单机棋盘式半即时解谜RPG的开发与反思、1
下一篇: 一个单机棋盘式半即时解谜RPG的开发与反思、3
若简LL
博客等级 码龄11年 8粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值