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

WPF 中的 PaddingBall 游戏

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (7投票s)

2008年6月5日

CPOL

3分钟阅读

viewsIcon

47960

downloadIcon

2284

本文展示了如何使用 WPF 开发 Padding Ball 游戏。

介绍/背景

还记得那些美好的旧时光吗,当时有一款游戏,使用一个小挡板让球在屏幕的所有角落移动,还有一款“打砖块”游戏,通过打破堆叠在窗口顶部的砖块来扫除我们所有的快乐。

本文讲述了使用 WPF 技术开发一款名为“Paddling Ball”的小游戏,这只是一个类似演示的游戏,它使用很少的用户交互,并且没有太多的图形项目。

游戏窗口

XAML 允许您以声明方式创建菜单、球和挡板对象,如下所示

<Window x:Class="PaddingBall.Window1" 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  Title="Padding Ball v1.0" Height="500" 
  Width="700" Background="Gray" 
  Name="playground" ResizeMode="NoResize" 
  WindowStartupLocation="CenterScreen" SizeToContent="Manual"> 
<Canvas Width="700" Height="500"> 
<Menu VerticalAlignment="Top" HorizontalAlignment="Left" 
  Height="20" Width="700" 
  Background="AliceBlue" Foreground="Blue"> 
<MenuItem Header="File"> 
<MenuItem Header="Start Game" 
  Background="AliceBlue" Click="StartGame"></MenuItem> 
<MenuItem Header="Exit" Background="AliceBlue" 
  Click="ExitGame"></MenuItem> 
</MenuItem> 
<MenuItem Header="About" 
       Click="ShowAboutBox"></MenuItem> 
</Menu> 
<Grid Height="462" Width="700"> 
<Grid.ColumnDefinitions> 
<ColumnDefinition Width="700*" /> 
<ColumnDefinition Width="0*" /> 
<ColumnDefinition Width="0*" /> 
</Grid.ColumnDefinitions> 
<Rectangle Margin="114,132,0,0" Name="ball" 
  Stroke="Black" RadiusX="120" RadiusY="120" 
  Fill="Blue" Height="38" VerticalAlignment="Top" 
  Stretch="UniformToFill" 
  HorizontalAlignment="Left" Width="38"> 
<Rectangle.BitmapEffect> 
<BevelBitmapEffect BevelWidth="11" /> 
</Rectangle.BitmapEffect> 
<Rectangle.BitmapEffectInput> 
<BitmapEffectInput /> 
</Rectangle.BitmapEffectInput> 
</Rectangle> 
<Rectangle Height="13" Margin="200,390,0,0" 
  Name="pad" Stroke="Black" VerticalAlignment="Bottom" 
  Fill="Black" HorizontalAlignment="Left" Width="100" /> 
</Grid> 
</Canvas> 
</Window>

paddingballmenu.jpg

正如您所看到的,每个菜单项都绑定到 Click 事件的相应事件处理程序。当您打开应用程序时,您会看到一个窗口,其顶部带有菜单栏。您可以通过在“文件”菜单中选择“开始游戏”命令来开始游戏。

WPF 的应用

在使用 WPF 开发这款游戏时,我发现借助 XAML 可以更轻松地绘制球、挡板和背景。另一方面,游戏的行为部分仍然有其自身的复杂性,尤其是在球和挡板的动画过程中。尽管如此,通过用户的键盘交互来控制动画的实现,为我提供了 WPF 编程的新思路。

球和挡板的大部分动画和定位都是使用 System.Windows 命名空间中的 Thickness 结构和 PresentationFramework.dll 程序集的 System.Windows.Media.Animation 命名空间中的 ThicknessAnimation 类完成的。

Thickness 结构描述了矩形周围框架的粗细,在本例中,是 BallPad。四个 double 值分别描述了封装 BallPad 对象的矩形的 LeftTopRightBottom 边。

ThicknessAnimation 类创建两个目标值之间的过渡。要设置其目标值,请使用窗口内 BallPad 元素的 FromTo 属性。

不用说,我们需要一个 StoryBoard 对象来承载整个动画。为 BallPad 对象创建的 ThicknessAnimation 实例,以及指定的持续时间,都作为子项添加到 StoryBoard,我们使用 Begin 方法来启动动画。

这是在用户按下向右和向左箭头键时为挡板设置动画的代码

void AnimatePad(double x) 
{ 
    moveThePad = new ThicknessAnimation(); 
    moveThePad.From = PadCurrentPos; 
    moveThePad.To = new Thickness(pad.Margin.Left+x, pad.Margin.Top, 0, 0); 
    moveThePad.Duration = new Duration(TimeSpan.FromSeconds(0)); 
    Storyboard.SetTargetName(moveThePad, "pad"); 
    Storyboard.SetTargetProperty(moveThePad, 
       new PropertyPath(Rectangle.MarginProperty)); 
    PlayPad = new Storyboard(); 
    if (PlayPad.Children.Count > 0) 
    PlayPad.Children.RemoveAt(0); 
    PlayPad.Children.Add(moveThePad); 
    PlayPad.Begin(this, true); 
}

x 指的是为挡板的目标位置(MarginLeft 属性)指定的增量或减量值。这可以通过在窗口的 KeyDown 事件中编写以下代码轻松完成

void playground_KeyDown(object sender, KeyEventArgs e) 
{ 
    PadCurrentPos = pad.Margin; 
    double xPadValue=0; 
    if (e.Key == Key.Left) 
        if (pad.Margin.Left > -100) 
            xPadValue = -50; 
    if (e.Key == Key.Right) 
        if (pad.Margin.Left <= (playground.Width - pad.Width)) 
    xPadValue = 50; 
    AnimatePad(xPadValue); 
}

为球设置动画

当球在窗口内移动时,MarginLeftTop 属性会发生变化,并立即触发特定 WPF 元素的 LayoutUpdated 事件。在那里,我们可以编写一些代码来控制动画球的行为,例如检查它是否越过窗口的边界,或者球是否被挡板击中。

void ball_LayoutUpdated(object sender, EventArgs e) 
{
    BallCurrentPos = ball.Margin; 
    if (((ball.Margin.Top - ball.Height) >= pad.Margin.Top) && 
          ball.Margin.Left >= pad.Margin.Left && 
          ball.Margin.Left <= (pad.Margin.Left + 30)) 
    { 
        BallNextPos.Top = 0; 
        BallNextPos.Left = BallCurrentPos.Left - 200; 
        AnimateBall(BallNextPos, BallCurrentPos); 
    } 
    else if (((ball.Margin.Top - ball.Height) >= pad.Margin.Top) && 
               ball.Margin.Left >= (pad.Margin.Left + 30) && 
               ball.Margin.Left <= (pad.Margin.Left + 60)) 
    { 
    BallNextPos.Top = 0; 
    AnimateBall(BallNextPos, BallCurrentPos); 
    } 
    else if (((ball.Margin.Top - ball.Height) >= pad.Margin.Top) && 
               ball.Margin.Left >= (pad.Margin.Left + 60) && 
               ball.Margin.Left <= (pad.Margin.Left + 100)) 
    { 
        BallNextPos.Top = 0; 
        BallNextPos.Left = BallCurrentPos.Left + 200; 
        AnimateBall(BallNextPos, BallCurrentPos); 
    } 
    else if (ball.Margin.Top <= 5) 
    { 
        BallNextPos.Top = playground.Height; 
        AnimateBall(BallNextPos, BallCurrentPos); 
    } 
    else if (ball.Margin.Left <= 0) 
    { 
        BallNextPos.Left = playground.Width; 
        AnimateBall(BallNextPos, BallCurrentPos); 
    } 
    else if (ball.Margin.Left >= playground.Width - 50) 
    { 
        BallNextPos.Left = 0; 
        AnimateBall(BallNextPos, BallCurrentPos); 
    }
}

当您在菜单栏中选择“关于”命令时,您将获得有关游戏的有用信息和说明。

PaddingBall

摘要

回到 WPF 环境中并带回挡板和球是一次不错的体验。除了用挡板打球之外,还有很多事情要做,例如设置游戏时长、球的数量以及计算玩家获得的分数。当这些功能得到实现时,对于任何人来说,它都将是一款完美的游戏,可以充分展示 WPF 的功能。希望我能推出游戏的第 2 版。

© . All rights reserved.