Oyunda atanan ve atan2 ne kullanılır?


47

Bazı problemleri anlamakta zorluk çekiyorum Math.tan()ve Math.atan()ve Math.atan2().

Trigonmetri hakkında temel bilgilere sahibim ancak oyun geliştirme için SIN, COS ve TAN vb. Kullanımı benim için çok yeni.

Bazı dersleri okuyorum ve teğet kullanarak, bir nesnenin hangi fareyle döndürülmesinin gerekli olduğu açıyı elde edebileceğimizi görüyorum, örneğin farem. Peki neden hala atanan veya atan2 kullanmamız gerekiyor?


açıyı belirlemek için kullanılır, bin farklı şey için faydalıdır. Kullanımı hakkında gerçek bir sorunuz mu var, yoksa sadece genel matematik yardımını mı arıyorsunuz?
BlueRaja - Danny Pflughoeft

5
Bu fonksiyonun arkasındaki matematiği / geometriyi kesinlikle anlamanız gerekir; Bir kez onları ustalaştığınızda, konuşmak için her gün kullandığınız temel gramer gibi, “dünya anlayışınızın” bir parçası olacaklar. "Matematik / geometriyi" konuşabildiğinizde, bu fonksiyonların bir sonuç elde etmek için kullanımı en doğal olan basit araç olduğunu göreceksiniz.
FxIII

Bu dersler ya yanlış ya da yanlış anladınız. Açıyı bir nesneden diğerine almak için atan2 () işlevini kullanırsınız. Bunun nasıl çalıştığı aşağıda açıklanmıştır.
jhocking

cevaplar için insanlar teşekkür ederim, şimdi sınıfta daha fazla dikkat
etmiyoruz pişmanım

Yanıtlar:


93

Teğet formül budur:

tan(angle) = opposite/adjacent

Bu çizime bakınız:

Dik açılı bir üçgenin diyagramı, açılı teta ve bunun karşıt ve bitişik kenarları işaretli

aBitişik taraf nerede , ozıt taraf ve thetaaçıdır. Benzer şekilde, sinüs ve kosinüs sin (ang) = o / h ve cos (ang) = a / h huzun yan ise: http://www.mathwords.com/s/sohcahtoa.htm

Bu arada atan(kısa yay tanjantı olarak da bilinen, ters teğet ) tersidir tanşöyle:

atan(opposite/adjacent) = angle

Böylece hem zıt hem de bitişik tarafların değerlerini biliyorsanız (örneğin, nesnenin koordinatlarını fare koordinatlarından çıkartarak) açının değerini elde edebilirsiniz atan.

Oysa oyun geliştirmede, bitişik tarafın 0'a eşit olması sıkça gerçekleşebilir (örneğin, bir vektörün x koordinatı 0'dır). tan(angle) = opposite/adjacentFeci bir sıfıra bölünme hatası olasılığının açık olması gerektiğini hatırlamak . Bu yüzden, birçok kütüphane atan2sizin için sıfırı bölmekten kaçınmak ve sağ kadranda bir açı vermek için hem xve yparametreleri belirlemenizi sağlayan bir işlev sunar .

atan2 diyagramı

(Gareth izniyle şema, lütfen cevabını da oyla)


Oyun gelişiminde trigonometri kullanımı, özellikle vektörlerde oldukça yaygındır, ancak genellikle kütüphaneler sizin için trigonometri çalışmasını gizler. Üçgenden bir değer bulmak için geometrik manipülasyonlar içeren birçok görev için sin / cos / tan komutunu kullanabilirsiniz. Tek ihtiyacınız olan bir dikdörtgen üçgenin diğer değerlerini bulmak için 3 değerdir (yan uzunluklar / açı değerleri), bu yüzden oldukça kullanışlıdır.

Bir oyunda özel davranışlar için sinüs ve kosinüs fonksiyonlarının “bisiklete binme” özelliğini bile kullanabilirsiniz, örneğin bir nesneyi diğerinin etrafında döndürmek için çok fazla kullandığını gördüm.


8
Wikipedia belirterek It yetmeyecek açıklanır ATAN2 diğer kullanımlarını ( değil sadece sıfıra bölme kaçınarak daha atan). Örneğin, kullanılan kadran için düzeltir, normalde tüm bunları kendiniz yapmanız gerekir.
doppelgreener

Gerçekten de, orada çok önemli bir not. Cevabım güncelleniyor.
Jesse Emond

İlk uzun paragrafında bronzlaşıp geriye atamadın mı? Açıyı elde etmek için atanmış (yani denklemi tersine çevirir) ve kenarların oranını elde etmek için bronzlaşırsınız (yani denklemin tam olarak söylediği gibi).
jhocking

Eğer a / a'nın örneğin 3'e eşit olduğunu biliyorsanız, o zaman yaptığınız açıyı istiyorsanız (3), demek istediğim: açıyı izole etmek istiyorsanız, oran üzerinde atanmış olursunuz. Oranı izole etmek istiyorsanız açıyı ten kullanırsınız.
Jesse Emond

O zaman ifadenizi değiştireceğim, çünkü tam tersi söylüyormuşsunuz gibi geliyor.
jhocking

63

görüntü tanımını buraya girin


1
Bu diyagramın içinde olması için en üstteki cevabı düzenlemek imkansız olur mu? Bu şema harikadır ve Jesse'nin atan2 () tarafından yazılan açıklamasından hemen sonra uygun olacaktır.
12'de atıyor

1
Devam et: benim misafirim ol! Bu cevabı tamamladıktan sonra silerim.
Gareth Rees

7
Hayır hayır. Aynen böyle devam! Bu kredilendirilir ve diyagram için insanlar hala bu noktada oy kullanmalıdır.
Jesse Emond

12

İşte size yararlı bulduğum (atan () ve atan2 () dahil) trig işlevleriyle ilgili biraz farklı bir düşünce şekli ("karşıt / bitişik" anlamındaki açıklamalar sadece bir nedenden dolayı kafamı karıştırıyor).

x, y, r, teta

Bir noktadan diğerine x birimlerini yatay hareket ettirerek ve y birimlerini dikey olarak ( dikdörtgen veya Kartezyen koordinatları olarak adlandırılır ) veya distance ( 2B'de kutupsal koordinatlar olarak adlandırılır) açısıyla r hareket ettirerek elde edebilirsiniz .

Diyelim ki bir kutupsal koordinatımız var (r, it) ve onu (x, y) 'ye dönüştürmek istiyoruz.

cos (Ɵ) size x ekseni boyunca uzanan r oranını verir :

  • Eğer r = 1 ise x = cos (Ɵ).
  • Eğer r = 100 ise x = 100 * cos (Ɵ).
  • Genelde x = r * cos (Ɵ).

Aynı şekilde günah (Ɵ) size y ekseni boyunca uzanan r oranını verir :

  • Eğer r = 1 ise, y = sin (Ɵ).
  • Eğer r = 100 ise y = 100 * sin (Ɵ).
  • Genelde y = r * sin (Ɵ).

Dikdörtgen koordinatı (x, y) kutupsal koordinata (r, Ɵ) dönüştürmeye ne dersiniz?

r , x ve y'nin oluşturduğu dik üçgenin hipotenüsü , yani:

  • r = sqrt (x x + y y)

tan (Ɵ) eğriyi - r uzunluğu ile çizginin ilerleyişini - verir . Yani:

  • tan (Ɵ) = y / x
  • Ɵ = atandı (y / x)

Ancak, y / x gerçekleştirirken, 3/4 hesaplamak, -3 / -4 hesaplamakla aynı cevabı verir. Aynı şekilde -3/4, 3 / -4 ile aynı cevabı verir. Bu yüzden bireysel işaretleri doğru şekilde işleyen ve sıfıra / sonsuzluk hatasını önleyen atan2 (y, x) ayarına sahibiz.

  • Ɵ = atan2 (y, x)

4

Jesse ve Sid temelde haklılar, ancak sorunla ilgili gerçekten bir iç görüşten sonra olduğundan şüpheleniyorum.

Atan2 (), atan () olarak ihtiyaç duyduğunuz yatayda, açıyı dörtgenlerle baş etmediğinden size söylemez.

Bu, vektörler (-2,2) ve (2, -2) için atanmanın aynı değeri vereceği anlamına gelir. Ardından kendi argümanlarının işaretini açacak ve sonuca pi ekleyeceksin. Ek olarak, Jesse'nin bahsettiğini düşünmek için sıfıra sıfır özel vakayla sahip oldunuz. Ayrıca atan2 (), x 0'a yakın olduğunda atanmadan daha iyi çalışır

Öyleyse -pi ve pi arasındaki bir vektörün açısını istiyorsanız

x = -2
y = 2
angle = Math.Atan2(y, x)

veya

x = -2
y = 2
angle = calculateAngle(y, x);

double CalculateAngle(double y, double x)
{
    double angle = 0;
    if (x == 0)
    {
        if (y == 0)
            angle = 0;
        else if (y > 0)
            angle = Math.PI/2;
        else
            angle = -Math.PI/2;
    }
    else
    {
        angle = Math.Atan(y/x);
        if (x < 0)
        {
            if (y > 0)
            {
                angle += Math.PI;
            }
            else if (y < 0)
            {
                angle -= Math.PI;
            }
            else
            {
                angle = Math.PI;
            }
        }
    }
    return angle;
}

1
"Bu, vektörler için atanan (-2,2) ve (2,2) 'nin aynı değeri vereceği anlamına gelir." Eğer durum buysa, atamanız inanılmaz derecede kırıldı, çünkü bunlardan biri -π / 4, diğeri π / 4 olmalı. Bu çöpü oylayan herkese utanmalısın.

Kod hala yanlış. Diğer dalda y==0bölüştürüp test ediyorsun x.
sam hocevar,

0

Birkaç şeyi özlü bir şekilde netleştireceğim. Lütfen ayrıntılı bir açıklama için çevrimiçi trigonometri eğitimlerine bakın.

Bir açı olsun. Sonra tan (a) = tan (a + 2 * pi).

atan ten rengi ters, yani ten rengi veren açıyı verir. Atan (tan (a + 2 * pi)) deyince, cevap a olacaktır. Bu, başvurunuz için yetersiz kalacaktır.

atan2, bu kesin durumlara yardımcı olmak için 2 argüman alacaktır. atan, temelde cos (a) ve günah (a) olan x ve y'yi alır.

atan2 (günah (a), cos (a)) = a atan2 (günah (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * günah ve cos farklı işaretlere sahiptir; farklı bir cevaba * /

Lütfen bunun neden böyle olduğunu açıklayan bazı dersler bulun.

Kodunuz böyle bir şey olmalı:

if (mouseMoved)
{
  double angle = atan2(mousey - objecty, mousex - objectx);

  object. setTransform to Rotate(angle);

  // If you want to print it
  print radian_to_degrees(angle); // Because angle is in radian 360 degrees = 2*Pi radians
}

tan(a) = - tan(-a), ifade etmek istediğiniz denklem belki de oldutan(a) = tan(pi+a)
Ali1S232

0

Kodumda atan2bulduğum bir kullanım "imzalı açı" dır.

Normalde iki vektör arasındaki açıyı bulma şekliniz

inline float angleWith( const Vector2f& o ) const
{
    return acosf( this->normalizedCopy().dot(o.normalizedCopy()) ) ;
}

Fakat bu size hangisinin "yol gösterici" olduğunu söylemez (yani, diğerinden daha "saat yönünde ileride"). Bu bilgi jest takibi için önemli olabilir.

Her (1,0)iki vektör için de x ekseninden açıyı bulabilirsiniz , ancak belirsizliğin belirsizliği sorunu var: 315 derecelik bir açı ile bir vektör cosyukarıdaki yöntemi kullanarak 45 dereceye döner ve böylece 45 derecelik bir açı yapar. Bunu ydüzeltmek için bir işaret kontrolü yapabilir veya kullanabilirsiniz atan2.

// Returns + if this leads o.
// more expensive than unsigned angle.
inline float signedAngleWith( const Vector2f& o ) const
{
  float aThis = atan2f( y, x );
  float aO = atan2f( o.y, o.x ) ;
  return aThis - aO ;
}

0

Lütfen not atanmadı. arktan veya tan ters, sadece -PI / 2 ve PI / 2 arasındaki bir fonksiyondur. Bu deseni tekrar eder, ancak birden fazla cevabı ele almadığı için bilgisayar için problem olan bir fonksiyon değildir.

Bu, -PI / 2 ve PI / 2 arasındaki asin ve 0 ile PI arasındaki acos için aynıdır. Bunlar, bir fonksiyonun gerçekleşmesi için en basit aralıklardır. Atanan ve asin için en olumsuzdan en pozitifine doğru gider. Acos için en olumludan en olumsuzuna gider. (bu daha doğru cevapların enterpolasyonuna yardımcı olur)

yani asin, acos ve atanan matematiksel fonksiyonlardır.

atan2 ancak tam devrimi sağladığı için programlama için çok daha faydalıdır (radyan veya 360 derece veya 400 gradiyanda PI). Onlar sadece günah veya cos için değil tan için bir tane üretti. Tan yatay ve dikey kullanan tek kişidir (x, y)

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.