1.道路的自动生成

道路自动生成概述:

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

原理:

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


图1-1

实现方法:

步骤1:

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


图1-1-1

步骤2:

道路的拼接原理及实现:

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

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


图1-2-1-1

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


图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开源游戏引擎:游戏起源,皆因有我!!!

 


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

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 团体程序设计天梯赛-练习集L1-001. Hello World

    L1-001. Hello World 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 这道超级简单的题目没有任何输入. 你只需要在一行中输 ...

  2. 【转】Spring+Hibernate+EHcache配置(一)

    大量数据流动是web应用性能问题常见的原因,而缓存被广泛的用于优化数据库应用.cache被设计为通过保存从数据库里load的数据来减少应用和数据库之间的数据流动.数据库访问只有当检索的数据不在cach ...

  3. zoj 3725

    题意: n个格子排成一条直线,可以选择涂成红色或蓝色,问最少 m 个连续为红色的方案数. 解题思路: 应该是这次 ZOJ 月赛最水的一题,可惜还是没想到... dp[i] 表示前 i 个最少 m 个连 ...

  4. uva 10827

    与108类似 多加了两层循环 水过 #include <iostream> #include <cstring> #include <cstdio> #includ ...

  5. c++实现文本中英文单词和汉字字符的统计

    源代码下载:http://download.csdn.net/detail/nuptboyzhb/4987141 1.统计文本中汉字的频数,为后续的文本分类做基础.对于汉字的统计,需要判断读取的是否为 ...

  6. Why does yum return error: [Errno 256] No more mirrors to try ?

    https://access.redhat.com/solutions/203603 ISSUE yum update fails with the error : [Errno 256] No mo ...

  7. ADT(android-bundler) HTML EDIT 编辑 xml HTML

    逗比的ADT,安装个html一直不成功,最后发现了如下方法 Helper_Install New Software_ http://download.eclipse.org/releases/indi ...

  8. 【无聊放个模板系列】POJ 1274 (匈牙利)

    #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #inc ...

  9. [矩阵快速幂]HDOJ4565 So Easy!

    题意:给a, b, n, m 求 $\left \lceil ( a+ \sqrt b )^n \right \rceil$ % m 看到 $( a+ \sqrt b )^n$ 虽然很好联想到共轭 但 ...

  10. java中List集合及其遍历详解

    1. 首先List<E>集合继承与Collection<E>,是一个接口. ①  Collection (集合框架是JDK1.2版本出现的) ②   list:是有序的,元素可 ...