以下东西已过时,新的 代码制作 教程正在筹备更新中

自定义地图制作教程

地图生成器提供了利用自己写的lua脚本 和生成器提供的api, 从头生成生成一张地图的能力
所使用的lua版本为5.3,

更新日志详见 这里, 如果想用更新的测试版本,欢迎加q群 1013586495

快速入门

建议动手开编辑器(任何一个能输入文字的编辑器,推荐vscode)跟随教程一起

你的第一张lua地图

生成器提供了map这一全局变量,map提供了生成地图所需要的一系列接口函数(能力),例如初始化地图大小和人数,设置水域,设置某个位置的高度,保存地图等

首先,让我们来创建一张纯水域地图吧

  1. -- 初始化地图大小、人数
  2. mapWidth = 600
  3. mapHeight = 600
  4. -- 创建地图必须先调用下面这个函数
  5. map:setup(mapWidth, mapHeight,6)
  6. -- 初始化地图使用到的所有贴图
  7. map:initTextures("Dirt_Yucatan01", "Grass_Hawaii02", "Grass_Hawaii03", "Grass_Hawaii04", "Grass_Heidelberg05")
  8. -- 设置地图高度和贴图
  9. for i = 0, mapWidth-1 do
  10. for j = 0, mapHeight-1 do
  11. -- 设置高度
  12. map:setHeight(i,j, 120)
  13. -- 设置地表贴图
  14. map.setTexture(i,j,"Dirt_Yucatan01")
  15. end
  16. end
  17. map:setWaterHeight(200)
  18. -- 设置玩家位置,第一个参数位玩家编号,范围16,后面两个参数为横纵坐标
  19. map.setPlayerPos(1, 240, 200)
  20. map.setPlayerPos(2, 400, 300)
  21. -- 保存地图
  22. map:save()

保存为MyMap.lua(文件名即地图名) ,然后打开地图生成器,选择MyMap.lua文件,点击右边的生成

恭喜,你已经成功生成了一张自己的地图

添加地表贴图

所有贴图完整列表

为了添加地表贴图,需要先初始化地图所使用的的所有贴图列表

  1. map:initTextures("Dirt_Yucatan01", "Grass_Hawaii02", "Grass_Hawaii03", "Grass_Hawaii04", "Grass_Heidelberg05")

然后再给某个位置设置贴图,注意这里所使用的贴图必须是上面那个函数参数里的其中一个

  1. map.setTexture(i,j,"Dirt_Yucatan01")

添加矿脉

添加矿脉使用如下函数

  1. -- 前两个参数为位置,最后一个位角度(角度制)
  2. map.addOreNode(440, 280, 45)

添加斜坡

添加斜坡使用如下函数

目前这个函数有点问题,后面会修复

  1. -- 参数位,起始点横纵坐标,终点横纵坐标,斜坡宽度
  2. map:ramp(300, 90, 300, 110, 12)

让我们利用已有的知识,创建一个圆岛地图

  1. -- 初始化地图大小、人数、名字
  2. mapWidth = 600
  3. mapHeight = 600
  4. map:setup(mapWidth, mapHeight,6)
  5. -- 初始化贴图数据
  6. map:initTextures("Dirt_Yucatan01", "Grass_Hawaii02", "Grass_Hawaii03", "Grass_Hawaii04", "Grass_Heidelberg05")
  7. -- 设置地图基本高度(水底高度)
  8. for i = 0, mapWidth-1 do
  9. for j = 0, mapHeight-1 do
  10. map:setHeight(i,j, 120)
  11. map.setTexture(i,j,"Dirt_Yucatan01")
  12. end
  13. end
  14. -- 创建一个圆形的高度为210的陆地,圆心在地图中心
  15. for i = 0, mapWidth-1 do
  16. for j = 0, mapHeight-1 do
  17. if (math.sqrt( (i - mapWidth /2 ) * (i - mapWidth /2 ) + (j - mapHeight /2 ) * (j - mapHeight /2 )) < 200 ) then
  18. map:setHeight(i,j, 210)
  19. map.setTexture(i,j,"Grass_Hawaii02")
  20. end
  21. end
  22. end
  23. map:setWaterHeight(200)
  24. -- 添加3个玩家
  25. map.setPlayerPos(1, 240, 200)
  26. map.setPlayerPos(2, 400, 300)
  27. map.setPlayerPos(3, 300, 300)
  28. -- 初始化随机数
  29. math.randomseed(os.time())
  30. math.random(); math.random(); math.random() -- 让随机数稍微启动一下
  31. -- 利用随机数添加矿脉
  32. for i = 1,3 do
  33. map.addOreNode(math.random(20, 580), math.random(20, 580), 45)
  34. end
  35. -- 添加斜坡
  36. map:ramp(300, 90, 300, 110, 12)
  37. -- 设置最大坡度(弧度制)
  38. -- 如果地图中相邻两个位置的坡度超过这个角度,那么updatePassabilityAuto函数会把这里标记为不可通过
  39. map:seUnPassableAngle(math.pi / 3)
  40. -- 根据地图高度和自动更新地图可通过信息
  41. -- 可通过信息(bool)决定了能否通过这个地方
  42. map:updatePassabilityAuto()
  43. -- 自动混合地表贴图(让贴图连接处更加自然)
  44. map:mixTextures()
  45. -- 保存地图
  46. map:save()

利用精准制作地图的能力

精准制作地图的教程参考这里
在lua里可以用通过调用函数运用此能力,函数如下

  1. -- 下面三个函数的参数都为文件路径
  2. -- 导入RGB
  3. map:loadImageTerrain("c:\\map\\myMap.png")
  4. -- 导入物体描述文件
  5. map:loadObjectList("objects.txt")
  6. -- 导入贴图颜色文件
  7. map:loadTextureColorMap("textureColor.txt")

特效

为地图添加画面特效,函数如下

  1. -- 设置曝光特效,参数范围0.0 ~ 5.0
  2. map:setBloom(0.5)
  3. -- 设置lookup特效,第一个参数为特效名字,第二个参数为特效值,范围0.0~ 5.0
  4. -- 特效名字有以下几种 LUSaturateColors_Vol , LUShiftBlue_Vol ,
  5. -- LUSaturateColors_Vol
  6. -- LUShiftBlue_Vol
  7. -- BleachByPass_vol
  8. -- LUGrayscale_Vol
  9. map:setLookupTable("LUSaturateColors_Vol", 0.47f)

脚本

地图生成器提供了完整的脚本生成能力,涉及到的脚本主要有3个

  1. -- beginScript表明开始一个脚本
  2. -- conditionAnd添加一个脚本条件
  3. -- execute添加一个脚本动作(满足脚本条件则触发)
  4. -- endScript表明结束当前脚本编辑
  5. -- 下面这个脚本的作用是 设置玩家1的金钱50000
  6. map:beginScript()
  7. :conditionAnd(3, "CONDITION_TRUE")
  8. :execute(128, "PLAYER_SET_MONEY",
  9. map:pair(arg_PlayerName, "Player_1"),
  10. map:pair(arg_Integer, 50000))
  11. :endScript()

conditionAnd的第一个参数为条件类型,第二个参数为条件名字(条件类型和条件名字是一一对应的)
execute的第一个参数为动作类型,第二个参数为动作名字(动作类型和动作名字是一一对应的)。之后的参数是可变长度的参数(这些参数必须用map:pair包裹起来)
map:pair的第一个参数为脚本参数类型(都以arg_开头),第二个为脚本参数值

你可能要问,条件类型和参数类型有哪些,幸运的是,这个可以在地图编辑器中直接找到,如下图所示

1.png

每个脚本项最后的那个数字就是动作(条件)类型

参数类型则有以下这些

arg_Integer arg_RealNumber arg_ScriptName arg_TeamName arg_CounterName arg_FlagName arg_Comparison arg_WaypointName arg_Boolean arg_TriggerAreaName arg_Text arg_PlayerName arg_SoundName arg_SubroutineName arg_UnitName arg_ObjectName arg_PositionCoordinate arg_Angle arg_TeamState arg_Relation arg_AiMood arg_SpeechName arg_MusicName arg_MovieName arg_WaypointPathName arg_LocalizedStringName arg_BridgeName arg_UnitOrStructureKind arg_AttackPrioritySetName arg_RadarEventType arg_SpecialPowerName arg_ScienceName arg_UpgradeName arg_UnitAbilityName arg_BoundaryName arg_Buildability arg_SurfaceType arg_CameraShakeIntensity arg_CommandButtonName arg_FontName arg_ObjectStatus arg_TeamAbilityName arg_SkirmishApproachPath arg_Color arg_EmoticonName arg_ObjectPanelFlag arg_FactionName arg_ObjectTypeListName arg_MapRevealName arg_ScienceAvailabilityName arg_EvacuateContainerSide arg_Percentage arg_Percentage2 arg_UnitReference arg_TeamReference arg_NearOrFar arg_MathOperator arg_ModelCondition arg_AudioName arg_ReverbRoomType arg_ObjectType arg_Hero arg_Emotion

至于条件名字和动作名字,目前正在寻找,会逐步给出

注意,生成脚本都是链式调用,以调用beginScript开头,以调用endScript结束

你可能会好奇,怎么没有看到设置脚本名字,这是因为生成器会自动为这个脚本赋予名字(每条脚本的名字都必须唯一),当然,你也可以自己设置名字
(方便其他地方引用),如下所示

  1. map:beginScript()
  2. :name("myFirstScript1")
  3. :conditionAnd(3, "CONDITION_TRUE")
  4. :execute(128, "PLAYER_SET_MONEY",
  5. map:pair(arg_PlayerName, "Player_1"),
  6. map:pair(arg_Integer, 50000))
  7. :endScript()

再来看看几个常用脚本

  1. -- 设置玩家1电力为60000
  2. map:beginScript()
  3. :conditionAnd(3, "CONDITION_TRUE")
  4. :execute(487, "PLAYER_SET_BASE_POWER",
  5. map:pair(arg_PlayerName, "Player_1"),
  6. map:pair(arg_Integer, 60000))
  7. :endScript()
  8. -- 禁止玩家1建造苏联真空内爆蛋
  9. map:beginScript()
  10. :conditionAnd(3, "CONDITION_TRUE")
  11. :execute(283, "ALLOW_DISALLOW_ONE_BUILDING",
  12. map:pair(arg_PlayerName, "Player_1"),
  13. map:pair(arg_ObjectName, SovietSuperWeaponAdvanced”)
  14. map:pair(arg_Boolean, 0))
  15. :endScript()
  16. map:beginScript()
  17. :conditionAnd(3, "CONDITION_TRUE")
  18. :execute(534, "PLAYER_LOCK_PLAYER_TECH",
  19. map:pair(arg_PlayerName, "Player_1"),
  20. map:pair(arg_ObjectName, PlayerTech_Allied_TimeBomb_Rank1”)
  21. map:pair(arg_Boolean, 0))
  22. :endScript()

目前一些脚本支持还潜在一些错误,等待后续会逐步修正

队伍

地图生成器也支持队伍的创建,通过以下函数

  1. -- 添加一个队伍
  2. -- 第一个参数为玩家名字,第二个参数为队伍名字(随意设置)
  3. -- 给队伍添加一种单位类型(每个队伍最多7种)
  4. map:teamAdd("Player_1", "xunluo")
  5. -- 第一个参数为玩家名字,第二个参数为队伍名字(随意设置),第三个参数为最小值,第四个参数为最大值,第五个参数为单位类型名称
  6. map:teamAddType("Player_1", "xunluo", 4, 6, "SovietMCV")
  7. -- 设置单位微操
  8. map:teamSetMicroManager("Player_1", "xunluo", "FearlessMicroManager")

路径点

地图生成器也支持路径点的创建,通过以下函数

  1. -- 前两个是横纵坐标,第三个是路径点名称(注意路径点名称必须唯一)
  2. map:addWaypoint(100,200,"luaPoint")

区域

地图生成器也支持区域的创建,通过以下函数

  1. -- 第一个是区域名称(注意区域名称必须唯一),后面可变长度的区域顶点坐标(3个以上)
  2. map:addArea("myArea1", map:pair(100,200), map:pair(200,300), map:pair(400,100))

小地图颜色控制

为特定地表贴图设置对应的小地图颜色

  1. -- 第一个参数为贴图名称,后面三个分别为R, G, B
  2. map:setTextureColor("Grass_Hawaii02", 255,255,0)

添加物体

所有物体名称列表
通过以下函数添加属于某个玩家的某个队伍的物体

  1. -- 在(300, 300)这个位置添加属于玩家1的苏联MCV,并且命名叫luaMCV
  2. map:addObject("SovietMCV", "Player_1", "teamPlayer_1", 300, 300, math.pi / 2, "luaMCV")

地图默认设定

地图中合法的玩家名称为

"Player_1", "Player_2", "Player_3", "Player_4", "Player_5", "Player_6", "PlyrCivilian", "PlyrNeutral"

其中前6个才是玩家可操控的,后面2个是中立玩家(如果一个物体属于中立玩家,那么这个物体就是中立的)

每个玩家名称都有默认的队伍,如下

Player_1的默认队伍为teamPlayer_1 Player_2的默认队伍为teamPlayer_2 Player_3的默认队伍为teamPlayer_3 Player_4的默认队伍为teamPlayer_4 Player_5的默认队伍为teamPlayer_5 Player_6的默认队伍为teamPlayer_6 PlyrCivilian的默认队伍为teamPlyrCivilian PlyrNeutral的默认队伍为teamPlyrNeutral

API

void setup(int width, int height, int playerCount)
初始化地图

void setHeight(int x, int y, float value)
设置某个位置的高度

public float getHeight(int x, int y)
获取某个位置的高度

public bool getPassability(int x, int y)
获取某个位置的通过性(返回true表示可通过,返回false表示不可通过)

save()
保存地图

void initTextures(params string[] textures)
设置地图使用的贴图,参数为可变长度

void setTexture(int x, int y, string name)
设置某个位置使用的使用的贴图名字

void seUnPassableAngle(double angle)
设置最大不可通过角度

void setPassability(int x, int y, bool passible)
设置某个位置的通过性

bool getPassability(int x, int y)
获得某个位置的通过性

void setPlayerPos(int playerNum, float x, float y)
设置玩家出生点位置

void addOreNode(float x, float y, float angle)
在某位置增加矿脉

void ramp(float x1,float y1, float x2, float y2, float rampWidth)
在两点间创建指定宽度的斜坡

void mixTextures()
自动混合地表贴图

void updatePassabilityAuto()
自动根据seUnPassableAngle所设置的角度更新整个地图的不可通过性