Урок 4.5: Проект: Простая игра
📌 Ключевые моменты этого урока:
- Игровой цикл: UpdateGame() → Invalidate() → Paint() → UI обновляется на экране
- Спрайт - это просто объект с координатами (x, y) и методом Draw()
- Столкновения проверяются через Rectangle.IntersectsWith()
- Игра работает в режиме Timer с Interval ~16-50 мс (зависит от сложности)
- Всегда используйте DoubleBuffered = true и KeyPreview = true для обработки клавиш
Архитектура игры
СТРУКТУРА: Player (спрайт) → Враги/Препятствия → Игровой цикл (Timer) → Столкновения → Score
- Игровой объект (управляемый игроком)
- Враги или препятствия
- Игровой цикл (таймер)
- Обработка столкновений
- Система очков
Игровой цикл
private Timer gameTimer;
private bool isGameRunning = false;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
gameTimer = new Timer();
gameTimer.Interval = 50; // 20 FPS
gameTimer.Tick += GameLoop;
}
private void GameLoop(object sender, EventArgs e)
{
UpdateGame(); // Обновление логики
this.Invalidate(); // Перерисовка
}
private void UpdateGame()
{
// Обновление позиций объектов
// Проверка столкновений
// Обновление счета
}Обработка столкновений
private bool CheckCollision(Rectangle rect1, Rectangle rect2)
{
return rect1.IntersectsWith(rect2);
}
private void UpdateGame()
{
Rectangle playerRect = new Rectangle(playerX, playerY, 20, 20);
foreach (var enemy in enemies)
{
Rectangle enemyRect = new Rectangle(enemy.X, enemy.Y, 20, 20);
if (CheckCollision(playerRect, enemyRect))
{
// Столкновение!
GameOver();
return;
}
}
}Завершенная мини-игра
Создайте игру со следующими элементами:
- Управляемый объект (стрелками или WASD)
- Движущиеся враги
- Система очков
- Экран начала игры
- Экран окончания игры
- Возможность перезапуска
📝 Пример задания — отскакивающий шар
Шар движется с начальной скоростью (4, 3) и отражается от стенок формы. Таймер 16 мс обеспечивает ~60 FPS:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace CSharpGraphicsApp
{
public class Task16_BouncingBall : Form
{
private PointF position = new PointF(100, 100);
private PointF velocity = new PointF(4, 3);
private readonly Timer timer = new Timer();
public Task16_BouncingBall()
{
Text = "Задание 18 — Прыгающий шар";
Size = new Size(600, 400);
BackColor = Color.White;
DoubleBuffered = true;
Paint += Form1_Paint;
timer.Interval = 16;
timer.Tick += Timer_Tick;
timer.Start();
FormClosed += (s, e) => timer.Stop();
}
private void Timer_Tick(object sender, EventArgs e)
{
position.X += velocity.X;
position.Y += velocity.Y;
if (position.X < 0 || position.X > ClientSize.Width - 50)
velocity.X = -velocity.X;
if (position.Y < 0 || position.Y > ClientSize.Height - 50)
velocity.Y = -velocity.Y;
position.X = Math.Max(0, Math.Min(position.X, ClientSize.Width - 50));
position.Y = Math.Max(0, Math.Min(position.Y, ClientSize.Height - 50));
Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
position.X, position.Y, 50, 50);
e.Graphics.DrawString("Отскоки от стенок",
SystemFonts.DefaultFont, Brushes.Black, 10, 10);
}
}
}
Практическое задание
Задание: Простая игра
- Создайте игру "Ловец шариков"
- Реализуйте игровой цикл с таймером
- Добавьте обработку столкновений
- Реализуйте систему очков
Задание по аналогии: Отскакивающий шар
По аналогии с Task16_BouncingBall реализуйте шар, отражающийся от границ окна.
- Добавьте поля
PointF positionиPointF velocityс начальными значениями. - В
Timer_Tickобновляйте позицию:position.X += velocity.X,position.Y += velocity.Y. - При касании левой/правой границы инвертируйте
velocity.X, при касании верхней/нижней —velocity.Y. - Зафиксируйте позицию через
Math.Clamp, чтобы шар не вышел за пределы. - Дополнительно: увеличивайте скорость на 0.1% после каждого отскока.
💡 Совет: Проверяйте границу не
> Width, а > Width - ballSize, иначе шар будет «застревать» в стенке.
Проверка знаний
Ответьте на вопросы, чтобы проверить, насколько хорошо вы усвоили материал:
1. Усвоили ли вы основные концепции урока?
2. Готовы ли вы применить изученное на практике?
3. Что такое игровой цикл?