前两天我们的策划想要实现一个像《少年三国志》游戏的大厅里的3D旋转效果,大概是这个样子的:在主界面有九个角色组成了一个椭圆形区域,滑动屏幕的时候,可以按滑动方向的不同可以左右旋转并且前面的会覆盖后面的角色卡片。我试着使用NGUI3.8实现了这个功能。《少年三国志》主界面的效果图如下:
主要思路:使用每个点与x轴的角度计算点在屏幕上的位置。从屏幕上输入位移控制旋转的角度,每帧计算点的位置。遮挡的问题可以使用widged的depth控制。
我设计了这两个类:
EllipsePlugin: 计算出一个椭圆区域,用于摆放需要旋转的物件。这些物件(gameObject)的位置自动生成(其实也可以自己设定,为着程序的方便,改成自动摆放了)
Point: 椭圆上的每个点(gameObject)每帧更新自己的位置。
第一步,我们先实现椭圆区域的旋转。
首先,分析椭圆方程,把(x,y)使用椭圆的长短轴(a长轴,b短轴),中心点坐标(x0,y0)及角度sita表示=>(x, y)=(x0 + a * cos(sita), y0 + b * sin(sita))
然后,我们可以按照需求构建几个类,
第一个控制椭圆区域及输入处理Ellipse
类成员:椭圆中心点,长轴,短轴
类函数:OnDrag(float delta) 把屏幕位移转换成椭圆上的点(gameObject)的角度变化
第二个椭圆上的点:Point
类成员:角度(Angle)
类函数:每帧处理位置变化
按上述方法可以实现拖动旋转
我的初级效果图
接下来是加强实现
实现缩放及遮挡
1. 缩放
缩放与椭圆上点的y坐标有关,也可以使用长短轴及旋转角度计算,y坐标越大,显示越小,让人感觉距离物体越远
2. 遮挡
可以使用渲染的深度widget的depth实现,depth值越大,渲染越靠前,也是可以使用椭圆的长短轴及旋转角度表示的
代码实现比较简单,就不上代码了(我的代码写的比较乱)
最后我们要加上动画显示,如果旋转到某一点,松开手指后,要把距离最前面位置的点使用动画的方式停靠过去。
这一块首先要计算停靠点,只要计算椭圆上每个点与停靠点的夹角,得到最小的角度的那个点即可,然后设置动画移动。由于我们使用角度进行所有的逻辑的控制,这里按角度进行更新最方便,设置每帧移动一个很小的角度即可。
我上面说的有点粗略,如果有实现不了的,可以在下面的评论中一起讨论。
效果图如下:
这里的缩放比例都是可以调节的
在我实现完成之后,我发现《少年三国志里》实现没有我想的那么细,它在施动的开始就决定了最终的旋转方向,比如我刚开始向左施动,在鼠标弹起时,不管我是向哪个方向,都会向左滑动到指定的位置。