Anis-эффект Как скролить (вправо-влево, вверх-вниз), надеюсь, вы знаете. Что такое полярные координаты, наверно то же. Так вот этот эффект основан на скролинге, но в полярных координатах. Соответственно скролинг вдоль координаты [math]r[/math] - выглядит как втягивание-вытягивание, а изменение угла [math]\alpha[/math] - как повороты по часовой стрелке или против. Вот и вся теория. Теперь начнется практика. Пусть центр нашего anis`a находиться в центре экрана. Тектуру, которую мы хотим вращать, возьмем размером 256x256. Основное требование к этой текстуре - быть бесшовной, чтобы удобно было скроллить. Посмотрите на мою текстуру, чтобы понять о чем речь: в не имеющих названия единицах, которых в круге 256. Теперь сопоставим углу [math]\alpha[/math] - координату [math]x[/math] в нашей текстуре, а координате [math]r[/math] - [math]y[/math] нашей текстуры. Теперь, что бы втягивать-вытягивать и вращать текстуру, достаточно изменить начальные смещения по [math]x[/math] и [math]y[/math] в нашей текстуры. Реализуем наши соображения в алгоритме, он разделится на две части: 1. Инициализация. Заведем два массива texture и anis. В первом храним нашу текстурку, а во втором (типа unsigned short, размер такой же как у экрана) будем хранить смещения текстуры. Далее в цикле проходим по всем точкам массива anis, преобразуем декартовы координаты текущей точки в полярные, по этим координатам вычисляем смещение от начала массива texture, и заносим его в текущую ячейку массива anis: Код (C): long x,y,u,v,p=0; double angle, radius; for(y=-100;y<100;y++) for(x=-160;x<160;x++) { radius=sqrt(x*x+y*y); if(radius<1) radius=1; angle=atan2(y,x)+PI; v=radius; u=angle*128/PI; anis[p++]=(u&0xFF)+((v&0xFF)<<8); } 2. Рендеринг. Для каждого выводимого кадра решаем насколько нам надо повернуть, втянуть-вытянуть нашу текстуру, то есть находим сдвиг по координате [math]r[/math] и углу [math]\alpha[/math]. В цикле проходим по массиву anis, считываем из него смещение, прибавляем вычисленный ранее сдвиг, и по этому смещению считываем пиксель из массива texture. Записываем его по текущим координатам в буфер экрана: Код (C): long u=256*cos(time); long v=512*sin(time); long screen_ptr=(long)&screen; long i=0; for(long k=0;k<64000;k++) *((char*)screen_ptr++)=texture[(anis[i++]+u+(v<<8))&0xFFFF]; Взято здесь, текст программы немного переделан, в результате СОМ-файл уменьшился с 668 байт до 428 байт Код (ASM): ; masm dos com # .286 .model tiny .code .386 org 100h WIDTH_SREEN equ 320 HEIGHT_SCREEN equ 200 SCREENSIZE equ WIDTH_SREEN*HEIGHT_SCREEN MEMBLOCKSIZE equ SCREENSIZE/16 IMPUT_STATUS_0 equ 3DAh ;регистр статуса ввода 0 VGA_SEGMENT equ 0A000h u equ dword ptr [bp-4] v equ dword ptr [bp-8] x equ dword ptr [bp-12] y equ dword ptr [bp-16] x2 equ dword ptr [bp-20];x2=x*x radius equ dword ptr [bp-24] anis equ word ptr [bp-26] texture equ word ptr [bp-28] screen equ word ptr [bp-30] start: mov sp,0FB0h mov ah,4Ah ; ADJUST MEMORY BLOCK SIZE (SETBLOCK) mov bx,0FBh; BX = new size in paragraphs int 21h; ES = segment address of block to change enter 30,0 mov bx,MEMBLOCKSIZE mov ah,48h ; ALLOCATE MEMORY int 21h ; BX = number of 16-byte paragraphs desired mov screen,ax mov bx,1000h mov ah,48h ; ALLOCATE MEMORY int 21h ; BX = number of 16-byte paragraphs desired mov texture,ax mov bx,MEMBLOCKSIZE*2 mov ah,48h ; ALLOCATE MEMORY int 21h ; BX = number of 16-byte paragraphs desired mov fs,ax; mov anis,ax mov ax,13h int 10h ; - VIDEO - SET VIDEO MODE ;read bmp-file-------------------------------------------------------------- mov dx,offset filename; DS:DX-> ASCIZ filename "texture.bmp" mov ax,3D00h ; OPEN FILE FOR READ int 21h mov bx,ax xor cx,cx mov dx,54;Первые 54 байта - заголовок, в котором хранится разнообразная информация о картинке. mov ax,4200h; MOVE FILE READ/WRITE POINTER (LSEEK) int 21h ; AL = method: offset from beginning of file ;Эта информация нам не нужна, так как мы и так знаем какую картинку считываем. ;Если наша картинка 8-битная то следующие 1024 байта занимает палитра нашей картинки. mov dx,offset pal mov cx,1024 mov ah,3Fh ; READ FROM FILE int 21h ; BX = file handle, CX = number of bytes to read mov di,1023 @@: shr pal[di],2 dec di jns @b push ds mov ds,texture; word ptr ds:39Eh mov dx,0FF00h @@: mov cx,256 ;dx=y*256 mov ah,3Fh ; READ FROM FILE int 21h ; BX = file handle, CX = number of bytes to read sub dh,1 jnc @b pop ds mov ah,3Eh ; CLOSE A FILE WITH HANDLE int 21h ; BX = file handle ;init_anis----------------------------------------------- ;Заведем два массива texture и anis. В первом храним нашу текстурку, а во втором ;(типа unsigned short, размер такой же как у экрана) будем хранить смещения текс ;туры. Далее в цикле проходим по всем точкам массива anis, преобразуем декартовы ;координаты текущей точки в полярные, по этим координатам вычисляем смещение от ;начала массива texture, и заносим его в текущую ячейку массива anis xor di, di mov es,anis mov y,-HEIGHT_SCREEN/2 a0: mov x,-WIDTH_SREEN/2 a1: mov eax,x imul eax mov x2,eax;x2=x*x mov eax,y imul eax add eax,x2 mov radius,eax;radius=y*y+x2 fild radius fsqrt fistp radius;radius=sqrt(x*x+y*y) cmp radius,1;if (radius < 1) radius = 1; jge @f mov radius,1 @@: fild x fild y fpatan fldpi faddp st(1), st ;angle=atan2(y,x)+PI; fmul const_128_pi fistp x2 ;u=angle*128/PI; mov ah,byte ptr radius mov al,byte ptr x2 stosw;anis[p++]=(u&0xFF)+((v&0xFF)<<8); test di,di jnz @f mov ax,es add ax,1000h mov es,ax @@: inc x cmp x,WIDTH_SREEN/2 jl a1 inc y cmp y,HEIGHT_SCREEN/2 jl a0 ;set color table---------------------------------- xor bx,bx;mov bx,255*4 xor ax,ax mov cx,256 ;set rgb palette mov dx,3C8h out dx,al inc dx @@: mov al,pal[bx+2];красный out dx,al mov al,pal[bx+1];зеленый out dx,al mov al,pal[bx];синий out dx,al add bx,4 loop @b ;------------------------------------------------- ;Рендеринг ;Для каждого выводимого кадра решаем насколько нам надо повернуть, втянуть- ;вытянуть нашу текстуру, то есть находим сдвиг по координате r и углу alpha. В ;цикле проходимся по массиву anis, считываем из него смещение, прибавляем ;вычисленный ранее сдвиг, и по этому смещению считываем пиксель из массива ;texture. Записываем его по текущим координатам в буфер экрана: fldz; time=0 @@: fld st fsincos fmul const_512 fistp v ;long v=512*sin(time); fmul const_256 fistp u ;long u=256*cos(time); shl v,8 ;long screen_ptr=(long)&screen; xor bx,bx ;long i=0; mov es,screen;for(long k=0;k<64000;k++) mov fs,anis ;*((char*)screen_ptr++)=texture[(anis[i++]+u+(v<<8))&0xFFFF]; mov gs,texture mov cx,SCREENSIZE xor di,di a2: mov si,fs:[bx] add si,word ptr u add si,word ptr v movs byte ptr es:[di],gs:[si] inc bx inc bx jnz a3 mov ax,fs add ax,1000h mov fs,ax a3: loop a2 ;copy virtual screen mov dx,IMPUT_STATUS_0 WaitVerticalSync:in al,dx test al,8 jz WaitVerticalSync WaitNotVerticalSync:in al,dx test al,8 jnz WaitNotVerticalSync push VGA_SEGMENT pop es xor di,di xor si,si fadd const_001;time+=0.01 push ds mov ds,screen mov cx,SCREENSIZE/4 rep movsd push 0 pop ds mov ax,ds:[41Ah] sub ax,ds:[41Ch] pop ds jz @b @@: mov ax,3 int 10h ; - VIDEO - SET VIDEO MODE int 20h const_001 dd 0.01 const_128_pi dd 40.743665431525205956834243423364;128/3.14 const_256 dd 256.0 const_512 dd 512.0 filename db 'texture.bmp' pal db 0 end start Берем файл texture.bmp в результате получаем следующий эффект