• Cocos2d-x 3.2 学习笔记(十五)保卫萝卜 场景与数据


         保卫萝卜~场景的思路以及数据的存储。
         学习要写笔记,记录自己的步骤。
    一、场景构建Tiled
         关于Tiled网上有一大堆的教程,这个比较好用,特别是构建塔防类的游戏极其简单,我也是爽了一把。
    场景的资源目录结构比较好做,根据场景id进行区分目录。
    场景对应目录:
     
      然后使用Tiled构建基本的场景
     
     
         这里有
         1、两个图块层(底图层、路径层)       2、三个对象层(可行路径对象格、障碍对象格、建筑对象格)
    格子使用80X80,跟资源的大小刚好合适……导出.tmx文件,加入舞台就能看到成果了,顿时觉得比较爽。
    Cocos2dx已经封装的 TMXTiledMap类使用起来也是顺手至极啊。
     
         TMXTiledMap::create(tmxUrl)
     
    创建一个TMXTiledMap对象直接addChild至场景就可以看到效果,如果要获得对象层的数据,通过name就能获得。通过处理对象层的数据(坐标,宽高,类型、等属性)就可以搞定场景建筑搭建,怪物行走路径,鼠标可点击区域等,通过格子矩形的判断就能实现场景逻辑部分。
     
      对Tiled的了解不是很多,但是够用就行……
     
    二、数据管理SQLite
     
         数据大概是游戏的命脉啊,可惜自己的数值功力有限,只能设计个自己能用的数据库了,借助于SQLite实现对数据的管理。
    SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。
     
    下载sqlite文件
    下载网址:http://www.sqlite.org/download.html
     
     
     
      这是最新版本。如下图把解压后的三个文件导入项目中就可以开心的使用了。
     
     
    ok,关于创建SQLite数据库的工具也有一大堆,不过我还是喜欢使用   Navicat_Premium_9.1.11 用的爽就行~
     
     
    OK,这样创建好数据库DB文件就好啦,下面使用辅助类就可以完美的 增、删、查、改!
     
    三、自封装DB数据类
     
         关于封装SQLite的类也是有很多的,但是适用自己的才是最好的,封装起来也是比较简单的,不过鉴于自己的c++水平有限……(拿来主义)……在以前在网上找了个工具类,
    后来自己也修改了下,改成自己适用的,贡献下自己修改后的DBUtil类。
     
    #ifndef __DBUtil__
    #define __DBUtil__
    #include <string>
    #include "cocos2d.h"
    #include "sqlite3.h"
    
    using namespace std;
    USING_NS_CC;
    class DBUtil{
    public:
        
        /************************************************************
                封装 sqlite3操作
         ************************************************************/
        //用来创建一个db数据库 db为数据库的名字
        //  打开数据库
        static void initDB(const char *url);
        
        //用来判断表格是否存在
        // name:表示表名
        static bool tableIsExist(string table_name);
        
        
        //用来创建一个表名为name的表格,创建时会先匹配时否有该表的存在如果存在则不创建
        //创建表
        static void createTable(string sql,string table_name);
        
        //用来删除一张表名为name的表格,删除时会先匹配是否有该表的存在如果不存在则不执行删除操作
        //删除表名
        static void deleteTable(string sql,string table_name);
        
        //用来向表中插入一条数据
        //插入一条数据
        static void insertData(string sql);
        
        //用来向表中删除一条数据
        //删除一条数据
        static void deleteData(string sql);
        
        //用来向表中修改一条数据
        // 修改一条数据
        static void updateData(string sql);
        
        //获取表的全部数据
        // 返回记录的条数
        static int getAllData(string table_name,std::function<void(std::map<string,string>)> callback);
        
        //读取一条记录的信息
        /*
         *  此方法是查询方法,pSender()
         */
        static void getDataInfo(string sql,std::function<void(std::map<string,string>)> callback);
        
        //关闭打开的数据库
        static void closeDB();
    };
    
    #endif
    DBUtil.h
    #include "DBUtil.h"
    
    sqlite3 *pDB = NULL;//数据库指针
    char * errMsg = NULL;//错误信息
    std::string sqlstr;//SQL指令
    int result;//sqlite3_exec返回值
    unsigned int _count=0;
    std::map<unsigned int,std::function<void(std::map<string,string>)>> _keyMap;
    
    void DBUtil::initDB(const char *db)
    {
        //打开一个数据库,如果该数据库不存在,则创建一个数据库文件
        result = sqlite3_open(db, &pDB);
        if( result != SQLITE_OK )
            log( "打开数据库失败,错误码:%d ,错误原因:%s
    " , result, errMsg );
    }
    
    
    //tableIsExist的回调函数
    int isExisted( void * para, int n_column, char ** column_value, char ** column_name )
    {
        bool *isExisted_=(bool*)para;
        *isExisted_=(**column_value)!='0';
        return 0;
    }
    
    bool DBUtil::tableIsExist( string table_name )
    {
        if (pDB!=NULL)
        {
            //判断表是否存在
            bool tableIsExisted;
            sqlstr = "select count(type) from sqlite_master where type='table' and name ='"+table_name+"'";
            result =sqlite3_exec(pDB,sqlstr.c_str(),isExisted,&tableIsExisted,&errMsg);
            return tableIsExisted;
        }
        return false;
    }
    
    void DBUtil::createTable( string sql,string table_name )
    {
        if (!tableIsExist(table_name))
        {
            //创建表,设置ID为主键,且自动增加
            result = sqlite3_exec(pDB,sql.c_str(),NULL,NULL,&errMsg);
            if( result != SQLITE_OK )
                log( "创建表失败,错误码:%d ,错误原因:%s
    " , result, errMsg );
        }
        
    }
    
    void DBUtil::deleteTable( string sql,string table_name )
    {
        if (tableIsExist(table_name))
        {
            result = sqlite3_exec(pDB,sql.c_str(),NULL,NULL,&errMsg);
            if( result != SQLITE_OK )
                log( "创建表失败,错误码:%d ,错误原因:%s
    " , result, errMsg );
        }
    }
    
    //@示例语句sqlstr=" insert into MyTable_1( name ) values ( 'data',..... ) ";
    void DBUtil::insertData( string sql ){
        result = sqlite3_exec( pDB, sql.c_str() , NULL, NULL, &errMsg );
        if(result != SQLITE_OK )
            log( "插入记录失败,错误码:%d ,错误原因:%s
    " , result, errMsg );
    }
    
    //@示例语句sqlstr="delete from MyTable_1 where ID = 2";
    void DBUtil::deleteData( string sql )
    {
        result=sqlite3_exec( pDB, sql.c_str() , NULL, NULL, &errMsg );
        if(result != SQLITE_OK )
            log( "插入记录失败,错误码:%d ,错误原因:%s
    " , result, errMsg );
    }
    
    //@示例语句        sqlstr="update MyTable_1 set name='data' where ID = 3";
    void DBUtil::updateData( string sql )
    {
        result = sqlite3_exec( pDB, sql.c_str() , NULL, NULL, &errMsg );
        if(result != SQLITE_OK )
            log( "插入记录失败,错误码:%d ,错误原因:%s
    " , result, errMsg );
    }
    
    
    //getDataCount的回调函数
    int loadRecordCount( void *para, int n_column, char ** column_value, char ** column_name )
    {
        std::map<string,string> data;
        int index;
        for( index = 0 ; index < n_column; index ++ )
        {
            data.insert(std::pair<string,string>( column_name[index], column_value[index] ));
        }
        auto num = *(unsigned int *)para;
        auto callback = _keyMap.at(num);
        if( callback != nullptr )
        {
            callback(data);
        }
        return 0;
    }
    
    int DBUtil::getAllData(string table_name,std::function<void(std::map<string,string>)> callback)
    {
        string sql = "select * from "+table_name;
        _count++;
        _keyMap.insert(std::pair<unsigned int,std::function<void(std::map<string,string>)>>(_count,callback));
        int count=sqlite3_exec( pDB, sql.c_str() , loadRecordCount, &_count, &errMsg );
        return count;
    }
    
    //getDataInfo的回调函数
    int loadRecord( void * para, int n_column, char ** column_value, char ** column_name )
    {
        std::map<string,string> data;
        int index;
        for( index = 0 ; index < n_column; index ++ )
        {
            string str1 = column_name[index];
            if( column_value[index] == NULL )
            {
                log("DBUtil Get Data Value Failure! Table Name Is  '%s'",str1.c_str());
                continue;
            }
            string str2 = column_value[index];
            data.insert(std::pair<string,string>(str1,str2));
        }
        auto num = *(unsigned int *)para;
        auto callback = _keyMap.at(num);
        if( callback != nullptr )
        {
            _keyMap.erase(num);
            callback(data);
        }
        return 0;
    }
    
    void DBUtil::getDataInfo( string sql,std::function<void(std::map<string,string>)> callback )
    {
        _count++;
        _keyMap.insert(std::pair<unsigned int,std::function<void(std::map<string,string>)>>(_count,callback));
        sqlite3_exec( pDB, sql.c_str() , loadRecord, &_count, &errMsg );
    }
    
    void DBUtil::closeDB()
    {
        sqlite3_close(pDB);
    }
    DBUtil.cpp
      这样在数据初始化的时候就可以直接传入表中怪物ID 直接初始化数据
     
    四、总结
     
         有场景编辑器,有数据库,我觉得我终于可以完成我想要的效果了~~开心一把。哈哈哈,不过自己空闲时间也不多啊 惆怅……。
    好想做*******,可惜C++懂得不多……
     
  • 相关阅读:
    LeetCode-198-打家劫舍
    LeetCode-279-完全平方数
    LeetCode-91-解码方法
    Redis RDB 分析工具 rdbtools 说明(转载)
    ftp软件下载,ftp软件到底在哪里下载
    element-ui组件库二次开发——打包、上传npm
    ftp客户端工具,这6款好用的ftp客户端工具,站长们必不可少的常用工具!
    不会用Java Future,我怀疑你泡茶没我快, 又是超长图文!!(转载)
    ftp管理软件,ftp管理软件怎么使用
    Android连载22-自定义广播之标准广播发送(转载)
  • 原文地址:https://www.cnblogs.com/Richard-Core/p/4229224.html
Copyright © 2020-2023  润新知