Bu eğitim seti Michael James Williams tarafından hazırlanmıştır. Ben kendisinin izniyle Türkçe'ye tercüme ediyorum. Umarım faydalı olur.
Giriş
Bir çok flash uygulama geliştirici Actionscript 2'den Actionscript 3'e geçmeyi çok göz korkutucu bulur. Aksine diğer dilleri kullanan bir çok programcı Actionscript 3'ü sezgisel olarak elde edilebilen bir dil olarak görürler ama Actionscript 2'den nefret ederler. Bu eğitim serisine başlamak için AS2 bilmenize gerek yok hatta Flash kullanmayı bilmenize bile gerek yok. Tabii ki değişkenler, if, else if, döngüler ve fonksiyonlar gibi bir çok programlama dilinde aynı olan ifadeleri bilmeniz sizin yararınızadır. Eğer hiç bir programlama bilginiz yoksa meraklanmayın, bu eğitim serisinde hepsini öğreneceksiniz. AS2 ve AS3 arasındaki bazı büyük değişiklikleri de anlatmaya çalışıcam ama bu değişiklikler üzerinde fazla durmayacağız.
Frozen Haddock ActionScript 2 Avoider Oyun Eğitim Seti 'ni Actionscript 3'e aktarmama izin verecek kadar nazikti. Teşekkürler Frozen Haddock! Bu eğitim seti Frozen Haddock'un AS2 için hazırladığı eğitim setinin aynen AS3'e çevrilmiş hali değil. AS3 tasarımına uygun olması amacıyla kod baştan düzenlenmiştir.
AS3'e uygun olması demek:
- Tek frame
- Tek katman
- Ekranda herhangi bir çizim olmayacak
- Timeline'da herhangi bir kod bulunmayacak
- Sembollerde herhangi bir kod bulunmayacak
(Eğer daha önce Flash ile bir oyun geliştirmediyseniz, yukarıdakiler muhtemelen size pek bir şey ifade etmeyecektir. Yukarıdaki saydıklarımız iyi bir kod yapısı için önemlidir, bana güvenin)
Sıra preloader(önyükleme) hazırlamaya geldiğinde bu kurallar biraz esnetilebilir.
Ayrıca sınıfları, olayları ve OPP(nesne yönelimli programlamayı) ve diğer güzel programlama tekniklerini kullanıcaz. Bu bölümde her şeyi hazırlayıp oyunun temel mekaniğine giriş yapıcaz.
Aşağıdaki resime tıklayarak oyunun bu bölüm sonunda nasıl bir şey olacağını görebilirsiniz.
12. bölümün sonunda oyunda klavye ile kontrol, bir çok level, müzik ve daha fazlası olacak. Aşağıdaki resime tıklayarak oyunun 12. bölümün sonundaki halini görebilirsiniz.
Kurulum
Basitten başlayalım. Adobe Flash CS3 (ya da daha sonraki bir versiyonunu) çalıştırın ve File > New > Flash File (ActionScript 3.0) yeni bir flash dosyası oluşturun.
File > Save 'e tıklayın ve yeni bir klasör oluşturun. Bu klasör bütün dosyalarımızı kaydedeceğimiz klasör olacak. Olşuturacağımız ilk klasöre Avoider Game gibi bir isim verelim(herhangi bir isim de olur), bu klasörün içinde Classes isimli bir klasör oluşturun. Bu adımlardan sonra FLA dosyamızı Avoider Game klasörünün içine kaydedin- ana dosyanın içine kaydedin, classes isimli klasörün içine değil.

Oyunu düzgün bir şekilde çalıştırabilmek için başlamadan önce değiştirmemiz gereken bazı ayarlar var. File > Publish Settings 'e tıklayın. Flash sekmesine sonrasında Settings'e tıklayın.

Aşağıdaki resimdeki gözüken artı işaretine tıklayın. Classpath'e sınıfları kaydedeceğimiz biraz önce oluşturduğumuz "classes" isimli dosyayı ekliyoruz. Burada yaptığımız sınıfları depolayacağımız klasörü flash'a tanıtmak.

Ayrıca “Automatically declare stage instances” kısmında tik yoksa buraya tik koyun.
Bundan sonra oyunla alakalı bazı ayarları yapıcaz. Modify > Document tıklayın ve oyunu istediğiniz gibi ayarlayın. Frozen Haddock oyunda 300x300 boyutunu ve gri bir arkaplan rengini kullanmış. Bende gri arkaplanı kullanıcam ancak boyutları 400x300 olarak değiştiricem. Bu ekran ayarını daha sonra istediğiniz zaman değiştirebilirsiniz. FPS(saniyede oynatılcak frame sayısı) olarak 24 seçmenizi tavsiye ederim. Benim ayarlarımı aşağıdaki resimden görebilirsiniz:

Buraya kadarki anlattıklarımız programla ilgili ayarlardı, artık biraz çizim yapmaya ve kod yazmaya başlayalım.
Düşmanı Oluşturma
Bu oyun Avoider tarzı bir oyun olacağı için düşman kendisinden kaçacağımız bir obje olacak. Düşmanın kodlamasına girmeden önce düşman nesnesinin çizimini yapalım.
Bu oyun Avoider tarzı bir oyun olacağı için düşman kendisinden kaçacağımız bir obje olacak. Düşmanın kodlamasına girmeden önce düşman nesnesinin çizimini yapalım. Insert > New Symbol tıklayalım, açılan pencerede isim olarak Enemy yazın(E büyük harfle! yoksa ileride kodlama ile ilgili problemlerle karşılaşabilirsiniz) ve tür olarak MovieClip seçin. OK'e tıklayın. Oluşturduğunuz Enemy nesnesini artık kütüphanede görebilirsiniz.
Eğer kütüphaneyi göremiyorsanız. Window>Library ile kütüphaneyi aktif hale getirin. Objeyi oluştururken OK'e tıkladığınızda sizi direk olarak objeyi düzenlediğiniz sayfaya götürmesi gerekiyor.Timeline'ın altında çubuktan(bar) -aşağıdaki resimdeki gibi- hangi objeyi düzenlediğinizi görebilirsiniz.

Eğer bir sebeple Enemy nesnesinin düzenleme ekranında(buna aslında Enemy nesnesinin içinde de diyoruz) değilseniz kütüphaneden Enemy nesnesine 2 kere tıklayarak(ya da sağ tıklayıp edit'e basarak) düzenleme ekranına girebilirsiniz. Düzenleme ekranında düşmanı çizin. Frozen Haddock kötü adam için gülen bir yüz çizmiş. Bende aynısını kullanıcaz. Siz istediğiniz herhangi bir şey çizebilirsiniz. Fakat yaklaşık olarak yuvarlak bir şey çizin. Eğer cin ali tarzı bir şeyler çizerseniz bu eğitim setinin bazı kısımları sizin için uygun olmaz. Eğer çizim konusunda pek bir bilginiz yoksa şuraya bir göz atabilirsiniz. Benim çizimim:

Oldukça iyi :). Aslında küçük bir problem var. Arkası beyaz renkli siyah artı işaretini görüyor musunuz?Buna registration point(kayıt noktası) denir ve bu nokta kodlamaya başladığımızda düşmanı şu noktaya koy dediğimizde flash'ın kullanacağı nokta budur. Şu anda biraz karışık görünüyor olabilir ama kodlamaya başladığımızda ne demek istediğimi anlayacaksınız. genellikle bu noktayı objenin ortasına koyarız. Bu noktayı ortaya şöyle alabiliriz:
İlk olarak Enemy isimli nesneyi düzenlediğinizden emin olun. Daha sonra ekrandaki her şeyi seçin. Artı işareti belirecektir.

Seçtiğimiz her şeyi Modify>Group Together(Ctrl+G) ile grup yapın. Objenin etrafında mavi bir çerçeve belirecek. Böylece bütün çizimi tek bir parça haline getirdik.

Align paneli açık değilse Window> Align ile bu paneli açın. Ekranda Enemy(gülen surat) seçili olarak aşağıdaki resimdeki gibi 2 ortalama butonuna basın.(To stage butonunu tıklanmış olmasına dikkat edin, bu şekilde objeyi ekrana göre ortaya yerleştireceğiz)

Buraya kadar Enemy nesnesi için çizimi bitirdik. Timeline'ın altındaki Scene 1'e tıklayarak düşmanı editlediğimiz ekranı kapatabiliriz. Bu noktada File>Save ile yaptıklarımız kaydetmek iyi olacaktır :)
The Enemy’s Instructions
Buraya kadar daha önceki Flash versiyonlarında yaptığımızdan çok değişik bir işlem yapmadık. Bu değişmek üzere. Düşmanın nasıl davranacağını belirlemek üzere kod yazmaya başlıyoruz. Daha öncede bahsettiğimiz gibi bu kodlar timeline'da ya da bir objenin içinde olmayacak.(AS2 kullandıysanız, AS2'de kodu genellikle timeline'a ve objelerin içine yazardık) Bunun yerine kodları harici dosyalara yazıcaz. Bunun bize bir çok yararları var:
- Kod çizimlerden tamamıyla ayrı dosyada olacak. Bu sayede bir grafiker ile birlikte çalışırken grafikere herhangi bir kod göndermeden sadece FLA dosyasını gönderebiliriz.
- Aynı şekilde bir programcıya herhangi bir çizim, ses vs. göndenmeden sadece kodun bir kısmını veya tamamını gönderebilirsiniz.
- Birden fazla programcının beraber çalıştığı durumlarda herkes farklı bir kısım üzerinde çalışabilir. Bu kodların en sonda birleştirilmesi daha kolay olur.
File > New tıklayın ve ActionScript File seçeneğini seçin. Boş bir yazı düzenleme ekranı karşınıza çıkıcak. Hemen dosyayı Enemy.as ismiyle daha önce oluşturduğumuz Classes.as klasörünün içine kaydedin. Bu oluştruduğumuz dosya Enemy nesnesi için gereken kodları içerecek.
Burası bir çok AS2 programcısının AS3'ün ne kadar zor olduğu hakkında şikayet etmeye başladıkları yerdir. Çünkü AS3'de bir objenin bir şeyler yapması için çok fazla kod yazmak gerekmektedir. Evet AS3'te daha fazla kod yazıyoruz ama kodlamanın ilerleyen aşamalarında AS3'ün daha düzenli olduğunu göreceksiniz.
Burası bir çok AS2 programcısının AS3'ün ne kadar zor olduğu hakkında şikayet etmeye başladıkları yerdir. Çünkü AS3'de bir objenin bir şeyler yapması için çok fazla kod yazmak gerekmektedir. Evet AS3'te daha fazla kod yazıyoruz ama kodlamanın ilerleyen aşamalarında AS3'ün daha düzenli olduğunu göreceksiniz.
Oluşturduğumuz Enemy.as dosyasına aşağıdakileri yazarak başlayalım.
1 2 3 4 | package { } |
package kelimesi basitçe kendisiniz takip eden 2 süslü parantez arasındakilerin bu oluşturduğumuz sınıfa ait kodlar olduğunu gösterir. Bir kaç istisnai durum dışında yazacağımız bütün kodları package kısmına yazarız. Açıkçası ben şimdiye kadar package dışına kod yazma ihtiyacı hissetmedim. Bir kaç istisnai durum dememin sebebi okuduğum bir AS3 programlama kitabında package dışına da fonksiyon yazabileceğimiz söyleniyordu.
package'nin bir parçası olarak Enemy sınıfını tanımlayacağız:
1 2 3 4 5 6 7 | package { public class Enemy extends MovieClip { } } |
Bu kodu adım adım inceleyelim:
- class Enemy — “sonraki 2 süslü parantez arasındaki her şey Enemy sınıfını oluşturacak.”
- public — “public kodu ile oluşturduğumuz sınıf diğer sınıflar tarafından erişilebilir.” Public'e alternatif olarak internal kodunu kullanabiliriz. Internal kodunu kullandığımızda bu sınıfa aynı package içinden erişilebilir.
- extends MovieClip — “Bu sınıf MovieClip sınıfının yapabildiği her şeyi yapabilir” extends kodu kullanılarak bir sınıfın kodları diğer sınıf tarafından kullanılabilir. Bizim durumumuzda Enemy sınıfımız MovieClip sınıfına ait olan fonksiyonları -mesela play komutu- kullanabilir. Bunun haricinde biz de Enemy sınıfımıza MovieClip sınıfında bulunmayan yeni özellikler ekleyebiliriz.
MovieClip sınıfı sıklıkla kullanılan bir sınıf olmasına rağmen MovieClip sınıfını kullanmak için import etmemiz gerekiyor. Bu sebeple aşağıdaki 3. satırı yazarız.
1 2 3 4 5 6 7 8 | package { import flash.display.MovieClip; public class Enemy extends MovieClip { } } |
Son olarak Enemy sınıfımızın constructor fonksiyonunu yazarız. Bu fonksiyon yeni oluşturulan her Enemy objesi için çağırılan bir fonksiyondur. Bütün constructor fonksiyonları tanımlandığı sınıfla aynı isimde olmalıdır. 6. satırda constructor fonksiyonumuzu tanımlıyoruz:
1 2 3 4 5 6 7 8 9 10 11 | package { import flash.display.MovieClip; public class Enemy extends MovieClip { public function Enemy() { } } } |
Yine public anahtar sözcüğüyle tanımladık. Enemy fonksiyonundan sonraki süslü parantezlere dikkat edin, bunların arasına ne yazacağımıza daha sonra değinicez.
Buraya kadar Enemy sınıfımızı hazırladık. Şimdi oluşturduğumuz Enemy çizimini koda bağlamamız gerekiyor. Enemy.as dosyamızı kaydedelim ve ilk başta oluşturduğumuz FLA dosyasına geri dönelim. Kütüphanedeki Enemy nesnesine sağ tıklayıp selectProperties'i seçin. Advanced'a tıklayarak. Aşağıdaki resimdeki gibi Export for ActionScript kutusuna tik koyun ve Class kısmında Enemy yazdığından emin olun. Enemy.as dosyasını bağlamak için sağ taraftaki küçük kalem işaretine tıklayın. Burada dikkat ederseniz Base Class kısmındaki sınıf extends anahtar sözcüğüyle sınıfımızda kullandığımız MovieClip sınıfı.

OK'e tıklayarak bu pencereyi kapatın.
Şimdi sıra Enemy objesinin ne yapacağıyla ilgili için kod yazmaya geldi. Peki ne yapması gerekiyor? Bu noktada yapması gerekenler:
- Düşman oluşturulduğunda ekranın tepesinde yer alamalı
- Bundan sonra aşağıya doğru hareket etmeli
Düşman oluşturulduğunda direk çalışacak kod daha öncede söylediğimiz gibi constructor fonksiyonudur. Bu sebeple düşmanın sahnenin tepesinde belirmesi için constructor fonksiyonun içine x ve y değerlerini gireceğiz.
1 2 3 4 5 6 7 8 9 10 11 12 | package { import flash.display.MovieClip; public class Enemy extends MovieClip { public function Enemy() { x = 100; y = 0; } } } |
MovieClip sınıfnda x ve y özelliği olduğu için biz de sınıfımızda x ve y'i kullanabiliriz(extends ile MovieClip sınıfını seçtiğimiz için.
Gördüğünüz gibi x değeri olarak 100 ve y değeri olarak 0 girdik. Bildiğiniz üzere kartezyen koordinat sisteminde x sağa doğru y yukarı doğru artar. Bu durumda y değerini 0 girdiğimiz için düşmanın sahnenin altında ortaya çıkması lazım. Ancak Flash koordinat sistemini daha farklı kullanır. Flash'ta x değeri sağa doğru y değeri aşağıya doğru artar ve sahnenin sol üst tarafı (0,0)'dır.

Zamanla bu sisteme alışırsınız :)
Düşmanın hareket etmesi için sınıfımıza bir fonksiyon ekleyeceğiz. MovieClip sınıfının böyle bir fonksiyonu olmadığı için kendimiz bir fonksiyon oluşturucaz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package { import flash.display.MovieClip; public class Enemy extends MovieClip { public function Enemy() { x = 100; y = 0; } public function moveDownABit():void { y = y + 3; } } } |
Yukarıdaki kodu incelersek:
- function moveDownABit() — Bu kısımdan sonraki 2 süslü parantez arasındaki kısım moveDownABit fonksiyonunu oluşturur. Buraya bu fonksiyonun yapacaklarını yazıcaz.
- public —Oyunun başka bir kısmı bu fonksiyonu çağıracağı için bu fonksiyonu public olarak atadık.
- :void — void olarak atanan bir fonksiyon çağrıldığında hiç bir değer döndürmez. Şimdilik bununla pek bir işimiz yok buraya fazla takılmayın.
- y = y + 3; — bu kodla objemizin y değerine 3 ekliyoruz. Bu fonksiyonu sürekli çağırarak objemizin hareket etmesini sağlayacağız.
Düşmanı Oluşturma
Enemy.as dosyasını kaydedin ve FLA dosyamıza geri dönelim. Bir sonraki adımımız düşmanı oyunumuza eklemek yani ekranda belirmesini sağlamak. Şimdiye kadar sadece şablon ile ilgileniyorduk. Şablonu hazırladık şimdi bu şablonun bir örneğini oluşturup bunu ekranda göstericez.
Şunu hatırlamak gerekir ki Flash ilk olarak animasyon oluşturmak için geliştirilmiş bir yazılımdır. O zamandan beri çok gelişmesine rağmen, flash hla oluşturduğumuz her şeyi bir MovieClip olarak görür. Bildiğimiz üzere MovieClip'lerin de bir constructor fonksiyonları vardır ve ilk oluşturulduklarında çalıştırılırlar. Aynı şekilde oluşturduğumuz oyununda bir constructor fonksiyonu vardır. Bu özelliği kullanarak yeni oluşturacağımız bir AS dosyasının oyun ilk başladığında çalıştırılacak dosya olmasını sağlayacağız.
Yeni bir AS dosyası oluşturun, aşağıdaki kodları bu dosyaya yazalım ve bu dosyayı Classes klasörünün içine AvoiderGame.as ismiyle kaydedin.
1 2 3 4 5 6 7 8 9 10 11 | package { import flash.display.MovieClip; public class AvoiderGame extends MovieClip { public function AvoiderGame() { } } } |
Daha önce Enemy.as dosyasında yazdığımız koda benzer bir şekilde AvoiderGame.as dosyamızı oluşturduk.Sıra bu dosyayı FLA dosyamıza bağlamaya geldi.
FLA dosyamıza geri dönelim. Ana pencerede olduğunuza emin olun(Enemy nesnesinin düzenlendiği ekrandaysanız Scene 1'e tıklayarak ana pencereye dönün) Properties Panel'e tıklayın(eğer açık değilse Window>Properties ile aktif hale getirin. Properties penceresinde Document Class yazan yere ilk olarak çalıştırılacak AS dosyasının adını yazıyoruz. Bizim durumumuzda bu AvoiderGame olacak. Daha sonrasında yandaki küçük kaleme tıklayın.

Şimdi oluşturduğumuz AvoiderGame.as dosyamızı düzenlemeye geçebiliriz.
1 2 3 4 5 6 7 8 9 10 11 | package { import flash.display.MovieClip; public class AvoiderGame extends MovieClip { public function AvoiderGame() { enemy = new Enemy(); } } } |
Yukarıdaki kodu AvoiderGame.as dosyamızın içine yazın. Bu noktada büyük harf, küçük harf yazımına dikkat edin. Flash büyük, küçük harfe duyarlıdır yani Enemy ile enemy aynı şey değildir. Küçük harfle yazdığımız enemy Enemy sınıfına ait bir nesne örneğidir. Bir nesne örneğini new sınıfismi() şeklinde oluştururuz.
Bu şekilde oluşturduğumuzda enemy objesi sadece constructor fonksiyon içerisinde erişilebilir olacaktır. enemy objesinin sınıfın her yerinden erişilebilmesi için objeyi hemen sınıf tanımının altında tanımlarız.(6.satır)
1 2 3 4 5 6 7 8 9 10 11 12 13 | package { import flash.display.MovieClip; public class AvoiderGame extends MovieClip { public var enemy:Enemy; public function AvoiderGame() { enemy = new Enemy(); } } } |
- public — bunu artık biliyorsunuz :)
- var — var anahtar kelimesi variable(değişkenin) kısaltılmış şeklidir. Bu anahtar sözcükle yeni bir değişken oluştururuz.
- enemy:Enemy — “değişkenin ismi olarak enemy seçtik ve sınıf tipi Enemy”
Sınıfın içerisinde tanımladığımız için(bundan kastım herhangi bir fonksiyon içinde değilde direk sınıfın içerisinde tanımlanması) enemy nesnesi AvoiderGame.as dosyasının her yerinden ulaşılabilecek.
Şimdiye kadar bir düşman(enemy) oluşturduk. Ancak oluşturduğumuz bu düşman henüz ekranda gözükmeyecek. Ekranda belirmesi için bir satır daha kod yazmamız gerekecek :)
8 9 10 11 12 | public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); } |
İşte yeni bir fonksiyon: addChild(). Bu fonksiyonla objenin ekranda görünmesini sağlıyoruz. addChild ile ana dosyamıza eklenmiş(AvoiderGame.as bizim ilk çalışan dosyamız yani ana dosyamız) objeler ekranda belirecek.
Böylece enemy isimli objemiz AvoiderGame sınıfının çocuğu(child), AvoiderGames sınıfımız enemy objemizin velisi :)(parent) durumuna geldi. Her bir objenin sadece 1 adet velisi(parent) olabilir ancak sonsuz sayıda çocuğa(child) sahip olabilir.
Nihayet oyunumuzu çalıştırıp ekranda bir şeylerin belirmesini, bir şeyler olmasını umabiliriz :). Yaptığımız her şeyi kaydedin ve sonrasında Control>Test Movie ile oyunumuzu test edelim. Buna benzer bir şeyler elde edeceksiniz:

Gördüğünüz gibi düşmanımızın sadece yarısı ekranda. Ama biz düşmanın ekranın üstünde belirmesini istiyoruz yani başta ekranda gözükmeyecek daha sonra aşağıyo doğru kayacak. Hatırlarsanız önceden registration point diye bir noktadan(siyah artı işareti aslında) bahsetmiştik. Bu nokta tam ortası olduğu için nesnenin y değerini sıfır olarak atadığımızda nesnenin ortası sıfır noktasında oluyor. Bu sebeple düşmanımızın y değerini değiştirmeliyiz:
6 7 8 9 10 | public function Enemy() { x = 100; y = -15; } |
Düşmanın y değerini düşmanın yüksekliğinin yarısı kadar düşürmeliyiz. Bizim örneğimizdeki 30 px olduğu için 15 px düşürdük.(Aslında buraya 15 gibi bir değer girmek yerine height/2 şeklinde de yapabilirdik, ancak şimdilik -15 işimizi görür)
Bringing the Enemy to Life
Enemy sınıfı için moveDownABit() isimli bir fonksiyonumuz olmasına rağmen henüz düşmanın hareket etmesi için herhangi bir işlem yapmadık. Öyleyse düşmana hareket verelim.
Düşmanı hareket ettirmek için yapmamız gereken oyunun düşmana saniyede 10-20 kere bir kaç piksel aşağıya gitmesini söylemesi. AS3'te bu tarz işlemler için Timer sınıfını kullanırız.
Oyunun constructor fonksiyonunda(AvoiderGame.as'ın constructor fonksiyonu) Timer sınıfının bir nesne örneğini oluşturacağız. Timer sınıfı built-in class(Flash ile gelen sınıfılar MovieClip sınıfı gibi) olduğu için yeni bir sınıf oluşturmamıza gerek yok. Bu sebeple AvoiderGame.as sınıfını düzenlemeye devam ediyoruz:
8 9 10 11 12 13 14 | public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); gameTimer = new Timer( 25 ); } |
Oluşturduğumuz değişkenin adı gameTimer. enemy oluştururken kullandığımız gibi yine new anahtar sözcüğünü kullanacağız. Atadığımız 25 değeri ise gameTimer değişkenimizin ne kadar zamanda bir işeyeceği. Buradaki 25'in birimi milisaniyedir(1000 milisaniye=1 saniye). Yani programımız 25 saniyede 1 istediğimiz işlemleri yapacak.
gameTimer değişkenimizi oyun boyunca kullanacağımız için enemy gibi sınıfın altında tanımlamalıyız:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package { import flash.display.MovieClip; public class AvoiderGame extends MovieClip { public var enemy:Enemy; public var gameTimer:Timer; public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); gameTimer = new Timer( 25 ); } } } |
…Timer sınıfı içinde MovieClip sınıfı ile aynı şekilde import etmeliyiz.(4.satır):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package { import flash.display.MovieClip; import flash.utils.Timer; public class AvoiderGame extends MovieClip { public var enemy:Enemy; public var gameTimer:Timer; public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); gameTimer = new Timer( 25 ); } } } |
11 12 13 14 15 16 17 18 | public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); gameTimer = new Timer( 25 ); gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy ); } |
- gameTimer.addEventListener — “gameTimer'a bir olay denetleyicisi ekliyoruz” Bir olay denetleyicisi robot gibidir ve istenen olayın gerçekleşip gerçekleşmediğini sürekli kontrol eder. Olay denetleyicisi için 2 gerekli parametre vardır.
- TimerEvent.TIMER — Birincisi olayın türüdür. Bizim durumumuzda bu bir TimerEvent.TIMER yani her 25 milisaniyede istediğimiz fonksiyonu çağıracak.
- moveEnemy —İkincisi ise çalıştırılacak fonksiyondur. Henüz bu fonksiyonu yazmadık ama birazdan bu fonksiyonu yazacağız. Kısaca bu fonksiyon 25 milisaniyede bir çalışacak fonksiyonumuz.
Aynı şekilde TimerEvent'i de import etmemiz gerekecek(Satır 5).
1 2 3 4 5 | package { import flash.display.MovieClip; import flash.utils.Timer; import flash.events.TimerEvent; |
Şimdi her 25 milisaniyede bir çalışması için moveEnemy() fonksiyonumuzu yazıyoruz (satır 21-24):
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class AvoiderGame extends MovieClip { public var enemy:Enemy; public var gameTimer:Timer; public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); gameTimer = new Timer( 25 ); gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy ); } public function moveEnemy( timerEvent:TimerEvent ):void { } } |
Tekrar parantezler içinde henüz görmediğimiz bir ifade var. Bu kısmı şimdilik kullanmayacağız böyle kalmasında bir sakınca yok :).
Şimdi yapmamız gereken bu yeni fonksiyonda Enemy sınıfında tanımladığımız moveDownABit() fonksiyonunu çağırmak. Hatırlarsanız bu fonksiyonu çağırarak düşman objesini aşağıya doğru kaydıracaktık.
21 22 23 24 | public function moveEnemy( timerEvent:TimerEvent ):void { enemy.moveDownABit(); } |
Bu değişikliği de yapıp her şeyi kaydedin ve Ctrl+Enter veya Control>Test Movie ile oyunumuzu test edelim.
Hiç bir şey olmadı :)
Sayacımızı çalıştırmadığımız için herhangi bir şey olmadı. 19.satırda gameTimer.start() ile sayacımızı aktif hale getiriyoruz.
12 13 14 15 16 17 18 19 20 | public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); gameTimer = new Timer( 25 ); gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy ); gameTimer.start(); } |
Tekrardan kaydedin ve oyunu tekrardan çalıştırın. Bu sefer düşman objemizin aşağıya doğru hareket etmesi lazım.
Avatarımızı Ekleyelim
Buradan itibaren avatar olarak bahsedeceğim obje bizim kontrol edeceğimiz obje olacak. Düşman objesini oluşturduğumuza benzer şekilde FLA dosyasında bir MovieClip oluşturun ve isim olarak Avatar yazın. İstediğiniz bir şeyler çizin. Biz burada bir kurukafa kullanıcaz.

1 2 3 4 5 6 7 8 9 10 11 | package { import flash.display.MovieClip; public class Avatar extends MovieClip { public function Avatar() { } } } |
Aynı şekilde kütüphaneden bu sınıfı Avatar isimli MovieClip'e bağlayın.
Oluşturduğumuz Avatar şimdilik sadece imleci takip edecek yani Avatarımızı mouse ile kontrol edeceğiz.
AvaiderGame.as dosyamıza geri dönelim ve Avatarımızı oyuna ekleyelim. Avatarımızı enemy objesine eklediğimize benzer bir şekilde ekliyoruz. Satır 10,18 ve 19:
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class AvoiderGame extends MovieClip { public var enemy:Enemy; public var avatar:Avatar; public var gameTimer:Timer; public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); avatar = new Avatar(); addChild( avatar ); gameTimer = new Timer( 25 ); gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy ); gameTimer.start(); } public function moveEnemy( timerEvent:TimerEvent ):void { enemy.moveDownABit(); } } |
Eğer oyunu bu haliyle test ederseniz avatarın sol üstte olduğunu göreceksiniz. Eğer oluşturduğunuz objeye x,y koordinat değeri atamazsanız Flash objeyi (0,0) noktasına yerleştirir. Avatarın mouse'un olduğu yere gitmesi için kullanacağımız özellikler MovieClip sınıfına ait mouseX ve mouseY özellikleri. MovieClip sınıfını extends özelliğiyle kullanabildiğimiz için bu özellikleri kullanabiliriz. Satır 20 ve 21'de bu işlemi yapıyoruz yani avatarın x değerini mouse'un x değerine, y değerini mouse'un y değerine atıyoruz.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public function AvoiderGame() { enemy = new Enemy(); addChild( enemy ); avatar = new Avatar(); addChild( avatar ); avatar.x = mouseX; avatar.y = mouseY; gameTimer = new Timer( 25 ); gameTimer.addEventListener( TimerEvent.TIMER, moveEnemy ); gameTimer.start(); } |
Bu şekilde test ettiğinizde avatar mouse'un olduğu yerde ortaya çıkacak ancak bu kod sadece 1 kez çalıştırıldığı için muhtemelen siz bunu göremeyeceksiniz. Bildiğiniz gibi bizim 25 milisaniyede bir çağırılan bir fonksiyonumuz var. Yazdığımız 2 satırlık x y koordinat kodunu bu fonksiyonun içine de yazarsak avatarımız imleci takip eder. 31 ve 32. satırlara da aynı kodu yazıyoruz:
28 29 30 31 32 33 | public function moveEnemy( timerEvent:TimerEvent ):void { enemy.moveDownABit(); avatar.x = mouseX; avatar.y = mouseY; } |
Bu noktada fonksiyonun ismi olarak moveEnemy() pek mantıklı olmadı, çünkü aynı zamanda Avatarın hareketlerini de kontrol ediyor. Bu sebeple fonksiyonun ismini moveEnemyAndAvatar() olarak değiştiriyorum.
28 29 30 31 32 33 | public function moveEnemyAndAvatar( timerEvent:TimerEvent ):void { enemy.moveDownABit(); avatar.x = mouseX; avatar.y = mouseY; } |
Fonksiyonun ismini değiştirdiğimiz için gameTimer'a ekldiğimiz olay dinleyicisinde de fonksiyonumuzun ismini değiştirmeliyiz.
24 | gameTimer.addEventListener( TimerEvent.TIMER, moveEnemyAndAvatar ); |
Her şeyi kaydedin ve oyunu test edin. Avatarın imleci takip etmesi lazım.(burada şunu da belirteyim ki takip etmekten kastım avatarın "mouse pointer" gibi kullanılması-bu kelime için uygun bir Türkçe karşılık bulamadım)

Objelerin Birbirleriyle Etkileşimi
Belki farketmişsinizdir eğer avatarımız düşmana değerse an itibariyle hiç bir şey olmuyor. Şimdi bu kısma el atıyoruz.
Peki birbirlerine deydiklerini nasıl test edebiliriz? MovieClip sınıfının hitTestObject isminde bir fonksiyonu mevcut Bu fonksiyon 2 objenin birbirine değip değmediklerini test eder. Bu fonksiyonu kullanarak iki objenin birbirine değip değmediklerini test edeceğiz.Satır 34 37 arası bu işlemi yapıyor.
28 29 30 31 32 33 34 35 36 37 38 | public function moveEnemyAndAvatar( timerEvent:TimerEvent ):void { enemy.moveDownABit(); avatar.x = mouseX; avatar.y = mouseY; if ( avatar.hitTestObject( enemy ) ) { } } |
- avatar.hitTestObject( enemy ) — eğer avatarımız düşmana değiyorsa bu ifade true değerini çevirecek
- if — if kelimesi eğer anlamına gelir. Eğer if kelimesinden sonraki parantezler arasındaki ifade true(doğru) ise süslü parantezler arasındaki kısım çalıştırılır. False(yanlış) ise hiç bir işlem yapılmaz.
Şimdilik süslü parantezler arasında hiç bir şey yok yani birbirlerine değseler bile hiç bir şey olmayacak. Bu noktada fonksiyonumuzun(moveEnemyAndAvatar) ismini tekrar değiştirme ihtiyacı hissediyoruz. Çünkü artık bu fonksiyon objelerin birbirine değip değmediğini de kontrol ediyor. Şöyle bir isim kullanabiliriz ama işler baya karışır :) moveEnemyAndAvatarAndAlsoCheckToSeeIfTheyHaveCollided. Bunun yerine başka bir kelime kullancağız:
- Tick — gameTimer her 25 milisaniyede bir tikliyor(bunu başka nasıl ifade edebilirdim bilemedim) Bu sebeple bu fonksiyonu Tick diye adlandırıyoruz.
Böylece fonksiyonun ismini onTick olarak değiştiriyoruz:
28 29 30 31 32 33 34 35 36 37 38 | public function onTick( timerEvent:TimerEvent ):void { enemy.moveDownABit(); avatar.x = mouseX; avatar.y = mouseY; if ( avatar.hitTestObject( enemy ) ) { } } |
gameTimer'a eklediğimiz olay dinleyicisindeki fonksiyon ismini de değiştirmeyi unutmayın.
Son olarak avatar düşmana değdiğinde oyunun bir şeyler yapması lazım. Henüz fazla detaylı şeyler görnmediğimiz için sadece sayacımızı durduracağız böylece oyunda duracak. Şimdilik bununla idare edeceğiz :). Satır 34:
28 29 30 31 32 33 34 35 36 | public function onTick(event:TimerEvent):void { enemy.moveDownABit(); avatar.x=mouseX; avatar.y=mouseY; if (avatar.hitTestObject(enemy)) { gameTimer.stop(); } } |
Her şeyi kaydedin ve oyunu test edin. Söylediğim gibi düşmana değdiğinizde oyunun durması lazım. Buradan 2 şey öğrenebiliriz.
- Uyguladığımız çarpışma kontrol sistemimiz(fonksiyonumuz) çok kötü
- İleride oyunumuza pause(oyunu durdurma) eklememiz çok kolay olacak.
Sonuç
Buraya kadar çok basit olarak Avoider tipi bir oyun yaptık. Buraya kadar yaptığımız işlemlerin kaynak dosyasını burdan indirebilirsiniz.
2.Bölüm Buradan
2.Bölüm Buradan


0 yorum:
Yorum Gönder