RSS

Jumat, 01 Oktober 2010

Pembuatan AI dengan implementasi C++ (part 2)

Setelah kemarin kita bahas tentang komponen dasar pembuatan AI sekarang kita langsung terjun ke pemrogramannya...Seperti yang sudah dikatakan sebelumnya bahwa untuk membuat sebuah game kita membutuhkan basic matematika dan fisika yang kuat terutama untuk vektor (lihat kembali buku aljabar liniernya..) saya akan beri satu contoh file header untuk vektor 2d...
Untuk membuat projectnya buka visual studio - new - project - pilih visual c++ -pilih win32 project - pilih windows application...
disitu sudah tersedia contoh untuk windows application dasar (kita dapat merubahnya nanti) silahkan tekan f5 untuk melihat menu windownya...

Lalu di menu solution explorer klik kanan - add - header file - tuliskan namanya menjadi Vector2D.h...

sudah?

nah sekarang kita harus menuliskan kode program untuk semua operasi vector yang nantinya akan dipakai untuk menggambar lapangan, pergerakan pemain, dan pergerakan bola...

Vector2D.h

#ifndef VECTOR2D_H
#define VECTOR2D_H

#include
#include
#include
#include
#include "utils.h" //tar dibuat file header utils.h

struct Vector2D
{
double x;
double y;

Vector2D(): x(0,0), y(0,0){} // ctor tanpa parameter
Vector2D(double a, double b) : x(a),y(b){} // ctor dengan parameter

void Nol() {x=0,0; y=0,0;}

bool isNol()const {return (x*x + y*y)< MinDouble;} // nah MinDouble itu nanti ada di utils.h

inline double Length()const;

inline double Lengthsq()const; // bedanya klo Lengthsq tanpa pke sqrt (akar)

inline void Normalize();

inline double Dot(const Vector2D& v2)const;

inline int Sign(const Vector2D& v2)const; // Vektor memiliki arah, tujuannya untuk
//Menentukan arah vektor positif atau negatif

inline Vector2D Perp()const;

inline void Truncate(double max);

//Jarak antara vektor
inline double Distance(const Vector2D &v2)const;

//akarkan Vektor diatas.
inline double DistanceSq(const Vector2D &v2)const;

inline void Reflect(const Vector2D& norm);

//kembalikan nilai vektor yang direverse
inline Vector2D GetReverse()const;


//Overload operator
const Vector2D& operator+=(const Vector2D &rhs)
{
x += rhs.x;
y += rhs.y;

return *this;
}

const Vector2D& operator-=(const Vector2D &rhs)
{
x -= rhs.x;
y -= rhs.y;

return *this;
}

const Vector2D& operator*=(const double& rhs)
{
x *= rhs;
y *= rhs;

return *this;
}

const Vector2D& operator/=(const double& rhs)
{
x /= rhs;
y /= rhs;

return *this;
}

bool operator==(const Vector2D& rhs)const
{
return (isEqual(x, rhs.x) && isEqual(y,rhs.y) );
}

bool operator!=(const Vector2D& rhs)const
{
return (x != rhs.x) || (y != rhs.y);
}

};

//---------------------------------------------------beberapa overload operator
inline Vector2D operator*(const Vector2D &lhs, double rhs);
inline Vector2D operator*(double lhs, const Vector2D &rhs);
inline Vector2D operator-(const Vector2D &lhs, const Vector2D &rhs);
inline Vector2D operator+(const Vector2D &lhs, const Vector2D &rhs);
inline Vector2D operator/(const Vector2D &lhs, double val);
std::ostream& operator<<(std::ostream& os, const Vector2D& rhs);
std::ifstream& operator>>(std::ifstream& is, Vector2D& lhs);


//------------------------------------------------------------------------Fungsi member

//------------------------- Length ---------------------------------------
//
// returns the length of a 2D vector
//------------------------------------------------------------------------
inline double Vector2D::Length()const
{
return sqrt(x * x + y * y);
}


//------------------------- LengthSq -------------------------------------
//
// returns the squared length of a 2D vector
//------------------------------------------------------------------------
inline double Vector2D::LengthSq()const
{
return (x * x + y * y);
}


//------------------------- Vec2DDot -------------------------------------
//
// calculates the dot product
//------------------------------------------------------------------------
inline double Vector2D::Dot(const Vector2D &v2)const
{
return x*v2.x + y*v2.y;
}

//------------------------ Sign (penanda positif atau negatif----------------------------------
//
// Positif jika vektor searah jarum jam,
// negatif jika vektor berlawanan arah jarum jam (Y axis kebawah, X axis to kanan)
//------------------------------------------------------------------------
enum {clockwise = 1, anticlockwise = -1};

inline int Vector2D::Sign(const Vector2D& v2)const
{
if (y*v2.x > x*v2.y)
{
return anticlockwise;
}
else
{
return clockwise;
}
}

//------------------------------ Perpendicular ------------------------------------
//
// Prependicular vektor
//------------------------------------------------------------------------
inline Vector2D Vector2D::Perp()const
{
return Vector2D(-y, x);
}

//------------------------------ Distance --------------------------------
//
// calculates the euclidean distance between two vectors
//------------------------------------------------------------------------
inline double Vector2D::Distance(const Vector2D &v2)const
{
double ySeparation = v2.y - y;
double xSeparation = v2.x - x;

return sqrt(ySeparation*ySeparation + xSeparation*xSeparation);
}


//------------------------------ DistanceSq (jarak tanpa sqrt) ------------------------------
//
// calculates the euclidean distance squared between two vectors
//------------------------------------------------------------------------
inline double Vector2D::DistanceSq(const Vector2D &v2)const
{
double ySeparation = v2.y - y;
double xSeparation = v2.x - x;

return ySeparation*ySeparation + xSeparation*xSeparation;
}

//----------------------------- Truncate (pemotongan) ---------------------------------
//
// truncates a vector so that its length does not exceed max
//------------------------------------------------------------------------
inline void Vector2D::Truncate(double max)
{
if (this->Length() > max)
{
this->Normalize();

*this *= max;
}
}


//---------------------------REFLEKSI -------------------------------------
inline void Vector2D::Reflect(const Vector2D& norm)
{
*this += 2.0 * this->Dot(norm) * norm.GetReverse();
}

//----------------------- REVERSE ----------------------------------------
//
// returns the vector that is the reverse of this vector
//------------------------------------------------------------------------
inline Vector2D Vector2D::GetReverse()const
{
return Vector2D(-this->x, -this->y);
}


//------------------------- Normalize ------------------------------------
//
// normalizes a 2D Vector
//------------------------------------------------------------------------
inline void Vector2D::Normalize()
{
double vector_length = this->Length();

if (vector_length > std::numeric_limits::epsilon())
{
this->x /= vector_length;
this->y /= vector_length;
}
}


//------------------------------------------------------------------------Fungsi yang bukan //member vektor

inline Vector2D Vec2DNormalize(const Vector2D &v)
{
Vector2D vec = v;

double vector_length = vec.Length();

if (vector_length > std::numeric_limits::epsilon())
{
vec.x /= vector_length;
vec.y /= vector_length;
}

return vec;
}


inline double Vec2DDistance(const Vector2D &v1, const Vector2D &v2)
{

double ySeparation = v2.y - v1.y;
double xSeparation = v2.x - v1.x;

return sqrt(ySeparation*ySeparation + xSeparation*xSeparation);
}

inline double Vec2DDistanceSq(const Vector2D &v1, const Vector2D &v2)
{

double ySeparation = v2.y - v1.y;
double xSeparation = v2.x - v1.x;

return ySeparation*ySeparation + xSeparation*xSeparation;
}

inline double Vec2DLength(const Vector2D& v)
{
return sqrt(v.x*v.x + v.y*v.y);
}

inline double Vec2DLengthSq(const Vector2D& v)
{
return (v.x*v.x + v.y*v.y);
}


inline Vector2D POINTStoVector(const POINTS& p)
{
return Vector2D(p.x, p.y);
}

inline Vector2D POINTtoVector(const POINT& p)
{
return Vector2D((double)p.x, (double)p.y);
}

inline POINTS VectorToPOINTS(const Vector2D& v)
{
POINTS p;
p.x = (short)v.x;
p.y = (short)v.y;

return p;
}

inline POINT VectorToPOINT(const Vector2D& v)
{
POINT p;
p.x = (long)v.x;
p.y = (long)v.y;

return p;
}



// Overload Operator
inline Vector2D operator*(const Vector2D &lhs, double rhs)
{
Vector2D result(lhs);
result *= rhs;
return result;
}

inline Vector2D operator*(double lhs, const Vector2D &rhs)
{
Vector2D result(rhs);
result *= lhs;
return result;
}

//overload the - operator
inline Vector2D operator-(const Vector2D &lhs, const Vector2D &rhs)
{
Vector2D result(lhs);
result.x -= rhs.x;
result.y -= rhs.y;

return result;
}

//overload the + operator
inline Vector2D operator+(const Vector2D &lhs, const Vector2D &rhs)
{
Vector2D result(lhs);
result.x += rhs.x;
result.y += rhs.y;

return result;
}

//overload the / operator
inline Vector2D operator/(const Vector2D &lhs, double val)
{
Vector2D result(lhs);
result.x /= val;
result.y /= val;

return result;
}

///////////////////////////////////////////////////////////////////////////////



inline void WrapAround(Vector2D &pos, int MaxX, int MaxY)
{
if (pos.x > MaxX) {pos.x = 0.0;}

if (pos.x < 0) {pos.x = (double)MaxX;}

if (pos.y < 0) {pos.y = (double)MaxY;}

if (pos.y > MaxY) {pos.y = 0.0;}
}


inline bool NotInsideRegion(Vector2D p,
Vector2D top_left,
Vector2D bot_rgt)
{
return (p.x <> bot_rgt.x) ||
(p.y <> bot_rgt.y);
}

inline bool InsideRegion(Vector2D p,
Vector2D top_left,
Vector2D bot_rgt)
{
return !((p.x <> bot_rgt.x) ||
(p.y <> bot_rgt.y));
}

inline bool InsideRegion(Vector2D p, int left, int top, int right, int bottom)
{
return !( (p.x <> right) || (p.y <> bottom) );
}


inline bool isSecondInFOVOfFirst(Vector2D posFirst,
Vector2D facingFirst,
Vector2D posSecond,
double fov)
{
Vector2D toTarget = Vec2DNormalize(posSecond - posFirst);

return facingFirst.Dot(toTarget) >= cos(fov/2.0);
}





#endif
}

-bingung? baca lagi Pengantar C++ nya....
-Kenapa menggunakan C++ ? karena dia full support untuk OOP...
-beberapa operasi vektor pada kode diatas adalah jumlah operasi vektor yang sebenarnya (aljabar linear lanjutan)

Minggu, 26 September 2010

Pembuatan AI dengan implementasi C++ (part 1)

Bagi para gamers yang penasaran dengan pembuatan AI (kecerdasan buatan) pada game itu seperti apa,sedikit penjelasan tentang design AI dan implementasinya dengan C++...

Kebetulan ini menjadi topik skripsi saya yaitu otomasi AI dengan voice command, berhubung voice command nya belum dibuat, jadi saya cerita tentang AI nya dulu..

Ok,..pertama basic matematika dan fisika kita harus kuat (yang gak kuat belajar lagi kayak saya) terutama tentang koordinat cartesian, fungsi2, trigonometri lalu vektor..beberapa developer game menyebut vektor adalah "sahabat" karena jika game tersebut berbasis 2D maka kita menggunakan vektor 2D jika 3D? ya vektor 3D...
untuk basic fisikanya, masih ingat s = v.t? itu adalah rumus menghitung jarak s(jarak) = v(kecepatan) * time (waktu), serta rumus2 percepatan, gravitasi dll....

itu untuk basic matematika dan fisikanya..sekarang kita masuk ke bagian AI nya,,

pernah dengan FSM? itu adalah sebutan mutlak untuk para developer game yaitu Finite State Machine atau kondisi AI nya... sebagai contoh adalah game PacMan,..dalam game PacMan ada beberapa kondisi :
1. Jika PacMan belum makan Bulatan maka setan akan mengejar dan PacMan menghindar
2. Jika sudah makan Buletan maka PacMan mengejar, setan menghindar..

atau contoh yang lebih mudah adalah sebuah lampu:
1. Jika saklar Off maka lampu mati
2. Jika saklar On maka lampu hidup..

udah jelas? kebayang kan berapa state yang dibuat jika ingin membuat game yang komplex?
untuk implementasinya perhatikan script berikut :

enum StateType

void Agent:: UpdateState (StateType CurrentState)
{
switch (CurrentState)
{
case state_kabur;
HindariMusuh();
if (Safe())
{
ChangeState(state_siaga);
}
break;

case state_siaga;
IkutiAlur();
if(bahaya())
{
if(MusuhlebihLemah())
{
ChangeState(state_serang);
}
else
{
ChangeState(state_kabur);
}
}
break;

case state_serang;
if(MusuhlebihKuat())
{
ChangeState(state_kabur);
}
else
{
HancurkanMusuh();
}
break;
}
}

script C++ diatas adalah script dasar dari game DotA (Defense of the Ancient),tapi scriptnya gak semudah itu lho...masih banyak script2 lainnya yang belum saya pelajari...

ok itu untuk FSM nya....

sekarang kita masuk ke Agent..
disini anda harus mengerti Autonomous Agent..apa itu???
Autonomous Agent adalah AI yang dapat berinteraksi dengan lingkungannya...
misal dalam game, Ada ranjau didepan prajurit, tetapi prajurit berhasil menghindar, berarti si AI prajurit itu bisa berinteraksi dengan lingkungan,buktinya dia bisa tau ada ranjau didepan...
karena AI itu kita buat berdasarkan pengetahuan maka AI tidak bersifat Omnisscience (serba tahu) kita tidak dapat menyalahkan AI jika dia salah persepsi, karena AI diciptakan berdasarkan pengetahuan dari kita..(berarti klo AI salah, salahin juga yang buatnya.hehehe)....

ok, didalam implementasi C++ para developer game telah sepakat menentukan komponen2 yang akan dipakai untuk pembuatan game (khususnya AI)..diantaranya :
MovingEntity, BaseGameEntity, SteeringBehavior, GroupBehavior,dll..
jika ingin dilihat Class Diagramnya..monggo..


silahkan dicoba codingannya sendiri,,,kalau ada salah design mohon maaf ya,.namanya juga baru belajar...
selesai part 1 kali ini, karena ane udah pegel ngetik + ngantuk,,,nanti disambung lagi dipart 2 yah...