Click here to Skip to main content
Click here to Skip to main content

GesturCubes

, 4 Nov 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
WPF 3D cubes puzzle game for the AIO(All-In-One) PC

Please note

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.

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.

2x2 cube mode

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.

3x3 cube model in Blender

Expression Design

Expression Blend

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

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

 

To animate the addition and removal of items in the ItemsControl I use 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>

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

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

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.

 

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)

Share

About the Author

Meshack Musundi
Software Developer
Kenya Kenya
Meshack is an avid programmer with a bias towards WPF and VB.NET. He has about 5 years of programming experience initially starting off with Java before shifting to .NET, thanks to the allure of WPF. He has developed several applications, and written several articles about them, which can be viewed here on CodeProject. He currently resides in a small town in Kiambu county, Kenya.
 
Awards;
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • Best VB.NET article of August 2013
  • Best VB.NET article of February 2013
  • Best VB.NET article of October 2012
  • Best VB.NET article of July 2012
  • Best VB.NET article of February 2012
  • Best VB.NET article of January 2012
  • Best VB.NET article of November 2011
  • Best VB.NET article of June 2011
  • Best VB.NET article of May 2011
  • Best VB.NET article of March 2011
  • Best VB.NET article of February 2011
  • Best VB.NET article of January 2011
  • Best VB.NET article of December 2010
  • Best VB.NET article of November 2010

Comments and Discussions

 
QuestionInno Setup problems PinprofessionalChris Boss12-Nov-13 7:53 
AnswerRe: Inno Setup problems PinmvpMeshack Musundi12-Nov-13 8:15 
GeneralRe: Inno Setup problems PinprofessionalChris Boss12-Nov-13 8:26 
QuestionHow's app development going? Will you be submitting on time? PinstaffKevin Priddle24-Oct-13 6:54 
AnswerRe: How's app development going? Will you be submitting on time? PinmvpMeshack Musundi25-Oct-13 7:01 
GeneralRe: How's app development going? Will you be submitting on time? PinstaffKevin Priddle25-Oct-13 11:50 
GeneralMy vote of 5 PinmemberSudhanshu SP Gupta10-Sep-13 21:31 
GeneralRe: My vote of 5 PinmvpMeshack Musundi10-Sep-13 21:52 
AdminThanks for entering the Intel AIC 2013! PinstaffKevin Priddle15-Aug-13 11:03 
GeneralRe: Thanks for entering the Intel AIC 2013! PinmvpMeshack Musundi15-Aug-13 22:18 
GeneralMy vote of 5 Pinmemberayesha238-Aug-13 1:11 
GeneralRe: My vote of 5 PinmvpMeshack Musundi8-Aug-13 2:36 
GeneralMy vote of 5 PinprofessionalAhmed Bensaid29-Jul-13 0:12 
GeneralRe: My vote of 5 PinmvpMeshack Musundi29-Jul-13 0:16 
GeneralMy vote of 5 PinmemberAbhishek Nandy27-Jul-13 4:47 
GeneralRe: My vote of 5 PinmvpMeshack Musundi27-Jul-13 7:53 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 5 Nov 2013
Article Copyright 2013 by Meshack Musundi
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid