Gerakan musuh dalam garis lurus ke pemain dalam permainan mengejar

10

Saya membuat game di mana musuh-musuh muncul secara acak di peta lalu bergerak ke arah setiap frame pemain dengan kecepatan acak. Peta tidak memiliki hambatan sehingga musuh harus selalu bergerak dalam garis lurus. Saya menulis fungsi gerakan beberapa kali tetapi tidak peduli apa musuh selalu mengenai 0, 45, 90, 135, 180, 225, 270, 315 sudut tetapi tidak pernah garis lurus. Berikut ini contoh kode:

    base_speed = random();

    diff_x = abs(enemy_y_pos - player_x_pos);
    diff_y = abs(enemy_x_pos - player_y_pos);
     if (diff_x > diff_y) {
      y_speed = base_speed;
     } else if (diff_y > diff_x) {
      x_speed = base_speed;
     }

     if (enemy_x_pos < player_x_pos) {
      velocity.x = x_speed;
     } else if (enemy_x_pos > player_x_pos) {
      velocity.x = -x_speed;
     } else {
      velocity.x = 0;
     }

     if (enemy_y_pos < player_y_pos) {
      velocity.y = y_speed;
     } else if (enemy_y_pos > player_y_pos) {
      velocity.y = -y_speed;
     } else {
            velocity.y = 0;
    }

    enemy_x_pos = enemy_x_pos + velocity.x;
    enemy_y_pos = enemy_y_pos + velocity.y;

Ini adalah upaya pertama saya di pemrograman game. Saya kira itu harus menggunakan algoritma seperti Bresenham's Line ( http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ) tetapi upaya saya untuk mengimplementasikan memiliki masalah yang sama. Bagaimana cara membuat musuh bergerak dalam garis lurus?

pengguna4761
sumber

Jawaban:

17

Algoritma garis Bresenham dikembangkan untuk menggambar garis cepat tanpa menggunakan operasi floating point (operasi integer lebih cepat). Ini sangat menarik secara historis tetapi bukan solusi yang sangat baik untuk sebuah game (terutama karena Anda tidak dapat menentukan kecepatan).

Saat melakukan gerakan 2D gunakan selalu vektor. Ini akan melakukan semua hal untuk Anda. Terkadang aljabar hanya indah.

Vec2d playerPos;
Vec2d direction; // always normalized
float velocity;

update()
{
   direction = normalize(playerPos - enemyPos);
   playerPos = playerPos + direction * velocity;
}

Akan ada beberapa kelas vector2D untuk bahasa target Anda.

Notabene
sumber
Itu bekerja dengan sempurna. Normalisasi adalah fungsi yang saya butuhkan. Terima kasih.
user4761
9

Apakah Anda menghitung setiap frame? Kode Anda menetapkan x_speed atau y_speed ke angka acak dan yang lainnya menjadi nol (atau default). Katakanlah musuh berada di 0, 0 dan pemain di 20, 10. Ini terlihat seperti itu akan mengatur x_speed ke beberapa nomor acak setiap frame dan memindahkan musuh ke kanan sampai ia berada di 10, 0. Kemudian musuh akan bergerak baik x atau y setiap frame sehingga sepertinya dia bergerak dalam sudut 45 derajat hingga 10, 10.

Penjelasan vektor Notabene benar tetapi inilah cara kerjanya. Vec2d akan memiliki komponen x dan y. Pada contoh di atas, playerPos - enemyPos akan memberi Anda vektor (20, 10). normalize () mengubah vektor sehingga panjangnya 1. Saat ini panjangnya adalah sqrt (20 * 20 + 10 * 10). Itu sekitar 22.36068. normalkan membagi X dan Y dengan angka ini, memberi Anda sekitar (0,89443, 0,44721) untuk arah, yang merupakan vektor yang menunjuk dari musuh ke pemain dengan panjang 1. Mengalikan ini dengan kecepatan acak Anda melakukan apa yang Anda inginkan.

Namun saya tidak akan menghitung kecepatan acak baru setiap frame. Anda mungkin hanya ingin mengatur kecepatan acak satu kali, atau memiliki kecepatan awal dan kecepatan target yang Anda lebih dekat ke setiap frame. Itu tidak masuk akal bagi musuh Anda untuk pergi 100 mph pada awalnya, kemudian 50 mph untuk satu frame dan 200 mph untuk yang berikutnya.

float targetSpeed = random(); // do this only rarely, or each frame if you don't mind slowing down and speeding up constantly

float acceleration = max(abs(targetSpeed - speed), 0.5) * sgn(targetSpeed - speed); // cap accel/decel at 0.5 per frame
speed = speed + acceleration;
Jason Goemaat
sumber
Penjelasan dan tambahan yang bagus Jason, terima kasih. Saya suka fungsi akselerasi Anda
Notabene
random () dalam lingkup itu salah ketik. Penjelasan dan kode Anda dengan apa yang ditulis notabene membantu saya membuat game berfungsi. Terima kasih.
user4761