عجلة سلاح في Doom 1993

تحية طيبة.



كثير منا لديه ولع لألعاب الفيديو القديمة التي ظهرت في مطلع القرن. لديهم جو ممتاز ، وديناميكيات محمومة والعديد من الحلول الأصلية التي لم تعد قديمة بعد عقود. ومع ذلك ، في الوقت الحاضر ، تغيرت رؤية واجهة اللعبة إلى حد ما - فقد حلت الممرات الخطية محل مستويات مربكة ، واستبدل التجديد مجموعات الإسعافات الأولية ، وبدلاً من صف طويل من المفاتيح 0-9 لتحديد ترسانة ، جاءت أولاً عجلة الماوس ، ثم العجلة الافتراضية. نتحدث عنه اليوم.



صورة



ملخص تاريخي



في السابق ، أثناء ظهور نوع مطلق النار على هذا النحو ، لم يتم طرح مسألة التحكم في الماوس - تم استخدام لوحة المفاتيح فقط للسيطرة على بطل الرواية. علاوة على ذلك ، لم يكن هناك تنسيق إدارة واحد أيضًا - أصبح WASD هو المعيار بعد ذلك بقليل. يمكنك قراءة المزيد حول تخطيطات لوحة مفاتيح الألعاب القديمة هنا .



وفقًا لذلك ، في تلك الألعاب التي تم فيها تنفيذ القدرة على اختيار المعدات (Doom و Wolfenstein و Quake وغيرها) ، تم تنفيذها بالطريقة البديهية الوحيدة في ذلك الوقت - باستخدام مفاتيح الأرقام على لوحة المفاتيح. ولسنوات عديدة كانت هذه الطريقة هي الوحيدة.

بعد ذلك ، في أواخر التسعينيات ، أصبح من الممكن تغيير الأسلحة باستخدام عجلة الماوس.



لم نتمكن من العثور على معلومات لا لبس فيها حول هذا الموضوع ، ولكن في CS 1.6 تم تمكين هذه الميزة من خلال وحدة التحكم. ومع ذلك ، قد تكون هذه السوابق موجودة من قبل - في هذه الحالة ، يرجى الإشارة إلى ذلك في التعليقات أو في PM. ولكن في الشكل المألوف في عصرنا ، لم يتم استخدام عجلة الأسلحة إلا مع Crysis وقائمة البدلة الخاصة بها. على الرغم من وجود محاولات للقيام بشيء مماثل منذ HL2 ، فإن "العجلة" ذهبت إلى الجماهير فقط في أواخر القرن العشرين ، والآن هي السائدة ...



ومع ذلك ، هذا مجرد ملخص تاريخي ، لا يهم سوى قصة. في إطار هذه المقالة لن تكون هناك مناقشات مطولة حول أسباب شعبية حل معين. بالإضافة إلى النكهة حول المحدد الأفضل. ببساطة لأن ما يلي سيصف عملية تكييف Doom القديم الجيد لاختيار الأسلحة باستخدام الماوس.



يضع اهداف



من أجل تنفيذ WW ، تحتاج إلى اعتراض حركة الماوس بطريقة أو بأخرى ، وتتبع حركته أثناء الضغط باستمرار على مفتاح المحدد ، وعند تحريره ، قم بمحاكاة نقرة على الزر المقابل للقطاع المحدد.



لهذا ، استخدمت لغة جافا ، على وجه الخصوص ، يتم تنفيذ اعتراض المفتاح باستخدام مكتبة jnativehook ، والضغط يرجع إلى awt.Robot. معالجة الخطافات المستلمة ليست صعبة ، لذلك تتم يدويًا.



التنفيذ



في السابق ، تم تطوير الفصول التي تحدد أزواج الإحداثيات لتحديد متجه الإزاحة.



على وجه الخصوص ، تسمح لك فئة Shift بتخزين متجه ثنائي الأبعاد ، وكذلك تحديد طوله ، وتسمح لك فئة NormalizedShift ، المصممة لتخزين متجه طبيعي ، من بين أشياء أخرى ، بتحديد الزاوية بين المتجه المعترض والمتجه (1،0).



رأس المفسد
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);
    };
};




فهي ليست ذات أهمية خاصة ، والخطوط 73-74 فقط ، وتطبيع المتجه ، تتطلب تعليقًا. من بين أمور أخرى ، يتم قلب المتجه. يتغير إطار المرجع - الحقيقة هي أنه من وجهة نظر البرمجيات ومن وجهة نظر الرياضيات المألوفة ، يتم توجيه المتجهات بشكل مختلف بشكل تقليدي . هذا هو السبب في أن نواقل فئة Shift لها أصلها في أعلى اليسار ، وفئة NormalizedShift - في أسفل اليسار.



لتنفيذ عمل البرنامج ، تم تنفيذ فئة Wheel ، التي تنفذ واجهات NativeMouseMotionListener و NativeKeyListener. الرمز تحت المفسد.



رأس المفسد
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;
        }
    }




دعونا نكتشف ما يحدث هنا.



يخزن المتغير KEYCODE رمز المفتاح المستخدم لاستدعاء المحدد. عادة ما يكون هذا TAB ، ولكن إذا لزم الأمر ، يمكن تغييره في التعليمات البرمجية أو - من الناحية المثالية - سحبه من ملف التكوين.



يقوم السابق بتخزين موضع مؤشر الماوس عند استدعاء المحدد. يتم الاحتفاظ بالموضع الحالي للمؤشر في التيار. وفقًا لذلك ، عندما يتم تحرير مفتاح الاختيار ، يتم طرح المتجهات ويتم كتابة تحول المؤشر إلى متغير التحول خلال الوقت الذي يتم فيه الضغط باستمرار على مفتاح الاختيار.



ثم ، في السطر 140 ، يتم تطبيع المتجه ، أي يتم اختزاله عندما يكون طوله قريبًا من واحد. بعد ذلك ، يتم نقل المتجه المعياري إلى المطابق ، مما يثبت التوافق بين رمز المفتاح المراد الضغط عليه وزاوية دوران الناقل. لأسباب تتعلق بالقراءة ، يتم تحويل الزاوية إلى درجات ، وكذلك - يتم توجيهها على طول دائرة الوحدة الكاملة (يعمل acos فقط بزوايا تصل إلى 180 درجة).



تحدد فئة ButtonMatcher المراسلات بين الزاوية ورمز المفتاح المحدد.



رأس المفسد
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);
    }
}




بالإضافة إلى ذلك ، يحدد الرقم المتغيرOfButtons عدد القطاعات والأزرار المقابلة لها ، ويحدد baseShift زاوية الدوران (على وجه الخصوص ، يوفر تناظرًا حول المحور الرأسي ويدير العجلة 90 درجة بحيث يكون سلاح المشاجرة في الأعلى) ، وتخزن الرموز مجموعة الرموز المفاتيح - في حالة تغيير الأزرار ، ولن تكون الرموز متتالية. في إصدار أكثر دقة ، سيكون من الممكن سحبها لأعلى من ملف التكوين ، ولكن مع التصميم القياسي للمفاتيح ، فإن الإصدار الحالي قابل للتطبيق تمامًا.



خاتمة



في إطار هذه المقالة ، تم وصف إمكانية تخصيص واجهة الرماة الكلاسيكية للمعايير الحديثة. بالطبع ، نحن لا نضيف أيًا من مجموعات الإسعافات الأولية أو الخطية هنا - هناك العديد من التعديلات لهذا ، ولكن في كثير من الأحيان يكمن في واجهة سهلة ومريحة. يدرك المؤلف أنه ربما لم يصف الطريقة المثلى لتحقيق النتيجة المرجوة ، ويتوقع أيضًا صورة مع رغيف وحافلة ترولي في التعليقات ، ولكن مع ذلك كانت تجربة مثيرة للاهتمام ، ربما ، ستشجع بعض اللاعبين على اكتشاف عالم جافا الرائع.



النقد البناء مرحب به.



رموز المصدر



All Articles