Membuat Game Racing Sederhana Dengan C++ dan Libsigil - Iqbal Pambudi

Latest

7/26/2018

Membuat Game Racing Sederhana Dengan C++ dan Libsigil

Halo teman-teman apa kabar, sudah lama juga tidak posting baru kali ini ada waktu. Hmm kali ini saya akan membuat game sederhana yaitu game racing dengan bahasa C++. "Terus Libsigil itu apa ?" Oke jadi gini, Libsigil adalah salah satu External Library yang dapat kita gunakan, ada juga SFML, OpenGL dll. Kenapa saya pakai Libsigil ? karena kebetulan dapat tugas yang berhubungan dengan ini maka saya sekalian tulis dan berbagi di blog ini. Oke tanpa basa-basi lagi, sepertia biasa kita siapkan alat tempurnya

Alat dan Bahan

  1. Visual Studio (Saya menggunakan Visual 2012)
  2. Libsigil (download disini) 
  3. Gambar objek Mobil, Truk, Coin dan Jalan (pastikan dalam format png dan letakan pada working folder project kalian, kalau saya pribadi saya buatkan folder dengan nama data pada working directory)
  4.  Sound untuk suara mobil tabrakan dan background music (letakan pada working directory)
Working directory saya
Isi dari folder data


Step 1. Cara Pasang Libsigil pada Visual Studio 

  1. Pertama  kalian buka Visual Studio
  2. Buat Project baru misalkan "Need For Speed 2018" wkwkw
  3. Setelah itu Pilih menu Debug dan "Need For Speed 2018 Property"
  4. Pilih pada C/C++ dan pilih General, lalu di sebelah kanan akan ada beberapa pilihan lalu pada Additional Include Directories kalian ubah path nya dan arahkan ke folder Include pada LibSigil (Ekstrak dulu LibSigil)
    Memasang Include Directories

  5. Setelah itu kita akan memasang Library Sigilnya, caranya yaitu Klik menu Linker disebelah kiri

  6. Setingan terakhir yaitu menambahkan sigil.lib ke program. Caranya yaitu masih di menu Linker tapi pilih Input dibawah General lalu di Additional Depedencies edit dan ketikan sigil.lib setelah itu Apply dan Ok. Akhirnya selesai juga seting External Librarynya, Oke kita lanjut ke pembuatan program

 Step 2. Membuat Program 

Pada project kali ini kita akan membuat 6 file header dan 5 file cpp yang terdiri dari
  1. car.h (untuk pendefinisian objek mobil dan merupakan turunan dari object.h)
  2. truck.h (untuk pendefinisian objek truk dan merupakan turunan dari objek.h)
  3. object.h (sebagai base class yang datanya diwariskan ke car.h dan truck.h)
  4. misc.h (sebagai objek tambahan berupa pepohonan,coin, dan bahan bakar)
  5. global.h (sebagai tempat pendefinisian texture pada game)
  6. game.h (sebagai fungsi untuk memanggil game start, run dan end)

Lalu untuk file cpp nya terdiri dari
  1. car.cpp (berisi konfigurasi untuk objek mobil)
  2. truck.cpp (berisi konfigurasi untuk truk)
  3. misc.cpp (berisi konfigurasi untuk objek tambahan)
  4. game.cpp (berisi tempat semua objek objek dalam game disatukan)
  5. main.cpp (fungsi main yang menjalankan state game)

Proses Coding
  • Pada Visual Studio bagian kanan klik kanan pada Header Files lalu add new item dan buat header file dengan nama object.h. File object.h ini digunakan untuk class induk untuk mobil dan truk. Ketikan kode seperti dibawah 
  • 
    //---------Object.h-------------
    #ifndef OBJECT
    #define OBJECT
    
    class object
    {
    protected:
     double posX;
     double posY;
     double velX;
     double velY;
    public:
    
     double getX() { return posX;}
     double getY() { return posY;}
    
     virtual void draw()= 0;
     virtual void update()=0;
     virtual void loadTexture() = 0;
    };
    #endif
    
    


  • Kode untuk file car.h, File ini berfungsi untuk membuat definisi dari objek mobil. Masukan kode berikut
  • //---------CAR.h---------------
    #ifndef CAR
    #define CAR
    
    #include "object.h"
    
    class Car: public object
    {
    private:
     int texture;
    public:
     Car(double px,double py);
     void draw();
     void update();
     void control(double cx);
     void loadTexture();
    };
    #endif
    


  • Kode untuk truck.h , Berfungsi untuk pendefinisian objek truck. Masukan kode 
  • 
    //------------TRUCK.h------------
    #ifndef GLOBAL
    #define GLOBAL
    
    
    const double SCR_W =480;
    const double SCR_H =640;
    
    //texture
    const char TEX_CAR[]= "data\\car_red.png";
    const char TEX_CAR2[]= "data\\car_blue.png";
    const char TEX_TRUCK[]= "data\\truck_1.png";
    const char TEX_ROAD[]= "data\\road.png";
    const char TEX_TREE[]= "data\\tree.png";
    const char TEX_COINS[]= "data\\coins.png";
    const char TEX_GASOLINE[]= "data\\gasoline.png";
    const char TEX_CAR_PURPLE[]= "data\\carpurple.png";
    //font
    const char FNT_STYLE[]= "data\\whitrabt.ttf";
    
    //sfx
    const char SFX_MUSIC[]= "data\\music.wav";
    const char SFX_CRASH[]= "data\\crash.wav";
    const char SFX_COINS[]= "data\\coins.wav";
    #endif

  • Kode untuk misc.h File ini berisikan beberapa tambahan objek seperti pohon, coin, dan gasoline. Masukan kode
  • 
    //------------MISC.h------------
    #ifndef MISC
    #define MISC
    
    #include "object.h"
    
    class misc:public object
    {
    private:
     double misc_spd;
     int MiscTexCoins;
     int MiscTex;
     int MiscTexGasoline;
    public:
     misc(double x,double y,double v);
     void draw();
     void drawcoins();
     void drawgasoline();
     void update();
     void updatecoins();
     void updategasoline();
     void reset();
     void resetCoins();
     void resetGasoline();
     void loadTexture()override;
     void loadTextureCoins();
     void loadTextureGasoline();
     void setMiscSpd(double s);
    };
    #endif
    

  • Kode untuk global.h File ini berisikan pendefinisian beberapa texture pada game. Masukan kode
  • 
    //------------GLOBAL.h------------
    #ifndef GLOBAL
    #define GLOBAL
    
    
    const double SCR_W =480;
    const double SCR_H =640;
    
    //texture
    const char TEX_CAR[]= "data\\car_red.png";
    const char TEX_CAR2[]= "data\\car_blue.png";
    const char TEX_TRUCK[]= "data\\truck_1.png";
    const char TEX_ROAD[]= "data\\road.png";
    const char TEX_TREE[]= "data\\tree.png";
    const char TEX_COINS[]= "data\\coins.png";
    const char TEX_GASOLINE[]= "data\\gasoline.png";
    const char TEX_CAR_PURPLE[]= "data\\carpurple.png";
    //font
    const char FNT_STYLE[]= "data\\whitrabt.ttf";
    
    //sfx
    const char SFX_MUSIC[]= "data\\music.wav";
    const char SFX_CRASH[]= "data\\crash.wav";
    const char SFX_COINS[]= "data\\coins.wav";
    #endif
    

  • Kode untuk game.h File ini berisikan fungsi pemanggilan namespace pada game.cpp ke main.cpp. Masukan kode
  • 
    //------------GAME.h------------
    #ifndef OGAME
    #define OGAME
    
    namespace game
    {
     void init();
     void run();
     void end();
    }
    #endif
    

  • Kode untuk game.cpp File ini berisikan konfigurasi untuk objek mobil. Masukan kode
  • 
    //------------CAR.cpp------------
    #include "car.h"
    #include "object.h"
    #include "sl.h"
    #include "global.h"
    
    Car::Car(double px,double py)
    {
     posX=px;
     posY=py;
    }
    
    void Car::loadTexture()
    { 
      texture = slLoadTexture(TEX_CAR); 
    }
    
    void Car::draw()
    {
     slSprite(texture,posX,posY,50,85);
    }
    
    void Car::update()
    {
     posX+=velX;
     if(posX-23 <=30 || posX+20 >=360)
      velX*=-0.5;
    }
    
    void Car::control(double cx)
    {
     velX+=cx;
    }
    

  • Kode untuk truck.cpp File ini berisikan konfigurasi objek truk. Masukan kode
  • 
    //------------TRUCK.cpp------------
    #include "object.h"
    #include "truck.h"
    #include "global.h"
    #include <sl.h>
    #include <cstdlib>
    
    
    truck::truck(double px,double py,double vx)
    {
     posX=px;
     posY=py;
     velX=vx;
    }
    
    void truck::loadTexture()
    {
     texture = slLoadTexture(TEX_TRUCK);
    }
    
    void truck::draw()
    {
     slSprite(texture,posX,posY,50,85);
    }
    
    void truck::update()
    {
     posY+=truck_spd;
     if(posY <= -40)
      {
       reset();
       truck_spd-=0.2;
      } 
    }
    
    //fungsi untuk reset posisi truk secara random
    void truck::reset()
    {
     int arr[]={66,132,200,266};
     int random;
     random=rand() % 4 ;
     posY=700;
     posX=arr[random];
    }
    
    void truck::setTruckSpd(double s)
    {
     truck_spd=s;
    }
    

  • Kode untuk misc.cpp File ini berisikan konfigurasi objek tambahan seperti pohon,coin dan gasoline. Masukan kode
  • 
    //------------MISC.cpp------------
    #include "misc.h"
    #include <sl.h>
    #include "global.h"
    #include <cstdlib>
    
    misc::misc(double x,double y,double v)
    {
     posX=x;
     posY=y;
     velY=v;
    };
    
    void misc::loadTexture()
    {
     MiscTex = slLoadTexture(TEX_TREE);
    }
    
    void misc::loadTextureCoins()
    {
     MiscTexCoins=slLoadTexture(TEX_COINS);
    }
    
    void misc::loadTextureGasoline()
    {
     MiscTexGasoline=slLoadTexture(TEX_GASOLINE);
    }
    
    void misc::draw()
    {
     slSprite(MiscTex,posX,posY,100,100);
    }
    
    void misc::drawcoins()
    {
     slSprite(MiscTexCoins,posX,posY,40,40);
    }
    
    void misc::drawgasoline()
    {
     slSprite(MiscTexGasoline,posX,posY,40,40);
    }
    
    void misc::update()
    {
     posY+=misc_spd;
     if(posY <= -40)
      {
       reset();
      } 
    }
    void misc::updatecoins()
    {
     posY+=misc_spd;
     if(posY <= -40)
      {
       resetCoins();
      } 
    }
    
    void misc::updategasoline()
    {
     posY+=misc_spd;
     if(posY <= -40)
      {
       resetGasoline();
      } 
    }
    
    void misc::setMiscSpd(double s)
    {
     misc_spd=s;
    }
    
    void misc::reset()
    {
     posY=700;
     int arr[]={365,30};
     int ran=rand() % 2 ;
     posX=arr[ran];
    } 
    
    void misc::resetCoins()
    {
     int arr[]={100,132,200,245};
     int ran=rand() % 4 ;
     posY=2000;
     posX=arr[ran];
    }
    
    void misc::resetGasoline()
    {
     int arr[]={100,132,200,245};
     int ran=rand() % 4 ;
     posY=3000;
     posX=arr[ran];
    }
    

  • Kode untuk game.cpp File ini berisikan semua objek yang telah kita buat dan akan digabungkan menjadi 1. Mohon tetap tenang dan jangan pusing atau panik wkwkwk. Masukan kode
  • 
    //------------GAME.cpp------------
    #include "car.h"
    #include "truck.h"
    #include "global.h"
    #include "misc.h"
    
    #include <sl.h>
    #include <iostream>
    #include <string>
    #include <cmath>
    #include <windows.h>
    //====================================//PEMBUATAN OBJEK\\===============================
    Car car(200,100);    //car
    truck vehicle(200,400,2);  //vehcile
    truck vehicle2(250,600,2.5); //vehicle 2
    
    misc tree1(365,700,1);   //tree 1
    misc tree2(365,900,1);   //tree 2
    misc tree3(365,1100,1);   //tree 3
    
    misc coins(66,750,2);   //coins
    misc gasoline(100,2500,2);  //gasoline
    //=================================================================================
    
    //state game
    enum GameState:int {Start, CarSelect,Play, Pause, GameOver};
    GameState state = GameState::Start;
    
    int road;
    int font;
    int sfxmusic;
    int sfxcrash;
    int sfxcoins;
    int IcoCoin;
    int IcoGasoline;
    std::string player;
    
    //score
    int score=0;
    int count=0;
    int hiscore = 0;
    int fuel=20;
    
    //prototype
    void info();
    void key();
    bool isCollide(object* e1, object* e2,const double h);
    
    namespace game
    {
    void init()
     {
    
     //set name player
     std::cout << "  Your nickname: ";
     std::getline(std::cin, player);
     if (player == "")
     player = "Noname";
    
     //create windows
     std::cout <<  "  creating windows...\n";
     slWindow(480, 640, "Not For Speed 2018 v1.0", false);
     slSetBackColor(0, 0.4, 0.2);
    
     //load texture & font
     std::cout<<"  loading texture...\n";
     car.loadTexture();
     vehicle.loadTexture();
     vehicle2.loadTexture();
     tree1.loadTexture();
     tree2.loadTexture();
     tree3.loadTexture();
     coins.loadTextureCoins();
     gasoline.loadTextureGasoline();
    
     road=slLoadTexture(TEX_ROAD);
     font=slLoadFont(FNT_STYLE);
     IcoCoin=slLoadTexture(TEX_COINS);
     IcoGasoline=slLoadTexture(TEX_GASOLINE);
     slSetFont(font,20);
    
     //load audio
     std::cout<<"  loading audio...\n";
     sfxmusic=slLoadWAV(SFX_MUSIC);
     sfxcrash=slLoadWAV(SFX_CRASH);
     sfxcoins=slLoadWAV(SFX_COINS);
    
     //play game music
     slSoundLoop(sfxmusic);
    
     //set object speed
     vehicle.setTruckSpd(-3);
     vehicle2.setTruckSpd(-2);
     tree1.setMiscSpd(-1);
     tree2.setMiscSpd(-1);
     tree3.setMiscSpd(-1);
     coins.setMiscSpd(-4);
     gasoline.setMiscSpd(-6);
     }
    
    
    void run()
     {
     std::cout << "  Game: Run\n";
     while (!slShouldClose())
     {
    
      //draw road texrure
      slSprite(road,SCR_W/2,SCR_H/2,SCR_W,SCR_H);
    
      //draw car & vehicles texture
      car.draw();
      vehicle.draw();
      vehicle2.draw();
    
      //draw miscellaneous
      tree1.draw();
      tree2.draw();
      tree3.draw();
      coins.drawcoins();
      gasoline.drawgasoline();
    
      //draw info & key
      info();
      key();
    
      //state play
      if(state ==GameState::Play)
       {
       //update car & vehicle
         
       car.update();
       vehicle.update();
       vehicle2.update();
    
       //update miscellaneous
       tree1.update();
       tree2.update();
       tree3.update();
       coins.updatecoins();
       gasoline.updatecoins();
    
       //penghitung score
       count++;
       if(count==100)
        {
        score++;
        count=0;
        }
    
        if(count==30)
        {
        fuel--;
        }
    
        //mengecek apakah 2 objek bertabrakan
        if (isCollide(&car, &vehicle,50.0))
         {
         if(score>=hiscore)
          {
          hiscore=score;
          }
          slSoundPlay(sfxcrash);
          state = GameState::GameOver;
          std::cout<<"  *Game Over!\n";
         }
    
        if (isCollide(&car, &vehicle2,50.0))
         {
          if(score>=hiscore)
          {
          hiscore=score;
          }
          slSoundPlay(sfxcrash);
          state = GameState::GameOver;
          std::cout<<"  *Game Over!\n";
         }
        if (isCollide(&car, &coins,40.0))
         {
          score+=10;
          coins.resetCoins();
          slSoundPlay(sfxcoins);
         }
        if (isCollide(&car, &gasoline,40.0))
         {
          fuel+=5;
          gasoline.resetGasoline();
          slSoundPlay(sfxcoins);
         }
         if(fuel==0)
         {
          state = GameState::GameOver;
         }
    
        }
    
       slRender();
      }
    
     }
    
    void end()
    {
    std::cout<<"  Game End\n";
    }
    
    }
    void key()
    {
     if (state == GameState::Start)
     {
      if (slGetKey(SL_KEY_ENTER))
       state = GameState::Play;
     }
    
     else if (state==GameState::CarSelect)
     {
    
     }
    
     else if (state == GameState::Play)
     {
      if(slGetKey(SL_KEY_RIGHT))
       car.control(0.2);
      if(slGetKey(SL_KEY_LEFT))
       car.control(-0.2);
      if (slGetKey('P'))
       state = GameState::Pause;
     }
    
     else if (state == GameState::Pause)
     {
      // resume:
      if (slGetKey('R'))
      { 
       state = GameState::Play;
      }
     }
    
     else if (state == GameState::GameOver)
     {
      // replay:
      if (slGetKey('R'))
      {
       //reset all object
       score=0;
       fuel=20;
       state = GameState::Play;
       vehicle.reset();
       vehicle.setTruckSpd(-1.5);
       vehicle2.reset();
       vehicle2.setTruckSpd(-2);
       coins.resetCoins();
       gasoline.resetGasoline();
      }
     }
    
    }
    
    void info()
    {
     slSetFontSize(20);
     slSetTextAlign(SL_ALIGN_CENTER);
     slText(SCR_W-50,SCR_H-50, player.c_str());
     slSetFontSize(16);
     slSetTextAlign(SL_ALIGN_CENTER);
     slText(SCR_W-50, SCR_H - 100, "score");
     slText(SCR_W-50, SCR_H - 120, std::to_string(score).c_str());
     slText(SCR_W-50, SCR_H - 150, "hiscore");
     slText(SCR_W-50, SCR_H - 170, std::to_string(hiscore).c_str());
     slText(SCR_W-50, SCR_H - 210, "FUEL");
     slText(SCR_W-50, SCR_H - 230, std::to_string(fuel).c_str());
    
     if (state == GameState::Start)
     {
     // menampilkan instruksi:
     slSetForeColor(0.0, 0.0, 0.0, 0.7);
     slRectangleFill(SCR_W / 2.0, SCR_H / 2.0, SCR_W, SCR_H);
     slSetFontSize(16);
     slSetTextAlign(SL_ALIGN_CENTER);
     slSetForeColor(1.0, 1.0, 1.0, 1.0);
     slText(SCR_W / 2, 480, "Drive the Car so as not to crash");
     slText(SCR_W / 2, 460, "using LEFT or RIGHT key.");
     slSprite(IcoCoin,120,405,40,40);
     slSprite(IcoGasoline,120,350,30,40);
     slText(SCR_W / 2+25, 400, "Pick Coins for Extra Score");
     slText(SCR_W / 2+35, 350, "Pick Gasoline for Extra Fuel");
     slText(SCR_W / 2, 256, "Press ENTER to Start");
     }
     else if (state == GameState::GameOver)
     {
     // menampilkan Game Over dan perolehan score:
     slSetForeColor(0.0, 0.0, 0.0, 0.7);
     slSetFontSize(40);
     slSetTextAlign(SL_ALIGN_CENTER);
     slText(SCR_W / 2.0, SCR_H / 2.0, "Game Over");
     slSetForeColor(1.0, 1.0, 1.0, 1.0);
     slSetFontSize(16);
     slText(SCR_W / 2.0 - 10, SCR_H / 2.0 - 25, "Your score:");
     slText(SCR_W / 2.0 + 50, SCR_H / 2.0 - 25, std::to_string(score).c_str());
     slText(SCR_W / 2.0, SCR_H / 2.0 - 60, "Press 'R' to Replay");
      
     }
     else if (state == GameState::Pause)
     {
     // menampilkan informasi instruksi untuk resume game:
     slSetForeColor(1.0, 1.0, 1.0, 1.0);
     slSetFontSize(16);
     slSetTextAlign(SL_ALIGN_CENTER);
     slText(SCR_W / 2.0, SCR_H / 2.0, "Press R to Resume");
     }
     else if (state == GameState::Play)
     {
     // menampilkan informasi instruksi pause game:
     slSetForeColor(1.0, 1.0, 1.0, 1.0);
     slSetFontSize(16);
     slSetTextAlign(SL_ALIGN_RIGHT);
     slText(SCR_W - 15, SCR_H - 25, "Press P to Pause");
     }
    }
    
    //fungsi untuk mengecek tabrakan 2 objek
    bool isCollide(object* e1, object* e2,const double h)
    {
     return (std::hypot(e1->getX() - e2->getX(), e1->getY() - e2->getY()) <= h);
    }
    
    

  • Terakhir gan, Kode untuk main.cpp File ini cuma berisikan namespace dari game.h dan akan memnaggil fungsi start, run dan end pada game.cpp . Masukan kode
  • 
    //------------MAIN.cpp------------
    #include "game.h"
    
    int main()
    {
     game::init();
     game::run();
     game::end();
     return 0;
    }
    
    
    

  • Akhirnya selesai juga gan, setelah itu kita compile dan jalankan game nya.
    Nah itu dia sedikit tutorial dari saya, tapi sih kayaknya gak sedikit ya heheh, panjang beut tutorialnya. Mohon kritik dan saran perbaikan untuk game nya. Sekian dari saya, Terimakasih semoga berkah. Bagi yang mau coba game nya silahkan download disini. Untuk source code linknya disini

10 comments:

  1. Bro, gambar mobil, jalan, truk, dsb itu desain sendiri ya? Boleh bagi file .png-nya?

    ReplyDelete
    Replies
    1. Itu dibawah ada link source code sama assets" nya gan, boleh didownload

      Delete
  2. bro, pas di coba kok banyak yg error ya sintaksnya? Mohon pencerahannya bro!

    ReplyDelete
    Replies
    1. Coba dicek pesan errornya apa, pastikan juga library libsigilnya sudah terpasang di visual studio, kalo masih error coba dibawah udah tak kasih link source codenya

      Delete
  3. itukan terpisah ya file nya terus supaya bisa ngerunprogram nya jadi satu gimana gan

    ReplyDelete
    Replies
    1. nanti file yang terpisah-pisah itu di include di file game.cpp gan

      Delete