Mengapa objek saya bergerak lebih cepat di 45 derajat daripada di 90 derajat?

32

Saya memiliki objek dalam permainan saya yang bergerak lebih cepat pada 45 derajat kemudian pada 90 derajat.

Setiap objek memiliki

  • Titik (x, y) posisi
  • Arah Vector2D (x, y)
  • Kecepatan int

Dan yang saya lakukan saat pembaruan adalah posisi baru dihitung sebagai:

position.x += direction.x * speed
position.y += direction.y * speed

Bagaimana saya memperbaikinya? Saya ingin bergerak dengan kecepatan yang sama di sudut mana pun.

Jason94
sumber
8
Normalisasi vektor arah Anda sebelum digunakan; masalah terpecahkan.
decaviatedcaviar
1
Harus google normalisasi :) menemukan situs yang berguna ini fundza.com/vectors/normalize/index.html
Jason94
Dan jika Anda menggunakan input pengguna untuk mengontrol objek ini, waspadai mengunci ke arah 12,3,6,9 seperti yang dijelaskan di sini untuk pengembang XNA: xona.com/2010/05/03.html . Ini mungkin sesuatu yang Anda inginkan (seperti dalam game RPG) atau tidak (seperti dalam game gaya Geometry Wars).
Xonatron
di game lama Descent , ini adalah fitur .
J. Holmes
@ 32bitkid Ya, lihat juga Doom straferunning
bobobobo

Jawaban:

55

Ini dapat dijelaskan dengan Teorema Pythagoras , yang merupakan rumus berikut:

a² + b² = c²

Dalam kasus Anda, saat bergerak ke kanan, Anda menggunakan (x: 1, y: 0) yang memberi kami

c² = 1 + 0 = 1
c = sqrt(1) = 1.00

Saat bergerak ke atas dan ke kanan, Anda menggunakan (x: 1, y: 1) yang memberi kami

c² = 1 + 1 = 2
c = sqrt(2) = 1.41

Jadi seperti yang Anda lihat, panjang diagonal lebih panjang dari panjang pada sumbu kardinal.

Seperti yang disebutkan orang lain, Anda harus menormalkan vektor arah Anda. Jika Anda menggunakan XNA, dilakukan seperti ini:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed
William Mariager
sumber
Saya memberi Anda +1 untuk bantuan Anda dalam pertanyaan saya :)
Martin.
12

Normalisasi vektor arah Anda sebelum digunakan.

Seperti yang dijelaskan oleh MindWorX, ini dapat dipahami dengan mudah, jika Anda khawatir tentang vektor arah Anda mungkin memberi Anda kesedihan, pastikan mereka vektor satuan (besaran / panjang 1).

Length(Vector2(1, 1)) == 1.4142135623730951 // first hint of grief
Length(Vector2(1, 0)) == 1

Vector2(1, 1) * 2 == Vector2(2, 2)
Vector2(1, 0) * 2 == Vector2(2, 0)

Length(Vector2(2, 2)) = 2.8284271247461903 // second hint
Length(Vector2(2, 0)) = 2

Jika dinormalkan:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect
kaviar melambat
sumber
14
Bukan jawaban yang membantu. Jika si penanya tahu apa artinya "menormalkan vektor arah", dia tidak akan mengajukan pertanyaan.
Kristopher Johnson
@ KristopherJohnson tidak jelas si penanya tidak tahu cara menormalkan vektor. Meskipun si penanya tampaknya cukup banyak akal sehingga tidak masalah.
decaviatedcaviar
2
@KristopherJohnson: jika si penanya tidak tahu apa artinya "menormalkan vektor arah", dia hanya perlu mengetikkannya ke google, menambahkan nama bahasanya, dan mendapatkan kode dengan penjelasan.
Lie Ryan
6

Bagaimana Anda menghitung arah Anda? Jika 45 derajat (1,1), maka itu pasti akan lebih cepat dari 90 derajat (1,0).

Saya sarankan Anda menggunakan sesuatu seperti ini:

direction.x = Math.Cos(angleInRadians);
direction.y = Math.Sin(angleInRadians);

Untuk mendapatkan sudut dalam radian, Anda harus melipatgandakan gelar Anda dengan PI / 180atau bahkan lebih baik, gunakan MathHelper. Misalnya.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method
bummzack
sumber
6

Jason,

Daripada memiliki tiga atribut objek,

  • Titik (x, y) posisi
  • Arah Vector2D (x, y)
  • Kecepatan int

seringkali lebih mudah untuk menggabungkan arah dan kecepatan menjadi vektor kecepatan. Maka Anda hanya memiliki dua atribut,

  • Titik (x, y) posisi
  • Vector2D (x, y) kecepatan

Memperbarui posisi

Saat Anda perlu memperbarui posisi objek, sesederhana:

position.x += velocity.x * Δt;
position.y += velocity.y * Δt;

di mana Δtdelta waktu Anda - atau perbedaan waktu - atau langkah waktu.

Memperbarui posisi dan kecepatan

Cara menangani akselerasi (seperti dari gravitasi) juga sangat mudah. Jika Anda memiliki vektor percepatan, Anda dapat memperbarui kecepatan dan posisi bersama-sama seperti ini:

position.x += (velocity.x * Δt) + (0.5 * acceleration.x * Δt * Δt);
position.y += (velocity.y * Δt) + (0.5 * acceleration.y * Δt * Δt);

velocity.x += acceleration.x * Δt;
velocity.y += acceleration.y * Δt;

(Ini pada dasarnya adalah rumus s = vt + ½at² dari Fisika 101.)

Menerapkan kecepatan

Jika Anda ingin menerapkan kecepatan tertentu dalam beberapa arah yang dinormalkan, Anda dapat mengatur kecepatan seperti ini:

velocity.x = normalizedDirection.x * speed;
velocity.y = normalizedDirection.y * speed;

Turunkan kecepatan

Dan jika Anda perlu melakukan sebaliknya - menurunkan kecepatan dan arah dari vektor kecepatan yang diberikan - Anda cukup menggunakan teorema Pythagoras atau .Length()metode:

speed = velocity.Length();

Dan begitu kecepatan diketahui, arah yang dinormalisasi dapat dihitung dengan membagi kecepatan dengan kecepatan (berhati-hati untuk menghindari membagi dengan nol):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
Todd Lehman
sumber