Пятница, 26.04.2024, 12:21
Приветствую Вас Гость | RSS

Кузница миров

Меню сайта
Категории раздела
Мои статьи [2]
Курс : "Основы С++ для начинающих программистов игр." [25]
WindMill Engine [3]
XNA4 RPG [0]
Перевод туториалов но созданию RPG на C# c XNA4.
C# & Leadwerks [5]
Программирование Leadwerks Engine на языке С# с помощью врапера Le.NET.

Каталог статей и уроков

Главная » Статьи » Курс : "Основы С++ для начинающих программистов игр."

1.5. Мини игра «Осада»
Теперь, приобретя некоторые знания, попытаемся написать небольшую игру. А как же иначе, ведь мы будущие программисты игр. В процессе ее разработки мы освоим такие новые элементы языка как переменные, операторы и ввод-вывод.

Планирование
Каждый проект должен начинаться с тщательного планирования. Прежде чем приступить к работе, необходимо решить, что же именно мы будем писать, как это будет реализовано и что для этого понадобится.
Значит, идем по порядку.
Что же именно мы будем делать.
Поскольку наши знания пока еще весьма скудны, ничего сложного написать не получится. Поэтому делать будем простенькую игру об осаде замка. Суть ее будет в том, что у вас есть армия, состоящая из четырех видов войск. В свою очередь каждую стену замка также охраняет определенный вид воинов. В процессе игры необходимо точно определить, кому кого противопоставить, поскольку из всех войск только один их вид способен победить конкретного противника. Если все войска противника погибли, то вы захватили замок, то есть выиграли. Если хоть кто-то выжил, то вы проиграли.

Как это будет реализовано.
Реализовано это будет в виде диалога. Программа сначала выводит небольшое сюжетное введение, а затем последовательно запрашивает у вас данные, и в конце выводит результат. Также в выводимом тексте должны содержаться подсказки по управлению программой.

Что для этого понадобится.
Программа сначала выводит небольшое сюжетное введение, а следовательно для этого мы должны ознакомится с таким понятиями как ввод-вывод и текстовые строки.

Ввод-вывод текстовой информации
Каждая игровая программа, чтобы быть хоть чуточку интересной, должна как-то взаимодействовать с пользователем, ну а в нашем случае - с игроком. То есть она должна выводить определенную информацию и принимать определенные данные. Делая разбор первой программы, мы уже печатали на мониторе текст "Начинающий программист приветствует этот мир!".
Для этого мы воспользовались инструкцией cout. Синтаксис ее такой.

Code
cout << «ВЫВОДИМЫЙ ТЕКСТ»;


cout воплощает в себе стандартное средство вывода, то есть монитор.
Две стрелки(<<) – это специальный оператор потока(поток – последовательность символов или данных вообще). Если говорить по-простому, то этот оператор запихивает наш текст в cout, выводя его таким образом на экран.
Согласно правил, строка текста – это набор символов, заключенных в кавычки. Так компилятор узнает, с чем он работает. В качестве выводимого текста могут быть также и числа. В таком случае кавычки не требуются.

Code
cout << 1545;


Но как же нам вывести сами кавычки, ведь они будут восприниматься как начало или конец строки текста.
То есть вот такая запись будет не верной,

Code
cout << “””;


и компилятор выдаст ошибку.

Для того чтобы все работало так как нужно, используются специальные управляющие символьные последовательности. Кроме того эти последовательности дают возможность выполнить незначительное форматирование выводимого текста. Все управляющие символьные последовательности начинаются с обратного слеша - \ (наклоненная влево вертикальная черта).
Вот некоторые из них:

\a Сигнал
\b Возврат курсора на символ назад
\t Горизонтальная табуляция
\n Переход на новую строку
\v Вертикальная табуляция
\r Возврат курсора на строку вверх
\" Кавычки
\' Апостроф
\0 Ноль-символ
\\ Обратный слеш
\? Вопросительный знак

Теперь, зная их, вместо предыдущего варианта достаточно написать:

Code
cout << “\“”;


и все заработает.
Думаю, настало время немного поиграться. Откройте, если она еще не открыта, созданную ранее первую программу, и подставьте в строчку:

Code
cout << "Начинающий программист приветствует этот мир!";


в любое понравившееся место выводимого текста, одну из представленных символьных последовательностей. Запустите программу и полюбуйтесь на результат. Наигравшись досхочу, можем переходить к изучению дальнейшего материала.

Открою вам один маленький, но неприятный момент. Максимальная длина строки выводимого текста – 256 символов. Если ваш текст окажется длиннее, то все что не поместилось, просто будет отброшено. В общем-то, ничего страшного, ведь на практике редко встречаются такие длинные предложения.
Чтобы напечатать большое количество текста просто достаточно воспользоваться двумя, тремя или вообще любым количеством операторов cout. Вот так это будет выглядеть:

Code
cout << "Допустим что в этом тексте 150 символов.";    
cout << "И в этом 150";    
cout << "Ура, мы напечатали намного больше, чем 256 символов.";


Вышеуказанный пример можно немного сократить. Синтаксис языка допускает такой вариант оформления:

Code
cout << "Допустим что в этом тексте 150 символов." << "И в этом 150"  << "Ура, мы напечатали намного больше, чем 256 символов.";


Как в первом, так и во втором варианте текст будет выведен в одну строку. Каждый следующий cout начинает вывод в том месте, где остановился предыдущий.



Предположим что нам необходимо, чтобы последнее предложение начиналось с новой строки. Для этого достаточно в его начало, или в конец предыдущего, вставить управляющий символ \n. Вот так:

Code
cout << "Допустим что в этом тексте 150 символов." << "И в этом 150"  << "\nУра, мы напечатали намного больше, чем 256 символов.";


И мы получим:



Что и требовалось.

Ну что ж. С выводом данных разобрались, теперь рассмотрим ввод. Для этих целей используется оператор cin. Его мы тоже уже немного упоминали раньше.
Также как и cout, cin ассоциируется с реальным устройством, но в его случае это стандартное устройство ввода – клавиатура. После набора данных и нажатия Enter, вся введенная информация достается cin. Вот синтаксис его использования.

cin >> переменная;

Здесь >> - все тот же поток, но теперь он получает из cin введенные данные и передает их в какую-то переменную. Чтобы следовать в нашем обучении дальше, теперь нам необходимо познакомится с этими самыми переменными.

Переменные. Типы данных.
В своей игре нам нужно в каком то виде представить и хранить наши войска. Со словом хранить в первую очередь ассоциируется такая вещь, как сундук. В языке с++ такими сундуками выступают переменные.
В программировании, как и в математике под переменной подразумевают некую величину, которая при необходимости может варьироваться. Опять на ум приходит то же сундук, в который можно что-то класть, что-то забирать. Также как сундук может быть приспособлен для хранения определенных вещей, так и переменные могут относится к определенному типу данных.
В языке программирования С++ используются основные данные такого типа:
void (Пустой тип) – как это ни парадоксально, но в С++ есть тип, который указывает на отсутствие информации.
char (Символьный тип) – в переменных этого типа может храниться один символ, то есть буква, спецсимвол, одна цифра и другие.
int (Целое число) – как понятно из названия используется для хранения целых чисел.
float (Число с плавающей точкой) – понятно и так, но на всякий случай приведу пример. Это числа вроде – 1.5, 127.52, 0.5867. То есть это числа, в которых присутствуют десятые, сотые, тысячные и т.д.
double – улучшенная, более точная версия float, отличается тем, что в нее вмещается больше цифр после точки.
bool (Логический тип) – очень простой, но весьма важный тип. Может иметь всего два значения – правда и ложь(true и false). Любой из перечисленных выше типов может содержать в себе это логическое значение. Просто если значение есть то это true, а если его нет или оно равно нолю то это false.

Возможно, вам покажется что их мало, но смею вас заверить, что такого их количества нам будет вполне достаточно для любой программы. Если это вас не утешило, могу вас обрадовать, позже мы познакомимся и с другими, а также научимся создавать собственные.
Кроме того что переменная имеет тип, она еще имеет и название ну и естественно какое-то значение. Сейчас я расскажу вам, как создавать, или если использовать терминологию программирования – объявлять, в своей программе переменные определенных типов. Синтаксис этого действия весьма простой:

Тип_данных Имя_переменной;

Думаю, тут все просто. Сначала идет тип данных, затем имя переменной и заканчивается все неизменной точкой с запятой.
Пример:
Code
    int i;
    void Ha;
    bool Pravda;
    float f;


Разбирая объявления нельзя не упомянуть об именах переменных и некоторых правилах:
1. Имя должно содержать только символы латинского алфавита.(В Microsoft Visual Studio 2005/2008 допускается использование кирилицы, тоесть имена можно писать на русском языке)
2. Имя может включать любые другие символы, кроме специальных(!@#$%^&*()+-=/.,<>).
3. Имя должно начинаться только буквой, также допускается символ подчеркивания(_).
4. Имя должно быть уникальным. Двух переменных с одинаковыми именами, пусть даже и разных типов, быть не должно.
5. Имя переменной не должно совпадать с зарезервированными словами.(Зарезервированные слова это слова за которыми в языке программирования С++ закреплены определенные действия или значения. Например include, или типы данных int, bool и т.д. Редактор Microsoft Visual Studio выделяет такие слова синим цветом).

Добавлю еще кое-что. Компилятор языка С++ делает четкое различие между одинаковыми буквами но в разном регистре.
То есть здесь:

Code
int А;
int а;


с точки зрения компилятора было объявлено две разные переменные. И еще один пример:

Code
    int variable;
    int Variable;
    int vARIABLE;
    int vaRiable;
    int variablE;


Все эти переменные также считаются разными.
Скажу еще немного об объявлении. Две и больше переменных одного типа, можно объявить, разместив их в ряд через запятую, после типа данных. Вот так:

Code
    int х, y, z, cell;


Здесь х, y, z, cell – целочисленные переменные.

Ну вот, с объявлением переменных разобрались. Теперь нам нужно уяснить такую вещь. Сами по себе переменные никому не нужны. Важным является лишь содержащееся в них значение, и без разницы символ это, число, или логическое выражение. Поэтому сейчас я расскажу, как это значение переменной присваивается. Для этого используется специальный оператор присвоения. Логично, да? Вот синтаксис присвоения:

Тип_данных Имя_переменной = ЗНАЧЕНИЕ;

Здесь символ равно (=) это и есть оператор присвоения. Все просто. Но не настолько, как вы подумали. Вот пример:

Code
    int i = 127;
    bool Pravda = true;
    float f = 1.5f;
    char c = 'c';


Думаю с типом int и bool все понятно, а вот что это за странное число - 1.5f. Приписанная в его конце буква f означает, что это число с плавающей точкой, то есть – float. Вообще-то можно обойтись и без этой f. Все равно компилятор правильно его обработает. По большему счету, такая запись просто улучшает ориентацию в коде(или если говорить языком программистов – улучшает читабельность).
Ну и напоследок осталось разобраться с типом char. Относящиеся к нему данные в языке С++ записываются заключенными в одинарные кавычки, как выше и показано в примере.
Также следует знать, что значение переменным можно присваивать не только во время их объявления, но и позже. Вот так:

Code
    int х;
    х = 777;


Ну и естественно, значения одних переменных, можно присваивать другим:

Code
    int х;
    х = 777;
    int у = х;


Хранящиеся в сундуке вещи не приносят никакой пользы их владельцу. Так и с переменными. Они должны для чего-то использоваться, взаимодействовать между собой, и как-то меняться. Переменные все-таки. Для работы с «числовыми» типами данных используются специальные арифметические операторы. Их мы дальше и рассмотрим.

Арифметические операторы
Ну, назвав их специальными, я немного погорячился. На самом деле они знакомы нам со школы. Это те же самые:

1. * (умножение),
2. / (деление).
3. +(сложение).
4. - (вычитание),

Думаю, объяснять, что они делают, не нужно, и пока что нам их хватит. В дальнейшем, по мере необходимости я познакомлю вас и с остальными. Да с остальными, ведь не думаете же вы, что в таком мощном языке как С++ всего четыре арифметических оператора.)
Строка кода, содержащая переменные, числа и арифметические операторы называется – выражение. В одном выражении может содержаться сколько угодно операторов:

Code
int х = y + 256 - 13 * z / 3;


Надеюсь, вы помните со школы, что арифметические операторы имеют приоритет выполнения. Если нет, то я вам напомню. Выше по тексту в списке операторы расположены согласно их приоритета. То есть наивысший приоритет имеет умножение, оно будет выполнено в первую очередь, а вычитание будет выполнено последним.
Но самый низкий приоритет среди операторов имеет оператор присвоения (=). В выражении он всегда выполняется последним, присваивая результат вычислений переменной.
Если нам нужно чтобы вычисление в выражении произошло в иной последовательности чем это предписано приоритетами, то необходимо использовать скобки.

Code
int х = y + (256 – 13) * (z / 3);


В этом случае сначала будет выполнено вычитание и деление, а уже затем, согласно приоритета операторов – умножение, а за ним сложение.
Надеюсь что вы еще не устали. На текущий момент это вся информация, которую вам необходимо знать об арифметических операторах. Так что можете немного отвлечься и пойти погулять.

«Осада»
Наконец- то мы добрались до этого места. Сейчас, используя все полученные знания, мы напишем свою первую игру. Раньше мы уже определились, что будем делать, и как это будет реализовано. Ну а в последних разделах я только и делал, что объяснял основы языка программирования, которые нам для этого понадобятся.
В самом начале обучения мы уже написали первую программу. Сейчас мы внесем в нее необходимые изменения, чтоб она превратилась в небольшую игру.
Приступаем к самой интересной части.
Как уже было оговорено раньше, наша игра сначала должна вывести небольшое сюжетное введение. Вы же помните, что за вывод текста у нас отвечает оператор cout. Откроем в редакторе студии ранее созданные файл с исходным кодом, у меня он называется Siege.cpp (siege – с английского «Осада»), и вместо имеющейся там строчки вывода приветствия, добавим следующий код:

Code
    cout << "После долгого, долгого перехода вы наконец-то добрались к окресностям форта,\n";
    cout << "который приказом короля вам велено захватить.\n";
    cout << "Но, как выяснилось, форт хорошо охраняется:\n\n";
    cout << "Южные ворота охраняет Дракон.\n";
    cout << "Северную стену - Голем.\n";
    cout << "На восточной расположились лучники,\n" ;
    cout << "а на западной - крестьяне.\n\n";


Думаю теперь, после моих объяснений, в этом коде вам должно быть все знакомо. У нас здесь есть оператор cout, оператор потока и строки с текстом. Поскольку символов в тексте намного больше, чем допускается, каждую строчку я вывел с помощью отдельного оператора. Чтобы выводимый текст было удобнее читать, он отформатирован с помощью известного вам символа - \n.
Как видно из введения, форт охраняется четырьмя видами войск. Для их представления нам необходимо обьявить четыре целочисленные переменные. Как это сделать, вы уже знаете. Также нам необходимо присвоить им определенные значения. Их необходимо выбрать так, чтобы только в одной комбинации нападающих и защищающихся войск все защитники погибли, то есть, чтобы в соответствующей паре значения совпадали, в таком случае результат их вычитания будет равен нолю.
Я сделал так:

Code
    int Draco=2;    // Дракон
    int Golem=4;    // Голем
    int Arrows=3;    // Лучники
    int Peasant=1;    // Крестьяне


Дальше по сюжету нам необходимо выбрать, на какую стену, то есть против какого противника кого из воинов послать. Список воинов с их порядковыми номерами и небольшой инструкцией выводим следующим кодом:

Code
    cout << "Ваша армия состоит из\n";
    cout << "1. Асасинов\n";
    cout << "2. Магов\n";
    cout << "3. Латников\n";
    cout << "4. Катапульты\n\n";
    cout << "(Для выбора вариант ответа вводите соответствующий номер и нажимаете ENTER.\n";
    cout << "Выбрать войска можно только один раз.)\n\n";
    cout << "Кого вы отправите против Дракона?\n";

.
Здесь тоже все должно быть понятно. В последней строке программа задает вопрос, на который ожидает ответ. То есть далее предполагается получение от пользователя определенных данных. Эти даные нужно где-то хранить, поэтому нам необходимы еще целочисленные переменные. Но поскольку их ввод будет производится последовательно, после каждого введенного числа можно проводить вычисления для отдельного типа войск. Поэтому для ввода нам будет достаточно всего одной переменной.

Code
int i;


Как видим, значение у нее нет, поскольку оно в последствии будет получено от пользователя. Вспоминаем что ввод осуществляется с помощью оператора cin и добавляем необходимый код:

Code
cin >> i;


Здесь программа получит введенное число и передаст ее в переменную i.
После того как даные получены, выполняем вычисления для текущего защитника и нападающего. Для этого используем вот такое простое выражение.

Code
Draco = Draco - i;


Если значениями Draco и i является одинаковое число, то результат вычисления будет равен нолю, что нам и нужно. У меня драконам соответствую маги, големам – катапульта, лучникам – латники а крестьянам – асасины. Поэтому значение переменных в этих парах должно быть одинаковое. Добавим код и для остальных войск. Не забываем выводить запрос, получать введенные данные и проводить вычисления.

Code
cout << "Кого вы отправите против Голема?\n";
    cin >> i;
    Golem = Golem - i;
    cout << "Кого вы отправите против лучников?\n";
    cin >> i;
    Arrows = Arrows - i;
    cout << "Кого вы отправите против крестьян?\n";
    cin >> i;
    Peasant = Peasant - i;


Теперь, когда все данные получены, вычисления произведены можно выводить результат, добавив к нему описание условия победы или поражения:

Code
    cout << "У противника осталось " << Draco << " Драконов, "<< Golem << " Големов, "<< Arrows << " Лучников, "<< Peasant << " Крестьян\n." << "Если войск у противника не осталось - ВЫ ВЫИГРАЛИ";


Как видно из кода, я воспользовался вторым способом вывода, без повторного использования оператора cout. Но в коде, вместо текстовых строк присутствуют используемые для войск переменные. Как я уже упоминал, само имя переменной для программы не важно, она работает с ее значением. Поэтому вместо имен переменных в тексте будут напечатаны их значения. Переменная – это не текст, так что ее имя в кавычки заключать не нужно.
На этом написание нашей первой игры завершено. Добавлю лишь некоторые моменты. Обьявление переменных желательно проводить в начале кода, так сразу будет понятно, какими данными управляет программа.
Строка для вывода данных в конце прграммы получилась слишком длинной и в редакторе вышла за пределы экрана, что неудобно. Поэтому ее можно разбить на несколько частей вставив перенос строки(клавиша Enter). При этом важно знать что разбивать на части операторы, имена переменных или строки нельзя. Подобное будет воспринято компилятором как ошибка. Вот такая запись не правильная:

Code
cout << "У противника    
осталось " << Draco <<
" Драконов, "<< Golem <
< " Големов, ";

Нужно так:

Code
cout << "У противника осталось "
<< Draco <<    
" Драконов, "<< Golem <<
" Големов, ";


Вот полный исходный код нашей игры:

Code
#include <iostream>    
using namespace std;

int main( void )  // главная функция программы
{        
    setlocale( LC_ALL, "Russian" ); // задействование русского языка
       
    int Draco=2;    // переменная для Дракона
    int Golem=4;    // голем
    int Arrows=3;    // лучник
    int Peasant=1;    // крестьянин
    int i=0;  // переменная для хранения введенного игроком числа

    // Вывод вступительного текста
    cout << "После долгого, долгого перехода вы наконец-то добрались к окресностям форта,\n";
    cout << "который приказом короля вам велено захватить.\n";
    cout << "Но, как выяснилось, форт хорошо охраняется:\n\n";
    cout << "Южные ворота охраняет Дракон.\n";
    cout << "Северную стену - Голем.\n";
    cout << "На восточной расположились лучники,\n" ;
    cout << "а на западной - крестьяне.\n\n";
    cout << "Ваша армия состоит из\n";
    cout << "1. Асасинов\n";
    cout << "2. Магов\n";
    cout << "3. Латников\n";
    cout << "4. Катапульты\n\n";
    cout << "(Для выбора вариант ответа вводите соответствующий номер и нажимаете ENTER.\n";
    cout << "Выбрать войска можно только один раз.)\n\n";
    cout << "Кого вы отправите против Дракона?\n";
    cin >> i;    // получение данных от игрока
    Draco = Draco - i;  // вычисление результата для Дракона
    cout << "Кого вы отправите против Голема?\n";
    cin >> i;    // получение данных от игрока
    Golem = Golem - i;  // вычисление результата для Голема
    cout << "Кого вы отправите против лучников?\n";
    cin >> i;    // получение данных от игрока
    Arrows = Arrows - i;    // вычисление результата для Лучников
    cout << "Кого вы отправите против крестьян?\n";
    cin >> i;    // получение данных от игрока
    Peasant = Peasant - i;    // вычисление результата для Крестьян

    // Вывод результата вместе с условиями выиграша
    cout << "У противника осталось " << Draco << " Драконов,"
     << Golem << " Големов, "<< Arrows << " Лучников, "<< Peasant <<    
     " Крестьян\n." << "Если войска остались - ВЫ ПРОИГРАЛИ";

    cin.get();    // ожидание нажатия клавиши
    cin.get();    // ожидание нажатия клавиши
    return 0;    // возвращение значения, и завершение программы
}

В конце программы есть некоторая конструкция, которую я считаю нужным обьяснить.

Code
    cin.get();    // ожидание нажатия клавиши
    cin.get();    // ожидание нажатия клавиши


С cin.get() мы уже знакомы. Она используется для того, чтобы заставить нашу программу подоздать нажатия клавишы. Но почему она дублируется?
Все очень просто. При вводе чисел вы подтвержнаете эту опрацию нажатием клавиши Enter. Так вот это нажатие и будет воспринято cin.get() и программа сразу же завершится. Чтобы этого не произошло, строка cin.get(); написана дважды.

Теперь вы со всем разобрались, конечно игра получилась слишком простая и не совсем корректная, зато ее можно уже запускать и играть, если бы не одно но…
Всегда есть это но. Кто вам сказал, что она у вас запустится?
Категория: Курс : "Основы С++ для начинающих программистов игр." | Добавил: nilrem (10.10.2011)
Просмотров: 1785 | Комментарии: 1 | Рейтинг: 5.0/3
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0