Saturday, 31 December 2011

Ayo bikin "Win32 Application" (2)

Game -> New Game (F2)


Tulisan ini merupakan lanjutan dari:
Ayo bikin "Win32 Application" (1)

Untuk menambahkan menu kita perlu membuat file tambahan yaitu file 'resource.h' dan 'resource.rc'. Langsung saja, klik File -> New -> Empty File. Ketika ditanya "Do you want to add this new file in the active project (has to be saved first)?", pilih Yes untuk menlanjutkan, lalu ketikan resource.h untuk nama file yang akan disimpan. Lanjutkan dengan memilih OK untuk Multiple Selection :

Gambar 1. Tambahkan file lainnya kedalam project.

lalu ketikan (file resource.h):

#define MENU_BUATAN 101

#define MENU_FILE_NEW 1001
#define MENU_FILE_EXIT 1002

#define MENU_HELP_ABOUT 1003

Tambahkan file baru, seperti langkah diatas dengan nama resource.rc. Kemudian isi seperti berikut :

#include "resource.h"

MENU_BUATAN  MENU
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&New", MENU_FILE_NEW
        MENUITEM "E&xit", MENU_FILE_EXIT
    END

    POPUP "&Help"
    BEGIN
        MENUITEM "Abou&t", MENU_HELP_ABOUT
    END
END


Untuk membuat struktur data menu kita perlu memasukkan key MENU sesudah variabel menu utama kita, yaitu MENU_BUATAN. Lalu dimulai dengan BEGIN untuk memulai, selanjutnya POPUP "&File" yang berarti ada nama File pada Menubar yang berisi submenu selanjutnya (dimulai dengan BEGIN, dan diakhiri dengan END). Sedangkan penambahan karakter '&' berarti menggunakan karakter selanjutnya untuk membuat shortkey pada menu tersebut (dalam hal ini huruf F). Untuk mencobanya tekan tombol Alt lalu akan muncul garis bawah pada setiap menu dalam Menubar. Shortkey ini tidak akan tercipta jika kita tidak menambahkan karakter '&' . Selanjutnya penambahan preprocessor seperti MENU_FILE_EXIT agar dapat menandakan menu tertentu saat diklik. Setelah selesai mempersiapkan kedua file tersebut, kita perlu menambahkan beberapa kode kedalam file utama (main.cpp):


...
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);

 // 1
 wincl.lpszMenuName = MAKEINTRESOURCE( MENU_BUATAN);                 /* My Menu :) */

    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */

...
 
/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {

 // 2
        case WM_COMMAND:
            switch( LOWORD(wParam))
            {
                case MENU_FILE_EXIT:
                    PostQuitMessage(WM_QUIT);
                    break;
    // 3
                case MENU_HELP_ABOUT:
                    MessageBox(NULL, "Selamat Anda telah membuat menu pada program anda. :D", "About This Program", MB_OK);
                    break;
            };
            return 0;

        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

... 

Untuk dapat memasukkan menu buatan kita sendiri ke dalam Window, kita hanya perlu mengisi nilai pada variabel wincl (1). Tepatnya nilai wincl.lpszMenuName dengan MAKEINTRESOURCE( MENU_BUATAN). Dengan ini menu kita dapat tampil walau belum dapat menjalankan intruksi. Untuk itu kita perlu menambahkan WS_COMMAND dalam jantung utama program kita yaitu WindowProcedure() (2). Karena kita telah memasukkan nilai-nilai untuk setiap menu (seperti Exit = MENU_FILE_EXIT), kita cukup melakukan percabangan lalu menjalankan intruksi yang sesuai. Pada menu Help -> About , program akan menampilkan kotak pesan singkat yang berisi , hmm... Selamat! (3).

Akhir kata Selamat Tahun Baru 2012! ...

- krofz

Wednesday, 30 November 2011

Ayo bikin "Win32 Application" (1)

Pernah terbayang membuat program seperti notepad?, program yang satu ini memang sudah tidak asing lagi dari jaman Windows 98 . Biarpun tampilannya sederhana jangan anggap remeh fungsinya, yah apalagi kalau bukan mengetik teks hehehe. Agar dapat membuat program seperti itu, dan tampil secara minimalis serta GUI di Sistem Operasi (SO) Windows, kita perlu berinteraksi dengan Win32 API. Atau biasanya disebut Win32 Application.

Win32 Application adalah program yang mengarah kepada penggunaan WIN32 API (Application Programming Interface) sebagai librarynya. Mengapa dikatakan Win32? Karena ditulis dengan operasi 32-bit , dan dijalankan di SO Windows. Untuk lebih jelasnya pengertian Windows API .

Sebagai permulaan kita awali dengan template pada Code::Blocks, jalankan program Code::Blocks lalu pilih File -> New -> Project -> Win32 GUI Project. Maka akan keluar wizard yang akan membantu kita menentukan lokasi dan tipe dari program Win32 kita (Frame atau Dialog). Tipe yang akan dibuat adalah "Frame Based", seperti gambar berikut :

Gambar 1. Frame Based

Selanjutnya wizard akan menanyakan lokasi penyimpanan, dan metode peng-kompilasian program apakah Debug atau Release, atau keduanya. Pilih keduanya. Lanjutkan sampai finish dan Boom! sederet kode untuk membuat program Win32 sederhana telah tercipta . Lakukan kompilasi dan langsung jalankan (F9). Jika sukses maka anda akan melihat jendela program yang masih kosong, hanya ada tombol Minimize, Maximize, dan Close dipojok atas. Dibanding menghapal satu-satu kode yang amat banyak ini , kita mulai dari yang sederhana yaitu mengubah Caption/Judul program. Judul yang berasal dari template adalah "Code::Blocks Template Windows App". Judul ini diisi pada fungsi CreateWindowEx(), pada parameter ketiga. Silahkan cari lalu ubah menjadi "Latihan Win32" atau dengan kalimat yang diinginkan, lalu kompilasi ulang.

Jika semuanya lancar, kita lanjut ke dua fungsi utama. Yaitu int WINAPI WinMain() dan LRESULT CALLBACK WindowProcedure(). Pada fungsi int WINAPI WinMain(), parameter pertama berfungsi untuk menangani modul program saat dijalankan dan aktif di memory. Parameter kedua menunjuk ke instance sebelumnya, tetapi jika tidak maka akan diabaikan, dan umumnya selalu diabaikan/dilewati (bahkan bernilai NULL). Parameter ketiga adalah string yang mewakili semua item yang digunakan pada baris perintah untuk mengkompilasi aplikasi, katanya sih begitu . Parameter keempat/terakhir berfungsi sebagai pengatur bagaimana program kita akan ditampilkan (melalui fungsi ShowWindow (hwnd, nCmdShow);). Sedangkan LRESULT CALLBACK WindowProcedure(), adalah sebuah prosedur yang wajib pada program kita, karena pengulangan program terjadi disini. Jangan dipikirin dulu yang beginian . Yang penting program kita sudah kita dapat dimodifikasi dan berjalan dengan lancar. Selanjutnya kita akan menambahkan menu seperti File, New, Exit, dsb. So, Happy Coding...

- krofz

Wednesday, 2 November 2011

Inheritance pada Class

Inheritance (indonesia : Warisan) adalah cara yang digunakan untuk menurunkan sifat-sifat atau objek-objek (baik variabel atau fungsi) pada Pemrograman Berorientasi Objek (PBO, inggris : Object Oriented Programming - OOP). Penurunan objek ini dimaksudkan agar kita tidak menuliskan 2 kali objek yang memiliki nilai/fungsi yang sama. Untuk lebih jelasnya mari kita lihat kode berikut :


#include  < iostream > 

using namespace std;

class Badan{
    int tinggi, berat; //berat badan
public:
    Badan() :tinggi(100) , berat(50) {} //default Constructor
    void set(int t, int b){
        tinggi = t; berat = b; }
    int getTinggi(){ return tinggi; }
    int getBerat(){ return berat; }
};

//Kelas Turunan dari Badan
class Alien : public Badan{
public:
    //ketLien = Keterangan Alien
    void ketLien(){
        cout << "Tinggi Alien : " << getTinggi() << endl;
        cout << "Berat Alien : " << getBerat() << endl;
    }
};

class Manusia : public Badan{
public:
    //ketMan = Keterangan Manusia
    void ketMan(){
        cout << "Tinggi Manusia : " << getTinggi() << endl;
        cout << "Berat Manusia : " << getBerat() << endl;
    }
};

int main(int argc, char* argv[]){
    Alien A;
    A.set(150,40);
    A.ketLien();

    cout << endl;

    Manusia B;
    B.set(170,60);
    B.ketMan();

    return 0;
}

Kelas Alien dan Manusia merupakan kelas turunan dari kelas Badan. Dikarenakan alien dan manusia pasti memiliki objek yang sama, yaitu tinggi dan berat badan. Dengan pewarisan memudahkan kita dalam menambahkan objek yang sama itu, dibandingkan harus menuliskannya didalam kedua kelas (Alien dan Manusia). Sehingga pengunaan baris kode yang diperlukan dapat diminimalisir. Ditambah lagi jika fungsi yang digunakan bersama semakin banyak seperti fungsi berjalan, berlari, atau bekerja yang akan digunakan oleh Alien atau Manusia (atau Makhluk lainnya? ).

Penambahan warisannya cukup dengan tanda titik dua (:) pada kelas yang diinginkan. Selain itu kita juga dapat menambahkan 2 atau lebih kelas yang ingin mewariskan sifatnya (menggunakan koma ',' setelah kelas dasar pertama). Seperti contoh berikut:


//bentuk umum kelas turunan.
class Turunan : public Utama{
 ...
};

//contoh, dengan 2 kelas yang mewariskan
class Alien : public Badan ,  public Sayap{
 ...
};

Dapat dilihat dari kode diatas kelas alien memiliki objek dari kelas Badan dan Sayap. Objek yang dapat digunakan oleh kelas turunan adalah objek yang memiliki hak akses public dan protected. So Happy Coding! ...

- krofz

Wednesday, 21 September 2011

Constructor pada Class

Constructor adalah fungsi khusus untuk melakukan inisialiasi nilai pada objek kelas. Fungsi ini dipanggil saat sebuah objek dari suat kelas dibuat. Tujuan fungsi ini adalah untuk menghindari nilai yang tidak diinginkan. Contoh :


#include <iostream>

class Kotak{
    int p, l; //p = panjang , l = lebar
public:
    void set(int _p, int _l){ p = _p; l = _l;}
    int luas(){ return p*l; }
};

int main(){
 Kotak k;
 int a = k.luas();

 std::cout << a;
 return 0;
}

Jika kita langsung memanggil fungsi luas sebelum melakukan pemasukkan (set) nilai panjang dan lebar, maka nilai yang dihasilkan akan bermacam-macam atau malah menghasilkan sesuatu yang tidak diinginkan (error). Untuk mencegah hal ini maka kita perlu memanggil fungsi Constructor. Berikut contoh kodenya :


#include <iostream>

class Kotak{
    int p, l; //p = panjang , l = lebar
public:
    Kotak(): p(10) , l(10) {} //Constructor
 
    void set(int _p, int _l){ p = _p; l = _l;}
    int luas(){ return p*l; }
};

int main(){
 Kotak k;
 int a = k.luas();
 std::cout << "Nilai dari Constructor : " << a;

 k.set(15,15);
 a = k.luas();
 std::cout << "\nNilai dari set : " << a;
 return 0;
}

Constructor dapat juga memiliki parameter, seperti contoh berikut :


#include <iostream>

class Kotak{
    int p, l; //p = panjang , l = lebar
public:
    Kotak(): p(10) , l(10) {} //Constructor
    Kotak(int a){ p = a; l = a*a; } //dengan 1 parameter

    Kotak(int b, int c){ p = b + c; l = b + c + 1; } //dengan 2 parameter
    void set(int _p, int _l){ p = _p; l = _l;}
    int luas(){ return p*l; }
};

int main(){

 Kotak k(5); //secara otomatis memanggil constructor berparameter 1
 std::cout << "Nilai dari 1 parameter : " << k.luas();

 return 0;
}

So, Happy Coding....

- krofz

Friday, 22 July 2011

Operasi Bit Dengan XOR

Sebelum kita melangkah lebih jauh, mari kita bahas terlebih dahulu apa itu Bit?. Bit adalah sebuah digit dalam sistem angka biner (untuk lebih jelasnya tentang Bit). Sekalian belajar Sistem Bilangan Biner. Ada beberapa macam operasi bit seperti NOT, AND, OR, Shift Left, dan Shift Right. Dan tentunya XOR. Kali ini kita akan membahas XOR. XOR atau 'Exclusive OR', adalah operasi bit yang akan menghasilkan nilai 1 jika kedua bit berbeda. Berbeda dengan OR yang akan menampilkan nilai 1 untuk perbandingan '1 OR 1'. Dalam bahasa C biasa dilambangkan dengan '^' (dibaca 'caret' atau 'tanda sisipan', misal 'a^b'). Untuk lebih jelasnya lihat potongan kode berikut:


...
    //26 = 11010
    //12 = 01100
    //22 = 10110 <-- hasil
 
    int a = 26 xor 12; // atau 26 ^ 12
    printf("%d", a);
...

Dapat dilihat pada baris komentar operasi yang terjadi dalam biner. Perubahan apa saja yang terjadi pada setiap digit baris yang berurutan, misal 1 ketemu 0 hasilnya 1, dan selanjutnya. Operasi ini juga dapat digunakan dalam logika perpindahan nilai antara 2 variabel, seperti pada kode berikut ini:


#include < stdio.h >

int main(int argc, char *argv[])
{

    int a = 30,
        b = 15;

    printf("Nilai a = %d\nNilai b = %d\nsebelum ditukar", a,b);

    a = a xor b;
    b = a xor b;
    a = a xor b;

    printf("\n\n");
    printf("Nilai a = %d\nNilai b = %d\nsetelah ditukar",a,b);

    return 0;
}

Bagaimana cara kerjanya? perhatikan kode berikut:

int a = 30,
    b = 15;
  
a = a xor b; //pertama
16 8 4 2 1 <- desimalnya
1  1 1 1 0 <- biner
0  1 1 1 1 <- biner
---------- xor
1  0 0 0 1 = 17 

b = a xor b; //kedua
16 8 4 2 1
1  0 0 0 1 <- nilai a telah berubah
0  1 1 1 1
---------- xor
1  1 1 1 0 = 30


a = a xor b; //ketiga
16 8 4 2 1
1  0 0 0 1
1  1 1 1 0
---------- xor
0  1 1 1 1 = 15

Masih banyak manfaat dari operasi bit XOR, selain menukar 2 nilai variabel berbasarkan nilai bitnya. So, happy coding...

- krofz

Wednesday, 22 June 2011

Ayo Menghitung Cepat (2)

Tulisan ini merupakan lanjutan dari:
Ayo Menghitung Cepat (1)

Seperti janji saya yang berbunyi, yaitu "... akan saya bahas lagi sedikit tentang proses pemilihan jawabannya ..." hehehe. Maka setelah kita membuat kelas tombol ( class tombol{...}; ) yang tentunya sebagai objek utama dalam program ini, kita perlu menyiapkan variabel lainnya seperti berikut ini :


...
    // program main loop
    int fps = 0, a = 0, b = 0, c = 0, d = 0, poin = 10, jawaban = 0, kurangPoin = 0;
    bool done = false, reloadAngka = true;
    std::string pertanyaan;
...

Variabel a,b,c, dan d untuk menampung pilihan-pilihan jawaban. Selanjutnya variabel poin, untuk menampung nilai poin yang dimiliki. Poin akan bertambah jika jawaban yang dipilih benar. Dan poin juga berfungsi sebagai indikator perubahan bilangan-bilangan perkalian, semakin besar poin maka semakin besar bilangan yang akan dikalikan. Proses ini terletak pada pengecekkan kondisi var booelan reloadAngka (yang pada artikel sebelumnya juga sudah menampakkan diri ) :


...
    if( reloadAngka){
        int _x = 1+poin/60+rand()%4+(poin/30),
            _y = 1+poin/60+rand()%4+(poin/30);

        jawaban = _x*_y;

        int _z = _x+_y;
        a=jawaban+1+rand()%_z;
        b=jawaban+3+rand()%_z;
        c=jawaban-1-rand()%_z;
        d=jawaban-3-rand()%_z;

        int _start = rand()%4;
        switch(_start){
            case 0: a=jawaban; break;
            case 1: b=jawaban; break;
            case 2: c=jawaban; break;
            case 3: d=jawaban; break;
            default:;
        }

        std::stringstream SS;
        SS << _x << " x " << _y << " = ";
        pertanyaan = SS.str().c_str();
        reloadAngka = false;
    }
...

Variabel jawaban sudah pasti untuk menampung jawaban yang benar dan berfungsi sebagai parameter yang dibutuhkan dalam memilih jawaban yang benar. Var pertanyaan untuk menampung kalimat (string) perkalian. Sedangkan var kurangPoin sebagai timer untuk mengurangi 1 poin setiap 3 detik, jadi jangan kelamaan mikirnya atau poin anda akan berkurang dengan sendirinya . Penempatan jawabannya dilakukan secara acak (random), jadi tidak hanya jawabannya saja yang acak . Kita lanjutkan pada bagian terpenting yaitu pemilihan jawaban:


...
 //tahap 1
    case SDL_MOUSEMOTION:
        Xmouse = event.motion.x;
        Ymouse = event.motion.y;
        break;
    
    case SDL_MOUSEBUTTONDOWN:
        if( event.button.button == SDL_BUTTON_LEFT) klikKiri = true;
        break;
...
 //tahap 2
 const int _benar = 1;
    const int _salah = 2;
    int benar = 0; //0 (nol) berarti diam saja

    if( A.proses( Xmouse, Ymouse)){
        if(jawaban == a) benar = _benar;
        else benar = _salah;
    }
    else if( B.proses( Xmouse, Ymouse)){
        if(jawaban == b) benar = _benar;
        else benar = _salah;
    }
    else if( C.proses( Xmouse, Ymouse)){
        if(jawaban == c) benar = _benar;
        else benar = _salah;
    }
    else if( D.proses( Xmouse, Ymouse)){
        if(jawaban == d) benar = _benar;
        else benar = _salah;
    }
...

Untuk memastikan jawaban yang diklik itu benar, terlebih dahulu penanganan pada mouse yaitu dengan memperoleh koordinat X, dan Y serta penekanan tombol kiri (tahap 1 pada potongan kode diatas). Setelah bahan-bahan yang dibutuhkan telah siap, lalu memeriksa setiap tombol dengan fungsi "proses" yang dimilikinya (kelas tombol) - tahap 2. Dikarenakan variabel klikKiri adalah variabel global. Sehingga pemeriksaan tombol kiri sudah tertekan atau belum tidak tampak pada kode diatas tetapi terletak pada fungsi proses pada kelas tombol. Saran jangan terlalu banyak membuat variabel global atau anda akan pusing ketika para serangga (bug) datang (-.-) . Jika area tombol benar-benar terklik maka selanjutnya memeriksa apakah nilai yang dimiliki tombol sama dengan jawaban. Jika iya maka akan terjadi pengaturan pada var benar. Fungsi utama var benar ini untuk menampilkan gambar benar (tanda bulat hijau) atau salah (tanda silang merah). Kurang lebih seperti itu program ini bekerja .

- krofz

Wednesday, 11 May 2011

Ayo Menghitung Cepat (1)

Gambar 1. 1 x 1 = 2?

Akhirnya update juga blognya hehehe....  . Setelah sekian lama 'cuti'  dalam dunia pembloggeran hahaha. Kali ini kita akan membuat program kuis dengan tema hitung-hitungan. Kita mulai dengan yang sederhana terlebih dahulu dengan melakukan perkalian antara 2 buah bilangan. Nggak perlu basa-basi lagi, berikut ini link download program dan source code-nya :

Link : http://www.mediafire.com/?b49hcpoyp23246b
Size : 564.03 KB

Konsep layoutnya sederhana seperti gambar 1 diatas. Pada bagian tengah ditampilkan poin yang dimiliki dan pertanyaan bilangan yang dikalikan. Lalu dibawahnya terdapat 4 buah tombol jawaban yang berbeda nilainya (ya iyalah... ). Tidak seperti program kuis lainnya yang menampilkan huruf A, B, C, atau D disini tidak. Kenapa tidak? Karena belum saya buat hehehe. Jika anda masih kesulitan dalam pembuatan tombol pada program ini silahkan lihat kembali artikel Klik Tombolnya. Untuk penulisan teksnya sendiri (dengan TTF) jika masih mengalami kendala silahkan lihat kembali artikel Kapal Luar Angkasa yang membahas pengaturan library SDL_TTF dan penggunaannya.

Untuk membuat jawabannya dinamis baik dalam hal nilai dan juga penempatannya (A,B,C, atau D) kita perlu sedikit nilai acak, yang terdapat pada kode berikut:


...
   int _x = 1+poin/60+rand()%4+(poin/30),
       _y = 1+poin/60+rand()%4+(poin/30);
 
   jawaban = _x*_y;

   int _z = _x+_y;
   a=jawaban+1+rand()%_z;
   b=jawaban+3+rand()%_z;
   c=jawaban-1-rand()%_z;
   d=jawaban-3-rand()%_z;

   int _start = rand()%4;
   switch(_start){
      case 0: a=jawaban; break;
      case 1: b=jawaban; break;
      case 2: c=jawaban; break;
      case 3: d=jawaban; break;
      default:;
   }
...

Setelah a, b, c, dan d memperoleh nilainya masing-masing yang masih acak dan salah, maka dimulai pemilihan posisi untuk menentukan dimana jawaban akan diletakkan. Untuk mempermudah penggunaan fungsi-fungsi yang biasa digunakan seperti SDL_Surface *memuat(std::string namafile, int r, int g, int b), atau fungsi semacamnya. Maka ada baiknya kita pisahkan file ke dalam file terpisah dalam hal ini file "FungsiUmum.cpp". Sehingga sewaktu-waktu ada program yang membutuhkan fungsi yang sama cukup dengan memanggil FungsiUmum.cpp.

Selanjutnya akan saya bahas lagi sedikit tentang proses pemilihan jawabannya. Program ini masih jauh dari sempurna terlebih hanya melakukan perkalian 2 bilangan, untuk itu kritik dan saran anda sangat dinantikan :D .

- krofz

Next Part II
Update (12-12-21) : Download Link

Wednesday, 23 March 2011

Exception : Tangkap Errornya!

Exception atau jika diterjemahkan adalah 'pengecualian' adalah salah satu cara yang menangkap (catch) atau bereaksi terhadap sesuatu yang tak terduga seperti Runtime Errors. Pada umumnya kita mengatasi error dengan kondisi 'if'. Lalu bagaimana error ini ditangani oleh exception. Bagaimana cara kerjanya? Ia akan mengubah alur pada saat eksekusi program, dengan melempar (throw) sebuah objek tertentu yang memiliki informasi untuk alur yang baru. Untuk lebih jelasnya perhatikan kode berikut:


#include <iostream>

using namespace std;

int main(){
    try{
        cout<<"Masukkan angka antara 0-100: ";
        int a; //a = angka
        cin>>a;
        if( a > 100 || a < 0) throw a;
        cout << "\nAngka yang anda masukkan " << a << " dan berjalan normal";
    }
    catch( int ga){ //ga = get angka
        cout << "\nAngka yang tak terduga!! adalah " << ga;
    }
    return 0;
}

Program diatas akan meminta user memasukkan angka, lalu dengan kondisi if (wah pake if juga ternyata.. ) diperiksa apakah nilai tidak diantara 0-100. Jika nilainya diatas 100 (contoh 200) atau dibawah 0 maka alur program akan dilempar kepada bagian yang akan menangkap , yaitu keyword catch . Tetapi kita juga harus teliti dalam penggunaannya karena jika kita salah melempar tipe data yang sesuai maka program bisa langsung ngambek (alias error). Seperti contoh berikut ini:


#include <iostream>

using namespace std;
int main(){

    //1. Disini akan berjalan lancar
    try{
        throw 20;
    }
    catch( int ga){ //ga = get angka
        cout << "\nAngka yang tak terduga!! adalah " << ga;
    }

    //2. BE CAREFULL!!
    //kode berikut ini akan membuat error program!
    try{
        throw 'a';
    }
    catch( int ga2){
        cout << "\nAngka yang tak terduga!! adalah " << ga2;
    }

    return 0;
}

Pada try kedua terlihat bahwa data yang dilempar adalah tipe char, karena yang ditangkap hanya tipe integer maka program akan error. Mungkin terbesit sebuah tanya mengapa bisa terjadi error padahal tugas utamanya adalah untuk menangkap error , sungguh ironis. Sehingga perlu ditambahkan penangkapan yang bersifat universal, seperti pada kode berikut ini:


...
    try{
        throw 'a';
    }
    catch( int ga2){
        cout << "\nAngka yang tak terduga!! adalah " << ga2;
    }
 catch(...){
  cout << "\nSungguh terlalu...";
 }
...

Sampai disini kita sudah mengetahui dasar-dasar exceptions. Terlihat sedikit ribet menggunakan Exceptions, tetapi suatu teknik atau cara bahkan disini keyword untuk C++ tidak mungkin diciptakan tanpa ada manfaatnya. Begitu juga dengan exceptions ini, mungkin kita hanya belum terlalu mengerti fungsinya lebih dalam. Yang terpenting bijaksanalah dalam menggunakannya .

- krofz

Monday, 28 February 2011

Tile Map dengan SDL (4)

"001, 002, 003, ... 999" + ".mymap"



Seperti janji saya sebelumnya, maka langsung saja kita download saja program dan source codenya pada link berikut ini.

Link : http://www.ziddu.com/download/13984636/49_Tile_Map.v0.2.7z.html
Size : 371.05 KB
Control : Use Arrow Up and Down.

Perhatikan fungsi diatas fungsi utama (main), yaitu 'bool setPolaTile(int _nomor)'. Sesuai namanya ia akan mengatur pola dari ubin-ubin yang akan menghias peta kita . Didalam fungsi ini kita akan memanggil file yang telah ditentukan, lalu nilai-nilai dalam file tersebut dimasukkan ke dalam array pola (yang sekarang telah menjadi variabel global). Terlihat bahwa parameter yang digunakan bertipe int atau bilangan bulat, ini untuk memudahkan pemanggilan file. Contoh 'setPolaTile(15)', yang berarti memanggil file peta ke 15 (015.mymap). Kenapa ada nolnya? seperti '009.mymap', '015.mymap', dst. Dibuat agar lebih rapi saja hehehe (atau malah lebih ribet. ) . Sebelum kita 'asal' panggil file dengan ifstream, terlebih dahulu nilai dari parameter fungsi (var _nomor) kita konversikan karena masih bertipe bilangan bulat. Sedangkan pengisian lokasi file pada ifstream harus bertipe string atau const char*. Dan tipe data stringstream berkerja disini, ia akan mengonversikan angka ke string atau sebaliknya.

Selanjutnya dengan variabel _namaFile, kita tampung terlebih dahulu string yang berisi lokasi file. Dengan inisialisasi awal berisi "Map/" menandakan file yang dituju ada dalam suatu folder, yaitu folder Map. Selanjutnya kita pastikan keberadaan file ini eksis atau tidak dengan pengecekkan kondisi '!= NULL', jangan sampai ia kurang pergaulan karena ketidak eksis-annya . Setelah file ditemukan lalu memasukkan nilai-nilainya ke array pola. Ibarat seorang turis yang berkunjung turis ini harus diperiksa terlebih dahulu isi kopernya, jangan bertanya apa yang harus dilakukan jika dia nggak bawa koper . Begitu juga dengan nilai-nilai ini, harus diperiksa kebenarannya:


   //jika nilainya tidak sesuai
   _file >> pola[c][d];
   if( pola[c][d] < 0 ) pola[c][d] = 0;
   else if( pola[c][d] > MAX_TILE ) pola[c][d] = MAX_TILE-1;

Kode diatas juga untuk mencegah nilai-nilai dasyat karena jumlah nilai pada file terlalu sedikit atau mengandung karakter (yang umumnya diterjemahkan dengan angka-angka besar). Serta jika file hanya memiliki beberapa nilai saja:

Gambar 1. Ada yang salah dengan file ini!

Hmm, dari percobaan yang dilakukan ternyata program akan berhenti mentransfer nilai-nilai tersebut jika kondisinya seperti diatas. Misal jika ditengah jalan ketemu si a atau berada pada ujung file padahal belum berakhir, maka tidak terjadi perpindahan nilai. Tetapi pengulangan tetap berlangsung sampai akhir (sebanyak TilePerbaris*TilePerkolom). Sehingga nilai yang digunakan masih nilai pada kondisi terakhir. Untuk mengganti file peta dapat menggunakan tombol panah atas dan bawah.

Untuk tata letak clip / potongan gambarnya sendiri, belum saya tata dengan rapi ( Maaf untuk kemalasan saya ). Jika teman-teman ada yang ingin menatanya dan menambah potongan gambarnya dan memposting link download atau semacamnya disini saya sangat berterima kasih, maju terus Programmer Indonesia!. Terakhir baru nyadar kalau source code cpp selama ini disertakan ternyata masih menggunakan judul artikel yang lama pada bagian komentar diawal (masih pakai yang "Efek Transparan pada Gambar") *dodol .

- krofz

Friday, 25 February 2011

Tile Map dengan SDL (3)

Agar Lebih Praktis.


Tulisan ini merupakan lanjutan dari:
Tile Map dengan SDL (1)
Tile Map dengan SDL (2)

Banyak kekurangan pada kode sebelumnya, salah satunya adalah saat kita menampilkan tile-tile tersebut:


...
   for(int c=0;c < TilePerkolom;c++){
      for(int d=0;d < TilePerbaris;d++){
         terapinGbr(d*ukuranTile,c*ukuranTile, tileSet, screen, &clipTile40x40[pola[c][d]]);
      }
   }
...

Dimana letak kesalahannya? Yaitu saat menampilkan nilai pada array pola[][]. Misalkan kita menampilkan potongan gambar (clipTile40x40) yang tidak sesuai. Seperti diketahui potongan ini dimulai dari angka 0 sampai 3 (berjumlah 4 potong). Apa yang terjadi jika nilainya dibawah 0 (-1,-2,dst) atau diatas 3 (4,5,dst)? Untungnya program masih dapat berjalan hanya saja potongan gambar ini menjadi aneh . Sehingga kita perlu memperbaiki kode tersebut:


...
   for(int c=0;c < TilePerkolom;c++){
      for(int d=0;d < TilePerbaris;d++){

         int _temp = pola[c][d];
         if( pola[c][d] < 0 ) _temp = 0;
         else if( pola[c][d] > MAX_TILE ) _temp = MAX_TILE-1;

         terapinGbr(d*ukuranTile,c*ukuranTile, tileSet, screen, &clipTile40x40[ _temp]);
      }
   }
...

Dapat dilihat bahwa jika nilainya tidak sesuai, maka akan disesuaikan (ya iyalah... kalau nggak error lagi ntar ). Intinya kita mencegah nilai-nilai yang tidak semestinya yang dapat menyebabkan program 'Crash'. Ini baru dari sisi keamanan nilai, bagaimana dengan sisi yang lainnya? Misal kemudahan pengembangan Map (peta). Disini jika kita ingin merubah nilai-nilainya maka perlu melakukan proses build ulang, atau nilainya berada pada tubuh program (secara Hardcore). Yang tentu kurang efisien, terlebih ketika melibatkan banyak library dan banyak perubahan tata letak gambar pada peta. Sehingga kita perlu sedikit modifikasi. Yang diperlukan adalah sebuah file yang menyimpan deretan nilai peta kita, seperti contoh file berikut ini (kita namakan 001.mymap):


2 2 1 1  2 3 1 1  2 1 1 1  3 3 1 1
2 1 1 1  2 3 1 1  2 1 1 1  3 3 1 1 
1 1 1 1  2 3 1 1  1 1 1 1  3 3 1 1 
1 1 1 1  2 3 1 1  2 1 2 1  1 1 1 3 
1 1 1 1  1 1 2 1  1 1 2 1  3 3 1 3 
1 1 1 1  2 3 1 1  2 1 1 1  3 2 1 1  

2 1 2 3  1 2 1 1  2 1 1 1  1 1 2 3 
1 1 1 1  1 1 1 1  3 1 1 1  1 3 1 1 
1 1 1 1  1 3 1 1  2 1 1 1  3 3 1 3 
3 3 1 1  2 1 1 1  1 1 1 1  1 3 1 1 
1 0 3 5  2 3 2 2  2 1 1 1  3 1 2 2 
0 1 3 3  3 3 1 1  3 1 1 1  3 1 1 1 

Dengan memanggil sebuah file tentu kita sudah dapat membuat kode-nya lalu menampilkan nilai-nilai dari file 001.mymap diatas dong? . Disini kita melakukannya secara Softcore, yaitu tanpa perlu build ulang source code. Dengan bermodalkan notepad kita sudah dapat merubah nilai-nilai diatas (jangan bingung dengan ektensi '.mymap' hehe..). Jika anda belum bisa maka akan kita bahas di tulisan selanjutnya hehehe... berikut program dan source codenya. Happy Coding!

- krofz

Monday, 31 January 2011

Tile Map dengan SDL (2)


Gunakan Array!


Tulisan ini merupakan lanjutan dari:
Tile Map dengan SDL (1)

Kita mulai menjelajahi dari variabel global dibawah pemanggilan file header. Variabel-variabel ini akan memudahkan kita dalam perawatan atau penambahan nilai-nilai pada program. Contohnya variabel ukuranTile yang bertipe 'integer konstan' berguna jika sewaktu-waktu ukuran Tile Set pada gambar berupa, misalkan sebelumnya 40 menjadi 30 maka secara otomatis semua nilai yang harus digantipun berubah. Sehingga program kita ini telah didesain sedemikian rupa agar kita hanya perlu mengubah nilainya (var ukuranTile) maka penempatan posisi (x,y) untuk penggambilan ukuran clip (lebar atau panjang) menjadi otomatis menyesuaikan. Variabel selanjutnya MAX_TILE, TilePerbaris, dan TilePerkolom memiliki ciri-ciri yang sama seperti sebelumnya, yaitu kemudahan dan kenyamanan dalam berkoding hehehe . MAX_TILE berfungsi untuk menyatakan banyaknya tile clip atau potongan-potongan gambar dalam satu file gambar. Nilai-nilai atau koordinat potongan gambar ini disimpan pada variabel SDL_Rect clipTile40x40[MAX_TILE]. Pengaturan koordinat untuk setiap potongan gambar ini terdapat pada fungsi void aturClip(). Dan lihat! pengaturan potongan gambar ini menjadi lebih mudah dengan ukuranTile, tak perlu mengganti-ganti nilainya jika terjadi perubahan cukup ganti ukuranTile. Dan pastinya jangan lupa memanggil fungsi ( "aturClip()" ) ini di dalam fungsi main, jika tidak ingin program menjadi aneh-aneh.

Lansung saja kita ke bagian "DRAWING TIME". Agar layar (screen) program tidak menjadi aneh saat proses penggambaran kita perlu mengisinya dengan SDL_FillRect(), kita isi dengan warna hitam. Selanjutnya kita mulai menggambar "Ubin"-nya satu persatu. Yang diperlukan hanyalah array 2 dimensi:


...
   int pola[TilePerkolom][TilePerbaris]
      = {{0,0,1,0, 2,3,0,1, 2,1,0,0, 3,3,0,1},
         {0,0,1,0, 2,3,0,1, 2,1,0,0, 3,3,0,1},
         {0,0,1,0, 2,3,0,0, 0,0,0,0, 3,3,0,1},
         {0,1,1,0, 2,3,0,1, 2,1,2,0, 0,0,0,3},
         {0,0,1,0, 1,0,2,1, 0,1,2,1, 3,3,0,3},
         {0,0,1,0, 2,3,0,1, 2,1,0,0, 3,2,0,1},

         {0,0,1,0, 2,3,0,1, 2,1,0,0, 1,3,0,1},
         {0,0,0,0, 0,0,0,1, 3,1,0,0, 0,3,0,1},
         {0,0,1,0, 0,3,0,1, 2,1,0,0, 3,3,0,3},
         {0,2,1,0, 2,0,0,1, 0,1,0,0, 0,3,0,1},
         {0,2,0,0, 2,3,2,2, 2,1,0,0, 3,0,2,2},
         {0,1,1,1, 1,3,0,1, 3,1,0,0, 3,1,0,1}};
...    

Dengan ukuran setiap dimensinya sesuai dengan banyaknya kolom atau baris ubin. Dapat dilihat bahwa array 2 dimensi ini seperti sebuah table. Yang artinya variabel pola[16][12] bukan memiliki 28 (16 + 12) nilai bilangan bulat yang berbeda melainkan 192 nilai (16 x 12). Untuk pengisian nilai-nilainya dapat menggunakan operator for atau manual seperti diatas. Jika menggunakan cara manual kita harus teliti jangan sampai kompiler ngomel-ngomel saat proses kompilasi / build. Cara otomatis memang terdengar menjanjikan tapi hanya untuk penggunaan pola peta yang sistematis, simetris atau bahkan acak (random). Intinya tak semudah namanya, 'otomatis!'. Nilai pada array ini sesuai dengan potongan gambar yang kita buat sebelumnya:

Gambar 1. Potongan gambar.

Perlu diperhatikan bahwa indeks array dimulai dengan 0, sehingga gambar nomor 1 diisi dengan nilai 0. Jika ingin menambahkan gambar-gambar atau potongan baru cukup dengan merubah nilai MAX_TILE. Misal menjadi 12 maka program akan menggambil potongan gambarnya menjadi seperti pola berikut:

Gambar 2. Jika dipotongan 12.

Ini karena pengaturan nilai x pada fungsi aturClip(). Untuk lebih jelasnya lihat lagi kode pada fungsi tersebut sebagai berikut:


...
    for(int c=0;c < MAX_TILE;c++){
        clipTile40x40[c].x=(c%2)*ukuranTile;
        clipTile40x40[c].y=(c/2)*ukuranTile;
        clipTile40x40[c].w=ukuranTile;
        clipTile40x40[c].h=ukuranTile;
    }
...

Tentu masih banyak yang harus diperbaiki disini terlebih penggambilan potongan gambarnya, yang semakin banyak justru semakin panjang kebawah. Dan saya yakin kalian pasti dapat menyelesaikannya, bukan begitu? - "My Clue", ubah angka 2 pada operasi(c%2) dan (c/2) menjadi banyaknya gambar perbaris. Yang perlu diperhatikan saat membuatnya (gambar tile) menjadi berdimensi kotak, tidak seperti sebelumnya yang seperti balok panjang kebawah. Adalah posisi gambar dibawahnya (contohnya gambar nomor 3 dan 4) dipindahkan kesamping gambar nomor 2. Ini jika algoritma yang digunakan masih sama seperti sebelumnya hanya dirubah nilai pada operasi (c%2) dan (c/2). Sehingga terlihat seperti gambar berikut:

Gambar 3. Penempatan yang tepat untuk potongan gambarnya, a). Anda punya Algoritma potongan gambar sendiri?, dan b). Algoritma ini sangat mudah yaitu dari baris atas ke bawah.

Mengapa? karena jika sudah mendesain peta dengan nomor-nomor gambar tertentu pada array dan posisi tertentu pada potongan gambar, hasil yang diperoleh akan menjadi aneh. Ya, kalian bisa melihatnya kan?. Semoga tutorial ini bermanfaat... .

- krofz

Friday, 28 January 2011

Tile Map dengan SDL (1)

Luasnya 16 x 12


Tile Map, atau jika diubah menjadi bahasa Indonesia-nya adalah "Peta Ubin" merupakan sebuah lingkungan game (berupa peta/area permainan) yang digambarkan berdasarkan pola seperti ubin dengan ukuran tertentu secara berulang-ulang. Berbeda dengan penggambaran background biasa (contohnya seperti game Zuma atau Plants VS Zombie), game ini memiliki kelebihan dan kekurangan. Kelebihannya yaitu ukuran game dapat dikompres / dikecilkan karena cukup dengan 2 atau beberapa gambar kecil (berbentuk ubin/kotak) lingkungan gamepun dapat dibuat. Kekurangannya lingkungan game akan terlihat kaku dan perlu lebih banyak gambar untuk dapat menciptakan lingkungan yang lebih halus dan realistis. Tidak seperti penggambaran Background biasa yang dapat diciptakan dengan cepat, tapi dengan konsekuensi ukuran yang besar (pada umumnya):

Gambar 1. Game Warlord IV dengan Battle menggunakan penggambaran Background biasa (sumber: Internet).

Jika anda suka bermain game Nitendo di era 90-an (di Indonesia baru ada di tahun itu kali yah? ) tentu kenal dengan game Mario Bros, kalau belum kenal, silahkan kenalan dulu :

Gambar 2. Mario Bros, salah satu game yang me-Legenda! (sumber: Internet).

Dapat dilihat cukup dengan 3 gambar tile tersebut (tidak termasuk rumput dan pipa) sudah dapat menciptakan lingkungan permainan untuk sih paman Mario. So, langsung saja kita mulai dari yang sederhana, berikut program beserta source code yang diperlukan:

Link : http://www.ziddu.com/download/13552658/46_Tile_Map.a.7z.html
Size : 247.01 KB

Jalankan program tersebut maka akan terlihat hasilnya seperti berikut (tanpa angka 1-16 kesamping, dan 1-12 kebawah):

Gambar 3. Tile Map pertama kita!

Pada tulisan selanjutnya akan kita bahas kode-kode yang mungkin masih amat sangat asing dan aneh ini...

- krofz
 

back to top

back to top