ძირითადი მასალა
კომპიუტერული პროგრამირება
კურსი: კომპიუტერული პროგრამირება > თემა 5
გაკვეთილი 8: ნაწილაკთა სისტემები- შესავალი ნაწილაკთა სისტემებში
- მხოლოდ ერთი ნაწილაკი
- გამოწვევა: დაცვენილი ფოთლები
- ნაწილაკთა სისტემა
- გამოწვევა: თევზის ბუშტუკები
- ნაწილაკთა სისტემების სისტემები
- გამოწვევა: ცეცხლის წამკიდებელი
- ნაწილაკთა ტიპები
- გამოწვევა: ჯადოსნური ქვაბი
- ნაწილაკთა სისტემები და ძალები
- გამოწვევა: მდინარის ქვები
- პროექტი: არსებათა კოლონიები
© 2023 Khan Academyგამოყენების პირობებიკონფიდენციალურობის პოლიტიკაშენიშვნა ქუქი-ჩანაწერებზე
ნაწილაკთა ტიპები
ახლა გამოვიყენებთ ობიექტზე ორიენტირებული პროგრამირების მაღალი დონის ტექნიკებს, როგორიცაა მემკვიდრეობითობა, ასე რომ, შეიძლება, გამოგადგეთ "მემკვიდრეობითობის" გადახედვა JS-ის შესავლის კურსში და შემდეგ დაბრუნდით. არ ინერვიულოთ, ჩვენ დაგელოდებით!
კარგად იცით, როგორ მუშაობს მემკვიდრეობითობა? კარგია, რადგან ჩვენ გამოვიყენებთ მემკვიდრეობითობას სხვადასხვა ტიპის
Particle
ქვეობიექტის გასაკეთებლად, რომლებიც დიდი დოზით იზიარებენ ფუნქციონალობას, მაგრამ ასევე მნიშვნელოვნად განსხვავდებიან.განვიხილოთ გამარტივებული
Particle
-ის იმპლემენტაცია: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);
};
ახლა,
Particle
-ზე დაყრდნობით ვქმნით ობიექტის ახალ ტიპს, რომელსაც დავარქმევთ Confetti
-ს. დავიწყებთ კონსტრუქტორი ფუნქციით, რომელიც იღებს იმავე რაოდენობის არგუმენტებს და, უბრალოდ, იძახებს Particle
კონტსრუქტორს და გადასცემს მათ:var Confetti = function(position) {
Particle.call(this, position);
};
ახლა კი, ჩვენმა
Confetti
ობიექტებმა რომ გაიზიარონ იგივე მეთოდები, რომლებიც Particle
ობიექტებს აქვთ, უნდა მივუთითოთ, რომ საჭიროა, მათი პროტოტიპი Particle
პროტოტიპზე იყოს დაფუძნებული:Confetti.prototype = Object.create(Particle.prototype);
Confetti.prototype.constructor = Confetti;
ამ მომენტისთვის გვაქვს
Confetti
ობიექტები, რომლებიც ზუსტად ისევე მოქმედებენ, როგორც Particle
ობიექტები. მემკვიდრეობითობის იდეა არ არის დუბლიკატების შექმნა, მისი იდეაა ახალი ობიექტების შექმნა, რომლებიც დიდი დოზით იზიარებენ ფუნქციონალს, მაგრამ, აგრეთვე, რაღაცით განსხვავდებიან. ასე რომ, რით არის Confetti
ობიექტი განსხვავებული? მხოლოდ სახელითაც კი ჩანს, რომ განსხვავებულად უნდა გამოიყურებოდეს. ჩვენი Particle
ობიექტები არის ელიფსები, მაგრამ კონფეტი ხშირად არის კვადრატულად ამოჭრილი პატარა ფურცელი, ასე რომ, უნდა შევცვალოთ display
მეთოდი და ისინი ვაჩვენოთ მართკუთხედებად: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);
};
აი, პროგრამა ერთი
Particle
ობიექტის ნიმუშით და ერთი Confetti
ობიექტის ნიმუშით. აღვნიშნოთ, რომ ისინი იქცევიან ერთნაირად, მაგრამ განსხვავდებიან ვიზუალურად: მობრუნების დამატება
მოდით, ცოტა გავართულოთ. ვთქვათ, გვინდა, რომ
Confetti
ნაწილაკმა იტრიალოს ჰაერში ფრენისას. ცხადია, შეგვიძლია, შევქმნათ მოდელი კუთხური სიჩქარისა და აჩქარებისათვის, როგორც ეს რხევის სექციაში ვქენით. ამის ნაცვლად ვცდით სწრაფ და უხეშ ამოხსნას.ვიცით, რომ ნაწილაკს გააჩნია x კოორდინატი სადღაც 0-სა და ფანჯრის სიგანეს შორის. ვთქვათ, რომ, თუ ნაწილაკის x კოორდინატი 0-ის ტოლია, მისი მობრუნება იყოს 0; როცა მისი x კოორდინატი სიგანის ტოლია, მისი მობრუნება იყოს
TWO_PI
-ის ტოლი. გეცნობათ? როდესაც გვაქვს ერთი მნიშვნელობა ერთი განსაზღვრის არით, რომლის სხვა განსაზღვრის არეზე ასახვა გვინდა, შეგვიძლია, გამოვიყენოთ ProcessingJS-ის map()
ფუნქცია ახალი მნიშვნელობის ადვილად გამოსათვლელად.var theta = map(this.position.x, 0, width, 0, TWO_PI);
და, მხოლოდ დამატებითი ხიბლის შესაძენად, შეგვიძლია, კუთხის დიაპაზონი ავსახოთ 0-იდან
TWO_PI*2
-მდე. მოდით, შევხედოთ, როგორ ჯდება ეს კოდი display()
მეთოდში.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();
};
აი, როგორ გამოიყურება ის — გადატვირთეთ რამდენჯერმე, რათა ნახოთ მობრუნების ეფექტი:
აგრეთვე შეგვეძლო, theta (თეტა) დაგვეფუძნებინა y მდებარეობაზე, რასაც ოდნავ განსხვავებული ეფექტი აქვს. რატომ ხდება ასე? ნაწილაკს აქვს არანულოვანი მუდმივი აჩქარება y მიმართულებით, რაც ნიშნავს, რომ y სიჩქარე არის დროის წრფივი ფუნქცია, y მდებარეობა კი — დროის პარაბოლური (კვადრატული) ფუნქცია. შეგიძლიათ, ეს ქვემოთ მოცემული გრაფიკებზე ნახოთ (რომლებიც დაგენერირებულია ზემოთ მოცემული პროგრამის მიხედვით):
ეს ნიშნავს, რომ თუ კონფეტის (კუთხით) მობრუნებას დავაფუძნებთ y მდებარეობაზე, მაშინ მობრუნებაც პარაბოლური იქნება. ეს არ იქნება ფიზიკურად ძალიან ზუსტი, რადგან კონფეტის ტრიალი ჰაერში საკმაოდ ჩახლართულია, მაგრამ სცადეთ ეს თქვენით და ნახეთ, რამდენად რეალურად გამოიყურება! შეგიძლიათ, მოიფიქროთ სხვა ფუნქციები, რომლებიც კიდევ უფრო რეალურად გამოიყურება?
მრავალფეროვანი ნაწილაკების სისტემა
ახლა გვინდა, რომ შეგვეძლოს, შევქმნათ ბევრი
Particle
ობიექტი და ბევრი Confetti
ობიექტი. ამისთვის გავაკეთეთ ParticleSystem
ობიექტი. იქნებ შეგვიძლია, გავაფართოვოთ ის ისე, რომ Confetti
ობიექტებისთვის თვალყურის დევნაც შევძლოთ? აი, ამის გაკეთების ერთ-ერთი გზა — ვაკოპირებთ იმას, რაც Particle
ობიექტებისთვის გავაკეთეთ:var ParticleSystem = function(position) {
this.origin = position;
this.particles = [];
this.confettis = [];
};
ParticleSystem.prototype.addParticle = function() {
this.particles.push(new Particle(this.origin));
this.confettis.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();
}
};
აღვნიშნოთ, რომ გვაქვს ორი განსხვავებული მასივი, ერთი ნაწილაკებისათვის, მეორე კი — კონფეტისთვის. ყოველ ჯერზე, როცა ნაწილაკების მასივს რაიმეს ვუკეთებთ, ეს კონფეტის მასივსაც უნდა გავუკეთოთ! ეს გამაღიზიანებელია, რადგან ეს ნიშნავს, რომ ორჯერ უფრო მეტი კოდი უნდა დავწეროთ და თუ რაიმეს შევცვლით, ეს ორ ადგილას უნდა შევცვალოთ. შეგვიძლია, ეს გამეორება თავიდან ავირიდოთ, რადგან JavaScript-ში მასივებში სხვადასხვა ტიპის ობიექტების შენახვააა შესაძლებელი და, ვინაიდან ჩვენს ობიექტებს ერთი და იგივე ინტერფეისი აქვთ, ვიძახებთ
run()
მეთოდს და ობიექტების ორივე ტიპი განსაზღვრავს ამ ინტერფეისს. ასე რომ, დავუბრუნდებით მხოლოდ ერთი მასივის შენახვას, შემთხვევითად შევარჩევთ, რა ტიპის ნაწილაკის ობიექტი დავამატოთ, და დავუბრუნდებით ერთი მასივის გადაყოლას. ეს გაცილებით უფრო მარტივი ცვლილებაა — მხოლოდ addParticle
მეთოდის შეცვლა გვიწევს: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);
}
}
};
ახლა ყველაფერი მწყობრშია!
გსურთ, შეუერთდეთ დისკუსიას?
პოსტები ჯერ არ არის.