Java'da Plants vs. Zombies'in basit bir sürümünü yazın

Yazar | Lin Lychee

Kaynak | programcı Xiaohui

Önsöz

Hiç Bitkiler vs Zombies oynayan oldu mu?

Bir Xiao Hui okuyucusu, Java'da kendi Plants vs. Zombies oyununu geliştirdi. Sistem nispeten basit olmasına rağmen, serçe küçük ve eksiksizdir ve oyun geliştirmeyle ilgilenen arkadaşlar bunu öğrenebilir ~~

oyun tasarımı

Plants vs. Zombies'de küçük bir oyun seviyesi vardır.Ekranın hemen üzerinde rastgele bitki oluşturacak bir silindir makinesi vardır.Oyuncular, yerleştirmek için çimleri seçmek için bitkileri serbestçe seçebilirler. Bu oyun moduna dayanarak seviyeyi çıkardım ve Plants vs. Zombies'in basit bir versiyonunu yaptım. Oyun ekranı kabaca şu şekildedir:

Bitkinin kartı, ekranın sol tarafında otomatik olarak oluşturulacak ve seçmek için tıklandıktan sonra çimenlere yerleştirilebilir. Zombiler otomatik olarak sağ tarafta oluşturulur. Farklı zombilerin farklı hareket hızları ve farklı kan hacimleri vardır. Bazı zombilerin gizli ödülleri vardır, örneğin: tam ekran zombi statik, tam ekran zombi ölümü vb. O sırada, ekran görüntüsünün zamanlamasını kontrol etmeyi zorlaştıran oyun duraklatma işlevi yoktu. İşte oyun duraklatma işlevinin nasıl yapılacağı.

Duraklatmanın en basit yolu, fareyi ekrandan uzaklaştırmaktır ve oyun duraklatılır. Yani burada bir fare dinleyici olayı tanıtmanız gerekiyor.

public void mouseMoved (MouseEvent e) {// Oyun çalışırken if (status == start) {// Fare hareketi olay nesnesi aracılığıyla geçerli fare konumunu alın int x = e.getX; int y = e.getY ; // Fare oyun arayüzünün ötesine geçerse if (x > Game.WIDTH || y > Game.HEIGHT) {// Oyunun durumunu duraklatıldı durumuna değiştir = duraklat;}}}

Elbette bu, farenin konumunu izleyerek oyunun durumunu değiştirmenin basit bir yoludur. Bir tuşa basıldığında oyunu duraklatmak için klavye dinleyiciyi de kullanabilirsiniz, bu da daha iyi bir kullanıcı deneyimi sağlar. Ancak prensip aynıdır, bu nedenle kod burada gösterilmemiştir.

Oyun nesnesi

İlk önce oyunda hangi nesnelerin olduğunu analiz edin. Her çeşit bitki, her çeşit zombi, her türlü mermi. Daha sonra burada üç ana tip, yani bitkiler, zombiler ve mermiler çizilebilir. Nesne yönelimli olarak, alt sınıf, ana sınıfın tüm özelliklerini ve yöntemlerini miras alır. Bu nedenle, üç kategorinin ortak özellikleri ve yöntemleri, kendi ana kategorilerine çıkarılabilir. Örneğin, zombi ebeveyn:

public abstract class Zombie {// Zombie parent class // Zombiler tarafından paylaşılan öznitelikler korumalı int genişliği; korumalı int yüksekliği; korumalı int canlı; korumalı int x; korumalı int y; ...... // Zombi durumu genel statik son int LIFE = 0; public static final int ATTACK = 1; public static final int DEAD = 2; protected int state = LIFE; / * * Ana sınıfın neden soyut bir sınıf olduğuna ilişkin bir ek burada, örneğin, her zombinin bir hareket yöntemi vardır, * Ancak her zombi farklı bir şekilde hareket eder, bu nedenle bu yöntemin yöntem gövdesi farklı olabilir. * Soyut yöntemin yöntem gövdesi yoktur. Alt sınıfta yeniden yazabilirsiniz. * Ancak soyut yöntemlere sahip sınıf, Soyut sınıf, dolayısıyla ana sınıf genellikle soyut sınıftır * / // Hareket yöntemi public abstract void step; ....}

Aynısı bitki ana öğesi ve ana madde için de geçerlidir.

Yukarıda belirtildiği gibi, alt sınıflar tarafından paylaşılan yöntemlerin üst sınıftan çıkarılması gerekir, bu nedenle bazı alt sınıflar tarafından paylaşılan yöntemlerle nasıl başa çıkılır? Örneğin, bezelye atan ve buz atan mermi ateşleyebilir, ancak Somun Duvarı ateş etmez. Yani burada arayüzü (Arayüz) kullanmanız gerekir.

public interface Shoot {// Arayüzün çekilmesi - bazı alt sınıflar tarafından paylaşılan davranışların arayüze çıkarılması // Arayüzdeki yöntemler varsayılan olarak genel soyuttur ve standart kodlama bu alanı genel soyut Bullet shoot;}

Şimdiye kadar, oyun nesnesinin özellikleri ve yöntemleri temel olarak tanımlanmıştır.Resmin gösterimi ve resmin nasıl çizileceğine gelince, sadece burada açıklanmayacak olan ilgili API'yi kullanmanız gerekir. Bir yıl çalıştıktan sonra geriye dönüp baktığımızda, burada optimize edilebilecek birçok şey var. Örneğin, hedefin kan hacmi, saldırı gücü, hareketi vb. Yapılandırma dosyasına yazılabilir, böylece oyun parametrelerini ayarlamaya gitmenize gerek kalmaz. Kodun içeriğini değiştirmek için, sadece konfigürasyon dosyasındaki parametreleri değiştirmeniz gerekir.

Oyun içeriği

Artık oyunun nesnelerine sahip olduğumuza göre, nesneleri oyuna eklemenin zamanı geldi, sonra hareket etmelerine izin verin ve sonunda savaşmalarına izin verin. Öncelikle objeyi oyuna ekleyelim, ben böyle yaptım işte zombi örneği:

// Öncelikle, bir zombi koleksiyonu olmalı // zombi koleksiyonunun Özel Listesi < Zombi > zombiler = new ArrayList < Zombi > ; // Daha sonra rastgele zombi oluşturma yöntemini tanımlayın public Zombie nextOneZombie {Random rand = new Random; // Farklı zombi türlerinin olasılığını kontrol edin int type = rand.nextInt (20); if (type < 5) {yeni Zombie0 döndür;} else if (tür < 10) {yeni Zombie1'i döndür;} else if (tür < 15) {yeni Zombie2'yi iade et;} yoksa {yeni Zombie3'ü iade et;}} // Zombi girişi // Giriş aralığını ayarlayın / ** İşte bu yüzden giriş aralığını ayarlamamız gerekiyor * Oyun bir zamanlayıcıya göre çalıştığı için * Zamanlayıcı, arada bir eklediğiniz zamanlamayı çalıştıracak Oyun oyuncusunun yöntemi, * Yani burada oyunun hızını kontrol etmek için giriş aralığını ayarlamanız gerekiyor. * / int zombieEnterTime = 0; public void zombieEnterAction {zombieEnterTime ++; // kendiliğinden artan zombieEnterTime'ın kalanını hesapla if (zombieEnterTime% 300 == 0) {// Koşullar karşılandığında rastgele zombi oluşturma yöntemini çağırın ve zombiler oluşturun Zombies.add (nextOneZombie);}} zombi kümesine ekleyin

Kullandığım ilk veri yapısı bir diziydi, ancak sonraki kodlamada zombi nesneler için birçok geçiş, toplama ve silme işlemi olduğunu buldum.Dizilerin toplama ve silme işlemleri çok zahmetli ve karmaşık, bu yüzden onları koleksiyonlarla değiştirdim. Aynısı işte de geçerlidir.Önce kodlamayı düşünmek, doğru veri yapısını seçmek çoğu zaman çabanın yarısı ile iki kat daha fazla sonuç alabilir.

Bitki kabulünün tasarımı, çok ince olduğunu düşündüğüm bir noktaydı. O sırada kodlamada bulunan problemlerden bahsedeyim. Öncelikle fabrikalar sahaya girdiklerinde merdaneli makinenin üzerindedir ve merdaneli makinedeki hareket takip etme ve durma problemini içerecektir. Takip etmenin yolu elbette bir önceki bitki kartını kovalamaktır, ancak ilk bitki kartı seçilip çimlere yerleştirildiğinde nasıl takip edilir?

İlk yaklaşımım, bu sorunu çözmek için tesise birkaç durum daha eklemekti, ancak çok fazla durumun if kararındaki koşulları büyük ölçüde artıracağını ve denedikten sonra hala istenen etkiyi elde edemediğini gördüm, bu yüzden tesisi değiştirdim. Koleksiyon ikiye ayrılıyor.Oyun fonksiyonunun tasarımında daha sonra geriye dönüp baktım ve bitki koleksiyonunun silindir makinedeki koleksiyona ve savaş alanındaki koleksiyona bölündüğünü gördüm. Lütfen beni dinle:

// Silindir makina üzerindeki tesis, durum durur ve bekle özel Liste < Bitki > bitkiler = new ArrayList < Bitki > ; // Savaş alanındaki bitkilerin durumu can ve harekettir - hareket, fare ile seçilip hareket ettirilme durumudur.Buradaki tasarım mantıksızdır, bu da arkada bir HATA Özel Listesi oluşturacaktır. < Bitki > PlantsLife = new ArrayList < Bitki > ; // Valsli makinedeki fabrikaların çarpışma tespiti public void plantBangAction {// (int i = 1; i için ikinciden başlayarak silindirli makinedeki bitki setini çaprazlayın) < Plants.size; i ++) {// İlk bitkinin y değeri 0'dan büyükse ve durma durumundaysa, durum beklemek için değiştirilir (bitkiler.get (0) .getY > 0plants.get (0) .isStop) {Plants.get (0) .goWait;} // i'inci bitki y, i-1 bitkisinin y + yüksekliğinden küçükse, bu karşılandığı anlamına gelir ve durmak için i'nin durumunu değiştirin eğer ((Plants.get (i) .isStop || Plants.get (i) .isWait) (Plants.get (i-1) .isStop || Plants.get (i-1) .isWait) Plants.get ( i) .getY < = bitkiler.get (i-1) .getY + bitkiler.get (i-1) .getHeight) {bitkiler.get (i) .goStop;} / * * Eğer i-inci bitki y, i-1 bitkisinden daha büyükse Y + yüksekliği, dokunulmadığı veya i-1'inci * bitkisinin kaldırıldığı anlamına gelir. İ'nin durumunu beklemeye değiştirin ve yukarı çıkmaya devam edebilirsiniz * / if (bitkiler.get (i) .isStop bitkiler. get (i) .getY > Plants.get (i-1) .getY + Plants.get (i-1) .getHeight) {Plants.get (i) .goWait;}}} // Silindir makinesindeki tesis durumunu kontrol edin public void checkPlantAction1 {// Yineleme Yineleyici < Bitki > it = Plants.iterator; while (it.hasNext) {Plant p = it.next; / * * Silindir makine setinde hareket halinde veya yaşam durumunda olan bitkiler varsa *, bunları savaş alanı bitkileri setine ekleyin ve orijinal diziden çıkarın Sil * / / * * Artık, tekerlekli makinede hareket halindeki bitkileri savaş alanındaki * fabrika koleksiyonuna eklemenin, çalışmak için en iyi zaman olması * gerektiği, eklemeden önce tesis durumunun canlanmasını bekleyin. * / if (p.isMove || p.isLife) {PlantsLife.add (p); it.remove;}}}

Elbette, tekerlekli makinedeki bitkilerin durumunu değerlendirme kodu hala sarsıntılı ve tam da bu kodu optimize etmek istediğimde, oyun tasarım sürecini ve oyun kodunu paylaşma fikrine sahip oluyorum. Şimdi bu kodun nasıl optimize edileceğinden bahsedelim:

// Önce durumu açıklayın // bekleyin - bitki kartı tekerlekli makinede hareket ediyor, çünkü fare ile seçilmeyi bekliyor, bu yüzden bekle olarak adlandırılır // durdur - tekerlekli makinede bitki kartı durur, iki tip vardır Durum, 1-ilk 2-vuruş önceki karta ulaştı // Aşağıdaki kodu optimize etmeye başla // i-inci bitki y, i-1 tesisinin y + yüksekliğinden küçükse, bu karşılandığı anlamına gelir, i'yi değiştirin Durum durdur // if ((Plants.get (i) .isStop || Plants.get (i) .isWait) // (Plants.get (i-1) .isStop || Plants.get (i-1) .isWait) // Plants.get (i) .getY < = Plants.get (i-1) .getY + Plants.get (i-1) .getHeight //) {// Plants.get (i) .goStop; //} // Optimize edilmiş kod şuna benzer / / Karmaşık bir booleanı birden çok if koşuluna böler if (! (Plants.get (i) .isStop || Plants.get (i) .isWait) {break;} if (! (Plants.get (i-1 ) .isStop || Plants.get (i-1) .isWait)) {break;} if (! (Plants.get (i) .getY < = bitkiler.get (i-1) .getY + bitkiler.get (i-1) .getHeight)) {break;} Plants.get (i) .goStop;

Elbette boole koşulları da optimize edilebilir ve hatta bitkilerin durumu basitleştirilebilir. Oyunun kuralları gereği zombiler sadece çimdeki bitkilere saldırabilir, bu nedenle kemer ile yerleştirilen bitkileri ve çimin üzerindeki bitkileri ikiye bölmek oldukça makul ve hassastır. Bir zombinin bir bitkiye saldırıp saldırmadığına karar verirken, yalnızca çimenlikteki bitki koleksiyonunu geçmeniz gerekir. Bölünmezseniz, bir zombinin bir bitkiye saldırıp saldırmadığını belirlemek istediğinizde, taranması gereken koleksiyon tüm bitki koleksiyonları olacaktır ve bitkinin çimenlikte mi yoksa merdanede mi olduğunu ayırt etmek için en az 2 durum eklemeniz gerekir. Bu kodu düşünün. Kokulu ve uzun.

O zaman konuları hareket ettirme zamanı. Daha önce de belirtildiği gibi, ebeveyn sınıfındaki hareket yöntemi soyut bir yöntemdir.İlgili alt sınıflarda yeniden yazıldıktan sonra, farklı nesne hareket yöntemleri çeşitlidir.

// Mermi hareketi public void BulletStepAction {for (Bullet b: bullets) {b.step;}} // Zombi hareketi // Hareket aralığını ayarla int zombieStepTime = 0; public void zombieStepAction {if (zombieStepTime ++% 3 == 0) { for (Zombie z: zombies) {// Yalnızca yaşayan zombiler hareket ederse (z.isLife) {z.step;}}}}

Koddaki koleksiyonun karmaşık geçişine baktığımda, lambda ifadelerinin gerçekten iyi şeyler olduğunu düşünmek zorundayım:

// Bullet move public void BulletStepAction {bullets.forEach ((b) - > b.adım); ....}

Lambda ifadelerinin güçlü işlevlerini göstermenin hala bir yolu yok gibi görünüyor.Lütfen aşağıdaki örneğe bakın:

// Ürünlerin sürekli değişen ihtiyaçlarıyla baş edebilmek için, öncüllerin deneyimlerini özetledikleri tasarım kalıpları bu sorunla bir dereceye kadar baş edebildi. // Kalıpları tasarla, strateji arayüzünü bildir ve uygulama sınıfı public List'de filtreleme mantığını tamamla < Öğrenci > filterStudentByStrategy (Liste < Öğrenci > öğrenciler, SimpleStrategy < Öğrenci > strateji) {Liste < Öğrenci > filterStudents = new ArrayList < > ; for (Öğrenci öğrenci: filterStudents) {if (strategy.operate (öğrenci)) {filterStudents.add (öğrenci);}} return filterStudents;} // Gereksinimler değiştiğinde, yalnızca strateji arayüzünün uygulama sınıfında değiştirilmesi gerekir Yargı mantığı genel arayüz SimpleStrategy olabilir < T > {public boolean operation (T t);}

Ama biraz zahmetli görünüyor.Arayüzler ve uygulama sınıfları yazmak gerekiyor.Sonraki bakım da bir baş ağrısı. Şu anda kurtarıcı lambda ifadesi ortaya çıkıyor:

// Gereksinim Listesinde hızlı değişiklikler elde etmek için arayüze gerek yok < Öğrenci > lambdaStudents = öğrenciler.stream.filter (öğrenci- > student.getGender == 1) .collect (Collectors.toList);

Bakalım yukarıda ne oldu. İlk olarak, veri toplama akışı yapılır ve ardından filtre yöntemi çağrılır Güçlü lambda ifadesi kodu kısa yapar ve karar koşulunun değiştirilmesi, strateji arayüzünün uygulama sınıfında bakım olmaksızın doğrudan kodda korunabilir. Son olarak bir koleksiyona dönüştürülür ve ürünün ihtiyacını karşılayan bir koleksiyon iade edilir.

Konuya geri dönersek, konular nasıl kavga ettirilir? İşte bitkilere saldıran zombilere bir örnek:

// Zombi üst sınıfı, zombilerin saldırı yöntemini tanımlar. // Zombilerin saldırı davranışları aynı olduğundan, normal yöntem şu şekildedir. // Zombiler bitkilere saldırır public boolean zombieHit (Plant p) {int x1 = this.xp. getWidth; int x2 = this.x + this.width; int y1 = this.yp.getHeight; int y2 = this.y + this.width; int x = p.getX; int y = p.getY; dönüş x > = x1 x < = x2 y > = y1 y < = y2;}

Resim ile birleştirildiğinde, yukarıdaki kod daha iyi anlaşılmalıdır. Siyah çerçeve P bitkileri ve siyah çerçeve Z bitkileri temsil eder Noktalı çizgi ikisi arasındaki sınır mesafesini ifade eder.Zombi noktalı çizgiye girdiğinde bitkiye saldırması garanti edilir.

// Zombi saldırısı // Saldırı aralığını ayarlayın int zombieHitTime = 0; public void zombieHitAction {if (zombieHitTime ++% 100 == 0) {for (Zombie z: zombies) {// Savaş alanında bitki yoksa, tüm zombilerin durumunu ayarlayın Hayata geçin / * * İşte bu yüzden önce tüm zombilerin durumunu, yani mobil durum olan yaşam durumuna değiştirmemiz gerekiyor * Çünkü zombinin bitkiye saldırıp saldırmadığına dair aşağıdaki yargı, savaş alanındaki bitki koleksiyonunu dolaşmaktan başlıyor * Bir zombi bitki yiyorsa ve savaş alanındaki tek bitki yenirse, * O zaman zombinin durumu saldırmaktan hareket etmeye değişecek? * İşte tersine düşünmenin kullanımı, önce tüm zombileri mobil duruma getirin * Saldırı koşulları karşılandıysa, ardından saldırı durumuna geçin, * Savaş alanında bitki olmasa bile, zombiler hala hareketli durumda * / if (! z.isDead) {z.goLife;} // (Plant p: PlantsLife) için savaş alanında dolaşılacak bitkilerin toplanmasıyla ilgili bir karar verilmelidir {// zombi yaşıyorsa ve bitki yaşıyorsa , Ve zombiler saldıran bitkilerin menziline giriyor / * * Burada bir hata var, zombiler fare tarafından seçilen ve bırakılmamış bitkilere saldıracak. * Bu nedenle aşağıdaki değerlendirme koşullarının da fare tarafından seçilen bitkileri kaldırması gerekiyor * / if ( z.isLife! p.isDeadz.zombieHit (p)! (p instanceof Spikerock)) {// zombi durumu saldırı durumuna değiştirildi z.goAttack; // Bitkiler kan kaybediyor p.loseLive;}}}}}

Bazı efekt ofseti varsa, nedeni resimlerin farklı boyutlarının neden olduğu koordinat ofsetidir.Resimlerin tümü çevrimiçi olarak bulunduğundan, efekt pek ideal değildir.

Bu noktada oyunun temel işlevleri temelde gerçekleşmiş oluyor. Java, nesne yönelimli bir dildir, her şey bir nesnedir, özellikler niteliklerdir ve davranışlar yöntemlerdir. Çıplak gözle görülebilen zombiler, bitkiler ve çimenlerin hepsi nesnelerdir.Kan hacmi ve hareket hızı gibi nesne özellikleri niteliklerdir.Hareket, saldırı ve ölüm gibi nesne davranışlarının hepsi yöntemlerdir.

Oyun işlevinin optimizasyonundan bahsedelim.

Oyun optimizasyonu

Zaten yerleştirilmiş olan çimen artık bitkileri yerleştiremez. Önceden, çim iki boş ve bekletme durumunda tasarlanıyordu, ancak şimdi sadece doğru ve yanlışı döndürmemiz ve tüm bitki koleksiyonunu sanal bir boole koleksiyonu olarak tanımlamamız gerekiyor.

2. Bitkileri uzaklaştırmanın optimizasyonu

Tasarım fikri, yeni bir kürek nesnesi eklemektir:

// kürek koleksiyonu özel Listesi < Kürek > kürekler = new ArrayList < Kürek > ; // Shovel Entry public void shovelEnterAction {// Yalnızca bir kürek if (shovels.size == 0) {shovels.add (new Shovel);}) // Bir kürek Yineleyici kullanın < Kürek > it = kürekler.iterator; Yineleyici < Bitki > it2 = PlantsLife.iterator; while (it.hasNext) {Shovel s = it.next; // Kürek hareket ediyorsa, bitki koleksiyonunu çaprazlayın if (s.isMove) {while (it2.hasNext) {Plant p = it2 .next; int x1 = p.getX; int x2 = p.getX + p.getWidth; int y1 = p.getY; int y2 = p.getY + p.getHeight; if ((p.isLife || ((Blover ) p) .isClick) Mx > x1Mx < x2My > y1My < y2shovelCheck) {// bitkileri kaldır it2.remove; // küreği kaldır it.remove; shovelCheck = false;}}}}

Bu son derece karmaşık ve görünüşte güçlü koda baktığımda, yine acımasız bir el olma fikrine kapıldım, ancak onu yerli tutmak için buna direndim. Bu yüzden bir HATA buldum. Kürek seçilirse ve savaş alanındaki tek bitki zombi tarafından yenirse, kürek her zaman fareyi takip edecek ve kullanımdan sonra eleme etkisini elde edemeyecektir. Çözüm elbette çok basit.Savaş alanındaki bitki koleksiyonunun boyutu 0 olduğunda, kürek koleksiyonunu boşaltın.

3. Oyun oynanabilirliğinin optimizasyonu

Yukarıdaki oyun tasarımında bahsedilen zombiler öldürüldükten sonra rastgele elde edilebilecek ödül türleri bu şekilde gerçekleşmektedir. Yine de tasarım analizinden başlayarak, tüm zombi türleri ödüllendirilemez, bu nedenle ödül arayüze yerleştirilmelidir:

public interface Award {// Award arayüzü / * * Burada hala bir kod düzensizliği sorunu var * Varsayılan arayüz yöntemi genel soyuttur * Arayüzdeki değişkenler varsayılan olarak public static final * Bu varsayılan alanlar atılmalıdır * / // Tam ekran Statik public static final int CLEAR = 0; // tam ekran net public static final int STOP = 1; public abstract int getAwardType;}

Bir zombi öldüğünde, zombinin bir ödül arayüzüne sahip olup olmadığını belirlemek ve öyleyse, ilgili ödül yöntemini uygulamak gerekir:

// Zombi durumunu algıla herkese açık void checkZombieAction {// Yineleyici Yineleyici < Zombi > it = zombies.iterator; while (it.hasNext) {Zombie z = it.next; // Zombie z = it.next; // Zombinin kan hacmi 0'dan küçükse ölür ve ölü zombi koleksiyondan silinir if (z.getLive < = 0) {// Bir zombinin ödül alıp almadığını belirleyen bir arayüz if (z instanceof Award) {Award a = (Award) z; int type = a.getAwardType; switch (type) {case Award.CLEAR: for (Zombie zo: zombiler) {zo.goDead;} break; case Award.STOP: for (Zombie zom: zombies) {zom.goStop; timeStop = 1; // zombieGoLife;} break;}} z.goDead; it.remove;} / / Zombi eve koşar ve oyun ömrü bir azalır ve eğer (z.OutOfBound) {gameLife--; it.remove;}}} ise zombi silinir

4. Oyun arka plan müziği ekleyin

bgm, bir oyunun ruhlarından biridir. Burada oyuna arka plan müziği eklemek için, benim seçimim müziğin analizi ve oynatılmasına adanmış yeni bir iş parçacığı oluşturmak:

// Müzik yüklemek için iş parçacığı başlat Runnable r = new zombieAubio ("bgm.wav"); Thread t = new Thread (r); t.start; public class zombieAubio, Runnable {// ses WAV formatını okumak için özel iş parçacığı uygular private String dosya adı; public zombieAubio (String wavfile) {filename = wavfile;} ......

Java'da müzik ayrıştırma API'sinin yalnızca WAV formatındaki dosyaları desteklediğini ve çoğu müzik çaların dosya formatı dönüştürme yapabildiğini burada belirtmek gerekir.

Takip optimizasyonu

1. Bitki türlerinin genişlemesi ve ilgili işlevlerin gerçekleştirilmesi

Örneğin, en ölümcül mısır topu. Sentezlemek için 4 küçük mısır gereklidir, bu nedenle mısır topunun sentezlenip sentezlenemeyeceğine karar verirken, koordinat kararını vermek için bitki koleksiyonunun çaprazlanması gerekir.Bu nedenle, sentezlenebilir bitkilerin ayrı bir koleksiyona yerleştirilmesi önerilir. Sentetik kararlar vermek çok daha basittir Koleksiyonun boyutu 4'ten küçük olduğunda, sentezin başarısız olduğunu gösterebilir. Aynı şey donmuş karpuzun tasarım fikri için de geçerli.

2. Sırıkla atlama zombileri, dans eden zombiler vb. Gibi aksiyon zombilerinin eklenmesi.

Sırıkla atlama zombilerinin tasarım fikrinden bahsedin.Diğer zombilerle karşılaştırıldığında bu tür zombilerin fazladan bir sıçrama davranışı vardır, yani ayrı bir yöntem ve ayrı bir durum olacaktır. Ayrıca, atlama yalnızca bir kez tetiklenebilir, bu nedenle sırıkla atlama zombisinin durum değişikliği yürüyor olmalıdır. > Bitkilerin üzerinden atla > Bir bitki ile karşılaştığınızda, saldırmaya başlayacaksınız.Bir durum değişikliği gerçekleştirirken, mevcut durumun hala atlayıp atlayamayacağını düşünmelisiniz.

3. Bitkinin saldırı menzilinde zombi olmadığında, bitki saldırmayı durdurur

Basitçe şunu çekin: Tesis saldırı yöntemini çalıştırdığında, aynı Y koordinatına sahip zombiler olup olmadığını kontrol edin.

GitHub kaynak kodu:

https://github.com/llx330441824/plant_vs_zombie_simple.git

Konteyner gelecek mi?
önceki
Alibaba eğlence testi savaşı: makine öğrenimi + sıcak bağlantı önerisine dayalı drenaj, karşılaştırma testini daha doğru hale getiriyor
Sonraki
CVPR 2020 için seçilen meydan okuma kağıdı hakkında ne yazdınız?
DCP iletiminin verimliliğini artırmak için Ali mühendisleri bunu yaptı
Yukarı kaldırın! Ali Pingtou'nun hazırladığı üç makale ISCA tarafından seçildi
Wuling Bölgesi, Danzhou Kasabası, medeniyet, fedakarlık, ağaç ve yeni tarz temalı bir tanıtım ve ikna etkinliği başlattı
Zhangjiajie Yangını, Qingming Festivalinden Önce Yangın Propaganda Hizmetini Başlattı
Sangzhi İlçesi İtfaiye Tugayı, "Devrimci Şehitleri Hatırlamak ve Uygar Kurbanı Savunmak" ı başlattı
Guizhou'nun son partisi Hubei sağlık ekibine yardım etti Guiyang'a döndü
"3 Mart Zhuang Nationality" Guangxi People's Network Cloud "Gangge Fuarı
Fuzhou, Hubei göçmen işçilerinin ilk partisini işe geri döndürmek için araba kiraladı
Merkezi medya, övgülerini 00 savaş sonrası salgınına iletti! Nandu'nun salgın karşıtı tema animasyonu İnternette sıcak bir yayına başladı
Kadrolar turizmde başı çekiyor ve hafta sonları 2,5 gün izin alıyor. Jiangxi turizmini kurtarma ve canlandırma önlemleri "zor".
İlkbahar Ekinoks Günü: On millik bahar esintisi "kiraz", eve git, pamuk ağacı çok güzel, kahramana Guangdong'a hoş geldin
To Top