Программирование игр для Windows. Советы профессионала

Состояния бытия


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

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

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

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

Для наглядности, используя наш метод имитации игровых объектов, я создал целый муравейник. Листинг 11.4 показывает эту программу.

Листинг 11.4. Муравейник (ANTS.С).

// ВКЛЮЧАЕМЫЕ ФАЙЛЫ

/////////////////////////////////////////

#include <dos.h>




#include <bios.h>

#include <stdio.h>



#include <math.h>

#include <conio.h>

#include <graph.h>

// определения /////////////////////////////////////////////

#define ANT_NORTH 0

#define ANT_EAST 1 #define ANT_SOUTH 2

#define ANT_WEST 3 #define NUM_ANTS 50

// структуры ////////////////////////////

// структура муравья

typedef struct ant_typ

{

int x,y;              // позиция муравья

int state;            // состояние муравья

unsigned char color; // цвет муравья: красный или зеленый

unsigned back_color; // фон

под муравьем

} ant, *ant_ptr;

// ГЛОБАЛЬНЫЕ

ПЕРЕМЕННЫЕ

///////////////////////////////////

unsigned char far *video_buffer: = (char far *)0xA0000000L;

// указатель

на видеобуфер

unsigned int far *clock = (unsigned int far *)0x0000046C;

// указатель на внутренний таймер

// наши маленькие муравьи

ant ants[NUM_ANTS];      

// ФУНКЦИИ /////////////////////////////////////////////////

void Timer(int clicks)

{

// эта функция использует внутренний таймер с частотой 18.2 "тик"/с.

//32-битовое значение этого таймера находится по адресу 0000:046Ch

unsigned int now;

//получаем текущее время

now = *clock;

//Ожидаем до истечения указанного периода времени.

//Заметьте; что каждый,"тик" имеет длительность примерно в 55мс.

while(abs(*clock - now) < clicks){}

) // конец Timer

////////////////////////////////////////////////////////////

void Plot_Pixel_Fast(int x,int y,unsigned char color)

{

// эта функция рисует точку заданного цвета несколько быстрее чем

// обычно, за счет применения операции сдвига вместо операции

// умножения

// используется тот факт, что 320*у = 256*у + б4*у = у<<8 + у<<6

video_buffer[ ( (у<<8) + (у<<6) ) + х] = color;

} // конец Plot_Pixel_Fast ////////////////////////////////////////////////////////////

unsigned char Read_Pixel_Fast(int x,int у)

{

// читаем значение пикселя из видеобуфера

return (video_buffer [((у<<8) + (у<<6) ) + х]);



} // конец Read_Pixel_Fast

///////////////////////////////////////

void Draw_Ground(void)

{

int index;

// эта функция рисует разбросанные по экрану серые камешки

for (index=0; index<200; index++)

{

Plot_Pixel_Fast(rand()%320,rand()%200, 7 + rand()%2);

} // конец

цикла

} // конец Draw_Ground ///////////////////////////////////////////////

void Initialize_Ants(void)

{

int index;

for (index=0; index<NUM_ANTS; index++)

{

// выбираем случайным образом начальную позицию, цвет и состояние

// для каждого муравья, а также определяем его фон

ants[index].х     = rand(}%320;

ants[index].у     = rand()%200;

ants[index].state = rand()%4;

if (rand()%2==1)

ants[index].color = 10;

else

ants[index].color = 12;

// сканирование фона

ants[index].back_color = Read_Pixel_Fast(ants[index].х, ants[index].y);

} // конец цикла

} // конец Initialize_Ants ////////////////////////////////////////////////////////////

void Erase_Ants(void)

{

int index;

// в цикле обрабатывается массив муравьев, все муравьи замещаются

// точками, цвета соответствующего фона

for (index=0; index<NUM_ANTS; index++)

{

Plot_Pixel_Fast(ants[index].х, ants[index].y,

ants[index].back_color) ;

} // конец цикла

} // конец Erase Ants

////////////////////////////////////////////////////////////

void Move_Ants(void)

{

int index,rock;

//в цикле обрабатывается массив муравьев, каждый муравей перемещается

//в соответствии со своим состоянием

for (index=0; index<NUM ANTS; index++)

{

// каково состояние муравья?

switch(ants[index].state)

{

сазе ANT_NORTH:

{

ants[index].у—;

} break;

case ANT_SOUTH:

{

ants[index].y++;

} break;

case ANT_WEST:

{

ants[index].x--;

} break;

case ANT_EAST:

{

ants[index].x++;

} break;

} // конец оператора switch

// проверка, не столкнулся ли муравей

// с границами экрана или с камнем

if (ants[index].x > 319) ants[index].x = 0;

else if (ants[index].x <0)

ants[index].x = 319;

if (ants[index].у > 200)

ants[index].у = 200;



else if (ants[index].у <0)

ants[index].у = 199;

// здесь проверяем, не столкнулся ли муравей с камнем

rock = Read_Pixel_Fast(ants[index].x, ants[index].у);

if (rock)

{

// изменение состояния

ants[index].state =rand()%4;  // выбор нового состояния

} // конец оператора if

} // конец цикла

} // конец Move_Ants

////////////////////////////////////////////////

void Behind_Ants(veid)

{ int index;

// в цикле обрабатывается массив муравьев,

// определяется цвет фона для каждого муравья

for (index=0; index<NUM_ANTS; index++)

{ // читается пиксель и его значение сохраняется

// для

дальнейшего использования

ants[index].back_color = Read_Pixel_Fast(ants[index].x, ants[index].y) ;

} // конец

цикла

} // конец Behind_Ants ////////////////////////////////////////////////////////////

void Draw_Ants(void)

{

int index;

// в цикле обрабатывается массив муравьев, рисуется каждый

// муравей соответствующим цветом

for (index=0;index<NUM_ANTS; index++)

{

Plot_Pixel_Fast(ants[index].x, ants[index].y, ants[index].color);

} // конец

цикла

} // конец Draw_Ants

// ОСНОВНАЯ ПРОГРАММА //////////////////////////////////////

void main

(void)

{

// установка видеорежима 320х200х256

_setvideomode(_MRES256COLOR);

_settextposition(2,0);

printf("Hit any key to exit.");

//построение игрового пространства

Draw_Ground() ;

/ создаем

муравьев

Initialize_Ants();

while(!kbhit())

{ // стираем всех муравьев

Erase_Ants

(};

// перемещаем всех муравьев

Move_Ants

();

// определяем фон под муравьями

Behind_Ants() ;

// рисуем всех муравьев

Draw_Ants

(),;

// немного подождем

Timer(2);

} // конец оператора while

// восстановление первоначального видеорежима

_setvideomode(_DEFAULTMODE);

} // конец функции main

Если вы запустите программу, то увидите кучу точек на экране. Красные и зеленые точки — это муравьи, а серые — это камни. Когда муравьи натыкаются на камни, они меняют направление движения. Эта программа показывает использование переменных состояния.Позже мы узнаем, как использовать переменные состояния для создания более сложных для вычисления структур, называемых состоянием машины.

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


Содержание раздела