การป้อนข้อมูลด้วยเมาส์

หัวข้อนี้จะครอบคลุมวิธีใช้การป้อนข้อมูลด้วยเมาส์สำหรับ Google Play Games บน PC เกมที่โหมดแปลภาษาป้อนข้อมูลไม่ได้มอบประสบการณ์การใช้งานที่ยอดเยี่ยมให้กับผู้เล่น

โปรแกรมเล่น PC มักมีแป้นพิมพ์และเมาส์ แทนที่จะเป็นหน้าจอสัมผัส สิ่งสำคัญคือต้องพิจารณาว่าเกมของคุณรองรับการป้อนข้อมูลด้วยเมาส์หรือไม่ โดยค่าเริ่มต้น Google Play Games บน PC จะแปลงเหตุการณ์เมาส์เมื่อคลิกซ้ายเป็นเหตุการณ์เดียว กิจกรรมการแตะเสมือนจริง วิธีนี้เรียกว่า "โหมดแปลภาษา"

แม้ว่าโหมดนี้จะทำให้เกมของคุณทำงานได้โดยมีการเปลี่ยนแปลงเพียงเล็กน้อย แต่ก็ไม่ได้ ทำให้ผู้เล่น PC ได้รับประสบการณ์ดั้งเดิมที่เรียบง่าย เราจึงขอแนะนำ ที่คุณใช้สิ่งต่อไปนี้

  • สถานะวางเมาส์เหนือสำหรับเมนูตามบริบทแทนการกดค้างไว้
  • คลิกขวาเพื่อดูการดำเนินการอื่นๆ ที่เกิดขึ้นเมื่อกดค้างหรือในบริบท เมนู
  • เมาส์มองหาเกมแอ็กชันของบุคคลที่หนึ่งหรือบุคคลที่สามแทนที่จะเน้นสื่อและ เหตุการณ์การลาก

คุณต้องปิดใช้อินพุตเพื่อให้สามารถรองรับรูปแบบ UI ทั่วไปบน PC ได้ โหมดการแปล

การจัดการการป้อนข้อมูลสำหรับ Google Play Games บน PC จะเหมือนกับของ ChromeOS การเปลี่ยนแปลงที่รองรับ PC ด้วย เพื่อปรับปรุงเกมของคุณ สำหรับผู้เล่น Android ทุกคน

ปิดใช้งานโหมดการแปลอินพุต

ในไฟล์ AndroidManifest.xml ประกาศ android.hardware.type.pc ฟีเจอร์ ซึ่งเป็นการระบุว่าเกมของคุณใช้ฮาร์ดแวร์ของ PC และปิดใช้การแปลอินพุต นอกจากนี้ การเพิ่ม required="false" ก็ช่วยให้มั่นใจได้ว่าเกมของคุณ จะยังคงถูกติดตั้งบนโทรศัพท์และแท็บเล็ตโดยไม่ต้องใช้เมาส์ เช่น

<manifest ...>
  <uses-feature
      android:name="android.hardware.type.pc"
      android:required="false" />
  ...
</manifest>

Google Play Games บน PC เวอร์ชันที่ใช้งานจริงจะเปลี่ยนเป็นเวอร์ชันที่ถูกต้อง เมื่อเปิดเกม เมื่อเรียกใช้ในโปรแกรมจำลองสำหรับนักพัฒนาซอฟต์แวร์ คุณต้องทำดังนี้ คลิกขวาที่ไอคอนแถบงาน แล้วเลือกตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์ จากนั้นเลือก โหมด PC(KiwiMouse) เพื่อรับอินพุตเมาส์ดิบ

ภาพหน้าจอของ &quot;โหมด PC(KiwiMouse)&quot; เลือกไว้ในเมนูตามบริบท

หลังจากดําเนินการแล้ว ระบบจะรายงานการเคลื่อนไหวของเมาส์ตาม View.ongenericMotionEvent พร้อมแหล่งที่มา SOURCE_MOUSE แสดงว่าเป็นเหตุการณ์ของเมาส์

Kotlin

gameView.setOnGenericMotionListener { _, motionEvent ->
    var handled = false
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        // handle the mouse event here
        handled = true
    }
    handled
}

Java

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        // handle the mouse event here
        return true;
    }
    return false;
});

สำหรับรายละเอียดเกี่ยวกับการจัดการอินพุตด้วยเมาส์ โปรดดู เอกสารประกอบของ ChromeOS

การจัดการการเคลื่อนที่ของเมาส์

หากต้องการตรวจจับการเคลื่อนที่ของเมาส์ ให้ฟัง ACTION_HOVER_ENTER, ACTION_HOVER_EXIT และ ACTION_HOVER_MOVE กิจกรรม

วิธีนี้ทำงานได้ดีที่สุดสำหรับการตรวจหาผู้ใช้วางเมาส์เหนือปุ่มหรือวัตถุใน ให้โอกาสคุณแสดงกล่องคำแนะนำหรือใช้สถานะเมาส์โอเวอร์ เพื่อไฮไลต์สิ่งที่ผู้เล่นกำลังจะเลือก เช่น

Kotlin

gameView.setOnGenericMotionListener { _, motionEvent ->
   var handled = false
   if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
       when(motionEvent.action) {
           MotionEvent.ACTION_HOVER_ENTER -> Log.d("MA", "Mouse entered at ${motionEvent.x}, ${motionEvent.y}")
           MotionEvent.ACTION_HOVER_EXIT -> Log.d("MA", "Mouse exited at ${motionEvent.x}, ${motionEvent.y}")
           MotionEvent.ACTION_HOVER_MOVE -> Log.d("MA", "Mouse hovered at ${motionEvent.x}, ${motionEvent.y}")
       }
       handled = true
   }

   handled
}

Java

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_HOVER_ENTER:
                Log.d("MA", "Mouse entered at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
            case MotionEvent.ACTION_HOVER_EXIT:
                Log.d("MA", "Mouse exited at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
            case MotionEvent.ACTION_HOVER_MOVE:
                Log.d("MA", "Mouse hovered at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
        }
        return true;
    }
    return false;
});

การจัดการปุ่มเมาส์

พีซีจะมีทั้งปุ่มซ้ายและขวาของเมาส์ ทำให้เกิดองค์ประกอบที่โต้ตอบได้ ทั้งการดำเนินการหลักและรอง ในเกม ให้แตะการดำเนินการต่างๆ เช่น การแตะ จะทำงานได้ดีที่สุดเมื่อมีการคลิกซ้ายเมื่อแตะ และ รู้สึกถึงการดำเนินการมากที่สุด เป็นธรรมชาติด้วยการคลิกขวา ในเกมกลยุทธ์แบบเรียลไทม์ที่คุณอาจใช้ คลิกขวาเพื่อเลือก และคลิกขวาเพื่อย้าย เกมยิงมุมมองบุคคลที่หนึ่งอาจมอบหมาย กำหนดไฟเป็นไฟหลักและคลิกซ้ายไปขวาและคลิกขวา เกมวิ่งไม่สิ้นสุดอาจ ให้ใช้การคลิกซ้ายเพื่อข้ามและคลิกขวาเพื่อขีดกลาง เรายังไม่ได้เพิ่มการสนับสนุนสำหรับ เหตุการณ์คลิกกลาง

หากต้องการจัดการการกดปุ่ม ให้ใช้ ACTION_DOWN และ ACTION_UP จากนั้นใช้ getActionButton เพื่อดูว่าปุ่มใดเรียกใช้การดำเนินการ หรือ getButtonState เพื่อดูสถานะของปุ่มทั้งหมด

ในตัวอย่างนี้ enum จะใช้เพื่อช่วยแสดงผลลัพธ์ของ getActionButton:

Kotlin

enum class MouseButton {
   LEFT,
   RIGHT,
   UNKNOWN;
   companion object {
       fun fromMotionEvent(motionEvent: MotionEvent): MouseButton {
           return when (motionEvent.actionButton) {
               MotionEvent.BUTTON_PRIMARY -> LEFT
               MotionEvent.BUTTON_SECONDARY -> RIGHT
               else -> UNKNOWN
           }
       }
   }
}

Java

enum MouseButton {
    LEFT,
    RIGHT,
    MIDDLE,
    UNKNOWN;
    static MouseButton fromMotionEvent(MotionEvent motionEvent) {
        switch (motionEvent.getActionButton()) {
            case MotionEvent.BUTTON_PRIMARY:
                return MouseButton.LEFT;
            case MotionEvent.BUTTON_SECONDARY:
                return MouseButton.RIGHT;
            default:
                return MouseButton.UNKNOWN;
        }
    }
}

ในตัวอย่างนี้ ระบบจะจัดการการดำเนินการที่คล้ายกับเหตุการณ์เมื่อวางเมาส์

Kotlin

// Handle the generic motion event
gameView.setOnGenericMotionListener { _, motionEvent ->
   var handled = false
   if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
       when (motionEvent.action) {
           MotionEvent.ACTION_BUTTON_PRESS -> Log.d(
               "MA",
               "${MouseButton.fromMotionEvent(motionEvent)} pressed at ${motionEvent.x}, ${motionEvent.y}"
           )
           MotionEvent.ACTION_BUTTON_RELEASE -> Log.d(
               "MA",
               "${MouseButton.fromMotionEvent(motionEvent)} released at ${motionEvent.x}, ${motionEvent.y}"
           )
       }
       handled = true
   }

   handled
}

Java

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_BUTTON_PRESS:
                Log.d("MA", MouseButton.fromMotionEvent(motionEvent) + " pressed at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
            case MotionEvent.ACTION_BUTTON_RELEASE:
                Log.d("MA", MouseButton.fromMotionEvent(motionEvent) + " released at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
        }
        return true;
    }
    return false;
});

จัดการการเลื่อนลูกกลิ้งเมาส์

เราขอแนะนำให้ใช้ล้อเลื่อนของเมาส์แทนการบีบนิ้วเพื่อซูม ท่าทางสัมผัส หรือแตะและลากพื้นที่สำหรับเลื่อนในเกม

หากต้องการอ่านค่าล้อเลื่อน ให้ฟังเหตุการณ์ ACTION_SCROLL เดลต้า เนื่องจากดึงเฟรมล่าสุดได้โดยใช้ getAxisValue กับ AXIS_VSCROLL สำหรับออฟเซ็ตแนวตั้งและ AXIS_HSCROLL สำหรับออฟเซ็ตแนวนอน เช่น

Kotlin

gameView.setOnGenericMotionListener { _, motionEvent ->
   var handled = false
   if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
       when (motionEvent.action) {
           MotionEvent.ACTION_SCROLL -> {
               val scrollX = motionEvent.getAxisValue(MotionEvent.AXIS_HSCROLL)
               val scrollY = motionEvent.getAxisValue(MotionEvent.AXIS_VSCROLL)
               Log.d("MA", "Mouse scrolled $scrollX, $scrollY")
           }
       }
       handled = true
   }
   handled
}

Java

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_SCROLL:
                float scrollX = motionEvent.getAxisValue(MotionEvent.AXIS_HSCROLL);
                float scrollY = motionEvent.getAxisValue(MotionEvent.AXIS_VSCROLL);
                Log.d("MA", "Mouse scrolled " + scrollX + ", " + scrollY);
                break;
        }
        return true;
    }
    return false;
});

บันทึกอินพุตจากเมาส์

บางเกมต้องควบคุมเคอร์เซอร์เมาส์ได้เต็มที่ เช่น ลำดับที่ 1 หรือ 3 เกมแอ็กชันแสดงการเคลื่อนที่ของเมาส์ตามการเคลื่อนที่ของกล้อง วิธีดำเนินการ การควบคุมเมาส์แต่เพียงผู้เดียว เรียกใช้ View.requestPointerCapture()

requestPointerCapture() จะใช้งานได้เมื่อลำดับชั้นการแสดงผลที่มี มีโฟกัส ด้วยเหตุนี้ คุณจึงไม่ได้รับการบันทึกตัวชี้ใน การติดต่อกลับของ onCreate คุณควรรอให้การโต้ตอบของผู้เล่นจับภาพ เช่น เมื่อโต้ตอบกับเมนูหลัก หรือใช้ onWindowFocusChanged Callback เช่น

Kotlin

override fun onWindowFocusChanged(hasFocus: Boolean) {
   super.onWindowFocusChanged(hasFocus)

   if (hasFocus) {
       gameView.requestPointerCapture()
   }
}

Java

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if (hasFocus) {
        View gameView = findViewById(R.id.game_view);
        gameView.requestPointerCapture();
    }
}

เหตุการณ์ที่ requestPointerCapture() บันทึกไว้ จะถูกส่งไปยังมุมมองที่โฟกัสได้ซึ่งลงทะเบียน OnCapturedPointerListener เช่น

Kotlin

gameView.focusable = View.FOCUSABLE
gameView.setOnCapturedPointerListener { _, motionEvent ->
    Log.d("MA", "${motionEvent.x}, ${motionEvent.y}, ${motionEvent.actionButton}")
    true
}

Java

gameView.setFocusable(true);
gameView.setOnCapturedPointerListener((view, motionEvent) -> {
    Log.d("MA", motionEvent.getX() + ", " + motionEvent.getY() + ", " + motionEvent.getActionButton());
    return true;
});

เพื่อนำเสนอการจับเมาส์แบบพิเศษ เช่น เพื่อให้ผู้เล่น โต้ตอบกับเมนูหยุดชั่วคราว เรียกใช้ View.releasePointerCapture()