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

Parçacık türleri

Şimdi kalıt gibi daha ileri nesne tabanlı programlama teknikleri kullanacağız, onun için, JS'ye Giriş dersindeki "Kalıt" konusunu tekrar edip, sonra dönmek isteyebilirsiniz. Merak etmeyin, sizi bekleyeceğiz!
Kalıtın nasıl çalıştığını anladınız mı? İyi, çünkü kalıt kullanarak farklı türlerde Particle alt-nesneleri oluşturacağız, bunlar aynı işlevselliğe sahip olacak ama önemli farklılıklar da gösterecektir.
Basitleştirilmiş bir Particle uygulamasına bakalım:
var Particle = function(position) {
  this.acceleration = new PVector(0, 0{,}05);
  this.velocity = new PVector(random(-1, 1), random(-1, 0));
  this.position = position.get();
};

Particle.prototype.run = function() {
  this.update();
  this.display();
};

Particle.prototype.update = function(){
  this.velocity.add(this.acceleration);
  this.position.add(this.velocity);
};

Particle.prototype.display = function() {
  fill(127, 127, 127);
  ellipse(this.position.x, this.position.y, 12, 12);
};
Sonra, Particle tabanlı yeni bir nesne türü oluşturuyoruz, adına da Confetti diyoruz. Aynı sayıyı argüman olarak alan ve bunları geçirerek Particle yapıcısını çağıran bir yapıcı fonksiyonuyla başlayacağız:
var Confetti = function(position) {
  Particle.call(this, position);
};
Şimdi, Confetti nesnelerinin Particle nesneleriyle aynı yöntemlere sahip olduğundan emin olmak için, onların prototipinin Particle prototipine bağlı olduğunu belirtmemiz gerekir:
Confetti.prototype = Object.create(Particle.prototype);
Confetti.prototype.constructor = Confetti;
Bu aşamada, Particle nesneleriyle aynı şekilde hareket eden Confetti nesnelerimiz var. Kalıtımın amacı, kopya değil, işlevlerini paylaşan ama bir şekilde farklı olan yeni nesneler yapmaktır. Şimdi, bir Confetti nesnesi nasıl farklıdır? Sadece isme bakarsak, farklı görünmesi gerekiyor. Particle nesnelerimiz elipstir, ama konfeti genelde kare şeklinde küçük kağıtlardan oluşur; en azından, bunların display yöntemini dikdörtgen olarak değiştirmeliyiz:
Confetti.prototype.display = function(){
  rectMode(CENTER);
  fill(0, 0, 255, this.timeToLive);
  stroke(0, 0, 0, this.timeToLive);
  strokeWeight(2);
  rect(0, 0, 12, 12);
};
Bir Particle nesnesi ve bir Confetti nesnesi olan program buradadır. Dikkat ederseniz, benzer davranırlar ama farklı görünürler:

Döndürme ekleme

Bunu biraz daha karmaşıklaştıralım. Diyelim ki, Confetti parçacığının havada uçarken dönmesini istiyoruz. Salınımlar bölümünde olduğu gibi, açısal hız ve ivmeyi de modelleyebiliriz. Bunun yerine, hızlı bir çözüm deneyeceğiz.
Parçacıklar boşlukta olsaydı,
Parçacığın 0 ile pencerenin eni arasında bir x konumu olduğunu biliyoruz. Ya şöyle deseydik: parçacığın x konumu 0 olduğunda, döndürmesi 0 olmalı; x konumu ene eşit olduğunda, döndürmesi TWO_PI olmalı? Kulağa tanıdık geliyor mu? Bir aralıktaki değeri başka bir aralığa eşleştirmek istiyorsanız, ProcessingJS map() fonksiyonunu kullanarak yeni değeri kolaylıkla bulabiliriz.
var theta = map(this.position.x, 0, width, 0, TWO_PI);
Biraz daha ilginç kılmak için, açının aralığını 0 ile TWO_PI*2 arasında eşleştirebiliriz. Bu kodun display() yöntemine nasıl uyduğuna bakalım.
Confetti.prototype.display = function(){
  rectMode(CENTER);
  fill(0, 0, 255);
  stroke(0, 0, 0);
  strokeWeight(2);
  pushMatrix();
  translate(this.position.x, this.position.y);
  var theta = map(this.position.x, 0, width, 0, TWO_PI * 2);
  rotate(theta);
  rect(0, 0, 12, 12);
  popMatrix();
};
Bu, şöyle görünür - birkaç kere yeniden başlatarak, döndürmenin etkisini görün:
Tetayı y konumunda, temellendirebiliriz, bunun etkisi farklı olur. Bunun nedeni nedir? Parçacığın y yönünde sıfır olmayan sabit ivmesi vardır; bunun anlamı, y dürstinin zamana göre doğrusal bir fonksiyon olduğu ve y konumunun zamana göre parabolik bir fonksiyon olduğudur. Bunun anlamını aşağıdaki grafiklerde görebilirsiniz (bunlar yukarıdaki program kullanılarak oluşturulmuştur):
Konfeti döndürmeyi y konumuna bağlarsak, döndürme de parabolik olur. Bu, fiziksel olarak çok da doğru olmayacaktır; çünkü konfetinin havadan düşerken gerçek dönüşü gayet karmaşıktır, ama kendiniz bunu deneyin ve ne kadar gerçekçi olduğunu görün! Daha gerçekçi görünebilen başka fonksiyonlar düşünebilir misiniz?"

Çeşitli bir ParticleSystem

Şimdi, esas yapmak istediğimiz şey birçok Particle nesnesi ve birçok Confetti nesnesi yaratmaktır. <ParticleSystem nesnesini bunun için yaptık, belki de uzatıp Confetti nesnelerini takip etmesini sağlayabiliriz? Bunu şu şekilde yapabiliriz, Particle nesneleri için yaptığımızı kopyalayabiliriz:
var ParticleSystem = function(position) {
  this.origin = position;
  this.particles = [];
  this.confettis = []; // SAD FACE!
};

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

ParticleSystem.prototype.run = function(){
  for (var i = this.particles.length-1; i >= 0; i--) {
    var p = this.particles[i];
    p.run();
  }
for (var i = this.confettis.length-1; i >= 0; i--) {
    var p = this.confettis[i]; p.run();
  }
};
Dikkat ederseniz, iki ayrı dizimiz var, biri parçacıklar için ve biri konfeti için. Parçacık dizisine bir şey yaptığımızda, konfeti dizisine de aynı şeyi yapmalıyız! Bu can sıkıcıdır, çünkü iki katı kod yazmamızı gerektirir ve bir şeyi değiştirirsek, iki yerde değiştirmemiz gerekir. Aslında bu çoğaltmayı engelleyebiliriz, çünkü JavaScript değişik türde nesneleri dizilerle depolamamıza izin verir ve nesnelerimizin hepsinde aynı arayüz vardır - run() yöntemini çağırırız ve iki nesne türü bu arayüzü tanımlar. Bir dizi saklamaya döneceğiz, hangi tür parçacık nesnesi ekleyeceğimize rastgele karar vereceğiz ve tek dizide yinelemeye döneceğiz. Bu, çok daha basit bir değişimdir - sonunda sadece addParticle yöntemini değiştiririz:
var ParticleSystem = function(position) {
  this.origin = position;
  this.particles = [];
};

ParticleSystem.prototype.addParticle = function() {
  var r = random(1);
  if (r < 0{,}5) {
    this.particles.push(new Particle(this.origin));
  } else {
    this.particles.push(new Confetti(this.origin));
  }
};

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);
    }
  }
};
Şimdi hepsi birden!