Пишем игры на C++, Часть 2/3 — State-based программирование
Здравствуй, Хабрахабр!
Наконец-то мы будем писать игры! Это заключительная часть из цикла уроков
О чем эта часть?
- Напишем несколько довольно известных игр
Какие именно игры?
- Крестики-нолики
- Змейка (возможно)
- Сапер (возможно)
Исходники и .exe будут представлены в конце статьи
3.1 Крестики-нолики
Классика жанра начинающего девелопера — крестики-нолики.
Это будет небольшой разминкой.
Описывать код в статье не буду, берите попкорн и читайте комментарии в коде :)
Открываем main.cpp
#include "Project.h"
// Размер поля. Размер крестиков и ноликов должен быть 200x200 пикселей
const int GRID_SIZE = 600;
class TicTacToeScreen : public Screen
{
private:
Input* input;
Graphics* graphics;
// Изображения фона, крестиков и ноликов
Image* back;
(Image* player)[2];
// Массив, обозначающий поле, и текущий игрок
int grid[3][3], currplayer;
void StartSettings()
{
// Берем объекты Graphics и Input и устанавливаем заголовок окна
input = game->GetInput();
graphics = game->GetGraphics();
SDL_WM_SetCaption("Tic-Tac-Toe",0);
}
void LoadingImage()
{
// Загрузка изображений
back = graphics->NewImage("C:\\Users\\HOME\\Desktop\\back.bmp");
player[0] = graphics->NewImage("C:\\Users\\HOME\\Desktop\\X.bmp",255,255,255);
player[1] = graphics->NewImage("C:\\Users\\HOME\\Desktop\\O.bmp",255,255,255);
}
void Reset()
{
// Очистка поля и вывод фона
currplayer = 1;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
grid[i][j] = 0;
graphics->DrawImage(back,0,0);
graphics->Flip();
}
int GameOver()
{
// -1 - игра не окончена; 0 - ничья; 1 - победили крестики; 2 - победили нолики
// Проверка на чью-нибудь победу
for(int i = 1; i < 3; i++)
// По горизонтали
if( (grid[0][0] == i && grid[1][0] == i && grid[2][0] == i) ||
(grid[0][1] == i && grid[1][1] == i && grid[2][1] == i) ||
(grid[0][2] == i && grid[1][2] == i && grid[2][2] == i) ||
// По вертикали
(grid[0][0] == i && grid[0][1] == i && grid[0][2] == i) ||
(grid[1][0] == i && grid[1][1] == i && grid[1][2] == i) ||
(grid[2][0] == i && grid[2][1] == i && grid[2][2] == i) ||
// По диагонали
(grid[0][0] == i && grid[1][1] == i && grid[2][2] == i) ||
(grid[2][0] == i && grid[1][1] == i && grid[0][2] == i) )
return i;
// Проверка на ничью
int count = 0;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
if(grid[i][j] != 0)
count++;
// Заполнено все поле
if(count == 9)
return 0;
return -1;
}
void GameOverHandle(int over)
{
// Обработка конца игры
char* message;
switch(over)
{
case 0:
message = "Ничья! Желаете сыграть еще раз?";
break;
case 1:
message = "Крестики победили! Желаете сыграть еще раз?";
break;
case 2:
message = "Нолики победили! Желаете сыграть еще раз?";
break;
// Если игра не окончена, возвращаемся из функции
default:
return;
}
// Спрашиваем пользователя, хочет ли он сыграть еще раз
if(MessageBox(0,message,"Игра окончена",MB_YESNO) == IDYES)
Reset();
else
game->Exit();
}
public:
void Start()
{
StartSettings();
LoadingImage();
Reset();
}
void Update()
{
// Если нажат красный крестик в окне
if(input->IsExit())
game->Exit();
// Если нажата левая кнопка мыши
// P.S. 1 - ЛКМ, 2 - СКМ, 3 - ПКМ
if(input->IsMouseButtonDown(1))
{
// Берем координаты нажатой клетки
int x = input->GetButtonDownCoords().x / (GRID_SIZE / 3),
y = input->GetButtonDownCoords().y / (GRID_SIZE / 3);
// Если мы нажали на пустую клетку
if(grid[x][y] == 0)
{
// Устанавливаем крестик или нолик в клетку
grid[x][y] = currplayer;
if(currplayer == 1)
currplayer = 2;
else
currplayer = 1;
// Рисуем задник
graphics->DrawImage(back,0,0);
// Рисуем крестики и нолики
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
if(grid[i][j] != 0)
graphics->DrawImage(player[ grid[i][j]-1 ], i * (GRID_SIZE / 3), j * (GRID_SIZE / 3));
// Выводим на экран
graphics->Flip();
// Обрабатываем конец игры
GameOverHandle(GameOver());
}
}
}
};
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
Game game;
return game.Execute(new TicTacToeScreen(),GRID_SIZE,GRID_SIZE);
}
TO BE CONTINUED в ближайшее время.
Следите за этим постом
По всем вопросам обращайтесь в ЛС, а если вам не повезло быть зарегистрированным на хабре, пишите на мейл izarizar@mail.ru
This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:
- Massacres That Matter - Part 1 - 'Responsibility To Protect' In Egypt, Libya And Syria
- Massacres That Matter - Part 2 - The Media Response On Egypt, Libya And Syria
- National demonstration: No attack on Syria - Saturday 31 August, 12 noon, Temple Place, London, UK
Комментариев нет:
Отправить комментарий