Alt sınıf türü sormaktan kaçınmak için iyi bir tasarım uygulaması nedir?


11

Programınız bir nesnenin hangi sınıf olduğunu bilmek gerektiğinde, genellikle bir tasarım kusurunu gösterir, bu yüzden bunu idare etmek için iyi bir uygulama olduğunu bilmek istiyorum. Circle, Polygon veya Rectangle gibi miras alınan farklı alt sınıflara sahip bir Shape Shape uyguluyorum ve bir Circle'ın Polygon veya Rectangle ile çarpışıp çarpışmadığını bilmek için farklı algoritmalar kullanıyorum. Daha sonra iki Shape örneğimiz olduğunu varsayalım ve birinin diğerini çarpışıp çarpmadığını bilmek istiyorum, bu yöntemde hangi algoritmayı çağırmam gerektiğini bilmek için çarpıştığım nesne olduğunu hangi alt sınıf türünden çıkarım bulmalıyım ama bu bir kötü tasarım veya uygulama? Bu şekilde çözdüm.

abstract class Shape {
  ShapeType getType();
  bool collide(Shape other);
}

class Circle : Shape {
  getType() { return Type.Circle; }

  bool collide(Shape other) {
    if(other.getType() == Type.Rect) {
      collideCircleRect(this, (Rect) other);     
    } else if(other.getType() == Type.Polygon) {
      collideCirclePolygon(this, (Polygon) other);
    }
  }
}

Bu kötü bir tasarım deseni mi? Alt sınıf türlerini çıkarmak zorunda kalmadan bunu nasıl çözebilirim?


1
Her Örneğin Circle gibi diğer tüm Şekil Türlerini bildiğini görürsünüz. Yani hepsi bir şekilde sağlam bir şekilde bağlılar. Üçgen gibi yeni bir şekil eklediğinizde, her yere Üçgen desteği eklersiniz. Daha sık ne değiştirmek istediğinize bağlıdır, yeni Şekiller ekleyeceksiniz, bu tasarım kötü. Çözüm yayılımınız olduğu için - Üçgen desteğiniz her yere eklenmelidir. Bunun yerine, Collisiondetection'ınızı her türle çalışabilen ve temsilci atanabilecek ayrı bir sınıfa çıkarmalısınız.
thepacker


IMO bu performans gereklilikleri ile ilgilidir. Kod ne kadar spesifik olursa, o kadar optimize edilebilir ve daha hızlı çalışır. Özel çarpışma çekleri olabilir çünkü bu özel durumda (bunu uygulamaya da), tip kontrol Tamam enourmously hızlı genel bir çözüm daha. Ancak çalışma zamanı performansı kritik olmadığında, her zaman genel / polimorfik yaklaşımla giderdim.
marstato

Herkes sayesinde, benim durumumda performans kritiktir ve yeni şekiller eklemeyeceğim, belki de CollisionDetection yaklaşımını yapıyorum, ancak yine de bir "Type getType ()" yöntemi tutmalı mıyım? Şekil veya bunun yerine CollisionDetection sınıfında Shape ile bir tür "örneği" mi yapıyorsunuz?
Alejandro

1
Soyut Shapenesneler arasında etkili bir çarpışma prosedürü yoktur . Sınır noktaları için çarpışmayı kontrol etmediğiniz sürece mantığınız diğer nesnenin içlerine bağlıdır bool collide(x, y)(kontrol noktalarının bir alt kümesi iyi bir dengede olabilir). Aksi takdirde türü bir şekilde kontrol etmeniz gerekir - soyutlamalara gerçekten ihtiyaç duyuyorsanız, Collisiontürler (mevcut aktör alanındaki nesneler için) üretmek doğru yaklaşım olmalıdır.
titreme

Yanıtlar:


13

Polimorfizm

Kullandığınız getType()veya bunun gibi bir şey olduğu sürece, polimorfizm kullanmıyorsunuz.

Hangi tipe sahip olduğunuzu bilmeniz gerektiğini hissediyorum. Ama bunu bilerek yapmak istediğiniz herhangi bir çalışma gerçekten sınıfa doğru itilmelidir. Sonra sadece ne zaman yapacağınızı söylersiniz.

Prosedür kodu bilgi alır ve kararlar alır. Nesneye yönelik kod, nesnelere bir şeyler yapmasını söyler.
- Alec Sharp

Bu prensibe söyle denir , sorma . Aşağıdakiler, yazım gibi ayrıntıları yaymamanıza ve üzerinde etkili olan mantık oluşturmanıza yardımcı olur. Bunu yapmak bir sınıfı ters yüz eder. Bu davranışı sınıf içinde tutmak daha iyidir, böylece sınıf değiştiğinde değişebilir.

kapsülleme

Bana başka hiçbir şekle ihtiyaç duyulmayacağını söyleyebilirsin ama sana inanmıyorum ve sen de yapmamalısın.

Enkapsülasyonu takip etmenin güzel bir etkisi, yeni türler eklemenin kolay olmasıdır, çünkü ayrıntıları gösterildikleri koda ifve switchmantığa yayılmaz . Yeni bir türün kodu tek bir yerde olmalıdır.

Bir cahil çarpışma tespit sistemi

Size performansı gösteren ve herhangi bir 2D şekli ile çalışan bir çarpışma algılama sistemini nasıl tasarlayacağımı göstereceğim.

resim açıklamasını buraya girin

Bunu çizmen gerektiğini söyle. Basit görünüyor. Hepsi daireler. Çarpışmaları anlayan bir çevre sınıfı yaratmak caziptir. Sorun şu ki, bu bizi 1000 çevreye ihtiyacımız olduğunda ayrılan bir düşünce çizgisine gönderiyor.

Çevreleri düşünmemeliyiz. Pikselleri düşünmeliyiz.

Bu adamları çizmek için kullandığınız aynı kodun, dokundukları zaman veya hatta kullanıcının tıkladığında algılamak için kullanabileceğiniz şey olduğunu söylersem ne olur?

resim açıklamasını buraya girin

Burada her daireyi benzersiz bir renkle çizdim (gözleriniz siyah anahattı görecek kadar iyiyse, görmezden gelin). Bu, bu gizli görüntüdeki her pikselin çizdiği şeye geri eşlendiği anlamına gelir. Bir hashmap buna iyi bakar. Aslında polimorfizmi bu şekilde yapabilirsiniz.

Bu görüntüyü asla kullanıcıya göstermeniz gerekmez. Birincisini çeken kodla oluşturursunuz. Sadece farklı renklerle.

Kullanıcı bir daireye tıkladığında tam olarak hangi daireyi biliyorum çünkü sadece bir daire o renktir.

Bir başkasının üzerine bir daire çizdiğimde, üzerine yazmak üzere olduğum her pikseli bir kümeye dökerek hızlı bir şekilde okuyabilirim. Yaptığım zaman çarpıştığı her çembere ayar noktaları ve şimdi çarpışmayı bildirmek için her birini sadece bir kez çağırmam gerekiyor.

Yeni bir tür: Dikdörtgenler

Bunların hepsi dairelerle yapıldı ama size soruyorum: dikdörtgenlerle farklı mı çalışır?

Algılama sistemine hiçbir daire bilgisi sızmamıştır. Yarıçap, çevre veya merkez noktasını umursamıyor. Pikselleri ve renkleri önemsiyor.

Bu çarpışma sisteminin münferit şekillere itilmesi gereken tek kısmı benzersiz bir renktir. Bunun dışında şekiller sadece şekil çizmeyi düşünebilir. Zaten iyi oldukları şey de bu.

Şimdi çarpışma mantığını yazdığınızda hangi alt tipe sahip olduğunuz umurumda değil. Çarpışmasını söylersiniz ve çizdiğini düşündüğü şeklin altında ne bulduğunu söyler. Türü bilmenize gerek yok. Bu, diğer sınıflardaki kodu güncellemek zorunda kalmadan istediğiniz kadar alt tür ekleyebileceğiniz anlamına gelir.

Uygulama seçenekleri

Gerçekten, benzersiz bir renk olması gerekmez. Gerçek nesne referansları olabilir ve bir dolaylı yoldan kaydedilebilir. Ama bu cevapta çizildiklerinde hoş görünmezlerdi.

Bu sadece bir uygulama örneğidir. Kesinlikle başkaları da var. Bunun gösterilmesi gereken şey, bu şekil alt türlerinin ne kadar yaklaştıklarına tek sorumlulukları ile bağlı kalmaları, tüm sistemin daha iyi çalışmasıdır. Muhtemelen daha hızlı ve daha az bellek yoğun çözümler var, ancak beni alt türlerin bilgisini yaymaya zorlarlarsa, bunları performans kazanımlarında bile kullanmaya razı olurum. Açıkça ihtiyaç duymadıkça onları kullanmazdım.

Çift gönderim

Şimdiye kadar çifte sevkiyatı tamamen görmezden geldim . Bunu yaptım çünkü yapabildim. Çarpışma mantığı hangi iki türün çarpıştığına aldırış etmediği sürece buna ihtiyacınız yoktur. İhtiyacınız yoksa, kullanmayın. İhtiyacınız olabileceğini düşünüyorsanız, olabildiğince uzun süre uğraşın. Bu tutuma YAGNI denir .

Eğer gerçekten farklı türden çarpışmalara ihtiyacınız olduğuna karar verirseniz, kendinize n şekil alt türlerinin gerçekten n 2 tür çarpışmaya ihtiyacı olup olmadığını sorun . Şimdiye kadar başka bir şekil alt türü eklemeyi kolaylaştırmak için çok çalıştım. Daireleri, karelerin var olduğunu bilmeye zorlayan bir çift ​​gönderme uygulamasıyla bozmak istemiyorum .

Zaten kaç çeşit çarpışma var? Biraz spekülasyon (tehlikeli bir şey) elastik çarpışmalara (kabarık), esnek olmayan (yapışkan), enerjik (patlayan) ve yıkıcı (zararlı) icat eder. Daha fazlası olabilir ama bu n 2'den küçükse , çarpışmalarımızı fazla tasarlamamıza izin verir.

Bu, torpidoumun hasar kabul eden bir şeye çarpması durumunda, bir uzay gemisine çarptığını bilmek zorunda olmadığı anlamına gelir. Sadece "Ha ha! 5 puan hasar aldın" demek zorunda.

Hasar veren şeyler hasar mesajı kabul eden şeylere hasar mesajı gönderir. Bu şekilde, diğer şekillere yeni şekil hakkında bilgi vermeden yeni şekiller ekleyebilirsiniz. Sonunda sadece yeni çarpışma türlerine yayılırsınız.

Uzay gemisi "Ha ha! 100 puan hasar aldın" torpuna geri gönderebilir. ve "Artık gövdeme yapıştın". Ve torp geri gönderebilir "Eh, bu yüzden beni unutmuşum".

Hiçbir noktada her birinin tam olarak ne olduğunu bilmiyor. Bir çarpışma arayüzü aracılığıyla birbirleriyle nasıl konuşacaklarını biliyorlar.

Şimdi emin olun, çift gönderme, işleri bundan daha yakından kontrol etmenizi sağlar, ancak bunu gerçekten istiyor musunuz?

Bunu yaparsanız, en azından bir şeklin gerçek şekil uygulamasında değil, ne tür çarpışmaların kabul edildiğinin soyutlamalarıyla çifte sevkiyat yapmayı düşünün. Ayrıca, çarpışma davranışı bağımlılık olarak enjekte edebileceğiniz ve bu bağımlılığa delege edebileceğiniz bir şeydir.

Verim

Performans her zaman önemlidir. Ancak bu her zaman bir sorun olduğu anlamına gelmez. Test performansı. Sadece spekülasyon yapmayın. Performans adına her şeyi feda etmek genellikle yine de performans koduna yol açmaz.



+1 için "Bana başka hiçbir şekle ihtiyaç duyulmayacağını söyleyebilirsin ama sana inanmıyorum ve sen de
istememelisin

Bu program şekiller çizmekten ibaret değil, tamamen matematiksel hesaplamalar hakkındaysa pikselleri düşünmek sizi hiçbir yere götürmez. Bu cevap, algılanan nesne yönelimli saflığa kadar her şeyi feda etmeniz gerektiğini ima eder. Ayrıca bir çelişki içerir: ilk önce tüm tasarımımızı gelecekte daha fazla şekle ihtiyacımız olabileceği fikrine dayandırmamız gerektiğini söylüyorsunuz, sonra "YAGNI" diyorsunuz. Son olarak, tür eklemeyi kolaylaştırmanın çoğu zaman işlem eklemenin daha zor olduğu anlamına gelir, bu da tür hiyerarşisi nispeten istikrarlıysa ancak işlemler çok değişirse kötüdür.
Christian Hackl

7

Sorunun açıklaması, bu özel durumda Multimethods (aka Çoklu dağıtım) kullanmanız gerektiği gibi geliyor - Double dispatch . İlk cevap, tarama oluşturmada çarpışan şekillerle nasıl genel olarak başa çıkılacağı konusunda uzadı, ancak OP'nin "vektör" çözümü istediğine ya da belki de tüm sorunun OOP açıklamalarında klasik örnek olan Şekiller açısından yeniden düzenlendiğine inanıyorum.

Alıntı yapılan wikipedia makalesi bile aynı çarpışma metaforunu kullanıyor, sadece alıntı yapmama izin verin (Python'un diğer diller gibi yerleşik multimetreleri yok):

@multimethod(Asteroid, Asteroid)
def collide(a, b):
    """Behavior when asteroid hits asteroid"""
    # ...define new behavior...
@multimethod(Asteroid, Spaceship)
def collide(a, b):
    """Behavior when asteroid hits spaceship"""
    # ...define new behavior...
# ... define other multimethod rules ...

Bir sonraki soru, programlama dilinizde multimettodlar için nasıl destek alacağınızdır.



Evet, cevaba eklenen Multimethods adlı Çoklu sevkıyat örneği
Roman Susi

5

Bu sorun iki düzeyde yeniden tasarım gerektirir.

Öncelikle, şekiller arasındaki şekiller arasındaki çarpışmayı tespit etmek için mantığı çıkarmanız gerekir. Bu, modele her yeni şekil eklemeniz gerektiğinde OCP'yi ihlal etmeyeceğinizdir . Zaten Daire, Kare ve Dikdörtgen tanımlı olduğunu düşünün. Daha sonra böyle yapabilirsin:

class ShapeCollisionDetector
{
    public void DetectCollisionCircleCircle(Circle firstCircle, Circle secondCircle)
    { 
        //Code that detects collision between two circles
    }

    public void DetectCollisionCircleSquare(Circle circle, Square square)
    {
        //Code that detects collision between circle and square
    }

    public void DetectCollisionCircleRectangle(Circle circle, Rectangle rectangle)
    {
        //Code that detects collision between circle and rectangle
    }

    public void DetectCollisionSquareSquare(Square firstSquare, Square secondSquare)
    {
        //Code that detects collision between two squares
    }

    public void DetectCollisionSquareRectangle(Square square, Rectangle rectangle)
    {
        //Code that detects collision between square and rectangle
    }

    public void DetectCollisionRectangleRectangle(Rectangle firstRectangle, Rectangle secondRectangle)
    { 
        //Code that detects collision between two rectangles
    }
}

Daha sonra, onu çağıran şekle bağlı olarak uygun yöntemin çağrılmasını ayarlamanız gerekir. Bunu polimorfizm ve Ziyaretçi Kalıbı kullanarak yapabilirsiniz . Bunu başarmak için, uygun nesne modeline sahip olmalıyız. İlk olarak, tüm şekiller aynı arayüze uymalıdır:

    interface IShape
{
    void DetectCollision(IShape shape);
    void Accept (ShapeVisitor visitor);
}

Ardından, bir ana ziyaretçi sınıfımız olmalıdır:

    abstract class ShapeVisitor
{
    protected ShapeCollisionDetector collisionDetector = new ShapeCollisionDetector();

    abstract public void VisitCircle (Circle circle);

    abstract public void VisitSquare(Square square);

    abstract public void VisitRectangle(Rectangle rectangle);

}

Burada bir sınıf özniteliği kullanıyorum, çünkü her ziyaretçi nesnesinin ShapeCollisionDetectortür niteliğine sahip olması gerekiyor .

Her IShapearabirim uygulaması , uygun ziyaretçiyi başlatır Acceptve çağıran nesnenin etkileşimde bulunduğu nesnenin uygun yöntemini şöyle çağırır :

    class Circle : IShape
{
    public void DetectCollision(IShape shape)
    {
        CircleVisitor visitor = new CircleVisitor(this);
        shape.Accept(visitor);
    }

    public void Accept(ShapeVisitor visitor)
    {
        visitor.VisitCircle(this);
    }
}

    class Rectangle : IShape
{
    public void DetectCollision(IShape shape)
    {
        RectangleVisitor visitor = new RectangleVisitor(this);
        shape.Accept(visitor);
    }

    public void Accept(ShapeVisitor visitor)
    {
        visitor.VisitRectangle(this);
    }
}

Ve belirli ziyaretçiler şöyle görünür:

    class CircleVisitor : ShapeVisitor
{
    private Circle Circle { get; set; }

    public CircleVisitor(Circle circle)
    {
        this.Circle = circle;
    }

    public override void VisitCircle(Circle circle)
    {
        collisionDetector.DetectCollisionCircleCircle(Circle, circle);
    }

    public override void VisitSquare(Square square)
    {
        collisionDetector.DetectCollisionCircleSquare(Circle, square);
    }

    public override void VisitRectangle(Rectangle rectangle)
    {
        collisionDetector.DetectCollisionCircleRectangle(Circle, rectangle);
    }
}

    class RectangleVisitor : ShapeVisitor
{
    private Rectangle Rectangle { get; set; }

    public RectangleVisitor(Rectangle rectangle)
    {
        this.Rectangle = rectangle;
    }

    public override void VisitCircle(Circle circle)
    {
        collisionDetector.DetectCollisionCircleRectangle(circle, Rectangle);
    }

    public override void VisitSquare(Square square)
    {
        collisionDetector.DetectCollisionSquareRectangle(square, Rectangle);
    }

    public override void VisitRectangle(Rectangle rectangle)
    {
        collisionDetector.DetectCollisionRectangleRectangle(Rectangle, rectangle);
    }
}

Bu şekilde, her yeni şekil eklediğinizde şekil sınıflarını değiştirmeniz gerekmez ve uygun çarpışma algılama yöntemini çağırmak için şekil türünü kontrol etmeniz gerekmez.

Bu çözümün bir dezavantajı, yeni bir şekil eklerseniz, ShapeVisitor sınıfını bu şeklin yöntemiyle genişletmeniz (örn. VisitTriangle(Triangle triangle)) Ve sonuç olarak bu yöntemi diğer tüm ziyaretçilere uygulamanız gerekir. Bununla birlikte, bu bir uzantı olduğundan, mevcut yöntemlerin değiştirilmemesi, ancak yalnızca yenilerinin eklenmesi anlamında, OCP'yi ihlal etmez ve kod yükü minimumdur. Ayrıca, sınıfı kullanarak, SRP'ninShapeCollisionDetector ihlali ve kod fazlalığı önlersiniz.


5

Temel probleminiz, modern OO programlama dillerinin çoğunda işlev aşırı yüklemesinin dinamik bağlama ile çalışmamasıdır (yani işlev bağımsız değişkenlerinin türü derleme zamanında belirlenir). İhtiyacınız olan şey, yalnızca bir nesne yerine iki nesne üzerinde sanal olan sanal bir yöntem çağrısıdır. Bu tür yöntemlere çoklu yöntemler denir . Ancak, Java, C ++, vb. Gibi dillerde bu davranışı taklit etmenin yolları vardır . Bu, çift ​​gönderimin çok kullanışlı olduğu yerdir .

Temel fikir, polimorfizmi iki kez kullanmanızdır. İki şekil çarpıştığında, nesnelerden birinin doğru çarpışma yöntemini polimorfizm yoluyla çağırabilir ve genel şekil türünün diğer nesnesini geçirebilirsiniz. Aranan yöntemde, bu nesnenin daire, dikdörtgen veya başka bir şey olup olmadığını bilirsiniz . Daha sonra, geçirilen şekil nesnesinde çarpışma yöntemini çağırır ve bu nesneyi iletirsiniz . Bu ikinci çağrı daha sonra tekrar polimorfizm yoluyla doğru nesne tipini bulur.

abstract class Shape {
  bool collide(Shape other);
  bool collide(Rect other);
  bool collide(Circle other);
}

class Circle : Shape {

  bool collide(Shape other) {
    return other.collide(this);
  }

  bool collide(Rect other) {
    // algorithm to detect collision between Circle and Rect
  }

  // ...
}

class Rect : Shape {

  bool collide(Shape other) {
    return other.collide(this);
  }

  bool collide(Circle other) {
    // algorithm to detect collision between Circle and Rect
  }

  // ...
}

Bununla birlikte, bu tekniğin büyük bir dezavantajı, hiyerarşideki her sınıfın tüm kardeşler hakkında bilgi sahibi olması gerektiğidir. Bu, daha sonra yeni bir şekil eklenirse yüksek bakım yükü getirir.


2

Belki de bu soruna yaklaşmanın en iyi yolu bu değildir

Matematik behing şekil çarpışması şekil kombinasyonlarına özeldir. Yani ihtiyacınız olacak alt rutinlerin sayısı, sisteminizin desteklediği şekil sayısının karesidir. Şekil çarpışmaları aslında şekiller üzerindeki işlemler değil, şekilleri parametre olarak alan işlemlerdir.

Operatör Aşırı Yük Stratejisi

Temel matematik problemini basitleştiremiyorsanız, operatörün aşırı yük yaklaşımını öneriyorum. Gibi bir şey:

 public final class ShapeOp 
 {
     static { ... }

     public static boolean collision( Shape s1, Shape s2 )  { ... }
     public static boolean collision( Point p1, Point p2 ) { ... }
     public static boolean collision( Point p1, Square s1 ) { ... }
     public static boolean collision( Point p1, Circle c1 ) { ... }
     public static boolean collision( Point p1, Line l1 ) { ... }
     public static boolean collision( Square s1, Point p2 ) { ... }
     public static boolean collision( Square s1, Square s2 ) { ... }
     public static boolean collision( Square s1, Circle c1 ) { ... }
     public static boolean collision( Square s1, Line l1 ) { ... }
     (...)

Statik başlatıcıda, genel çarpışma (Şekil s1, Şekil s2) yöntemine bir diynamik dağıtıcı uygulamak için yöntemlerin bir haritasını yapmak için yansımayı kullanacağım. Statik başlatıcı ayrıca, eksik çarpışma fonksiyonlarını tespit etmek ve bunları rapor etmek, sınıfı yüklemeyi reddetmek için bir mantığa sahip olabilir.

Bu, C ++ operatörünün aşırı yüklenmesine benzer. C ++ operatörünün aşırı yüklenmesi çok kafa karıştırıcıdır çünkü aşırı yükleyebileceğiniz sabit bir simge kümeniz vardır. Bununla birlikte, konsept çok ilginçtir ve statik işlevlerle çoğaltılabilir.

Bu yaklaşımı kullanmamın nedeni, çarpışmanın bir nesne üzerinde bir işlem olmamasıdır. Bir çarpışma, iki keyfi nesne hakkında bir ilişki anlatan harici bir işlemdir. Ayrıca, statik başlatıcı bazı çarpışma fonksiyonlarını özlediğimi kontrol edebilecek.

Mümkünse matematik probleminizi basitleştirin

Bahsettiğim gibi, çarpışma fonksiyonlarının sayısı şekil tiplerinin sayısının karesidir. Bu, sadece 20 şekle sahip bir sistemde, 21 şekil 441 ve benzeri ile 400 rutine ihtiyacınız olacağı anlamına gelir. Bu kolayca genişletilebilir değildir.

Ancak matematiğinizi basitleştirebilirsiniz . Çarpışma fonksiyonunu uzatmak yerine her şekli rasterleştirebilir veya üçgenleyebilirsiniz. Bu şekilde çarpışma motorunun genişletilebilir olması gerekmez. Çarpışma, Mesafe, Kavşak, Birleştirme ve diğer birçok işlev evrensel olacaktır.

üçgenlere

Çoğu 3d paket ve oyunun her şeyi üçgenlediğini fark ettiniz mi? Matematiği basitleştirmenin biçimlerinden biri budur. Bu, 2d şekiller için de geçerlidir. Polisler üçgenleştirilebilir. Daireler ve yivler çokgenlere yakın olabilir.

Yine ... tek bir çarpışma fonksiyonunuz olacak. Sınıfınız o zaman:

public class Shape 
{
    public Triangle[] triangulate();
}

Ve operasyonlarınız:

public final class ShapeOp
{
    public static boolean collision( Triangle[] shape1, Triangle[] shape2 )
}

Daha basit değil mi?

Rasterleştir

Tek bir çarpışma işlevine sahip olmak için şeklinizi rasterleştirebilirsiniz.

Rasterleştirme radikal bir çözüm gibi görünebilir, ancak şekil çarpışmalarınızın ne kadar hassas olması gerektiğine bağlı olarak uygun fiyatlı ve hızlı olabilir. Hassas olmaları gerekmiyorsa (bir oyunda olduğu gibi) düşük çözünürlüklü bitmap'lere sahip olabilirsiniz. Çoğu uygulama matematikte mutlak hassasiyete ihtiyaç duymaz.

Yaklaşımlar yeterince iyi olabilir. Biyoloji simülasyonu için ANTON süper bilgisayarı bir örnektir. Matematiği hesaplaması zor olan birçok kuantum efekti atar ve şimdiye kadar yapılan simülasyonlar gerçek dünyada yapılan deneylerle tutarlıdır. Oyun motorlarında ve oluşturma paketlerinde kullanılan PBR bilgisayar grafik modelleri, her bir kareyi oluşturmak için gereken bilgisayar gücünü azaltan basitleştirmeler yapar. Aslında fiziksel olarak doğru değil ama çıplak göze ikna olacak kadar yakın.

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.