上一篇文章用在UI界面上绘制骨骼数据的例子展示了骨骼追踪系统涉及的主要对象,然后详细讨论了骨骼追踪中所涉及的对象模型。但是了解了基本概念是一回事,能够建立一个完整的可用的应用程序又是另外一回事,本文通过介绍一个简单的Kinect游戏来详细讨论如何应用这些对象来建立一个完整的Kinect应用,以加深对Kinect骨骼追踪所涉及的各个对象的了解。
1. Kinect连线游戏
相信大家在小时候都做过一个数学题目,就是在纸上将一些列数字(用一个圆点表示)从小到大用线连起来。游戏逻辑很简单,只不过我们在这里要实现的是动动手将这些点连起来,而不是用笔或者鼠标。
这个小游戏显然没有第一人称射击游戏那样复杂,但如果能够做成那样更好。我们要使用骨骼追踪引擎来收集游戏者的关节数据,执行操作并渲染UI界面。这个小游戏展示了自然用户界面(Natural User Interface,NUI)的理念,这正是基于Kinect开发的常见交互界面,就是手部跟踪。这个连线小游戏没有仅仅用到了WPF的绘图功能,没有好看的图片和动画效果,这些以后可以逐步添加。
在开始写代码之前,需要明确定义我们的游戏目标。连线游戏是一个智力游戏,游戏者需要将数字从小到大连起来。程序可以自定义游戏上面的数字和位置(合称一个关卡)。每一个关卡包括一些列的数字(以点表示)及其位置。我们要创建一个DotPuzzle类来管理这些点对象的集合。可能一开始不需要这个类,仅仅需要一个集合就可以,但是为了以后方便添加其他功能,使用类更好一点。这些点在程序中有两个地方需要用到,一个是最开始的时候在界面上绘制关卡,其次是判断用户是否碰到了这些点。
当用户碰到点时,程序开始绘制,直线以碰到的点为起始点,直线的终点位用户碰到的下一个点。然后下一个点又作为另一条直线的起点,依次类推。直到最后一个点和第一个点连起来,这样关卡算是通过了,游戏结束。
游戏规则定义好了之后,我们就可以开始编码了,随着这个小游戏的开发进度,可能会添加一些其他的新功能。一开始,建一个WPF工程,然后引用Microsoft.Kinect.dll,和之前的项目一样,添加发现和初始化Kinect传感器的代码。然后注册KinectSensor对象的SkeletonFrameReady事件。
1.1 游戏的用户界面
游戏界面代码如下,有几个地方需要说明一下。Polyline对象用来表示点与点之间的连线。当用户在点和点之间移动手时,程序将点添加到Polyline对象中。PuzzleBoardElement Canvas对象用来作为UI界面上所有点的容器。Grid对象下面的Canvas的顺序是有意这样排列的,我们使用另外一个GameBoardElement Canvas对象来存储手势,以Image来表示,并且能够保证这一层总是在点图层之上。 将每一类对象放在各自层中的另外一个好处是重新开始一个新的游戏变得很容易,只需要将PuzzleBoardElement节点下的所有子节点清除,CrayonElement元素和其他的UI对象不会受到影响。
Viewbox和Grid对象对于UI界面很重要。如上一篇文章中讨论的,骨骼节点数据是基于骨骼空间的。这意味着我们要将骨骼向量转化到UI坐标系中来才能进行绘制。我们将UI控件硬编码,不允许它随着UI窗体的变化而浮动。Grid节点将UI空间大小定义为1920*1200。通常这个是显示器的全屏尺寸,而且他和深度影像数据的长宽比是一致的。这能够使得坐标转换更加清楚而且能够有更加流畅的手势移动体验。
<Window x:Class="KinectDrawDotsGame.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="600" Width="800" Background="White"> <Viewbox> <Grid x:Name="LayoutRoot" Width="1920" Height="1200"> <Polyline x:Name="CrayonElement" Stroke="Black" StrokeThickness="3" /> <Canvas x:Name="PuzzleBoardElement" /> <Canvas x:Name="GameBoardElement"> <Image x:Name="HandCursorElement" Source="Images/hand.png" Width="75" Height="75" RenderTransformOrigin="0.5,0.5"> <Image.RenderTransform> <TransformGroup> <ScaleTransform x:Name="HandCursorScale" ScaleX="1" /> </TransformGroup> </Image.RenderTransform> </Image> </Canvas> </Grid> </Viewbox> </Window>
硬编码UI界面也能够简化开发过程,能够使得从骨骼坐标向UI坐标的转化更加简单和快速,只需要几行代码就能完成操作。况且,如果不应编码,相应主UI窗体大小的改变将会增加额外的工作量。通过将Grid嵌入Viewbox节点来让WPF来帮我们做缩放操作。最后一个UI元素是Image对象,他表示手的位置。在这个小游戏中,我们使用这么一个简单的图标代表手。你可以选择其他的图片或者直接用一个Ellipse对象来代替。本游戏中图片使用的是右手。在游戏中,用户可以选择使用左手或者右手,如果用户使用左手,我们将该图片使用ScaleTransform变换,使得变得看起来像右手。
1.2 手部追踪
游戏者使用手进行交互,因此准确判断是那只手以及手的位置对于基于Kinect开发的应用程序显得至关重要。手的位置及动作是手势识别的基础。追踪手的运动是从Kinect获取数据的最重要用途。在这个应用中,我们将忽视其他关节点信息。
小时候,我们做这中连线时一般会用铅笔或者颜料笔,然后用手控制铅笔或则颜料笔进行连线。我们的这个小游戏颠覆了这种方式,我们的交互非常自然,就是手。这样有比较好的沉浸感,使得游戏更加有趣。当然,开发基于Kinect的应用程序这种交互显得自然显得至关重要。幸运的是,我们只需要一点代码就能实现这一点。
在应用程序中可能有多个游戏者,我们设定,不论那只手离Kinect最近,我们使用距离Kinect最近的那个游戏者的那只手作为控制程序绘图的手。当然,在游戏中,任何时候用户可以选择使用左手还是右手,这会使得用户操作起来比较舒服,SkeletonFrameReady代码如下:
private void KinectDevice_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { using (SkeletonFrame frame = e.OpenSkeletonFrame()) { if (frame != null) { frame.CopySkeletonDataTo(this.frameSkeletons); Skeleton skeleton = GetPrimarySkeleton(this.frameSkeletons); Skeleton[] dataSet2 = new Skeleton[this.frameSkeletons.Length]; frame.CopySkeletonDataTo(dataSet2); if (skeleton == null) { HandCursorElement.Visibility = Visibility.Collapsed; } else { Joint primaryHand = GetPrimaryHand(skeleton); TrackHand(primaryHand); TrackPuzzle(primaryHand.Position); } } } } private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons) { Skeleton skeleton = null; if (skeletons != null) { //查找最近的游戏者 for (int i = 0; i < skeletons.Length; i++) { if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked) { if (skeleton == null) { skeleton = skeletons[i]; } else { if (skeleton.Position.Z > skeletons[i].Position.Z) { skeleton = skeletons[i]; } } } } } return skeleton; }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索对象
, kinect
, kinect2.0
, kinect2.0 win8.1
, kinect开发
, 用户
, 位置追踪
, 追踪
, kinect,C#,输出坐标
, 一个
游戏开发手势
kinect 骨骼点追踪、kinect骨骼跟踪、kinect2.0骨骼节点、kinect 骨骼、kinect获取骨骼坐标,以便于您获取更多的相关知识。