Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Листинг 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. Единственная альтернатива проверке на регенерацию экрана — это использование видеорежимов, поддерживающих несколько видеостраниц, и переключение между ними.
|