鱼C论坛

 找回密码
 立即注册
查看: 1256|回复: 1

[技术交流] 流星蝴蝶剑地图信息提取

[复制链接]
发表于 2020-1-5 23:35:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 逾越书 于 2020-1-5 23:47 编辑

流星蝴蝶剑是2002年出的单机游戏,
我们现在对里面的地图信息进行读取,做交流学习之用
定义地图结构(自定义)
struct MeteorMap
{
        /*ReadOne*/
        int _mapFlag = 0x05;                        //1. ( 4个char ) 05 00 00 00 地图标记---------
        int mapNumber=0xF0000000;                                        //2. ( 4个char ) 0A 00 00 00 编号
        int mapNameSize;                                //3. ( 4个char ) 07 00 00 00 名字长度
        /*ReadTwo*/
        char* mapName = NULL;                        //4. (mapNameSize 个char) D6 D3 C8 E9 B6 B4 00 地图名字 char mapName[mapNameSize];
        int snNameSize;                                        //5. ( 4个char ) 63 4E 31 33 31 00 sn长度
        /*ReadThree*/
        char* snName = NULL;                        //6. ( snNameSize 个char) 63 4E 31 33 31 00 sn名字 char snName[snNameSize];
        char _plotFlagChar1 = 0x01;                //7(1个char) 01 00 00 00  辅助标记-------- -
        int _NULL = 0x00;                                //8. ( 4个char ) 00 00 00 00  暂时理解为填充0---------
        int _plotFlag3 = 0x03;                        //9. ( 4个char ) 03 00 00 00  辅助标记 ---------
        int mapDisplay;                                        //10. ( 4个char ) 0B 00 00 00  将0B改成0A此地图将不会显示
        int modeDisplay;                                //11.( 4个char ) 11 00 00 00  剧情模式 按逻辑位或 (剧情|死斗|暗杀|护城|劫镖|盟主)
        int __NULL = 0x00;                                //12.( 4个char ) 00 00 00 00  暂时理解为填充0---------
        int _plotFlagC = 0x0C;                        //13.( 4个char ) 0C 00 00 00  辅助标记 ---------
        int musicNum;                                        //14.( 4个char ) 05 00 00 00  音乐编号 ( 05 ) == (s5.mp3)
        int ___NULL = 0x00;                                //15.( 4个char ) 00 00 00 00  辅助标记 ---------
        int _plotFlag1 = 0x01;                        //16.( 4个char ) 01 00 00 00  辅助标记 ---------
        int modeList;                                        //17.( 4个char ) 03 00 00 00  剧情任务排号
        int curMapSize = 0x41;                        //18.( 4个char ) 0x41+mapSize+snSize  当前地图长度(非常重要的元素)//这个值会写入数组地图信息
        int ____NULL = 0x00;                        //19.( 4个char ) 00 00 00 00  辅助标记 ---------
};
接着用数组保存地图信息 MeteorMap mapAllList[999];        //全部地图为999
char mapAllName[999][30];        //地图名字 "一线天"
char snAllName[999][20];                //地图表示 "SN03"
接下来是部分是读取过程:

        CFile file;
        CString filePath = _T("d:\\Meteor.res");
        MeteorMap map;        //临时存储一个地图数据
        int Arr[12] = { 0 };        //次要成员变量存储
        char snName[30] = { 0 };        // str "钟乳洞"
        char mapName[20] = { 0 };        // str "SN01"
        int mapEntryAddress = 0xEA1E;        //第一个地图开始位置偏移
        file.Open(filePath, CFile::modeRead | CFile::modeReadWrite);        //打开文件
        file.Seek(mapEntryAddress, CFile::begin);        //定位地图开始位置
        int index = 0;
        for ( index = 0;index<999;index++)
        {
                /*ReadOne*/
                file.Read(&map._mapFlag, 4);        //读标志
                file.Read(&map.mapNumber, 4);                //编号
                file.Read(&map.mapNameSize, 4);                //名字长度
                if ((0x00000005 != map._mapFlag) | (map.mapNameSize <= 4))        //标志不存在结束
                {
                        break;
                }
                /*ReadTwo*/
                file.Read(mapName, map.mapNameSize);        //Read名字
                strncpy_s(mapAllName[index], mapName,30);        //临时mapname copy到列表数组里面
                file.Read(&map.snNameSize, 4);                //SN01长度
                /*ReadThree*/
                file.Read(snName, map.snNameSize);
                strncpy_s(snAllName[index], snName, 20);

                file.Read(&map._plotFlagChar1, 1);
                for (int i = 0; i < 12; i++)
                {
                        file.Read(&Arr, 4);                //后面成员一次读取4个char 总共12次, 读完一个地图

                }
                map.mapDisplay = Arr[2];        //将0B改成0A此地图将不会显示
                map.modeDisplay = Arr[3];        //剧情模式 按逻辑位或 (剧情|死斗|暗杀|护城|劫镖|盟主)
                map.musicNum = Arr[6];                //音乐编号 ( 05 ) == (s5.mp3)
                map.modeList = Arr[9];                //剧情任务排号
                map.curMapSize =0x41+map.mapNameSize+map.snNameSize;
                mapAllList[index] = map;        //        存储  MeteorMap  结构体
                lastMap = map;                                //把当前地图当做最后一个地图
                map._mapFlag = 0;//如果存在标志,置为0,方便下次读取
        }

        file.Close();

问:读入过程为何分为三部分?
答:。因为第2次读取位置根据第1次map.mapNameSize值决定,同样,第3次读取位置根据第一次 map.snNameSize值决定,不然,定位不对,无法正确读到下一个地图

现在信息已经保存在mapAllList数组里面了,接下来就是把mapAllList成员信息显示

        USES_CONVERSION;
        CString str;
        int i = m_ListBox.GetCurSel();
        SetDlgItemText(IDC_EDIT1, A2T(mapAllList.mapName));
        SetDlgItemText(IDC_EDIT2, A2T(mapAllList.snName));
        str.Format(_T("%d"), mapAllList.modeDisplay);
        SetDlgItemText(IDC_EDIT3, str);
        str.Format(_T("%d"), mapAllList.modeList);
        SetDlgItemText(IDC_EDIT4, str);
        str.Format(_T("%d"), mapAllList.curMapSize);
        SetDlgItemText(IDC_EDIT5, str);
        str.Format(_T("%d"), mapAllList.musicNum);
        SetDlgItemText(IDC_EDIT6, str);

讲数组SetDlgItemText(IDC_EDIT1, A2T(mapAllList.mapName));放入编辑框显示,i数值就是地图meteor.res编号
下面显示出来主要部分,其它部分可以通过MeteorMap结构相应显示 。
QQ:1947767412
Met.png
MET2.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-4-9 10:36:30 | 显示全部楼层
自己顶起来!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-1 17:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表