
كيفية إنشاء لعبة منصات (Platformer) باستخدام LibGDX
لعبة المنصات (Platformer) هي نوع كلاسيكي ومحبوب من الألعاب،
حيث يتحكم اللاعب بشخصية تتنقل عبر مستويات مليئة بالمنصات، العقبات، الأعداء،
والعناصر القابلة للجمع. يتطلب بناء هذا النوع من الألعاب فهمًا عميقًا لحركة اللاعب،
الفيزياء، اكتشاف التصادم، وتصميم المستويات. يوفر LibGDX، بفضل مرونته وقوته،
جميع الأدوات اللازمة لإنشاء تجربة منصات ممتعة وغنية بالميزات.
يهدف هذا المقال إلى إرشادك خلال المفاهيم الأساسية والخطوات البرمجية الرئيسية
لإنشاء لعبتك المنصات الخاصة باستخدام LibGDX.
لماذا LibGDX للعبة منصات ؟
- متعدد المنصات : يمكنك كتابة الكود مرة واحدة وتشغيله على Android، iOS، Desktop، و HTML5.
- تحكم كامل : يوفر وصولاً منخفض المستوى إلى الرسومات والمدخلات، مما يمنحك تحكمًا دقيقًا.
- أداء ممتاز : مبني على OpenGL ES، مما يضمن أداءً سلسًا حتى على الأجهزة ذات الموارد المحدودة.
- مكتبات قوية : يتضمن مكتبات مدمجة ومجتمعية لميزات أساسية مثل الفيزياء
(Box2D)، الرسوم المتحركة (Animation)، وإدارة الخرائط (Tiled Maps).
المفاهيم الأساسية لبناء لعبة منصات في LibGDX
تصميم المستويات باستخدام Tiled Map Editor:
تُعد برامج تصميم الخرائط مثل Tiled Map Editor أداة لا غنى عنها لألعاب المنصات.
تسمح لك ببناء مستوياتك باستخدام "البلاط" (Tiles) الذي يمثل الأرض، المنصات، والخلفيات.
1* طبقات (Layers): يمكنك إنشاء طبقات مختلفة لـ :
- الخلفية (Background): للزينة.
- المنصات/الأرض (Ground/Platforms): للبلاط الذي يتفاعل معه اللاعب فيزيائيًا.
- الأشياء (Objects): لوضع اللاعب، الأعداء، العناصر القابلة للجمع، أو مناطق التصادم المخصصة.
- بيانات التصادم (Collision Data): يمكنك تحديد خصائص للبلاط (مثل "قابل للتصادم")
أو رسم أشكال تصادم خاصة (Object Layers) في Tiled لاستخدامها في محرك الفيزياء.
2* تحميل وعرض خرائط Tiled في LibGDX:
LibGDX يدعم بشكل ممتاز خرائط Tiled عبر فئات مثل TmxMapLoader و
OrthogonalTiledMapRenderer.
- TmxMapLoader: لتحميل ملف .tmx الخاص بالخريطة.
- TiledMap: لتمثيل بيانات الخريطة بعد تحميلها.
- OrthogonalTiledMapRenderer: لرسم الخريطة على الشاشة.
* مثال (conceptual):
Java
TiledMap map;
OrthogonalTiledMapRenderer renderer;
public void create() {
map = new TmxMapLoader().load("levels/my_platform_level.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
}
public void render() {
renderer.setView(camera); // تعيين الكاميرا
renderer.render(); // رسم الخريطة
}
public void dispose() {
map.dispose();
renderer.dispose();
}
--
3* الشخصية الرئيسية (اللاعب) والحركة:
اللاعب هو محور اللعبة.
يجب أن يكون لديه:
- تمثيل مرئي (Sprite/Animation): مجموعة من الصور أو الرسوم المتحركة (Idle, Run, Jump).
- حالة (State): هل هو يقف، يركض، يقفز، يسقط؟
- موضع (Position) وسرعة (Velocity): يتم تحديثها بناءً على المدخلات والفيزياء.
- منطق الحركة: التعامل مع الجري يسارًا ويمينًا، والقفز.
* مثال (conceptual):
Java
public class Player { Vector2 position; Vector2 velocity; boolean onGround; Animation<TextureRegion> runAnimation; // للرسوم المتحركة float stateTime; // لتتبع وقت حالة الرسوم المتحركة
public Player(float x, float y) { position = new Vector2(x, y); velocity = new Vector2(0, 0); onGround = false; // هنا يتم تحميل الرسوم المتحركة }
public void update(float deltaTime) { // تطبيق الجاذبية على السرعة velocity.y -= GRAVITY * deltaTime;
// تحديث الموضع بناءً على السرعة position.add(velocity.x * deltaTime, velocity.y * deltaTime);
// تحديث وقت حالة الرسوم المتحركة stateTime += deltaTime; }
public void jump() { if (onGround) { velocity.y = JUMP_STRENGTH; onGround = false; } } // دالة لرسم اللاعب (باستخدام SpriteBatch) public void draw(SpriteBatch batch) { TextureRegion currentFrame = runAnimation.getKeyFrame(stateTime, true); batch.draw(currentFrame, position.x, position.y); }}
--
4* الفيزياء واكتشاف التصادم (Box2D):
لجعل حركة اللاعب واقعية والتفاعل مع البيئة، يُعد محرك الفيزياء ثنائي الأبعاد مثل Box2D ضروريًا.
- World: تمثل عالم الفيزياء حيث تتفاعل الكائنات. يتم فيها تحديد الجاذبية.
- Body: يمثل جسمًا فيزيائيًا (مثل اللاعب، البلاط). يمكن أن يكون ثابتًا
(StaticBody)، حركيًا (KinematicBody)، أو ديناميكيًا (DynamicBody).
- Fixture: يمثل شكل التصادم المرتبط بالجسم (مثل دائرة، مربع).
- ContactListener: واجهة للتعامل مع أحداث التصادم بين الأجسام.
- التحويل من Pixel إلى Meter: Box2D يعمل بوحدات المتر، بينما LibGDX يعمل بالبكسل.
ستحتاج إلى عامل تحويل (مثال: PIXELS_PER_METER).
* مثال (conceptual):
Java
// داخل دالة create()
World physicsWorld = new World(new Vector2(0, -9.8f), true); // جاذبية للأسفل
// لإنشاء جسم للاعب:
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(player.position.x / PIXELS_PER_METER, player.position.y / PIXELS_PER_METER);
Body playerBody = physicsWorld.createBody(bodyDef);
PolygonShape playerShape = new PolygonShape();
playerShape.setAsBox(player.width / 2 / PIXELS_PER_METER, player.height / 2 / PIXELS_PER_METER);
playerBody.createFixture(playerShape, 1.0f); // الكثافة
// في دالة render()، قم بتحديث عالم الفيزياء:
physicsWorld.step(Gdx.graphics.getDeltaTime(), 6, 2); // تحديث الفيزياء
// ثم تحديث موضع اللاعب من playerBody.position
--
5* إدارة الكاميرا (Camera Management):
تتبع الكاميرا اللاعب لضمان بقائه في مركز التركيز، مع مراعاة حدود المستوى.
- OrthographicCamera: كاميرا مثالية للألعاب ثنائية الأبعاد.
- تحديث الكاميرا: في دالة render(), قم بتحديث موضع الكاميرا ليتبع اللاعب، ثم قم بتحديث الكاميرا نفسها (camera.update()) وتطبيقها على SpriteBatch و TiledMapRenderer.
- حدود الكاميرا (Camera Bounds): تأكد من أن الكاميرا لا تخرج عن حدود الخريطة.
* مثال (conceptual):
Java
OrthographicCamera camera;
public void create() {
camera = new OrthographicCamera(Gdx.graphics.getWidth() / PPM, Gdx.graphics.getHeight() / PPM);
camera.setToOrtho(false, VIRTUAL_WIDTH, VIRTUAL_HEIGHT); // تعيين الأبعاد الافتراضية
}
public void updateCamera(float playerX, float playerY) {
camera.position.x = Math.max(camera.viewportWidth / 2, Math.min(playerX, mapWidth - camera.viewportWidth / 2));
camera.position.y = Math.max(camera.viewportHeight / 2, Math.min(playerY, mapHeight - camera.viewportHeight / 2));
camera.update();
}
--
6* الرسوم المتحركة (Animations):
إضافة الرسوم المتحركة تجعل اللعبة حيوية.
- Sprite Sheets: دمج عدة إطارات للرسوم المتحركة في ملف صورة واحد لتحسين الأداء.
- TextureRegion: لقص الإطارات الفردية من Sprite Sheet.
- Animation: فئة في LibGDX لإدارة تسلسل الإطارات وسرعة التشغيل.
7* إدارة الشاشات (Screen Management):
الألعاب تتكون عادة من شاشات متعددة (قائمة رئيسية، شاشة اللعب، شاشة النهاية).
- Screen Interface: يوفر LibGDX واجهة Screen، كل شاشة
(مثل PlayScreen, MainMenuScreen) تنفذ هذه الواجهة ولها دورة
حياتها الخاصة (show(), render(), hide(), dispose()).
- Game Class: فئة Game تسمح لك بالتبديل بين الشاشات باستخدام setScreen().
* مثال (conceptual):
Java
// في فئة اللعبة الرئيسية (التي ترث من Game وليس ApplicationAdapter)
public class MyPlatformerGame extends Game {
@Override
public void create() {
setScreen(new MainMenuScreen(this)); // البدء بشاشة القائمة
}
}
// مثال لشاشة اللعب
public class PlayScreen implements Screen {
MyPlatformerGame game; // مرجع إلى كائن اللعبة للتبديل بين الشاشات
public PlayScreen(MyPlatformerGame game) {
this.game = game;
}
@Override
public void render(float delta) {
// منطق اللعب والرسم
if (player.isDead()) {
game.setScreen(new GameOverScreen(game)); // التبديل إلى شاشة النهاية
}
}
// بقية دوال الواجهة (show, hide, resize, pause, resume, dispose)
}
--
8* خطوات التنفيذ التفصيلية (Conceptual):
* إعداد المشروع:
- استخدم أداة إعداد مشروع LibGDX. تأكد من تحديد Box2D كمكتبة إضافية.
- قم بتضمين أصولك (صور، ملفات Tiled) في مجلد core/assets/.
* تصميم المستوى:
- افتح Tiled Map Editor.
- أنشئ New Map، اختر Orthogonal، وحدد حجم البلاط (مثلاً 32x32 بكسل).
- استورد Tileset (مجموعة البلاط) الخاصة بك (صورة تحتوي على كل البلاط الذي ستستخدمه).
- أنشئ طبقات: Background, Ground, و Objects (للتصادم والأعداء).
- ارسم مستواك.
- في طبقة Objects، ارسم مستطيلات لتمثل مناطق التصادم التي لا تظهر مرئيًا
(مثل حدود الخريطة أو الفراغات). يمكنك تسمية هذه الكائنات collision.
- احفظ الخريطة كـ level1.tmx في مجلد assets/levels/.
* إنشاء شاشات اللعبة:
- أنشئ فئات جديدة تنفذ Screen، مثل MainMenuScreen و
PlayScreen و GameOverScreen.
- اجعل MyGameClass (فئة اللعبة الرئيسية) ترث من Game بدلاً من
ApplicationAdapter لتمكين التبديل بين الشاشات.
9* تطبيق الفيزياء (Box2D) في PlayScreen:
- في PlayScreen.show()، قم بتهيئة World لـ Box2D.
- قم بتحميل TiledMap باستخدام TmxMapLoader.
- قم بالمرور على طبقات الكائنات في TiledMap لإنشاء Bodys و Fixtures
ثابتة للبلاط الذي يجب أن يتصادم معه اللاعب.
- ستحتاج إلى تحويل إحداثيات البكسل من Tiled إلى وحدات المتر الخاصة بـ Box2D.
- أنشئ Body و Fixture للاعب (DynamicBody) وقم بربطهما بموضع اللاعب.
* تطوير منطق اللاعب:
- في PlayScreen.render(), قم بتحديث player.update() و physicsWorld.step().
- استخدم Gdx.input.isKeyPressed() أو InputProcessor للتحكم في حركة اللاعب (أفقيًا والقفز).
- قم بتحديث الرسوم المتحركة للاعب بناءً على حالته (جري، قفز، خمول).
* اكتشاف التصادم:
- نفّذ ContactListener لمعالجة أحداث التصادم بين اللاعب والبلاط، أو اللاعب والأعداء،
أو اللاعب والعناصر القابلة للجمع. على سبيل المثال، لتحديد ما إذا كان اللاعب على الأرض (onGround).
* إدارة الكاميرا:
- في PlayScreen.show(), قم بتهيئة OrthographicCamera.
- في PlayScreen.render(), قم بتحديث موضع الكاميرا ليتبع اللاعب.
- طبق الكاميرا على SpriteBatch و OrthogonalTiledMapRenderer قبل الرسم: batch.setProjectionMatrix(camera.combined); و
renderer.setView(camera);.
- نفّذ منطق حدود الكاميرا لمنعها من الخروج عن حدود الخريطة.
* الرسومات والرندر:
- في PlayScreen.render(), قم بمسح الشاشة.
- قم برسم الخريطة باستخدام renderer.render().
- ابدأ SpriteBatch، ثم ارسم اللاعب والأعداء والعناصر.
- أنهِ SpriteBatch.
* التوسع:
- الأعداء: أنشئ فئات للأعداء مع سلوكيات أساسية (المشي ذهابًا وإيابًا، مطاردة اللاعب).
- العناصر القابلة للجمع: عملات معدنية، قوى خاصة.
- واجهة المستخدم (HUD): لعرض النقاط، الحياة، الوقت.
- الصوت: إضافة موسيقى خلفية ومؤثرات صوتية للقفز، جمع العملات، إلخ.
الخاتمة:
- لبناء لعبة منصات في LibGDX، يُعد Tiled Map Editor أداة أساسية
لتصميم المستويات وتحديد بيانات التصادم.
- يُستخدم TmxMapLoader و OrthogonalTiledMapRenderer في
LibGDX لتحميل وعرض خرائط Tiled بسلاسة.
- محرك الفيزياء Box2D ضروري لحركة اللاعب الواقعية واكتشاف التصادم في
ألعاب المنصات، حيث يتعامل مع الأجسام الثابتة والديناميكية.
- OrthographicCamera في LibGDX تتبع اللاعب وتحافظ على
حدود الكاميرا داخل حدود الخريطة لإنشاء تجربة لعب سلسة.
- إدارة الشاشات باستخدام واجهة Screen و Game Class في LibGDX
تسمح بتبديل منظم بين القوائم ومستويات اللعب وشاشات النهاية.
- الرسوم المتحركة في LibGDX تُنفذ باستخدام Sprite Sheets و Animation class
لإضفاء الحيوية على شخصيات اللعبة.
- التحويل من وحدات البكسل إلى وحدات المتر ضروري عند استخدام Box2D في LibGDX،
حيث يعمل Box2D بوحدات قياس مختلفة عن نظام الرسم.
بناء لعبة منصات باستخدام LibGDX يوفر لك تحكمًا لا مثيل له في كل جانب
من جوانب لعبتك. على الرغم من أن الأمر يتطلب فهمًا أعمق لمفاهيم برمجة الألعاب
مثل الفيزياء واكتشاف التصادم وإدارة الأصول، إلا أن الأدوات والمكتبات المتاحة في
LibGDX تجعل هذه العملية ممتعة ومجزية. من خلال دمج Tiled Map Editor
لإنشاء المستويات، و Box2D لمحاكاة الفيزياء، ومرونة LibGDX في الرسم والمدخلات،
يمكنك بناء لعبة منصات قوية ومقنعة تعمل بسلاسة على مجموعة واسعة من الأجهزة.