好用的地图编辑器 gridarta

这段时间在为网游教程找一个相匹配的地图编辑器,虽然几乎每个游戏都有地图编辑器,但我却未能找到比较满意的,绝大部分的地图编辑器都是不公开的,还有很大一部分地图编辑器都是只能在指定的游戏中使用的,剩下的只有歪瓜劣枣了。我找了几个候选的,mappy,hust,gridarta,并分别试用了下:

mappy,功能强大,支持种类多,支持多层,问题是,它怎么就不支持层透明呢?新建一个层就看不到下面的层了,还有,地图分块,是按照竖向排列的,无法在原始图上选择,结果超级的浪费眼睛不说,还是黑灯瞎火的。放弃掉。值得一提的是,这个有pro版,需要花钱的,我没钱,不知道情况如何。反正被我第一个pass掉了。

hust,应该是国产的,版本号挺高,4.2了,我创建了一个比较大的图,512×512的,这下悲剧了,地图块8×8的,太小了,想要放大?我没有找到明显的地方。只支持方块,无斜视角。我个人比较偏好斜视角的,但苦于素材难找,觉得方块的也将就着吧。但也不要大图无法创建啊。尝试了几下,考虑到身体健康,只好放弃了(非常不甘心,我本来期望挺高的)。

gridarta,我其实下载的是daimonin的mapmaker,考虑到编译环境等等,在用之前,我已经做好了失败的准备,甚至考虑着自己也写一个了。结果发现还不错,直接可以了,还附带有大量的资源(可惜没有我最想要的外景的资源,比如房子什么的)。斜45度,支持插件操作,默认保存的都是文本,本来准备写一个数据转换的,但又一想,先看看插件如何吧。然后看它的README,才发现原来是gridarta啊,里面已经有了一个插件了,看了下代码,java的,但关于这方面的文档几乎没有,gridarta也找到(或许我粗心)。只好将gridarta的代码svn co了,然后大致的浏览,分析下各个部件的作用,而外国人写的java项目,代码的位置都变态的深,模块又多,让我狂点鼠标。然后写个测试的插件,折腾了一天,大约明白怎么回事了,然后今天,写了下数据的导出。稍后给出源代码。总算是找到一个比较满意的了:

下面是插件的代码:

       //input your beanshell Code
import net.sf.gridarta.model.gameobject.GameObject;
import net.sf.gridarta.model.io.RecursiveFileIterator;
import net.sf.gridarta.model.map.validation.ErrorCollector;
import net.sf.gridarta.model.map.validation.errors.ValidationError;

void log(String message) {
        print(message);
}
void inttobyte(byte[] abyte, int offset, int param) {
        abyte[offset+0] = (byte)((param>>24)&0xFF);
        abyte[offset+1] = (byte)((param>>16)&0xFF);
        abyte[offset+2] = (byte)((param>>8)&0xFF);
        abyte[offset+3] = (byte)((param)&0xFF);
}
void processMap(String outFile) 
{

        map = mapManager.getCurrentMap();
        if (map == null) {
                log(mapPath + ":");
                log("- cannot load map file "+mapFile);
                return;
        }
        Vector out_object = new Vector();
        Vector cell_object = new Vector();
        mapmode = map.getMapModel();
        archtype = mapmode.getMapArchObject();
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(outFile));
        Iterator it = mapmode.getAllGameObjects().iterator();
        while(it.hasNext()) {
                gameobject = it.next();
                /*
                log(""+gameobject.getMapX()+","+gameobject.getMapY()+"="+gameobject.getFaceObjName()+",bestName="
                    +gameobject.getBestName()+",["+gameobject.getMinX()+","+gameobject.getMinY()+","+gameobject.getMaxX()
                    +","+gameobject.getMaxY()+"],archetype.folder="+gameobject.getArchetype().getEditorFolder()+",Archename="+gameobject.getAnimName());
                */
                String name;
                if (gameobject.getAnimName() != null) {
                        name = gameobject.getArchetype().getEditorFolder()+gameobject.getAnimName()+".ani";
                } else 
                        name = gameobject.getArchetype().getEditorFolder()+gameobject.getFaceObjName()+".png";
                int found = -1;
                for (int i = 0; i < out_object.size(); i++) {
                        String temp = (String)(out_object.elementAt(i));
                        if (name.equals(temp)) {
                                found = i;
                                break;
                        }
                }
                if (found == -1) {
                        found = out_object.size();
                        out_object.addElement(name);
                }
                byte[] buf = new byte[4];
                inttobyte(buf, 0, gameobject.getMapX());
                for (int i = 0; i < 4; i++) {
                        cell_object.addElement(buf[i]);
                }
                inttobyte(buf, 0, gameobject.getMapY());
                for (int i = 0; i < 4; i++) {
                        cell_object.addElement(buf[i]);
                }
                inttobyte(buf, 0, found);
                for (int i = 0; i < 4; i++) {
                        cell_object.addElement(buf[i]);
                }
                buf = null;
        }
        int length = cell_object.size();
        length += 4;//cell_object.size
        length += 4;//out_object.size
        for (int i = 0; i < out_object.size(); i++) {
                length += 4; //string_length
                length += ((String)out_object.elementAt(i)).length();
        }
        length += 8;//mapx, mapy
        length += 4;//crc32
        byte[] out = new byte[length];
        int index = 4;

        inttobyte(out, index, archtype.getMapSize().getWidth());
        index += 4;
        inttobyte(out, index, archtype.getMapSize().getHeight());
        index += 4;
        inttobyte(out, index, out_object.size());
        index += 4;
        for (int i = 0; i < out_object.size(); i++) {
                String temp = (String)(out_object.elementAt(i));
                int slength = temp.length();
                inttobyte(out, index, slength);
                index += 4;
                System.arraycopy(temp.getBytes(), 0, out, index, slength);
                index += slength;
        }
        inttobyte(out, index, cell_object.size());
        index += 4;
        for (int i = 0; i < cell_object.size(); i++) {
                out[index] = (byte)(cell_object.elementAt(i));
                index++;
        }
        dos.write(out, 0, length);
        dos.close();
        out = null;
        list = null;
        mapManager.release(map);
        log("process over!!");
}
String mapDefaultFolder = globalSettings.getMapsDirectory().getPath();
String rootDirectory = mapDefaultFolder;
log(rootDirectory);
String OutFile = outFile.length() == 0 ? "temp.bin" : outFile;
processMap(OutFile);
       

简单说下使用方法,在菜单中选择编辑插件,新建一个插件,然后添加一个String类型的变量,命名为outFile,在code里面贴上上面的代码,然后打开一个地图,运行新建的插件,会将数据导出为二进制的。文件的结构如下:

       {CRCCode:32,
                         MapWidth:32,
                        MapHeight:32,
                        object_num:32,
                        obj_list:[
                         {file_name_length:32,
                         file_name_string: file_name_length
                         }
                         ],
                         cell_num:32,
                         cell: [
                               {cell_x:32,
                               cell_y:32,
                               cell_object_index:32
                               }]
                        }
     

上面的内容中,CRCCode未添加,只保留了空间,改天找下java的crc代码加上。我将动画的后缀名命名为.ani,图像的为png,其他的可能有些错误(比如event或者msg或者ai之类的),到时候再说了。现在仅作为一个参考。

发布者

rix

如果连自己都不爱自己,哪还有谁来爱你