《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇01:道路的自动生成》

时间:2021-02-25 05:27:03

1.道路的自动生成

道路自动生成概述:

3D跑酷游戏的核心就是跑,在跑这一过程中增加趣味性使得游戏具有更多的可玩性。道路的自动生成和*拼接,为游戏增设了更多的不可预见性。这种不可预见性使得玩家在游戏中更多的体验到探索精神,进而开发玩家对游戏的兴趣。因此在跑酷游戏中,并不建议开发者设定好固定的场景道路,道路的自动生成模式更能吸引玩家。开发者可以通过不同的方式来实现道路的自动生成,将角色固定点场景后移的方式实现;或者固定道路的坐标,通过角色的向前奔跑产生位移变化。

原理:

通过使角色不断奔跑,产生相应位移变化,来达到道路的自动生成为例。将道路抽象的想象成一块块的板子,道路的不同场景转换和消失就如同板子的拼接和掉落。其原理流程,如图1-1所示。

《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇01:道路的自动生成》
图1-1

实现方法:

步骤1:

导入美术资源。将制作好的道路美术资源导入Genesis-3D引擎中。以shanggu01.fbx为例。将shanggu01.fbx文件导入项目文件夹->将项目文件里的资源文件拖入场景->附材质。这里需要注意,为了使道路可以完美拼接,道路场景制作接口处尺寸应该一样。并将文件转换为template。方便重复利用资源,方法如下图1-1-1所示。

《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇01:道路的自动生成》
图1-1-1

步骤2:

道路的拼接原理及实现:

2.1拼接原理:以两个道路拼接为例,抽象理解为板子A、B。

引擎中在板首尾的同侧方向创建两个空对象,按照下图原则,将所有道路场景文件都标记好。如图1-2-1-1所示

《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇01:道路的自动生成》
图1-2-1-1

通过创建Template,把下一个板的中心点,放到前一个板的连接点就可以了,即将当前游戏角色所在A板的连接点坐标覆盖为下一块板B中心点的坐标。

《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇01:道路的自动生成》
图1-2-1-2

2.2道路的拼接与生成实现。道路自动生成与拼接的相关代码框架,如下所示。。

在RunTimeBoardMgr文件中,Init初始化函数里加上你要新添加的模板类型:

01 public void Init ()
02 {                    
03  AddTemplate("ShanDong_01.template", GroundBoardType.Beginner, 0, 0);
04  AddTemplate("ShanDong_01.template", GroundBoardType.ShanDong1, 0, 0);
05  AddTemplate("ShanDong_02.template", GroundBoardType.ShanDong2, 0, 0);
06  AddTemplate("ShanDong_03.template", GroundBoardType.ShanDong3, 0, 0);
07  AddTemplate("ShanGu_01.template", GroundBoardType.ShanGu, 0, 0);
08  AddTemplate("ShanGu_02.template", GroundBoardType.ShanGu, 0, 0);
09  _boardConnectionMgr.Init();
10  Reset();
11  Preload();
12 }

其中AddTemplate()函数的参数分别是你要添加的模板名字、地形块儿类型、地形块儿等级以及地形块儿的障碍物类型。

01  void AddTemplate (string templateName, GroundBoardType type, int level, int barrierType)
02 {
03  nt templateListIndex = (int)type;
04  if (templateListIndex < 0 || templateListIndex >= _templateList.Length)
05  {
06   return;
07  }
08  if (_templateList[templateListIndex] == null)
09  {
10   _templateList[templateListIndex] = new BoardTemplateGroup();
11  }
12   BoardTemplate newTemplate = new BoardTemplate(templateName, level, barrierType);
13   _templateList[templateListIndex].Add(newTemplate);
14 }

AddTemplate()函数会创建一个新的BoardTemplate对象,并把它放到模板列表中,BoardTemplate类,如下所示。

01 public class BoardTemplate
02 {
03  string _templateName;// 模板名字
04  int _level;//板子的等级
05  int _barrierType;//障碍物类型
06  public BoardTemplate(string name, int level, int barrierType)
07  {
08   _templateName = name;
09   _level = level;
10   _barrierType = barrierType;
11  }
12  
13  public string Name
14  {
15   get{return _templateName;}
16  }
17  public int Level
18  {
19   get{return _level;}
20  }
21  public int BarrierType
22  {
23   get{return _barrierType;}
24  }
25 }

接着在LogicMgr.cs的Tick里面,每一帧都会用角色的位置信息,去判定是否要更新地形块儿。

1 public void Tick (float elapseTime)
2 {
3  …………
4  …………
5  _runtimeBoardMgr.CheckUpdateBoard(PlayerDataMgr.Singleton.Pos.Z);
6  …………
7  …………
8 }

当满足判定条件时,就会自动的创建一块儿新板子拼接上去。

01 public void CheckUpdateBoard (float playerPosZ)
02 {
03  if (playerPosZ > _EndPos - StaticData.CreateBoardDistance)
04  {
05   if(LogicMgr.Singleton.IsBeginner && _boardList.Count > 0)
06   {
07    CreateNewBorad (RandomBoardType.Beginner);
08   }
09   else
10   {
11    CreateNewBorad (RandomBoardType.Normal);
12   }
13  }
14  …………
15  …………
16 }

创建新板子的代码,如下所示。

01 void CreateNewBorad (RandomBoardType randomBoardType)
02 {
03  //是否是第一块儿板子
04  bool firstBoard = _boardList.Count > 0 ? false true;
05  //创建一个新的GroundBoardBase
06  GroundBoardBase newBoard = null;
07  //根据板子的随机类型调用不同的随机板子函数
08  if (randomBoardType == RandomBoardType.Beginner)
09  {
10   newBoard = RandomBeginnerBoard ();
11  }
12  else
13  {
14   newBoard = RandomNextBoard (firstBoard);
15  }
16  if (newBoard == null)
17  {return; }
18  //初始化这个newBoard上面的Item
19  GroundBoardBase.InitData initData = new GroundBoardBase.InitData ();
20  initData.PlayerZSpeed = PlayerDataMgr.Singleton._zSpeed;
21  if (newBoard.IsHaveItem)
22  {
23   initData.RandomItemType = _randomItemMgr.RandomItem ();
24  }
25  else
26  {
27   initData.RandomItemType = Item.ItemType.Nothing;
28  }
29  newBoard.Init(initData);
30  newBoard.ResetBoard();
31  //根据上一块板子的连接点位置,来摆放这块儿新板子
32  if (firstBoard)
33  {
34   newBoard.SetPos (StaticData.kBoardWidth / 2, 0, 0);
35  }
36  else
37  {               
38   GroundBoardBase preBoard = _boardList [_boardList.Count - 1];
39   newBoard.SetPos(preBoard.EndPos.X,preBoard.EndPos.Y,preBoard.EndPos.Z);
40  }
41   _EndPos += newBoard.Length;
42   _boardList.Add (newBoard);
43 }

创建普通板子举例:

01 GroundBoardBase RandomNextBoard (bool firstBoard)
02 {
03  //根据自行定义的拼接规则,随机出一个下一块板子的模板文件
04  AreaType nextBarrierType = AreaType.Rest;
05  if (firstBoard)
06  {
07   _lastBoardType = StaticData.FirstBoardType;
08  }
09  else
10  {
11   _lastBoardType=_boardConnectionMgr.RandomNextBoardType (_lastBoardType);
12   nextBarrierType = RandomNextAreaType();
13  }
14   BoardTemplateGroup boardGroup = _templateList[(int)_lastBoardType];
15   BoardTemplate template = boardGroup.Random (nextBarrierType);
16   //根据模板文件的名字创建新板子
17   if (template == null)
18   {return null;}
19   GroundBoardBase newBoard = null;                   
20   newBoard = new GroundBoardFlat (template.Name, _lastBoardType);
21   eturn newBoard;
22 }

这里创建一个新的GroundBoardBase的时候,会根据模板文件的名字来创建这个Actor:

1 public GroundBoardBase (string templateName)
2 {
3  _groundActor=ActorManager.CreateFromTemplate (StaticData.BoardTemplatePath + templateName,false);
4   }

如果开发者的设计思路,与游戏DEMO相同的话,可以直接套用上面的代码,只需要在最上面的AddTemplate(模板文件名, 板子类型, 板子等级, 障碍物类型);稍作修改,即可使用。


引擎官方网站:http://www.genesis-3d.com.cn/

官方论坛:http://bbs.9tech.cn/genesis-3d/

官方千人大群:59113309   135439306

YY频道-游戏开发大讲堂(完全免费,定期开课):51735288

Genesis-3D开源游戏引擎:游戏起源,皆因有我!!!