├── lib ├── SharpDX.dll ├── SharpDX.DXGI.dll ├── SharpDX.Direct2D1.dll ├── SharpDX.Direct3D11.dll └── License.txt ├── Cyjb.Projects.JigsawGame ├── JigsawGame.ico ├── GlobalSuppressions.cs ├── Resources │ ├── Loading.gif │ ├── JigsawHelp.png │ ├── Settings.png │ ├── ShowThumb.png │ ├── ShowBackground.png │ └── ShowBorderOnly.png ├── Jigsaw │ ├── JigsawPieceType.cs │ ├── JigsawPieceState.cs │ └── JigsawPieceSelectedCollection.cs ├── Renderer │ ├── JigsawRendererType.cs │ ├── JigsawScaleChangedEventArgs.cs │ ├── JigsawRenderer.cs │ ├── JigsawSimpleRenderer.cs │ └── JigsawRenderPanel.cs ├── Shape │ ├── PathType.cs │ ├── JigsawShapeType.cs │ ├── LineSegment.cs │ ├── EndFigureSegment.cs │ ├── PathSegment.cs │ ├── BezierSegment.cs │ ├── JigsawStandardCircleShape.cs │ ├── JigsawStandardShape.cs │ ├── ArcSegment.cs │ ├── JigsawStandardSmoothShape.cs │ ├── Path.cs │ └── JigsawShape.cs ├── Cyjb.Projects.JigsawGame.csproj.user ├── WinFormUtility.cs ├── LoadingForm.cs ├── JigsawSerializeContext.cs ├── Program.cs ├── HelpForm.cs ├── ToolForm.Designer.cs ├── AssemblyInfo.cs ├── JigsawInfo.cs ├── BugReportForm.cs ├── ThumbForm.Designer.cs ├── LoadingForm.Designer.cs ├── SettingForm.cs ├── ToolForm.cs ├── JigsawSetting.settings ├── App.config ├── SharpDXUtility.cs ├── BugReportForm.Designer.cs ├── ThumbForm.cs ├── Resources.Designer.cs ├── HelpForm.Designer.cs ├── HelpForm.resx ├── LoadingForm.resx ├── ThumbForm.resx ├── BugReportForm.resx ├── NewGameForm.resx ├── SettingForm.resx ├── Resources.resx ├── SettingForm.Designer.cs ├── JigsawSetting.Designer.cs ├── NewGameForm.cs ├── Cyjb.Projects.JigsawGame.csproj ├── DeviceManager.cs └── MainForm.Designer.cs ├── .gitignore ├── README.md └── Cyjb.Projects.JigsawGame.sln /lib/SharpDX.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/lib/SharpDX.dll -------------------------------------------------------------------------------- /lib/SharpDX.DXGI.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/lib/SharpDX.DXGI.dll -------------------------------------------------------------------------------- /lib/SharpDX.Direct2D1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/lib/SharpDX.Direct2D1.dll -------------------------------------------------------------------------------- /lib/SharpDX.Direct3D11.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/lib/SharpDX.Direct3D11.dll -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/JigsawGame.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/JigsawGame.ico -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/GlobalSuppressions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/GlobalSuppressions.cs -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources/Loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/Resources/Loading.gif -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources/JigsawHelp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/Resources/JigsawHelp.png -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/Resources/Settings.png -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources/ShowThumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/Resources/ShowThumb.png -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources/ShowBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/Resources/ShowBackground.png -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources/ShowBorderOnly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CYJB/Cyjb.Projects.JigsawGame/HEAD/Cyjb.Projects.JigsawGame/Resources/ShowBorderOnly.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | bin 3 | obj 4 | Properties 5 | *.pdb 6 | 7 | # mstest test results 8 | TestResults 9 | 10 | # my test project 11 | ConsoleTest 12 | 13 | # files 14 | *.suo 15 | *.snk 16 | *.vspx -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Jigsaw/JigsawPieceType.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame.Jigsaw 2 | { 3 | /// 4 | /// 表示拼图碎片的类型。 5 | /// 6 | public enum JigsawPieceType 7 | { 8 | /// 9 | /// 普通碎片。 10 | /// 11 | Normal, 12 | /// 13 | /// 边界碎片。 14 | /// 15 | Border 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Renderer/JigsawRendererType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Cyjb.Projects.JigsawGame.Renderer 4 | { 5 | /// 6 | /// 拼图渲染器的类型。 7 | /// 8 | public enum JigsawRendererType 9 | { 10 | /// 11 | /// 简单渲染器。 12 | /// 13 | [Description("简单渲染器")] 14 | Simple, 15 | /// 16 | /// 特效渲染器。 17 | /// 18 | [Description("特效渲染器")] 19 | Effect 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/PathType.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame.Shape 2 | { 3 | /// 4 | /// 路径的类型。 5 | /// 6 | public enum PathType 7 | { 8 | /// 9 | /// 直线段。 10 | /// 11 | Line, 12 | /// 13 | /// 弧线。 14 | /// 15 | Arc, 16 | /// 17 | /// 三次贝塞尔曲线。 18 | /// 19 | Bezier, 20 | /// 21 | /// 结束形状。 22 | /// 23 | EndFigure 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Cyjb.Projects.JigsawGame.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 发布\ 5 | 6 | 7 | 8 | 9 | 10 | zh-CN 11 | false 12 | 13 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/JigsawShapeType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace Cyjb.Projects.JigsawGame.Shape 4 | { 5 | /// 6 | /// 拼图的形状类型 7 | /// 8 | public enum JigsawShapeType 9 | { 10 | /// 11 | /// 四边形。 12 | /// 13 | [Description("四边形")] 14 | Square, 15 | /// 16 | /// 标准圆形。 17 | /// 18 | [Description("标准圆形")] 19 | StandardCirle, 20 | /// 21 | /// 标准形状。 22 | /// 23 | [Description("标准形状")] 24 | Standard, 25 | /// 26 | /// 标准平滑形。 27 | /// 28 | [Description("标准平滑形")] 29 | StandardSmooth, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Jigsaw/JigsawPieceState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Cyjb.Projects.JigsawGame.Jigsaw 4 | { 5 | /// 6 | /// 拼图碎片所处的状态。 7 | /// 8 | [Flags] 9 | [Serializable] 10 | public enum JigsawPieceState 11 | { 12 | /// 13 | /// 普通状态。 14 | /// 15 | None = 0x0, 16 | /// 17 | /// 高亮状态。 18 | /// 19 | Highlight = 0x1, 20 | /// 21 | /// 被选中的状态。 22 | /// 23 | Selected = 0x2, 24 | /// 25 | /// 正在拖动状态。 26 | /// 27 | Draging = 0x4, 28 | /// 29 | /// 被选中且拖动状态。 30 | /// 31 | SelectedDraging = 0x6 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/WinFormUtility.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Forms; 3 | 4 | namespace Cyjb.Projects.JigsawGame 5 | { 6 | /// 7 | /// 包含 WinForm 的实用方法。 8 | /// 9 | public static class WinFormUtility 10 | { 11 | /// 12 | /// 初始化文件对话框的文件名。 13 | /// 14 | /// 对话框。 15 | /// 文件名。 16 | public static void InitFileName(this FileDialog dialog, string fileName) 17 | { 18 | if (!string.IsNullOrWhiteSpace(fileName)) 19 | { 20 | dialog.FileName = Path.GetFileName(fileName); 21 | dialog.InitialDirectory = Path.GetDirectoryName(fileName); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/LoadingForm.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace Cyjb.Projects.JigsawGame 4 | { 5 | /// 6 | /// 等待窗体。 7 | /// 8 | public partial class LoadingForm : ToolForm 9 | { 10 | /// 11 | /// 构造函数。 12 | /// 13 | public LoadingForm() 14 | { 15 | this.BackColor = JigsawSetting.Default.BackgroundColor; 16 | InitializeComponent(); 17 | } 18 | /// 19 | /// 将窗体置于父窗体的中心。 20 | /// 21 | public void CenterParent() 22 | { 23 | this.Location = new Point(this.Owner.Location.X + (this.Owner.Size.Width - this.Width) / 2, 24 | this.Owner.Location.Y + (this.Owner.Size.Height - this.Height) / 2); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/LineSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | 5 | namespace Cyjb.Projects.JigsawGame.Shape 6 | { 7 | /// 8 | /// 表示一条直线路径段。 9 | /// 10 | [Serializable] 11 | public sealed class LineSegment : PathSegment 12 | { 13 | /// 14 | /// 使用指定的终结点初始化 类的新实例。 15 | /// 16 | /// 直线路径段的终结点。 17 | public LineSegment(Vector2 end) 18 | : base(PathType.Line, end) 19 | { } 20 | /// 21 | /// 使用当前的路径填充指定的路径几何。 22 | /// 23 | /// 要填充的路径几何。 24 | public override void FillGeometry(GeometrySink sink) 25 | { 26 | sink.AddLine(this.EndPoint); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Renderer/JigsawScaleChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Cyjb.Projects.JigsawGame.Renderer 4 | { 5 | /// 6 | /// 拼图缩放比例被改变的事件参数。 7 | /// 8 | public sealed class JigsawScaleChangedEventArgs : EventArgs 9 | { 10 | /// 11 | /// 初始化 类的新实例。 12 | /// 13 | public JigsawScaleChangedEventArgs() 14 | { } 15 | /// 16 | /// 使用指定的缩放比例初始化 类的新实例。 17 | /// 18 | /// 拼图的缩放比例。 19 | public JigsawScaleChangedEventArgs(float scale) 20 | { 21 | this.Scale = scale; 22 | } 23 | /// 24 | /// 获取或设置拼图的缩放比例。 25 | /// 26 | public float Scale { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/JigsawSerializeContext.cs: -------------------------------------------------------------------------------- 1 | using SharpDX.Direct2D1; 2 | 3 | namespace Cyjb.Projects.JigsawGame 4 | { 5 | /// 6 | /// 拼图反序列化的上下文。 7 | /// 8 | public sealed class JigsawSerializeContext 9 | { 10 | /// 11 | /// 设备管理器。 12 | /// 13 | private DeviceManager manager; 14 | /// 15 | /// 使用指定的设备管理器初始化 类的新实例。 16 | /// 17 | /// 设备管理器。 18 | public JigsawSerializeContext(DeviceManager manager) 19 | { 20 | this.manager = manager; 21 | } 22 | /// 23 | /// 获取 Direct2D 的工厂。 24 | /// 25 | public Factory Factory { get { return manager.D2DFactory; } } 26 | /// 27 | /// 获取 Direct2D 的设备上下文。 28 | /// 29 | public DeviceContext DeviceContext { get { return manager.D2DContext; } } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JigsawGame 2 | ==== 3 | 4 | 该项目是我使用 [SharpDX 类库](http://sharpdx.org/)实现拼图游戏的源代码,仅供个人学习使用。 5 | 6 | 使用 Visual Studio 2013 编写,游戏的最低系统要求是 **Windows 7**,需要 **.Net Framework 4.5** 的支持。一些游戏特效需要 **DirectX 11.1** 的支持,但不影响游戏过程。 7 | 8 | 游戏操作很简单,用户选定的图片会被分割为很多拼图碎片,游戏过程就是拖动拼图碎片,并拼成完整的图案。关于游戏的更多说明,请参见我的[博客](http://www.cnblogs.com/cyjb/p/JigsawGame.html)。 9 | 10 | 知识共享许可协议
JigsawGameCYJB 创作,采用 知识共享 Attribution-NonCommercial-NoDerivatives 4.0 国际 许可协议进行许可。 11 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace Cyjb.Projects.JigsawGame 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// 应用程序的主入口点。 10 | /// 11 | [STAThread] 12 | static void Main(string[] fileNames) 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.ThreadException += (sender, e) => 17 | { 18 | new BugReportForm(e.Exception).ShowDialog(); 19 | Application.Exit(); 20 | }; 21 | AppDomain.CurrentDomain.UnhandledException += (sender, e) => 22 | { 23 | new BugReportForm(e.ExceptionObject as Exception).ShowDialog(); 24 | }; 25 | DeviceManager device = new DeviceManager(); 26 | if (!device.SupportD2D) 27 | { 28 | MessageBox.Show("您的操作系统不支持 Direct2D 特性,不能运行此游戏"); 29 | return; 30 | } 31 | Application.Run(new MainForm(device, fileNames)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cyjb.Projects.JigsawGame", "Cyjb.Projects.JigsawGame\Cyjb.Projects.JigsawGame.csproj", "{1D1EF63A-E2E6-4869-81BB-AB049718781F}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {1D1EF63A-E2E6-4869-81BB-AB049718781F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {1D1EF63A-E2E6-4869-81BB-AB049718781F}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {1D1EF63A-E2E6-4869-81BB-AB049718781F}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {1D1EF63A-E2E6-4869-81BB-AB049718781F}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/HelpForm.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Windows.Forms; 3 | 4 | namespace Cyjb.Projects.JigsawGame 5 | { 6 | /// 7 | /// 帮助窗口。 8 | /// 9 | public partial class HelpForm : Form 10 | { 11 | /// 12 | /// 构造函数。 13 | /// 14 | public HelpForm() 15 | { 16 | InitializeComponent(); 17 | } 18 | /// 19 | /// 打开链接的事件。 20 | /// 21 | private void pbxLink_Click(object sender, System.EventArgs e) 22 | { 23 | Process.Start("http://www.cnblogs.com/cyjb/"); 24 | } 25 | /// 26 | /// 打开协议的事件。 27 | /// 28 | private void pbxLicense_Click(object sender, System.EventArgs e) 29 | { 30 | Process.Start("http://creativecommons.org/licenses/by-nc-nd/3.0/cn/"); 31 | } 32 | /// 33 | /// 打开帮助链接的事件。 34 | /// 35 | private void pbxHelpLink_Click(object sender, System.EventArgs e) 36 | { 37 | Process.Start("http://www.cnblogs.com/cyjb/p/JigsawGame.html"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/EndFigureSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | 5 | namespace Cyjb.Projects.JigsawGame.Shape 6 | { 7 | /// 8 | /// 结束当前形状的路径段。 9 | /// 10 | [Serializable] 11 | public sealed class EndFigureSegment : PathSegment 12 | { 13 | /// 14 | /// 使用指定的终结点初始化 类的新实例。 15 | /// 16 | /// 形状结束段的终结点。 17 | /// 下一段路径是否为黑色。 18 | public EndFigureSegment(Vector2 endPoint, bool isBlack) 19 | : base(PathType.EndFigure, endPoint) 20 | { 21 | this.IsBlack = isBlack; 22 | } 23 | /// 24 | /// 获取下一段路径是否为黑色。 25 | /// 26 | public bool IsBlack { get; private set; } 27 | /// 28 | /// 使用当前的路径填充指定的路径几何。 29 | /// 30 | /// 要填充的路径几何。 31 | public override void FillGeometry(GeometrySink sink) 32 | { 33 | sink.EndFigure(FigureEnd.Closed); 34 | sink.BeginFigure(EndPoint, FigureBegin.Filled); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/ToolForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class ToolForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 33 | this.Text = "ToolForm"; 34 | } 35 | 36 | #endregion 37 | } 38 | } -------------------------------------------------------------------------------- /lib/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2012 SharpDX - Alexandre Mutel 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.InteropServices; 5 | 6 | // 有关程序集的常规信息通过以下 7 | // 特性集控制。更改这些特性值可修改 8 | // 与程序集关联的信息。 9 | [assembly: AssemblyTitle("JigsawGame")] 10 | [assembly: AssemblyDescription("拼图游戏")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("CYJB")] 13 | [assembly: AssemblyProduct("JigsawGame")] 14 | [assembly: AssemblyCopyright("Copyright © CYJB 2013")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // 将 ComVisible 设置为 false 使此程序集中的类型 19 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, 20 | // 则将该类型上的 ComVisible 特性设置为 true。 21 | [assembly: ComVisible(false)] 22 | 23 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 24 | [assembly: Guid("ca084006-b01a-4a28-a713-792b46358bf1")] 25 | 26 | // 程序集的版本信息由下面四个值组成: 27 | // 28 | // 主版本 29 | // 次版本 30 | // 生成号 31 | // 修订号 32 | // 33 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 34 | // 方法是按如下所示使用“*”: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("1.1.0.0")] 37 | [assembly: AssemblyFileVersion("1.1.0.0")] 38 | [assembly: NeutralResourcesLanguageAttribute("en")] 39 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/PathSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | 5 | namespace Cyjb.Projects.JigsawGame.Shape 6 | { 7 | /// 8 | /// 表示一条路径段。 9 | /// 10 | [Serializable] 11 | public abstract class PathSegment 12 | { 13 | /// 14 | /// 使用指定的路径段类型和终结点初始化 类的新实例。 15 | /// 16 | /// 路径段的类型。 17 | /// 路径的终结点。 18 | protected PathSegment(PathType type, Vector2 end) 19 | { 20 | this.PathType = type; 21 | this.EndPoint = end; 22 | } 23 | /// 24 | /// 获取路径段的类型。 25 | /// 26 | public PathType PathType { get; private set; } 27 | /// 28 | /// 获取路径的终结点。 29 | /// 30 | public Vector2 EndPoint { get; private set; } 31 | /// 32 | /// 使用当前的路径填充指定的路径几何。 33 | /// 34 | /// 要填充的路径几何。 35 | public abstract void FillGeometry(GeometrySink sink); 36 | /// 37 | /// 返回当前对象的字符串表示形式。 38 | /// 39 | /// 当前对象的字符串表示形式。 40 | public override string ToString() 41 | { 42 | return string.Concat(PathType, " (", EndPoint.X, ", ", EndPoint.Y, ")"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/JigsawInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Drawing; 4 | 5 | namespace Cyjb.Projects.JigsawGame 6 | { 7 | /// 8 | /// 表示拼图游戏的相关信息。 9 | /// 10 | [Serializable] 11 | public sealed class JigsawInfo 12 | { 13 | /// 14 | /// 获取或设置是否允许旋转拼图。 15 | /// 16 | public bool Rotatable { get; set; } 17 | /// 18 | /// 获取或设置是否允吸附到背景。 19 | /// 20 | public bool AnchorToBackground { get; set; } 21 | /// 22 | /// 获取或设置吸附的半径。 23 | /// 24 | public float AnchorRadius { get; set; } 25 | /// 26 | /// 获取或设置拼图碎片的总个数。 27 | /// 28 | public int PieceSum { get; set; } 29 | /// 30 | /// 获取或设置当前游戏的缩放比例。 31 | /// 32 | public float Scale { get; set; } 33 | /// 34 | /// 获取或设置当前游戏窗口的滚动位置。 35 | /// 36 | public Point ScrollPosition { get; set; } 37 | /// 38 | /// 获取或设置拼图的图像数据。 39 | /// 40 | [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] 41 | public byte[] ImageData { get; set; } 42 | /// 43 | /// 获取或设置已被使用的时间。 44 | /// 45 | public TimeSpan UsedTime { get; set; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/BezierSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | using D2D1 = SharpDX.Direct2D1; 5 | 6 | namespace Cyjb.Projects.JigsawGame.Shape 7 | { 8 | /// 9 | /// 表示一条三次贝塞尔曲线路径段。 10 | /// 11 | [Serializable] 12 | public sealed class BezierSegment : PathSegment 13 | { 14 | /// 15 | /// 使用指定的设置初始化 类的新实例。 16 | /// 17 | /// 三次贝塞尔曲线路径段的终结点。 18 | /// 三次贝塞尔曲线路径的第一个控制点。 19 | /// 三次贝塞尔曲线路径的第二个控制点。 20 | public BezierSegment(Vector2 end, Vector2 point1, Vector2 point2) 21 | : base(PathType.Arc, end) 22 | { 23 | this.Point1 = point1; 24 | this.Point2 = point2; 25 | } 26 | /// 27 | /// 获取第一个控制点。 28 | /// 29 | public Vector2 Point1 { get; private set; } 30 | /// 31 | /// 获取第二个控制点。 32 | /// 33 | public Vector2 Point2 { get; private set; } 34 | /// 35 | /// 使用当前的路径填充指定的路径几何。 36 | /// 37 | /// 要填充的路径几何。 38 | public override void FillGeometry(GeometrySink sink) 39 | { 40 | D2D1.BezierSegment bezier = new D2D1.BezierSegment() 41 | { 42 | Point1 = this.Point1, 43 | Point2 = this.Point2, 44 | Point3 = this.EndPoint 45 | }; 46 | sink.AddBezier(bezier); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/JigsawStandardCircleShape.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | 5 | namespace Cyjb.Projects.JigsawGame.Shape 6 | { 7 | /// 8 | /// 拼图的标准圆形。 9 | /// 10 | public sealed class JigsawStandardCircleShape : JigsawShape 11 | { 12 | /// 13 | /// 初始化 的新实例。 14 | /// 15 | public JigsawStandardCircleShape() : base(0) { } 16 | /// 17 | /// 向拼图碎片的路径中添加一条边,路径的当前节点总是在起始点。 18 | /// 19 | /// 路径。 20 | /// 边的起始点。 21 | /// 边的结束点。 22 | /// 该边的凹凸性。 23 | /// 与该条边相关的一组随机数,范围都是 [0, 1)。 24 | protected override void AddBorder(Path path, Vector2 startPoint, Vector2 endPoint, 25 | bool border, float[] randoms) 26 | { 27 | Vector2 sp = Vector2.Lerp(startPoint, endPoint, 1f / 3); 28 | Vector2 ep = Vector2.Lerp(startPoint, endPoint, 2f / 3); 29 | path.AddLine(sp); 30 | double angle = Math.Atan2(endPoint.Y - startPoint.Y, endPoint.X - startPoint.X) * 180 / Math.PI + 180; 31 | float len = Vector2.Distance(startPoint, endPoint) / 6; 32 | path.AddArc(ep, new Size2F(len, len), (float)angle, 33 | border ? SweepDirection.CounterClockwise : SweepDirection.Clockwise, ArcSize.Small); 34 | path.AddLine(endPoint); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/BugReportForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | 6 | namespace Cyjb.Projects.JigsawGame 7 | { 8 | /// 9 | /// 报告异常的窗体。 10 | /// 11 | public partial class BugReportForm : Form 12 | { 13 | /// 14 | /// 初始化 类的新实例。 15 | /// 16 | /// 异常对象。 17 | public BugReportForm(Exception ex) 18 | { 19 | InitializeComponent(); 20 | if (ex == null) 21 | { 22 | tbxException.Text = "无异常信息。"; 23 | } 24 | else 25 | { 26 | StringBuilder text = new StringBuilder(); 27 | FormatException(ex, text); 28 | tbxException.Text = text.ToString(); 29 | } 30 | } 31 | /// 32 | /// 格式化异常。 33 | /// 34 | /// 要格式化的异常对象。 35 | /// 格式化后的文本。 36 | private void FormatException(Exception ex, StringBuilder text) 37 | { 38 | text.Append(ex.GetType()); 39 | text.Append(": "); 40 | text.AppendLine(ex.Message); 41 | text.AppendLine(ex.StackTrace); 42 | if (ex.InnerException != null) 43 | { 44 | text.AppendLine(); 45 | text.AppendLine("InnerException:"); 46 | FormatException(ex.InnerException, text); 47 | } 48 | } 49 | /// 50 | /// 报告异常的链接。 51 | /// 52 | private void linkReport_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 53 | { 54 | Process.Start("http://www.cnblogs.com/cyjb/p/JigsawGame.html"); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/JigsawStandardShape.cs: -------------------------------------------------------------------------------- 1 | using SharpDX; 2 | 3 | namespace Cyjb.Projects.JigsawGame.Shape 4 | { 5 | /// 6 | /// 拼图的标准形状。 7 | /// 8 | public sealed class JigsawStandardShape : JigsawShape 9 | { 10 | /// 11 | /// 初始化 的新实例。 12 | /// 13 | public JigsawStandardShape() : base(3) { } 14 | /// 15 | /// 向拼图碎片的路径中添加一条边,路径的当前节点总是在起始点。 16 | /// 17 | /// 路径。 18 | /// 边的起始点。 19 | /// 边的结束点。 20 | /// 该边的凹凸性。 21 | /// 与该条边相关的一组随机数,范围都是 [0, 1)。 22 | protected override void AddBorder(Path path, Vector2 startPoint, Vector2 endPoint, 23 | bool border, float[] randoms) 24 | { 25 | // 贝塞尔曲线的起始和结束点。 26 | float rate1 = 1f / 3 + randoms[0] / 12; 27 | Vector2 sp = Vector2.Lerp(startPoint, endPoint, rate1); 28 | Vector2 ep = Vector2.Lerp(startPoint, endPoint, 1 - rate1); 29 | // 贝塞尔曲线的控制点。 30 | float rate2 = rate1 - randoms[1] / 4; 31 | Vector2 c1 = Vector2.Lerp(startPoint, endPoint, rate2); 32 | Vector2 c2 = Vector2.Lerp(startPoint, endPoint, 1 - rate2); 33 | // 与边框垂直的向量。 34 | Vector2 cross = new Vector2(endPoint.Y - startPoint.Y, startPoint.X - endPoint.X); 35 | if (!border) 36 | { 37 | cross.X *= -1; 38 | cross.Y *= -1; 39 | } 40 | cross *= 1f / 4 + randoms[2] / 8; 41 | path.AddLine(sp); 42 | path.AddBezier(ep, c1 + cross, c2 + cross); 43 | path.AddLine(endPoint); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/ArcSegment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | using SharpDX.Direct2D1; 4 | using D2D1 = SharpDX.Direct2D1; 5 | 6 | namespace Cyjb.Projects.JigsawGame.Shape 7 | { 8 | /// 9 | /// 表示一条弧线路径段。 10 | /// 11 | [Serializable] 12 | public sealed class ArcSegment : PathSegment 13 | { 14 | /// 15 | /// 使用指定的设置初始化 类的新实例。 16 | /// 17 | /// 弧线路径段的终结点。 18 | /// 弧线路径段的尺寸。 19 | /// 弧线路径段的旋转角度。 20 | /// 弧线路径段的绘制方向。 21 | /// 弧线路径段是否大于 180 度。 22 | public ArcSegment(Vector2 end, Size2F size, float rotationAngel, 23 | SweepDirection sweepDirection, ArcSize arcSize) 24 | : base(PathType.Arc, end) 25 | { 26 | this.Size = size; 27 | this.RotationAngle = rotationAngel; 28 | this.SweepDirection = sweepDirection; 29 | this.ArcSize = arcSize; 30 | } 31 | /// 32 | /// 获取弧线路径段的尺寸。 33 | /// 34 | public Size2F Size { get; private set; } 35 | /// 36 | /// 获取弧线路径段的旋转角度。 37 | /// 38 | public float RotationAngle { get; private set; } 39 | /// 40 | /// 获取弧线路径段的绘制方向。 41 | /// 42 | public SweepDirection SweepDirection { get; private set; } 43 | /// 44 | /// 获取弧线路径段是否大于 180 度。 45 | /// 46 | public ArcSize ArcSize { get; private set; } 47 | /// 48 | /// 使用当前的路径填充指定的路径几何。 49 | /// 50 | /// 要填充的路径几何。 51 | public override void FillGeometry(GeometrySink sink) 52 | { 53 | D2D1.ArcSegment arc = new D2D1.ArcSegment() 54 | { 55 | Point = EndPoint, 56 | Size = Size, 57 | RotationAngle = RotationAngle, 58 | SweepDirection = SweepDirection, 59 | ArcSize = ArcSize 60 | }; 61 | sink.AddArc(arc); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/JigsawStandardSmoothShape.cs: -------------------------------------------------------------------------------- 1 | using SharpDX; 2 | 3 | namespace Cyjb.Projects.JigsawGame.Shape 4 | { 5 | /// 6 | /// 拼图的标准平滑形状。 7 | /// 8 | public sealed class JigsawStandardSmoothShape : JigsawShape 9 | { 10 | /// 11 | /// 初始化 的新实例。 12 | /// 13 | public JigsawStandardSmoothShape() : base(5) { } 14 | /// 15 | /// 向拼图碎片的路径中添加一条边,路径的当前节点总是在起始点。 16 | /// 17 | /// 路径。 18 | /// 边的起始点。 19 | /// 边的结束点。 20 | /// 该边的凹凸性。 21 | /// 与该条边相关的一组随机数,范围都是 [0, 1)。 22 | protected override void AddBorder(Path path, Vector2 startPoint, Vector2 endPoint, bool border, float[] randoms) 23 | { 24 | // 贝塞尔曲线的起始和结束点。 25 | float rate1 = 1f / 3 + randoms[0] / 12; 26 | Vector2 sp = Vector2.Lerp(startPoint, endPoint, rate1); 27 | Vector2 ep = Vector2.Lerp(startPoint, endPoint, 1 - rate1); 28 | // 贝塞尔曲线的控制点。 29 | float rate2 = rate1 - randoms[1] / 4; 30 | Vector2 c1 = Vector2.Lerp(startPoint, endPoint, rate2); 31 | Vector2 c2 = Vector2.Lerp(startPoint, endPoint, 1 - rate2); 32 | // 与边框垂直的向量。 33 | Vector2 cross = new Vector2(endPoint.Y - startPoint.Y, startPoint.X - endPoint.X); 34 | if (!border) 35 | { 36 | cross.X *= -1; 37 | cross.Y *= -1; 38 | } 39 | cross *= 1f / 4 + randoms[2] / 8; 40 | c1 += cross; 41 | c2 += cross; 42 | // 连接边框的贝塞尔曲线。 43 | float rate3 = 1f / 6 + randoms[3] / 6; 44 | Vector2 sc2 = sp + (sp - c1) * rate3; 45 | Vector2 sc1 = Vector2.Lerp(startPoint, sc2, randoms[4]); 46 | Vector2 ec1 = ep + (ep - c2) * rate3; 47 | Vector2 ec2 = Vector2.Lerp(endPoint, ec1, randoms[4]); 48 | path.AddBezier(sp, sc1, sc2); 49 | path.AddBezier(ep, c1, c2); 50 | path.AddBezier(endPoint, ec1, ec2); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/ThumbForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class ThumbForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // ThumbForm 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.ClientSize = new System.Drawing.Size(284, 261); 38 | this.DoubleBuffered = true; 39 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; 40 | this.MaximizeBox = false; 41 | this.MinimizeBox = false; 42 | this.MinimumSize = new System.Drawing.Size(100, 100); 43 | this.Name = "ThumbForm"; 44 | this.ShowIcon = false; 45 | this.ShowInTaskbar = false; 46 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 47 | this.Text = "缩略图"; 48 | this.SizeChanged += new System.EventHandler(this.ThumbForm_SizeChanged); 49 | this.Paint += new System.Windows.Forms.PaintEventHandler(this.ThumbForm_Paint); 50 | this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ThumbForm_MouseDown); 51 | this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ThumbForm_MouseMove); 52 | this.ResumeLayout(false); 53 | 54 | } 55 | 56 | #endregion 57 | 58 | } 59 | } -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/LoadingForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class LoadingForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.pictureBox1 = new System.Windows.Forms.PictureBox(); 32 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); 33 | this.SuspendLayout(); 34 | // 35 | // pictureBox1 36 | // 37 | this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill; 38 | this.pictureBox1.Image = global::Cyjb.Projects.JigsawGame.Resources.Loading; 39 | this.pictureBox1.Location = new System.Drawing.Point(0, 0); 40 | this.pictureBox1.Name = "pictureBox1"; 41 | this.pictureBox1.Size = new System.Drawing.Size(100, 100); 42 | this.pictureBox1.TabIndex = 0; 43 | this.pictureBox1.TabStop = false; 44 | // 45 | // LoadingForm 46 | // 47 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 48 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 49 | this.ClientSize = new System.Drawing.Size(100, 100); 50 | this.Controls.Add(this.pictureBox1); 51 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 52 | this.MaximumSize = new System.Drawing.Size(100, 100); 53 | this.MinimumSize = new System.Drawing.Size(100, 100); 54 | this.Name = "LoadingForm"; 55 | this.ShowIcon = false; 56 | this.ShowInTaskbar = false; 57 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 58 | this.Text = "等待..."; 59 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); 60 | this.ResumeLayout(false); 61 | 62 | } 63 | 64 | #endregion 65 | 66 | private System.Windows.Forms.PictureBox pictureBox1; 67 | } 68 | } -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/SettingForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Forms; 4 | using Cyjb.Projects.JigsawGame.Renderer; 5 | 6 | namespace Cyjb.Projects.JigsawGame 7 | { 8 | /// 9 | /// 设置窗体。 10 | /// 11 | public partial class SettingForm : Form 12 | { 13 | /// 14 | /// 构造函数。 15 | /// 16 | /// 是否可以使用 Effect 拼图渲染器。 17 | public SettingForm(bool enabledEffect) 18 | { 19 | InitializeComponent(); 20 | this.tbarBackgroundAlpha.Value = (int)(JigsawSetting.Default.BackgroundAlpha * 100); 21 | this.pbxBackgroundColor.BackColor = JigsawSetting.Default.BackgroundColor; 22 | if (enabledEffect) 23 | { 24 | this.RendererType = EnumExt.Parse(JigsawSetting.Default.Renderer); 25 | if (this.RendererType == JigsawRendererType.Effect) 26 | { 27 | rbtnEffect.Checked = true; 28 | } 29 | this.lblEffectWarn.Visible = false; 30 | } 31 | else 32 | { 33 | this.rbtnSample.Checked = true; 34 | this.rbtnEffect.Enabled = false; 35 | this.lblEffectWarn.Visible = true; 36 | } 37 | } 38 | /// 39 | /// 获取设置的拼图渲染器。 40 | /// 41 | public JigsawRendererType RendererType { get; private set; } 42 | /// 43 | /// 背景不透明度被改变的事件。 44 | /// 45 | private void tbarBackgroundAlpha_Scroll(object sender, EventArgs e) 46 | { 47 | lblBackgroundAlphaInfo.Text = tbarBackgroundAlpha.Value.ToString(CultureInfo.CurrentCulture) + "%"; 48 | JigsawSetting.Default.BackgroundAlpha = (float)tbarBackgroundAlpha.Value / 100; 49 | } 50 | /// 51 | /// 打开颜色设置对话框。 52 | /// 53 | private void pbxBackgroundColor_Click(object sender, EventArgs e) 54 | { 55 | this.backgroundColorDialog.Color = JigsawSetting.Default.BackgroundColor; 56 | if (this.backgroundColorDialog.ShowDialog() == DialogResult.OK) 57 | { 58 | JigsawSetting.Default.BackgroundColor = this.backgroundColorDialog.Color; 59 | this.pbxBackgroundColor.BackColor = JigsawSetting.Default.BackgroundColor; 60 | } 61 | } 62 | /// 63 | /// 拼图渲染器被改变的事件。 64 | /// 65 | private void rbtnSample_CheckedChanged(object sender, EventArgs e) 66 | { 67 | if (rbtnSample.Checked) 68 | { 69 | this.RendererType = JigsawRendererType.Simple; 70 | } 71 | else 72 | { 73 | this.RendererType = JigsawRendererType.Effect; 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/ToolForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security.Permissions; 4 | using System.Windows.Forms; 5 | 6 | namespace Cyjb.Projects.JigsawGame 7 | { 8 | /// 9 | /// 工具窗体的基类。 10 | /// 11 | public partial class ToolForm : Form 12 | { 13 | /// 14 | /// 初始化 类的新实例。 15 | /// 16 | public ToolForm() 17 | { 18 | InitializeComponent(); 19 | } 20 | /// 21 | /// 获取或设置是否可以在工作区拖动窗体。 22 | /// 23 | protected bool ClientDraggable { get; set; } 24 | 25 | #region 消息循环 26 | 27 | /// 28 | /// 设置活动窗口。 29 | /// 30 | /// 活动窗口的句柄。 31 | /// 返回值。 32 | [DllImport("user32.dll")] 33 | private extern static IntPtr SetActiveWindow(IntPtr handle); 34 | /// 35 | /// WM_ACTIVATE 消息。 36 | /// 37 | private const int WM_ACTIVATE = 0x006; 38 | /// 39 | /// WM_ACTIVATEAPP 消息。 40 | /// 41 | private const int WM_ACTIVATEAPP = 0x01C; 42 | /// 43 | /// WM_NCACTIVATE 消息。 44 | /// 45 | private const int WM_NCACTIVATE = 0x086; 46 | /// 47 | /// WA_INACTIVE 消息。 48 | /// 49 | private const int WA_INACTIVE = 0; 50 | /// 51 | /// WM_MOUSEACTIVATE 消息。 52 | /// 53 | private const int WM_MOUSEACTIVATE = 0x21; 54 | /// 55 | /// MA_NOACTIVATE 消息。 56 | /// 57 | private const int MA_NOACTIVATE = 3; 58 | /// 59 | /// 窗口消息循环重载,用于使缩略图窗口不接受焦点。 60 | /// 61 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] 62 | protected override void WndProc(ref Message m) 63 | { 64 | // 鼠标左键按下 65 | if (m.Msg == 0x0201) 66 | { 67 | // 当可以在工作区拖动窗体时。 68 | if (this.ClientDraggable) 69 | { 70 | // 改消息为非客户区按下鼠标 71 | m.Msg = 0x00a1; 72 | // 默认值 73 | m.LParam = IntPtr.Zero; 74 | // 鼠标放在标题栏内 75 | m.WParam = new IntPtr(2); 76 | } 77 | } 78 | else if (m.Msg == WM_MOUSEACTIVATE) 79 | { 80 | m.Result = new IntPtr(MA_NOACTIVATE); 81 | return; 82 | } 83 | else if (m.Msg == WM_NCACTIVATE) 84 | { 85 | if (((int)m.WParam & 0xFFFF) != WA_INACTIVE) 86 | { 87 | if (m.LParam != IntPtr.Zero) 88 | { 89 | SetActiveWindow(m.LParam); 90 | } 91 | else 92 | { 93 | SetActiveWindow(IntPtr.Zero); 94 | } 95 | } 96 | } 97 | base.WndProc(ref m); 98 | } 99 | 100 | #endregion // 消息循环 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/JigsawSetting.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 0.3 7 | 8 | 9 | 400, 300 10 | 11 | 12 | 0, 0 13 | 14 | 15 | True 16 | 17 | 18 | White 19 | 20 | 21 | 0, 0 22 | 23 | 24 | 0, 0 25 | 26 | 27 | Normal 28 | 29 | 30 | 0 31 | 32 | 33 | 0 34 | 35 | 36 | 37 | 38 | 39 | Effect 40 | 41 | 42 | False 43 | 44 | 45 | False 46 | 47 | 48 | False 49 | 50 | 51 | False 52 | 53 | 54 | 0.3 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Jigsaw/JigsawPieceSelectedCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Cyjb.Projects.JigsawGame.Jigsaw 5 | { 6 | /// 7 | /// 表示被选择的拼图碎片集合。 8 | /// 9 | public sealed class JigsawPieceSelectedCollection : IEnumerable 10 | { 11 | /// 12 | /// 拼图碎片集合。 13 | /// 14 | private HashSet items = new HashSet(); 15 | /// 16 | /// 是否选择了单个拼图碎片。 17 | /// 18 | private bool singleSelected = false; 19 | /// 20 | /// 获取是否选择了单个拼图碎片。 21 | /// 22 | public bool SingleSelected { get { return singleSelected; } } 23 | /// 24 | /// 将指定的拼图碎片添加到被选择的集合中。 25 | /// 26 | /// 要添加的拼图碎片。 27 | public void Add(JigsawPiece piece) 28 | { 29 | piece.State |= JigsawPieceState.Selected; 30 | items.Add(piece); 31 | singleSelected = true; 32 | } 33 | /// 34 | /// 将指定的拼图碎片集合添加到被选择的集合中。 35 | /// 36 | /// 要添加的拼图碎片集合。 37 | public void AddRange(IEnumerable pieces) 38 | { 39 | foreach (JigsawPiece piece in pieces) 40 | { 41 | if (!piece.Frozen) 42 | { 43 | piece.State |= JigsawPieceState.Selected; 44 | items.Add(piece); 45 | } 46 | } 47 | singleSelected = false; 48 | } 49 | /// 50 | /// 清除所有被选择的拼图碎片。 51 | /// 52 | public void Clear() 53 | { 54 | foreach (JigsawPiece piece in this.items) 55 | { 56 | piece.State &= ~JigsawPieceState.Selected; 57 | } 58 | this.items.Clear(); 59 | singleSelected = false; 60 | } 61 | /// 62 | /// 返回当前集合中是否包含给定的拼图碎片。 63 | /// 64 | /// 要测试的拼图碎片。 65 | /// 如果指定的拼图碎片包含在集合中,则为 true; 66 | /// 否则为 false 67 | public bool Contains(JigsawPiece piece) 68 | { 69 | return this.items.Contains(piece); 70 | } 71 | /// 72 | /// 修改当前的集合,以仅包含该对象和指定集合中存在的元素。 73 | /// 74 | /// 要与当前的集合进行比较的集合。 75 | public void IntersectWith(IEnumerable other) 76 | { 77 | this.items.IntersectWith(other); 78 | } 79 | 80 | #region IEnumerable 成员 81 | 82 | /// 83 | /// 返回一个循环访问集合的枚举器。 84 | /// 85 | /// 可用于循环访问集合的 86 | public IEnumerator GetEnumerator() 87 | { 88 | return this.items.GetEnumerator(); 89 | } 90 | 91 | #endregion // IEnumerable 成员 92 | 93 | #region IEnumerable 成员 94 | 95 | /// 96 | /// 返回一个循环访问集合的枚举器。 97 | /// 98 | /// 可用于循环访问集合的 99 | IEnumerator IEnumerable.GetEnumerator() 100 | { 101 | return this.GetEnumerator(); 102 | } 103 | 104 | #endregion // IEnumerable 成员 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 0.3 15 | 16 | 17 | 400, 300 18 | 19 | 20 | 0, 0 21 | 22 | 23 | True 24 | 25 | 26 | White 27 | 28 | 29 | 0, 0 30 | 31 | 32 | 0, 0 33 | 34 | 35 | Normal 36 | 37 | 38 | 0 39 | 40 | 41 | 0 42 | 43 | 44 | 45 | 46 | 47 | Effect 48 | 49 | 50 | False 51 | 52 | 53 | False 54 | 55 | 56 | False 57 | 58 | 59 | False 60 | 61 | 62 | 0.3 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/SharpDXUtility.cs: -------------------------------------------------------------------------------- 1 | using SharpDX; 2 | using SharpDX.Direct2D1; 3 | 4 | namespace Cyjb.Projects.JigsawGame 5 | { 6 | /// 7 | /// 包含 SharpDX 的实用方法。 8 | /// 9 | public static class SharpDXUtility 10 | { 11 | 12 | #region 几何操作 13 | 14 | /// 15 | /// 获取给定点集合中心(坐标平均值)。 16 | /// 17 | /// 要计算的点集合。 18 | /// 点集合的中心。 19 | public static Vector2 GetCenter(params Vector2[] args) 20 | { 21 | float x = 0, y = 0; 22 | for (int i = 0; i < args.Length; i++) 23 | { 24 | x += args[i].X; 25 | y += args[i].Y; 26 | } 27 | return new Vector2(x / args.Length, y / args.Length); 28 | } 29 | /// 30 | /// 计算三角形的面积(的二倍)。 31 | /// 32 | /// 三角形的第一个顶点坐标。 33 | /// 三角形的第二个顶点坐标。 34 | /// 三角形的第三个顶点坐标。 35 | /// 36 | public static float Area(Vector2 p1, Vector2 p2, Vector2 p3) 37 | { 38 | float area = (p1.X - p2.X) * (p1.Y - p3.Y) - (p1.X - p3.X) * (p1.Y - p2.Y); 39 | return area < 0 ? -area : area; 40 | } 41 | /// 42 | /// 将给定的几何图形组合并为一个组。 43 | /// 44 | /// 要合并集合图形组。 45 | /// 合并得到的集合图形组。 46 | public static GeometryGroup Merge(params GeometryGroup[] geometies) 47 | { 48 | int[] idx = new int[geometies.Length]; 49 | for (int i = 0; i < geometies.Length; i++) 50 | { 51 | if (i == 0) 52 | { 53 | idx[i] = geometies[i].SourceGeometryCount; 54 | } 55 | else 56 | { 57 | idx[i] = idx[i - 1] + geometies[i].SourceGeometryCount; 58 | } 59 | } 60 | Geometry[] geoms = new Geometry[idx[idx.Length - 1]]; 61 | for (int i = 0; i < geometies.Length; i++) 62 | { 63 | if (i == 0) 64 | { 65 | geometies[i].GetSourceGeometry().CopyTo(geoms, 0); 66 | } 67 | else 68 | { 69 | geometies[i].GetSourceGeometry().CopyTo(geoms, idx[i - 1]); 70 | } 71 | } 72 | return new GeometryGroup(geometies[0].Factory, FillMode.Winding, geoms); 73 | } 74 | 75 | #endregion // 几何操作 76 | 77 | #region 颜色操作 78 | 79 | /// 80 | /// 将指定的 对象转换为等价的 81 | /// 对象。 82 | /// 83 | /// 要转换的 对象。 84 | /// 转换得到的 对象。 85 | public static Color4 ToColor4(this System.Drawing.Color color) 86 | { 87 | uint argb = (uint)color.ToArgb(); 88 | // Color4 的 R, G, B, A 是从小端到大端排列。 89 | uint rgba = (argb & 0xFF00FF00) | ((argb >> 16) & 0x000000FF) | ((argb << 16) & 0x00FF0000); 90 | return new Color4(rgba); 91 | } 92 | /// 93 | /// 将指定的 对象转换为等价的 对象。 94 | /// 95 | /// 要转换的 对象。 96 | /// 转换得到的 对象。 97 | public static System.Drawing.Color ToColor(this Color4 color) 98 | { 99 | uint rgba = (uint)color.ToRgba(); 100 | // Color4 的 R, G, B, A 是从小端到大端排列。 101 | uint argb = (rgba & 0xFF00FF00) | ((rgba >> 16) & 0x000000FF) | ((rgba << 16) & 0x00FF0000); 102 | return System.Drawing.Color.FromArgb((int)argb); 103 | } 104 | 105 | #endregion // 颜色操作 106 | 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/BugReportForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class BugReportForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.lblTitle = new System.Windows.Forms.Label(); 32 | this.tbxException = new System.Windows.Forms.TextBox(); 33 | this.linkReport = new System.Windows.Forms.LinkLabel(); 34 | this.btnClose = new System.Windows.Forms.Button(); 35 | this.SuspendLayout(); 36 | // 37 | // lblTitle 38 | // 39 | this.lblTitle.AutoSize = true; 40 | this.lblTitle.Location = new System.Drawing.Point(12, 9); 41 | this.lblTitle.Name = "lblTitle"; 42 | this.lblTitle.Size = new System.Drawing.Size(161, 12); 43 | this.lblTitle.TabIndex = 0; 44 | this.lblTitle.Text = "游戏出现了无法处理的异常:"; 45 | // 46 | // tbxException 47 | // 48 | this.tbxException.Location = new System.Drawing.Point(12, 34); 49 | this.tbxException.Multiline = true; 50 | this.tbxException.Name = "tbxException"; 51 | this.tbxException.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 52 | this.tbxException.Size = new System.Drawing.Size(426, 186); 53 | this.tbxException.TabIndex = 1; 54 | // 55 | // linkReport 56 | // 57 | this.linkReport.AutoSize = true; 58 | this.linkReport.Location = new System.Drawing.Point(12, 231); 59 | this.linkReport.Name = "linkReport"; 60 | this.linkReport.Size = new System.Drawing.Size(347, 12); 61 | this.linkReport.TabIndex = 2; 62 | this.linkReport.TabStop = true; 63 | this.linkReport.Text = "到 http://www.cnblogs.com/cyjb/p/JigsawGame.html 报告异常"; 64 | this.linkReport.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkReport_LinkClicked); 65 | // 66 | // btnClose 67 | // 68 | this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; 69 | this.btnClose.Location = new System.Drawing.Point(365, 226); 70 | this.btnClose.Name = "btnClose"; 71 | this.btnClose.Size = new System.Drawing.Size(75, 23); 72 | this.btnClose.TabIndex = 3; 73 | this.btnClose.Text = "关闭"; 74 | this.btnClose.UseVisualStyleBackColor = true; 75 | // 76 | // BugReportForm 77 | // 78 | this.AcceptButton = this.btnClose; 79 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 80 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 81 | this.CancelButton = this.btnClose; 82 | this.ClientSize = new System.Drawing.Size(450, 261); 83 | this.Controls.Add(this.btnClose); 84 | this.Controls.Add(this.linkReport); 85 | this.Controls.Add(this.tbxException); 86 | this.Controls.Add(this.lblTitle); 87 | this.MaximizeBox = false; 88 | this.MinimizeBox = false; 89 | this.Name = "BugReportForm"; 90 | this.ShowIcon = false; 91 | this.ShowInTaskbar = false; 92 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 93 | this.Text = "异常报告"; 94 | this.ResumeLayout(false); 95 | this.PerformLayout(); 96 | 97 | } 98 | 99 | #endregion 100 | 101 | private System.Windows.Forms.Label lblTitle; 102 | private System.Windows.Forms.TextBox tbxException; 103 | private System.Windows.Forms.LinkLabel linkReport; 104 | private System.Windows.Forms.Button btnClose; 105 | } 106 | } -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Renderer/JigsawRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | using Cyjb.Projects.JigsawGame.Jigsaw; 5 | using SharpDX.Direct2D1; 6 | 7 | namespace Cyjb.Projects.JigsawGame.Renderer 8 | { 9 | /// 10 | /// 拼图的渲染器。 11 | /// 12 | public abstract class JigsawRenderer : IDisposable 13 | { 14 | /// 15 | /// 创建指定类型的拼图渲染器。 16 | /// 17 | /// 拼图渲染器的类型。 18 | /// 设备管理器。 19 | public static JigsawRenderer CreateRenderer(JigsawRendererType rendererType, DeviceManager deviceManager) 20 | { 21 | switch (rendererType) 22 | { 23 | case JigsawRendererType.Effect: 24 | return new JigsawEffectRenderer(deviceManager); 25 | default: 26 | return new JigsawSimpleRenderer(deviceManager); 27 | } 28 | } 29 | /// 30 | /// 设备管理器。 31 | /// 32 | private DeviceManager deviceManager; 33 | /// 34 | /// 需要渲染的拼图碎片列表。 35 | /// 36 | private List currentPieces = new List(); 37 | /// 38 | /// 使用指定的设备管理器初始化 类的新实例。 39 | /// 40 | /// 设备管理器。 41 | protected JigsawRenderer(DeviceManager deviceManager) 42 | { 43 | this.deviceManager = deviceManager; 44 | } 45 | 46 | #region IDisposable 成员 47 | 48 | /// 49 | /// 释放对象占用的资源。 50 | /// 51 | public void Dispose() 52 | { 53 | this.Dispose(true); 54 | GC.SuppressFinalize(this); 55 | } 56 | /// 57 | /// 释放对象占用的资源。 58 | /// 59 | /// 是否释放托管资源。 60 | protected virtual void Dispose(bool disposing) 61 | { 62 | ClearResources(); 63 | } 64 | 65 | #endregion // IDisposable 成员 66 | 67 | /// 68 | /// 获取拼图渲染器的类型。 69 | /// 70 | public abstract JigsawRendererType RendererType { get; } 71 | /// 72 | /// 获取拼图图片数据。 73 | /// 74 | protected Bitmap Image { get; private set; } 75 | /// 76 | /// 获取 Direct2D 渲染目标。 77 | /// 78 | protected RenderTarget RenderTarget 79 | { 80 | get { return this.deviceManager.RenderTarget; } 81 | } 82 | /// 83 | /// 获取 Direct2D 设备上下文。 84 | /// 85 | protected DeviceContext DeviceContext 86 | { 87 | get { return this.deviceManager.D2DContext; } 88 | } 89 | /// 90 | /// 获取设备管理器。 91 | /// 92 | protected DeviceManager DeviceManager 93 | { 94 | get { return this.deviceManager; } 95 | } 96 | /// 97 | /// 获取需要渲染的拼图碎片列表,以拼图被传入的顺序排列。 98 | /// 99 | protected IList CurrentPieces 100 | { 101 | get { return this.currentPieces; } 102 | } 103 | /// 104 | /// 准备渲染拼图碎片。 105 | /// 106 | /// 拼图使用的图片数据。 107 | /// 所有拼图碎片的集合。 108 | /// 拼图碎片是否可以旋转。 109 | /// 取消任务的通知。 110 | public virtual void PrepareRender(byte[] imageData, JigsawPieceCollection pieces, bool rotatable, 111 | CancellationToken ct) 112 | { 113 | if (imageData == null) 114 | { 115 | throw CommonExceptions.ArgumentNull("imageData"); 116 | } 117 | ClearResources(); 118 | this.Image = this.deviceManager.LoadBitmapFromBytes(imageData); 119 | } 120 | /// 121 | /// 清除渲染使用的资源。 122 | /// 123 | public virtual void ClearResources() 124 | { 125 | if (this.Image != null) 126 | { 127 | this.Image.Dispose(); 128 | this.Image = null; 129 | } 130 | } 131 | /// 132 | /// 渲染指定的拼图碎片。 133 | /// 134 | /// 要绘制的拼图碎片集合。 135 | public void Render(IEnumerable pieces) 136 | { 137 | this.currentPieces.Clear(); 138 | this.currentPieces.AddRange(pieces); 139 | Render(); 140 | } 141 | /// 142 | /// 渲染拼图碎片。 143 | /// 144 | protected abstract void Render(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/ThumbForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace Cyjb.Projects.JigsawGame 6 | { 7 | /// 8 | /// 缩略图窗口。 9 | /// 10 | public partial class ThumbForm : ToolForm 11 | { 12 | /// 13 | /// 显示的缩略图。 14 | /// 15 | private Image image; 16 | /// 17 | /// 图片的缩放比例。 18 | /// 19 | private float imageScale; 20 | /// 21 | /// 最小的可用缩放比例。 22 | /// 23 | private float minScale; 24 | /// 25 | /// 图片的当前缩放比例。 26 | /// 27 | private float currentScale; 28 | /// 29 | /// 上一次的鼠标位置。 30 | /// 31 | private Point lastMouseLocation; 32 | /// 33 | /// 图片的 X 坐标。 34 | /// 35 | private float imageX; 36 | /// 37 | /// 图片的 Y 坐标。 38 | /// 39 | private float imageY; 40 | /// 41 | /// 构造函数。 42 | /// 43 | public ThumbForm() 44 | { 45 | InitializeComponent(); 46 | } 47 | /// 48 | /// 获取或设置显示的缩略图。 49 | /// 50 | public Image Image 51 | { 52 | get { return this.image; } 53 | set 54 | { 55 | this.image = value; 56 | if (this.image != null) 57 | { 58 | minScale = Math.Min((float)this.ClientRectangle.Width / image.Width, 59 | (float)this.ClientRectangle.Height / image.Height); 60 | imageScale = float.NegativeInfinity; 61 | imageX = imageY = 0f; 62 | } 63 | this.Invalidate(); 64 | } 65 | } 66 | 67 | #region 控件事件 68 | 69 | /// 70 | /// 鼠标按下的事件。 71 | /// 72 | private void ThumbForm_MouseDown(object sender, MouseEventArgs e) 73 | { 74 | lastMouseLocation = e.Location; 75 | } 76 | /// 77 | /// 鼠标移动的事件。 78 | /// 79 | private void ThumbForm_MouseMove(object sender, MouseEventArgs e) 80 | { 81 | if (this.image == null) 82 | { 83 | return; 84 | } 85 | if (e.Button == MouseButtons.Left) 86 | { 87 | imageX -= (e.Location.X - lastMouseLocation.X) / this.currentScale; 88 | imageY -= (e.Location.Y - lastMouseLocation.Y) / this.currentScale; 89 | this.Invalidate(); 90 | } 91 | else if (e.Button == MouseButtons.Right) 92 | { 93 | float rate = this.currentScale; 94 | this.imageScale = this.currentScale + (e.Location.X - lastMouseLocation.X) / 200.0f; 95 | rate = this.imageScale / rate - 1; 96 | this.imageX += this.ClientRectangle.Width / 2 * rate; 97 | this.imageY += this.ClientRectangle.Height / 2 * rate; 98 | this.Invalidate(); 99 | } 100 | lastMouseLocation = e.Location; 101 | } 102 | /// 103 | /// 绘制窗体的事件。 104 | /// 105 | private void ThumbForm_Paint(object sender, PaintEventArgs e) 106 | { 107 | e.Graphics.Clear(JigsawSetting.Default.BackgroundColor); 108 | if (image == null) 109 | { 110 | return; 111 | } 112 | float scale = imageScale; 113 | this.ClientDraggable = false; 114 | if (scale < minScale) 115 | { 116 | scale = minScale; 117 | this.ClientDraggable = true; 118 | } 119 | else if (scale > 4f) 120 | { 121 | scale = 4f; 122 | } 123 | currentScale = scale; 124 | float iw = this.ClientRectangle.Width / scale; 125 | float ih = this.ClientRectangle.Height / scale; 126 | if (imageX < 0) 127 | { 128 | imageX = 0; 129 | } 130 | if (imageX > image.Width - iw) 131 | { 132 | imageX = image.Width - iw; 133 | if (imageX < 0) 134 | { 135 | // 令图片居中对齐。 136 | imageX /= 2; 137 | } 138 | } 139 | if (imageY < 0) 140 | { 141 | imageY = 0; 142 | } 143 | if (imageY > image.Height - ih) 144 | { 145 | imageY = image.Height - ih; 146 | if (imageY < 0) 147 | { 148 | // 令图片居中对齐。 149 | imageY /= 2; 150 | } 151 | } 152 | RectangleF imageRect = new RectangleF(imageX, imageY, iw, ih); 153 | e.Graphics.DrawImage(image, this.ClientRectangle, imageRect, GraphicsUnit.Pixel); 154 | } 155 | /// 156 | /// 窗体大小被改变的事件。 157 | /// 158 | private void ThumbForm_SizeChanged(object sender, EventArgs e) 159 | { 160 | if (this.image == null) 161 | { 162 | return; 163 | } 164 | minScale = Math.Min((float)this.ClientRectangle.Width / image.Width, 165 | (float)this.ClientRectangle.Height / image.Height); 166 | this.Invalidate(); 167 | } 168 | 169 | #endregion //控件事件 170 | 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/Path.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cyjb.Collections.ObjectModel; 4 | using SharpDX; 5 | using SharpDX.Direct2D1; 6 | 7 | namespace Cyjb.Projects.JigsawGame.Shape 8 | { 9 | /// 10 | /// 表示一条路径。 11 | /// 12 | [Serializable] 13 | public sealed class Path : ListBase 14 | { 15 | /// 16 | /// 当前路径包含的图形的数目。 17 | /// 18 | private int figureCount = 1; 19 | /// 20 | /// 使用指定的起始点、重心和权重初始化 类的新实例。 21 | /// 22 | /// 路径的起始点。 23 | /// 当前路径是否为黑色。 24 | public Path(Vector2 start, bool isBlack) 25 | { 26 | this.StartPoint = start; 27 | this.IsBlack = isBlack; 28 | } 29 | /// 30 | /// 获取路径的起始点。 31 | /// 32 | public Vector2 StartPoint { get; private set; } 33 | /// 34 | /// 获取或设置路径的重心。 35 | /// 36 | public Vector2 Center { get; set; } 37 | /// 38 | /// 获取路或设置径的权重。 39 | /// 40 | public float Weight { get; set; } 41 | /// 42 | /// 获取当前路径是否为黑色。 43 | /// 44 | public bool IsBlack { get; private set; } 45 | /// 46 | /// 向当前路径中添加一条直线段。 47 | /// 48 | /// 直线段的终结点。 49 | public void AddLine(Vector2 end) 50 | { 51 | this.Add(new LineSegment(end)); 52 | } 53 | /// 54 | /// 向当前路径中添加一条弧线段。 55 | /// 56 | /// 弧线路径段的终结点。 57 | /// 弧线路径段的尺寸。 58 | /// 弧线路径段的旋转角度。 59 | /// 弧线路径段的绘制方向。 60 | /// 弧线路径段是否大于 180 度。 61 | public void AddArc(Vector2 end, Size2F size, float rotationAngel, 62 | SweepDirection sweepDirection, ArcSize arcSize) 63 | { 64 | this.Add(new ArcSegment(end, size, rotationAngel, sweepDirection, arcSize)); 65 | } 66 | /// 67 | /// 向当前路径中添加一条三次贝塞尔曲线。 68 | /// 69 | /// 三次贝塞尔曲线段的终结点。 70 | /// 三次贝塞尔曲线路径的第一个控制点。 71 | /// 三次贝塞尔曲线路径的第二个控制点。 72 | public void AddBezier(Vector2 end, Vector2 point1, Vector2 point2) 73 | { 74 | this.Add(new BezierSegment(end, point1, point2)); 75 | } 76 | /// 77 | /// 将指定集合中的路径段添加到当前集合中。 78 | /// 79 | /// 要添加的路径段集合。 80 | public void AddRange(IEnumerable other) 81 | { 82 | foreach (PathSegment p in other) 83 | { 84 | this.Add(p); 85 | } 86 | } 87 | /// 88 | /// 根据当前的路径生成几何组。 89 | /// 90 | /// Direct2D 工厂。 91 | /// 生成的几何组。 92 | public GeometryGroup GetGeometryGroup(Factory factory) 93 | { 94 | Geometry[] geometries = new Geometry[this.figureCount]; 95 | PathGeometry path = new PathGeometry(factory); 96 | GeometrySink sink = path.Open(); 97 | sink.SetFillMode(FillMode.Winding); 98 | sink.BeginFigure(this.StartPoint, FigureBegin.Filled); 99 | int cnt = this.Count; 100 | int idx = 0; 101 | for (int i = 0; i < cnt; i++) 102 | { 103 | EndFigureSegment end = this[i] as EndFigureSegment; 104 | if (end == null) 105 | { 106 | this[i].FillGeometry(sink); 107 | } 108 | else 109 | { 110 | sink.EndFigure(FigureEnd.Closed); 111 | sink.Close(); 112 | geometries[idx++] = path; 113 | path = new PathGeometry(factory); 114 | sink = path.Open(); 115 | sink.SetFillMode(FillMode.Winding); 116 | sink.BeginFigure(end.EndPoint, FigureBegin.Filled); 117 | } 118 | } 119 | sink.EndFigure(FigureEnd.Closed); 120 | sink.Close(); 121 | geometries[idx++] = path; 122 | return new GeometryGroup(factory, FillMode.Winding, geometries); 123 | } 124 | /// 125 | /// 返回当前路径中包含的形状的颜色(黑/白)。 126 | /// 127 | /// 表示颜色的数组。 128 | public bool[] GetColors() 129 | { 130 | bool[] colors = new bool[figureCount]; 131 | colors[0] = this.IsBlack; 132 | int cnt = this.Count; 133 | for (int i = 0, idx = 1; i < cnt; i++) 134 | { 135 | EndFigureSegment end = this[i] as EndFigureSegment; 136 | if (end != null) 137 | { 138 | colors[idx++] = end.IsBlack; 139 | } 140 | } 141 | return colors; 142 | } 143 | /// 144 | /// 将指定的路径与当前的路径合并。 145 | /// 146 | /// 要合并的路径。 147 | public void Merge(Path path) 148 | { 149 | float sum = this.Weight + path.Weight; 150 | this.Center = new Vector2((this.Center.X * this.Weight + path.Center.X * path.Weight) / sum, 151 | (this.Center.Y * this.Weight + path.Center.Y * path.Weight) / sum); 152 | this.Weight = sum; 153 | this.Add(new EndFigureSegment(path.StartPoint, path.IsBlack)); 154 | this.AddRange(path); 155 | this.figureCount += path.figureCount; 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.18051 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Cyjb.Projects.JigsawGame { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Cyjb.Projects.JigsawGame.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 使用此强类型资源类,为所有资源查找 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 65 | /// 66 | internal static System.Drawing.Bitmap JigsawHelp { 67 | get { 68 | object obj = ResourceManager.GetObject("JigsawHelp", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 75 | /// 76 | internal static System.Drawing.Bitmap Loading { 77 | get { 78 | object obj = ResourceManager.GetObject("Loading", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 85 | /// 86 | internal static System.Drawing.Bitmap Settings { 87 | get { 88 | object obj = ResourceManager.GetObject("Settings", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 95 | /// 96 | internal static System.Drawing.Bitmap ShowBackground { 97 | get { 98 | object obj = ResourceManager.GetObject("ShowBackground", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 105 | /// 106 | internal static System.Drawing.Bitmap ShowBorderOnly { 107 | get { 108 | object obj = ResourceManager.GetObject("ShowBorderOnly", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// 查找 System.Drawing.Bitmap 类型的本地化资源。 115 | /// 116 | internal static System.Drawing.Bitmap ShowThumb { 117 | get { 118 | object obj = ResourceManager.GetObject("ShowThumb", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Renderer/JigsawSimpleRenderer.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Cyjb.Projects.JigsawGame.Jigsaw; 3 | using SharpDX; 4 | using SharpDX.Direct2D1; 5 | 6 | namespace Cyjb.Projects.JigsawGame.Renderer 7 | { 8 | /// 9 | /// 拼图的简单渲染器。 10 | /// 11 | public sealed class JigsawSimpleRenderer : JigsawRenderer 12 | { 13 | /// 14 | /// 绘制拼图碎片的笔刷。 15 | /// 16 | private BitmapBrush brush; 17 | /// 18 | /// 普通边界的笔刷。 19 | /// 20 | private Color normalColor = Color.Black; 21 | /// 22 | /// 高亮边界的笔刷。 23 | /// 24 | private Color highlightColor = Color.Red; 25 | /// 26 | /// 被选择的边界的笔刷。 27 | /// 28 | private Color selectedColor = Color.Red; 29 | /// 30 | /// 普通边界的笔刷。 31 | /// 32 | private SolidColorBrush normalBrush; 33 | /// 34 | /// 高亮边界的笔刷。 35 | /// 36 | private SolidColorBrush highlightBrush; 37 | /// 38 | /// 被选择时的画笔。 39 | /// 40 | private SolidColorBrush selectedBrush; 41 | /// 42 | /// 使用指定的设备管理器初始化 类的新实例。 43 | /// 44 | /// 设备管理器。 45 | public JigsawSimpleRenderer(DeviceManager deviceManager) 46 | : base(deviceManager) 47 | { 48 | InitBrushes(); 49 | } 50 | /// 51 | /// 初始化笔刷。 52 | /// 53 | private void InitBrushes() 54 | { 55 | this.normalBrush = new SolidColorBrush(this.RenderTarget, normalColor); 56 | this.highlightBrush = new SolidColorBrush(this.RenderTarget, highlightColor); 57 | this.selectedBrush = new SolidColorBrush(this.RenderTarget, selectedColor); 58 | } 59 | 60 | #region IDisposable 成员 61 | 62 | /// 63 | /// 释放对象占用的资源。 64 | /// 65 | /// 是否释放托管资源。 66 | protected override void Dispose(bool disposing) 67 | { 68 | this.normalBrush.Dispose(); 69 | this.highlightBrush.Dispose(); 70 | this.selectedBrush.Dispose(); 71 | if (this.brush != null) 72 | { 73 | this.brush.Dispose(); 74 | } 75 | base.Dispose(true); 76 | } 77 | 78 | #endregion // IDisposable 成员 79 | 80 | #region 渲染器属性 81 | 82 | /// 83 | /// 获取拼图渲染器的类型。 84 | /// 85 | public override JigsawRendererType RendererType { get { return JigsawRendererType.Simple; } } 86 | /// 87 | /// 获取或设置普通状态的拼图边框颜色。 88 | /// 89 | public Color NormalBorderColor 90 | { 91 | get { return normalColor; } 92 | set 93 | { 94 | normalColor = value; 95 | normalBrush.Color = value; 96 | } 97 | } 98 | /// 99 | /// 获取或设置高亮状态的拼图边框颜色。 100 | /// 101 | public Color HighlightBorderColor 102 | { 103 | get { return highlightColor; } 104 | set 105 | { 106 | highlightColor = value; 107 | highlightBrush.Color = value; 108 | } 109 | } 110 | /// 111 | /// 获取或设置被选择的状态的拼图边框颜色。 112 | /// 113 | public Color SelectedBorderColor 114 | { 115 | get { return selectedColor; } 116 | set 117 | { 118 | selectedColor = value; 119 | selectedBrush.Color = value; 120 | } 121 | } 122 | 123 | #endregion // 渲染器属性 124 | 125 | /// 126 | /// 准备渲染拼图碎片。 127 | /// 128 | /// 拼图使用的图片数据。 129 | /// 所有拼图碎片的集合。 130 | /// 拼图碎片是否可以旋转。 131 | /// 取消任务的通知。 132 | public override void PrepareRender(byte[] imageData, JigsawPieceCollection pieces, bool rotatable, 133 | CancellationToken ct) 134 | { 135 | base.PrepareRender(imageData, pieces, rotatable, ct); 136 | if (this.brush == null) 137 | { 138 | this.brush = new BitmapBrush(this.RenderTarget, this.Image); 139 | } 140 | else 141 | { 142 | this.brush.Bitmap = this.Image; 143 | } 144 | } 145 | /// 146 | /// 清除渲染使用的资源。 147 | /// 148 | public override void ClearResources() 149 | { 150 | base.ClearResources(); 151 | if (this.brush != null) 152 | { 153 | this.brush.Dispose(); 154 | this.brush = null; 155 | } 156 | } 157 | /// 158 | /// 渲染拼图碎片。 159 | /// 160 | protected override void Render() 161 | { 162 | int idx = CurrentPieces.Count - 1; 163 | for (; idx >= 0; idx--) 164 | { 165 | JigsawPiece piece = CurrentPieces[idx]; 166 | if (!piece.Visible) 167 | { 168 | continue; 169 | } 170 | brush.Transform = piece.TransformMatrix; 171 | this.RenderTarget.FillGeometry(piece.Path, brush); 172 | Brush lineBrush = normalBrush; 173 | if ((piece.State & JigsawPieceState.Selected) == JigsawPieceState.Selected) 174 | { 175 | lineBrush = selectedBrush; 176 | } 177 | else if ((piece.State & JigsawPieceState.Highlight) == JigsawPieceState.Highlight) 178 | { 179 | lineBrush = highlightBrush; 180 | } 181 | this.RenderTarget.DrawGeometry(piece.Path, lineBrush, 1); 182 | } 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/HelpForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class HelpForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btnClose = new System.Windows.Forms.Button(); 32 | this.pbxLink = new System.Windows.Forms.PictureBox(); 33 | this.pbxLicense = new System.Windows.Forms.PictureBox(); 34 | this.pbxHelpLink = new System.Windows.Forms.PictureBox(); 35 | ((System.ComponentModel.ISupportInitialize)(this.pbxLink)).BeginInit(); 36 | ((System.ComponentModel.ISupportInitialize)(this.pbxLicense)).BeginInit(); 37 | ((System.ComponentModel.ISupportInitialize)(this.pbxHelpLink)).BeginInit(); 38 | this.SuspendLayout(); 39 | // 40 | // btnClose 41 | // 42 | this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 43 | this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; 44 | this.btnClose.Location = new System.Drawing.Point(499, 319); 45 | this.btnClose.Name = "btnClose"; 46 | this.btnClose.Size = new System.Drawing.Size(75, 23); 47 | this.btnClose.TabIndex = 4; 48 | this.btnClose.Text = "关闭"; 49 | this.btnClose.UseVisualStyleBackColor = true; 50 | // 51 | // pbxLink 52 | // 53 | this.pbxLink.BackColor = System.Drawing.Color.Transparent; 54 | this.pbxLink.Cursor = System.Windows.Forms.Cursors.Hand; 55 | this.pbxLink.Location = new System.Drawing.Point(279, 7); 56 | this.pbxLink.Name = "pbxLink"; 57 | this.pbxLink.Size = new System.Drawing.Size(174, 25); 58 | this.pbxLink.TabIndex = 5; 59 | this.pbxLink.TabStop = false; 60 | this.pbxLink.Click += new System.EventHandler(this.pbxLink_Click); 61 | // 62 | // pbxLicense 63 | // 64 | this.pbxLicense.BackColor = System.Drawing.Color.Transparent; 65 | this.pbxLicense.Cursor = System.Windows.Forms.Cursors.Hand; 66 | this.pbxLicense.Location = new System.Drawing.Point(72, 33); 67 | this.pbxLicense.Name = "pbxLicense"; 68 | this.pbxLicense.Size = new System.Drawing.Size(380, 25); 69 | this.pbxLicense.TabIndex = 5; 70 | this.pbxLicense.TabStop = false; 71 | this.pbxLicense.Click += new System.EventHandler(this.pbxLicense_Click); 72 | // 73 | // pbxHelpLink 74 | // 75 | this.pbxHelpLink.BackColor = System.Drawing.Color.Transparent; 76 | this.pbxHelpLink.Cursor = System.Windows.Forms.Cursors.Hand; 77 | this.pbxHelpLink.Location = new System.Drawing.Point(212, 327); 78 | this.pbxHelpLink.Name = "pbxHelpLink"; 79 | this.pbxHelpLink.Size = new System.Drawing.Size(62, 25); 80 | this.pbxHelpLink.TabIndex = 5; 81 | this.pbxHelpLink.TabStop = false; 82 | this.pbxHelpLink.Click += new System.EventHandler(this.pbxHelpLink_Click); 83 | // 84 | // HelpForm 85 | // 86 | this.AcceptButton = this.btnClose; 87 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 88 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 89 | this.BackgroundImage = global::Cyjb.Projects.JigsawGame.Resources.JigsawHelp; 90 | this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; 91 | this.CancelButton = this.btnClose; 92 | this.ClientSize = new System.Drawing.Size(586, 354); 93 | this.Controls.Add(this.pbxLicense); 94 | this.Controls.Add(this.pbxHelpLink); 95 | this.Controls.Add(this.pbxLink); 96 | this.Controls.Add(this.btnClose); 97 | this.DoubleBuffered = true; 98 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 99 | this.MaximizeBox = false; 100 | this.MinimizeBox = false; 101 | this.Name = "HelpForm"; 102 | this.ShowIcon = false; 103 | this.ShowInTaskbar = false; 104 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 105 | this.Text = "游戏帮助"; 106 | ((System.ComponentModel.ISupportInitialize)(this.pbxLink)).EndInit(); 107 | ((System.ComponentModel.ISupportInitialize)(this.pbxLicense)).EndInit(); 108 | ((System.ComponentModel.ISupportInitialize)(this.pbxHelpLink)).EndInit(); 109 | this.ResumeLayout(false); 110 | 111 | } 112 | 113 | #endregion 114 | 115 | private System.Windows.Forms.Button btnClose; 116 | private System.Windows.Forms.PictureBox pbxLink; 117 | private System.Windows.Forms.PictureBox pbxLicense; 118 | private System.Windows.Forms.PictureBox pbxHelpLink; 119 | } 120 | } -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/HelpForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/LoadingForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/ThumbForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/BugReportForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/NewGameForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/SettingForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | Resources\JigsawHelp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | Resources\Loading.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | Resources\Settings.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | Resources\ShowBackground.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | Resources\ShowBorderOnly.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | 137 | Resources\ShowThumb.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Shape/JigsawShape.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using SharpDX; 3 | 4 | namespace Cyjb.Projects.JigsawGame.Shape 5 | { 6 | /// 7 | /// 拼图形状的抽象基类。 8 | /// 9 | public class JigsawShape 10 | { 11 | /// 12 | /// 创建指定类型的拼图形状。 13 | /// 14 | /// 拼图形状的类型。 15 | /// 指定类型的拼图形状。 16 | public static JigsawShape CreateShape(JigsawShapeType type) 17 | { 18 | switch (type) 19 | { 20 | case JigsawShapeType.Square: 21 | return new JigsawShape(); 22 | case JigsawShapeType.StandardCirle: 23 | return new JigsawStandardCircleShape(); 24 | case JigsawShapeType.Standard: 25 | return new JigsawStandardShape(); 26 | case JigsawShapeType.StandardSmooth: 27 | return new JigsawStandardSmoothShape(); 28 | } 29 | return null; 30 | } 31 | /// 32 | /// 拼图分割时的随机化程度(0.0 - 1.0)。 33 | /// 34 | private float randomization = 0.3f; 35 | /// 36 | /// 拼图分割的水平片数。 37 | /// 38 | private int horizontalDimension = 10; 39 | /// 40 | /// 拼图分割的垂直片数。 41 | /// 42 | private int verticalDimension = 10; 43 | /// 44 | /// 拼图的尺寸。 45 | /// 46 | private Size2F size = new Size2F(100, 100); 47 | /// 48 | /// 拼图形状集合。 49 | /// 50 | private List paths = new List(); 51 | /// 52 | /// 生成边时需要的随机数个数。 53 | /// 54 | private int randomCount; 55 | /// 56 | /// 创建一个新的拼图划分器。 57 | /// 58 | private JigsawShape() 59 | : this(0) 60 | { } 61 | /// 62 | /// 创建一个新的拼图划分器。 63 | /// 64 | /// 生成边时需要的随机数个数。 65 | protected JigsawShape(int randomCnt) 66 | { 67 | this.randomCount = randomCnt; 68 | } 69 | /// 70 | /// 获取或设置拼图分割时的随机化程度(0.0 - 1.0)。 71 | /// 72 | public float Randomization 73 | { 74 | get { return this.randomization; } 75 | set 76 | { 77 | if (value < 0f || value > 1f) 78 | { 79 | throw CommonExceptions.ArgumentOutOfRange("value", value, 0, 1); 80 | } 81 | else 82 | { 83 | this.randomization = value; 84 | } 85 | } 86 | } 87 | /// 88 | /// 获取或设置拼图分割的水平片数。 89 | /// 90 | public int HorizontalDimension 91 | { 92 | get { return this.horizontalDimension; } 93 | set 94 | { 95 | if (value <= 0) 96 | { 97 | throw CommonExceptions.ArgumentOutOfRange("value", value); 98 | } 99 | this.horizontalDimension = value; 100 | } 101 | } 102 | /// 103 | /// 获取或设置拼图分割的垂直片数。 104 | /// 105 | public int VerticalDimension 106 | { 107 | get { return this.verticalDimension; } 108 | set 109 | { 110 | if (value <= 0) 111 | { 112 | throw CommonExceptions.ArgumentOutOfRange("value", value); 113 | } 114 | this.verticalDimension = value; 115 | } 116 | } 117 | /// 118 | /// 获取或设置拼图的尺寸。 119 | /// 120 | public Size2F Size 121 | { 122 | get { return this.size; } 123 | set 124 | { 125 | if (value.Height <= 0f || value.Width <= 0f) 126 | { 127 | throw CommonExceptions.ArgumentOutOfRange("value", value); 128 | } 129 | this.size = value; 130 | } 131 | } 132 | /// 133 | /// 获取拼图形状集合。 134 | /// 135 | public IList Paths 136 | { 137 | get { return this.paths; } 138 | } 139 | /// 140 | /// 生成拼图形状。 141 | /// 142 | public void GererateJigsawShape() 143 | { 144 | // 拼图尺寸。 145 | float width = Size.Width; 146 | float height = Size.Height; 147 | // 拼图碎片的尺寸。 148 | float pWidth = width / horizontalDimension; 149 | float pHeight = height / verticalDimension; 150 | // 拼图碎片的随机化尺寸。 151 | float rWidth = pWidth * randomization / 3; 152 | float rHeight = pHeight * randomization / 3; 153 | float x, y; 154 | // 最后一行节点。 155 | Vector2[] corners = new Vector2[horizontalDimension + 1]; 156 | Vector2 lastPoint = new Vector2(); 157 | // 最后一行的边凹凸性。 158 | bool[] borders = new bool[horizontalDimension + 1]; 159 | bool lastBorder = false; 160 | // 最后一行的随机数。 161 | float[][] values = new float[horizontalDimension + 1][]; 162 | float[] lastValue = null; 163 | for (int i = 0; i <= this.verticalDimension; i++) 164 | { 165 | for (int j = 0; j <= this.horizontalDimension; j++) 166 | { 167 | y = pHeight * i; 168 | if (i > 0 && i < this.verticalDimension && rHeight != 0f) 169 | { 170 | y += (float)((RandomExt.NextDouble() * 2 - 1) * rHeight); 171 | } 172 | x = pWidth * j; 173 | if (j > 0 && j < horizontalDimension && rWidth != 0f) 174 | { 175 | x += (float)((RandomExt.NextDouble() * 2 - 1) * rWidth); 176 | } 177 | Vector2 currentPoint = new Vector2(x, y); 178 | if (i == 0) 179 | { 180 | corners[j] = currentPoint; 181 | } 182 | else if (j == 0) 183 | { 184 | lastPoint = currentPoint; 185 | } 186 | else 187 | { 188 | // 将拼图碎片放置在国际象棋盘上,每片会分别对应黑色和白色。 189 | bool isBlack = (i + j) % 2 == 0; 190 | Path path = new Path(corners[j], isBlack); 191 | // 逆时针添加边。 192 | // 顶边。 193 | if (i == 1) 194 | { 195 | path.AddLine(corners[j - 1]); 196 | } 197 | else 198 | { 199 | AddBorder(path, corners[j], corners[j - 1], !borders[j], values[j]); 200 | } 201 | // 左边。 202 | if (j == 1) 203 | { 204 | path.AddLine(lastPoint); 205 | } 206 | else 207 | { 208 | AddBorder(path, corners[j - 1], lastPoint, !lastBorder, lastValue); 209 | } 210 | // 底边。 211 | if (i == verticalDimension) 212 | { 213 | path.AddLine(currentPoint); 214 | } 215 | else 216 | { 217 | borders[j] = RandomExt.NextBoolean(); 218 | values[j] = GenerateRandom(); 219 | AddBorder(path, lastPoint, currentPoint, borders[j], values[j]); 220 | } 221 | // 右边。 222 | if (j == horizontalDimension) 223 | { 224 | path.AddLine(corners[j]); 225 | } 226 | else 227 | { 228 | lastBorder = RandomExt.NextBoolean(); 229 | lastValue = GenerateRandom(); 230 | AddBorder(path, currentPoint, corners[j], lastBorder, lastValue); 231 | } 232 | this.paths.Add(path); 233 | // 计算形状的重心。 234 | Vector2 c1 = SharpDXUtility.GetCenter(corners[j - 1], corners[j], lastPoint); 235 | Vector2 c2 = SharpDXUtility.GetCenter(corners[j], lastPoint, currentPoint); 236 | float w1 = SharpDXUtility.Area(corners[j - 1], corners[j], lastPoint); 237 | float w2 = SharpDXUtility.Area(corners[j], lastPoint, currentPoint); 238 | path.Weight = w1 + w2; 239 | path.Center = new Vector2((c1.X * w1 + c2.X * w2) / path.Weight, (c1.Y * w1 + c2.Y * w2) / path.Weight); 240 | corners[j - 1] = lastPoint; 241 | lastPoint = currentPoint; 242 | if (j == this.horizontalDimension) 243 | { 244 | corners[j] = currentPoint; 245 | } 246 | } 247 | } 248 | } 249 | } 250 | /// 251 | /// 生成指定个数的随机数。 252 | /// 253 | /// 生成的随机数数组。 254 | private float[] GenerateRandom() 255 | { 256 | if (randomCount == 0) 257 | { 258 | return null; 259 | } 260 | float[] randoms = new float[randomCount]; 261 | for (int i = 0; i < randomCount; i++) 262 | { 263 | randoms[i] = RandomExt.NextSingle(); 264 | } 265 | return randoms; 266 | } 267 | /// 268 | /// 向拼图碎片的路径中添加一条边,路径的当前节点总是在起始点。 269 | /// 270 | /// 路径。 271 | /// 边的起始点。 272 | /// 边的结束点。 273 | /// 该边的凹凸性。 274 | /// 与该条边相关的一组随机数,范围都是 [0, 1)。 275 | protected virtual void AddBorder(Path path, Vector2 startPoint, Vector2 endPoint, 276 | bool border, float[] randoms) 277 | { 278 | path.AddLine(endPoint); 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/SettingForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class SettingForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.lblBackgroundAlpha = new System.Windows.Forms.Label(); 32 | this.tbarBackgroundAlpha = new System.Windows.Forms.TrackBar(); 33 | this.lblBackgroundAlphaInfo = new System.Windows.Forms.Label(); 34 | this.lblBackgroundColor = new System.Windows.Forms.Label(); 35 | this.pbxBackgroundColor = new System.Windows.Forms.PictureBox(); 36 | this.backgroundColorDialog = new System.Windows.Forms.ColorDialog(); 37 | this.btnClose = new System.Windows.Forms.Button(); 38 | this.lblRenderer = new System.Windows.Forms.Label(); 39 | this.rbtnSample = new System.Windows.Forms.RadioButton(); 40 | this.rbtnEffect = new System.Windows.Forms.RadioButton(); 41 | this.lblEffectWarn = new System.Windows.Forms.Label(); 42 | ((System.ComponentModel.ISupportInitialize)(this.tbarBackgroundAlpha)).BeginInit(); 43 | ((System.ComponentModel.ISupportInitialize)(this.pbxBackgroundColor)).BeginInit(); 44 | this.SuspendLayout(); 45 | // 46 | // lblBackgroundAlpha 47 | // 48 | this.lblBackgroundAlpha.AutoSize = true; 49 | this.lblBackgroundAlpha.Location = new System.Drawing.Point(12, 17); 50 | this.lblBackgroundAlpha.Name = "lblBackgroundAlpha"; 51 | this.lblBackgroundAlpha.Size = new System.Drawing.Size(113, 12); 52 | this.lblBackgroundAlpha.TabIndex = 0; 53 | this.lblBackgroundAlpha.Text = "背景图片不透明度:"; 54 | // 55 | // tbarBackgroundAlpha 56 | // 57 | this.tbarBackgroundAlpha.Location = new System.Drawing.Point(131, 12); 58 | this.tbarBackgroundAlpha.Maximum = 100; 59 | this.tbarBackgroundAlpha.Name = "tbarBackgroundAlpha"; 60 | this.tbarBackgroundAlpha.Size = new System.Drawing.Size(341, 45); 61 | this.tbarBackgroundAlpha.TabIndex = 0; 62 | this.tbarBackgroundAlpha.TickFrequency = 10; 63 | this.tbarBackgroundAlpha.Value = 30; 64 | this.tbarBackgroundAlpha.Scroll += new System.EventHandler(this.tbarBackgroundAlpha_Scroll); 65 | // 66 | // lblBackgroundAlphaInfo 67 | // 68 | this.lblBackgroundAlphaInfo.AutoSize = true; 69 | this.lblBackgroundAlphaInfo.Location = new System.Drawing.Point(129, 45); 70 | this.lblBackgroundAlphaInfo.Name = "lblBackgroundAlphaInfo"; 71 | this.lblBackgroundAlphaInfo.Size = new System.Drawing.Size(23, 12); 72 | this.lblBackgroundAlphaInfo.TabIndex = 1; 73 | this.lblBackgroundAlphaInfo.Text = "30%"; 74 | // 75 | // lblBackgroundColor 76 | // 77 | this.lblBackgroundColor.AutoSize = true; 78 | this.lblBackgroundColor.Location = new System.Drawing.Point(30, 69); 79 | this.lblBackgroundColor.Name = "lblBackgroundColor"; 80 | this.lblBackgroundColor.Size = new System.Drawing.Size(95, 12); 81 | this.lblBackgroundColor.TabIndex = 3; 82 | this.lblBackgroundColor.Text = "游戏背景颜色 :"; 83 | // 84 | // pbxBackgroundColor 85 | // 86 | this.pbxBackgroundColor.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 87 | this.pbxBackgroundColor.Location = new System.Drawing.Point(131, 65); 88 | this.pbxBackgroundColor.Name = "pbxBackgroundColor"; 89 | this.pbxBackgroundColor.Size = new System.Drawing.Size(50, 20); 90 | this.pbxBackgroundColor.TabIndex = 4; 91 | this.pbxBackgroundColor.TabStop = false; 92 | this.pbxBackgroundColor.Click += new System.EventHandler(this.pbxBackgroundColor_Click); 93 | // 94 | // backgroundColorDialog 95 | // 96 | this.backgroundColorDialog.AnyColor = true; 97 | // 98 | // btnClose 99 | // 100 | this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; 101 | this.btnClose.Location = new System.Drawing.Point(205, 121); 102 | this.btnClose.Name = "btnClose"; 103 | this.btnClose.Size = new System.Drawing.Size(75, 23); 104 | this.btnClose.TabIndex = 5; 105 | this.btnClose.Text = "关闭"; 106 | this.btnClose.UseVisualStyleBackColor = true; 107 | // 108 | // lblRenderer 109 | // 110 | this.lblRenderer.AutoSize = true; 111 | this.lblRenderer.Location = new System.Drawing.Point(60, 97); 112 | this.lblRenderer.Name = "lblRenderer"; 113 | this.lblRenderer.Size = new System.Drawing.Size(65, 12); 114 | this.lblRenderer.TabIndex = 6; 115 | this.lblRenderer.Text = "拼图样式:"; 116 | // 117 | // rbtnSample 118 | // 119 | this.rbtnSample.AutoSize = true; 120 | this.rbtnSample.Checked = true; 121 | this.rbtnSample.Location = new System.Drawing.Point(131, 95); 122 | this.rbtnSample.Name = "rbtnSample"; 123 | this.rbtnSample.Size = new System.Drawing.Size(47, 16); 124 | this.rbtnSample.TabIndex = 7; 125 | this.rbtnSample.TabStop = true; 126 | this.rbtnSample.Text = "简单"; 127 | this.rbtnSample.UseVisualStyleBackColor = true; 128 | this.rbtnSample.CheckedChanged += new System.EventHandler(this.rbtnSample_CheckedChanged); 129 | // 130 | // rbtnEffect 131 | // 132 | this.rbtnEffect.AutoSize = true; 133 | this.rbtnEffect.Location = new System.Drawing.Point(184, 95); 134 | this.rbtnEffect.Name = "rbtnEffect"; 135 | this.rbtnEffect.Size = new System.Drawing.Size(47, 16); 136 | this.rbtnEffect.TabIndex = 8; 137 | this.rbtnEffect.Text = "特效"; 138 | this.rbtnEffect.UseVisualStyleBackColor = true; 139 | // 140 | // lblEffectWarn 141 | // 142 | this.lblEffectWarn.AutoSize = true; 143 | this.lblEffectWarn.Enabled = false; 144 | this.lblEffectWarn.Location = new System.Drawing.Point(224, 97); 145 | this.lblEffectWarn.Name = "lblEffectWarn"; 146 | this.lblEffectWarn.Size = new System.Drawing.Size(161, 12); 147 | this.lblEffectWarn.TabIndex = 9; 148 | this.lblEffectWarn.Text = "(您的电脑不支持特效样式)"; 149 | // 150 | // SettingForm 151 | // 152 | this.AcceptButton = this.btnClose; 153 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 154 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 155 | this.CancelButton = this.btnClose; 156 | this.ClientSize = new System.Drawing.Size(484, 157); 157 | this.Controls.Add(this.rbtnEffect); 158 | this.Controls.Add(this.lblEffectWarn); 159 | this.Controls.Add(this.rbtnSample); 160 | this.Controls.Add(this.lblRenderer); 161 | this.Controls.Add(this.btnClose); 162 | this.Controls.Add(this.pbxBackgroundColor); 163 | this.Controls.Add(this.lblBackgroundColor); 164 | this.Controls.Add(this.lblBackgroundAlphaInfo); 165 | this.Controls.Add(this.tbarBackgroundAlpha); 166 | this.Controls.Add(this.lblBackgroundAlpha); 167 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 168 | this.MaximizeBox = false; 169 | this.MinimizeBox = false; 170 | this.Name = "SettingForm"; 171 | this.ShowIcon = false; 172 | this.ShowInTaskbar = false; 173 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 174 | this.Text = "游戏设置"; 175 | ((System.ComponentModel.ISupportInitialize)(this.tbarBackgroundAlpha)).EndInit(); 176 | ((System.ComponentModel.ISupportInitialize)(this.pbxBackgroundColor)).EndInit(); 177 | this.ResumeLayout(false); 178 | this.PerformLayout(); 179 | 180 | } 181 | 182 | #endregion 183 | 184 | private System.Windows.Forms.Label lblBackgroundAlpha; 185 | private System.Windows.Forms.TrackBar tbarBackgroundAlpha; 186 | private System.Windows.Forms.Label lblBackgroundAlphaInfo; 187 | private System.Windows.Forms.Label lblBackgroundColor; 188 | private System.Windows.Forms.PictureBox pbxBackgroundColor; 189 | private System.Windows.Forms.ColorDialog backgroundColorDialog; 190 | private System.Windows.Forms.Button btnClose; 191 | private System.Windows.Forms.Label lblRenderer; 192 | private System.Windows.Forms.RadioButton rbtnSample; 193 | private System.Windows.Forms.RadioButton rbtnEffect; 194 | private System.Windows.Forms.Label lblEffectWarn; 195 | } 196 | } -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/JigsawSetting.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.18051 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Cyjb.Projects.JigsawGame { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class JigsawSetting : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static JigsawSetting defaultInstance = ((JigsawSetting)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new JigsawSetting()))); 19 | 20 | public static JigsawSetting Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("0.3")] 29 | public float BackgroundAlpha { 30 | get { 31 | return ((float)(this["BackgroundAlpha"])); 32 | } 33 | set { 34 | this["BackgroundAlpha"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("400, 300")] 41 | public global::System.Drawing.Size ThumbSize { 42 | get { 43 | return ((global::System.Drawing.Size)(this["ThumbSize"])); 44 | } 45 | set { 46 | this["ThumbSize"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("0, 0")] 53 | public global::System.Drawing.Point ThumbLocation { 54 | get { 55 | return ((global::System.Drawing.Point)(this["ThumbLocation"])); 56 | } 57 | set { 58 | this["ThumbLocation"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 65 | public bool ShowBackground { 66 | get { 67 | return ((bool)(this["ShowBackground"])); 68 | } 69 | set { 70 | this["ShowBackground"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("White")] 77 | public global::System.Drawing.Color BackgroundColor { 78 | get { 79 | return ((global::System.Drawing.Color)(this["BackgroundColor"])); 80 | } 81 | set { 82 | this["BackgroundColor"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("0, 0")] 89 | public global::System.Drawing.Point MainLocation { 90 | get { 91 | return ((global::System.Drawing.Point)(this["MainLocation"])); 92 | } 93 | set { 94 | this["MainLocation"] = value; 95 | } 96 | } 97 | 98 | [global::System.Configuration.UserScopedSettingAttribute()] 99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 100 | [global::System.Configuration.DefaultSettingValueAttribute("0, 0")] 101 | public global::System.Drawing.Size MainSize { 102 | get { 103 | return ((global::System.Drawing.Size)(this["MainSize"])); 104 | } 105 | set { 106 | this["MainSize"] = value; 107 | } 108 | } 109 | 110 | [global::System.Configuration.UserScopedSettingAttribute()] 111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 112 | [global::System.Configuration.DefaultSettingValueAttribute("Normal")] 113 | public global::System.Windows.Forms.FormWindowState MainState { 114 | get { 115 | return ((global::System.Windows.Forms.FormWindowState)(this["MainState"])); 116 | } 117 | set { 118 | this["MainState"] = value; 119 | } 120 | } 121 | 122 | [global::System.Configuration.UserScopedSettingAttribute()] 123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 124 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 125 | public int Difficulty { 126 | get { 127 | return ((int)(this["Difficulty"])); 128 | } 129 | set { 130 | this["Difficulty"] = value; 131 | } 132 | } 133 | 134 | [global::System.Configuration.UserScopedSettingAttribute()] 135 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 136 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 137 | public int Shape { 138 | get { 139 | return ((int)(this["Shape"])); 140 | } 141 | set { 142 | this["Shape"] = value; 143 | } 144 | } 145 | 146 | [global::System.Configuration.UserScopedSettingAttribute()] 147 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 148 | [global::System.Configuration.DefaultSettingValueAttribute("")] 149 | public string FileName { 150 | get { 151 | return ((string)(this["FileName"])); 152 | } 153 | set { 154 | this["FileName"] = value; 155 | } 156 | } 157 | 158 | [global::System.Configuration.UserScopedSettingAttribute()] 159 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 160 | [global::System.Configuration.DefaultSettingValueAttribute("Effect")] 161 | public string Renderer { 162 | get { 163 | return ((string)(this["Renderer"])); 164 | } 165 | set { 166 | this["Renderer"] = value; 167 | } 168 | } 169 | 170 | [global::System.Configuration.UserScopedSettingAttribute()] 171 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 172 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 173 | public bool ShowThumb { 174 | get { 175 | return ((bool)(this["ShowThumb"])); 176 | } 177 | set { 178 | this["ShowThumb"] = value; 179 | } 180 | } 181 | 182 | [global::System.Configuration.UserScopedSettingAttribute()] 183 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 184 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 185 | public bool ShowBorder { 186 | get { 187 | return ((bool)(this["ShowBorder"])); 188 | } 189 | set { 190 | this["ShowBorder"] = value; 191 | } 192 | } 193 | 194 | [global::System.Configuration.UserScopedSettingAttribute()] 195 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 196 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 197 | public bool Anchor { 198 | get { 199 | return ((bool)(this["Anchor"])); 200 | } 201 | set { 202 | this["Anchor"] = value; 203 | } 204 | } 205 | 206 | [global::System.Configuration.UserScopedSettingAttribute()] 207 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 208 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 209 | public bool Rotatable { 210 | get { 211 | return ((bool)(this["Rotatable"])); 212 | } 213 | set { 214 | this["Rotatable"] = value; 215 | } 216 | } 217 | 218 | [global::System.Configuration.UserScopedSettingAttribute()] 219 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 220 | [global::System.Configuration.DefaultSettingValueAttribute("0.3")] 221 | public float Randomization { 222 | get { 223 | return ((float)(this["Randomization"])); 224 | } 225 | set { 226 | this["Randomization"] = value; 227 | } 228 | } 229 | 230 | [global::System.Configuration.UserScopedSettingAttribute()] 231 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 232 | [global::System.Configuration.DefaultSettingValueAttribute("")] 233 | public string ImageFileName { 234 | get { 235 | return ((string)(this["ImageFileName"])); 236 | } 237 | set { 238 | this["ImageFileName"] = value; 239 | } 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Renderer/JigsawRenderPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Windows.Forms; 4 | using SharpDX; 5 | using SharpDX.Windows; 6 | using Point = System.Drawing.Point; 7 | using Size = System.Drawing.Size; 8 | 9 | namespace Cyjb.Projects.JigsawGame.Renderer 10 | { 11 | /// 12 | /// 用于渲染拼图游戏的控件。 13 | /// 14 | public sealed class JigsawRenderPanel : RenderControl 15 | { 16 | /// 17 | /// 设备管理器。 18 | /// 19 | private DeviceManager devices; 20 | /// 21 | /// 自动滚动的定时器。 22 | /// 23 | private Timer autoScrollTimer; 24 | /// 25 | /// 是否自动根据鼠标位置滚动。 26 | /// 27 | private bool autoMouseScroll; 28 | /// 29 | /// 拼图自动滚动的时间间隔。 30 | /// 31 | private int autoMouseScrollInterval = 16; 32 | /// 33 | /// 拼图自动滚动的最小距离。 34 | /// 35 | private int autoMouseScrollMargin = 20; 36 | /// 37 | /// 拼图图片至边距的最小距离。 38 | /// 39 | private float jigsawMargin = 100f; 40 | /// 41 | /// 拼图游戏的矩形范围。 42 | /// 43 | private RectangleF jigsawRegion; 44 | /// 45 | /// 拼图图片的尺寸。 46 | /// 47 | private Size2F imageSize; 48 | /// 49 | /// 拼图游戏的缩放比例。 50 | /// 51 | private float jigsawScale = 1f; 52 | /// 53 | /// 拼图游戏的矩形范围被改变的事件。 54 | /// 55 | public event EventHandler JigsawRegionChanged; 56 | /// 57 | /// 拼图游戏的缩放比例被改变之前的事件。 58 | /// 59 | public event EventHandler JigsawScaleChanging; 60 | /// 61 | /// 拼图游戏的缩放比例被改变的事件。 62 | /// 63 | public event EventHandler JigsawScaleChanged; 64 | /// 65 | /// 获取或设置设备管理器。 66 | /// 67 | public DeviceManager Devices 68 | { 69 | get { return this.devices; } 70 | set 71 | { 72 | this.devices = value; 73 | devices.CreateRenderTarget(this); 74 | } 75 | } 76 | /// 77 | /// 获取或设置拼图图片至边距的最小距离。 78 | /// 79 | [Description("拼图图片至边距的最小距离。")] 80 | [Category("Layout")] 81 | [DefaultValue(100f)] 82 | public float JigsawMargin 83 | { 84 | get { return this.jigsawMargin; } 85 | set 86 | { 87 | this.jigsawMargin = value; 88 | this.UpdateSize(); 89 | } 90 | } 91 | /// 92 | /// 获取拼图游戏的矩形范围。 93 | /// 94 | [Browsable(false)] 95 | public RectangleF JigsawRegion 96 | { 97 | get { return this.jigsawRegion; } 98 | } 99 | /// 100 | /// 获取或设置拼图图片的尺寸。 101 | /// 102 | [Browsable(false)] 103 | public Size2F ImageSize 104 | { 105 | get { return this.imageSize; } 106 | set 107 | { 108 | this.imageSize = value; 109 | this.UpdateSize(); 110 | } 111 | } 112 | /// 113 | /// 获取拼图游戏的缩放比例。 114 | /// 115 | [Browsable(false)] 116 | public float JigsawScale 117 | { 118 | get { return this.jigsawScale; } 119 | } 120 | /// 121 | /// 获取渲染区域的转换矩阵。 122 | /// 123 | [Browsable(false)] 124 | public Matrix3x2 RenderTargetTansform 125 | { 126 | get 127 | { 128 | return Matrix3x2.Translation(this.AutoScrollPosition.X - jigsawRegion.X, 129 | this.AutoScrollPosition.Y - jigsawRegion.Y); 130 | } 131 | } 132 | 133 | #region 尺寸变化 134 | 135 | /// 136 | /// 设置拼图的缩放比例。 137 | /// 138 | /// 缩放比例。 139 | /// 缩放的中心点,是当前的控件坐标。 140 | public void SetJigsawScale(float scale, Point center) 141 | { 142 | EventHandler scaleChanging = this.JigsawScaleChanging; 143 | if (scaleChanging != null) 144 | { 145 | JigsawScaleChangedEventArgs eventArgs = new JigsawScaleChangedEventArgs(scale); 146 | scaleChanging(this, eventArgs); 147 | scale = eventArgs.Scale; 148 | } 149 | if (this.jigsawScale == scale) 150 | { 151 | return; 152 | } 153 | this.jigsawScale = scale; 154 | // 更新尺寸的同时移动滚动条,使缩放的中心点尽可能不变。 155 | float oldWidth = jigsawRegion.Width; 156 | Point scroll = new Point(this.HorizontalScroll.Value + center.X, 157 | this.VerticalScroll.Value + center.Y); 158 | UpdateSize(); 159 | // 这里强制重绘一次,防止出现闪烁。 160 | this.Invalidate(); 161 | float rate = jigsawRegion.Width / oldWidth; 162 | this.AutoScrollPosition = new Point((int)(scroll.X * rate - center.X), (int)(scroll.Y * rate - center.Y)); 163 | EventHandler scaleChanged = this.JigsawScaleChanged; 164 | if (scaleChanged != null) 165 | { 166 | scaleChanged(this, null); 167 | } 168 | } 169 | /// 170 | /// 缩放和滚动拼图,使得图片恰好居中显示在界面中。 171 | /// 172 | public void ShowImage() 173 | { 174 | float sw = this.ClientSize.Width / imageSize.Width; 175 | float sh = this.ClientSize.Height / imageSize.Height; 176 | float scale = 1f; 177 | if (sw < sh) 178 | { 179 | scale = sw; 180 | sw = this.jigsawMargin * scale; 181 | sh = -(this.ClientSize.Height - imageSize.Height * scale) / 2 + this.jigsawMargin * scale; 182 | } 183 | else 184 | { 185 | scale = sh; 186 | sw = -(this.ClientSize.Width - imageSize.Width * scale) / 2 + this.jigsawMargin * scale; 187 | sh = this.jigsawMargin * scale; 188 | } 189 | this.SetJigsawScale(scale, new Point()); 190 | this.AutoScrollPosition = new Point((int)sw, (int)sh); 191 | } 192 | /// 193 | /// 控件尺寸改变的事件。 194 | /// 195 | protected override void OnSizeChanged(EventArgs e) 196 | { 197 | if (devices != null) 198 | { 199 | devices.ResizeRenderTarget(this); 200 | this.UpdateSize(); 201 | } 202 | base.OnSizeChanged(e); 203 | } 204 | /// 205 | /// 更新拼图的尺寸。 206 | /// 207 | private void UpdateSize() 208 | { 209 | jigsawRegion = new RectangleF(-jigsawMargin * jigsawScale, -jigsawMargin * jigsawScale, 210 | (imageSize.Width + 2 * jigsawMargin) * jigsawScale, (imageSize.Height + 2 * jigsawMargin) * jigsawScale); 211 | Size autoScrollMinSize = new Size(0, 0); 212 | if (jigsawRegion.Width < this.ClientSize.Width) 213 | { 214 | jigsawRegion.Left = -(this.ClientSize.Width - imageSize.Width * this.jigsawScale) / 2; 215 | jigsawRegion.Right = jigsawRegion.Left + this.ClientSize.Width; 216 | } 217 | else 218 | { 219 | autoScrollMinSize.Width = (int)jigsawRegion.Width; 220 | } 221 | if (jigsawRegion.Height < this.ClientSize.Height) 222 | { 223 | jigsawRegion.Top = -(this.ClientSize.Height - imageSize.Height * this.jigsawScale) / 2; 224 | jigsawRegion.Bottom = jigsawRegion.Top + this.ClientSize.Height; 225 | } 226 | else 227 | { 228 | autoScrollMinSize.Height = (int)jigsawRegion.Height; 229 | } 230 | EventHandler jigsawRegionChanged = this.JigsawRegionChanged; 231 | if (jigsawRegionChanged != null) 232 | { 233 | jigsawRegionChanged(this, null); 234 | } 235 | this.AutoScrollMinSize = autoScrollMinSize; 236 | } 237 | 238 | #endregion // 尺寸变化 239 | 240 | #region 坐标映射 241 | 242 | /// 243 | /// 将指定渲染区域的坐标转换为拼图的坐标。 244 | /// 245 | /// 渲染区域的坐标。 246 | /// 拼图的坐标。 247 | public Vector2 PointToJigsaw(Point location) 248 | { 249 | return new Vector2(location.X - this.AutoScrollPosition.X + this.jigsawRegion.X, 250 | location.Y - this.AutoScrollPosition.Y + this.jigsawRegion.Y); 251 | } 252 | /// 253 | /// 将指定的拼图坐标转换为渲染区域的坐标。 254 | /// 255 | /// 拼图坐标。 256 | /// 渲染区域的坐标。 257 | public Point PointToClient(Vector2 location) 258 | { 259 | return new Point((int)(location.X + this.AutoScrollPosition.X - this.jigsawRegion.X), 260 | (int)(location.Y + this.AutoScrollPosition.Y - this.jigsawRegion.Y)); 261 | } 262 | 263 | #endregion // 坐标映射 264 | 265 | /// 266 | /// 鼠标滚轮滚动的事件。 267 | /// 268 | protected override void OnMouseWheel(MouseEventArgs e) 269 | { 270 | if (Control.ModifierKeys == Keys.Shift) 271 | { 272 | if (this.HorizontalScroll.Visible) 273 | { 274 | this.AutoScrollPosition = new Point(this.HorizontalScroll.Value - e.Delta / 4, 275 | this.VerticalScroll.Value); 276 | } 277 | } 278 | else if (Control.ModifierKeys == Keys.Control) 279 | { 280 | this.SetJigsawScale(this.jigsawScale + (float)e.Delta / 1200, e.Location); 281 | } 282 | else 283 | { 284 | if (this.VerticalScroll.Visible) 285 | { 286 | this.AutoScrollPosition = new Point(this.HorizontalScroll.Value, 287 | this.VerticalScroll.Value - e.Delta / 4); 288 | } 289 | } 290 | // 屏蔽父控件的鼠标滚轮事件,也不再引发 MouseWheel 事件。 291 | } 292 | 293 | #region 自动滚动 294 | 295 | /// 296 | /// 获取或设置拼图自动滚动的最小距离。 297 | /// 298 | [Description("拼图自动滚动的最小距离。")] 299 | [Category("Layout")] 300 | [DefaultValue(20)] 301 | public int AutoMouseScrollMargin 302 | { 303 | get { return this.autoMouseScrollMargin; } 304 | set { this.autoMouseScrollMargin = value; } 305 | } 306 | /// 307 | /// 获取或设置拼图自动滚动的时间间隔。 308 | /// 309 | [Description("拼图自动滚动的时间间隔。")] 310 | [Category("Behavior")] 311 | [DefaultValue(16)] 312 | public int AutoMouseScrollInterval 313 | { 314 | get { return this.autoMouseScrollInterval; } 315 | set 316 | { 317 | this.autoMouseScrollInterval = value; 318 | if (this.autoScrollTimer != null) 319 | { 320 | this.autoScrollTimer.Interval = value; 321 | } 322 | } 323 | } 324 | /// 325 | /// 获取或设置当前控件是否根据鼠标坐标自动滚动。 326 | /// 327 | [Description("当前控件是否根据鼠标坐标自动滚动。")] 328 | [Category("Behavior")] 329 | [DefaultValue(false)] 330 | public bool AutoMouseScroll 331 | { 332 | get { return this.autoMouseScroll; } 333 | set 334 | { 335 | this.autoMouseScroll = value; 336 | if (this.autoScrollTimer == null) 337 | { 338 | this.autoScrollTimer = new Timer(); 339 | this.autoScrollTimer.Interval = autoMouseScrollInterval; 340 | this.autoScrollTimer.Tick += this.UpdateAutoScrollPosition; 341 | } 342 | if (value) 343 | { 344 | this.autoScrollTimer.Start(); 345 | } 346 | else 347 | { 348 | this.autoScrollTimer.Stop(); 349 | } 350 | } 351 | } 352 | /// 353 | /// 更新自动滚动的位置。 354 | /// 355 | private void UpdateAutoScrollPosition(object sender, EventArgs e) 356 | { 357 | if (this.HorizontalScroll.Visible || this.VerticalScroll.Visible) 358 | { 359 | Point point = this.PointToClient(Control.MousePosition); 360 | int tx = 0, ty = 0; 361 | int tw = this.ClientSize.Width - autoMouseScrollMargin; 362 | int th = this.ClientSize.Height - autoMouseScrollMargin; 363 | if (point.X <= autoMouseScrollMargin) 364 | { 365 | tx = point.X - autoMouseScrollMargin; 366 | } 367 | else if (point.X >= tw) 368 | { 369 | tx = point.X - tw; 370 | } 371 | if (point.Y <= autoMouseScrollMargin) 372 | { 373 | ty = point.Y - autoMouseScrollMargin; 374 | } 375 | else if (point.Y >= th) 376 | { 377 | ty = point.Y - th; 378 | } 379 | if (tx != 0 || ty != 0) 380 | { 381 | this.AutoScrollPosition = new Point(this.HorizontalScroll.Value + tx, 382 | this.VerticalScroll.Value + ty); 383 | this.OnMouseMove(new MouseEventArgs(Control.MouseButtons, 1, point.X, point.Y, 0)); 384 | } 385 | } 386 | } 387 | 388 | #endregion // 自动滚动 389 | 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/NewGameForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Windows.Forms; 8 | using Cyjb.Projects.JigsawGame.Shape; 9 | 10 | namespace Cyjb.Projects.JigsawGame 11 | { 12 | /// 13 | /// 新建游戏的窗体。 14 | /// 15 | public partial class NewGameForm : Form 16 | { 17 | /// 18 | /// 游戏图像。 19 | /// 20 | private Image image; 21 | /// 22 | /// 可分割的最小碎片数。 23 | /// 24 | private int minPieceCount; 25 | /// 26 | /// 可分割的最大碎片数。 27 | /// 28 | private int maxPieceCount; 29 | /// 30 | /// 拼图横向分割的块数。 31 | /// 32 | private int horizontalDimension; 33 | /// 34 | /// 拼图纵向分割的块数。 35 | /// 36 | private int verticalDimension; 37 | /// 38 | /// 图片网格的起始 X 位置。 39 | /// 40 | private float netX; 41 | /// 42 | /// 图片网格的起始 Y 位置。 43 | /// 44 | private float netY; 45 | /// 46 | /// 图片网格的宽度。 47 | /// 48 | private float netW; 49 | /// 50 | /// 图片网格的高度。 51 | /// 52 | private float netH; 53 | /// 54 | /// 绘制网格的画笔。 55 | /// 56 | private Pen pen = new Pen(Color.Red); 57 | /// 58 | /// 拼图的所有合理划分。 59 | /// 60 | private IList partitions = new List(); 61 | /// 62 | /// 拼图信息。 63 | /// 64 | private JigsawInfo info = new JigsawInfo(); 65 | /// 66 | /// 拼图形状。 67 | /// 68 | private JigsawShape shape; 69 | /// 70 | /// 构造函数。 71 | /// 72 | public NewGameForm() 73 | { 74 | InitializeComponent(); 75 | picture.BackColor = JigsawSetting.Default.BackgroundColor; 76 | combShape.DisplayMember = "Text"; 77 | combShape.ValueMember = "Value"; 78 | combShape.DataSource = EnumExt.GetDescValues(); 79 | combDifficulty.SelectedIndex = JigsawSetting.Default.Difficulty; 80 | combShape.SelectedIndex = JigsawSetting.Default.Shape; 81 | cbxRotate.Checked = JigsawSetting.Default.Rotatable; 82 | cbxAnchor.Checked = JigsawSetting.Default.Anchor; 83 | tbarRand.Value = (int)(JigsawSetting.Default.Randomization * 100); 84 | tbarRand_Scroll(tbarRand, null); 85 | } 86 | /// 87 | /// 清理所有正在使用的资源。 88 | /// 89 | /// 如果应释放托管资源,为 true;否则为 false。 90 | protected override void Dispose(bool disposing) 91 | { 92 | if (disposing) 93 | { 94 | if (this.components != null) 95 | { 96 | this.components.Dispose(); 97 | } 98 | this.pen.Dispose(); 99 | if (this.image != null) 100 | { 101 | this.image.Dispose(); 102 | } 103 | } 104 | base.Dispose(disposing); 105 | } 106 | /// 107 | /// 获取拼图信息。 108 | /// 109 | public JigsawInfo JigsawInfo { get { return this.info; } } 110 | /// 111 | /// 获取拼图形状。 112 | /// 113 | public JigsawShape JigsawShape { get { return this.shape; } } 114 | /// 115 | /// 浏览图片。 116 | /// 117 | private void btnPic_Click(object sender, EventArgs e) 118 | { 119 | imageOpenDialog.InitFileName(JigsawSetting.Default.ImageFileName); 120 | if (imageOpenDialog.ShowDialog() == DialogResult.OK) 121 | { 122 | JigsawSetting.Default.ImageFileName = imageOpenDialog.FileName; 123 | try 124 | { 125 | image = Image.FromFile(imageOpenDialog.FileName); 126 | } 127 | catch (OutOfMemoryException) 128 | { 129 | MessageBox.Show("不是有效的图片格式", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); 130 | return; 131 | } 132 | lblPic.Text = string.Concat("选择图片:", imageOpenDialog.FileName, 133 | MultiplyFormat(image.Width, image.Height)); 134 | // 图片缩放后的大小 135 | if (image.Width * picture.Height >= image.Height * picture.Width) 136 | { 137 | netW = picture.Width - 1; 138 | netH = (float)picture.Width * image.Height / image.Width - 1; 139 | netX = 0; 140 | netY = ((float)picture.Height - netH) / 2; 141 | } 142 | else 143 | { 144 | netW = (float)picture.Height * image.Width / image.Height - 1; 145 | netH = picture.Height - 1; 146 | netX = ((float)picture.Width - netW) / 2; 147 | netY = 0; 148 | } 149 | PartitionImage(); 150 | tbarDifficulty.Enabled = tbarRand.Enabled = true; 151 | cbxRotate.Enabled = cbxAnchor.Enabled = true; 152 | combDifficulty.Enabled = combShape.Enabled = true; 153 | btnOK.Enabled = true; 154 | } 155 | } 156 | /// 157 | /// 划分游戏图片。 158 | /// 159 | private void PartitionImage() 160 | { 161 | // 图片的合理划分列表。 162 | int[] tmpPartition = new int[maxPieceCount - minPieceCount + 1]; 163 | // 合理的划分,纵横比例在图片纵横比例上下 1/3 之间,即拼图碎片的比例不会超过 4:3。 164 | float minRatio = (float)image.Height * 3 / (image.Width * 4); 165 | float maxRatio = (float)image.Height * 4 / (image.Width * 3); 166 | for (int hDim = 2; ; hDim++) 167 | { 168 | // 寻找相应的纵向分割块数。 169 | int minVDim = (int)(hDim * minRatio + 1); 170 | int maxVDim = (int)(hDim * maxRatio); 171 | int startVDim = minPieceCount / hDim; 172 | int endVDim = maxPieceCount / hDim; 173 | if (minVDim > endVDim) 174 | { 175 | break; 176 | } 177 | if (endVDim < maxVDim) 178 | { 179 | maxVDim = endVDim; 180 | } 181 | if (startVDim > minVDim) 182 | { 183 | minVDim = startVDim; 184 | } 185 | for (int vDim = minVDim; vDim <= maxVDim; vDim++) 186 | { 187 | int pieceCount = hDim * vDim; 188 | if (pieceCount < minPieceCount) 189 | { 190 | continue; 191 | } 192 | if (pieceCount > maxPieceCount) 193 | { 194 | break; 195 | } 196 | int oldHDim = tmpPartition[pieceCount - minPieceCount]; 197 | if (oldHDim > 0) 198 | { 199 | // 对于相同总块数的不同划分,总是选择最终划分最接近正方形的。 200 | float ratio = ((float)image.Width * pieceCount) / image.Height; 201 | float oldRatio = oldHDim * oldHDim - ratio; 202 | if (oldRatio < 0) 203 | { 204 | oldRatio = -oldRatio; 205 | } 206 | ratio = hDim * hDim - ratio; 207 | if (ratio < 0) 208 | { 209 | ratio = -ratio; 210 | } 211 | if (ratio < oldRatio) 212 | { 213 | tmpPartition[pieceCount - minPieceCount] = hDim; 214 | } 215 | } 216 | else 217 | { 218 | tmpPartition[pieceCount - minPieceCount] = hDim; 219 | } 220 | } 221 | } 222 | partitions.Clear(); 223 | for (int i = minPieceCount; i <= maxPieceCount; i++) 224 | { 225 | if (tmpPartition[i - minPieceCount] > 0) 226 | { 227 | partitions.Add(new Partition(i, tmpPartition[i - minPieceCount])); 228 | } 229 | } 230 | tbarDifficulty.Maximum = partitions.Count - 1; 231 | tbarDifficulty_Scroll(this, null); 232 | } 233 | /// 234 | /// 更新游戏难度信息。 235 | /// 236 | private void tbarDifficulty_Scroll(object sender, EventArgs e) 237 | { 238 | Partition partition = partitions[tbarDifficulty.Value]; 239 | this.horizontalDimension = partition.HorizontalDimension; 240 | this.verticalDimension = partition.VerticalDimension; 241 | lblPieces.Text = string.Concat("碎片数目:", 242 | partition.PieceCount.ToString(CultureInfo.CurrentCulture), 243 | MultiplyFormat(horizontalDimension, verticalDimension)); 244 | picture.Invalidate(); 245 | } 246 | /// 247 | /// 图片框大小被改变的事件。 248 | /// 249 | private void picture_Resize(object sender, EventArgs e) 250 | { 251 | if (image == null) 252 | { 253 | return; 254 | } 255 | // 图片缩放后的大小 256 | if (image.Width * picture.Height >= image.Height * picture.Width) 257 | { 258 | netW = picture.Width - 1; 259 | netH = (float)picture.Width * image.Height / image.Width - 1; 260 | netX = 0; 261 | netY = ((float)picture.Height - netH) / 2; 262 | } 263 | else 264 | { 265 | netW = (float)picture.Height * image.Width / image.Height - 1; 266 | netH = picture.Height - 1; 267 | netX = ((float)picture.Width - netW) / 2; 268 | netY = 0; 269 | } 270 | picture.Invalidate(); 271 | } 272 | /// 273 | /// 在图像上绘制网格。 274 | /// 275 | private void picture_Paint(object sender, PaintEventArgs e) 276 | { 277 | if (image == null) 278 | { 279 | return; 280 | } 281 | e.Graphics.DrawImage(image, netX, netY, netW, netH); 282 | float start = netY, end = netY + netH; 283 | float pieceW = netW / horizontalDimension; 284 | for (int i = 0; i <= horizontalDimension; i++) 285 | { 286 | e.Graphics.DrawLine(pen, netX + i * pieceW, start, netX + i * pieceW, end); 287 | } 288 | start = netX; 289 | end = netX + netW; 290 | float pieceH = netH / verticalDimension; 291 | for (int i = 0; i <= verticalDimension; i++) 292 | { 293 | e.Graphics.DrawLine(pen, start, netY + i * pieceH, end, netY + i * pieceH); 294 | } 295 | } 296 | /// 297 | /// 难度被改变的事件。 298 | /// 299 | private void combDifficulty_SelectedIndexChanged(object sender, EventArgs e) 300 | { 301 | JigsawSetting.Default.Difficulty = combDifficulty.SelectedIndex; 302 | switch (combDifficulty.SelectedIndex) 303 | { 304 | case 0: 305 | minPieceCount = 2; 306 | maxPieceCount = 200; 307 | break; 308 | case 1: 309 | minPieceCount = 201; 310 | maxPieceCount = 400; 311 | break; 312 | case 2: 313 | minPieceCount = 401; 314 | maxPieceCount = 800; 315 | break; 316 | case 3: 317 | minPieceCount = 801; 318 | maxPieceCount = 1200; 319 | break; 320 | } 321 | tbarDifficulty.Value = 0; 322 | if (image != null) 323 | { 324 | PartitionImage(); 325 | } 326 | } 327 | /// 328 | /// 随机程度被改变的事件。 329 | /// 330 | private void tbarRand_Scroll(object sender, EventArgs e) 331 | { 332 | lblRandInfo.Text = tbarRand.Value.ToString(CultureInfo.CurrentCulture) + "%"; 333 | } 334 | /// 335 | /// 确定按钮按下的事件。 336 | /// 337 | private void btnOK_Click(object sender, EventArgs e) 338 | { 339 | JigsawSetting.Default.Shape = combShape.SelectedIndex; 340 | JigsawSetting.Default.Anchor = info.AnchorToBackground = cbxAnchor.Checked; 341 | info.AnchorRadius = 5f; 342 | using (MemoryStream stream = new MemoryStream()) 343 | { 344 | image.Save(stream, ImageFormat.Png); 345 | stream.Seek(0, SeekOrigin.Begin); 346 | info.ImageData = stream.ToArray(); 347 | } 348 | info.Scale = 1f; 349 | info.PieceSum = horizontalDimension * verticalDimension; 350 | JigsawSetting.Default.Rotatable = info.Rotatable = cbxRotate.Checked; 351 | shape = JigsawShape.CreateShape((JigsawShapeType)combShape.SelectedValue); 352 | shape.HorizontalDimension = horizontalDimension; 353 | shape.VerticalDimension = verticalDimension; 354 | JigsawSetting.Default.Randomization = shape.Randomization = (float)tbarRand.Value / 100; 355 | shape.Size = new SharpDX.Size2F(image.Width, image.Height); 356 | this.DialogResult = DialogResult.OK; 357 | } 358 | /// 359 | /// 将指定数字格式化为相乘的格式。 360 | /// 361 | /// 左操作数。 362 | /// 右操作数。 363 | /// 格式化的结果。 364 | private static string MultiplyFormat(int left, int right) 365 | { 366 | return string.Concat(" (", left.ToString(CultureInfo.CurrentCulture), "×", 367 | right.ToString(CultureInfo.CurrentCulture), ")"); 368 | } 369 | /// 370 | /// 表示拼图的一个合理划分。 371 | /// 372 | private struct Partition 373 | { 374 | /// 375 | /// 拼图被分割的总块数。 376 | /// 377 | public int PieceCount; 378 | /// 379 | /// 拼图横向分割的块数。 380 | /// 381 | public int HorizontalDimension; 382 | /// 383 | /// 拼图纵向分割的块数。 384 | /// 385 | public int VerticalDimension; 386 | public Partition(int count, int hDim) 387 | { 388 | this.PieceCount = count; 389 | this.HorizontalDimension = hDim; 390 | this.VerticalDimension = count / hDim; 391 | } 392 | } 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/Cyjb.Projects.JigsawGame.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1D1EF63A-E2E6-4869-81BB-AB049718781F} 8 | WinExe 9 | Properties 10 | Cyjb.Projects.JigsawGame 11 | JigsawGame 12 | v4.5 13 | 512 14 | 15 | false 16 | 发布\ 17 | true 18 | Disk 19 | false 20 | Foreground 21 | 7 22 | Days 23 | false 24 | false 25 | true 26 | 0 27 | 1.0.0.%2a 28 | false 29 | true 30 | 31 | 32 | x86 33 | true 34 | full 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 4 40 | ..\..\Cyjb\CyjbRules.ruleset 41 | true 42 | false 43 | 44 | 45 | AnyCPU 46 | pdbonly 47 | true 48 | ..\bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | ..\..\Cyjb\CyjbRules.ruleset 53 | false 54 | 55 | 56 | JigsawGame.ico 57 | 58 | 59 | true 60 | 61 | 62 | CYJB_Code_Key.snk 63 | 64 | 65 | 66 | False 67 | ..\..\Cyjb\bin\Cyjb.dll 68 | 69 | 70 | False 71 | ..\lib\SharpDX.dll 72 | 73 | 74 | False 75 | ..\lib\SharpDX.Direct2D1.dll 76 | 77 | 78 | ..\lib\SharpDX.Direct3D11.dll 79 | 80 | 81 | False 82 | ..\lib\SharpDX.DXGI.dll 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | Form 94 | 95 | 96 | BugReportForm.cs 97 | 98 | 99 | 100 | 101 | 102 | Form 103 | 104 | 105 | HelpForm.cs 106 | 107 | 108 | 109 | 110 | True 111 | True 112 | JigsawSetting.settings 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | Form 121 | 122 | 123 | LoadingForm.cs 124 | 125 | 126 | Form 127 | 128 | 129 | MainForm.cs 130 | 131 | 132 | Form 133 | 134 | 135 | NewGameForm.cs 136 | 137 | 138 | 139 | 140 | 141 | 142 | UserControl 143 | 144 | 145 | 146 | 147 | 148 | True 149 | True 150 | Resources.resx 151 | 152 | 153 | Form 154 | 155 | 156 | SettingForm.cs 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | Form 173 | 174 | 175 | ThumbForm.cs 176 | 177 | 178 | Form 179 | 180 | 181 | ToolForm.cs 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | SettingsSingleFileGenerator 198 | JigsawSetting.Designer.cs 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | BugReportForm.cs 208 | 209 | 210 | HelpForm.cs 211 | 212 | 213 | LoadingForm.cs 214 | 215 | 216 | MainForm.cs 217 | 218 | 219 | NewGameForm.cs 220 | 221 | 222 | ResXFileCodeGenerator 223 | Resources.Designer.cs 224 | 225 | 226 | SettingForm.cs 227 | 228 | 229 | ThumbForm.cs 230 | 231 | 232 | 233 | 234 | False 235 | Microsoft .NET Framework 4 %28x86 和 x64%29 236 | true 237 | 238 | 239 | False 240 | .NET Framework 3.5 SP1 Client Profile 241 | false 242 | 243 | 244 | False 245 | .NET Framework 3.5 SP1 246 | false 247 | 248 | 249 | False 250 | Windows Installer 4.5 251 | true 252 | 253 | 254 | 255 | 262 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/DeviceManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | using SharpDX; 6 | using SharpDX.Direct2D1; 7 | using SharpDX.Direct3D; 8 | using SharpDX.Direct3D11; 9 | using SharpDX.DXGI; 10 | using SharpDX.IO; 11 | using SharpDX.WIC; 12 | using Bitmap = SharpDX.Direct2D1.Bitmap; 13 | using D2D1AlphaMode = SharpDX.Direct2D1.AlphaMode; 14 | using D2D1Device = SharpDX.Direct2D1.Device; 15 | using D2D1PixelFormat = SharpDX.Direct2D1.PixelFormat; 16 | using D3D11Device = SharpDX.Direct3D11.Device; 17 | using D3D11Device1 = SharpDX.Direct3D11.Device; 18 | using DeviceContext = SharpDX.Direct2D1.DeviceContext; 19 | using DXGIDevice = SharpDX.DXGI.Device; 20 | using DXGIFactory = SharpDX.DXGI.Factory; 21 | using Factory = SharpDX.Direct2D1.Factory; 22 | using PixelFormat = SharpDX.WIC.PixelFormat; 23 | 24 | namespace Cyjb.Projects.JigsawGame 25 | { 26 | /// 27 | /// 设备的管理器。 28 | /// 29 | public sealed class DeviceManager : IDisposable 30 | { 31 | 32 | #region 设备配置 33 | 34 | /// 35 | /// DXGI 格式。 36 | /// 37 | private static readonly Format Format = Format.B8G8R8A8_UNorm; 38 | /// 39 | /// Direct2D 的像素格式。 40 | /// 41 | private static readonly D2D1PixelFormat D2PixelFormat = new D2D1PixelFormat(Format, D2D1AlphaMode.Premultiplied); 42 | /// 43 | /// 像素格式。 44 | /// 45 | private static readonly Guid WICPixelFormat = PixelFormat.Format32bppPBGRA; 46 | /// 47 | /// 桌面的分辨率。 48 | /// 49 | private static Size2F Dpi; 50 | /// 51 | /// 位图的属性。 52 | /// 53 | private static BitmapProperties1 BitmapProps1; 54 | 55 | #endregion // 设备配置 56 | 57 | #region Direct3D 渲染 58 | 59 | /// 60 | /// Direct3D 设备。 61 | /// 62 | private D3D11Device d3DDevice; 63 | /// 64 | /// DXGI 设备。 65 | /// 66 | private DXGIDevice dxgiDevice; 67 | /// 68 | /// DXGI SwapChain。 69 | /// 70 | private SwapChain swapChain; 71 | /// 72 | /// SwapChain 缓冲区。 73 | /// 74 | private Surface backBuffer; 75 | /// 76 | /// 渲染的目标位图。 77 | /// 78 | private Bitmap1 targetBitmap; 79 | 80 | #endregion // Direct3D 渲染 81 | 82 | #region Direct2D 设备 83 | 84 | /// 85 | /// Direct2D 设备。 86 | /// 87 | private D2D1Device d2DDevice; 88 | /// 89 | /// Direct2D 的设备上下文。 90 | /// 91 | private DeviceContext d2DContext; 92 | /// 93 | /// Direct2D 的工厂。 94 | /// 95 | private Factory d2DFactory; 96 | /// 97 | /// Diect2D 渲染目标。 98 | /// 99 | private RenderTarget renderTarget; 100 | 101 | #endregion // Direct2D 设备 102 | 103 | /// 104 | /// Windows 图片组件的工厂。 105 | /// 106 | private ImagingFactory wicFactory; 107 | /// 108 | /// 初始化 类的新实例。 109 | /// 110 | [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] 111 | public DeviceManager() 112 | { 113 | try 114 | { 115 | // 创建 Dierect3D 设备。 116 | this.d3DDevice = new D3D11Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport); 117 | this.dxgiDevice = d3DDevice.QueryInterface().QueryInterface(); 118 | // 创建 Direct2D 设备和工厂。 119 | this.d2DDevice = new D2D1Device(dxgiDevice); 120 | this.d2DContext = new DeviceContext(d2DDevice, DeviceContextOptions.None); 121 | this.d2DFactory = this.d2DContext.Factory; 122 | this.wicFactory = new ImagingFactory2(); 123 | } 124 | catch 125 | { 126 | this.ClearResources(); 127 | try 128 | { 129 | // 创建 D3D 设备异常,则尝试 Direct2D 单线程工厂。 130 | this.d2DFactory = new Factory(FactoryType.SingleThreaded); 131 | this.wicFactory = new ImagingFactory(); 132 | } 133 | catch 134 | { 135 | this.ClearResources(); 136 | } 137 | } 138 | if (this.d2DFactory != null) 139 | { 140 | Dpi = d2DFactory.DesktopDpi; 141 | BitmapProps1 = new BitmapProperties1(D2PixelFormat, Dpi.Width, Dpi.Height, BitmapOptions.Target); 142 | } 143 | } 144 | /// 145 | /// 获取 Direct2D 的设备上下文。 146 | /// 147 | public DeviceContext D2DContext 148 | { 149 | get { return this.d2DContext; } 150 | } 151 | /// 152 | /// 获取 Direct2D 的工厂。 153 | /// 154 | public Factory D2DFactory 155 | { 156 | get { return this.d2DFactory; } 157 | } 158 | /// 159 | /// 获取 Direct2D 的渲染目标。 160 | /// 161 | public RenderTarget RenderTarget 162 | { 163 | get { return renderTarget; } 164 | } 165 | /// 166 | /// 获取是否支持 Direct3D 设备。 167 | /// 168 | public bool SupportD3D 169 | { 170 | get { return this.d2DContext != null; } 171 | } 172 | /// 173 | /// 获取是否支持 Direct2D 设备。 174 | /// 175 | public bool SupportD2D 176 | { 177 | get { return this.d2DFactory != null; } 178 | } 179 | 180 | #region 渲染器 181 | 182 | /// 183 | /// 使用指定的渲染目标控件创建渲染目标。 184 | /// 185 | /// 渲染的目标控件。 186 | public void CreateRenderTarget(Control control) 187 | { 188 | if (SupportD3D) 189 | { 190 | // 创建 Direct3D SwapChain。 191 | SwapChainDescription swapChainDesc = new SwapChainDescription() 192 | { 193 | BufferCount = 1, 194 | Usage = Usage.RenderTargetOutput, 195 | OutputHandle = control.Handle, 196 | IsWindowed = true, 197 | ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format), 198 | SampleDescription = new SampleDescription(1, 0), 199 | SwapEffect = SwapEffect.Discard 200 | }; 201 | this.swapChain = new SwapChain(dxgiDevice.GetParent().GetParent(), 202 | d3DDevice, swapChainDesc); 203 | this.backBuffer = Surface.FromSwapChain(this.swapChain, 0); 204 | this.targetBitmap = new Bitmap1(this.d2DContext, backBuffer); 205 | this.renderTarget = new DeviceContext(this.d2DDevice, DeviceContextOptions.None); 206 | ((DeviceContext)this.renderTarget).Target = targetBitmap; 207 | } 208 | else 209 | { 210 | // 创建 Direct2D 工厂。 211 | // 渲染参数。 212 | RenderTargetProperties renderProps = new RenderTargetProperties 213 | { 214 | PixelFormat = D2PixelFormat, 215 | Usage = RenderTargetUsage.None, 216 | Type = RenderTargetType.Default 217 | }; 218 | // 渲染目标属性。 219 | HwndRenderTargetProperties hwndProps = new HwndRenderTargetProperties() 220 | { 221 | Hwnd = control.Handle, 222 | PixelSize = new Size2(control.ClientSize.Width, control.ClientSize.Height), 223 | PresentOptions = PresentOptions.None 224 | }; 225 | // 渲染目标。 226 | this.renderTarget = new WindowRenderTarget(d2DFactory, renderProps, hwndProps) 227 | { 228 | AntialiasMode = AntialiasMode.PerPrimitive 229 | }; 230 | } 231 | } 232 | /// 233 | /// 调整渲染目标的尺寸。 234 | /// 235 | /// 渲染的目标控件。 236 | public void ResizeRenderTarget(Control control) 237 | { 238 | if (this.swapChain == null) 239 | { 240 | ((WindowRenderTarget)this.renderTarget).Resize( 241 | new Size2(control.ClientSize.Width, control.ClientSize.Height)); 242 | } 243 | else 244 | { 245 | ((DeviceContext)this.renderTarget).Target = null; 246 | this.backBuffer.Dispose(); 247 | this.targetBitmap.Dispose(); 248 | this.swapChain.ResizeBuffers(1, 0, 0, Format, SwapChainFlags.None); 249 | this.backBuffer = Surface.FromSwapChain(this.swapChain, 0); 250 | this.targetBitmap = new Bitmap1(this.d2DContext, backBuffer); 251 | ((DeviceContext)this.renderTarget).Target = targetBitmap; 252 | } 253 | } 254 | /// 255 | /// 开始渲染器的绘制。 256 | /// 257 | public void BeginDraw() 258 | { 259 | this.renderTarget.BeginDraw(); 260 | } 261 | /// 262 | /// 结束渲染器的绘制。 263 | /// 264 | public void EndDraw() 265 | { 266 | this.renderTarget.EndDraw(); 267 | if (this.swapChain != null) 268 | { 269 | this.swapChain.Present(0, PresentFlags.None); 270 | } 271 | } 272 | 273 | #endregion // 渲染器 274 | 275 | #region 辅助方法 276 | 277 | /// 278 | /// 创建指定尺寸的位图。 279 | /// 280 | /// 要创建位图的尺寸。 281 | /// 创建好的位图。 282 | public Bitmap1 CreateBitmap(Size2 size) 283 | { 284 | return new Bitmap1(this.d2DContext, size, BitmapProps1); 285 | } 286 | /// 287 | /// 从给定的 Byte 数组中加载 Direct2D 位图。 288 | /// 289 | /// 要加载位图的数据。 290 | /// 得到的 Direct2D 位图。 291 | public Bitmap LoadBitmapFromBytes(byte[] data) 292 | { 293 | using (MemoryStream stream = new MemoryStream(data)) 294 | { 295 | return LoadBitmapFromStream(stream); 296 | } 297 | } 298 | /// 299 | /// 从给定的流中加载 Direct2D 位图。 300 | /// 301 | /// 要加载位图的流。 302 | /// 得到的 Direct2D 位图。 303 | public Bitmap LoadBitmapFromStream(Stream stream) 304 | { 305 | using (BitmapDecoder decoder = new BitmapDecoder(wicFactory, stream, DecodeOptions.CacheOnLoad)) 306 | { 307 | using (FormatConverter formatConverter = new FormatConverter(wicFactory)) 308 | { 309 | formatConverter.Initialize(decoder.GetFrame(0), WICPixelFormat); 310 | return Bitmap.FromWicBitmap(this.renderTarget, formatConverter); 311 | } 312 | } 313 | } 314 | /// 315 | /// 将 Direct2D 位图保存到文件中。 316 | /// 317 | /// 要保存的位图。 318 | /// 要保存的文件名。 319 | public void SaveBitmapToFile(Bitmap image, string fileName) 320 | { 321 | using (ImagingFactory2 factory = new ImagingFactory2()) 322 | { 323 | using (WICStream stream = new WICStream(factory, fileName, NativeFileAccess.Write)) 324 | { 325 | using (BitmapEncoder encoder = new PngBitmapEncoder(factory)) 326 | { 327 | encoder.Initialize(stream); 328 | using (BitmapFrameEncode bitmapFrameEncode = new BitmapFrameEncode(encoder)) 329 | { 330 | bitmapFrameEncode.Initialize(); 331 | int width = image.PixelSize.Width; 332 | int height = image.PixelSize.Height; 333 | bitmapFrameEncode.SetSize(width, height); 334 | Guid wicPixelFormat = WICPixelFormat; 335 | bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); 336 | using (ImageEncoder imageEncoder = new ImageEncoder(factory, this.d2DDevice)) 337 | { 338 | imageEncoder.WriteFrame(image, bitmapFrameEncode, 339 | new ImageParameters(D2PixelFormat, 96, 96, 0, 0, width, height)); 340 | bitmapFrameEncode.Commit(); 341 | encoder.Commit(); 342 | } 343 | } 344 | } 345 | } 346 | } 347 | } 348 | 349 | #endregion // 辅助方法 350 | 351 | #region IDisposable 成员 352 | 353 | /// 354 | /// 清理所有正在使用的资源。 355 | /// 356 | public void Dispose() 357 | { 358 | ClearResources(); 359 | GC.SuppressFinalize(this); 360 | } 361 | /// 362 | /// 清理所有正在使用的资源,并设置为 null。 363 | /// 364 | private void ClearResources() 365 | { 366 | if (this.d3DDevice != null) 367 | { 368 | this.d3DDevice.Dispose(); 369 | this.d3DDevice = null; 370 | } 371 | if (this.dxgiDevice != null) 372 | { 373 | this.dxgiDevice.Dispose(); 374 | this.dxgiDevice = null; 375 | } 376 | if (this.swapChain != null) 377 | { 378 | this.swapChain.Dispose(); 379 | this.swapChain = null; 380 | } 381 | if (this.backBuffer != null) 382 | { 383 | this.backBuffer.Dispose(); 384 | this.backBuffer = null; 385 | } 386 | if (this.targetBitmap != null) 387 | { 388 | this.targetBitmap.Dispose(); 389 | this.swapChain = null; 390 | } 391 | if (this.d2DDevice != null) 392 | { 393 | this.d2DDevice.Dispose(); 394 | this.d2DDevice = null; 395 | } 396 | if (this.d2DContext != null) 397 | { 398 | this.d2DContext.Dispose(); 399 | this.d2DContext = null; 400 | } 401 | if (this.d2DFactory != null) 402 | { 403 | this.d2DFactory.Dispose(); 404 | this.d2DFactory = null; 405 | } 406 | if (this.renderTarget != null) 407 | { 408 | this.renderTarget.Dispose(); 409 | this.renderTarget = null; 410 | } 411 | if (this.wicFactory != null) 412 | { 413 | this.wicFactory.Dispose(); 414 | this.wicFactory = null; 415 | } 416 | } 417 | 418 | #endregion // IDisposable 成员 419 | 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /Cyjb.Projects.JigsawGame/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Cyjb.Projects.JigsawGame 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// 必需的设计器变量。 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | #region Windows 窗体设计器生成的代码 11 | 12 | /// 13 | /// 设计器支持所需的方法 - 不要 14 | /// 使用代码编辑器修改此方法的内容。 15 | /// 16 | private void InitializeComponent() 17 | { 18 | this.components = new System.ComponentModel.Container(); 19 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 20 | this.mainToolStrip = new System.Windows.Forms.ToolStrip(); 21 | this.newGameTSBtn = new System.Windows.Forms.ToolStripButton(); 22 | this.openGameTSBtn = new System.Windows.Forms.ToolStripButton(); 23 | this.saveGameTSBtn = new System.Windows.Forms.ToolStripButton(); 24 | this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator(); 25 | this.showThumbTSBtn = new System.Windows.Forms.ToolStripButton(); 26 | this.showBackgroundSTBtn = new System.Windows.Forms.ToolStripButton(); 27 | this.showBorderSTBtn = new System.Windows.Forms.ToolStripButton(); 28 | this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); 29 | this.settingsTSBtn = new System.Windows.Forms.ToolStripButton(); 30 | this.helpTSBtn = new System.Windows.Forms.ToolStripButton(); 31 | this.scaleSTBtn = new System.Windows.Forms.ToolStripDropDownButton(); 32 | this.finishSTLabel = new System.Windows.Forms.ToolStripLabel(); 33 | this.timeSTLabel = new System.Windows.Forms.ToolStripLabel(); 34 | this.gameTimer = new System.Windows.Forms.Timer(this.components); 35 | this.gameSaveDialog = new System.Windows.Forms.SaveFileDialog(); 36 | this.gameOpenDialog = new System.Windows.Forms.OpenFileDialog(); 37 | this.renderPanel = new Cyjb.Projects.JigsawGame.Renderer.JigsawRenderPanel(); 38 | this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); 39 | this.mainToolStrip.SuspendLayout(); 40 | this.SuspendLayout(); 41 | // 42 | // mainToolStrip 43 | // 44 | this.mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 45 | this.newGameTSBtn, 46 | this.openGameTSBtn, 47 | this.saveGameTSBtn, 48 | this.toolStripSeparator, 49 | this.showThumbTSBtn, 50 | this.showBackgroundSTBtn, 51 | this.showBorderSTBtn, 52 | this.toolStripSeparator1, 53 | this.settingsTSBtn, 54 | this.helpTSBtn, 55 | this.toolStripSeparator2, 56 | this.scaleSTBtn, 57 | this.finishSTLabel, 58 | this.timeSTLabel}); 59 | this.mainToolStrip.Location = new System.Drawing.Point(0, 0); 60 | this.mainToolStrip.Name = "mainToolStrip"; 61 | this.mainToolStrip.Size = new System.Drawing.Size(584, 25); 62 | this.mainToolStrip.TabIndex = 0; 63 | // 64 | // newGameTSBtn 65 | // 66 | this.newGameTSBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 67 | this.newGameTSBtn.Image = ((System.Drawing.Image)(resources.GetObject("newGameTSBtn.Image"))); 68 | this.newGameTSBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 69 | this.newGameTSBtn.Name = "newGameTSBtn"; 70 | this.newGameTSBtn.Size = new System.Drawing.Size(23, 22); 71 | this.newGameTSBtn.Text = "新建游戏(Ctrl+N)"; 72 | this.newGameTSBtn.Click += new System.EventHandler(this.newGameTSBtn_Click); 73 | // 74 | // openGameTSBtn 75 | // 76 | this.openGameTSBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 77 | this.openGameTSBtn.Image = ((System.Drawing.Image)(resources.GetObject("openGameTSBtn.Image"))); 78 | this.openGameTSBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 79 | this.openGameTSBtn.Name = "openGameTSBtn"; 80 | this.openGameTSBtn.Size = new System.Drawing.Size(23, 22); 81 | this.openGameTSBtn.Text = "打开游戏(Ctrl+O)"; 82 | this.openGameTSBtn.Click += new System.EventHandler(this.openGameTSBtn_Click); 83 | // 84 | // saveGameTSBtn 85 | // 86 | this.saveGameTSBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 87 | this.saveGameTSBtn.Image = ((System.Drawing.Image)(resources.GetObject("saveGameTSBtn.Image"))); 88 | this.saveGameTSBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 89 | this.saveGameTSBtn.Name = "saveGameTSBtn"; 90 | this.saveGameTSBtn.Size = new System.Drawing.Size(23, 22); 91 | this.saveGameTSBtn.Text = "保存游戏(Ctrl+S)"; 92 | this.saveGameTSBtn.Click += new System.EventHandler(this.saveGameTSBtn_Click); 93 | // 94 | // toolStripSeparator 95 | // 96 | this.toolStripSeparator.Name = "toolStripSeparator"; 97 | this.toolStripSeparator.Size = new System.Drawing.Size(6, 25); 98 | // 99 | // showThumbTSBtn 100 | // 101 | this.showThumbTSBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 102 | this.showThumbTSBtn.Image = global::Cyjb.Projects.JigsawGame.Resources.ShowThumb; 103 | this.showThumbTSBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 104 | this.showThumbTSBtn.Name = "showThumbTSBtn"; 105 | this.showThumbTSBtn.Size = new System.Drawing.Size(23, 22); 106 | this.showThumbTSBtn.Text = "显示缩略图(F2)"; 107 | this.showThumbTSBtn.Click += new System.EventHandler(this.showThumbTSBtn_Click); 108 | // 109 | // showBackgroundSTBtn 110 | // 111 | this.showBackgroundSTBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 112 | this.showBackgroundSTBtn.Image = global::Cyjb.Projects.JigsawGame.Resources.ShowBackground; 113 | this.showBackgroundSTBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 114 | this.showBackgroundSTBtn.Name = "showBackgroundSTBtn"; 115 | this.showBackgroundSTBtn.Size = new System.Drawing.Size(23, 22); 116 | this.showBackgroundSTBtn.Text = "显示背景图片(F3)"; 117 | this.showBackgroundSTBtn.Click += new System.EventHandler(this.showBackgroundSTBtn_Click); 118 | // 119 | // showBorderSTBtn 120 | // 121 | this.showBorderSTBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 122 | this.showBorderSTBtn.Image = global::Cyjb.Projects.JigsawGame.Resources.ShowBorderOnly; 123 | this.showBorderSTBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 124 | this.showBorderSTBtn.Name = "showBorderSTBtn"; 125 | this.showBorderSTBtn.Size = new System.Drawing.Size(23, 22); 126 | this.showBorderSTBtn.Text = "显示边框碎片(F4)"; 127 | this.showBorderSTBtn.Click += new System.EventHandler(this.showBorderSTBtn_Click); 128 | // 129 | // toolStripSeparator1 130 | // 131 | this.toolStripSeparator1.Name = "toolStripSeparator1"; 132 | this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); 133 | // 134 | // settingsTSBtn 135 | // 136 | this.settingsTSBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 137 | this.settingsTSBtn.Image = global::Cyjb.Projects.JigsawGame.Resources.Settings; 138 | this.settingsTSBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 139 | this.settingsTSBtn.Name = "settingsTSBtn"; 140 | this.settingsTSBtn.Size = new System.Drawing.Size(23, 22); 141 | this.settingsTSBtn.Text = "设置(F5)"; 142 | this.settingsTSBtn.Click += new System.EventHandler(this.settingsTSBtn_Click); 143 | // 144 | // helpTSBtn 145 | // 146 | this.helpTSBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 147 | this.helpTSBtn.Image = ((System.Drawing.Image)(resources.GetObject("helpTSBtn.Image"))); 148 | this.helpTSBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 149 | this.helpTSBtn.Name = "helpTSBtn"; 150 | this.helpTSBtn.Size = new System.Drawing.Size(23, 22); 151 | this.helpTSBtn.Text = "帮助(F1)"; 152 | this.helpTSBtn.Click += new System.EventHandler(this.helpTSBtn_Click); 153 | // 154 | // scaleSTBtn 155 | // 156 | this.scaleSTBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; 157 | this.scaleSTBtn.Image = ((System.Drawing.Image)(resources.GetObject("scaleSTBtn.Image"))); 158 | this.scaleSTBtn.ImageTransparentColor = System.Drawing.Color.Magenta; 159 | this.scaleSTBtn.Name = "scaleSTBtn"; 160 | this.scaleSTBtn.Size = new System.Drawing.Size(112, 22); 161 | this.scaleSTBtn.Text = "显示比例:100%"; 162 | this.scaleSTBtn.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.scaleSTBtn_DropDownItemClicked); 163 | // 164 | // finishSTLabel 165 | // 166 | this.finishSTLabel.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; 167 | this.finishSTLabel.Name = "finishSTLabel"; 168 | this.finishSTLabel.Size = new System.Drawing.Size(87, 22); 169 | this.finishSTLabel.Text = "完成度:100%"; 170 | // 171 | // timeSTLabel 172 | // 173 | this.timeSTLabel.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; 174 | this.timeSTLabel.Name = "timeSTLabel"; 175 | this.timeSTLabel.Size = new System.Drawing.Size(115, 22); 176 | this.timeSTLabel.Text = "游戏用时:00:00:00"; 177 | // 178 | // gameTimer 179 | // 180 | this.gameTimer.Tick += new System.EventHandler(this.UpdateTime); 181 | // 182 | // gameSaveDialog 183 | // 184 | this.gameSaveDialog.DefaultExt = "*.jig"; 185 | this.gameSaveDialog.FileName = "SavedJigsaw.jig"; 186 | this.gameSaveDialog.Filter = "拼图游戏存档|*.jig"; 187 | this.gameSaveDialog.Title = "保存游戏"; 188 | // 189 | // gameOpenDialog 190 | // 191 | this.gameOpenDialog.DefaultExt = "*.jig"; 192 | this.gameOpenDialog.FileName = "SavedJigsaw.jig"; 193 | this.gameOpenDialog.Filter = "拼图游戏存档|*.jig"; 194 | this.gameOpenDialog.Title = "打开游戏"; 195 | // 196 | // renderPanel 197 | // 198 | this.renderPanel.AutoScroll = true; 199 | this.renderPanel.AutoScrollMinSize = new System.Drawing.Size(200, 200); 200 | this.renderPanel.Dock = System.Windows.Forms.DockStyle.Fill; 201 | this.renderPanel.ImageSize = ((SharpDX.Size2F)(resources.GetObject("renderPanel.ImageSize"))); 202 | this.renderPanel.Location = new System.Drawing.Point(0, 25); 203 | this.renderPanel.Name = "renderPanel"; 204 | this.renderPanel.Size = new System.Drawing.Size(584, 336); 205 | this.renderPanel.TabIndex = 1; 206 | this.renderPanel.TabStop = false; 207 | this.renderPanel.JigsawScaleChanged += new System.EventHandler(this.renderPanel_JigsawScaleChanged); 208 | this.renderPanel.KeyDown += new System.Windows.Forms.KeyEventHandler(this.renderPanel_KeyDown); 209 | // 210 | // toolStripSeparator2 211 | // 212 | this.toolStripSeparator2.Name = "toolStripSeparator2"; 213 | this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); 214 | // 215 | // MainForm 216 | // 217 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 218 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 219 | this.ClientSize = new System.Drawing.Size(584, 361); 220 | this.Controls.Add(this.renderPanel); 221 | this.Controls.Add(this.mainToolStrip); 222 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 223 | this.MinimumSize = new System.Drawing.Size(600, 400); 224 | this.Name = "MainForm"; 225 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 226 | this.Text = "拼图游戏"; 227 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); 228 | this.SizeChanged += new System.EventHandler(this.MainForm_SizeChanged); 229 | this.Move += new System.EventHandler(this.MainForm_Move); 230 | this.mainToolStrip.ResumeLayout(false); 231 | this.mainToolStrip.PerformLayout(); 232 | this.ResumeLayout(false); 233 | this.PerformLayout(); 234 | 235 | } 236 | 237 | #endregion 238 | 239 | private System.Windows.Forms.ToolStrip mainToolStrip; 240 | private System.Windows.Forms.ToolStripButton newGameTSBtn; 241 | private System.Windows.Forms.ToolStripButton openGameTSBtn; 242 | private System.Windows.Forms.ToolStripButton saveGameTSBtn; 243 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator; 244 | private System.Windows.Forms.ToolStripButton showThumbTSBtn; 245 | private System.Windows.Forms.ToolStripButton showBackgroundSTBtn; 246 | private System.Windows.Forms.ToolStripButton showBorderSTBtn; 247 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; 248 | private System.Windows.Forms.ToolStripButton helpTSBtn; 249 | private System.Windows.Forms.ToolStripButton settingsTSBtn; 250 | private Cyjb.Projects.JigsawGame.Renderer.JigsawRenderPanel renderPanel; 251 | private System.Windows.Forms.ToolStripDropDownButton scaleSTBtn; 252 | private System.Windows.Forms.ToolStripLabel finishSTLabel; 253 | private System.Windows.Forms.Timer gameTimer; 254 | private System.Windows.Forms.ToolStripLabel timeSTLabel; 255 | private System.Windows.Forms.SaveFileDialog gameSaveDialog; 256 | private System.Windows.Forms.OpenFileDialog gameOpenDialog; 257 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; 258 | 259 | } 260 | } 261 | 262 | --------------------------------------------------------------------------------