Читайте также:
|
|
// ВКЛЮЧАЕМЫЕ ФАЙЛЫ ////////////////////////////////////////
#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
Итог
В этой главе мы затронули много тем, относящихся к серьезной работе с растровой графикой и специальными визуальными эффектами, но, самое главное, мы впервые в этой книге начали разговор о том, как сделать так, чтобы игрок получил от вашей игры удовольствие. Я думаю, многие программисты уже забыли, что это такое, променяв его на мегабайты оцифрованного звука и графики.
Поэтому не будем забывать об удовольствии!
Дата добавления: 2015-07-12; просмотров: 97 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Листинг 7.10. Программа, масштабирующая текстуры стен (SCALE.C). | | | ВЫСОКОСКОРОСТНЫЕ ТРЕХМЕРНЫЕ СПРАЙТЫ |