Apa yang digunakan untuk atan dan atan2 dalam game?

48

Saya mengalami kesulitan memahami Math.tan()dan Math.atan()dan Math.atan2().

Saya memiliki pengetahuan dasar tentang trigonetri tetapi penggunaan SIN, COS, dan TAN dll untuk pengembangan game sangat baru bagi saya.

Saya membaca beberapa tutorial dan saya melihat bahwa dengan menggunakan garis singgung kita bisa mendapatkan sudut di mana satu objek perlu diputar oleh berapa banyak untuk menghadapi objek lain misalnya mouse saya. Jadi mengapa kita masih perlu menggunakan atan atau atan2?

SutoL
sumber
atan digunakan untuk menentukan sudut, berguna untuk ribuan hal yang berbeda. Apakah Anda memiliki pertanyaan aktual tentang penggunaannya, atau Anda hanya mencari bantuan matematika umum?
BlueRaja - Danny Pflughoeft
5
Anda pasti perlu memahami matematika / geometri di balik fungsi tersebut; begitu Anda menguasainya, mereka akan menjadi bagian dari "pemahaman dunia" Anda, seperti tata bahasa dasar yang Anda gunakan sehari-hari untuk berbicara. Setelah Anda dapat "berbicara matematika / geometri" Anda akan melihat bahwa fungsi-fungsi tersebut adalah alat simpy untuk mencapai hasil, yang paling alami untuk digunakan.
FxIII
Tutorial itu salah atau Anda salah paham. Anda menggunakan atan2 () untuk mendapatkan sudut dari satu objek ke objek lain. Cara kerjanya dijelaskan di bawah ini.
jhocking
terima kasih banyak atas jawabannya, sekarang saya menyesal tidak memberi perhatian lebih di kelas
sutoL

Jawaban:

94

Rumus singgung adalah ini:

tan(angle) = opposite/adjacent

Lihat gambar ini:

Diagram segitiga siku-siku, dengan sudut theta dan sisi yang berlawanan dan bersebelahan ditandai

Di mana asisi yang berdekatan, oadalah sisi yang berlawanan dan thetasudut. Demikian pula, sinus dan cosinus adalah dosa (ang) = o / h dan cos (ang) = a / h di mana hsisi yang panjang: http://www.mathwords.com/s/sohcahtoa.htm

Sementara itu atan(kependekan dari arc-tangent , juga dikenal sebagai invers tangent ) adalah kebalikan dari tan, seperti:

atan(opposite/adjacent) = angle

Dengan demikian, jika Anda mengetahui nilai-nilai dari sisi yang berlawanan dan yang berdekatan (misalnya, dengan mengurangi koordinat objek dari koordinat mouse) Anda bisa mendapatkan nilai sudut dengan atan.

Dalam pengembangan game, hal itu dapat terjadi cukup sering bahwa sisi yang berdekatan sama dengan 0 (misalnya koordinat x dari vektor menjadi 0). Mengingat bahwa tan(angle) = opposite/adjacentpotensi kesalahan divide-by-zero bencana harus jelas. Jadi banyak perpustakaan menawarkan fungsi yang disebut atan2, yang memungkinkan Anda menentukan parameter xdan y, untuk menghindari pembagian dengan nol untuk Anda dan memberikan sudut di kuadran kanan.

diagram atan2

(diagram milik Gareth, tolong pilih jawabannya juga)


Penggunaan trigonometri dalam pengembangan game cukup umum, terutama dengan vektor, tetapi biasanya perpustakaan menyembunyikan kerja trigonometri untuk Anda. Anda dapat menggunakan sin / cos / tan untuk banyak tugas yang melibatkan manipulasi geometris untuk menemukan nilai dari segitiga. Yang Anda butuhkan adalah 3 nilai (nilai panjang sisi / sudut) untuk menemukan nilai lain dari segitiga persegi panjang, jadi itu cukup berguna.

Anda bahkan dapat menggunakan sifat "bersepeda" dari fungsi sinus dan cosinus untuk perilaku khusus dalam sebuah permainan, misalnya saya telah melihat cos / sin banyak digunakan untuk membuat objek membalikkan yang lain.

Jesse Emond
sumber
8
Perlu dicatat bahwa Wikipedia menggambarkan penggunaan lain untuk Atan2 ( bukan atan) daripada hanya menghindari pembagian dengan nol. Misalnya, itu mengoreksi dirinya sendiri untuk kuadran yang digunakan, di mana biasanya Anda harus melakukan semua itu sendiri.
doppelgreener
Memang, catatan sangat penting di sana. Memperbarui jawaban saya.
Jesse Emond
Bukankah Anda mendapatkan tan dan atan mundur dalam paragraf panjang pertama Anda? Anda akan menggunakan atan untuk mendapatkan sudut (mis. Membalikkan persamaan) dan tan untuk mendapatkan rasio sisi (mis. Persis apa yang dikatakan persamaan).
jhocking
Nah jika Anda tahu o / a sama dengan misalnya 3, maka jika Anda ingin sudut yang Anda lakukan atan (3), itulah yang saya maksudkan: jika Anda ingin mengisolasi sudut, Anda menggunakan atan pada rasio. Jika Anda ingin mengisolasi rasio, gunakan tan pada sudutnya.
Jesse Emond
Saya akan mengubah kata-kata Anda, karena sepertinya Anda mengatakan sebaliknya.
jhocking
64

masukkan deskripsi gambar di sini

Gareth Rees
sumber
1
Apakah tidak sopan untuk mengedit jawaban teratas untuk memiliki diagram ini di dalamnya? Diagram ini hebat dan akan cocok setelah penjelasan tertulis Jesse tentang atan2 ().
jhocking
1
Silakan: menjadi tamuku! Saya akan menghapus jawaban ini setelah Anda selesai.
Gareth Rees
7
Tidak tidak. Teruskan! Itu dikreditkan dan orang-orang masih harus memilih di sini untuk diagram.
Jesse Emond
12

Inilah cara berpikir yang sedikit berbeda tentang fungsi trigonometri - termasuk atan () dan atan2 () - yang menurut saya bermanfaat (penjelasan dalam istilah "berlawanan / berbatasan" hanya membingungkan saya untuk beberapa alasan).

x, y, r, theta

Anda dapat berpindah dari satu titik ke titik lainnya dengan menggerakkan x unit secara horizontal dan y unit secara vertikal (disebut koordinat empat persegi panjang atau Cartesian ) atau dengan memindahkan jarak r pada sudut Ɵ (disebut koordinat polar dalam 2D).

Katakanlah kita memiliki koordinat polar (r, Ɵ) dan kami ingin mengubahnya menjadi (x, y).

cos (Ɵ) memberi Anda proporsi r yang terletak di sepanjang sumbu x :

  • Jika r = 1 maka x = cos (Ɵ).
  • Jika r = 100 maka x = 100 * cos (Ɵ).
  • Secara umum x = r * cos (Ɵ).

Demikian juga dosa (Ɵ) memberi Anda proporsi r yang terletak di sepanjang sumbu y :

  • Jika r = 1 maka y = sin (Ɵ).
  • Jika r = 100 maka y = 100 * sin (Ɵ).
  • Secara umum y = r * sin (Ɵ).

Bagaimana dengan mengubah koordinat persegi panjang (x, y) menjadi koordinat kutub (r, Ɵ)?

r adalah sisi miring dari segitiga siku-siku yang dibentuk oleh x dan y , jadi:

  • r = sqrt (x x + yy)

tan (Ɵ) memberikan kemiringan - kenaikan pada lintasan - dari garis dengan panjang r . Begitu:

  • tan (Ɵ) = y / x
  • Ɵ = atan (y / x)

Namun, ketika melakukan y / x, menghitung 3/4 memberikan jawaban yang sama dengan menghitung -3 / -4. Demikian juga -3/4 memberikan jawaban yang sama dengan 3 / -4. Jadi kita memiliki atan2 (y, x) yang menangani masing-masing tanda dengan benar dan mencegah kesalahan divide-by-zero / infinity.

  • Ɵ = atan2 (y, x)
AbePralle
sumber
4

Jesse dan Sid pada dasarnya benar, tetapi saya curiga Anda benar-benar memahami masalah tersebut.

Atan2 () diperlukan karena atan () tidak memberi tahu Anda sudut dari horizontal yang Anda butuhkan karena tidak mengatasi kuadran.

Ini berarti bahwa menggunakan atan untuk vektor (-2,2) dan (2, -2) akan memberikan nilai yang sama. Anda kemudian akan mengaktifkan tanda argumen Anda dan menambahkan pi ke hasilnya. Selain itu, Anda memiliki pembagian dengan nol kasus khusus untuk mempertimbangkan bahwa Jesse disebutkan. Juga atan2 () bekerja lebih baik daripada atan ketika x dekat dengan 0

Jadi Anda jika Anda ingin sudut vektor antara -pi dan pi

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

atau

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;
}
LukeN
sumber
1
"Ini berarti menggunakan atan untuk vektor (-2,2) dan (2,2) akan memberikan nilai yang sama." Jika demikian, atan Anda sangat rusak, karena salah satunya adalah -π / 4 dan yang lainnya π / 4. Malu pada semua orang yang memilih sampah ini.
Kode masih salah. Anda sedang menguji untuk y==0kemudian membaginya xdi cabang lain.
sam hocevar
0

Saya akan mengklarifikasi beberapa hal secara ringkas. Silakan merujuk ke tutorial trigonometri online untuk penjelasan terperinci.

Biarkan sebuah sudut. Kemudian tan (a) = tan (a + 2 * pi).

atan adalah invers tan, yaitu memberi Anda sudut diberi tan. Saat Anda memanggil atan (tan (a + 2 * pi)), jawabannya adalah a. Ini tidak memadai untuk aplikasi Anda.

atan2 akan mengambil 2 argumen untuk membantu situasi yang tepat ini. atan mengambil x dan y, yang pada dasarnya adalah cos (a) dan sin (a).

atan2 (sin (a), cos (a)) = a atan2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * dosa dan cos memiliki tanda yang berbeda, mengarah untuk jawaban yang berbeda * /

Silakan temukan beberapa tutorial untuk menjelaskan mengapa demikian.

Kode Anda harus seperti ini:

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
}
Sid Datta
sumber
tan(a) = - tan(-a), persamaan yang ingin Anda ungkapkan mungkintan(a) = tan(pi+a)
Ali1S232
0

Satu kegunaan untuk atan2saya temukan dalam kode saya adalah "sudut yang ditandatangani".

Biasanya cara Anda menemukan sudut antara dua vektor adalah

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

Tapi ini tidak memberi tahu Anda yang mana "mengarah" (yaitu "lebih maju searah jarum jam" dari yang lain). Informasi ini mungkin penting untuk pelacakan gerakan.

Anda bisa menemukan sudut dari sumbu x (1,0)untuk kedua vektor, tetapi ada masalah ambiguitas yang buruk: vektor dengan sudut 315 derajat mengembalikan 45 derajat menggunakan cosmetode di atas, dan begitu juga sudut 45 derajat. Anda dapat melakukan tanda centang yuntuk memperbaikinya, atau Anda dapat menggunakannya 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 ;
}
bobobobo
sumber
0

Harap Dicatat atan tidak rusak. arctan atau tan inverse hanya fungsi antara -PI / 2 dan PI / 2. Itu mengulangi pola ini tetapi kemudian itu bukan fungsi yang merupakan masalah bagi komputer karena tidak menangani beberapa jawaban.

Ini sama untuk asin antara -PI / 2 dan PI / 2 dan acos antara 0 dan PI. Ini adalah rentang paling sederhana untuk suatu fungsi terjadi. Untuk atan dan asin, ia beralih dari yang paling negatif ke yang paling positif. Untuk ACOS dari yang paling positif ke yang paling negatif. (ini membantu interpolasi jawaban yang lebih akurat)

jadi asin, acos dan atan adalah fungsi matematika.

Namun atan2 jauh lebih berguna untuk pemrograman karena memberikan revolusi lengkap (PI dalam radian atau 360 derajat atau 400 gradian). Perhatikan mereka hanya menghasilkan satu untuk tan bukan untuk dosa atau cos. Tan adalah satu-satunya yang menggunakan horizontal dan vertikal (x, y)

Jus
sumber