Yapay Zeka - 1
Yapay Zeka
Yapay zeka ile ilgili biraz fikir
vermesi açısından bir kaç yazı. Bu yazıları genel bir yapayzeka kaynağı
olarak değilde, yeni başlayanlar için biraz fikir verecek, ilham
kaynağı olabilecek bir döküman olarak görmek en iyisi. İçinde hatalar
falan da vardır kesin. Neyse, umarım bir işe yarar..
Yazı 1
Çok Basit Yapay Zeka: (YIQ: 0-30 )
(YIQ: Yapay IQ: ben uydurdum, bilimsel değeri yok :) )
Bu tip yapay zekalar, pacman, mario gibi oyunlarda bulunur. Genel
olarak önceden belirlenmiş bir yol izlerler. Kodlaması basittir.
Örnek bir kod inceleyelim:
Önce, yolumuzu tutacak yapıyı yazmalıyız:
Vector3F tipi, 3 lük bir array, bu da oyunun geçtiği dünyada bir hedef
ve başlangıç koordinatı belirtiyor.
Yol tipi de, "zekalandırmak" (nasıl oluyosa) istediğimiz elemanın
rotasındaki düz bir yol parçasını tutuyor. Zaman da o rotadaki ilerleme
süresi
Rota tipi de Yol lardan oluşan tüm rotayı tutuyor. Aktif yol, o an
gidilen yol parçasının indexi, geçZaman da şu anki aktif yola girdiği
zaman (milisaniye cinsinden)
typedef
Vector3F float[ 3 ] ;
typedef
struct _yol
{
Vector3F bas ;
Vector3F son ;
float zaman ;
} Yol ;
typedef
struct _rota
{
int yolSay ;
Yol * yollar ;
int aktifYol ;
float gecZaman ;
} Rota ;
Şimdi de bu rota üzerinde adamımızı oynatacak bir fonksiyon:
Adamımızın tipinin Dusman olduğunu varsayıyorum ve bunun yer diye bir
Vektor3F elemanı olmalı.
struct Dusman
{
...
...
Vektor3F yer ;
Rota *rota ;
...
...
}
Şimdi adamımızı oynatacak kod geliyor. Kod, önce geçen zamana göre Rota
içinden seçilmesi gereken Yol u buluyor, sonra bu yoldaki koordinatını
Lineer Interpolasyon (ismi gören korkar ama sadece ortalama almak gibi
bişey) ile hesaplıyor.
void
dusmanOynat( Dusman *dusman, float zaman )
{
float *bas, *son ;
// delta t: zaman farkı
float dt ;
// Eğer şimdiki yolun sonuna geliyorsak
if( ( zaman ) > ( dusman->rota->gecZaman +
dusman->rota->yollar[ dusman->rota->aktifYol ].zaman ) )
{
// yola giriğ zamanını ayarla
// bir önceki yola giriş zamanı ile yolun
süresinin toplamı
dusman->rota->gecZaman =
dusman->rota->gecZaman + dusman->rota->yollar[
dusman->rota->aktifYol ].zaman ;
// bir sonraki yolu aktive et, sona geldiyse
başa don..
dusman->rota->aktifYol = (
dusman->rota->aktifYol + 1 ) % dusman->rota->yolSay ;
}
// şimdi yol içindeki konumu hesapla
bas = ( dusman->rota->yollar[
dusman->rota->aktifYol ]->bas ) ;
son = ( dusman->rota->yollar[
dusman->rota->aktifYol ]->son ) ;
// delta t: şimdiki zaman eksi yola giriş zamanı
dt = zaman - dusman->rota->gecZaman ;
dusman->rota->yollar[ dusman->rota->aktifYol ].zaman ;
// burda da, şimdiye kadar geçen zamanı, yolda toplam harcanması
gereken zamana bölüp,
// yolun kaçta kaçını gitmesi gerektiğini bulduk.. onu da basit
bi şekilde toplayıp, yeni yeri bulduk...
dusman->yer[ 0 ] = bas[ 0 ] + ( son[ 0 ] - bas[ 0 ] ) * ( dt /
dusman->rota->yollar[ dusman->rota->aktifYol ].zaman ) ;
dusman->yer[ 1 ] = bas[ 1 ] + ( son[ 1 ] - bas[ 1 ] ) * ( dt /
dusman->rota->yollar[ dusman->rota->aktifYol ].zaman ) ;
dusman->yer[ 2 ] = bas[ 2 ] + ( son[ 2 ] - bas[ 2 ] ) * ( dt /
dusman->rota->yollar[ dusman->rota->aktifYol ].zaman ) ;
}
Şimdi de bu fonksiyonu kodun içinden çağıracak bişeyler yazmak lazım..
Bir yerlerde, bizim bir pencere açan şunu bunu yapan bir kodumuzun
olduğunuz varsayarak (bakınız NeHeGL base code) bu kodumuzdaki "Update(
float milliseconds )" fonksiyonumuzun içine yazılacak kısmı yazmaya
geçebiliriz:
// Bunlara
biyerlerde değerler atanmalı
int
dusmanlarinSayisi ;
Dusman
*tumDusmanlar ;
void Update(
float milliseconds )
{
int i ;
static float toplamZaman = 0 ;
toplamZaman += milliseconds ;
...
..
for( i = 0; i < dusmanlarinSayisi; i++ )
{
dusmanOynat( tumDusmanlar[ i ], toplamZaman ) ;
}
....
...
}
Şunlara dikkat edilmesi gerekiyor:
- Tüm düşmanlar için dizimiz doldurulmuş olmalı, yoksa hatalar
verir..
- Eğer sonuncu yol ilkine birleşmiyorsa, yolun sonuna geldiğinde
atlama yapar. Birleşmesi daha iyi olur.
- Kodu çalıştırıp test etmedim, belki yazım hataları olabilir.
Ziyaretci :: 2004 :: OyunYapimi.Org
|
|