Click here to Skip to main content
15,860,861 members
Articles / Desktop Programming / WPF

GesturCubes

Rate me:
Please Sign up or sign in to vote.
5.00/5 (16 votes)
4 Nov 2013CPOL2 min read 33.9K   13   16
WPF 3D cubes puzzle game for the AIO(All-In-One) PC

This article is an entry in our AppInnovation Contest. Articles in this sub-section are not required to be full articles so care should be taken when voting.

Image 1

Overview

GesturCubes is a puzzle game targeted at the Lenovo Horizon 27" All-In-One® PC. It provides a fun and challenging experience with two modes of play; 2x2 cube mode and 3x3 cube mode.

Image 2

2x2 cube mode

Image 3

Features

Taking into consideration the capabilities of the AIO, GesturCubes incorporates the following features;

  • Multi-touch interface: The app takes advantage of the touch capability of the AIO allowing user/users to solve cubes, switch modes, and start the timer through touch interaction and controls. GesturCubes manages to do this by utilizing WPF's multi-touch support.  
  • Multi-user interface: One of the nice features of the Lenovo Horizon 27" All-In-One® is the large screen. GesturCubes takes advantage of this feature to provide a collaborative multi-user experience: The layout of UI elements enables two users to comfortably sit side-by-side and do a cube team solve in a more fun and easy way.
  • Multi-modal interaction: Users can solve, scramble, and switch between game modes using voice commands. 

Design

GesturCubes is a WPF application and contains several UI elements which I designed in Blender, Expression Design, and Expression Blend. The 3D cube models were designed in Blender, while some of the other UI elements, like the palm control for the timer, were designed in Expression Design. Everything was put together in Expression Blend.

Image 4

3x3 cube model in Blender

Image 5

Expression Design

Image 6

Expression Blend

The application makes use of MahApp.Metro for window styling.

XML
<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>
    ...

There are two MahApps.Metro Flyouts for displaying solve times.

Image 7 

To animate the addition and removal of items in the ItemsControl I use FluidMoveBehavior.

XML
<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>

The following is the xaml markup for the ItemsControl's DataTemplate,

XML
<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>

Code

The application is written in VB.NET. The following code snippet shows some of the methods in class CubePiece which are used to rotate a cube piece around the x, y, and z axes.

VB.NET
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

Integration with Aura Interface

One of the requirements for the All-in-One app submission is that the app should integrate with the Aura interface/Horizon shell. To meet this requirement I've created a EXE installer using Inno Setup.

Image 8 

History

  • 27th July 2013: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Kenya Kenya
Experienced C# software developer with a passion for WPF.

Awards,
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • CodeProject MVP 2021

Comments and Discussions

 
QuestionInno Setup problems Pin
Chris Boss12-Nov-13 6:53
professionalChris Boss12-Nov-13 6:53 
AnswerRe: Inno Setup problems Pin
Meshack Musundi12-Nov-13 7:15
professionalMeshack Musundi12-Nov-13 7:15 
Hi Chris, I did not have problems when creating the installer. I'm taking a look at your script. Will get back to you in a bit.
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"

GeneralRe: Inno Setup problems Pin
Chris Boss12-Nov-13 7:26
professionalChris Boss12-Nov-13 7:26 
QuestionHow's app development going? Will you be submitting on time? Pin
Kevin Priddle24-Oct-13 5:54
professionalKevin Priddle24-Oct-13 5:54 
AnswerRe: How's app development going? Will you be submitting on time? Pin
Meshack Musundi25-Oct-13 6:01
professionalMeshack Musundi25-Oct-13 6:01 
GeneralRe: How's app development going? Will you be submitting on time? Pin
Kevin Priddle25-Oct-13 10:50
professionalKevin Priddle25-Oct-13 10:50 
GeneralMy vote of 5 Pin
Sudhanshu SP Gupta10-Sep-13 20:31
Sudhanshu SP Gupta10-Sep-13 20:31 
GeneralRe: My vote of 5 Pin
Meshack Musundi10-Sep-13 20:52
professionalMeshack Musundi10-Sep-13 20:52 
AdminThanks for entering the Intel AIC 2013! Pin
Kevin Priddle15-Aug-13 10:03
professionalKevin Priddle15-Aug-13 10:03 
GeneralRe: Thanks for entering the Intel AIC 2013! Pin
Meshack Musundi15-Aug-13 21:18
professionalMeshack Musundi15-Aug-13 21:18 
GeneralMy vote of 5 Pin
ayesha238-Aug-13 0:11
ayesha238-Aug-13 0:11 
GeneralRe: My vote of 5 Pin
Meshack Musundi8-Aug-13 1:36
professionalMeshack Musundi8-Aug-13 1:36 
GeneralMy vote of 5 Pin
Ahmed Bensaid28-Jul-13 23:12
professionalAhmed Bensaid28-Jul-13 23:12 
GeneralRe: My vote of 5 Pin
Meshack Musundi28-Jul-13 23:16
professionalMeshack Musundi28-Jul-13 23:16 
GeneralMy vote of 5 Pin
Abhishek Nandy27-Jul-13 3:47
professionalAbhishek Nandy27-Jul-13 3:47 
GeneralRe: My vote of 5 Pin
Meshack Musundi27-Jul-13 6:53
professionalMeshack Musundi27-Jul-13 6:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.