好库网 好库网首页 | 我的好库
微微发软的芒果

文章分类

创建一个Windows Phone 7推箱子益智游戏

发布者:winphone
发布日期:2012/3/15 14:17:19   更新日期:2012/3/15 14:25:09
阅读次数:2581
评分:4.80
介绍:现在我们用Windows Phone 7创造一个益智游戏,使用Silverlight和XNA框架音频API的功能。
正文:

 

作者:Daniel Vaughan

 

下载源代码

 

介绍

 现在我们用Windows Phone 7创造一个益智游戏,使用Silverlight和XNA框架音频API的功能。

 

入门

 

安装WP7的工具

安装vs 2010 

安装程序将自动下载并安装所需的组件。

如果你想使用的Expression Blend 4 WP7的拓展,下载并安装Expression Blend 。

一旦安装过程完成后,重新启动Visual Studio 2010中。

 

游戏界面

这是主要的用户界面 PhoneApplicationPage。当你创建一个新的 Windows Phone 应用程序这是默认的代码。

 

PageOrientation

Windows Phone应用程式中一个重要的问题是与之匹配的布局方向,特别是检测到方向变化时,如何使我们的UI与之匹配。 PhoneApplicationPage有一个可设置的属性命名SupportedOrientations。该枚举值可以是横排(PORTRAIT)或竖排(LANDSCAPE),或者是PortraitOrLandscape的。分配给它一个值,无论是在XAML或代码中,我们可以控制应用程序如何能变换。我们采用PortraitOrLandscape,因为我希望用户根据自己的意愿自由选择。

一个值得注意的是,从用户代码设置方向是不可能的,因为它被标记为SecurityCritical。

 

SecurityCritical是大多数Silverlight开发人员熟悉的属性。 

请注意,这是Silverlight的安全,并没有具体到 Windows Phone。 

 

从反射,我们可以观察到Page.Orientation不是一个依赖项属性,(也不会引发Page.Orientation PropertyChanged事件),绑定到PhoneApplicationPage属性不会带到其它地方。

 

方向转换

我们可以简单地在OrientationChanged事件中处理,但我没有简单地这样做,而是在MainPage里创建依赖属性,当OrientationChanged事件发生时被调用。我创建了一个IValueConverter,当Page.Orientation属性改变,改变TextBlock的Visibility。

 

 

<TextBlock Visibility="{Binding ElementName=Page, Path=PageOrientation, 
    Converter={StaticResource OrientationToVisibilityConverter}, 
				ConverterParameter= Landscape}" .../>
以下代码从OrientationToVisibilityConverter中摘录,展示了转换器改变PageOrientation来改变Visibility的值。

 

 

public object Convert(object value, Type targetType, 
		object parameter, CultureInfo culture)
{
	var orientation = (PageOrientation)value;

	string showWhenOrientation = parameter.ToString().ToLower();
	bool show = false;
	switch (orientation)
	{
		case PageOrientation.Portrait:
		case PageOrientation.PortraitDown:
		case PageOrientation.PortraitUp:
			show = showWhenOrientation == "vertical";
			break;
		case PageOrientation.Landscape:
		case PageOrientation.LandscapeLeft:
		case PageOrientation.LandscapeRight:
			show = showWhenOrientation == "landscape";
			break;
	}

	return show ? Visibility.Visible : Visibility.Collapsed;
}
使用XNA Framework的音频API
我惊喜的是我们可以容易的使用XNA框架来播放音效。需要即时播放。被警告,但它有挑剔的格式。我发现,只有PCM格式的WAV文件提供了支持。我用GoldWave保存所有到PCM格式的音频。对于较长的片段,如果用MP3,更有意义,但你需要使用MediaElement控件。
所有的声音效果在MainPage.xaml.cs中的代码定义处,以下是代码演示:
readonly SoundEffect footStepSoundEffect = 
	SoundEffect.FromStream(TitleContainer.OpenStream("Audio/Footstep.wav"));
然后我们可以向这样播放声音效果:
footStepSoundEffect.Play();
MainPage实例化过程中,有一个Game实例作为其指定DataContext。
主要是控制其所有活动数据绑定和游戏属性的变化。 MainPage如下所示:
<phoneNavigation:PhoneApplicationPage 
    x:Class="DanielVaughan.Sokoban.UI.MainPage"
    x:Name="Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;
		assembly=Microsoft.Phone.Controls.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:controls="clr-namespace:DanielVaughan.Sokoban.UI" 
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
    SupportedOrientations="PortraitOrLandscape"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}" Orientation="Landscape">
    <phoneNavigation:PhoneApplicationPage.Resources>
        <controls:OrientationToVisibilityConverter 
		x:Key="OrientationToVisibilityConverter" />
        <Style x:Key="CenterLabels" TargetType="TextBlock">
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </Style>
        <Style x:Key="ToolBarWebdings" TargetType="Button">
            <Setter Property="Background">
                <Setter.Value>
                    <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                        <GradientStop Color="#FF9AFF95" Offset="0.21"/>
                        <GradientStop Color="#FF5DD757" Offset="0.589"/>
                        <GradientStop Color="#FF99FF93" Offset="1"/>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
            <Setter Property="FontFamily" Value="Webdings"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Padding" Value="5 "/>
        </Style>
        <Style x:Key="OrdinaryButton" TargetType="Button">
            <Setter Property="Background">
                <Setter.Value>
                    <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                        <GradientStop Color="#FF9AFF95" Offset="0.21"/>
                        <GradientStop Color="#FF5DD757" Offset="0.589"/>
                        <GradientStop Color="#FF99FF93" Offset="1"/>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Padding" Value="5 "/>
        </Style>
    </phoneNavigation:PhoneApplicationPage.Resources>

    <Grid x:Name="LayoutRoot" Background="White">        
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
               
        <controls:BackgroundControl Opacity=".3" />

        <Border VerticalAlignment="Top" Grid.Row="0" Height="60"  
                BorderBrush="#FFFFE63E" CornerRadius="10,10,10,10" 
		BorderThickness="2,2,2,2" Margin="0,0,0,0">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,-1.389" 
		StartPoint="0.5,2.389" SpreadMethod="Pad">
                    <GradientStop Color="#FFFF9900" Offset="1"/>
                    <GradientStop Color="#FFFF9900" Offset="0.58"/>
                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                </LinearGradientBrush>
            </Border.Background>
            <Grid>               
                <Rectangle Stroke="{x:Null}" Margin="5,3,5,18" 
                           RadiusX="10" RadiusY="10" Opacity="0.41">
                    <Rectangle.Fill>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#FFECECEC" Offset="0"/>
                            <GradientStop Color="#FFFFFFFF" Offset="1"/>
                        </LinearGradientBrush>
                    </Rectangle.Fill>
                </Rectangle>
                <StackPanel Height="50" x:Name="stackPanel1" Margin="15,0,5,0" 
                            VerticalAlignment="Center" HorizontalAlignment="Stretch" 
                            Width="Auto"  Orientation="Horizontal">
                    <TextBlock VerticalAlignment="Center" 
			Foreground="White" Text="Code:" TextWrapping="Wrap"/>
                    
                    <TextBox Text="{Binding Path=LevelCode, Mode=OneWay}"
                             x:Name="textBox_LevelCode" MaxLength="5"
                             Opacity="0.4" Width="110" TextAlignment="Center"
                             VerticalAlignment="Center" 
                             HorizontalContentAlignment="Center" 
                             GotFocus="TextBox_LevelCode_GotFocus" 
                             LostFocus="TextBox_LevelCode_LostFocus" 
                             KeyUp="TextBox_LevelCode_KeyUp"
                             Background="White" />

                    <Button Style="{StaticResource ToolBarWebdings}" 
			Margin="0,-10,0,0" Height="10" Content=""
                            Click="Button_Undo_Click"/>
                    <Button Style="{StaticResource ToolBarWebdings}" 
			Margin="0,-10,0,0" Height="10" Content=""
                            Click="Button_Redo_Click"/>
                    <TextBlock Visibility="{Binding ElementName=Page, 
			Path=PageOrientation, 
                            Converter={StaticResource OrientationToVisibilityConverter}, 
			ConverterParameter=Landscape}"
                        VerticalAlignment="Center" HorizontalAlignment="Center" 
                               TextAlignment="Center" Foreground="White" 
				Text="Alien Sokoban" 
                               FontFamily="Tahoma" FontSize="36" Margin="45,0,0,0"/>
                </StackPanel>
                <Grid HorizontalAlignment="Right">
                    <StackPanel Orientation="Horizontal">
                        <StackPanel VerticalAlignment="Center">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Style="{StaticResource CenterLabels}" 
				Text="Level "/>
                                <TextBlock x:Name="label_LevelNumber" 
                                           Style="{StaticResource CenterLabels}" 
                                           Text="{Binding Path=Level.LevelNumber}"/>
                                <TextBlock Style=
				"{StaticResource CenterLabels}" Text="/"/>
                                <TextBlock Style="{StaticResource CenterLabels}" 
				Text="{Binding Path=LevelCount}"/>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Style="{StaticResource CenterLabels}" 
				Text="Moves "/>
                                <TextBlock x:Name="label_Moves" 
				Style="{StaticResource CenterLabels}" 
                                           Text="{Binding Path=Level.Actor.MoveCount}"/>
                            </StackPanel>
                        </StackPanel>
                        <Button Style="{StaticResource ToolBarWebdings}" 
				Margin="0,-8,0,0" 
                                Height="10" x:Name="button_RestartLevel" Width="80" 
                                Click="Button_RestartLevel_Click" 
                                IsTabStop="False"  Content=""
                                HorizontalAlignment="Right" >
                            <ToolTipService.ToolTip>
                                <ToolTip Content="Restart"></ToolTip>
                            </ToolTipService.ToolTip>
                        </Button>
                    </StackPanel>

                </Grid>
            </Grid>
        </Border>
        <!-- The Game grid. -->
        <Border Grid.Row="1" Padding="5" BorderBrush="#919292" CornerRadius="12" 
                BorderThickness="0" Background="Transparent">
            <Grid x:Name="grid_Game" />
        </Border>

        <Grid x:Name="textBlock_PressAnyKey" 
              Background="#006DCAC1"
              HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.RowSpan="2">
            <StackPanel VerticalAlignment="Center" HorizontalAlignment="Stretch" 
                        Background="#556DCAC1">
                <TextBlock x:Name="feedbackControl" 
                           VerticalAlignment="Center"
                           HorizontalAlignment="Center" Text="TextBlock" FontSize="32"/>
                <Button Style="{StaticResource OrdinaryButton}" Content="Continue" 
                        VerticalAlignment="Center" HorizontalAlignment="Center"
                        Click="Button_Continue_Click"/>     
            </StackPanel>
        </Grid>
    </Grid>
    
</phoneNavigation:PhoneApplicationPage>
在MainPage的InitializeLevel方法中,每个网格用CellControl填充:
void InitialiseLevel()
{
	cellControls.Clear();
	commandManager.Clear();

	grid_Game.Children.Clear();
	grid_Game.RowDefinitions.Clear();
	grid_Game.ColumnDefinitions.Clear();

	for (int i = 0; i < Game.Level.RowCount; i++)
	{
		grid_Game.RowDefinitions.Add(new RowDefinition());
	}

	for (int i = 0; i < Game.Level.ColumnCount; i++)
	{
		grid_Game.ColumnDefinitions.Add(new ColumnDefinition());
	}

	var cellSize = CalculateCellSize();
	
	for (int row = 0; row < Game.Level.RowCount; row++)
	{
		for (int column = 0; column < Game.Level.ColumnCount; column++)
		{
			Cell cell = Game.Level[row, column];
			cell.PropertyChanged += cell_PropertyChanged;

			CellControl cellControl = new CellControl(cell);
			cellControl.MaxHeight = cellControl.MaxWidth = cellSize;
			cellControl.Click += Cell_Click;

			Grid.SetColumn(cellControl, column);
			Grid.SetRow(cellControl, row);
			grid_Game.Children.Add(cellControl);
			cellControls.Add(cellControl);
		}
	}

	/* Play the intro audio clip. */
	PlayAudioClip(introSoundEffect);
	/* Listen for actor property changes. */
	//Game.Level.Actor.PropertyChanged += Actor_PropertyChanged;

	RefreshGameGrid();
}
通常,我不会建议把这样的UI逻辑代码放在代码的旁边,因为我更喜欢使用MVVM方法。 然而权宜之计,我就用这个方法。
该CellControl被分配给一个游戏网格,显示效果由单元格的状态而定。 如果它被认为是一堵墙,它显示一个灰色正方形等。
Phone屏幕键盘
Windows Phone 7允许开发者在用户打开屏幕键盘时指定数据类型。这也是上下文敏感的,TextBox获得焦点时,TextBox将被放大。使用InputScope使键盘更适合于正在输入的数据。
例如,要指定一个默认的屏幕键盘,需应用InputScope到该TextBox 。
<TextBox> 
  <TextBox.InputScope> 
    <InputScope> 
      <InputScope.Names> 
        <InputScopeName NameValue="EmailNameOrAddress"/> 
      </InputScope.Names> 
    </InputScope> 
  </TextBox.InputScope> 
</TextBox>
通过使用EmailNameOrAddress NameValue,键盘包含了.com 和 @等字符。
以下是一些有效取值:
SIP 布局 XAML 或枚举值 SIP 描述
Default Default, and other standard input scope values 标准 QWERTY 键盘
Text Text 带特性的text,如自动更正和单词建议。
Web Url  URL
E-mail address EmailSmtpAddress  e-mail 地址
E-mail name or address EmailNameOrAddress  电子邮件名称或地址
Maps Maps 搜索在地图上的位置
Phone number TelephoneNumber 电话号码
Search Search 搜索查询
SMS contact NameOrPhoneNumber 短信
Chat Chat 文字输入,使用智能功能,如缩写

 

 

结论

 

在这篇文章中,我们已经看到了如何使用Silverlight 3创建一个Windows Phone益智游戏。 我们看到了PageOrientation和如何将其应用于控制布局。 我们根据上下文可以选择不同的键盘,我们还简要接触了XNA Framework的音频API,它可以用来播放声音效果。

 

这个平台的未来,我很兴奋。 花费了一个短暂的时间后,我已经有宾至如归的感觉。 我希望这个项目对你非常有用。 如果是的话,那么我会很感激,如果你能反馈一下,这会帮助我,使我的下一篇文章更好。

 

 


评论 [发表评论]
账号 密码 还没帐号呢,现在注册一个?

免责声明:好库网所展示的信息由买卖双方自行提供,其真实性、准确性和合法性由信息发布人负责。好库网不提供任何保证,并不承担任何法律责任。