Cara mengikat rilis peluru dengan animasi menembak

15

Katakanlah Anda memiliki animasi yang Anda inginkan terjadi ketika menembakkan peluru. Bagaimana Anda mendapatkan peluru muncul di akhir animasi. Satu-satunya hal yang saya tahu adalah mengetahui panjang waktu animasi, dan menunda pengaturan posisi peluru dan mengaturnya aktif sampai jumlah waktu telah berlalu. Saya hanya ingin tahu apakah ini pendekatan terbaik, bagaimana orang lain menangani ini?

EDIT: Saya pikir saya mengalami masalah dalam mengeja pertanyaan dengan benar.

Pertanyaan saya

tp0w3rn
sumber
Terima kasih! Banyak ide bagus dari Anda semua, saya suka ide menggunakan panggilan balik. Saya pikir saya akan mencoba dan mengimplementasikannya, saya benar-benar tidak ingin bergantung pada pelacakan waktu.
tp0w3rn

Jawaban:

8

Pada dasarnya Anda berada di jalur yang benar - Anda perlu tahu berapa lama animasi berlangsung untuk melakukan hal semacam ini. Animasi lebih dari sekadar kumpulan bingkai, ada segala macam informasi lain di sekitar mereka yang Anda butuhkan. Misalnya berapa banyak frame yang ada, apakah loop animasi, seberapa cepat pemutarannya (misalnya 10 frame animasi per detik atau 25, atau 60?). Setiap animasi dapat didefinisikan dalam beberapa bagian data, yang dapat dilihat dan diputar ulang oleh beberapa kode animasi umum. Anda harus merangkum bagian animasi dalam sedikit kode sendiri, yang tidak mengetahui apa-apa kecuali definisi animasi ini dan cara menampilkan masing-masing bingkai gambar. Artinya, miliki objek animasi yang dapat Anda muat, mulai mainkan, hentikan mainnya, dan suruh untuk merender di lokasi tertentu di layar.

Pendekatan yang fleksibel adalah dengan menggunakan semacam definisi animasi untuk merangkum informasi semacam ini. Jadi daripada hanya mengatakan "animasi X adalah semua frame ini, cukup mainkan melalui mereka", Anda mendapatkan sesuatu yang sedikit lebih kompleks.

Misalnya dengan semacam format data mocked up

animasi =
{
  {name = "walk", files = "walk * .png", frameCount = "12", loop = "true"},
  {name = "fire" files = "fire * .png" frameCount = "6",
       acara = {
           {name = "bulletLeavesGun", frame = "4", param1 = "43", param2 = "30"}
       }
  }
}

Jadi kode Anda mengatakan sesuatu seperti:

currentAnimation = animations.Get("fire");
currentAnimation.Play();

Cara Anda mendeteksi peristiwa bisa dengan kode animasi yang memanggil Anda kembali (yaitu ketika ia mendeteksi acara baru karena animasi telah diputar ke bingkai tertentu, ia memanggil kode permainan Anda untuk memberi tahu tentang acara baru), atau dengan polling animasi seperti ini:

List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
    if (event.name == "bulletLeavesGun")
    {
        Vector2 bulletPosition = new Vector2(event.param1, event.param2);
        Vector2 actualBulletPosition = new Vector2(
                 character.x + bulletPosition.x, 
                 character.y + bulletPosition.y);
        CreateBulletAt(actualBulletPosition);
    }
}

Poin yang perlu diperhatikan:

  • Kode animasi harus ada secara terpisah dari kode permainan. Anda benar-benar tidak ingin kode gameplay Anda terlalu terikat dengan mur dan baut pemutaran animasi.
  • Kode animasi tahu apakah akan mengulang berdasarkan definisi animasi atau tidak
  • Kode animasi tahu kapan animasi dilakukan, dan dapat memanggil kembali ke kode lain untuk mengatakan 'hei, animasi yang disebut "api" baru saja selesai, apa yang ingin Anda lakukan sekarang?'
  • Kode animasi tidak tahu apa-apa tentang acara selain bahwa mereka memiliki nama dan beberapa data arbitrer yang terkait dengannya (param1 dan param2)
  • Kode animasi tahu frame apa yang saat ini aktif, dan ketika itu berubah menjadi bingkai baru, ia dapat memeriksa dan berkata 'oh, saya di frame 4 sekarang, itu berarti peristiwa yang disebut "api" ini baru saja terjadi, tambahkan ke daftar acara terbaru saya sehingga saya dapat memberi tahu siapa pun yang bertanya tentang hal itu '.

Jika Anda tidak memerlukan tembakan peluru untuk terjadi di dalam animasi, tetapi hanya setelah itu selesai, Anda dapat pergi dengan sistem yang jauh lebih kompleks tanpa gagasan peristiwa. Tetapi Anda masih menginginkan sistem tempat animasi diputar sendiri, tahu berapa lama, dan dapat memanggil kembali kode permainan saat animasi selesai.

MrCranky
sumber
Saya tidak setuju dengan menjaga animasi logika sadar (pada frame 4 sekarang, itu berarti peristiwa ini disebut "api" baru saja terjadi). Animasi harus buta dan bisu. Saya harus melakukan beberapa logika sisi server dan merobek animasi dan UI dari permainan adalah sesuatu yang saya tidak ingin lakukan lagi. Saya benar-benar akan merekomendasikan menggunakan animasi yang sangat pendek dan tersegmentasi, memainkannya secara paralel dengan logika membiarkan logika memicu urutan animasi pada kecepatan yang ditentukan oleh logika. Tidak pernah memiliki tes logika untuk status animasi.
Coyote
Memisahkan animasi menjadi beberapa bagian sepertinya tidak perlu. Saya setuju dengan tidak memilih status animasi, tetapi itu masih meninggalkan rekomendasi pertamanya. Saya tidak tahu apakah dia bermaksud sistem acara terpisah untuk memisahkan kode animasi dari sisa permainan (pola pengamat?) Tapi itulah cara saya melakukannya. Baik "logika" seperti yang Anda masukkan harus tahu tentang kode animasi, atau sebaliknya.
jhocking
@Coyote Saya akan mengatakan di sana Anda mencampur dua hal yang terpisah. Ya, logika sisi server harus selalu independen dari visual (karena Anda tidak ingin harus menjalankan sistem animasi hanya untuk mencari tahu kapan peluru ditembakkan), tetapi itu tidak akan membantu Anda membangun sistem animasi pada klien . Pada klien, Anda benar-benar tidak ingin visual menjadi budak tanpa berpikiran ke server, karena itu akan terlihat mengerikan - peluru muncul pada waktu yang aneh dan tidak sinkron dengan karakter karena ada lonjakan lag antara permainan dan server . Tidak ada alasan Anda tidak dapat memiliki keduanya (lanjutan ...)
MrCranky
@Coyote (lanjutan ...), gameplay dapat didorong oleh server dipisahkan dari visual. Jadi peluru ditembakkan pada waktu X di server, dan klien mencerminkan tindakan itu dengan mulai memutar animasi api dengan segera, dengan tembakan peluru visual yang tertinggal beberapa frame di belakang simulasi gameplay peluru. Segala macam kompromi perlu dibuat antara kesetiaan visual dan simulasi gameplay, jadi untuk mengatakan bahwa "animasi harus buta dan bisu" benar-benar naif. Kadang-kadang acara benar-benar perlu dikaitkan dengan bingkai animasi, karena tidak ada metode lain yang akan membuatnya terlihat atau terdengar benar.
MrCranky
@Coyote Sebenarnya sekarang saya memikirkannya, penembakan peluru adalah contoh yang mengerikan untuk ini, sebagian besar karena jawaban dari thedaian di bawah ini. Penembakan harus segera terjadi. Contoh yang lebih baik adalah VFX debu yang menyala ketika sebuah karakter mendarat - server dan klien akan menyinkronkan kapan karakter mulai melompat, tetapi tampilan visual diserahkan kepada klien. Dan ketika animasi menyentuh bingkai yang tepat di mana kaki menyentuh tanah, acara VFX harus diaktifkan. Demikian pula, acara diperlukan jika keputusan perlu dibuat pada bingkai animasi tertentu apakah akan bercabang ke animasi lain.
MrCranky
3

Dalam beberapa cara, Anda harus menunggu sampai animasi selesai dan membuat peluru pada saat itu.

Pengaturan timer saja akan berhasil, jika Anda yakin laju animasi Anda sudah tetap. Sebagai variasi kecil, Anda dapat memiliki kode internal ke peluru yang membuatnya menunggu sebentar sebelum muncul dan bergerak.

Bergantung pada platform pengembangan Anda, Anda mungkin memiliki semacam fungsi pembaruan animasi atau panggilan balik yang akan memungkinkan Anda merespons saat yang tepat animasi mencapai titik yang diinginkan. Inilah yang saya lakukan dengan Flixel, misalnya.

Gregory Avery-Weir
sumber
1
addAnimationCallbackMetode Flixel dapat digunakan pada entitas firing. Dalam fungsi panggilan balik, Anda dapat melihat apakah bingkai animasi penembakan saat ini adalah bingkai yang seharusnya membuat entitas bullet. Jika sudah maka Anda bisa menambahkan peluru di layar.
Snow Blind
2

Jawaban lurus ke depan: Dengan asumsi Anda memiliki animasi yang ingin Anda mainkan ketika pemain menekan tombol 'tembak', dan kemudian peluru keluar setelah selesai bermain. Idealnya, Anda harus menghindari pengkodean waktu animasi yang sulit, dan menembakkan peluru ketika animasi selesai (menggunakan fungsi panggilan balik atau sesuatu, tergantung pada platform Anda). Saya tidak dapat memikirkan metode lain untuk melakukan ini yang tidak terlalu rumit.

Alternatif Desain Game jawaban: Kecuali ada yang benar- benar bagus untuk melakukannya, saya akan menghindari penundaan menekan tombol 'tembak' dan membiarkan peluru muncul. Kecuali jika animasinya benar-benar pendek (satu atau dua frame, maks, pada dasarnya moncong flash), itu akan membuat respons tombol api terasa lambat, dan itu hanya akan mengganggu pemain biasa. Bahkan jika Anda memutuskan untuk menggunakan animasi sebelum peluru keluar (giliran berbasis RPG dan permainan taktis akan menjadi alasan yang dapat diterima untuk melakukan ini), saya akan berpikir tentang menyertakan opsi "matikan animasi" di suatu tempat, untuk memungkinkan permainan untuk bergerak lebih cepat jika pemain menginginkannya.

thedaian
sumber
Ya jangan membuat api bereaksi perlahan. Ini seperti masalah umum dengan melompat; animator membuat windup besar, tetapi pemain berharap untuk mengudara segera setelah mereka menekan tombol
jhocking
2

Seperti kata MrCranky; pisahkan animasi dan logika.

Tetapi yang paling penting, logika harus tetap menjadi bagian utama .

  • Ketika tombol api ditekan, Anda harus memicu " aksi " gambar dalam status karakter Anda (logika).
  • Tindakan ini harus memicu animasi gambar dengan semua parameter (waktu untuk hidup dll).
  • Setelah aksi menggambar selesai, Anda dapat memicu aksi api (bisa menembak sekali atau lebih tergantung pada senjatanya)
  • Tindakan ini dapat menghasilkan peluru dan memicu animasi api .

Ingatlah bahwa mengendalikan UI dari logika adalah satu-satunya cara untuk memastikan Anda dapat menyimpan, menggunakan kembali, dan membagikan logika Anda nanti (renderer baru, game baru, versi server tanpa renderer ...)

Anjing hutan
sumber
1

Pertama, saya akan menggunakan sistem acara (pola pengamat?) Untuk memisahkan potongan-potongan kode. Ini bukan hanya untuk animasi, tetapi tentu saja berlaku di sana. Kemudian kode animasi dapat dengan mudah mengatakan dispatchEvent (event) dan beberapa bagian lain dari kode mendengarkan acara tersebut, tanpa ada bagian dari kode yang perlu saling mengetahui.

Sekarang kode animasi harus benar-benar memiliki referensi ke dispatcher acara (mudah dilakukan dengan injeksi ketergantungan) dan Anda perlu memiliki beberapa XML atau JSON yang benar-benar mendefinisikan animasi Anda. Sesuatu seperti:

{
  animation: {
    name: shoot,
    length: 12,
    spritesheet: shoot.png
    event: {
      frame: 4,
      name: bulletLeavesGun,
    },
  },
}

Baca dalam data saat memuat animasi, dan minta kode animasi mengirim acara ketika berada di bingkai itu selama pemutaran.

jhocking
sumber