Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Листинг 7.7. Демонстрация «animotion» (STICK.С).






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

#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 VEL_CONST -1 // флаг постоянной скорости перемещения

// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ///////////////////////////////////

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

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

sprite object;

pcx_picture stick_cells, street_cells;

// таблица выбора содержит величины перемещения для каждого

// мультипликационного кадра, чтобы движение было более реалистичным

int object_vel = {17, 0, 6, 2, 3, 0, 17, 0, 6, 2, 3, 0};

// функции ////////////////////////////////

void Timer (int clicks)

{

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

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

unsigned int now;

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

now = *clock;

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

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

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

// конец Timer

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

void main(void) {

int index, done=0,

vel_state=VEL_CONST;

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

Set_Mode(VGA256);

// установка размера для системы отображения спрайта

sprite_width = 32;

sprite_height =64;

// инициализация файла PCX, который содержит изображение улицы PCX_Init((pcx_picture_ptr)& street_cells);

// загрузка файла PCX, который содержит изображение улицы

PCX__Load(" street.pcx", (pcx_picture_ptr)& street_cells, 1};

PCX_Show_Buffer((pcx_picture_ptr)& street_cells);

// используем буфер PCX как дублирующий

double_buffer = street_cells.buffer;

Sprite_Init((sprite_ptr)& object, 0, 0, 0, 0, 0, 0);

// инициализация файла PCX, который содержит кадры спрайта PCX_Init((pcx_picture_ptr)& stick_cells);

// загрузка файла PCX, который содержит кадры спрайта

PCX_Load(" stickman.pcx", (pcx_picture_ptr) & stick_cells, 1);

// выбираем 6 кадров движения

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells,

(sprite_ptr)& object, 0, 0, 0);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells,

(sprite_ptr)& object, 1, 1, 0);

PCX_Grap_Bitmap((pcx_picture_ptr) & stick_cells,

(Sprite_ptr)& object, 2, 2, 0);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells,

(sprite_ptr)& object, 3, 3, 0);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick cells,

(sprite_ptr)& object/4, 4, 0);

PCX_Grap_Bitmap((pcx_picture_ptr) & stick_cells, (sprite_ptr) & object, 5, 5, 0);

PCX_Grap_Bitniap ((pcx_picture_ptr) & stick_cells, (sprite_ptr)& object, 6, 0, 1);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells,

(sprite_ptr)& object, 7, 1, 1);

PCX_Grap_Bitmap ((pcx_picture_ptr) & stick_cells,

(sprite_ptr)& object, 8, 2, 1);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells,

(sprite_ptr) & object, 9, 3, 1);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells, (sprite_ptr)& object, 10, 4, 1);

PCX_Grap_Bitmap((pcx_picture_ptr)& stick_cells,

(sprite_ptr)& object, 11, 5, 1);

// файл stickman.pcx больше не нужен

PCX_Delete((pcx_picture_ptr)& stick_cells);

// настраиваем параметры человечка

object.x = 10;

object.у = 120;

object.curr_frame = 0;

// сохраняем фон

Behind_Sprite((sprite_ptr)& object);

 

// главный цикл

while(! done)

{

// стираем спрайт

Erase_Sprite((sprite_ptr)& object);

// увеличиваем номер кадра на единицу

if (++object.curr_frame > 11) object.curr_fcame = 0;

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

// или таблицу выбора

if (vel_state==VEL_CONST)

{

object.x+=4;

}

// конец if

else

/ {

// используем номер кадра для определения величины

// перемещения по таблице выбора

object.x += object_vel[object.curr_frame];

} // конец else

}

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

Персональные компьютеры могут иметь специальное аппаратное обеспечение, облегчающее прокрутку. Некоторые карты VGA имеют до мегабайта оперативной памяти, что дает возможность рисовать мир вашей игры прямо в видеобуфере, поручая производить прокрутку самой видеокарте. Однако существует две проблемы:

Во-первых, если мы будем полагаться на определенную аппаратуру, наши программы станут аппаратнозависимыми и не будут работать на картах VGA с меньшей памятью;

Во-вторых, прокрутка в режиме 13h существенно сложнее, чем прокрутка в режимах EGA, так как видеопамять в этом случае не разбита на несколько плоскостей. Эта означает, что мы не можем использовать в данном режиме аппаратную прокрутку, таким же образом как в режимах EGA.

Таким образом, мы не будем использовать для прокрутки аппаратное обеспечение персонального компьютера. Мы будем это делать программно, применяя блочное копирование из памяти в видеобуфер. Используя этот метод, мы будем абсолютно независимыми от аппаратного обеспечения, следовательно наши программы будут более гибкими.

Прокрутку целого экрана или его части можно осуществлять двумя путями:

§ Можно нарисовать все пространство игры в обширном буфере памяти. Однако шесть предварительно нарисованных экранов займут 6х64000 байтов, то есть 384К. Это довольно большие потери памяти. В любом случае, как мы только что говорили, мы должны будем сделать воображаемое окно, перемещающееся по этому буферу и отображать все, что в него попадает, на экран; |

§ Второй метод более медленный, но требует меньше памяти. Он основан на генерации изображения «на лету». Под выражением " на лету" я подразумеваю, что мир будет представляться с помощью иначе структурированных данных - например, в виде двухмерной матрицы, где каждая ячейка 8х8 пикселей ставится в соответствие растровому изображению части игрового пространства. Такой ячеистый мир в шесть экранов будет занимать всего 6000 байт. При перемещении окна по ячейкам матрицы, на экране будут воспроизводиться соответствующие растровые изображения.

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

Чтобы показать вам пример скроллинга, я написал программу, которая создает игровое пространство размером 640х100 пикселей. Я двигаю окно по изображению мира игры и передаю его содержимое в середину экрана. В этой игре мир состоит из звезд и гористого горизонта. (Этот пейзаж немного напоминает игру Defender.) Перемещая с помощью клавиатуры окно просмотра вправо и влево, вы можете прокрутить весь пейзаж. Листинг 7.8 содержит текст этой программы, которая называется DEFEND.С.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.