ООП в написании игр. Часть 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