Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 7.11. Трехмерный астероид (AFIELD.С).
// ВКЛЮЧАЕМЫЕ ФАЙЛЫ //////////////////////////////////////// #include < io.h> #include < conio.h> #include < stdio.h> #include < stdlib.h> #include < dos.h> #include < bios.h> #include < fcntl.h> #include < memory.h> #include < malloc.h> #include < math.h> #include < string.h> #include " graph0.h" // включаем нашу графическую библиотеку // ОПРЕДЕЛЕНИЯ///////////////////////////////////////////// #define NUM_STARS 30 // СТРУКТУРЫ /////////////////////////////////////////////// typedef struct star_typ { int x, y; // позиция звезды int vel; // скорость звезды по координате х int color; // цвет звезды } star, *star_ptr; // ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ /////////////////////////////////// star stars[NUM_STARS]; // звездное поле sprite object; pcx_picture ast_cells; // функции /////////////////////////////////////////// void Star_Field(void) { static int star_first=1; // Эта функция создает трехмерное звездное поле int index; // проверяем, следует ли нам создать звездное поле, //то есть первый ли раз вызвана функция if (star_first) { // обнуляем флаг первого вызова star_first=0; // инициализируем все звезды for (index=0; index< NUM STARS; index++) { // инициализируем для каждой звезды позицию, скорость и цвет stars[index].х = rand()%320; stars[index].у = rand()%180; // определяем плоскость звезды switch(rand()%3){ case 0: // плоскость 1 - самая далекая { // установка скорости и цвета stars[index].vel = 2; stars[index].color.= 8; } break; case 1: // плоскость 2 - среднее расстояние { stars[index].vel = 4; stars[index].color = 7; ) break; case 2: //плоскость 3 - самая близкая { stars[index].vel = 6; stars[index].color = 15; } break; } // конец оператора switch } // конец цикла //конец оператора if else { // это не первый вызов, поэтому делаем рутинную работу - // стираем, двигаем, рисуем for (index=0; index< NUM_STARS; index++) { if ((stars[index].x+=stars[index].vel) > =320) stars[index].x = 0; // рисуем Plot_Pixel_Fast_D(stars[index].x, stars[index].y, stars[index].color); } // конец цикла } // конец оператора else } // конец Star_Field //////////////////////////////////////////////////////////// void Scale_Sprite(sprite_ptr sprite, float scale) { // эта функция масштабирует спрайт, рассчитывая число дублирования // исходных пикселей, необходимое для получения требуемого размера char far *work_sprite; int work_offset=0, offset, x, у; unsigned char data; float y_scale_index, x_scale_step, y_scale_step, x_scale_index; // берем первый пиксель исходного изображения y_scale_index = 0; // рассчитываем дробный шаг y_scale_step = sprite_height/scale; x_scale_step = sprite_width /scale; // для простоты даем указателю на спрайт новое имя work_sprite = sprite-> frames[sprite-> curr_frame]; // расчет смещения спрайта в видеобуфере offset = (sprite-> y < < 8) + (sprite-> y < < 6) + sprite-> x; // построчно масштабируем спрайт for (у=0; y< (int) (scale); у++) { // копируем следующую строчку в буфер экрана x_scale_index=0; for (x=0; x< (int)scale; x++) { // проверка на прозрачность пикселя //(то есть равен ли он 0), если нет - прорисовываем пиксель if ((data=work_sprite[work_offset+(int)x_scale_index])) double_buffer[offset+x] = data; x_scale_index+=(x_scale_step); } // конец цикла по X //используя дробный шаг приращения определяем // следующий пиксель исходного изображения у_scale_index+=y_scale_step; // переходим к следующей строке видеобуфера //и растрового буфера спрайта offset += SCREEN_WIDTH; work_offset = sprite_width*(int)(y_scale_index); } // конец цикла по Y } // конец Scale Sprite //////////////////////////////////////////////////////////// void Clear_Double_Buffer(void) { // эта функция очищает дублирующий буфер // несколько грубо, зато работает _fmemset(double_buffer, 0, SCREEN_WIDTH * SCREEN_HEIGHT + 1); } // конец Clear_Double_Buffer // ОСНОВНАЯ ПРОГРАММА /////////////////////////////////////// void main(void) { int index, done=0, dx=5, dy=4, ds=4; float scale=5; // установка видеорежима 320х200х256 Set_Mode(VGA256); // установка размера спрайта sprite_width = sprite_height = 47; // инициализация файла PCX, который содержит // мультипликационные кадры PCX_Init((pcx_picture_ptr)& ast_cells); // загрузка файла PCX, который содержит мультипликационные кадры PCX_Load(" asteroid.рсх", (pcx_picture_ptr)& ast_cells, 1); // резервируем память под дублирующий буфер Init_Double_Buffer(); Sprite_Init((sprite_ptr)& object, 0, 0, 0, 0, 0, 0); // загрузка кадров вращающегося астероида PCX_Grap_Bitmap((pcx_picture_ptr)& ast_cells, (sprite_ptr)& object, 0, 0, 0); PCX_Grap_Bitmap ((pcx_picture_ptr) & ast_cells, (sprite_ptr)& object, 1, 1, 0}; PCX_Grap_Bitmap((pcx_picture_ptr)& ast_cells, (sprite_ptr)& object, 2, 2, 0); PCX_Grap_Bitmap((pcx_picture_ptr)& ast_cells, (sprite_ptr)& object, 3, 3, 0); PCX_Grap_Bitmap ((pcx_picture_ptr) & ast_cells, (sprite_ptr)& object, 4, 4, 0); PCX_Grap_Bitmap((pcx_picture_ptr)& ast_cells, (sprite_ptr)& object, 5, 5, 0); PCX_Grap_Bitmap((pcx_picture_ptr)& ast_cells, (sprite_ptr)& object, 6, 0, 1); PCX_Grap_Bitmap({pcx_picture_ptr)& ast_cells, (sprite_ptr)& object, 1, 1, 1); // позиционирование объекта в центре экрана object.curr_frame =0; object.x = 160-(sprite width> > 1); object.у = 100-(sprite_height> > 1); // очистка дублирующего буфера Clear_Double_Buffer(); // вывол масштабированного спрайта Scale_Sprite((sprite_ptr)& object, scale); Show_Double_Buffer(double_buffer); // главный цикл while (! kbhit()) { // масштабируем астероид scale+=ds; // не слишком ли велик или мал астероид? if (scale> 100 |1 scale < 5) { ds=-ds; scale+=ds; } // конец if // перемещаем астероид object.x+=dx; object.y+=dy; // коснулся ли астероид края экрана? if ((object.x + scale) > 310 || object.x < 10) { dx=-dx; object.x+=dx; } // конец if if ((object.у + scale) > 190 || object.у < 10) { dy=-dy; object.y+=dy; } // конец if // поворот астероида на 45 градусов if (++object.curr_frame==8) object.curr_frame=0; // очистка дублирующего буфера Clear_Double_Buffer(); // прорисовка звезд Star_Field(); // масштабируем спрайт и выводим его в дублирующий буфер Scale_Sprite((sprite_ptr)& object, scale); // выводим дублирующий буфер на экран Show_Double_Buffer (double_buffer); } // конец оператора while // удаляем файл PCX PCX_Delete ((pcx_picture_ptr) & ast_cells); // возврат в текстовый режим Set_Mode (TEXT_MODE); } // конец функции main Итог В этой главе мы затронули много тем, относящихся к серьезной работе с растровой графикой и специальными визуальными эффектами, но, самое главное, мы впервые в этой книге начали разговор о том, как сделать так, чтобы игрок получил от вашей игры удовольствие. Я думаю, многие программисты уже забыли, что это такое, променяв его на мегабайты оцифрованного звука и графики. Поэтому не будем забывать об удовольствии!
|