Biraz değişiklik olsun diye, biraz geliştirici günlüğü tutmak istiyorum. Bir süre önce bir oyun yarışmasına katıldım ve bu oyunu - Fareler ve Kötü Seçimler - fareleri dışarı çekmek için labirentin etrafına peynir yerleştirdiğiniz kısa bir bulmaca oyunu yaptım. Eğlenceliydi ama bazı eksiklikler olduğu belliydi.
Bunlardan en önemlilerinden biri farelerin davranışlarının sezgisel olmamasıdır. Oyuncular, farelerin sadece dondurulmasını değil, sevilmeyen bir peynirin de itilmesini beklediklerini belirttiler. Ayrıca, bu mekaniğin uygulanması çok daha zengin bir bulmaca tasarımına olanak tanıyacaktır.
Dolayısıyla bunun Godot'ta otomatik testlerin yapılabilmesi için iyi bir fırsat olduğunu düşünüyorum.
Godot 4 için kullanılabilen birkaç test çerçevesi var, ancak I'imi yakalayan Godot Unit Test (GUT) oldu. GUT oldukça basittir:
test_
ile başlayan işlevler ekleyin ve bazı iddialar yazın; tipik birim test yapısı.
Bu özel durum için, karmaşık senaryoları, oyunun seviyelerini tanımladığım gibi, kod yerine motor editöründe tanımlamanın bir yoluna sahip olmak istedim (bu şekilde testler gerçeğe daha yakın olurdu). Bu nedenle şunları yapmak istiyorum:
O halde bunu açalım.
Yeni bir `MouseTestCase` sınıfı tanımlayalım. Onun Node2D
miras almasını istiyoruz (onu bir sahneye yerleştirmek istediğimiz gibi. Ve onun alt öğelerinden birini (sahneye kendimiz yerleştireceğimiz) bulmasını istiyoruz: bir fare ve beklenen son konumu (İşaretçi olarak)
extends Node2D class_name MouseTestCase @export var steps_left = 0 # How many steps to simulate @export var done = false @onready var mouse: Mouse = $Mouse @onready var expected_position = SnapUtils.get_tile_map_position($TestMarker.position)
Artık bunu sahneye koyabiliriz ve iyiyiz! Farenin nerede başladığını, nerede bitmesi gerektiğini ve kaç adımda biteceğini biliyoruz.
Şimdi bunlardan bir grup daha oluşturalım ve itici davranışımızı test etmek için bir harita hazırlayalım.
Bu davranış biraz karmaşık olduğundan, birbirinden biraz farklı birçok durumu ele almak istiyoruz:
Bu davranışı kapsayacak 12 test senaryosunu tanımlayan sonuçta ortaya çıkan harita yukarıda gösterilmiştir (tüm bu koordinatları koda sabit kodlamanın ne kadar sıkıcı olabileceğini hayal edin).
Yapılacak tek şey test çalıştırıcı işlevidir. Fonksiyonun şunları yapması gerekir:
Kod oldukça basit.
func run_level_with_mouse_test_cases(map_path: String): var level = load(map_path) map.load_level(level) var cases = MouseTestCase.cast_all_cases(get_tree().get_nodes_in_group(MouseTestCase.MTC_GROUP_NAME)) while (cases.any(func(case): return not case.done)): map.move_mice() for case in cases: if not case.done: case.steps_left -= 1 if case.steps_left == 0: case.done = true assert_eq(case.get_mouse_position(), case.expected_position, case.get_parent().name+"/"+case.name)
Bunun gelişeceğini hayal ediyorum, ancak mevcut uygulama şimdilik yeterince iyi. Testleri yazdım, mekaniği uyguladım ve testler aslında mekaniğin doğru şekilde uygulandığını doğruladı!
Burada oyunlardaki testlere yaklaşmanın bir yolunu gösterdim. Açıkçası burada geliştirilecek daha pek çok şey var ve okuyucuları kodu ve çerçeveyi alıp ihtiyaçlarına göre uyarlamaya teşvik ediyorum.
Her zaman olduğu gibi kod GitHub'da mevcuttur: https://github.com/d-lowl/of-mice-and-bad-choices Ayrıca testi tanıtan özel PR'ye de göz atabilirsiniz. Bonus puan olarak eğer birisi bunları CI'da çalıştırabilirse bu harika olur. Şerefe.