65.9K
CodeProject 正在变化。 阅读更多。
Home

GesturCubes

starIconstarIconstarIconstarIconstarIcon

5.00/5 (16投票s)

2013年7月27日

CPOL

2分钟阅读

viewsIcon

38158

AIO (All-In-One) PC 的 WPF 3D 立方体益智游戏

概述

GesturCubes 是一款针对联想地平线 27" 一体机® PC 设计的益智游戏。它提供两种游戏模式,带来有趣且具有挑战性的体验:2x2 立方体模式和 3x3 立方体模式。

2x2 立方体模式

特点

考虑到一体机的功能,GesturCubes 包含以下特性:

  • 多点触控界面:该应用利用一体机的触控功能,允许用户/用户通过触控交互和控制来解魔方、切换模式和启动计时器。GesturCubes 通过利用 WPF 的多点触控支持来实现这一点。 
  • 多用户界面联想地平线 27" 一体机® 的一个优点是其大屏幕。GesturCubes 利用此特性提供协作多用户体验:UI 元素布局使两位用户可以舒适地并排坐在一起,以更轻松有趣的方式进行 团队解魔方
  • 多模态交互:用户可以使用语音命令来解魔方、打乱和切换游戏模式。 

设计

GesturCubes 是一个 WPF 应用程序,包含我在 Blender、Expression Design 和 Expression Blend 中设计的几个 UI 元素。3D 立方体模型是在 Blender 中设计的,而其他一些 UI 元素,例如计时器的手掌控制,是在 Expression Design 中设计的。所有内容都在 Expression Blend 中组合在一起。

Blender 中的 3x3 立方体模型

Expression Design

Expression Blend

该应用程序使用 MahApp.Metro 进行窗口样式设置。

<Controls:MetroWindow
    ...
    xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls"
    ShowTitleBar="False" 
    ...>
    <Controls:MetroWindow.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml" />                
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Colours.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Styles.xaml"/>
                ...
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>                
    </Controls:MetroWindow.Resources>
    ...

有两个 MahApps.Metro Flyout 用于显示解题时间。

 

为了动画显示 ItemsControl 中项目的添加和删除,我使用 FluidMoveBehavior

<Controls:MetroWindow.Flyouts>
    <Controls:Flyout Header="2x2x2" Position="Right" Background="#FF0A1521">
        <Grid Margin="10">
            <ScrollViewer Width="330" VerticalScrollBarVisibility="Auto">
                <ItemsControl ItemTemplate="{StaticResource TimesTemplate}" ItemsSource="{Binding Solves2x2}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel>
                                <i:Interaction.Behaviors>
                                    <ei:FluidMoveBehavior AppliesTo="Children" Duration="0:0:0.5" Tag="DataContext">
                                        <ei:FluidMoveBehavior.EaseY>
                                            <CubicEase EasingMode="EaseIn"/>
                                        </ei:FluidMoveBehavior.EaseY>                                            
                                    </ei:FluidMoveBehavior>
                                </i:Interaction.Behaviors>
                            </StackPanel>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </ScrollViewer>                
        </Grid>
    </Controls:Flyout>
        
    <Controls:Flyout Header="3x3x3" Position="Right" Background="#FF0A1521">
        <Grid Margin="10">
            <ScrollViewer Width="330" VerticalScrollBarVisibility="Auto">
                <ItemsControl ItemTemplate="{StaticResource TimesTemplate}" ItemsSource="{Binding Solves3x3}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel>
                                <i:Interaction.Behaviors>
                                    <ei:FluidMoveBehavior AppliesTo="Children" Duration="0:0:0.5" Tag="DataContext">
                                        <ei:FluidMoveBehavior.EaseY>
                                            <CubicEase EasingMode="EaseIn"/>
                                        </ei:FluidMoveBehavior.EaseY>
                                    </ei:FluidMoveBehavior>
                                </i:Interaction.Behaviors>
                            </StackPanel>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </ScrollViewer>
        </Grid>
    </Controls:Flyout>
</Controls:MetroWindow.Flyouts>

以下是 ItemsControlDataTemplate 的 XAML 标记:

<DataTemplate x:Key="TimesTemplate">
    <Border BorderBrush="#FF595959" BorderThickness="0,0,0,1" Height="34" Canvas.Left="18" Canvas.Top="31" Width="300">
        <Grid>
            <TextBlock HorizontalAlignment="Left" Text="{Binding SolveTime}" Margin="12,0,0,0" VerticalAlignment="Center" 
                       FontSize="14" Foreground="#FFD6CD00"/>
            <TextBlock HorizontalAlignment="Left" Text="{Binding TimeOfSolve, StringFormat={}{0:G}}" Margin="104,0,0,0" 
                       VerticalAlignment="Center" 
                       FontSize="14" Foreground="#FFACACAC"/>
            <Button Height="16" Margin="0,0,12,0" Style="{DynamicResource DeleteTimeButtonStyle}" 
                    VerticalAlignment="Center" HorizontalAlignment="Right" Width="16" 
                    Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
                    CommandParameter="{Binding}"/>
        </Grid>
    </Border>
</DataTemplate>

代码

该应用程序是用 VB.NET 编写的。以下代码片段显示了类 CubePiece 中的一些方法,这些方法用于围绕 x、y 和 z 轴旋转立方体碎片。

Imports System.Windows.Media.Media3D
Imports System.Windows.Media.Animation

Public Class CubePiece
    ...
    Private Sub Rotate(ByVal angle As Double)
        rTransform3D = New RotateTransform3D(axisAngleRtn3D, axisPoint)
        dblAnimation = New DoubleAnimation(CDbl(angle), TimeSpan.FromMilliseconds(ROTATION_TIME),
                                           FillBehavior.HoldEnd)
        axisAngleRtn3D.BeginAnimation(AxisAngleRotation3D.AngleProperty, dblAnimation)
        tr3dGroup.Children.Add(rTransform3D)
        piece.Transform = tr3dGroup
    End Sub
    
    ''' <summary>
    ''' Rotate cube piece around the X-axis
    ''' </summary>
    ''' <param name="angle">The angle of rotation; -90° or 90°</param>
    Public Sub RotateAroundXaxis(ByVal angle As Double)
        axisAngleRtn3D = New AxisAngleRotation3D(New Vector3D(1, 0, 0), 0)
        Rotate(angle)
        ChangeLocationOnXaxisRotation(angle)
    End Sub

    ''' <summary>
    ''' Rotate cube piece around the Y-axis
    ''' </summary>
    ''' <param name="angle">The angle of rotation; -90° or 90°</param>
    Public Sub RotateAroundYaxis(ByVal angle As Double)
        axisAngleRtn3D = New AxisAngleRotation3D(New Vector3D(0, 1, 0), 0)
        Rotate(angle)
        ChangeLocationOnYaxisRotation(angle)
    End Sub

    ''' <summary>
    ''' Rotate cube piece around the Z-axis
    ''' </summary>
    ''' <param name="angle">The angle of rotation; -90° or 90°</param>
    Public Sub RotateAroundZaxis(ByVal angle As Double)
        axisAngleRtn3D = New AxisAngleRotation3D(New Vector3D(0, 0, 1), 0)
        Rotate(angle)
        ChangeLocationOnZaxisRotation(angle)
    End Sub
    ...
End Class

与 Aura 界面集成

一体机应用提交的要求之一是该应用应与 Aura 界面/Horizon shell 集成。为了满足此要求,我使用 Inno Setup 创建了一个 EXE 安装程序。

 

历史

  • 2013 年 7 月 27 日:初始发布
© . All rights reserved.