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 Flyout
s 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
Public Sub RotateAroundXaxis(ByVal angle As Double)
axisAngleRtn3D = New AxisAngleRotation3D(New Vector3D(1, 0, 0), 0)
Rotate(angle)
ChangeLocationOnXaxisRotation(angle)
End Sub
Public Sub RotateAroundYaxis(ByVal angle As Double)
axisAngleRtn3D = New AxisAngleRotation3D(New Vector3D(0, 1, 0), 0)
Rotate(angle)
ChangeLocationOnYaxisRotation(angle)
End Sub
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