Capture Sprite dari Game (Bag II)

BY IN QBasic Comments Off on Capture Sprite dari Game (Bag II)

Berbicara ttg game memang ngga ada habis2nya. Beberapa game yang sempat populer pada jaman DOS dulu diantaranya adalah serial King’s Quest buatan SIERRA yang sampe sekarang melegenda (bener enggak sih?). Ada juga game Quest for Glory, juga dari Sierra. Grafiknya sangat memukau (untuk masa itu tentunya…). Saya jadi inget pertama kali main King’s Quest III, saya main di Disket aja, waktu itu masih ada disket ukuran 5.25″, sekarang disket model gini keliatannya dah pensiun deh… pinjem dari temen saya sebangku waktu SMA. wah asyik deh pokoknya…
Ok jadi saya sampai pada satu pertanyaan, kenapa gambar hasil konversi BMP kok bisa berubah total ancur2an saat dijadikan SHP di QBasic. Jawabannya adalah karena sistem palet yang dipakai tidak sama… wah apa sih palet itu? Palet itu bisa digambarkan seperti seorang pelukis. Nah pelukis biasanya kan pake kanvas kalo melukis, selain itu dia juga butuh sebuah wadah untuk mengoleskan cat2nya yang nantinya dicampur untuk lukisannya. wadah ini biasa disebut palet.

Dalam pengertian program kita, palet itu suatu sistem warna yang digunakan dalam game kita. Pengertian 256 warna sebenarnya bukan berarti hanya maksimal 256 warna saja yang dapat kita pakai. Melainkan, lebih dari itu! Kita dapat menggunakan warna2 yang beraneka ragam. Hanya saja, dalam satu waktu, kita hanya diijinkan menggunakan warna sebanyak 256 saja.

Berikut ini program untuk menampilkan sistem palet default:

SCREEN 13 ‘ Set graphics mode

j% = 0
FOR i% = 0 TO 255
COLOR i%
PRINT “Color ” + STR$(i%)
IF j% MOD 20 = 0 THEN key$ = INPUT$(1)
j% = j% + 1
NEXT

disini kita nanti akan liat warna2 dari 0 sampai dengan 255 dengan menggunakan sistem palet default. Untuk file BMP yang kita habis capture, kita liat dulu statistiknya, baik informasi file BMPnya maupun informasi paletnya. Pertama2 kita intip dulu informasi2 di file BMPnya, tujuannya kita akan membuat statistik dari kode warna yang digunakan. Karena masing2 disimpan di dalam byte, maka nilainya pasti antara 0 sampai 255. berikut adalah program Informasi BMP-nya …

‘Read Information from BMP

TYPE BMPHeaderType
ID AS STRING * 2 ‘Should be “BM”
size AS LONG ‘Size of the data
rr1 AS INTEGER ‘
rr2 AS INTEGER ‘
Offset AS LONG ‘Position of start of pixel data
horz AS LONG ‘
wid AS LONG ‘Image width
hei AS LONG ‘Image height
Planes AS INTEGER ‘
bpp AS INTEGER ‘Should read 8 for a 256 colour image
pakbyte AS LONG ‘
imagebytes AS LONG ‘Width*Height
xres AS LONG ‘
yres AS LONG ‘
colch AS LONG ‘
ic AS LONG ‘
pal AS STRING * 1024 ‘Stored as
END TYPE

DIM BmpHeader AS BMPHeaderType

filename$ = “marlex.bmp”
OPEN filename$ FOR BINARY AS #1

GET #1, , BmpHeader

COLOR 15, 0
SCREEN 0
CLS

PRINT “File .BMP Information”
PRINT “Filename : “, filename$
PRINT “BMP ID : “, BmpHeader.ID
PRINT “Size in bytes : “, BmpHeader.size
PRINT “RR1 : “, BmpHeader.rr1
PRINT “RR2 : “, BmpHeader.rr2
PRINT “Horz : “, BmpHeader.horz
PRINT “Start Offset : “, BmpHeader.Offset
PRINT “Total Planes : “, BmpHeader.Planes
PRINT “BitPerPlanes : “, BmpHeader.bpp
PRINT “X-Res : “, BmpHeader.xres
PRINT “Y-Res : “, BmpHeader.yres
PRINT “Width : “, BmpHeader.wid
PRINT “Height : “, BmpHeader.hei
PRINT “Image Bytes : “, BmpHeader.imagebytes
PRINT “Pak Bytes : “, BmpHeader.pakbyte
PRINT “Colch : “, BmpHeader.colch
PRINT “IC : “, BmpHeader.ic

key$ = INPUT$(1)

a$ = BmpHeader.pal

CLS
PRINT “Palette Information”

j% = 1
FOR I% = 1 TO 1024 STEP 4
PRINT “Pallete ” + STR$(j%) + ” : “;
b% = ASC(MID$(a$, I%, 1)) \ 4 ‘blue
PRINT b%;
g% = ASC(MID$(a$, I% + 1, 1)) \ 4 ‘green
PRINT g%;
r% = ASC(MID$(a$, I% + 2, 1)) \ 4 ‘red
PRINT r%
j% = j% + 1
IF j% MOD 20 = 0 THEN key$ = INPUT$(1)
NEXT

key$ = INPUT$(1)

DIM warna(255) AS INTEGER

DIM pixel AS STRING * 1 ‘ Our pixel “byte”.

iHeight% = BmpHeader.hei – 1 ‘ Subtract 1 for actual screen position
iWidth% = BmpHeader.wid – 1 ‘

cnt = 1

FOR y% = iHeight% TO 0 STEP -1 ‘ Countdown for upsidedown image
FOR x% = 0 TO iWidth%

GET #1, , pixel ‘ read pixel ‘ Read one pixel (byte)
warna(ASC(pixel)) = warna(ASC(pixel)) + 1

PRINT cnt; ” ” + pixel + ” “; ASC(pixel) ‘ Pixel is actually a string so we get the pixel
‘ number by requesting the “ASC” value
cnt = cnt + 1

NEXT x%, y%

CLOSE #1

key$ = INPUT$(1)

CLS
PRINT “Image Statistics”
m = 0
n = 1
FOR l = 0 TO 255
IF warna(l) <> 0 THEN
PRINT “Total Byte for color ” + STR$(l) + “: “, warna(l)
m = m + 1
END IF
n = n + 1
IF n MOD 20 = 0 THEN key$ = INPUT$(1)
NEXT
PRINT “Total used color : “; m

hehehe… output dari program ini akan menghasilkan nilai2 atau angka2 yang digunakan untuk membuat suatu sprite. jadi alasan kenapa gambar kita ancur sebenarnya sederhana. Karena sistem palet default berbeda dengan palet yang digunakan dalam file BMP. Oleh karena itu, jika didapatkan suatu nilai, warna yang dirujuk oleh nilai tersebut pada file BMP, akan berbeda dengan warna yang dirujuk pada palet yang default. Saya perlu menulis program lagi untuk membaca info palette dari file BMP kita:

TYPE BMPHeaderType
id AS STRING * 2 ‘Should be “BM”
size AS LONG ‘Size of the data
rr1 AS INTEGER ‘
rr2 AS INTEGER ‘
offset AS LONG ‘Position of start of pixel data
horz AS LONG ‘
wid AS LONG ‘Image width
hei AS LONG ‘Image height
planes AS INTEGER ‘
bpp AS INTEGER ‘Should read 8 for a 256 colour image
pakbyte AS LONG ‘
imagebytes AS LONG ‘Width*Height
xres AS LONG ‘
yres AS LONG ‘
colch AS LONG ‘
ic AS LONG ‘
pal AS STRING * 1024 ‘Stored as
END TYPE

DIM BmpHeader AS BMPHeaderType

OPEN “marler6.bmp” FOR BINARY AS #1

GET #1, , BmpHeader

SCREEN 13 ‘ Set graphics mode

a$ = BmpHeader.pal ‘ Pal is stored in a 1024 character string

OUT &H3C8, 0 ‘ Start writing from Colour 0
FOR i% = 1 TO 1024 STEP 4
B% = ASC(MID$(a$, i%, 1)) \ 4 ‘blue
g% = ASC(MID$(a$, i% + 1, 1)) \ 4 ‘green
r% = ASC(MID$(a$, i% + 2, 1)) \ 4 ‘red
‘ I% + 3 is set to zero.
OUT &H3C9, r% ‘ Set the colour.
OUT &H3C9, g%
OUT &H3C9, B%
NEXT
CLOSE #1

j% = 0
FOR i% = 0 TO 255
COLOR i%
PRINT “Color ” + STR$(i%)
IF j% MOD 20 = 0 THEN key$ = INPUT$(1)
j% = j% + 1
NEXT

dari sini akan keliatan semua warna2 yang digunakan. kalo saya bandingkan dengan warna2 pada palet default, akan keliatan berbeda. Nah, disini saya mengalami dilema, gimana yah? kalo saya mempertahankan palet default, gambarnya ancur2an deh. tapi kalo misalnya saya pake sistem palet dari BMP, saya hanya akan bisa mengambil sprite dari 1 source saja.
gini aja deh, pikir saya. Saya akan tetep pake palet yang default, tapi saya harus cari warna alternatif yang sama atau mendekati warna dari file BMP kita.

Saya lihat kembali program InfoBMP dan InfoPal, lalu saya buat list dari masing2 nilai warnanya, misal untuk warna kulit tubuh, warna rambut, warna baju dan sebagainya. Saya buka lagi Default Palette-nya dan saya cari nilai warna yang bersesuaian dari list saya.
Berikutnya saya tulis program untuk mengubah nilai2 di file BMP;

‘Edit BMP Files per pixel

TYPE BMPHeaderType
ID AS STRING * 2 ‘Should be “BM”
size AS LONG ‘Size of the data
rr1 AS INTEGER ‘
rr2 AS INTEGER ‘
Offset AS LONG ‘Position of start of pixel data
horz AS LONG ‘
wid AS LONG ‘Image width
hei AS LONG ‘Image height
Planes AS INTEGER ‘
bpp AS INTEGER ‘Should read 8 for a 256 colour image
pakbyte AS LONG ‘
imagebytes AS LONG ‘Width*Height
xres AS LONG ‘
yres AS LONG ‘
colch AS LONG ‘
ic AS LONG ‘
pal AS STRING * 1024 ‘Stored as
END TYPE

DIM BmpHeader AS BMPHeaderType

filename$ = “marler.bmp”
OPEN filename$ FOR BINARY AS #1

GET #1, , BmpHeader

COLOR 15, 0
SCREEN 0
CLS

a$ = BmpHeader.pal

j% = 1
FOR I% = 1 TO 1024 STEP 4
b% = ASC(MID$(a$, I%, 1)) \ 4 ‘blue
g% = ASC(MID$(a$, I% + 1, 1)) \ 4 ‘green
r% = ASC(MID$(a$, I% + 2, 1)) \ 4 ‘red
NEXT

INPUT “Please Enter Bytes Value : “, SeekByte
INPUT “Please Enter New Value : “, ChangeByte

DIM pixel AS STRING * 1 ‘ Our pixel “byte”.
cnt = 0

iHeight% = BmpHeader.hei – 1 ‘ Subtract 1 for actual screen position
iWidth% = BmpHeader.wid – 1 ‘

‘Check Bytes
Byte.Remind = BmpHeader.imagebytes – (BmpHeader.wid * BmpHeader.hei)
IF Byte.Remind > 0 THEN
‘This will applied if the image size = 640 bytes
iHeight% = 31
iWidth% = 19
END IF

FOR y% = iHeight% TO 0 STEP -1 ‘ Countdown for upsidedown image
FOR x% = 0 TO iWidth%

GET #1, , pixel ‘ read pixel ‘ Read one pixel (byte)

IF ASC(pixel) = SeekByte THEN
cnt = cnt + 1
PRINT cnt; ” Old Value : “; ASC(pixel)
’save old current pointer
oldpointer = SEEK(1)
PRINT “Byte Position : “; oldpointer
SEEK #1, oldpointer – 1
pixel = CHR$(ChangeByte)
PUT #1, , pixel
SEEK #1, oldpointer

END IF

NEXT x%, y%
PRINT “Has made ” + STR$(cnt) + ” Replacement…”

CLOSE #1

mudah2an ga seberapa rumit… sebenarnya programnya sama aja kok, saya perlu menggabung fungsi membuka file BMP ke dalam satu function biar ga repot.

Ok, pada dasarnya saya menggunakan perintah SEEK untuk memindah pointer pada file bertipe binary dan mencari value pada sebuah file binary. Tinggal dimasukkan saja nilai lamanya berapa, dan mau diganti berapa…
sampe disini, saya sudah bisa mengganti nilai2 file BMP untuk selanjutnya saya konversi pake BMP2SHP. Dan… file SHP-nya sudah bisa dipakai…




Comments are closed.