至此已经解决了List和Combo。但还需要进一步的优化。另外源码中还有MobileMenuList和MobileMenuBar,MobileMenuInventory。
将当前实现了的列表做一下分析再实现这种类,秉持一贯原则:会使用比掌握原理更为重要。原理仅仅是帮助我学会这件东西。我非常讨厌从造轮子做起。
1. AntMobileMenuObject是Button,Label,List和Combo的父类。这里定义了其接受触碰。实现接口
interface AntITouchable; function OnPick(ETouchType EventType, float X, float Y);
接口声明Object被触碰的函数OnPick(...)
2.AntMobileMenuObject将其实现,MobileMenuObject implements(AntITouchable)
定义了bIsActive和bIsHighlighted根据ETouchType是否被激活。
每一个Object都有自己对应的X,Y坐标。这里面定义了一个函数CheckBounds来辅助OnPick函数来检测边界。X>=left&&X<=Left+Width Y轴的道理相同Top和Height
因为要实现List,还得检测是否是Swipe这种方式触摸方式。但这里是在MobileMenuScene检测。因为Object范围太小了。
3.Object的思想是,自己处理渲染环节。MenuScene接受屏幕输入然后将swipe或是Touch传递过去。在他的内部foreach所有的MenuObjects数组。MenuObject的OnPick来处理对应的工作。
使用一个辅助页面AntMobileMenuBase然后将其OnSceneTouch行为交给代理OnInputTouch,OnInputTouch做的动作,所有的主页面处理全交给辅助页面来检测屏幕情况。
主页面打开的同时开启辅助页面AntMobileMenuScene的Opended函数内部开启OpenMenuScene(class'AntMobileMenuBase'),所以这时候所有的触摸行为是针对AntMobileMenuBase操作的。
var AntMenuSceneBase HelperScene; HelperScene.OnInputTouch = OnSceneTouch;
在OnSceneTouch中进行一大堆的操作,例如检测是Swipe还是Touch。遍历Objects然后调用每个MenuObjects的OnPick接口,当然每个接口的功能在自己的类内部实现。
CheckSwipe的方法实现很简单。
if(EventType==Touch_Began) StartTouchLocation.x=TouchX; bswipe=false; if(EventType==Touch_Moved) CurrentTouchLocation.x=TouchX; checkswipe(); function checkswipe() VSize(StartTouchLocation-CurrentTouchLoaction)>SwipeTolerance
遍历的每个MenuObjects.OnPick(...)
4.Button的功能部分
关于Button的OnPick接口实现,仍然使用了代理OnClick函数,完全可以在不同的表单中自定义,这就是对外的执行动作接口API。
这个函数的实现在Combo中是ToggleList。在List的中Cancel Button用来取消Combo。Button的内容比较简单,以后我会使用枪械选择表单。
在AntMobileMenuButton的上层是label,这个label用来显示所有外框。
5.Label渲染部分
这一部分可以让我更方便的定义自己需要制作的表单。后边实现List的时候能修改滑动的方向。
Images[0]和[1]可以自由的填充需要的图片,在InitMenuObject初始化这些内容。RenderObject中设置图片的透明度,以及字体内容,如果图片没有设置就填充DrawRect绘制矩形区域。画矩形区域的话有漂亮的边界显示。程序功底好的话就抛弃画师自己动手吧。
DrawCaption是必须填充的一个地方,这里可以绘制语言描述,需要填写什么内容。
6.List是我们的最终目标
他可以实现炫目的《无尽之剑》滚动效果,没有源码看也没有关系,google总是能找到问题解决的线索。
List在最上面有自己的刊头,在左侧有一个退出按钮(尽管我现在还不能确定这是不是list自己画的)
这里的功能非常完善,退出Cancel,列表的高度,列表的惯性,还有一些沙盒参数。
在InitMenuObject中初始化列表的区域,同时初始化Cancel的区域和功能。Cancel.OnClick=HandleCancel;
List是MenuObject的子类,这里实现RenderObject方法,来绘制List。这个函数可是实现滚动菜单的关键哦!Listen to me carefully
用矩形绘制背景""计算当前世界时间""如果Items.length>0就开始继续绘制(以后我要在这里加上自己需要填充的图片,或者是给每个图片重新写一个类,他们占据的位置,他们具有的信息)
float ScrollInertia; //是不滚动时候的移动量,例如装在上边了然后被撞下来的量
if(Items[0].top>Top+TitileBarHeight) { ScrollInertia=Top+TitileBarHeight-Items[0].Top; ScrollDelta=ScrollInertia*DeltaTime*snapFactor; }
第二种情况是在不超过下部
if(items[Items.length-1].top+Itemheight<Top+ItemHeight) { ScrollInertia=(Top+Height)-(Items[Items.length-1].top+ItemHeight); ScrollDelta=ScrollInertia*DeltaTime*SnapFactor; }
第三种情况是ScrollDelta=ScrollInertia*DeltaTime;
渲染每个列表:以后在该位置改变绘制的横纵和是否用图片来显示。
for(i=0; i < Items.Length; i++) { //强制设置列表项的大小以防方位改变。 Items[i].Left = left; Items[i].Top += bActive ? ScrollAmount : ScrollDelta; Items[i].Width = Width; Items[i].Height = ItemHeight; //仅当部分列表项可见时渲染该项。 if(Items[i].Top + ItemHeight > Top && Items[i].Top < Top + Height) { Items[i].RenderObject(Canvas,DeltaTime); } }
添加物品栏,物品栏以后会进行拓展AddItem。例如武器栏会变成有武器图片和参数信息内容。
在AddItem中定义各种图片和文字信息:
NewItem=new(Outer) class'AntMobileMenuButton';
RemoveItem(int Idx);
7.Combo对List的初始化及使用
List中有非常大的代码量,但是很多都是沙盒代码。在外部学会使用即可,Combo中队List有打开以及插入Item。
一个初始化按钮用于打开一个列表 var instanced AntMobileMenuButton Label; var instanced AntMobileMenuList list;
var array<string>Items; //用于插入武器的名字及图片列表
在InitMenuObject中初始化需要的内容,
List.InitMenuObject(PlayerInput,Scene,ScreenWidth,ScreenHeight,bIsFirstInitialization);
List有自己的OnChange代理
8.Combo也需要在实例中初始化
下来是一个实例运用,他初始化了两个Combo,一个是Object,一个是Item。选定一种将会在表单中显示List中的变量,这其实提供了两个方向,一个是list的生成,一个是Label的接口
Items序列来添加每个内容,同样Image也可体用类似的方式添加。
在初始化表单的时候有一些工作
9 总结:
使用的是AntMobileMenuButton,以下是按钮初始化的内容
Begin Object class=UDNMobileMenuButton name=CancelButton Tag="Cancel" Width=64 Height=32 Caption="Cancel" TextFont=Font'EngineFonts.SmallFont' CaptionColors(0)=(r=1.0,g=1.0,b=1.0,a=1.0) CaptionColors(1)=(r=0.0,g=0.0,b=0.0,a=1.0) Images(0)=Texture2D'UDNExampleUI.Menus.T_MenuUI' Images(1)=Texture2D'UDNExampleUI.Menus.T_MenuUI' ImagesUVs(0)=(bCustomCoords=true,U=0,V=896,UL=256,VL=128) ImagesUVs(1)=(bCustomCoords=true,U=0,V=896,UL=256,VL=128) End Object Cancel=CancelButton
列表初始化的过程AntMobileMenuList,以下是列表初始化示例:
Begin Object class=UDNMobileMenuList name=List0 Tag="Combo_ItemsList" End Object List=List0
在列表栏中一个变量
1. var instanced AntMobileMenuList list;
然后在初始化InitMenuObject中添加列表,我制作一个武器栏列表,里面有各种武器的图片以及参数。
继承AntMobileMenuList开辟一个AntWeaponShopMenu和AntWeaponItemMenu;
在他们的InitMenuObject中foreach List补充图片和文字信息。
var array<AntWeapon> CurrentWeapn;
foreach AntWeapon(CurrentWeapon)
{
List.AddItem(CurrentWeapon);
}
2. 在AntMobileMenuList中实现AddItem函数
var instanced array<UDNMobileMenuButton> Items; function AddItem(AntWeapon Item) { local AntMobileButton NewItem; NewItem.Caption=Item.caption; NewItem.Image=Item.Caption; Items.AddItem(NewItem); }
事已至此,概念上的东西讲完了。我该let's make our hands dirty!