Ana içerik
Konu: Bilgisayar Programlama > Ünite 5
Ders 8: Parçacık Sistemleri- Parçacık sistemlerine giriş
- Tek bir parçacık
- Zor görev: Düşen yapraklar
- Bir parçacık sistemi
- Zor görev: Balık kabarcıkları
- Parçacık sistemi sistemleri
- Zor görev: Ateş başlatan
- Parçacık türleri
- Zor görev: Büyülü kazan
- Kuvvet içeren parçacık sistemleri
- Zor görev: Nehirdeki taşlar
© 2024 Khan AcademyKullanım ŞartlarıGizlilik PolitikasıÇerez Politikası
Kuvvet içeren parçacık sistemleri
Şimdilik bu bölümde, bir parçacık grubunu yönetmek için, kodumuzu nesne yönelimli bir şekilde yapılandırmaya odaklanıyorduk. Belki farkına vardınız, veya varmadınız; ama bu süreç boyunca, daha önceki bölümlerdeki yerimizden geri adım attık. Basit Parçacık nesnemizin yapısını inceleyelim:
var Particle = function(position) {
this.acceleration = new PVector(0, 0{,}05);
this.velocity = new PVector(random(-1, 1), random(-1, 0));
this.position = new PVector(position.x, position.y);
this.timeToLive = 255{,}0;
};
Ve şimdi
update()
yöntemine bakalım:Particle.prototype.update = function(){
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.timeToLive -= 2;
};
Dikkat ederseniz, ivmemiz sabittir, yapıcının dışında oluşturulmamıştır. Çok daha iyi bir yöntem Newton'ın ikinci yasasını ( ) izlemek ve bunu Kuvvetler bölümünde üzerinde çok çalıştığımız kuvvet biriktirme algoritması ile birleştirmek olacaktır.
Birinci adım, bir
applyForce()
yöntemi eklemektir. (Unutmayın, kütleye bölmeden önce, PVector
'un bir kopyasını yapmamız gerekir.)Particle.prototype.applyForce = function(force) {
var f = force.get();
f.div(this.mass);
this.acceleration.add(f);
};
Bunu bulduktan sonra,
update()
'in sonunda ivmeyi silmek için bir kod satırı daha ekleyebiliriz.Particle.prototype.update = function() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.mult(0);
this.timeToLive -= 2{,}0;
};
Böylece, kuvvet uygulanabilir bir
Particle
nesnemiz olur. Şimdi, applyForce()
fonksiyonunu nerede çağırmalıyız? Kodun neresinde parçacığa kuvveti uygulamak uygun olur? İşin aslını isterseniz doğru veya yanlış cevap yoktur; bu tamamen belirli bir programın fonksiyonlarına ve hedeflerine bağlıdır. Bununla birlikte, çoğu duruma uygun olacak genel bir durum yaratabiliriz ve bir sistemdeki bireysel parçacıklara kuvvetler uygulamak için bir model geliştirebiliriz.Rüzgarı ekleme
Aşağıdaki hedefi düşünün: Tüm parçacıklara her seferinde draw() yoluyla genel bir kuvvet uygulama. Parçacıkları sağa iten, basit bir rüzgar şeklinde kuvvet uygulamayla başlayalım:
var wind = new PVector(0,4, 0);
Her zaman uygulanması gerektiğini söylemiştik,
draw()
'a olduğu gibi, onun için şimdiki haliyle draw()
fonksiyonuna bakalım.draw = function() {
background(168, 255, 156);
particleSystem.addParticle();
particleSystem.run();
};
Galiba, küçük bir problemimiz var.
applyForce()
Particle
nesnesinin içinde yazılan bir yöntemdir, ama parçacıkların kendisinden bahsetmemektedir, sadece particleSystem
nesnesinden bahsetmektedir:particleSystem
değişkeni.Tüm parçacıkların kuvveti almasını istediğimizde, parçacık sistemine kuvveti uygulamaya karar verebiliriz ve kuvveti tüm parçacıklara uygulamasını isteyebiliriz.
draw = function() {
background(168, 255, 156);
particleSystem.applyForce(wind);
particleSystem.addParticle();
particleSystem.run();
};
Elbette,
draw()
'daki ParticleSystem
nesnesinde yeni bir fonksiyon çağırırsak, bu fonksiyonu ParticleSystem
nesnesinde yazmamız gerekir. Fonksiyonun uygulaması gereken işi tanımlayalım: bir PVector
kuvvetini alma ve bu kuvveti tüm parçacıklara uygulama.Şimdi kodda:
ParticleSystem.prototype.applyForce = function(f){
for(var i = 0; i < this.particles.length; i++){
this.particles[i].applyForce(f);
}
};
Bu işlevi yapmak saçma gibi görünüyor. Söylediğimiz şey şudur: “parçacık sistemine bir kuvvet uygulayın ki, sistem bu kuvveti tüm parçacıklara bireysel olarak uygulayabilsin.” Yine de gerçekten de oldukça makuldur. Ne de olsa,
ParticleSystem
nesnesi parçacıkların yönetiminden sorumludur, onun için parçacıklarla konuşmak istersek, onlarla yöneticisi vasıtasıyla konuşmamız gerekir.Hepsini böyle birleştiriyoruz. Güneş kuvvetiyle oynayın, ve parçacık hareketini nasıl etkilediğine bakın, ve farklı kütlelerdeki parçacıklarına farklı tepkilerine dikkat edin. Bunun nedenini düşünün.
Yerçekimini ekleme
Şimdi daha karmaşık bir kuvveti uygulayalım, yerçekimi, bu da rüzgardan farklıdır çünkü uygulandığı nesnelerin kütlesine göre değişir.
İki kütle arasındaki yerçekimi kuvvetini hesaplma denklemini hatırlayalım:
Dünya üzerinde yerçekimi kuvvetini modellerken, dünyanın uyguladığı kuvvetin diğer çekim kuvvetlerinden çok üstün olduğu için onları gölgede bıraktığını unutmayın, onun için ilgilendiğimiz tek denklem, dünya ile nesne arasındaki yerçekimi kuvvetini hesaplayan denklemdir. ve her parçacık için aynıdır, ve (dünyadan yarıçapı) temelde aynıdır (çünkü parçacıkların dünyadan uzaklığına kıyasla dünyanın yarıçapı çok büyüktür), o nedenle, bunları dünyadaki yerçekimi g, olarak sadeleştiririz:
Şimdi, yerçekimi kuvveti bir g sabiti çarpı parçacık kütlesi, çarpı kuvvetin yönünde bir birim vektördür (bu da hep aşağı doğru olur):
Kodda, bunun anlamı her parçacığa kütlesine göre farklı bir yerçekimi uygulamamız gerektiğidir. Bunu nasıl yapabiliriz? Mevcut
applyForce
fonksiyonunu yeniden kullanamayız, çünkü her parçacık için aynı kuvveti bekler. applyForce
'un kütleyi çarpmasını hatırlatan bir parametre geçirmeyi düşünebiliriz, ama isterseniz bu fonksiyonu yalnız bırakalım ve mutlak bir sabit vektöre göre kuvvet hesaplayan yeni bir fonksiyon applyGravity
, oluşturalım:// Üstte belirtilen, sabit bir aşağı vektörü
var gravity = new PVector(0, 0{,}2);
ParticleSystem.prototype.applyGravity = function() {
for(var i = 0; i < this.particles.length; i++) {
var particleG = gravity.get();
particleG.mult(this.particles[i].mass);
this.particles[i].applyForce(particleG);
}
};
Artık, bunların hepsini doğru yaptıysak, parçacıklarımızın hepsi, aşağıdaki simülasyonda aynı hızda düşmelidir. Bunun nedeni, yerçekimi kuvvetinin kütleyle çarpmaya bağlı olması, ancak ivmenin kütleye bölmeye bağlı olmasıdır, yani sonunda kütle etkisiz kalır. Bu kadar çaba sonucu etkisiz kalmak saçma gelebilir, ama birden çok farklı kuvveti birleştirdiğimizde önemli olacaktır.
İtici ekleme
Ya bunu bir aşama ileriye götürmeyi ve nesneler yaklaştıkça onları iten bir nesne eklemek istersek? Bu, daha önce oluşturduğumuz çeken nesneye benzerdir, sadece ters yönde itmektedir. Bir kez daha, yerçekimi gibi, her bir parçacık için farklı bir kuvver hesaplamamız gerekir, ama iticinin durumunda, aradaki fark, hesaplamanın kütleye değil, uzaklığa bağlı olmasıdır. Yerçekiminde, kuvvet vektörlerimizin hepsinin yönü aynıydı, ama iticide, kuvvet vektörlerinin hepsinin yönleri farklı olur:
İtici bir gücün hesaplanması yerçekiminin hesaplanmasından biraz daha karmaşık olduğundan (ve birden fazla itici isteyebiliriz!), bu problemi basit parçacık sistemimiz artı yerçekimi örneğine yeni bir Repeller nesnesi katarak çözeceğiz. Kodumuzda iki önemli ekleme gerekecek:
- Bir
Repeller
nesnesi (bildirilmiş, başlatılmış, ve gösterilen). Repeller
nesnesini, her bir parçacık nesnesine kuvvet uygulaması içinParticleSystem
'e geçirecek bir fonksiyon.
var particleSystem = new ParticleSystem(new PVector(width/2, 50));
var repeller = new Repeller(width/2-20, height/2);
var gravity = new PVector(0, 0{,}1);
draw = function() {
background(214, 255, 171);
// Tüm parçacıklara yer çekimi uygula
particleSystem.applyForce(gravity);
particleSystem.applyRepeller(repeller);
repeller.display();
particleSystem.addParticle();
particleSystem.run();
};
Görüntülenebilir bir
Repeller
nesnesini yapmak kolaydır; daha önce oluşturduğumuz Attractor
nesnesinin bir kopyasıdır:var Repeller = function(x, y) {
this.position = new PVector(x, y);
};
Repeller.prototype.display = function() {
stroke(255);
strokeWeight(2);
fill(127);
ellipse(this.position.x, this.position.y, 32, 32);
};
Daha zor olan soru,
applyRepeller()
yöntemini nasıl yazarız? PVector
'u applyForce()
gibi bir fonksiyona geçirmek yerine, bir Repeller
nesnesini applyRepeller()
fonksiyonuna ve bu fonksiyondan itici ve tüm parçacıklar arasındaki kuvveti hesaplamasını isteriz:ParticleSystem.prototype.applyRepeller = function(r) {
for(var i = 0; i < this.particles.length; i++){
var p = this.particles[i];
var force = r.calculateRepelForce(p);
p.applyForce(force);
}
};
Buradaki en büyük fark, her parçacık için yeni bir kuvvet hesaplanmasıdır, çünkü daha önce gördüğümüz gibi, kuvvet her parçacığın iticiye göre özelliklerine göre değişir. Bu kuvveti
calculateRepelForce
fonksiyonunu kullanarak hesaplarız, bu da Attractor
larımıza göre calculateAttractionForce
fonksiyonunun tersidir.Repeller.prototype.calculateRepelForce = function(p) {
// Calculate direction of force
var dir = PVector.sub(this.position, p.position);
// Distance between objects
var d = dir.mag();
// Yön vektörünü normalleştirin (burada uzaklık önemli değildir, bu vektörü sadece yön için istiyoruz)
dir.normalize();
// Uzaklığı makul bir aralıkta tutun
d = constrain(d, 1, 100);
// Tepme kuvveti uzaklıkla ters orantılıdır
var force = -1 * this.power/ (d * d);
// Kuvvet vektörünü alın --> büyüklük * yön
dir.mult(force);
return dir;
};
Dikkat ederseniz, çevreye itici ekleme süreci boyunca,
Particle
nesnesini düzenlemeyi hiç düşünmedik. Bir parçacık, çevresinin detaylarını bilmek zorunda değildir; sadece konumunu, hızını, ve ivmesini yönetmesi, ve dış kuvveti alıp tepki verme becerisine sahip olması yeterlidir.Artık bu örneğin tamamına bakabiliriz. Parçacıklara etki eden kuvvetlerin gücünü değiştirmeyi deneyin - yerçekimi ve itici - ve bunun, bunları nasıl değiştirdiğini görün:
Tartışmaya katılmak ister misiniz?
Henüz gönderi yok.