#c# #winforms #graphics #game-loop #c#-native-library
#c# #winforms #графика #игровой цикл #c #-native-library
Вопрос:
Я смог найти набор руководств по Java 2D game tutorials и руководств по играм для Android, в которых используются только собственные графические библиотеки.
Я ищу что-то похожее на C # (без DirectX или XNA)
Я нашел этот скелет игрового цикла, но в нем не указано, как отображать графику.
Цель — имитировать простое электронное устройство.
Мне нужно показать некоторый графический вывод, когда пользователь быстро «нажимает» некоторые клавиши на клавиатуре.Следовательно, это похоже на аркадную игру.
Например, когда пользователь нажимает одну из клавиш со стрелками, указатель (изображение) будет перемещаться соответствующим образом.
Я думаю, я не могу сделать это с помощью обычного приложения Windows Forms, не так ли?
Например, используйте PictureBox
элемент управления и перемещайте его в KeyPress
случае Form
.
Комментарии:
1. Нет причин, по которым вы не можете сделать это с помощью WinForms, хотя это не обязательно будет очень быстро.
2. Winforms и таймер были бы очень простым способом выполнения задач.
3. Например, могу ли я обрабатывать «5 нажатий клавиш» в секунду? И будет ли нормально использовать PictureBox?
4. Для рендеринга графики вы могли бы использовать picturebox. Я бы создал растровое изображение и нарисовал его с помощью графики. FromImage(backbuffer), затем обработайте событие рисования picturebox и нарисуйте backbuffer. В таймере сделайте недействительным поле с картинками, чтобы оно отображалось заново, как только что-то изменится.
5. А как насчет WPF Canvas?
Ответ №1:
Вот простая игра, использующая WinForms
и Timer
, использующая 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)
}
}
}
Комментарии:
1. Спасибо. Я был смущен комментариями и задавался вопросом, каким путем идти. И я собирался оставить сам проект в стороне и бороться с новыми материалами
2. Я реализовал этот код. Идея хорошая, но частота обновления действительно ужасна, я вижу, как перерисовывается speed ball, что просто уродливо с точки зрения пользователей. Я тоже пытаюсь создать демонстрационную 2D-игру, используя обычный c # (без DirectX или XNA) для образовательных целей. Все еще копаю до сих пор
3. Я решил это, добавив двойную буферизацию в форму, используя «DoubleBuffered = true»
4. @MehdiLAMRANI Интересно,
SetStyle
строки должны иметь тот же эффект, что и добавлениеDoubleBuffered = true
.
Ответ №2:
Если вы хотите создавать динамические рисунки, вы можете использовать для этих целей WPF Canvas. Она не поддерживает игры или что-то подобное, но это простой способ рисования примитивных форм и изображений, как вы бы делали на веб-сайте.
Ответ №3:
Собственной платформой рендеринга для приложений .NET winforms является GDI . В Интернете есть много руководств по рисованию простых фигур / графики с использованием GDI