Asla yeniden başlatmayan bir test dünyası nasıl kurulur?


23

Aşağıdakilerin nasıl yapılacağı hakkında fikirler arıyorum: Java'da basit bir "dünya" yazmak istiyorum. Var olan nesneler arasındaki farklı davranışları simüle etmek / gözlemlemek için ileriki bir tarihte daha sonra yeni nesneler ekleyebileceğim ve başlatabileceğim bir tanesi. Plan daha sonra eskileri bir süre izledikten sonra yeni nesneleri kodlamak ve sonra onları mevcut dünyaya yüklemek / bırakmaktır. Sorun şu ki, dünyayı başlattıktan sonra hiç durdurmak veya yeniden başlatmak istemiyorum, birkaç hafta çalışmasını istiyorum, ancak nesnelere düşme ve tekrarlama / yeniden yazma / silme / yaratma / değiştirme yeteneklerine ihtiyacım var Bir yeniden başlatma gerekmeden zamanla. Dünya, dünyayı görsel olarak temsil etmek için olası bir haritalanmış GUI ile 100 x 100 X / Y konum dizisi kadar basit olabilir. Nesneleri izlemek ve her birine 'hareket etme şansı vermek' için bir çeşit ticktimer işlemine ihtiyacım olduğunu biliyorum.

Örnek: Pazartesi günü World.java’yı kodladım ve çalışır durumda bıraktım. Sonra Salı günü Rock.java adında yeni bir sınıf yazdım (hareket etmiyor). Daha sonra (zaten?) Bu zaten çalışan dünyaya yüklüyorum / bırakıyorum (bu sadece dünya dizisinde rastgele bir yere düşüyor ve hiç hareket etmiyor). Sonra Çarşamba günü, Cat.java adında yeni bir sınıf yarattım ve dünyaya bırakıp tekrar rastgele yerleştirdim, ancak bu yeni nesne dünyanın etrafında hareket edebiliyor (bir süre zarfında), sonra Perşembe günü Köpek adında bir sınıf yazıyorum. Ayrıca etrafta dolanan ancak komşu konumdaysa başka bir nesne üzerinde 'hareket edebilen' java ve bunun tersi de geçerlidir.

İşte şey. Gelecekteki (ve şu anda olmayan) nesnelerin nasıl algılandığını / yüklendiğini / izlendiğini bilmek için gerçek dünya sınıfını hangi yapı / tasarım türüyle kodlamam gerektiğini bilmiyorum.

Java kullanarak böyle bir şeyi nasıl yapacağınız hakkında bir fikriniz var mı?


2
Sıcak takas gibi çok geliyor . Belki de bu konuda yardımcı olabilecek bazı literatürler vardır. Neyse, çok ilginç bir soru. +1…
Konrad Rudolph

Yanıtlar:


5

Temelde aradığınız şey çalışırken çıkarılabilir bir sistemdir. Bir ana uygulamayı çalıştırın ve sonra olay döngüsüne entegre olan çalışma zamanında eklentiler ekleyin. İlk önce, dünyanızın bir oyun varlıklarından ne beklediğini düşünmeye başlayın. Örneğin (açıklamanıza göre):

interface Entity {
   void init(World world);
   // Called when loaded for the first time in the world and adds itself
   // to the world (correct position in the array, scheduler for updates)

   void update(World world);
   // Called when scheduler fires (allows the entity to think about its
   // next move)

   Image getImage();
   // Called by the GUI when it is time to draw the entity on the screen
}

Tabii ki gerekli gördüğünüz diğer yöntemleri de ekleyebilirsiniz. Dünya parametresini ilgili iki yöntemle not alın. Bu, yeni varlığın kurulurken veya güncellenirken dünyayı düşünmesini sağlar. Örneğin, Köpek sınıfınızda, dünyadaki mahalledeki tüm kedileri isteyebilirsiniz. Ardından, bu arayüzle çalışan dünyanızı ve Java kodunu dinamik olarak derleyip yüklemek için bir sistem yaratırsınız. Bunun bir örneği burada bulunabilir .

void injectEntity(String filename, World world) {
    // Load the class as described in the mentioned link
    Entity e = (Entity) loadClass(filename);
    e.init(world);
}

Yeni varlıklar eklemek için bu yöntemi Dünya GUI'sinden çağırın. Dünyanızın uygulamasına bağlı olarak, bir Varlık init işlevi aşağıdaki gibi görünebilir:

void init(World world) {
   // Register entity with world for easy access
   world.register(this, "RockImpl A");

   // Place the entity on the world map
   Point initialLocation = Point(10,5);
   world.place(this, initialLocation);

   // Schedule its update method for every 5 seconds
   world.schedule(this, 5);
}

1
Google'da anahtar kelimeler: "IoC konteynerleri", "Kontrolün tersine çevrilmesi", "Bağımlılık enjeksiyonu". Bunlar çalışma anında bileşenleri keşfedebilen ve yükleyebilen genel çalışırken takılabilir sistemler için tekniklerdir.
Nevermind

16

Stendhal'da baskınlar için böyle bir şey yaptık .

Yeniden başlatmalardan tamamen kaçınmayı hedeflemedik. Bu nedenle, istemci / sunucu iletişimi gibi temel altyapı hizmetlerimizdeki değişikliklerin yeniden başlatılması gerekir. Ancak varlıklar, yaratıklar ve NPC'ler eklemek ve mevcut nesneleri değiştirmek işe yarar. (Oh, ve bazen canlı hata düzeltme, yansıma özel alanları bile manipüle etmek için kullanılabilir).

Yalnızca yeni verilere dayalı (başka bir arayüz gibi) yeni nesne istemediğimizden, yeni davranış eklemek istediğimizden, dünya programının yeni sınıf dosyaları yükleyebilmesi gerekir . Onlara "script" diyoruz, fakat bunlar gerçek derlenmiş Java sınıfları. Bu sınıflar Script.java arayüzünü uygular .

Maria.java basit bir örnek. Oyunculara içecek ve yiyecek satan yeni bir NPC. Orada da çok karmaşık nesneler tanımlayabiliriz .

Bu yolla yeni bir sınıf yüklenir:

// create a new class loader, with the script folder as classpath.
final File file = new File("./data/script");
final ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()});

// load class through new loader
final Class< ? > aClass = loader.loadClass(classname);
script = (Script) aClass.newInstance();

Benzersiz adlar sağlayabiliyorsanız ve sınıfları boşaltmak istemiyorsanız, düşük seviyeli işlerle tamamlanırsınız.

Boşaltma , ancak oldukça önemli görünüyor. Bunu başarmak için, yeni bir kod enjekte etmek istediğinizde yeni bir sınıf yükleyiciyi başlatmanız gerekir. Böylece GC, bu koda yapılan son referans temizlendikten sonra çalışmalarını yapabilir.

Biz var / boşaltma komutu bizim arayüzünde çağıran bir boşaltma yöntemi olduğunu komut temizleme yapabilir böylece. Gerçek boşaltma GC tarafından otomatik olarak yapılır.

Baskınlar sırasında çoğu zaman geçici nesneler yaratıyoruz . Ve baskın sona erdikten sonra hepsinin kaldırılmasını istiyoruz. Örneğin, görünmez yöneticinin yakınında birkaç cücenin ortaya çıktığı Gnomes Raid'i kullanıyoruz, bu kodu kullanıyoruz: GnomeRaid.java , CreateRaid.java'yı genişletiyor .

Komut dünyaya doğrudan erişebilir (ilk örnekte gösterildiği gibi) ve unload () yönteminde kendi temizliğini yapabilir. Ancak Java kodlayıcıları temizlik yapmak için kullanılmaz ve can sıkıcıdır. Böylece komut dosyalarının kullanabileceği bir sanal alan oluşturduk . Boşaltıldığında, dünyaya eklenen tüm nesneleri Sandbox sınıfı aracılığıyla kaldırır.


3

Dünyayı (amaçlanan yok) ve bütün hallerini (pozisyonlar, hızlar, tüm değişkenler) kurtarın.

  • Programı kapat.
  • Değişiklikleri uygulayın (tasarruflarla geriye dönük uyumluluk sağlama).
  • Programı yeniden derleyin.
  • Programı yeniden başlatın.
  • Dünyayı ve devleti yükleyin.
  • Tekrar et

Bu genel bir çözüm olsa da, sizin gibi kod bloklarını ve sınıflarını dinamik olarak uygulayıp uygulayamadığınızı Java ile ilgili bilmiyorum.

Seçenek 2 , anında yüklenebilecek bir betik dilini bağlamaktır.


Betik dili için +1. Java'ya bağlı değilseniz, LPC tabanlı MUD sürücülerinin ve çamurlukların bazılarını da deneyin.
Martin Sojka

1

Java için ihtiyacınız olan tek şey bir OSGi platformudur . Bununla modülleri veya uygulamaları çalışırken değiştirilebilir ve hatta uzaktan yönetim veya kısmi güncellemeler bile çok önemlidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.