
التحكم باللاعب في LibGDX عن طريق اللمس و لوحة المفاتيح
تُعد المدخلات (Inputs) العصب الرئيسي لأي لعبة؛ فبدونها، لا يمكن للاعب
التفاعل مع عالم اللعبة. سواء كنت تقوم بتطوير لعبة لمنصة محمولة تعتمد على
اللمس (Touch)، أو لعبة كمبيوتر تستخدم لوحة المفاتيح (Keyboard)،
فإن فهم كيفية التعامل مع هذه المدخلات بكفاءة في LibGDX أمر بالغ الأهمية.
توفر LibGDX نظامًا مرنًا وموحدًا لإدارة جميع أنواع المدخلات عبر
المنصات المختلفة، مما يسهل عليك كتابة كود واحد يعمل بسلاسة على أجهزة الأندرويد،
iOS، سطح المكتب، وحتى المتصفحات. يهدف هذا المقال إلى استكشاف
كيفية استخدام LibGDX لالتقاط ومعالجة مدخلات اللمس ولوحة المفاتيح،
مما يمنحك الأدوات اللازمة لجعل ألعابك تفاعلية وجذابة.
فهم نظام التحكم باللاعب في LibGDX: Gdx.input
في LibGDX، يتم الوصول إلى جميع المدخلات عبر الكائن الثابت
Gdx.input، والذي يوفر واجهة موحدة لـ اللمس (Touch)، لوحة
المفاتيح (Keyboard)، الماوس، ومستشعرات التسارع. يعتمد التعامل
الفعال مع المدخلات على فهم دورات الحياة (Lifecycle) للأحداث والتمييز بين
الاستقصاء اللحظي (Polling) للأزرار المضغوطة والاستماع للأحداث
(Event Listening) عبر InputProcessor للتعامل مع النقر، السحب،
والضغطات المتتالية على لوحة المفاتيح.
طرق التعامل مع التحكم باللاعب في LibGDX
توفر LibGDX طريقتين رئيسيتين للتعامل مع المدخلات :
1. الاستقصاء اللحظي (Polling)
هذه الطريقة مناسبة للتحقق من حالة زر أو مفتاح معين في لحظة محددة.
تستخدم هذه الطريقة داخل دالة render() التي يتم استدعاؤها في كل إطار (frame).
* مثال على استقصاء لوحة المفاتيح :
للتحقق مما إذا كان مفتاح معين مضغوطًا باستمرار (مثل مفتاح الحركة) :
Java
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
// داخل دالة render()
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
// حرك اللاعب إلى اليسار
player.x -= speed * Gdx.graphics.getDeltaTime();
}
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
// حرك اللاعب إلى اليمين
player.x += speed * Gdx.graphics.getDeltaTime();
}
--
* مثال على استقصاء اللمس/الماوس :
للتحقق مما إذا كانت الشاشة/الماوس مضغوطة وأخذ الإحداثيات:
Java
// داخل دالة render()
if (Gdx.input.isTouched()) {
float touchX = Gdx.input.getX();
float touchY = Gdx.input.getY();
// قم بمعالجة اللمس في (touchX, touchY)
System.out.println("Touch at: " + touchX + ", " + touchY);
}
--
* المميزات :
- بسيطة ومباشرة : سهلة الفهم والتطبيق للمدخلات المستمرة.
- مثالية للحركة المستمرة : مثل تحريك شخصية اللاعب.
* العيوب :
- غير فعالة للأحداث لمرة واحدة: إذا أردت معرفة متى تم "الضغط" على
زر لمرة واحدة، فقد تلتقط عدة ضغطات إذا بقي اللاعب ضاغطاً على الزر لأكثر من إطار واحد.
- صعبة للمدخلات المعقدة : مثل السحب، أو النقر المزدوج، أو التسلسلات.
2. الاستماع للأحداث (Event Listening) باستخدام InputProcessor
هذه الطريقة أكثر قوة ومرونة، وهي المفضلة للتعامل مع الأحداث التي
تحدث لمرة واحدة (مثل النقر، الضغط على زر) أو المدخلات المعقدة
(مثل السحب، الإفلات). تقوم بتعيين كائن InputProcessor يلتقط أحداث المدخلات فور حدوثها.
* خطوات استخدام InputProcessor :
إنشاء كلاس (Class) يطبق واجهة InputProcessor :
هذا الكلاس سيتضمن دوال لكل حدث مدخلات
(مثل keyDown، touchDown، touchDragged).
* تعيين الكائن كمُعالج للمدخلات :
باستخدام Gdx.input.setInputProcessor(yourInputProcessorInstance).
* مثال على InputProcessor للوحة المفاتيح واللمس :
Java
import com.badlogic.gdx.Gdx;import com.badlogic.gdx.Input;import com.badlogic.gdx.InputProcessor;import com.badlogic.gdx.Screen; // أو ApplicationAdapter
public class MyGameScreen implements Screen, InputProcessor {
// ... (كود اللعبة الأخرى)
@Override public void show() { Gdx.input.setInputProcessor(this); // تعيين هذا الكلاس كمعالج للمدخلات }
// --- دوال InputProcessor للوحة المفاتيح --- @Override public boolean keyDown(int keycode) { if (keycode == Input.Keys.SPACE) { System.out.println("Space bar pressed!"); // قم بتنفيذ حدث القفز أو إطلاق النار لمرة واحدة return true; // يشير إلى أن الحدث قد تم التعامل معه } return false; // يشير إلى أن الحدث لم يتم التعامل معه (للسماح لمعالجات أخرى بالتعامل معه) }
@Override public boolean keyUp(int keycode) { // يتم استدعاؤها عند رفع المفتاح return false; }
@Override public boolean keyTyped(char character) { // يتم استدعاؤها عند كتابة حرف (مثالي لإدخال النصوص) return false; }
// --- دوال InputProcessor للمس/الماوس --- @Override public boolean touchDown(int screenX, int screenY, int pointer, int button) { // يتم استدعاؤها عند لمس الشاشة/النقر بالماوس (pointer لتعريف اللمسات المتعددة) System.out.println("Screen touched at: " + screenX + ", " + screenY); // ابدأ بتسجيل السحب أو تنفيذ إجراء لمرة واحدة (مثل اختيار وحدة) return true; }
@Override public boolean touchUp(int screenX, int screenY, int pointer, int button) { // يتم استدعاؤها عند رفع الإصبع/الماوس return false; }
@Override public boolean touchDragged(int screenX, int screenY, int pointer) { // يتم استدعاؤها عند سحب الإصبع/الماوس System.out.println("Screen dragged to: " + screenX + ", " + screenY); // استخدم هذا لتحريك الكاميرا أو سحب الكائنات return true; }
@Override public boolean mouseMoved(int screenX, int screenY) { // يتم استدعاؤها عند تحريك الماوس بدون ضغط (لأجهزة سطح المكتب) return false; }
@Override public boolean scrolled(float amountX, float amountY) { // يتم استدعاؤها عند استخدام عجلة الماوس return false; }
// ... (باقي دوال Screen مثل render(), hide(), dispose() )}
--
* المميزات :
- دقيقة للأحداث لمرة واحدة : تلتقط ضغطة الزر الواحدة أو اللمسة الواحدة.
- دعم المدخلات المعقدة : تسهل التعامل مع السحب (drag)،
الإفلات (drop)، والنقر المزدوج (double tap).
- أفضل للمنطق القائم على الأحداث : حيث تحتاج اللعبة للتفاعل مع
حدث معين بدلاً من التحقق المستمر.
- دعم المدخلات المتعددة (Multi-touch) : pointer في دوال touch
يسمح بالتعامل مع عدة لمسات في نفس الوقت.
* نصائح و مفاهيم متقدمة LibGDX
- Multiple Input Processors (MultiPlexer) :
يمكنك تجميع عدة InputProcessors باستخدام InputMultiplexer.
هذا مفيد إذا كان لديك مكونات UI (مثل الأزرار أو القوائم) لها معالج
مدخلات خاص بها، وتريد أيضًا أن تعالج اللعبة نفسها المدخلات.
Java
InputMultiplexer multiplexer = new InputMultiplexer();
multiplexer.addProcessor(stage); // للتعامل مع UI
multiplexer.addProcessor(this); // للتعامل مع مدخلات اللعبة الخاصة بك
Gdx.input.setInputProcessor(multiplexer);
تحويل الإحداثيات (Coordinate Transformation):
--
عادةً ما تُعطى إحداثيات اللمس/الماوس (screenX, screenY) بالبكسل
من الزاوية العلوية اليسرى للشاشة.
إذا كنت تستخدم كاميرا (Camera) أو "viewport" في لعبتك، فستحتاج
إلى تحويل هذه الإحداثيات إلى إحداثيات عالم اللعبة (world coordinates)
باستخدام camera.unproject() لجعلها ذات معنى بالنسبة لأصول لعبتك.
* التعامل مع المنصات المختلفة :
أحد جمال LibGDX هو أن الكود أعلاه سيعمل على جميع المنصات.
لا داعي للقلق بشأن الاختلافات بين لمس الشاشة على الأندرويد أو نقر
الماوس على سطح المكتب؛ LibGDX توحد هذه الواجهة لك.
* الخلاصة :
إن إتقان التعامل مع المدخلات في LibGDX، سواء كان ذلك من
خلال الاستقصاء اللحظي (Polling) للحركة المستمرة أو الاستماع للأحداث
(Event Listening) للمدخلات التفاعلية، هو حجر الزاوية
في بناء ألعاب جذابة. من خلال استخدام Gdx.input وInputProcessor،
يمكنك إنشاء أنظمة تحكم بديهية وسريعة الاستجابة، مما يضمن أن يتمتع
اللاعبون بتجربة لعب سلسة وغامرة عبر جميع المنصات.
استثمر الوقت في فهم هذه المفاهيم، وستتمكن من فتح الباب أمام تفاعلات لا حصر لها في عوالم ألعابك.