仅使用本地库在C#中创建简单游戏

6
我可以找到一套仅使用本地图形库的Java 2D游戏教程Android游戏教程。我正在寻找类似于C#的内容(不使用DirectX或XNA)。 我发现了这个游戏循环框架,但它没有说明如何渲染图形。

目标是模拟一个简单的电子设备。当用户快速“按下”键盘上的一些键时,我需要显示一些图形输出。因此看起来像是一个街机游戏。

例如,当用户按下箭头键之一时,指针(一张图片)将相应移动。

我猜我不能用典型的Windows Forms应用程序来实现这个功能,对吗?例如,使用一个PictureBox控件并在FormKeyPress事件中移动它。

你完全可以使用WinForms来实现这个功能,但可能不会很快。 - ChrisF
2
Winforms和一个计时器是非常简单的做事方式。 - George Duckett
1
为了渲染图形,您可以使用picturebox。我会创建一个Bitmap,并使用Graphics.FromImage(backbuffer)进行绘制,然后处理picturebox的Paint事件并在其上绘制backbuffer。在计时器中,使picturebox无效,以便在发生更改时重新绘制它。 - George Duckett
1
那么WPF画布呢? - Marnix
WinForms并不知道如何进行渲染 - 你要找的技术是GDI+ - 我相信在谷歌上有很多很多关于如何使用GDI+绘图的教程 :) - MattDavey
显示剩余3条评论
3个回答

16
这是一个使用 WinFormsTimer 的简单游戏,使用Graphics进行绘制(封装了GDI+)。

它添加了一个计时器,每隔10毫秒“滴答”一次。每次滴答都执行游戏逻辑,然后将其绘制到离屏位图上。这与在链接示例中使用连续循环不同。

表单分别处理按键事件(而不是像使用GetKeyState等操作)

调整窗体大小和第一次加载时,它会创建正确大小的背景缓冲位图。


创建一个新表单并用以下代码替换所有代码。使用箭头键控制球。没有死亡概念。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsGame
{
    public partial class Form1 : Form
    {
        Bitmap Backbuffer;

        const int BallAxisSpeed = 2;

        Point BallPos = new Point(30, 30);
        Point BallSpeed = new Point(BallAxisSpeed, BallAxisSpeed);
        const int BallSize = 50;

        public Form1()
        {
            InitializeComponent();

            this.SetStyle(
            ControlStyles.UserPaint |
            ControlStyles.AllPaintingInWmPaint |
            ControlStyles.DoubleBuffer, true);

            Timer GameTimer = new Timer();
            GameTimer.Interval = 10;
            GameTimer.Tick += new EventHandler(GameTimer_Tick);
            GameTimer.Start();

            this.ResizeEnd += new EventHandler(Form1_CreateBackBuffer);
            this.Load += new EventHandler(Form1_CreateBackBuffer);
            this.Paint += new PaintEventHandler(Form1_Paint);

            this.KeyDown += new KeyEventHandler(Form1_KeyDown);
        }

        void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left)
                BallSpeed.X = -BallAxisSpeed;
            else if (e.KeyCode == Keys.Right)
                BallSpeed.X = BallAxisSpeed;
            else if (e.KeyCode == Keys.Up)
                BallSpeed.Y = -BallAxisSpeed; // Y axis is downwards so -ve is up.
            else if (e.KeyCode == Keys.Down)
                BallSpeed.Y = BallAxisSpeed;
        }

        void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (Backbuffer != null)
            {
                e.Graphics.DrawImageUnscaled(Backbuffer, Point.Empty);
            }
        }

        void Form1_CreateBackBuffer(object sender, EventArgs e)
        {
            if (Backbuffer != null)
                Backbuffer.Dispose();

            Backbuffer = new Bitmap(ClientSize.Width, ClientSize.Height);
        }

        void Draw()
        {
            if (Backbuffer != null)
            {
                using (var g = Graphics.FromImage(Backbuffer))
                {
                    g.Clear(Color.White);
                    g.FillEllipse(Brushes.Black, BallPos.X - BallSize / 2, BallPos.Y - BallSize / 2, BallSize, BallSize);
                }

                Invalidate();
            }
        }

        void GameTimer_Tick(object sender, EventArgs e)
        {
            BallPos.X += BallSpeed.X;
            BallPos.Y += BallSpeed.Y;


            Draw();

            // TODO: Add the notion of dying (disable the timer and show a message box or something)
        }
    }
}

谢谢。我对注释感到困惑,不知道该怎么做。我本来打算把项目放在一边,去学习新的东西。 - Dinushan
我实现了这段代码。这个想法很好,但刷新率真的很糟糕,我可以看到速度球被重新绘制,从用户的角度来看这很丑陋。我也在尝试使用纯C#(不使用DirectX或XNA)实现一个2D游戏演示,以教育为目的。目前还在深入挖掘中。 - Mehdi LAMRANI
我通过在窗体中添加双缓冲来解决它,使用“DoubleBuffered = true”。 - Mehdi LAMRANI
很有趣,SetStyle行应该具有与添加DoubleBuffered = true相同的效果。 - George Duckett

1
如果您想制作动态图形,可以使用WPF Canvas来实现。它不支持游戏等功能,但是它是一种简单的绘制基本形状和图像的方式,就像在网站上一样。

1

.NET WinForms应用程序的本地渲染框架是GDI+。有许多在线教程可以使用GDI+绘制简单的形状/图形。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接