If you're seeing this message, it means we're having trouble loading external resources on our website.

Bağlandığınız bilgisayar bir web filtresi kullanıyorsa, *.kastatic.org ve *.kasandbox.org adreslerinin engellerini kaldırmayı unutmayın.

Ana içerik

Bir parçacık sistemi

Şimdiye kadar, öldüğünde, tekrardan yarattığımız bir parçacık yaratmayı başardık. Şimdi, draw() ile her döngüde yeni birini eklediğimiz, sürekli bir parçacık akışı oluşturmak istiyoruz. Bir dizi oluşturup, her seferince buna yeni bir parçacık ekleyebiliriz:
var particles = [];
draw = function() {
  background(133, 173, 242);
  particles.push(new Particle(new PVector(width/2, 50)));

  for (var i = 0; i < particles.length; i++) {
    var p = particles[i];
    p.run();
  }
};
Bunu denerseniz ve bu kodu birkaç dakika boyunca çalıştırırsanız, kare hızının, program durana kadar gittikçe yavaşladığını görmeye başlarsınız. Bunun nedeni, hiçbirini kaldırmamakla birlikte, işleyip görüntülememiz gereken parçacıklar oluşturmamızdır. Parçacıklar öldükten sonra, işe yaramaz olurlar, o zaman programımızı gereksiz işten kurtarmalıyız ve bu parçacıkları kaldırmalıyız.
JavaScript'teki bir diziden öge çıkarmak için splice() yöntemini kullanabiliriz, silinmesi istenen indeks ve sayıyı (sadece bir) belirtiriz. Bunu parçacığın gerçekten de ölü olup olmadığını sorguladıktan sonra yaparız:
var particles = [];
draw = function() {
  background(133, 173, 242);
  particles.push(new Particle(new PVector(width/2, 50)));

  for (var i = 0; i < particles.length; i++) {
    var p = particles[i];
    p.run();
    if (p.isDead()) {
      particles.splice(i, 1);
    }
  }
};
Her ne kadar üstteki kod gayet iyi çalışacak (ve program hiç durmayacak da) olsa, orta boyda bir soruna yol açmış oluruz. Bir diziyi yinelerken aynı dizinin içeriğine müdahale edersek, başımıza dert açabiliriz. Örneğin, aşağıdaki koda bakın:
for (var i = 0; i < particles.length; i++) {
  var p = particles[i];
  p.run();
  particles.push(new Particle(new PVector(width/2, 50)));
}
Bu biraz aşırı bir örnektir (mantığı da kusurludur), ama bahsettiğimiz şeyi kanıtlıyor. Yukarıdaki durumda, dizideki her parçacık için, diziye yeni bir parçacık ekleriz (böylece, dizinin uzunluğunu değiştiririz). Bu sonsuz bir döngüye yol açar, çünkü i particles.length'in ötesine gidemez.
Bir döngü sırasında, parçacık dizisinden öge kaldırmak, (eklemekte olduğu gibi) programın çökmesine neden olmasa da, buradaki problem hiçbir kanıt bırakmayacak şekilde sinsidir. Sorunu keşfetmek için, önce önemli bir gerçeği ortaya koymamız gerekir. Bir öge bir diziden kaldırıldığında, tüm ögeler bir adım sola kaydırılır. C parçacığının (indeks 2) kaldırıldığı şemaya bakın. A ve B parçacıkları aynı indeksi korusa da, D ve E parçacıkları, sırasıyla, 3 ve 4'ten 2 ve 3'e kayarlar.
Dizide döngülenen i olduğumuzu farzedelim.
  • when i = 0 → Check particle A → Do not delete
  • when i = 1 → Check particle B → Do not delete
  • when i = 2 → Check particle C → Delete!
  • (D ve E parçacıklarını 3 ve 4. yuvalardan 2 ve 3. yuvalara geri kaydırın)
  • when i = 3 → Check particle E → Do not delete
Sorunu fark ettiniz mi? D parçacığını hiç kontrol etmedik! C yuva #2'den silindiğinde, D yuva #2'ye geldi, ama i zaten yuva #3'e gitmişti. Bu bir felaket değildir, çünkü D parçacığı bir sonraki seferde kontrol edilecektir. Yine de, beklenti, dizinin her öğesini yineleyen bir kod yazmamızdır. Bir öğeyi atlamak kabul edilemez.
Bu sorunun basit bir çözümü vardır: diziyi geriye doğru yineleyin. Parçacıkları kaldırıldığında, öğeleri sağdan sola kaydırıyorsanız, kazara bir öğeyi atlamak mümkün değildir. Yapmamız gereken tek şey, for döngüsündeki üç parçayı değiştirmektir:
  for (var i = particles.length-1; i >= 0; i--) {
    var p = particles[i];
    p.run();
    if (p.isDead()) {
      particles.splice(i, 1);
    }
  }
Bunların hepsini birleştirdiğimizde, şunu elde ederiz:
Tamam. Şimdi, iki şey yapmış olduk. Bir Parçacığı tanımlamak için bir nesne yazmış olduk. Birçok Parçacık nesnesini yönetmek için nasıl dizi kullanabileceğimizi (istediğimiz gibi ekleme veya kaldırma yaparak) öğrendik.
Burada durabiliriz. Ancak, atabileceğimiz ve atmamız gereken ekstra bir adım, Parçacık nesneleri grubunun kendisini tanımlamak için bir nesne yaratmaktır—ParticleSystem nesnesi. Bu, ana sekmedeki tüm parçacıkları döngülemenin hantal mantığını ortadan kaldırmamızı sağlamanın yanı sıra birden fazla parçacık sistemi olasılığını da yaratacaktır.
Bu bölümün başında belirlediğimiz hedefi hatırlarsanız, programımızın şöyle görünmesini istiyorduk:
var ps = new ParticleSystem(new PVector(width/2, 50));

draw = function() {
  background(0, 0, 0);
  ps.run();
};
Yukarıda yazdığımız programı alalım ve ParticleSystem nesnesine nasıl uyduracağımıza bakalım.
Daha önceden elimizde olan şudur - kalın satırlara dikkat edin:
var particles = [];

draw = function() {
  background(133, 173, 242);
  particles.push(new Particle(new PVector(width/2, 50)));

  for (var i = particles.length-1; i >= 0; i--) {
    var p = particles[i];
    p.run();
    if (p.isDead()) {
      particles.splice(i, 1);
    }
  }
};
Bunu bir nesne şeklinde şöyle yazabiliriz- parçacık dizisini nesnenin bir özelliği haline getireceğiz, yeni parçacıklar eklemek için bir sarmalayıcı yöntem, addParticle yaratacağız, ve parçacık çalıştırma mantığını run'a koyacağız:
var ParticleSystem = function() {
  this.particles = [];
};

ParticleSystem.prototype.addParticle = function() {
  this.particles.push(new Particle());
};

ParticleSystem.prototype.run = function() {
  for (var i = this.particles.length-1; i >= 0; i--) {
      var p = this.particles[i];
      p.run();
      if (p.isDead()) {
        this.particles.splice(i, 1);
      }
    }
};
Ayrıca, parçacık sisteminin kendisine de bazı yeni özellikler ekleyebiliriz. Örneğin ParticleSystem nesnesinin, parçacıkların oluşturulduğu bir başlangıç noktasını takip etmesi faydalı olur. Bu, parçacık sisteminin bir “yayıcı,”, parçacıkların doğduğu ve dünyaya dağıldığı bir yer, olduğu fikriyle uyumludur. Başlangıç noktası, yapıcı da sıfırlanmalıdır.
var ParticleSystem = function(position) {
  this.origin = position.get();
  this.particles = [];
};

ParticleSystem.prototype.addParticle = function() {
  this.particles.push(new Particle(this.origin));
};
İşte, hepsi birlikte: