Студопедия

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

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

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






Листинг 17.6. Демонстрационная программа мозаичного смещающегося слоя (TILES.C).






#include < stdio.h>

#include < stdlib.h>

#include < string.h>

#include < time.h>

#include < dos.h>

#include " paral.h"

#include " tiles.h"

char *MemBuf,

*BackGroundBmp,

*ForeGroundBnip,

*VideoRam;

PcxFile pcx;

int volatile KeyScan;

int frames=0,

PrevMode;

int background,

foreground, position;

char *tiles[NUM_TILES+l];

int tilemap[TILES_TOTAL];

void interrupt (*OldInt9)(void);

//

//

int ReadPcxFile(char *filename, PcxFile *pcx)

{

long i;

int mode=NORMAL, nbytes;

char abyte, *p;

FILE *f;

f=fopen(filename, " rb");

if(f==NULL)

return PCX_NOFILE;

fread(& pcx-> hdr, sizeof(PcxHeader), l, f);

pcx-> width=1+pcx-> hdr.xmax-pcx-> hdr.xmin;

pcx-> height=1+pcx-> hdr.ymax-pcx-> hdr.ymin;

pcx-> imagebytes= (unsigned int) (pcx-> width*pcx-> height);

if(pcx-> imagebytes > PCX_MAX_SIZE)

return PCX_TOOBIG;

pcx-> bitmap= (char*)malloc(pcx-> imagebytes);

if(pcx-> bitmap == NULL)

return PCX_NOMEM;

p=pcx-> bitmap;

for(i=0; i< pcx-> imagebytes; i++)

{

if(mode == NORMAL)

{

abyte=fgetc(f);

if((unsigned char)abyte > Oxbf)

{ nbytes=abyte & 0x3f;

abyte=fgetc(f);

if(-—nbytes > 0) mode=RLE;

}

}

else if(--nbytes ==0)

mode=NORMAL;

*p++=abyte;

}

fseek(f, -768L, SEEK_END);

fread(pcx-> pal, 768, 1, f);

p=pcx-> pal;

for(i=0; i< 768; i++) *p++=*p> > 2;

fclose(f);

return PCX_OK;

}

//

void _interrupt NewInt9(void) {

register char x;

KeyScan=inp(Ox60);

x=inp(0х61);

outp(0x61, (x|0x80));

outp(0x61, x);

outp(0х20, 0х20);

if(KeyScan == RIGHT__ARROW__REL ||

KeyScan == LEFT__ARROW_REL)

KeyScan=0;

}

//

void RestoreKeyboard(void) {

_dos_setvect(KEYBOARD, OldInt9);

}

//

void InitKeyboard(void)

{

Oldlnt9=_dos_getvect(KEYBOARD);

_dos_setvect(KEYBOARD, Newlnt9);

}

//

void SetAllRgbPalettefchar *pal)

{

struct SREGS s;

union REGS r;

segread(& s);

s.es=FP_SEG((void far*)pal);

r.x.dx=FP_OFF((void far*)pal);

r.x.ax=0xl012;

r.x.bx=0;

r.x.cx=256;

int86x(0xl0, & r, & r, & s);

}

//

void InitVideo()

{

union REGS r;

r.h.ah=0x0f;

int86(0xl0, & r, & r); PrevMode=r.h.al;

r.x.ax=0xl3;

int86(0xl0, & r, & r);

VideoRam=MK_FP(0xa000, 0);

}

//

void RestoreVideo()

{

union REGS r;

r.x.ax=PrevMode;

int86(0xl0, & r, & r);

}

//

int InitBitmaps()

{

int r;

background=foreground=l;

r=ReadPcxFile(" backgrnd.pcx", & pcx);

if(r! = PCX_OK) return FALSE;

BackGroundBnip=pcx.bitmap;

SetAllRgbPalette(pcx.pal);,

r=ReadPcxFile(" foregrnd.pcx", & pcx);

if(r! = PCX_OK) return FALSE;

ForeGroundBmp=pcx.bitmap;

MemBuf=malloc(MEMBLK);

if(MemBuf == NULL) return FALSE;

memset(MemBuf, 0, MEMBLK);

return TRUE;

) //

void FreeMem()

{

free(MemBuf);

free(BackGroundBmp);

free(ForeGroundBmp);

FreeTiles(};

}

//

void DrawLayers()

{ OpaqueBlt(BackGroundBmp, 0, 100, background);

TransparentBIt(ForeGroundBmp, 50, 100, foreground);

DrawTiles(position, 54);

}

//

void AnimLoop() {

while(KeyScan! = ESC_PRESSED)

{

switch(KeyScan)

{ case RIGHT_ARROW_PRESSED:

position+=4;

if(position > TOTAL_SCROLL) {

position=TOTAL_SCROLL;

break;

}

background-=1;

if(background < 1)

background+=VIEW_WIDTH;

foreground-=2; if(foreground < 1)

foreground+=VIEW_WIDTH;

break;

case LEFT_ARROW_PRESSED:

position-=4;

if(position < 0) {

position=0;

break;

}

background+=1;

if(background > VIEW_WIDTH-1) background-=VIEW_WIDTH;

foreground+=2;

if (foreground > VIEW_WIDTH-1) foreground-=VIEW_WIDTH;

break;

default:

break;

} DrawLayers();

memcpy(VideoRam, MemBuf, MEMBLK);

frames++;

} }

//

void Initialize()

{

position=0;

InitVideo(};

InitKeyboard();

if(! InitBitmaps())

{

Cleanup();

printf(" \nError loading bitmaps\n");

exit(l);

} ReadTileMap(" tilemap.dat");

ReadTiles();

}

// void Cleanup() {

RestoreVideo();

RestoreKeyboard();

FreeMem();

}

void ReadTiles(void)

{

PcxFile pcx;

char buf[80];

int i, result;

tiles[0]=NULL;

for(i=l; i< =NUM_TILES; i++)

{

sprintf(buf, " t%d.pcx", i);

result=ReadPcxFile(buf, & pcx);

if(result! = PCX_OK) (printf(" \nerror reading file: %s\n", buf);

exit(1);

} tiles[i]=pcx.bitmap;

} }

void FreeTiles() { int i;

for(i=0; i< NUM_TILES; i++) free(tiles[i]);

}

void ReadTileMap(char *filename)

{

int i;

FILE *f;

f=fopen(filename, " rt");

for (i=0; i< TILES__TOTAL; i-H-) {

fscanf(f, " %d", & (tilemap[i]));

}

fclose(f);

}

//

void DrawTile(char *bmp, int x, int y, int offset, int width)

{

char *dest;

int i;

if(bmp == NULL) return;

dest=MemBuf+y*VIEW_WIDTH+x;

bmp+=offset;

for(i=0; i< TILE_HEIGHT; i++) {

memcpy(dest, bmp, width);

dest+=VIEW_WIDTH;

bmp+=TILE_WIDTH;

} }

//

void DrawTiles(int VirtualX, int Starty)

{

int i, x, index, offset, row, limit;

index=VirtualX> > SHIFT;

offset=VirtualX - (index< < SHIFT);

limit=TILES_PER_ROW;

if(offset==0)

limit--;

for(row=Starty; row< Starty+TILE_HEIGHT*TILE_ROWS;

row+=TILE_HEIGHT) {

x=TILE_WIDTH-of£ set;

DrawTile(tiles[tilemap[index]], 0, row, offset,

TILE_WIDTH-offset);

for(i=index+l; i< index+limit; i++)

{

DrawTile(tiles [tilemap [i]], x, row, 0, TILE_WIDTH);

x+=TILE_WIDTH;

} DrawTile(tiles [tilemap[i] ], x, row, 0, offset);

index+=TILE_COLS;

}

}

//

int main() { clock_t begin, fini;

Initialize();

begin=clock();

AnimLoop();

fini=clock();

Cleanup();

printf(" Frames: %d\nfps: %f\n", frames,

(float)CLK_TCK*frames/(fini-begin));

return 0;

)

Устранение эффекта сдвига кадра

На медленных машинах или на машинах с медленными видеокартами можно заметить некий сдвиг изображения, как будто оно копируется на экран. Из-за эффекта сдвига изображение выглядит как бы разорванным. Этот интересный но нежелательный эффект появляется оттого, что адаптер сканирует видеобуфер и рисует изображение на дисплее примерно 60 раз в секунду. Этот процесс называется регенерацией экрана. Если программа в момент начала регенерации дисплея находится в процессе рисования кадра, вы заметите эффект сдвига изображения.

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

В Листинге 17.7 содержится фрагмент программы, ожидающей завершения цикла регенерации экрана. Это дает вам примерно 1/60 секунды, чтобы нарисовать следующий кадр. Данный фрагмент можно поместить непосредственно перед функцией, перемещающей кадр из системной памяти в видеобуфер. Выполняйте такую проверку каждый раз перед копированием буфера на экран. Только на очень быстрых машинах или при использовании небольшого окна вывода, одной шестидесятой секунды будет достаточно для изображения нескольких планов и их копирования на экран. Это главный недостаток режима 13h. Единственная альтернатива проверке на регенерацию экрана — это использование видеорежимов, поддерживающих несколько видеостраниц, и переключение между ними.






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