WPF实战俄罗斯方块

简介: 原文:WPF实战俄罗斯方块概述 本文试图通过经典的游戏-俄罗斯方块,来演示WPF强大的图形界面编程功能。 涉及的图形方面有这几个方面: 1、不规则界面的设置 2、布局系统的使用 3、2D图形的应用 4、输入事件的响应 5、风格样式的使用 6、跨线程的调用 7、自定义控件 我们先截两张成品的图片,获取一点感性的认识。
原文: WPF实战俄罗斯方块

概述

本文试图通过经典的游戏-俄罗斯方块,来演示WPF强大的图形界面编程功能。

涉及的图形方面有这几个方面:

1、不规则界面的设置

2、布局系统的使用

3、2D图形的应用

4、输入事件的响应

5、风格样式的使用

6、跨线程的调用

7、自定义控件

我们先截两张成品的图片,获取一点感性的认识。截图如下:

图1

图2

以上两张图中,整个程序界面已经和市场上的游戏比较接近。7种形状分别以不同的颜色进行区分,可以快速下落,一键下落,开始、暂停、算分,基本上功能全了。

实现

那这个程序究竟是怎么实现的呢?实际上,我在逻辑的层面,把它成分了两个层次,一个是图形展示层,一个是游戏算法实现层。游戏算法尽量地与图形界面分离,这样同的算法可以比较轻松地移植到别的平台上,比如用H5实现,或是用D3D实现等等,你只要关注不同平台的图形显示部分即可。

界面

界面上,除了基础的元素如分数、级别、启停按钮等,还对整体做了个性化的定制。比如使用了椭圆的程序界面,游戏主体部分使用了阴影显示,用一个动画显示欢迎信息等。

下边,我们一步一步把程序拆分开来。

1、主窗体部分

主窗体部分主要由Xaml来实现,包括其中的动画部分。

1)椭圆的实现

WPF中设置图形界面是十分的方便,整个应用程序就是一个大画布,想怎么画就怎么画。就算根窗体,一个Clip属性就可以改变它的形状。这里用的是.Net Framework里自带的

EllipseGeometry 类,只要设置两个半径和中心点即可。这里有别于Winform下边的GDI实现,不需要显式的调用图形API去画图。具体代码如下:
    <Window.Clip>
        <EllipseGeometry RadiusX="470" RadiusY="340" Center="512,384"/>
    </Window.Clip>

2)动画的实现

动画的实现,可以自己手动写代码。不过,可以通过VS Blend更方便的实现动画。这里将左边的“俄罗斯广场欢迎你!”几个字做一个随意的动画。为了提高开发效率,这里使用了Blend来制作的动画。下边的Blend的操作界面:

图3

以下是通过编辑器生成的代码:

-定义触发器

 <Window.Triggers>

        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
        </EventTrigger>

    </Window.Triggers>

-定义资源

<Window.Resources>
        <Storyboard x:Key="OnLoaded1" RepeatBehavior="Forever">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="label">
                <EasingDoubleKeyFrame KeyTime="0" Value="-24"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="69"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="-9"/>
                <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-115.5"/>
                <EasingDoubleKeyFrame KeyTime="0:0:4" Value="-90"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="label">
                <EasingDoubleKeyFrame KeyTime="0" Value="-21"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="3"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="100.5"/>
                <EasingDoubleKeyFrame KeyTime="0:0:3" Value="90"/>
                <EasingDoubleKeyFrame KeyTime="0:0:4" Value="-21"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="label">
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="-169.33"/>
                <EasingDoubleKeyFrame KeyTime="0:0:3" Value="150.377"/>
                <EasingDoubleKeyFrame KeyTime="0:0:4" Value="-3.442"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>

注:WPF任何属性定义都可以当作资源来重用。

3)花式按钮

这个比较简单,也就是设置了一下本身的样式。

编辑器窗口:

代码如下:

<Button Content="X" ToolTip="关闭" Focusable="False" HorizontalAlignment="Left" Margin="828,320,0,0" VerticalAlignment="Top" Width="75" Height="79" FontSize="36" Foreground="#FFA62121" Click="Button_Click">
            <Button.Background>
                <RadialGradientBrush>
                    <GradientStop Color="White" Offset="0"/>
                    <GradientStop Color="#FF6FDABD" Offset="1"/>
                </RadialGradientBrush>
            </Button.Background>
        </Button>

4)Grid布局

界面元素的摆放,可以通过绝对坐标的方式,但这种方式通常需要手工编码的方式去计算元素的位置,所以在复杂的应用系统中是不建议使用的。那么为了简化界面元素的排列,于是便有了布局系统。一般比较细粒度的一点的控制,多采用Grid,这里也采用了Grid。Grid主要是将界面分成若干行和列,然后将元素放入其中,类似Html中的Table,这里不赘述。

下边是一个一行两列的Grid,Grid本身铺满父容器。

 <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="300*"/>
        </Grid.ColumnDefinitions>
...
</Grid>

5)容器的拖拽

这里也很简单,写一段响应MouseDown事件的代码:

 private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }   

6)自定义控件

网格线的实现,及预置方块。代码如下:

private void UserControl_Initialized(object sender, EventArgs e)
        {
            for (var col = 0; col <= 10; col++)
            {
                Line line = new Line();
                line.X1 = col * 30;
                line.X2 = col * 30;
                line.Y1 = 0;
                line.Y2 = 600;
                line.Stroke = new SolidColorBrush(Color.FromArgb(0xFF, 0, 0, 1));
                grid.Children.Add(line);
            }

            for (var row = 0; row <= 20; row++)
            {
                Line line = new Line();
                line.X1 = 0;
                line.X2 = 300;
                line.Y1 = row * 30;
                line.Y2 = row * 30;
                line.Stroke = new SolidColorBrush(Color.FromArgb(0xFF, 0, 0, 1));
                grid.Children.Add(line);
            }

            for (int row = 0; row < 20; row++)
            {
                for (int col = 0; col < 10; col++)
                {
                    bool show = datas[row, col];
                    Cube cube = new Cube();
                    cube.Width = 24;
                    cube.Height = 24;
                    cube.HorizontalAlignment = HorizontalAlignment.Left;
                    cube.VerticalAlignment = VerticalAlignment.Top;
                    if (show)
                    {
                        cube.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        cube.Visibility = Visibility.Hidden;
                    }
                    var m = cube.Margin;
                    cube.Margin = new Thickness(m.Left + col * 30 + 3, m.Top + row * 30 + 3, m.Right, m.Bottom);
                    cubes[row, col] = cube;
                    grid.Children.Add(cube);
                }
            }
        }

 

算法

本程序的算法,主要是通过两个二维数组来实现的。

具体算法略。

源码

目录
相关文章
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
310 1
|
前端开发 C# 开发者
WPF开发者必读:MVVM模式实战,轻松构建可维护的应用程序,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离关注点,提高了代码的可维护性和可扩展性。本文详细介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定与逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种模式,开发者可以更高效地构建桌面应用程序。希望本文能帮助你在WPF开发中更好地应用MVVM模式。
653 1
|
C# 开发者 Windows
勇敢迈出第一步:手把手教你如何在WPF开源项目中贡献你的第一行代码,从选择项目到提交PR的全过程解析与实战技巧分享
【8月更文挑战第31天】本文指导您如何在Windows Presentation Foundation(WPF)相关的开源项目中贡献代码。无论您是初学者还是有经验的开发者,参与这类项目都能加深对WPF框架的理解并拓展职业履历。文章推荐了一些适合入门的项目如MvvmLight和MahApps.Metro,并详细介绍了从选择项目、设置开发环境到提交代码的全过程。通过具体示例,如添加按钮点击事件处理程序,帮助您迈出第一步。此外,还强调了提交Pull Request时保持专业沟通的重要性。参与开源不仅能提升技能,还能促进社区交流。
144 0
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
1033 0
|
C# 开发者 Windows
WPF遇上Office:一场关于Word与Excel自动化操作的技术盛宴,从环境搭建到代码实战,看WPF如何玩转文档处理的那些事儿
【8月更文挑战第31天】Windows Presentation Foundation (WPF) 是 .NET Framework 的重要组件,以其强大的图形界面和灵活的数据绑定功能著称。本文通过具体示例代码,介绍如何在 WPF 应用中实现 Word 和 Excel 文档的自动化操作,包括文档的读取、编辑和保存等。首先创建 WPF 项目并设计用户界面,然后在 `MainWindow.xaml.cs` 中编写逻辑代码,利用 `Microsoft.Office.Interop` 命名空间实现 Office 文档的自动化处理。文章还提供了注意事项,帮助开发者避免常见问题。
860 0
|
C# 前端开发 UED
WPF数据验证实战:内置控件与自定义规则,带你玩转前端数据验证,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据验证是确保输入正确性的关键环节。前端验证能及时发现错误,提升用户体验和程序可靠性。本文对比了几种常用的WPF数据验证方法,并通过示例展示了如何使用内置验证控件(如`TextBox`)及自定义验证规则实现有效验证。内置控件结合`Validation`类可快速实现简单验证;自定义规则则提供了更灵活的复杂逻辑支持。希望本文能帮助开发者更好地进行WPF数据验证。
380 0
|
前端开发 开发者 C#
WPF开发者必读:MVVM模式实战,轻松实现现代桌面应用架构,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离应用程序的逻辑和界面,提高了代码的可维护性和可扩展性。本文介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定和逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种方式,开发者可以构建更加高效和可扩展的桌面应用程序。
655 0
|
数据处理 开发者 C#
WPF数据绑定实战:从零开始,带你玩转数据与界面同步,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据绑定是核心技能之一,它能实现界面元素与数据源的同步更新。本文详细介绍了WPF数据绑定的概念与实现方法,包括属性绑定、元素绑定及路径绑定等技术,并通过示例代码展示了如何创建数据绑定。通过数据绑定,开发者不仅能简化代码、提高可维护性,还能提升用户体验。无论初学者还是有经验的开发者,都能从中受益,更好地掌握WPF数据绑定技巧。
276 0
|
C# Windows IDE
WPF入门实战:零基础快速搭建第一个应用程序,让你的开发之旅更上一层楼!
【8月更文挑战第31天】在软件开发领域,WPF(Windows Presentation Foundation)是一种流行的图形界面技术,用于创建桌面应用程序。本文详细介绍如何快速搭建首个WPF应用,包括安装.NET Framework和Visual Studio、理解基础概念、创建新项目、设计界面、添加逻辑及运行调试等关键步骤,帮助初学者顺利入门并完成简单应用的开发。
545 0
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
626 0