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初始化函数里加上你要新添加的模板类型:
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(); |
其中AddTemplate()函数的参数分别是你要添加的模板名字、地形块儿类型、地形块儿等级以及地形块儿的障碍物类型。
01 |
void AddTemplate (string templateName, GroundBoardType type, int level, int barrierType) |
03 |
nt templateListIndex = (int)type; |
04 |
if (templateListIndex < 0 || templateListIndex >= _templateList.Length) |
08 |
if (_templateList[templateListIndex] == null) |
10 |
_templateList[templateListIndex] = new BoardTemplateGroup(); |
12 |
BoardTemplate newTemplate = new BoardTemplate(templateName, level, barrierType); |
13 |
_templateList[templateListIndex].Add(newTemplate); |
AddTemplate()函数会创建一个新的BoardTemplate对象,并把它放到模板列表中,BoardTemplate类,如下所示。
01 |
public class BoardTemplate |
03 |
string _templateName;// 模板名字 |
05 |
int _barrierType;//障碍物类型 |
06 |
public BoardTemplate(string name, int level, int barrierType) |
10 |
_barrierType = barrierType; |
15 |
get{return _templateName;} |
21 |
public int BarrierType |
23 |
get{return _barrierType;} |
接着在LogicMgr.cs的Tick里面,每一帧都会用角色的位置信息,去判定是否要更新地形块儿。
1 |
public void Tick (float elapseTime) |
5 |
_runtimeBoardMgr.CheckUpdateBoard(PlayerDataMgr.Singleton.Pos.Z); |
当满足判定条件时,就会自动的创建一块儿新板子拼接上去。
01 |
public void CheckUpdateBoard (float playerPosZ) |
03 |
if (playerPosZ > _EndPos - StaticData.CreateBoardDistance) |
05 |
if(LogicMgr.Singleton.IsBeginner && _boardList.Count > 0) |
07 |
CreateNewBorad (RandomBoardType.Beginner); |
11 |
CreateNewBorad (RandomBoardType.Normal); |
创建新板子的代码,如下所示。
01 |
void CreateNewBorad (RandomBoardType randomBoardType) |
04 |
bool firstBoard = _boardList.Count > 0 ? false : true; |
05 |
//创建一个新的GroundBoardBase |
06 |
GroundBoardBase newBoard = null; |
07 |
//根据板子的随机类型调用不同的随机板子函数 |
08 |
if (randomBoardType == RandomBoardType.Beginner) |
10 |
newBoard = RandomBeginnerBoard (); |
14 |
newBoard = RandomNextBoard (firstBoard); |
18 |
//初始化这个newBoard上面的Item |
19 |
GroundBoardBase.InitData initData = new GroundBoardBase.InitData (); |
20 |
initData.PlayerZSpeed = PlayerDataMgr.Singleton._zSpeed; |
21 |
if (newBoard.IsHaveItem) |
23 |
initData.RandomItemType = _randomItemMgr.RandomItem (); |
27 |
initData.RandomItemType = Item.ItemType.Nothing; |
29 |
newBoard.Init(initData); |
30 |
newBoard.ResetBoard(); |
31 |
//根据上一块板子的连接点位置,来摆放这块儿新板子 |
34 |
newBoard.SetPos (StaticData.kBoardWidth / 2, 0, 0); |
38 |
GroundBoardBase preBoard = _boardList [_boardList.Count - 1]; |
39 |
newBoard.SetPos(preBoard.EndPos.X,preBoard.EndPos.Y,preBoard.EndPos.Z); |
41 |
_EndPos += newBoard.Length; |
42 |
_boardList.Add (newBoard); |
创建普通板子举例:
01 |
GroundBoardBase RandomNextBoard (bool firstBoard) |
03 |
//根据自行定义的拼接规则,随机出一个下一块板子的模板文件 |
04 |
AreaType nextBarrierType = AreaType.Rest; |
07 |
_lastBoardType = StaticData.FirstBoardType; |
11 |
_lastBoardType=_boardConnectionMgr.RandomNextBoardType (_lastBoardType); |
12 |
nextBarrierType = RandomNextAreaType(); |
14 |
BoardTemplateGroup boardGroup = _templateList[(int)_lastBoardType]; |
15 |
BoardTemplate template = boardGroup.Random (nextBarrierType); |
19 |
GroundBoardBase newBoard = null; |
20 |
newBoard = new GroundBoardFlat (template.Name, _lastBoardType); |
这里创建一个新的GroundBoardBase的时候,会根据模板文件的名字来创建这个Actor:
1 |
public GroundBoardBase (string templateName) |
3 |
_groundActor=ActorManager.CreateFromTemplate (StaticData.BoardTemplatePath + templateName,false); |
如果开发者的设计思路,与游戏DEMO相同的话,可以直接套用上面的代码,只需要在最上面的AddTemplate(模板文件名, 板子类型, 板子等级, 障碍物类型);稍作修改,即可使用。
引擎官方网站:http://www.genesis-3d.com.cn/
官方论坛:http://bbs.9tech.cn/genesis-3d/
官方千人大群:59113309 135439306
YY频道-游戏开发大讲堂(完全免费,定期开课):51735288
Genesis-3D开源游戏引擎:游戏起源,皆因有我!!!
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- 团体程序设计天梯赛-练习集L1-018. 大笨钟
L1-018. 大笨钟 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜 ...
- 利用钩子函数来捕捉键盘响应的windows应用程序
一:引言: 你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到 ...
- #pragma预处理指令讲解
在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...
- sqlmap映射继承机制及映射字段顺序与SQL查询字段顺序无关
<typeAlias alias="TblSpPartsinfo" type="com.bn.car.biz.supply.dao.po.PartsInfoPO&q ...
- CF 369 B. Valera and Contest
http://codeforces.com/contest/369/problem/B 题意 :n, k, l, r, sall, sk,n代表的是n个人,这n个人的总分是sall,每个人的得分大于 ...
- java 读取文件中文乱码问题
很少写java io的代码,今天整了一个发现 本地调试好好的,放到jmeter里就打印乱码.一番折腾,终于搞定~直接上代码: List<Order> orderList = new Arr ...
- 完全掌握Android Data Binding
转载:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html 来源 https://github.com/L ...
- 再谈 retain,copy,mutableCopy(官方SDK,声明NSString都用copy非retain)
之前一直以为retain就是简单的计数器+1,copy就是重新开辟内存复制对象: 其实不是这样,原来之前的自己独自徘徊于糊涂之中. (官方SDK,对NSString属性的定义都是用copy,而不是re ...
- (转)详解LVS负载均衡之三种工作模型原理和10种调度算法
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://linuxnx.blog.51cto.com/6676498/1195379 LV ...
- Java [Leetcode 242]Valid Anagram
题目描述: Given two strings s and t, write a function to determine if t is an anagram of s. For example, ...