Подробное руководство пользователя

Задание

В данной работе требуется разработать и реализовать концепцию игры «Zombie day». Смысл игры — заработать 10 тысяч очков опыта уничтожая всех вражеских персонажей с помощью оружия. Цель игры – набрать максимальное количество очков опыта. Требуется продумать систему бонусов, интеллект вражеских персонажей и физику игры.

Целями данного курсового проекта являются:

- практика разработки объектно-ориентированных проектов

- изучение основ проектирования игр

- практика работы с графическими библиотеками

- обучение созданию дружественного пользовательского интерфейса

Введение

Естественное и непреодолимое стремление детей к игре с большим успехом используется в педагогической практике. Существуют научно обоснованные игровые методики и технологии, рассчитанные на детей разного возраста. Основным отличием игры как метода обучения является наличие чёткой цели. Конкретное содержание и формы игрового процесса очень разнообразны и определяются рядом факторов.

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

Именно поэтому, темой курсовой работы я взял игру. Чтобы посмотреть на процесс разработки изнутри, чтобы опробовать свои силы и получить бесценный опыт объектно-ориентированного программирования и разработки компьютерных игр.

Теория

Язык C++

Язык возник в начале 1980-х годов, когда сотрудник фирмы Bell Labs Бьёрн Страуструп придумал ряд усовершенствований к языку C под собственные нужды. До начала официальной стандартизации язык развивался в основном силами Страуструпа в ответ на запросы программистского сообщества. В 1998 году был ратифицирован международный стандарт языка C++: ISO/IEC 14882:1998 «Standard for the C++ Programming Language»; после принятия технических исправлений к стандарту в 2003 году — нынешняя версия этого стандарта — ISO/IEC 14882:2003.[6]

Ранние версии языка, известные под именем «C с классами», начали появляться с 1980 года.[7] Идея создания нового языка берёт начало от опыта программирования Страуструпа для диссертации. Он обнаружил, что язык моделирования Симула имеет такие возможности, которые были бы очень полезны для разработки большого программного обеспечения, но работает слишком медленно. В то же время язык BCPL достаточно быстр, но слишком близок к языкам низкого уровня и не подходит для разработки большого программного обеспечения. Страуструп начал работать в Bell Labs над задачами теории очередей (в приложении к моделированию телефонных вызовов). Попытки применения существующих в то время языков моделирования оказались неэффективными. Вспоминая опыт своей диссертации, Страуструп решил дополнить язык C (преемник BCPL) возможностями, имеющимися в языке Симула. Язык C, будучи базовым языком системы UNIX, на которой работали компьютеры Bell, является быстрым, многофункциональным и переносимым. Страуструп добавил к нему возможность работы с классами и объектами. В результате, практические задачи моделирования оказались доступными для решения как с точки зрения времени разработки (благодаря использованию Симула-подобных классов) так и с точки зрения времени вычислений (благодаря быстродействию C). Вначале в C были добавлены классы (с инкапсуляцией), производные классы, строгая проверка типов, inline-функции и аргументы по умолчанию.

Разрабатывая C с классами (позднее C++), Страуструп также написал программу cfront — транслятор, перерабатывающий исходный код C с классами в исходный код простого C. Новый язык, неожиданно для автора, приобрёл большую популярность среди коллег и вскоре Страуструп уже не мог лично поддерживать его, отвечая на тысячи вопросов.

В 1983 году произошло переименование языка из C с классами в C++. Кроме того, в него были добавлены новые возможности, такие как виртуальные функции, перегрузка функций и операторов, ссылки, константы, пользовательский контроль над управлением свободной памятью, улучшенная проверка типов и новый стиль комментариев (//). Его первый коммерческий выпуск состоялся в октябре 1985 года.

Я использовал среду разработки Borland C++ Builder 6

Среда разработки C++ Builder

C++ Builder представляет собой SDI-приложение, главное окно которого содержит настраиваемую инструментальную панель (слева) и палитру компонентов (справа). Помимо этого, по умолчанию при запуске C++ Builder появляются окно инспектора объектов (слева) и форма нового приложения (справа). Под окном формы приложения находится окно редактора кода.

Формы являются основой приложений C++ Builder. Создание пользовательского интерфейса приложения заключается в добавлении в окно формы элементов объектов C++ Builder, называемых компонентами. Компоненты C++ Builder располагаются на палитре компонентов, выполненной в виде многостраничного блокнота. Важная особенность C++ Builder состоит в том, что он позволяет создавать собственные компоненты и настраивать палитру компонентов, а также создавать различные версии палитры компонентов для разных проектов.

Компоненты C++ Builder

Компоненты разделяются на видимые (визуальные) и невидимые (невизуальные). Визуальные компоненты появляются во время выполнения точно так же, как и во время проектирования. Примерами являются кнопки и редактируемые поля. Невизуальные компоненты появляются во время проектирования как пиктограммы на форме. Они никогда не видны во время выполнения, но обладают определенной функциональностью (например, обеспечивают доступ к данным, вызывают стандартные диалоги Windows и др.)

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

Каждый компонент C++ Builder имеет три разновидности характеристик: свойства, события и методы.

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

Свойства компонентов

Свойства являются атрибутами компонента, определяющими его внешний вид и поведение. Многие свойства компонента в колонке свойств имеют значение, устанавливаемое по умолчанию (например, высота кнопок). Свойства компонента отображаются на странице свойств (Properties). Инспектор объектов отображает опубликованные (published) свойства компонентов. Помимо published-свойств, компоненты могут и чаще всего имеют общие (public), опубликованные свойства, которые доступны только во время выполнения приложения. Инспектор объектов используется для установки свойств во время проектирования. Список свойств располагается на странице свойств инспектора объектов. Можно определить свойства во время проектирования или написать код для видоизменения свойств компонента во время выполнения приложения.

При определении свойств компонента во время проектирования нужно выбрать компонент на форме, открыть страницу свойств в инспекторе объектов, выбрать определяемое свойство и изменить его с помощью редактора свойств (это может быть простое поле для ввода текста или числа, выпадающий список, раскрывающийся список, диалоговая панель и т.д.).

События

Страница событий (Events) инспектора объектов показывает список событий, распознаваемых компонентом (программирование для операционных систем с графическим пользовательским интерфейсом, в частности, для Windows 95 или Windows NT пре полагает описание реакции приложения на те или иные события, а сама операционная система занимается постоянным опросом компьютера с целью выявления наступления какого-либо события). Каждый компонент имеет свой собственный набор обработчиков событий. В C++ Builder следует писать функции, называемые обработчиками событий, и связывать события с этими функциями. Создавая обработчик того или иного события, вы поручаете программе выполнить написанную функцию, если это событие произойдет.

Для того чтобы добавить обработчик событий, нужно выбрать на форме с помощью мыши компонент, которому необходим обработчик событий, затем открыть страницу событий инспектора объектов и дважды щелкнуть левой клавишей мыши на колонке значений рядом с событием, чтобы заставить C++ Builder сгенерировать прототип обработчика событий и показать его в редакторе кода. При этом автоматически генерируется текст пустой функции, и редактор открывается в том месте, где следует вводить код. Курсор позиционируется внутри операторных скобок { ... }. Далее нужно ввести код, который должен выполняться при наступлении события. Обработчик событий может иметь параметры, которые указываются после имени функции в круглых скобках.

Методы

Метод является функцией, которая связана с компонентом, и которая объявляется как часть объекта. Создавая обработчики событий, можно вызывать методы, используя следующую нотацию: ->, например:

Edit1->Show();

Отметим, что при создании формы связанные с ней модуль и заголовочный файл с расширением *.h генерируются обязательно, тогда как при создании нового модуля он не обязан быть связан с формой (например, если в нем содержатся процедуры расчетов). Имена формы и модуля можно изменить, причем желательно сделать это сразу после создания, пока на них не появилось много ссылок в других формах и модулях.

Практика

Основные концепции

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

Необходимо реализовать:

· Физику движения(обработка столкновений с блоками, с игроком, с пулями и с вражескими персонажами)

· Систему состояний объектов игрового мира(состояния игрока, пулей и персонажа)

· Систему бонусов и их взаимодействия с объектами игрового мира

· Реализовать систему жизней(кол-во очков здоровья).

· Реализовать интеллект для врагов.

· Интуитивно понятный дружелюбный интерфейс

· Реализовать систему уровней

По сути, игра представляет собой меняющиеся по времени сложность игры. Игра прекращается, как только пользователь потерял все жизни.

Описание объектов

Игрок – имеет здоровье(HP), оружие(Arm), гранаты, скорость(Speed), зависящую от нажатия клавиш W A S D. Персонаж представлен классом TPerson, наследованного от класса TCreature .

Вражеские персонажи – имеют здоровье(HP), 2 состояния, скорость(Speed), урон(Damage), который они наносит игроку. Вражеский персонаж представлен классом TMonster, наследованного от класса TCreature. Состояния в которых может находится персонаж это с оружием и без оружия. Обычно персонаж находится в режиме без оружия и имеет силу удара равную 1. В режиме с оружием, появляется после нахождения в игровой области более 15 персонажей.

Оружие – имеет скорость перезарядки между обоймами, интервал между выстрелом и количество патрон. Представлен классом TArm.

Пуля – имеет скорость, наносимый урон. Представлен классом TBullet, наследованного от класса TCreature.

Граната – имеет скорость. Представлен классом TGrenade, наследованного от класса TCreature.

Бонус предмет - объект, который активируется, если подойти у нему. В игре присутствует 4 типов бонусов: дополнительное здоровье, дополнительная граната, увеличение скорости, улучшение оружия. Представлен классом TThing, наследованного от класса TCreature.

Диаграмма классов

Подробное руководство пользователя - student2.ru

TTotal– класс представления всей структуры игра.

TMap – класс представления игровой карты.

TCreature– класс представления любого предмета находящегося на карте.

TPerson –класс представления игрока.

TMonster– класс представления вражеского персонажа

TArm– класс представления оружия.

TBullet– класс представления пули.

TGrenade– класс представления гранаты

TThing– класс представления бонусных предметов.

TPerk– класс представления коэффициента параметров игрока и персонажей

TTotal {

void Draw();– метод реализации игры .

void DrawInfa();– метод для рисования информации.

void DrawONForm();– метод для рисования фона на форме.

void DrawPerson();– метод для рисования игрока на фоне.

void DrawBullet();– метод для рисования пули на фоне.

void DrawMonster();– метод для рисования вражеских персонажей на фоне.

void DrawGrenade();– метод рисование гранат на фоне.

void DrawThing();– метод рисования бонусных предметов на фоне

float DetermineAngular(float XPos, float YPos); – подсчет угла поворота персонажа по курсору.

void ClashBullet();– метод для подсчета столкновение пули с игроком и монстрами.

void ClashTheng();– метод для подсчета сбора бонусных предметов.

void MotionMonster();–метод для реализации движения врагов.

void MotionBullet();– метод для реализации полета и столкновения со стеной.

void MotionGrenade();– метод для реализации полета гранаты.

void BOOMGrenade();– метод взрыва гранаты.

void AddBullet(int damage, int Speed, float x1, float y1, float angle, bool shot); – метод добавления пули.

void AddGrenade(int Speed, float angle, float x0, float y0, float x1, float y1); – метод добавления гранаты.

void PosCursor(int X,int Y); – метод получения нахождения курсора.

void RotateDC(HANDLE dc,float angle); – метод поворота изображения

void motion();– метод движения

void AddMonster(int col); – метод добавления врага.

bool ClashWallX(float X, float Y, int len, float angle, float speed); – метод подсчета разрешения перемещения по ось Оу.

bool ClashWallY(float X, float Y, int len, float angle, float speed); – метод подсчета разрешения перемещения по оси Ох.

void RandThing(float x ,float y); – метод вычисления случайного появления бонусного объекта.

void IncTime();– метод увеличения таймера.

void the_end(bool finish, int EX);–метод завершения игры

}

Руководство пользователя

Системные требования

Операционная система: Microsoft Windows XP, Vista, 7;

Жесткий диск: 20 мб свободного места;

Оперативная память: 128 мб;

Клавиатура, мышь;

Подробное руководство пользователя

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

Сразу после запуска игры, пользователь попадает в главное меню, представленное 2 пунктами:

1. Новая игра – Запускает новую игру

2. Выход – Закрывает игру

Подробное руководство пользователя - student2.ru

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

После выбора Новая игра игрок попадает на игровое поле.

Подробное руководство пользователя - student2.ru

Вверху находиться информационное меню.

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

Движение игровым персонажем управляется клавишами W A S D. Мышью указывается, куда направлен игрок.

При нажатии на кнопку курсора мыши персонаж стреляет под углом собственного направления.

Бросок гранаты осуществляется на клавишу G, а точка падения гранаты указывает курсор мыши.

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

Подробное руководство пользователя - student2.ru

Бонусы действуют постоянно.

Подробное руководство пользователя - student2.ru – Добавляет 10 здоровья. Если у игрового персонажа 100 здоровья тогда предмет не подбирается

Подробное руководство пользователя - student2.ru . – Добавляет одну гранату игровому персонажу.

Подробное руководство пользователя - student2.ru – Увеличивает в 1.1 раз скорость перемещения игрового персонажа.

Подробное руководство пользователя - student2.ru – Увеличивает максимальное количество патрон в обойме на один патрон. Увеличивает скорострельность.

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

Игра завершается выигрышам если наберешь опыта больше или равным 10 тысячам. Подробное руководство пользователя - student2.ru

Игра заканчивается, когда игрок теряет все жизни.

Подробное руководство пользователя - student2.ru

Заключение

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

Я получила достаточный опыт в разработке игр, научилась применять знания, полученные в ходе изучения курса ООП.

Возможные применения данного курсового проекта: как и любая игра, он создан для приятного время препровождения.

На данном примере мы видим преимущества объектно-ориентированного программирования.

Литература

1. Бондарев В.М. Программирование на С++.2005

2. Степанов А., Ли М. Руководство по стандартной библиотеке шаблонов (STL). 1999

3. Сайт http://www.cyberforum.ru

4. Сайт Wikipedia.org

5. Сайт http://bcb-games.narod.ru/index.htm

Приложение

Листинг программы

сlass TTotal

{

private:

int x,y;

bool Is_X_Move, Is_Y_Move;

float angleMonster;

int offset_x, offset_y;

float _XFG, _YFG;

int cube;

public:

Graphics::TBitmap *back;

Graphics::TBitmap *infa;

Graphics::TBitmap *infaElement;

Graphics::TBitmap *cursor;

TMap *map;

TPerson *person;

TArm *arm;

vector<TMonster*> monster;

vector<TBullet*> bullet;

TThing *thing;

TPerk *perk;

TGrenade* Grenade;

float XCursor, YCursor;

bool IsRight, IsLeft, IsUp, IsDown;// Доступ движения по форме

TTotal(int x, int y);

void Draw();

void DrawInfa();

void DrawONForm();

void DrawPerson();

void DrawBullet();

void DrawMonster();

void DrawGrenade();

void DrawThing();

float DetermineAngular(float XPos, float YPos);

void ClashBullet();

void ClashTheng();

void MotionMonster();

void MotionBullet();

void MotionGrenade();

void BOOMGrenade();

void AddBullet(int damage, int Speed, float x1, float y1, float angle, bool shot);

void AddGrenade(int Speed, float angle, float x0, float y0, float x1, float y1);

void PosCursor(int X,int Y);

void RotateDC(HANDLE dc,float angle);

void motion();

void AddMonster(int col);

bool ClashWallX(float X, float Y, int len, float angle, float speed);

bool ClashWallY(float X, float Y, int len, float angle, float speed);

void RandThing(float x ,float y);

void IncTime();

void the_end(bool finish, int EX);

};

struct Respaun

{

int _X, _Y;

};

//---------------------------------------------------------------------------

class TMap

{

public:

int MonsteRespaun;

TStringList *file;

vector<Respaun> respaun;

Graphics::TBitmap *Textur;

Graphics::TBitmap *BG;

TMap(int cube);

};

class TCreature

{

public:

float _Speed;

Graphics :: TBitmap *_Picture;

float _Angle;

float _XPos, _YPos;

float _XCenter, _YCenter;

int len;

TCreature();

TCreature(float Speed, float Angle, float XPos, float YPos,

float XCenter, float YCenter, String str);

};

class TPerson: public TCreature

{

public:

unsigned int _MaxHP;

int _HP;

unsigned int _AP;

unsigned int _EX;

unsigned int Grenade;

float _Damage;

TArm *arm;

TPerk *perk;

TPerson(unsigned int MaxHP, unsigned int AP, float Speed,

float Angle, float XPos, float YPos, float XCenter, float YCenter, String str);

unsigned int HP();

void AddHP(int hp);

void AddGrenade();

void AddSpeed();

void AddSpeedArm();

};

class TMonster: public TCreature

{

public:

unsigned int _MaxHP;

unsigned int _HP;

TArm *arm;

TPerk *perk;

bool IsArm;

unsigned int _Damage;

TMonster();

TMonster(unsigned int MaxHP, unsigned int Damage, int time,

float Speed, float Angle, float XPos, float YPos,

float XCenter, float YCenter, String str);

void Update(unsigned int MaxHP, int time, unsigned int Speed, float Angle, unsigned int Damage,

float XPos, float YPos, String str);

void MotionX();

void MotionY();

void AddArm(bool IsArm);

float DetermineAngular(float XGoal, float YGoal);

};

class TArm

{

public:

unsigned int interpal_recharge;

unsigned int interpal_shot;

unsigned int max_patron;

unsigned int coll_patron;

unsigned int time_patron;

bool shot();

void InterpalShot();

TArm(int interpal_recharge);

TArm(int patron, int interpal_recharge, int interpal_shot);

void Update(int interpal_recharge);

void IncArm();

};

class TBullet : public TCreature

{

public:

bool _Include;

unsigned int _Damage;

TBullet();

TBullet(unsigned int Speed, float Angle, unsigned int Damage, float XPos, float YPos,

float XCenter, float YCenter, String str, bool existence);

void Update(unsigned int Speed, float Angle, unsigned int Damage,

float XPos, float YPos, bool existence);

void Motion(TStringList *file, int cube, float speed);

};

class TGrenade: public TCreature

{

public:

float _XF, _YF;

int include;

void Update(unsigned int Speed, float Angle, float XPos, float YPos, float _XF, float _YF);

void Motion();

};

struct Thing

{

Graphics::TBitmap *picha;

float _XPos, _YPos;

int time;

};

class TThing

{

public:

vector<Thing*> HP;

vector<Thing*> Grenade;

vector<Thing*> Speed;

vector<Thing*> SpeedArm;

TThing();

void AddHP(int x, int y);

void AddGrenade(int x, int y);

void AddSpeed(int x, int y);

void AddSpeedArm(int x, int y);

};

class TPerk

{

public:

float HP;

float Speed;

float Damag;

float time_patron;

float Bullet_Speed;

TPerk();

void Increase();

void Add(TPerk* perk);

};

TTotal *total;

bool shoot = false;

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)

{

Screen->Cursors[1] = LoadCursorFromFile("date\\cursor.cur");

Form1->Cursor = TCursor(1);

total = new TTotal(Form1->ClientWidth, Form1->ClientHeight);

Timer1->Enabled = false;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{

total->IncTime();

total->Draw();

total->person->arm->InterpalShot();

if (shoot == true)

total->AddBullet(total->person->_Damage*total->person->perk->Damag, 10,total->person->_XPos, total->person->_YPos, total->person->_Angle, total->person->arm->shot());

if ((total->person->HP() <= 0))

{

Button2->Visible = true;

Button3->Visible = true;

Timer1->Enabled = false;

total->the_end(false, total->person->_EX);

}

if ((total->person->_EX >= 10000))

{

Button2->Visible = true;

Button3->Visible = true;

Timer1->Enabled = false;

total->the_end(true, total->person->_EX);

}

if (total->person->HP() > total->person->_MaxHP)

total->person->_HP = total->person->_MaxHP;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,

int X, int Y)

{

total->PosCursor(X,Y);

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,

TShiftState Shift)

{

if (Key==87) { total->IsUp=True; total->IsDown=False; }

if (Key==83) { total->IsDown=True; total->IsUp=False; }

if (Key==68) { total->IsRight=True; total->IsLeft=False; }

if (Key==65) { total->IsLeft=True; total->IsRight=False;}

if (Key==71)

{ total->AddGrenade(10, total->person->_Angle, total->person->_XPos, total->person->_YPos, total->XCursor, total->YCursor);}

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key,

TShiftState Shift)

{

if (Key == 87) total->IsUp=False;

if (Key == 83) total->IsDown=False;

if (Key == 68) total->IsRight=False;

if (Key == 65) total->IsLeft=False;

if (Key == 27)

{

if (Timer1->Enabled == true)

{

//Form1->Canvas->Draw(0,0,new Graphics::TBitmap());

Button1->Visible = true;

Button2->Visible = true;

Button3->Visible = true;

Timer1->Enabled = false;

}

else

{

Button1->Visible = false;

Button2->Visible = false;

Button3->Visible = false;

Timer1->Enabled = true;

}

}

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Timer2Timer(TObject *Sender)

{

Button1->Visible = false;

Button2->Visible = true;

Button3->Visible = true;

Button1->Left = Form1->ClientWidth/2 - Button1->Width/2;

Button1->Top = Form1->ClientHeight/2 - Button1->Height*3/2;

Button2->Left = Form1->ClientWidth/2 - Button2->Width/2;

Button2->Top = Form1->ClientHeight/2 - Button2->Height/2;

Button3->Left = Form1->ClientWidth/2 - Button3->Width/2;

Button3->Top = Form1->ClientHeight/2 + Button3->Height/2;

Timer2->Enabled = false;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y)

{

shoot=False;

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y)

{

shoot=true;

}

void TTotal :: DrawPerson()

{

RotateDC(back->Canvas->Handle,person->_Angle);

SetViewportOrgEx(back->Canvas->Handle, person->_XPos, person->_YPos, NULL);//Смещаем нашу точку

back->Canvas->Draw(person->_XCenter, person->_YCenter, person->_Picture);

SetViewportOrgEx(back->Canvas->Handle, 0, 0, NULL);//Смещаем нашу точку назад

RotateDC(back->Canvas->Handle, 0);

}

void TTotal :: RotateDC(HANDLE dc,float angle)

{

XFORM xform;

angle = angle *M_PI/ 180.0;

xform.eDx = 0.0f;

xform.eDy = 0.0f;

xform.eM11 = cos(angle);

xform.eM12 = sin(angle);

xform.eM21 = -sin(angle);

xform.eM22 = cos(angle);

SetGraphicsMode(dc, GM_ADVANCED);

SetWorldTransform(dc, &xform);

}

void TTotal :: motion()

{

if((IsLeft == True)&&(IsUp == True))

{

if (ClashWallX(person->_XPos, person->_YPos, person->len, -135, person->_Speed))

person->_XPos -= cos(45*M_PI/180.0)*person->_Speed;

if (ClashWallY(person->_XPos, person->_YPos, person->len, -135, person->_Speed))

person->_YPos -= sin(45*M_PI/180.0)*person->_Speed;

return;

}

if((IsRight == True)&&(IsUp == True))

{

if (ClashWallX(person->_XPos, person->_YPos, person->len, -45, person->_Speed))

person->_XPos += cos(45*M_PI/180.0)*person->_Speed;

if (ClashWallY(person->_XPos, person->_YPos, person->len, -45, person->_Speed))

person->_YPos -= sin(45*M_PI/180.0)*person->_Speed;

return;

}

if((IsLeft == True)&&(IsDown == True))

{

if (ClashWallX(person->_XPos, person->_YPos, person->len, 135, person->_Speed))

person->_XPos -= cos(45*M_PI/180.0)*person->_Speed;

if (ClashWallY(person->_XPos, person->_YPos, person->len, 135, person->_Speed))

person->_YPos += sin(45*M_PI/180.0)*person->_Speed;

return;

}

if((IsRight == True)&&(IsDown == True))

{

if (ClashWallX(person->_XPos, person->_YPos, person->len, 45, person->_Speed))

person->_XPos += cos(45*M_PI/180.0)*person->_Speed;

if (ClashWallY(person->_XPos, person->_YPos, person->len, 45, person->_Speed))

person->_YPos += sin(45*M_PI/180.0)*person->_Speed;

return;

}

if(IsUp == True)

if (ClashWallY(person->_XPos, person->_YPos, person->len, -90, person->_Speed))

{

person->_YPos -= person->_Speed;

return;

}

if(IsLeft == True)

if (ClashWallX(person->_XPos, person->_YPos, person->len, 180, person->_Speed))

{

person->_XPos -= person->_Speed;

return;

}

if(IsDown == True)

if (ClashWallY(person->_XPos, person->_YPos, person->len, 90, person->_Speed))

{

person->_YPos += person->_Speed;

return;

}

if(IsRight == True)

if (ClashWallX(person->_XPos, person->_YPos, person->len, 0, person->_Speed))

{

person->_XPos += person->_Speed;

return;

}

}

bool TTotal :: ClashWallY(float X, float Y, int len, float angle, float speed)

{

if(map->file->Strings[(int)(Y / cube)][(int)(X / cube)+1] == '1')

return false; // блок на каком находишься

if (angle >0)

{

if((hypot(cube - fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)+2] == '1'))

return false; // блок справа и в низу

if((hypot(cube - fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)] == '1'))

return false; // блок слева и в низу

if((fmod(Y, cube)> cube - (len + speed))

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)+1] == '1'))

return false; // блок внизу

}

if (angle <0)

{

if((hypot(fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)+2] == '1'))

return false; // блок справа и вверху

if((hypot(fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)] == '1'))

return false; // блок слева и в верху

if((fmod(Y, cube)< len + speed)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)+1] == '1'))

return false; // блок вверху

}

if ((angle == 0)||(angle == 180))

{

if((hypot(cube - fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)+2] == '1'))

return false; // блок справа и в низу

if((hypot(cube - fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)] == '1'))

return false; // блок слева и в низу

if((fmod(Y, cube)> cube - (len + speed))

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)+1] == '1'))

return false; // блок внизу

if((hypot(fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)+2] == '1'))

return false; // блок справа и вверху

if((hypot(fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)] == '1'))

return false; // блок слева и в верху

if((fmod(Y, cube)< len + speed)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)+1] == '1'))

return false; // блок вверху

}

return true;

}

bool TTotal :: ClashWallX(float X, float Y, int len, float angle, float speed)

{

if(map->file->Strings[(int)(Y / cube)][(int)(X / cube)+1] == '1')

return false; // блок на каком находишься

if (abs(angle)>90)

{

if((hypot(cube - fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)] == '1'))

return false; // блок слева и в низу

if((hypot(fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)] == '1'))

return false; // блок слева и в верху

if((fmod(X, cube)< len + speed)

&&(map->file->Strings[(int)(Y / cube)][(int)(X / cube)] == '1'))

return false; // блок слева

}

if (abs(angle)<90)

{

if((hypot(fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)+2] == '1'))

return false; // блок справа и вверху

if((hypot(cube - fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)+2] == '1'))

return false; // блок справа и в низу

if((fmod(X, cube)> cube - (len + speed))

&&(map->file->Strings[(int)(Y / cube)][(int)(X / cube)+2] == '1'))

return false; // блок справа

}

if((angle == -90)||(angle == 90))

{

if((hypot(fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)+2] == '1'))

return false; // блок справа и вверху

if((hypot(cube - fmod(Y, cube),cube - fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)+2] == '1'))

return false; // блок справа и в низу

if((hypot(cube - fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)+1][(int)(X / cube)] == '1'))

return false; // блок слева и в низу

if((hypot(fmod(Y, cube),fmod(X, cube))< len)

&&(map->file->Strings[(int)(Y / cube)-1][(int)(X / cube)] == '1'))

return false; // блок слева и в верху

if((fmod(X, cube)> cube - (len + speed))

&&(map->file->Strings[(int)(Y / cube)][(int)(X / cube)+2] == '1'))

return false; // блок справа

if((fmod(X, cube)< len + speed)

&&(map->file->Strings[(int)(Y / cube)][(int)(X / cube)] == '1'))

return false; // блок слева

}

return true;

}

Наши рекомендации