Roda senjata di Doom 1993

Salam pembuka.



Banyak dari kita dengan hangat berhubungan dengan video game jadul yang dirilis pada pergantian abad ini. Mereka memiliki atmosfer yang luar biasa, dinamika panik dan banyak solusi orisinal yang tidak menjadi usang setelah beberapa dekade. Namun, saat ini, visi antarmuka permainan telah sedikit berubah - koridor linier telah menggantikan level yang membingungkan, regenerasi telah menggantikan kit pertolongan pertama, dan alih-alih deretan panjang tombol 0-9 untuk memilih arsenal, pertama roda mouse, dan kemudian roda virtual, datang. Tentang dia hari ini yang akan dibahas.



gambar



Ringkasan sejarah



Sebelumnya, selama munculnya genre penembak seperti itu, pertanyaan tentang kontrol mouse tidak dimunculkan - hanya keyboard yang digunakan untuk mengontrol protagonis. Selain itu, tidak ada format manajemen tunggal - WASD menjadi standar beberapa saat kemudian. Anda dapat membaca lebih lanjut tentang tata letak keyboard game lama di sini .



Karenanya, dalam gim-gim tersebut di mana kemampuan untuk memilih peralatan diimplementasikan (Doom, Wolfenstein, Quake dll), itu diterapkan dengan satu-satunya cara intuitif pada waktu itu - menggunakan tombol angka pada keyboard. Dan selama bertahun-tahun metode ini adalah satu-satunya.

Kemudian, di akhir tahun 90-an, menjadi mungkin untuk mengubah senjata dengan roda mouse.



Kami tidak dapat menemukan informasi yang jelas tentang topik ini, tetapi di CS 1.6 fitur ini diaktifkan melalui konsol. Namun, preseden semacam itu mungkin sudah ada sebelumnya - dalam kasus ini, harap tunjukkan ini di komentar atau di PM. Namun dalam bentuk yang akrab di zaman kita, Weapon Wheel mulai digunakan hanya dengan Crysis dan menu Suit-nya. Meskipun ada upaya untuk melakukan sesuatu yang serupa sejak HL2, "roda" pergi ke massa hanya pada akhir 00-an, dan sekarang menjadi arus utama ...



Namun, ini hanya ringkasan sejarah, yang hanya menarik sebagai cerita. Dalam kerangka artikel ini tidak akan ada diskusi panjang tentang alasan popularitas solusi tertentu. serta rasa tentang pemilih mana yang lebih baik. Hanya karena proses mengadaptasi Doom lama yang baik dengan pilihan alat dengan mouse akan dijelaskan di bawah ini.



Menentukan tujuan



Untuk menerapkan WW, Anda perlu mencegat gerakan mouse, melacak pergerakannya saat tombol pemilih ditekan, dan, ketika dirilis, meniru klik pada tombol yang sesuai dengan sektor yang dipilih.



Untuk ini, saya menggunakan bahasa Jawa, khususnya, intersepsi kunci dilakukan menggunakan pustaka jnativehook, dan menekan dilakukan menggunakan awt.Robot. Pemrosesan kait yang diterima tidak sulit, oleh karena itu, dilakukan secara manual.



Penerapan



Sebelumnya, kelas dikembangkan yang menentukan pasangan koordinat untuk menentukan vektor perpindahan.



Secara khusus, kelas Shift memungkinkan Anda untuk menyimpan vektor dua dimensi, serta menentukan panjangnya, dan kelas NormalizedShift, yang dirancang untuk menyimpan vektor yang dinormalisasi, di antaranya, memungkinkan Anda untuk menentukan sudut antara vektor yang dicegat dan vektor (1,0).



Judul spoiler
class Shift{
    int xShift;
    int yShift;

    public int getxShift() {
        return xShift;
    }

    public int getyShift() {
        return yShift;
    }

    public void setxShift(int xShift) {
        this.xShift = xShift;
    }

    public void setyShift(int yShift) {
        this.yShift = yShift;
    }
    double getLenght(){
        return Math.sqrt(xShift*xShift+yShift*yShift);
    }

}
class NormalisedShift{
  double normalizedXShift;
  double normalizedYShift;
  double angle;
  NormalisedShift (Shift shift){
      if (shift.getLenght()>0)
      {
          normalizedXShift = -shift.getxShift()/shift.getLenght();
        normalizedYShift = -shift.getyShift()/shift.getLenght();
      }
      else
      {
          normalizedXShift = 0;
          normalizedYShift = 0;
      }
  }
  void calcAngle(){
      angle = Math.acos(normalizedXShift);
  }

  double getAngle(){
      calcAngle();
      return (normalizedYShift<0?angle*360/2/Math.PI:360-angle*360/2/Math.PI);
    };
};




Mereka tidak menarik, dan hanya garis 73-74, menormalkan vektor, memerlukan komentar. Antara lain, vektor dibalik. kerangka referensi berubah - faktanya adalah dari sudut pandang perangkat lunak dan dari sudut pandang matematika yang sudah dikenal, vektor secara tradisional diarahkan secara berbeda. Itulah sebabnya vektor dari kelas Shift memiliki asal di kiri atas, dan kelas NormalizedShift memiliki kiri bawah.



Untuk mengimplementasikan pekerjaan program, kelas Wheel diimplementasikan, yang mengimplementasikan antarmuka NativeMouseMotionListener dan NativeKeyListener. Kode berada di bawah spoiler.



Judul spoiler
public class Wheel  implements NativeMouseMotionListener, NativeKeyListener {

    final int KEYCODE = 15;
    Shift prev = new Shift();
    Shift current = new Shift();
    ButtomMatcher mathcer = new ButtomMatcher();


    boolean wasPressed = false;

    @Override
    public void nativeMouseMoved(NativeMouseEvent nativeMouseEvent) {
        current.setxShift(nativeMouseEvent.getX());
        current.setyShift(nativeMouseEvent.getY());

    }
    @Override
    public void nativeMouseDragged(NativeMouseEvent nativeMouseEvent) {

    }
    @Override
    public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {

    }

    @Override
    public void nativeKeyPressed(NativeKeyEvent nativeKeyEvent) {
        if (nativeKeyEvent.getKeyCode()==KEYCODE){
            if (!wasPressed)
            {
                prev.setxShift(current.getxShift());
                prev.setyShift(current.getyShift());
            }
            wasPressed = true;

        }
    }

    @Override
    public void nativeKeyReleased(NativeKeyEvent nativeKeyEvent) {
        if (nativeKeyEvent.getKeyCode() == KEYCODE){
            Shift shift = new Shift();
            shift.setxShift(prev.getxShift() - current.getxShift());
            shift.setyShift(prev.getyShift() - current.getyShift());
            NormalisedShift normalisedShift = new NormalisedShift(shift);
            mathcer.pressKey(mathcer.getCodeByAngle(normalisedShift.getAngle()));
            wasPressed = false;
        }
    }




Mari kita lihat apa yang terjadi di sini.



Variabel KEYCODE menyimpan kode kunci yang digunakan untuk memanggil pemilih. Biasanya ini TAB, tetapi jika perlu, dapat diubah dalam kode atau, idealnya, ditarik dari file konfigurasi.



prev menyimpan posisi kursor mouse ketika pemilih dipanggil. Surrent mempertahankan posisi kursor saat ini pada waktu tertentu. Dengan demikian, ketika kunci pemilih dilepaskan, vektor dikurangi dan pergeseran kursor ditulis ke variabel shift selama waktu tombol pemilih ditekan.



Kemudian, pada baris 140, vektor dinormalisasi, mis. dikurangi menjadi bentuk ketika panjangnya mendekati satu. Setelah itu, vektor yang dinormalisasi ditransmisikan ke korek api, yang menetapkan korespondensi antara kode kunci yang akan ditekan dan sudut rotasi vektor. Untuk alasan keterbacaan, sudut dikonversikan ke derajat, dan juga - ia berorientasi sepanjang lingkaran satuan lengkap (acos hanya bekerja dengan sudut hingga 180 derajat).



Kelas ButtonMatcher mendefinisikan korespondensi antara sudut dan kode kunci yang dipilih.



Judul spoiler
class ButtomMatcher{

    Robot robot;
    final int numberOfButtons = 6;
    int buttonSection = 360/numberOfButtons;
    int baseShift = 90-buttonSection/2;
    ArrayList<Integer> codes = new ArrayList<>();
    void matchButtons(){
        for (int i =49; i<55; i++)
            codes.add(i);

    }
    int getCodeByAngle(double angle){
        angle= (angle+360-baseShift)%360;
        int section = (int) angle/buttonSection;
        System.out.println(codes.get(section));
        return codes.get(section);
    }
    ButtomMatcher() {
        matchButtons();
        try
        {
            robot = new Robot();
        }
        catch (AWTException e) {
            e.printStackTrace();
        }
    }
    void pressKey(int keyPress)
    {

        robot.keyPress(keyPress);
        robot.keyRelease(keyPress);
    }
}




Selain itu, variabel numberOfButtons menentukan jumlah sektor dan tombol yang sesuai, baseShift menetapkan sudut rotasi (khususnya, memberikan simetri tentang sumbu vertikal dan memutar roda 90 derajat sehingga senjata jarak dekat berada di atas), dan kode array menyimpan kode tombol - jika tombol berubah, dan kode tidak akan berurutan. Dalam versi yang lebih maju, dimungkinkan untuk menarik mereka dari file konfigurasi, tetapi dengan tata letak keyboard standar - versi saat ini cukup layak.



Kesimpulan



Dalam kerangka artikel ini, kemungkinan menyesuaikan antarmuka penembak klasik untuk standar modern dijelaskan. Tentu saja, kami tidak menambahkan kit P3K atau linieritas apa pun di sini - ada banyak mod untuk ini, tetapi seringkali dengan detail sedemikian rupa sehingga antarmuka yang ramah dan nyaman terletak. Penulis menyadari bahwa ia mungkin tidak menggambarkan cara yang paling optimal untuk mencapai hasil yang diinginkan, dan juga menunggu di komentar untuk gambar dengan roti dan troli, tetapi bagaimanapun, itu adalah pengalaman yang menarik, mungkin, akan mendorong beberapa gamer untuk menemukan dunia Jawa yang menakjubkan.



Kritik konstruktif sangat dianjurkan.



Kode sumber



All Articles