ООП в написании игр. Часть 1

ООП в написании игр. Часть 1

автор: Dimouse

Речь пойдет о том как полезны классы вообще и в частности в играх. Конечно можно писать для каждого объекта свою функцию и копи-пастить с небольшими исправлениями, но во-первых, это долго, во-вторых, размер кода разрастается до неимоверных размеров, в-третьих, неудобно, особенно когда нужно исправить ошибки, ну и наконец, мы же не в каменном веке! Теперь программировать на C это значит программировать на C++! Как-то недавно пришлось немного по-программить на Turbo C 2.01, и как же это не удобно! Там даже нет комментариев /* ... */, приходится все двумя слешами комментировать. Отвыкли в общем уже, что еще раз подтверждает пословицу "к хорошему быстро привыкаешь". Так вот я хотел бы поговорить немного про классы, надеюсь будет полезно начинающим, да и тем кто программит на других языках программирования хотелось бы показать, насколько удобен и понятен С. Я буду показывать это на примере пошаговой РПГ игры, которую делал 5 лет назад, часть кода игры тоже будет приводиться. Итак сначала нам нужно сделать карту. С чего начать? Конечно с создания разных видов клеточек, трава, камень, деревья, враги, персонажи, дома, мебель в домах, сундуки, в общем все что может нам понадобиться в игре. Конечно самое трудное, это нарисовать все это, но к счастью у меня остался файлик от тех стародавних времен со всеми этими объектами и заново их рисовать мне не пришлось. А вот вам придется:)) Итак создаем класс объектов:

class object{
public:
char name[15];
int moveble;
int fire;
int num;
void decl();
load_ddd(BITMAP*,const char*);
draw(BITMAP*,BITMAP*,int,int,int);
};


name - это название объекта, movable - можно ли по нему ходить (например, по траве - можно, через стенку - нет. fire - у меня пока не использовалось, но теоретически оно означает, можно ли сжечь объект, например дерево можно, а каменную преграду - нет. num - номер объекта, самый главный параметр, как мы увидем дальше. Далее идут функции: decl() - декларация объекта. У меня она делается из файла discr.dat устроенного следующим образом:


&
None
0
0
0
1
&
Grass
1
1
1
1
&
Desert
1
1
1
1
&
Swamp
1
1
1
1
&
Snow
1
1
1
1
&
Field
1
1
1
1
&
Lava
1
1
1
1
&
Stone
0
1
1
1



Смотрим саму функцию decl():

void object::decl(){
fstream myfile;
myfile.open("discr.dat",ios::in);
char q;
int n=0;
for(;;){
myfile>>q;
if (myfile.eof()) break;
if (q=='&') n++;
if (n==num+1) break;
}
myfile>>name;
myfile>>moveble;
myfile>>fire;
//myfile>>mult;
//myfile>>read;
myfile>>q>>q>>q;
myfile.close();
}


Все просто, не так ли? Два последних числа для каждого объекта в discr.dat я уже и сам забыл зачем были нужны:) Теперь посмотрим функцию main(), как мы инициализируем объекты:


int i;
for(i=0;i<63;i++){
z[i].num=i;
z[i].decl();
z[i].load_ddd(sprites,"pic.dat");
}

Самые внимательные наверное еще раньше обратили внимание на функцию load_ddd, конечно же, ведь надо сами картинки этих объектов загрузить, не так ли? В принципе, то как это у меня делается для других пользы практической не представляет, поскольку грузит из собственного формата ddd, так что код я приводить не буду, скажу только что функция рисует объект в определенном квадрате на виртуальной странице, координаты квадрата определяются номером объекта по следующей формуле:
int x=(object::num)%20,y=(object::num)/20;

Потом еще каждый надо умножить на 20 (квадраты 20 на 20 пикселей). В классе есть еще функция draw. Она тоже подходит только для моего частного случая, а точнее для библиотеки Аллегра. Но поскольку она очень короткая, то приведу ее:


object::draw(BITMAP* source,BITMAP* dest, int x, int y,int mode){
if(mode==0)blit(source,dest,20*((object::num)%20),20*((object::num)/20),x*20,y*20,20,20);
if(mode==1)masked_blit(source,dest,20*((object::num)%20),20*((object::num)/20),x*20,y*20,20,20);
}

Здесь в случае mode=0 рисуется поверх всего, при mode=1 накладывается на уже нарисованное (нужно например, чтобы можно было одновременно нарисовать поверхность и врага на одну клеточку).

Почему я сделал такую сложную инициализацию, а не написал одну фунцкию, которая просто загружает картинки из файла в виртуальную страницу? Ответ на этот вопрос оставляю вам в качестве домашнего задания, мои маленькие создатели игр:) А в следующий раз я расскажу о реальном C++, когда классы используются на всю катушку, на примере NPC, главного героя и врагов, которые все наследуются от одного класса hero.

Последнее изменение Sun, 24 Jun 2018 автором Dimouse


Назад в раздел Old-games Diskmag 5