在写之前,我想先抒发一下我激动的心情。啊~舒畅、激动、开心。确实为何?只因偶遇这异常神奇的indienova平台。
由于我是程序员出身,因此也知道很多比较好的开发者平台与游戏论坛,比如:github、牛客网、蛮牛、IGN、游戏邦……等等。但这么多平台中,indienova是最让我震惊和喜欢的。不仅因为这里是独立游戏开发者聚集的天堂,更是因为它提供了这样记录开发日志甚至发布游戏的功能,可以说这是我之前根本没想到的,中国竟然还有如此棒的属于独立游戏者的平台!
从此以后,我的生活、我的工作都将因为它而改变……
——————————————————————————————————————————————————————
好的,抒发结束,正文开始。
由于之前设想的时候,有想过在每一关的末尾插入一段跑酷的玩法,不仅是作为一关的总结,也是为玩家提供玩法上的新鲜感。因此我在闲暇之余试着做了一个3D跑酷的demo出来。
这个demo包括跑酷核心玩法要实现的全部核心功能,其余的功能也就是在这上锦上添花而已了。其中包括:自动前进、左右跑道切换、跳起、俯身滑行、地图无限循环机制、障碍物随机生成这几个核心功能。如果有美工的加入,相信这个demo很快就能变成一个完整的游戏。
那么,这些功能的核心代码都是什么呢?我只记录比较重要的。
1.自动前进:说到这个,其实实现方法有很多种。我一一列举。
(1)Transform.Translate函数的循环使用。
使用这个方法有一个前提,那就是你的地图要是一条直线型的,如果有转弯、上行、下行,这个方法都很难达成跑动的效果,甚至直接穿出地图跑到别处了。
这种方法最适合的是——2D横版跑酷游戏/3D伪2D跑酷游戏。也就是说,类似于超级马里奥那种游戏界面是最为适合的。
(2)设置地图位置点,通过位置点与角色之间的差值计算要移动的方向,接着利用speed属性进行移动。
Vector3 targetPos = XXX;
//得到要运动的方向
Vector3 moveDir = targetPos - transform.position;
//moveSpeed是在类中定义的运动速度
transform.position += moveDir.normalized * moveSpeed * Time.deltaTime;
这个方法是最适合3D跑酷的运动方法,由于设置了位置点,这样的运动能够保证角色不会跑到外面去。
2.相机跟随:
//计算目标物体的旋转角度与目标高度
float wantedRotationAngle = target.eulerAngles.y;
float wantedHeight = target.position.y + height;
//当前相机的旋转角度与高度
float currentRotationAngle = transform.eulerAngles.y;
float currentHeight = transform.position.y;
//平滑旋转
currentRotationAngle = Mathf.SmoothDampAngle(currentRotationAngle, wantedRotationAngle, ref _RefRotation, rotationDamping);
//平滑改变高度
currentHeight = Mathf.SmoothDamp(currentHeight, wantedHeight, ref _RefHigh, heightDamping);
//得到当前相机要朝向的角度
Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);
//相机水平位置的设置
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
//相机垂直位置的设置
transform.position = new Vector3(transform.position.x, currentHeight, transform.position.z);
//transform.position.Set(transform.position.x, currentHeight, transform.position.z);
//面向物体
transform.LookAt(target);
3.地图无限循环机制
public Transform currentGround;
public Transform nextGround;
Transform player;
float mapLength = 200;
// Use this for initialization
void Start () {
player = GameObject.FindGameObjectWithTag("Player").transform;
}
// Update is called once per frame
void Update () {
//玩家已经过了当前地图
if(player.position.z > nextGround.position.z + 1)
{
GameObject newGround = Instantiate(Resources.Load("Ground") as GameObject, nextGround.position + new Vector3(0, 0, mapLength), Quaternion.identity);
Destroy(currentGround.gameObject);
currentGround = nextGround;
nextGround = newGround.transform;
}
}
4.障碍物随机生成:
说一下思路。
首先要在地图的长度以内随机生成一个z轴值。
由于设置了位置点,因此我们可以通过这个Z轴的值来获取x、y的值。怎么获取呢?首先找到离这个Z轴值最近的两个位置点,假设在此值之后的点为 Pos[i] ,下一个点为 Pos[i + 1] 。
要注意的是,(Pos[i + 1].z - Pos[i].z) / (Pos[i + 1].z - Z) 的比值与 distance(i+1 ,i) / distance(i+1 , Z对应点) 的比值是一样的。因此只需要做一个一元一次方程,就可以算出 Z对应点 的位置了。
其他的内容不是很难,就不一一记录了,这篇日志就到这。
暂无关于此日志的评论。