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


Полезное:

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


Категории:

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






Листинг 7.10. Программа, масштабирующая текстуры стен (SCALE.C)





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

#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" // включаем нашу графическую библиотеку

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

sprite object;

pcx_picture text_cells;

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

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 (y=0; y<(int) (scale); у++)

{

// копируем следующую строчку в буфер экрана

х_scale_index=0;

for (х=0; x<(int)scale; х++)

{

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

// (то есть равен ли он 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);

} // конец внешнего цикла (по У)

} // end 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;

float scale=64;

 

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

Set_Mode(VGA256);

// установка размера спрайта

sprite_width = sprite_height = 64;

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

// мультииликационные кадры

PCX__Init ((pcx_picture_ptr)&text_cells);

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

PCX_Load("textures.pcx", (pcx_picture_ptr)&text_cells,1);

// PCX_Show_Buffer((pcx_picture_ptr)&text_cells);

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

// выборка четырех интересующих нас текстур

PCX_Grap_Bitmap((pcx_picture_ptr)&text_cells,

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

PCX_Grap_Bitmap((pcx_picture_ptr)&text_cells,

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

PCX_Grap_Bitmap((pcx_picture_ptr)&text cells,

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

PCX_Grap_Bitmap((pcx_picture_ptr)&text_cells,

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

// резервируем память под дублирующий буфер

Init_Double_Buffer();

// позиционируем объект в центре экрана

object.curr frame =0;

object.х = 160-(sprite_width>>1);

object.у = 100-(sprite height>>1);

// очищаем дублирующий буфер

Clear_Double_Buffer();

// воспроизводим масштабированную текстуру

Scale_Sprite((sprite_ptr)&object,scale);

Show_Double_Buffer(double buffer);

_settextposition(24,0);

Printf("Q - Quit, < > - Scale, Space - Toggle.");

// главный цикл while(!done)

{

// нажал ли игрок клавишу?

if (kbhit())

{

switch(getch()) {

case '.': // увеличиваем объект

{

if (scale<180) (scale+=4;

object.x-=2;

object.y-=2;

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

} break;

case ',': // уменьшаем объект

{

if (scale>4) {

scale-=4;

object.x+=2;

object.y+=2;

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

} break;

case ' ': // смена текстуры

{

// текстуры исчерпались?

if (++object.curr_frame==4)

object. curr_frame=0;

} break;

case 'q': // до свидания! {

done=1;

) break;

default:break;

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

// очистка дублирующего буфера

Clear_Double_Buffer();

// масштабирование спрайта и прорисовка его

//в дублирующем буфере

Scale_Sprite((sprite_ptr)&object,scale);

// вывод дублирующего буфера на экран

Show_Double_Buffer(double_buffer);

_settextpostion(24,0);

printf("Q - Quit,"< > - Scale, Space - Toggle.");

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

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

// удаление файла PCX

PCX_Delete((pcx_picture_ptr)&text_cells);

// возврат в текстовый режим

Set_Mode(TEXT_MODE);

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

Повороты объектов

Хотя мы и не собираемся вращать многочисленные растровые изображения, для полноты картины познакомимся с основными принципами этого процесса.

Вращение битовых объектов до сих пор еще не до конца исследованная область. Инженеры и программисты и по сей день пытаются найти наиболее эффективные алгоритмы для этой операции. Проблема заключается в том, что битовый образ - это конгломерат сотни, если не тысячи пикселей и чтобы повернуть образ, нам надо правильно произвести поворот каждой из этих точек, Обычно это связано с довольно сложными математическими преобразованиями, которые выполняются на персональном компьютере не очень-то быстро. Вы можете спросить: «А как же это сделал Крис Роберте в игре Wing Commander?» Очень просто: он заранее получил все возможные повороты всех космических кораблей с помощью программы моделирования, а потом просто занес их в гигантскую таблицу. Единственная операция, которая могла бывыполняться долго ~ масштабирование, тоже была произведена заранее, а результаты также занесены в таблицу. Я всегда действую подобным же образом и вам советую заранее создать все варианты поворотов ваших изображений, используя один из двух пакетов, либо Deluxe Paint фирмы Electronic Arts или, если вам нравится тратить деньги, 3D Studio фирмы AutoDesk. Затем поместите их в таблицу, и пусть ваша программа извлекает изображения из этой таблицы, используя угол поворота, как индекс. Отрицательная сторона этого метода - не очень рациональное использование памяти. Хранение 32 или 64 битных образов для всех возможных объектов отъедает существенный кусок памяти. Однако можно использовать частичные а не полные таблицы. Например, вы можете поместить в таблицу только кадры для одного квадранта, а для других симметричных квадрантов генерировать изображения уже во время игры. Так как поворот вокруг осей Х и Y делается очень просто — такой метод используется очень часто.

Чтобы показать пример поворота растрового изображения с помощью таблиц, я написал программу, которая использует нашу функцию масштабирования для файла PCX, содержащего несколько кадров с летящим астероидом. Эта программа, которую я назвал AFIELD.С, передвигает астероид по трехмерному звездному полю, масштабируя его по мере приближения или удаления оигрока. Листинг 7.11 содержит текст этой программы.

Date: 2015-09-18; view: 405; Нарушение авторских прав; Помощь в написании работы --> СЮДА...



mydocx.ru - 2015-2024 year. (0.006 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию