Moi!
Nyt tuli vastaan pieni ongelma. Teen pientä merkkigrafiikkapeliä huvikseni assemblyllä, ja haluan kartan taulukkoon. Pitääkö siihen tehdä joku oma strukti, esim.
struct map line1 db 25 dup(?) line2 db 25 dup(?) line3 db 25 dup(?) ;jne... ends ;luodaan uusi instanssi kartasta: map1 map '#### ####################','####@####################', '#########################'
Vai pitääkö vain lukea kartta tiedostosta ja tumpata se yhteen muuttujaan?
ErroR++ kirjoitti:
Vai pitääkö vain lukea kartta tiedostosta ja tumpata se yhteen muuttujaan?
Siis yksinkertaisimmillaan ohjelmoijan näkökulmasta tuollainen kartta on vain label ja peräkkäisiä tavuja.
Alla historian kätköistä kaivettu yksinkertainen esimerkki structien käytöstä. Tarvinnee dosboxin tai OS/2:sen, jos tuota haluaa nykypäivänä kokeilla ajaa.
;************************************************************************* ; Simppeli animaatio testi ; ; käännä FLAT muistimallille ; ; Ohjelman kääntämisen ja linkitsemisen voi suorittaa ; käyttämällä OpenWatcom C/C++/ASM OpenSource kääntäjää, ; joka on kopioitavissa netistä ILMAISEKSI. ; ; Tai kopioimalla CauseWay tiedostot ; netistä osoitteesta: ; http://www.devoresoftware.com/freesource/cwsrc.htm ; ; ja kääntämällä MASM yhteensopivalla assemblerilla ; kuten TASM ja OpenWatcom paketissa oleva ; Openwatcom Assembler (WASM). Linkitseminen ; hoituu CauseWay -paketissa olevalla WL32 linkkerillä. ; ; Eli esim. wasm anim.asm (watcom assemblerilla) ; wl32 anim.obj /f ; ;************************************************************************ ; .386 ; Tässä järjestyksessä .model small ; takaavat use32 segmentit .stack 1024 ; Pitäisi riittää useimmille .. include cw.inc ; CauseWay API ;------------------------------------------------------------------------- VGA_SEGMENT equ 0A0000h SPRITE_WIDHT equ 24 SPRITE_HEIGHT equ 16 SCREEN_WIDHT equ 320 SCREEN_HEIGHT equ 200 LEFT equ 0 RIGHT equ SCREEN_WIDHT-SPRITE_WIDHT TOP equ 0 BOTTOM equ SCREEN_HEIGHT-SPRITE_HEIGHT sprite_struc struc x dw ? y dw ? deltax dw ? deltay dw ? sprite_struc ends ;-------------------------------------------------------------------------------- .data SpriteList label sprite_struc sprite_struc <160,110,1,1> sprite_struc <260,100,-1,1> sprite_struc <60,50,1,-1> sprite_struc <260,150,1,1> sprite_struc <220,70,-1,1> sprite_struc <200,110,1,-1> sprite_struc <250,40,1,-1> sprite_struc <140,30,-1,1> sprite_struc <30,10,1,-1> sprite_struc <40,90,-1,-1> SpriteListEnd label sprite_struc align 4 ScreenBuffer dd ? ;Osoitin näyttöpuskuriin Mem_message db 13,10,"Ei tarpeeksi muistia.",13,10,"$" Exit_message db 13,10,"Valmista.",13,10,"$" ;---------------------------------------------------------------------------------- ; .code Main: ; Osoita dataan mov ax,DGROUP mov ds,ax ; Lukitse ohjelman muisti mov esi,es:[EPSP_MemBase] mov ecx,es:[EPSP_MemSize] sys LockMem32 mov edx,offset Mem_message jc Exit ; Setup segment registers mov ax,ds mov es,ax mov fs,ax mov gs,ax ; Varaa muistia näyttöpuskurille mov ecx,SCREEN_WIDHT*SCREEN_HEIGHT call Malloc mov edx, offset Mem_message jc Exit mov [ScreenBuffer],esi ; Aseta näyttötila mov eax,13h int 10h ; Täytä näyttöpuskuri 0-värillä mov edi,esi mov ecx,(SCREEN_WIDHT*SCREEN_HEIGHT)/4 mov eax,0 rep stosd @@AnimationLoop: call Move call Draw ; Näppäimen painallus lopettaa mov ah,1 int 16h ;onko näppäintä painettu ? jz @@AnimationLoop ;ei -aloita alusta sub ah,ah int 16h ;kyllä, olemme valmiit ; Tekstitila mov eax,3 int 10h ; Vapauta näyttöpuskurille varattu muisti mov esi,[ScreenBuffer] call Free mov edx,offset Exit_message ;----------------------------------------------------------------------------------- ; ; Tulostaa viestin ja lopettaa ohjelman ; Exit: mov ah,09h int 21h mov ax,4c00h int 21h ;------------------------------------------------------------------------------------ ; ;Varaa muistia. ; ;Syöttöparametrit: ; ;ECX - tarvittava tavumäärä. ; ;Palauttaa: ; ;Carry asettuu, kun virhe muuten .. ; ;ESI - lineaari muistiosoite ; Malloc: push eax push ecx add ecx,4 ;Tee tilaa puskurin pituudelle. sys GetMemLinear32 ;Yritä varata muistia. jc @@malloc_2 sys LockMem32 ;Yritä lukita varattu muisti. jnc @@malloc_1 sys RelMemLinear32 ;Jos lukitus ei onnistu, vapauta varattu muisti. stc jmp @@malloc_2 @@malloc_1: mov [esi],ecx ;Tallenna varatun muistin määrä add esi,4 ; FREEtä varten. clc ;Varmista, että palautetaan onnistunut status. @@malloc_2: pop ecx pop eax ret ;------------------------------------------------------------------------------- ; ;Vapauttaa MALLOCilla varatun muistin. ; ;Syöttöparametrit: ; ;ESI - vapautettavan muistin lineaari osoite. ; Free: push eax push esi push ecx sub esi,4 ;Haetaan varatun .. mov ecx,[esi] ; muistin määrä. sys UnLockMem32 ;Poista lukitus. pop ecx sys RelMemLinear32 ;Vapauta muisti. pop esi pop eax ret ;-------------------------------------------------------------------------------- ; ; Kuvatieto käännettynä suoraan kuvanpiirtorutiiniiksi ; ; Käännetyn spriten etuna on kaikkien vertailujen ja ; hyppyjen eliminointi. Haittana on, että spriten pitää ; pysyä kokonaan näytön rajoissa. ; ; Syöttöparametrit: ; ; EAX - näyttöpuskurin osoite ; EBX - y-koordinaatti ; EDX - x-koordinaatti ; Sprite: ;Laskee näyttöosoitteen ; vastaa seuraavaa: (320 * y) + x mov ecx,ebx shl ebx,08h shl ecx,06h add eax,ebx add eax,ecx add eax,edx ; Piirtää kuvatiedon mov dword ptr [eax+0146h],010101010h mov dword ptr [eax+014Ah],010101010h mov dword ptr [eax+014Eh],010101010h mov byte ptr [eax+0152h],010h mov dword ptr [eax+0284h],0E101010h mov dword ptr [eax+0288h],0E0E0E0Eh mov dword ptr [eax+028Ch],0E0E0E0Eh mov dword ptr [eax+0290h],010100E0Eh mov byte ptr [eax+0294h],010h mov dword ptr [eax+03C3h],0E0E1010h mov dword ptr [eax+03C7h],0E0E100Eh mov dword ptr [eax+03CBh],0E0E0E0Eh mov dword ptr [eax+03CFh],0E0E0E10h mov word ptr [eax+03D3h],0100Eh mov byte ptr [eax+03D5h],010h mov dword ptr [eax+0501h],00E101010h mov dword ptr [eax+0505h],010100E0Eh mov dword ptr [eax+0509h],0E0E0E10h mov dword ptr [eax+050Dh],01010100Eh mov dword ptr [eax+0511h],0E0E0E0Eh mov word ptr [eax+0515h],01010h mov dword ptr [eax+0641h],0E0E0E10h mov dword ptr [eax+0645h],010100E0Eh mov dword ptr [eax+0649h],0E0E0E10h mov dword ptr [eax+064Dh],01010100Eh mov dword ptr [eax+0651h],0E0E0E0Eh mov word ptr [eax+0655h],0100Eh mov dword ptr [eax+0781h],0E0E0E10h mov dword ptr [eax+0785h],0100E0E0Eh mov dword ptr [eax+0789h],0E0E0E0Eh mov dword ptr [eax+078Dh],0E100E0Eh mov dword ptr [eax+0791h],0E0E0E0Eh mov word ptr [eax+0795h],0100Eh mov dword ptr [eax+08C1h],0E0E0E10h mov dword ptr [eax+08C5h],0E0E0E0Eh mov dword ptr [eax+08C9h],0E0E0E0Eh mov dword ptr [eax+08CDh],0E0E0E0Eh mov dword ptr [eax+08D1h],0E0E0E0Eh mov word ptr [eax+08D5h],0100Eh mov dword ptr [eax+0A01h],0E0E0E10h mov dword ptr [eax+0A05h],0E0E0E0Eh mov dword ptr [eax+0A09h],0E0E0E0Eh mov dword ptr [eax+0A0Dh],0E0E0E0Eh mov dword ptr [eax+0A11h],0E0E0E0Eh mov word ptr [eax+0A15h],0100Eh mov dword ptr [eax+0B41h],0E0E0E10h mov dword ptr [eax+0B45h],0E0E0E0Eh mov dword ptr [eax+0B49h],0E0E0E0Eh mov dword ptr [eax+0B4Dh],0E0E0E0Eh mov dword ptr [eax+0B51h],0E0E0E0Eh mov word ptr [eax+0B55h],0100Eh mov dword ptr [eax+0C81h],0E0E0E10h mov dword ptr [eax+0C85h],0E0E0E10h mov dword ptr [eax+0C89h],0E0E0E0Eh mov dword ptr [eax+0C8Dh],0E0E0E0Eh mov dword ptr [eax+0C91h],0E0E100Eh mov word ptr [eax+0C95h],0100Eh mov dword ptr [eax+0DC1h],0E0E0E10h mov dword ptr [eax+0DC5h],0E0E100Eh mov dword ptr [eax+0DC9h],0E0E0E0Eh mov dword ptr [eax+0DCDh],0E0E0E0Eh mov dword ptr [eax+0DD1h],0E0E0E10h mov word ptr [eax+0DD5h],0100Eh mov dword ptr [eax+0F01h],00E101010h mov dword ptr [eax+0F05h],010100E0Eh mov dword ptr [eax+0F09h],010101010h mov dword ptr [eax+0F0Dh],010101010h mov dword ptr [eax+0F11h],0100E0E0Eh mov word ptr [eax+0F15h],01010h mov dword ptr [eax+01043h],0E0E1010h mov dword ptr [eax+01047h],0E0E0E0Eh mov dword ptr [eax+0104Bh],0E0E0E0Eh mov dword ptr [eax+0104Fh],0E0E0E0Eh mov word ptr [eax+01053h],01010h mov dword ptr [eax+01184h],010101010h mov dword ptr [eax+01188h],010101010h mov dword ptr [eax+0118Ch],010101010h mov dword ptr [eax+01190h],010101010h ret ;-------------------------------------------------------------------------------------- ; ; Liikuttaa spritejä ; Move: mov ebx,offset SpriteList ;osoita sprite listaan @@CheckXLeftLimit: mov cx,[ebx+x] cmp cx,LEFT ;vasen reuna ? ja @@CheckXRightLimit ;ei -tarkasta oikea reuna neg [ebx+deltax] ;kyllä -käännä X suunta @@CheckXRightLimit: cmp cx,RIGHT ;oikea reuna ? jb @@MoveX ;ei -aika liikuttaa neg [ebx+deltax] ;kyllä -käännä X suunta @@MoveX: add cx,[ebx+deltax] ;lisää X koordinaattiin mov [ebx+X],cx ;talteen @@CheckYTopLimit: mov dx,[ebx+y] cmp dx,TOP ;yläreuna ? ja @@CheckYBottomLimit ;ei -tarkasta alareuna neg [ebx+deltay] ;kyllä -käännä Y suunta @@CheckYBottomLimit: cmp dx,BOTTOM ;alareuna ? jb @@MoveY ;ei -aika liikuttaa neg [ebx+deltay] ;kyllä -käännä Y suunta @@MoveY: add dx,[ebx+deltay] ;lisää Y koordinaattiin mov [ebx+y],dx ;talteen @@DoNextObject: add ebx, size sprite_struc ;osoita seuraavaan objektiin cmp ebx, offset SpriteListEnd ;ollaanko listan lopussa ? jb @@CheckXLeftLimit ;ei -seuraava objekti ret ;------------------------------------------------------------------------------------ ; ; Piirtää spritet näyttöpuskuriin ; Draw: mov esi,offset SpriteList @@DrawLoop: mov eax,[ScreenBuffer] movzx ebx,[esi+y] movzx edx,[esi+x] call Sprite add esi,size sprite_struc ;osoita seuraavaan objektiin cmp esi, offset SpriteListEnd ;ollaanko listan lopussa ? jb @@DrawLoop ;ei -seuraava objekti ; Kopioi näyttöpuskurin sisällön näytölle @@BufferToScreen: mov esi,[ScreenBuffer] mov edi,VGA_SEGMENT mov ecx,(SCREEN_WIDHT*SCREEN_HEIGHT)/4 mov dx,3dah ;VGA portti ja indeksi (Input Status Register) @@Retrace: in al,dx ;lue VGA portti and al,8 ;selvitä tahdistuksen tila jz @@Retrace ;odota näytön tahdistusta cld rep movsd ;kopioi 32-bittiä kerrallaan ret ;------------------------------------------------------------------------------------ end Main
format PE GUI 4.0 include 'win32ax.inc' .code start: invoke MessageBox, 0, juttu, 0, 0 invoke ExitProcess, 0 .end start .data juttu db 'abc' db 'def' db 0
Näyttää tekstin 'abcdef'.
Entä sitten törmäystesti?
Eikö kartan pitäisi olla taulukossa ja lisäksi: kartta ladataan tiedostosta (vähän WinAPI -pelleilyä ja CloseHandleja niin eiköhän sen kartan voi sieltä kiintolevyltä ladata).
Kaikkihan on "jonossa" siellä muistissa. Jos ajattelet esim. 2-ulotteista taulukkoa, niin tämähän on (korkeamman tason) kielien tarjoama abstraktio. Assemblyssä voit toteuttaa sen millä tavalla haluat.
; juttu[y][x] = juttu[y*rivin_leveys + x] ; ; tulo tallenetaan eaxin ja edxin muodostamaan 64-bittiseen ; muuttujaan (vähemmän merkitsevä osa eaxissa riittää) mov eax, 1 ; rivi 1 mov ecx, 3 ; yhden rivin pituus mul ecx ; kertolasku mov al, [juttu+eax+2] ; nyt al = 0x66 = 'f' juttu db 'abc' db 'def' db 0
Jos kerrotaan kahden potenssilla, niin kertolaskun voi korvata shl-käskyllä. Kertomisen luvulla joka on muotoa 2^n + 1
(missä 0 <= n <= 3
) pystyy kikkailemaan lea-käskyllä (esim. lea eax, [eax*8+eax]
).
Nyt älysin! Kiitos avusta!
Aihe on jo aika vanha, joten et voi enää vastata siihen.