收起左侧

[教程] 【MOD与扩展攻略】对战地图修改与创建教程

[复制链接]
叉烧要配米线发表于 2017-1-26 08:26:00
本教程是为了配合中华地图册计划寻找对对战地图编辑有兴趣的玩家
叉烧要配米线发表于 2017-1-26 08:31:00
【第一课】地图基本参数设计
195933qxasm2cqsuzazgsf.jpg

作为一张地图,以西伯利亚为例,它具有基本的坐标法则,可以明显看到地图如果被倾斜45度就会是一个中心线对称图形,其坐标系是下图这样的:
195933n1aighgihjawr5i0.jpg

地图正中间为0.5,0.5,最东面为1,1,最西面为0,0,是一个倾斜45度的XY轴坐标系。
こはね发表于 2018-3-2 11:03:00
195936wndffvj0vxlhz2xq.jpg
这个才是正确的地图坐标系,楼主的是错误的
叉烧要配米线发表于 2017-1-26 08:33:00
这一XY轴坐标系参数在地图的参数中起着关键作用,即便是个别使用弧度坐标系统的函数时中心点仍然需要用XY轴坐标系表示。
叉烧要配米线发表于 2017-1-26 08:43:00
195933loe3aaoyltkvdcod.jpg

除了土著佣兵等设定文件以外地图文件基本包括3种,第一种是地图主文件*.XS,是地图的描述文件。第二种是XML,是地图载入画面的内容,注意XML中第一行所规定的文件编码会让使用中文字可能需要转换。第三种是*.dmp.txt,这是在使用过地图后游戏程序自动生成的,其中包括地图所调用过的各个参数的基本结构,偶尔可以参考一下。
叉烧要配米线发表于 2017-1-26 08:45:00
下面我以禅定天下平衡版地图的西伯利亚地图为例来介绍一下地图包含的主要结构。
195934bi8kfxj4fzxxkkkx.jpg
叉烧要配米线发表于 2017-1-26 08:51:00
如果打开XML文件是这样的:
195934gzh1l1atyrra8119.jpg

第一行中的UTF-8代表文件编码,编码建议不修改,因为可能造成汉字乱码。
之后的语法结构主要是标记之间,
detailsText是地图介绍中的说明文字
\n是指回车换行
imagepath是载入地图时的图片
displayName是地图的名称
cannotreplace是指单机游戏是是不是允许选择按照当前分配的随机地图原封不动重玩
loaddetailstext是载入地图时的说明文字
loadBackground是载入地图时的地图背景框
叉烧要配米线发表于 2017-1-26 08:54:00
下面打开XS文件,可以看到最初的内容
195934i3vpf02tvt112u1u.jpg
叉烧要配米线发表于 2017-1-26 09:01:00
include后面的内容表示本地图文件的函数来自这3个文件的设定原型,不过这几个文件在哪我倒是没去找过,下次有机会找出来研究研究,也就是说include让当前的这个地图文件与这3个文件连接在了一起。下面重点是这3个参数的定义。
195934p1z2bwwc2l52h7cl.jpg

PlayerNum是玩家数量,numPlayer是指包含了“大地”的玩家数量,也就是说野外宝藏守护者,鲸鱼,猎物等的势力,theumberTeams是玩家的队伍数。

通常这3个参数是载入地图后自动赋予的,但因为本地图是用来观赏对战用的,所以在地图文件中给他们重新定义。PlayerNum=2意味着只允许前2个玩家出战,因此numPlayer也就被强制=3了(大地势力只有一家,代号是0,玩家1代号是1,玩家2代号是2)
theNumberTeams就不多说了,是势力的数量,这意味着玩家1和玩家2强制为2个不同队伍。也就是说这是一张1V1观察者地图,玩家1与玩家2对战,玩家3到8是观察者。
如果要改为2V2观察者地图那么只要把PlayerNum=4就行了
叉烧要配米线发表于 2017-1-26 09:06:00
195935b9t99ktttt91ptto.jpg

下面这段开始进入程序执行,"void main"是标准的C语言入口,意思就是说在main{}之外你只能定义函数和参数,但在main{}的2个大括号之间,你可以切实执行程序(也可以定义函数和参数,不过在什么地方执行和程序的效率有关)

之后的string XXXX是建立字符串类型的参数 XXXX="xxxx"是将右边的值赋予给这些参数。右边的值都是系统定义好的,代表了实际切确实的意义。

比如tradeRouteType=“water”意味着贸易路线是水中型的,不会因为西伯利亚中间的冰河而沉入水下。(通常地图上的都会沉入水下)
叉烧要配米线发表于 2017-1-26 09:11:00
第一课的最后说明一下地图主文件的基本结构。
1定义地图大小和样貌
2放置贸易路线

3定义间距
4放置宝藏
5放置猎物,金矿等资源
6 // Text
rmSetStatusText("",0.30);

第6个内容是载入地图时看到的进度条,0.30的意思是进度条走到30%,在地图文件中每隔几十行就放置一个标签就可以让我们看到地图载入的进度了。
195935ztg7hrurgpcmmvrs.jpg
尹以为荣发表于 2017-1-26 09:17:00
叉烧的文章,。。总是给我一种刚看很兴奋,再往下又蒙蔽,最后太长直接看评论
Ritsu发表于 2017-1-26 10:24:00
惊!西伯利亚竟惨遭毒手!
蓝色妖姬2017发表于 2017-1-26 10:32:00
int函数??难道说这地图是用vb语言编的吗?
我是的十八簿发表于 2017-1-26 15:33:00
支持
叉烧要配米线发表于 2017-2-1 09:31:00
第二课 地图基础设定

第一课有同学反应到了第二楼第三楼就听不懂了,那么我觉得可能是不熟悉C语言语法,所以第二课先讲讲C语言最基本的变量语法,接着第一课讲到main函数开始。

int PlayerNum=2;
int numPlayer=3;
int theNumberTeams=2;
void main(void)
{
// Text
// These status text lines are used to manually animate the map generation progress bar
rmSetStatusText("",0.01);

// initialize map type variables
string baseMix = "";
string baseTerrain = "";

string forestType = "";
string startTreeType = "";

string mapType1 = "";
string mapType2 = "";

string patchMix = "rockies_snow";

string huntable1 = "";
string huntable2 = "";

string lightingType = "";

string tradeRouteType = "";

开头有int的,比如int PlayerNum=2;这里面int的意思是整数类型,也就是说建立一个叫做PlayerNum的变量,然后这个变量必须是整数。PlayerNum=2是让PlayerNum的整数数值等于2。另外有一种用法是PlayerNum==2,双等号意思是作为在if语句中作为条件判断,如果这个变量等于2那么执行相关的语句。这里我们只需要知道单个的“=”是把右边的值赋予左边的变量就好了。
叉烧要配米线发表于 2017-2-1 09:46:00
举一反三,之后的以string开头的语句则是说明后面的变量类型是字符串。

好了下面我们继续第二课的内容。

// Map Basics

bool weird = false;
int teamZeroCount = rmGetNumberPlayersOnTeam(0);
int teamOneCount = rmGetNumberPlayersOnTeam(1);

/* if (theNumberTeams > 2 || (teamZeroCount - teamOneCount) > 2 || (teamOneCount - teamZeroCount) > 2)
weird = true;*/

int playerTiles = 13000;
if (PlayerNum >4)
playerTiles = 12500;
if (PlayerNum >6)
playerTiles = 12000;

if (weird == true)
playerTiles = playerTiles*1.75;

rmEchoInfo("Player Tiles = "+playerTiles);
int size=2.0*sqrt(PlayerNum*playerTiles);
rmEchoInfo("Map size="+size+"m x "+size+"m");
rmSetMapSize(size, size);

rmSetMapElevationParameters(cElevTurbulence, 0.05, 10, 0.4, 7.0);
rmSetMapElevationHeightBlend(1);

rmSetSeaLevel(1.0);
rmSetLightingSet(lightingType);

rmSetBaseTerrainMix(baseMix);
rmTerrainInitialize(baseTerrain, 0.0);
rmEnableLocalWater(false);
rmSetMapType(mapType1);
rmSetMapType(mapType2);
rmSetMapType("land");
rmSetWorldCircleConstraint(true);
rmSetWindMagnitude(2.0);

chooseMercs();

这一段中需要首先注意//和/* */两种字符,//是指后面一整行的内容是忽略不计的(可以用来标注解),而/**/之间的内容也是同样的意思,都是忽略不计的意思,这里的用法是把原始地图的一段内容屏蔽了。掌握这个知识点的好处是我在之后的内容就会以这2种标记来作为注释。

int playerTiles = 13000;//设定第一个整数参数为13000
if (PlayerNum >4)
playerTiles = 12500;//如果PlayerNum(玩家人数)大于4,让playerTiles变成12500
if (PlayerNum >6)
playerTiles = 12000;//如果PlayerNum(玩家人数)大于6,让playerTiles变成12000

if (weird == true)
playerTiles = playerTiles*1.75;//weird是一个被屏蔽的参数这里先不说明,因为地图内容中设定的默认值是false,所以这个语句并不会执行(false是指假(数值是0),true是指真(数值可以是非0的任意值,通常是1或-1))

rmEchoInfo("Player Tiles = "+playerTiles);//这里是输出文字的函数
int size=2.0*sqrt(PlayerNum*playerTiles);//这里是一个计算式,也就是playerTiles乘以玩家数(PlayerNum)的平方根再乘以2的数值赋予size参数。

rmEchoInfo("Map size="+size+"m x "+size+"m");//这里是输出文字的函数
rmSetMapSize(size, size);//这里是地图尺寸的最终数据,以size的数值为长和宽

总的来说这一段是在确认地图大小,有些标准地图具有大型地图,区别就是在这里。这段代码的主要内容是以玩家数量来确定地图生成的实际大小。不难看到玩家人数越多,虽然地图更大,但地图人均面积好像却越小
叉烧要配米线发表于 2017-2-1 15:41:00
其实写这个很多人肯定看得头都大了,只是以后别再冒出来说这么多年都没个人写地图制作攻略了!
123456809发表于 2017-2-2 17:37:00
还是从最简单的讲起吧
茉莉707发表于 2017-2-3 01:16:00
叉烧可以的,修改水平也很高啊
浪漫无边际缺发表于 2017-2-3 23:53:00
没有c++基础的会疯有的吧
马宝清马宝清发表于 2017-2-4 21:02:00
啊。。好复杂 虽然也猜到了会是这个
不过如果精细制作的地图无法加入对战的话想做moba的会很困扰吧
贰十岁装成熟装s发表于 2017-8-6 13:14:00
没了吗。。
新北狂纱发表于 2017-8-7 16:20:00
编写地图知道这些就够了吗。。。。
凡尘莲花1发表于 2018-3-3 09:09:00
好迷啊
跳转到