القائمة الرئيسية

الصفحات

دليل برمجة لعبة Snake للأندرويد بجافا: بناء المستويات والسرعة

واجهة لعبة الثعبان Snake Game على جهاز أندرويد لوحي، تُظهر المستوى الرابع ونظام النقاط العالية High Score، بخلفية رمادية احترافية لشرح برمجة الألعاب بجافا




دليل برمجة لعبة Snake للأندرويد بجافا: بناء المستويات والسرعة


 لماذا تبدأ رحلتك البرمجية بلعبة الثعبان؟
تعد برمجة الألعاب الكلاسيكية هي البوابة الذهبية لأي مطور يرغب في احتراف
 بيئة Android Studio. فبدلاً من الغرق في تعقيدات المحركات الكبيرة، تمنحك
 لعبة "الثعبان" (Snake Game) فرصة ذهبية لفهم "المنطق البرمجي" البحت.
 في هذا الدليل المحدث لعام 2026، لن نكتفي بصناعة لعبة تقليدية، بل سننتقل إلى مستوى
 الاحتراف عبر شرح كيفية استخدام مكتبة Canvas و Java لإدارة الجرافيك يدوياً، 
مع إضافة ميزات متقدمة مثل تغير السرعات تلقائياً و نظام المستويات المتعددة. نعدك بنهاية
 هذا المقال أن تكون قادراً على بناء لعبتك الأولى ونشرها على متجر جوجل بلاي بكل ثقة.


تجهيز مشروع لعبة Snake في Android Studio


قبل أن نلمس الكود البرمجي، يجب أن نهيئ "البيئة الخصبة" للمشروع.
 اتبع هذه الخطوات بدقة داخل أندرويد ستوديو:
- إنشاء المشروع: قم باختيار New Project ثم حدد القالب Empty Views Activity
 (وهو الخيار الأنسب للألعاب التي تعتمد على الرسم اليدوي).
- تسمية المشروع: اختر اسماً جذاباً مثل SnakeMaster2026.
- اللغة المستهدفة: تأكد من اختيار لغة Java بدلاً من Kotlin، نظراً لاستقرار مكتبات
 الرسم الكلاسيكية معها وتوافقها العالي.
- الحد الأدنى للنظام (SDK): اختر API 24 (أندرويد 7.0) لضمان أن لعبتك تعمل على
 99% من هواتف الأندرويد الموجودة حالياً في السوق العالمي.
* نصيحة ذهبية: لا تستخدم واجهات XML المعقدة لتصميم ساحة اللعب؛ فسر نجاح الألعاب 
السريعة يكمن في استخدام الـ Custom Views التي سنقوم ببرمجتها لاحقاً، 
لضمان استجابة فورية (Zero Lag) خاصة في السرعات العالية.

* هيكلة منطق اللعبة (Technical Logic)
لفهم كيف يتحرك الثعبان دون أن "يتجمد" التطبيق، يجب أن نقسم العمل إلى فئات 
(Classes) منفصلة. سنبدأ الآن بأهم فئة وهي التي تمثل "أجزاء الثعبان".

أولاً: فئة إحداثيات النقاط (SnakePoints.java)
هذا الكلاس هو "العمود الفقري" للعبة؛ فهو المسؤول عن تخزين مكان كل قطعة 
في جسم الثعبان على شبكة الإحداثيات (X, Y).
- اكتب الكود التالي يدوياً في ملف جديد باسم SnakePoints.java:
(تذكر: كتابة الكود يدوياً تساعدك على فهم تسلسل العمليات وتجنب أخطاء التوافق) :


// تعريف الكلاس المسؤول عن نقاط التموضع
public class SnakePoints {
    
    // متغيرات الإحداثيات الأفقية والرأسية
    private int positionX, positionY;

    // مشيد الكلاس (Constructor) لتعيين مكان البداية
    public SnakePoints(int positionX, int positionY) {
        this.positionX = positionX;
        this.positionY = positionY;
    }

    // دوال الوصول (Getters) لاستدعاء مكان القطعة أثناء الرسم
    public int getPositionX() { return positionX; }
    public int getPositionY() { return positionY; }

    // دوال التعديل (Setters) لتحديث مكان القطعة عند الحركة
    public void setPositionX(int positionX) { this.positionX = positionX; }
    public void setPositionY(int positionY) { this.positionY = positionY; }
}
--

* شرح المنطق البرمجي للكود أعلاه:
لماذا نستخدم Getters و Setters؟ ببساطة، لأننا في الألعاب نحتاج لتحديث 
مكان الثعبان آلاف المرات في الثانية الواحدة. هذه الطريقة تضمن أن البيانات محمية 
(Encapsulation) ولا يتم تعديلها إلا من خلال أوامر الحركة التي سنبرمجها في القسم القادم.


تهيئة بيئة العمل وبناء مشروع SnakeMaster 


قبل البدء بكتابة سطر برمجى واحد، يجب أن نجهز "الأساس التقني" للعبة
 داخل Android Studio. هذه الخطوة هامة جداً لأن إعدادات المشروع الصحيحة
 توفر عليك ساعات من إصلاح أخطاء التوافق لاحقاً، خاصة عند التعامل مع
 الرسوميات (Graphics) التي تستهلك موارد الجهاز.

أولاً: إنشاء مشروع جديد (New Project)
- قم بفتح برنامج Android Studio واضغط على New Project.
- من قائمة القوالب، اختر Empty Views Activity.
لماذا هذا القالب؟ لأنه يمنحنا السيطرة الكاملة على الواجهة دون إضافات برمجية 
زائدة قد تبطئ من استجابة الثعبان للأوامر.
- في نافذة الإعدادات:
- Name: ضع اسماً مميزاً (مثل: SnakePro_2026).
- Language: اختر Java (لضمان التوافق التام مع مكتبات الرسم الكلاسيكية).
- Minimum SDK: اختر API 24: Android 7.0 (Nougat)؛ هذا يضمن وصول
 لعبتك لأكبر عدد ممكن من المستخدمين حول العالم.
ثانياً: ضبط إعدادات الـ Gradle والمكتبات
لعبة الثعبان التي نبنيها تعتمد على "الأداء الصافي" (Pure Performance)،
 لذا لن نحتاج لمكتبات خارجية ضخمة، بل سنقوم بضبط ملفات الإعداد لتعمل بأقصى سرعة:
- افتح ملف build.gradle (Module: app).
- تأكد من تحديث نسخة compileSdk و targetSdk إلى إصدار 35 (المتوافق مع تحديثات 2026).
- ضبط أبعاد الشاشة: لضمان ظهور اللعبة بكامل الشاشة (Full Screen) وبدون حواف مزعجة، 
سنقوم بإضافة أمر برمجى في ملف AndroidManifest.xml لاحقاً، 
ولكن من هنا نتأكد أن التطبيق يدعم الوضعين الطولي والعرضي.
* ملاحظة للمطورين: في عام 2026، أصبحت معالجة الرسوميات داخل أندرويد ستوديو 
أكثر ذكاءً، لذا تأكد من تفعيل خاصية viewBinding في ملف الجرادل لتسهيل 
عملية الربط بين الكود والواجهة دون استهلاك ذاكرة الرام (RAM) بشكل مفرط.





الهندسة البرمجية وهيكلة منطق اللعبة 


بعد تهيئة المشروع، ننتقل الآن إلى المرحلة الأكثر أهمية: بناء محرك اللعبة. 
في تطوير ألعاب الأندرويد لعام 2026، لم يعد الاعتماد على الأزرار التقليدية (Buttons)
 كافياً، بل ننتقل إلى نظام الرسم البرمجي المباشر لضمان استجابة لحظية وحركة انسيابية للثعبان.

أولاً: تصميم واجهة اللعبة (XML) بنظام Canvas
بدلاً من تصميم واجهة معقدة بملفات XML، سنعتمد على عنصر واحد فقط وهو
 الـ SurfaceView. هذا العنصر يسمح لنا بالرسم على الشاشة بتردد عالٍ
 (High Refresh Rate)، وهو السر وراء عدم وجود "لاك" في الألعاب الاحترافية.
اذهب إلى ملف activity_main.xml واستبدل الكود الموجود بهذا الإطار البسيط:
XML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#121212">

    <FrameLayout
        android:id="@+id/game_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
--

ثانياً: برمجة فئات اللعبة (Classes)
سنقوم الآن بإنشاء الفئات التي تدير "ذكاء" اللعبة وحركتها. 
ستحتاج لإنشاء ملفين جديدين بجانب ملف الـ MainActivity.

1. فئة تمثيل جسم الثعبان SnakePoints.java
هذا الكلاس هو المسؤول عن تخزين إحداثيات كل "عقدة" أو "قطعة" في جسم الثعبان. بدون هذا الكلاس،
 لن يعرف المحاكي أين تنتهي الرأس وأين يبدأ الذيل.
(اكتب الكود التالي بعناية في ملف Java مستقل):

Java

public class SnakePoints {
    // تخزين إحداثيات الموقع الحالي لكل قطعة
    private int coordX, coordY;

    public SnakePoints(int coordX, int coordY) {
        this.coordX = coordX;
        this.coordY = coordY;
    }

    // دوال جلب الإحداثيات لرسمها على الـ Canvas
    public int getCoordX() { return coordX; }
    public int getCoordY() { return coordY; }

    // دوال تحديث الموقع عند تحرك الثعبان
    public void setCoordX(int coordX) { this.coordX = coordX; }
    public void setCoordY(int coordY) { this.coordY = coordY; }
}
--

2. فئة محرك الرسم وحلقة اللعبة GameView.java
هذا هو الجزء الأكبر والأهم؛ فهو المسؤول عن Game Loop (حلقة اللعبة) 
التي تقوم بمسح الشاشة ورسم الثعبان في مكانه الجديد كل جزء من الثانية.
* تنبيه للمبرمجين: حركة الثعبان تعتمد على مصفوفة من نوع List<SnakePoints>. 




في كل خطوة، نقوم بإضافة نقطة جديدة عند الرأس وحذف النقطة الأخيرة من الذيل، مما يعطي
 إيحاءً بالحركة الانسيابية، إليك هيكل المحرك الرئيسي (جزء من الكود لضمان التركيز):
Java

// تعريف محرك الرسم الذي يرث خصائص الـ SurfaceView
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
    
    private List<SnakePoints> snakePointsList = new ArrayList<>();
    private SurfaceHolder surfaceHolder;
    private Paint paint; // أداة التلوين والرسم

    public GameView(Context context) {
        super(context);
        this.surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
        
        // إعدادات أداة الرسم (اللون الأخضر للثعبان)
        paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
    }

    // وظيفة الرسم المتكرر على الشاشة
    private void drawCanvas() {
        Canvas canvas = surfaceHolder.lockCanvas();
        if (canvas != null) {
            // مسح الشاشة القديمة ورسم الخلفية السوداء
            canvas.drawColor(Color.BLACK);
            
            // رسم جسم الثعبان قطعة بقطعة
            for (SnakePoints point : snakePointsList) {
                canvas.drawRect(point.getCoordX(), point.getCoordY(), 
                               point.getCoordX() + 20, point.getCoordY() + 20, paint);
            }
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}
--

*شرح الكود :
لاحظ استخدام lockCanvas() و unlockCanvasAndPost(). 
هذه العملية تمنع "تمزق الشاشة" (Screen Tearing) وتضمن أن اللاعب يرى 
حركة ناعمة جداً حتى لو كانت سرعة الثعبان عالية جداً في المستويات المتقدمة.


برمجة السرعة ونظام المستويات الديناميكي (Levels & Speed) 


الفرق بين لعبة ثعبان "مملة" ولعبة احترافية هو التحدي التصاعدي.
 في هذا القسم، سنتعلم كيف نجعل اللعبة تشعر باللاعب؛ فكلما زادت مهارته وأكل 
المزيد من التفاح، زادت سرعة اللعبة وتغيرت ملامح المستوى، مما يرفع من مستوى الأدرينالين وصعوبة التحكم.

أولاً: التحكم البرمجي في السرعة باستخدام الـ Handler
في أندرويد ستوديو، لا نستخدم "النوم" (Thread.sleep) لأنه يجمد التطبيق. 
بدلاً من ذلك، نستخدم الـ Handler مع وظيفة postDelayed. السر هنا يكمن في 
تقليل "وقت التأخير" (Delay) كلما زادت النقاط.
إليك كود إدارة الوقت (Game Loop Timer):
Java

// متغيرات التحكم في الوقت والسرعة
private long currentDelay = 500; // البداية: نصف ثانية لكل خطوة
private final long MIN_DELAY = 100; // أقصى سرعة ممكنة (100 ميلي ثانية)

private void startGameLoop() {
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            moveSnake(); // تحريك الثعبان
            checkCollision(); // فحص التصادم
            drawCanvas(); // إعادة الرسم
            
            // إعادة تشغيل الحلقة بالسرعة الحالية
            handler.postDelayed(this, currentDelay);
        }
    }, currentDelay);
}
--

* شرح المنطق البرمجي:
كلما استدعى الـ Handler نفسه، فإنه ينتظر قيمة currentDelay. إذا قمنا بتقليل 
هذه القيمة، ستبدو حركة الثعبان أسرع بكثير على الشاشة.




ثانياً: نظام المستويات وتطور الصعوبة
لإضافة نظام مستويات احترافي، سنقوم ببرمجة دالة تراقب النتيجة (Score). 
عند الوصول لعدد نقاط معين، يتم تغيير سرعة اللعبة أو حتى تغيير لون الخلفية لإشعار 
اللاعب بالانتقال لمرحلة أصعب.
* كود تحديث المستوى (Level Up Logic):
Java

private void updateGameLevel() {
    // زيادة الصعوبة كلما أكل الثعبان 5 تفاحات
    if (score % 5 == 0 && currentDelay > MIN_DELAY) {
        currentDelay -= 50; // تقليل وقت الانتظار بمقدار 50 ميلي ثانية
        
        // تغيير لون الثعبان برمجياً لتمييز المستوى الجديد
        if (score >= 20) {
            paint.setColor(Color.RED); // المستوى الصعب
        } else if (score >= 10) {
            paint.setColor(Color.YELLOW); // المستوى المتوسط
        }
    }
}
--

ثالثاً: إضافة العوائق الديناميكية
في المستويات المتقدمة (مثلاً بعد 50 نقطة)، يمكنك برمجة "جدران" تظهر
 في منتصف الشاشة. يتم ذلك عبر إضافة نقاط ثابتة في مصفوفة التصادم، 
وإذا تساوت إحداثيات رأس الثعبان مع إحداثيات الجدار، تنتهي اللعبة (Game Over).
* تنبيه : تأكد دائماً من إيقاف الـ Handler عند خروج اللاعب من التطبيق 
باستخدام دالة onPause() لمنع استنزاف بطارية الهاتف في الخلفية.


 برمجة العوائق الديناميكية (Dynamic Obstacles)


بعد أن يتجاوز اللاعب حاجز الـ 50 نقطة، تصبح المساحة المفتوحة سهلة جداً بالنسبة له. 
هنا يأتي دور "الجدران المفاجئة" التي تظهر في منتصف الشاشة لتجبر اللاعب 
على تغيير مساره بسرعة. برمجياً، نحن لا نقوم برسم صورة ثابتة فحسب،
 بل نقوم بإنشاء "منطقة محظورة" في مصفوفة الإحداثيات.

1. إنشاء مصفوفة العوائق (Obstacles List)
سنقوم ببرمجة قائمة تحتوي على نقاط ثابتة تمثل الجدار. 
إذا لمس رأس الثعبان أي نقطة في هذه القائمة، تنتهي اللعبة فوراً.
أضف هذا الكود داخل فئة GameView.java:
Java

// قائمة لتخزين نقاط العوائق (الجدران)
private List<SnakePoints> obstaclesList = new ArrayList<>();

private void setupObstacles() {
    // تصفير القائمة القديمة لضمان عدم تكرار العوائق
    obstaclesList.clear();

    // إضافة جدار عمودي في منتصف الشاشة عند الوصول لـ 50 نقطة
    if (score >= 50) {
        for (int i = 0; i < 10; i++) {
            // إضافة 10 نقاط عمودية كجدار ثابت
            obstaclesList.add(new SnakePoints(centerX, centerY + (i * 20)));
        }
    }
}
--

2. رسم العوائق على الـ Canvas
لكي يرى اللاعب هذه الجدران، يجب أن نقوم بتلوينها بلون مختلف
 (مثلاً الرمادي أو الأحمر الداكن) داخل دالة الرسم.
كود الرسم (يُضاف داخل drawCanvas):
Java

// رسم العوائق بلون مختلف عن الثعبان والتفاح
paint.setColor(Color.GRAY);
for (SnakePoints obstacle : obstaclesList) {
    canvas.drawRect(obstacle.getCoordX(), obstacle.getCoordY(),
                   obstacle.getCoordX() + 20, obstacle.getCoordY() + 20, paint);
}
--

3. منطق التصادم مع الجدار (Collision Logic)
سنضيف شرطاً داخل دالة فحص التصادم للتأكد مما إذا كان الرأس قد لمس الجدار أم لا.
كود فحص التصادم مع العائق:
Java

private void checkObstacleCollision() {
    SnakePoints head = snakePointsList.get(0); // الحصول على رأس الثعبان
    
    for (SnakePoints wall : obstaclesList) {
        // إذا تساوت إحداثيات الرأس مع إحداثيات أي نقطة في الجدار
        if (head.getCoordX() == wall.getCoordX() && head.getCoordY() == wall.getCoordY()) {
            isGameOver = true; // إيقاف اللعبة فوراً
            showGameOverDialog();
        }
    }
}
--

* نصيحة : يجب ان تحرص على عدم توليد "التفاحة" (Food) فوق إحداثيات الجدار
 لأن ذلك سيجعل الوصول إليها مستحيلاً ويسبب إحباطاً للاعب!


آلية حفظ "أعلى نقاط" (High Score) لضمان استمرارية التحدي 


لا تكتمل أي لعبة احترافية دون وجود "نظام ذاكرة" يحفظ إنجازات اللاعب.
 تخيل أن يحقق اللاعب رقماً قياسياً ثم يختفي بمجرد إغلاق التطبيق! 
في أندرويد، نستخدم تقنية SharedPreferences لتخزين "أعلى سكور" في 
ذاكرة الهاتف الدائمة بشكل خفيف وذكي، دون الحاجة لقواعد بيانات معقدة مثل SQLite.

أولاً: مفهوم التخزين السحابي المحلي (SharedPreferences)
ببساطة، هذه التقنية تقوم بإنشاء ملف صغير جداً داخل نظام الأندرويد يحمل اسماً معيناً، 
ونقوم بتخزين قيمة "الرقم القياسي" داخله. 
عند فتح اللعبة مرة أخرى، يذهب الكود لهذا الملف ويسترجع القيمة المسجلة.




ثانياً: برمجة دالة "حفظ الرقم القياسي" (Save High Score)
يجب استدعاء هذه الدالة فقط عندما تنتهي اللعبة (Game Over) للتحقق
 مما إذا كان السكور الحالي أكبر من السكور القديم.
أضف هذا الكود في نهاية ملف الـ Java الخاص بك:
Java

private void saveHighScore(int currentScore) {
    // الوصول لملف التخزين المسمى "SnakeData"
    SharedPreferences preferences = getContext().getSharedPreferences("SnakeData", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = preferences.edit();

    // جلب الرقم القياسي القديم (القيمة الافتراضية 0 إذا كان أول مرة)
    int oldHighScore = preferences.getInt("highScore", 0);

    // إذا حقق اللاعب رقماً جديداً، نقوم بتحديث الملف
    if (currentScore > oldHighScore) {
        editor.putInt("highScore", currentScore);
        editor.apply(); // حفظ التغييرات فوراً
    }
}
--

ثالثاً: استرجاع وعرض الرقم القياسي (Load High Score)
لكي يشعر اللاعب بالتحدي، يجب أن يرى "أعلى نقاط" مسجلة دائماً في زاوية الشاشة أو في واجهة البداية.
كود جلب البيانات عند تشغيل اللعبة:
Java

private int getSavedHighScore() {
    SharedPreferences preferences = getContext().getSharedPreferences("SnakeData", Context.MODE_PRIVATE);
    // إرجاع القيمة المخزنة تحت مفتاح "highScore"
    return preferences.getInt("highScore", 0);
}
--

رابعاً: الربط مع واجهة المستخدم (UI Update)
داخل دالة الرسم drawCanvas التي شرحناها سابقاً، سنقوم بإضافة
 سطر برمجي بسيط لعرض هذه النقاط بشكل احترافي.
تعديل كود الرسم لإظهار السكور:
Java

// إعداد لون وشكل الخط للسكور
paint.setColor(Color.WHITE);
paint.setTextSize(40);

// رسم السكور الحالي والسكور العالي في أعلى الشاشة
canvas.drawText("Score: " + score, 50, 80, paint);
canvas.drawText("Best: " + getSavedHighScore(), 50, 130, paint);
--

* تنبيه للمبرمج : استخدم editor.apply() بدلاً من editor.commit()؛ 
لأن الأولى تعمل في الخلفية (Asynchronous) ولا تسبب أي "تهنيج"
 أو ثقل في واجهة اللعبة أثناء الحفظ.


اللمسات النهائية وبث الروح في اللعبة (Graphics & UX)


الآن وقد أصبح لديك ثعبان يتحرك ونظام نقاط يعمل، حان الوقت لإضافة "اللمسة السحرية". 
اللعبة بدون صوت أو تحكم سلس تشبه جسداً بلا روح.
 في هذا القسم، سنبرمج نظام الأصوات التفاعلية وطرق التحكم التي تجعل
 اللاعب يشعر بكل حركة يقوم بها الثعبان.

أولاً: إضافة المؤثرات الصوتية (Sound Effects)
في أندرويد، نستخدم كلاس MediaPlayer لتشغيل أصوات قصيرة عند
 وقوع أحداث معينة (مثل أكل التفاحة أو الاصطدام بالجدار).
 هذا يزيد من انغماس اللاعب في التجربة.

1. تجهيز ملفات الصوت:
يجب عليك إنشاء مجلد باسم raw داخل مجلد res ووضع ملفات الصوت فيه (بصيغة mp3 أو wav).

2. كود تشغيل الصوت برمجياً:
Java

// تعريف مشغلات الصوت
private MediaPlayer eatSound, gameOverSound;

private void initSounds() {
    // ربط الملفات الصوتية من مجلد raw
    eatSound = MediaPlayer.create(getContext(), R.raw.eat_crunch);
    gameOverSound = MediaPlayer.create(getContext(), R.raw.game_over_sound);
}

private void playEatSound() {
    if (eatSound != null) {
        eatSound.start(); // تشغيل صوت الأكل فوراً
    }
}
--

* نصيحة للمطور: لا تنسَ استدعاء release() للمشغلات في دالة onDestroy
 لتجنب استهلاك ذاكرة الهاتف (Memory Leak).




ثانياً: برمجة أدوات التحكم (Swipe Gestures)
بدلاً من الأزرار التقليدية التي تغطي مساحة الشاشة، سنبرمج نظام "السحب" 
(Swipe) الذي يفضله لاعبو 2026.
 سنقوم بالاعتماد على دالة onTouchEvent لاكتشاف اتجاه حركة إصبع اللاعب.
كود التحكم باللمس (Logic Control):
Java

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_UP) {
        float xEnd = event.getX();
        float yEnd = event.getY();

        // حساب الفرق بين نقطة البداية والنهاية لتحديد الاتجاه
        float deltaX = xEnd - xStart;
        float deltaY = yEnd - yStart;

        if (Math.abs(deltaX) > Math.abs(deltaY)) {
            // الحركة أفقية (يمين أو يسار)
            if (deltaX > 0 && !direction.equals("left")) direction = "right";
            else if (deltaX < 0 && !direction.equals("right")) direction = "left";
        } else {
            // الحركة رأسية (أعلى أو أسفل)
            if (deltaY > 0 && !direction.equals("up")) direction = "down";
            else if (deltaY < 0 && !direction.equals("down")) direction = "up";
        }
    }
    return true;
}
--

ثالثاً: تحسين الجرافيك بلمسات بسيطة (Visual Polish)
لإعطاء مظهر احترافي، سنقوم بتغيير شكل "التفاحة" (الغذاء) لتكون دائرية 
مع ظل خفيف بدلاً من مجرد مربع جامد.
تعديل كود رسم الغذاء:
Java

// رسم التفاحة بشكل دائري جذاب
paint.setColor(Color.RED);
canvas.drawCircle(foodX + 10, foodY + 10, 12, paint);

// إضافة لمعة صغيرة فوق التفاحة لإعطاء تأثير 2D احترافي
paint.setColor(Color.WHITE);
canvas.drawCircle(foodX + 7, foodY + 7, 4, paint);
--


الأسئلة الشائعة حول برمجة الألعاب في Android Studio 


في هذا القسم، نجيب على أكثر الأسئلة التي تشغل بال المطورين عند البدء 
في مشروعهم الأول باستخدام Java و Android Studio لعام 2026 :

1. هل يمكنني إضافة إعلانات (AdMob) للعبة الثعبان للربح منها؟
بالتأكيد! يمكنك دمج مكتبة Google Mobile Ads SDK بسهولة.
 ننصح بإضافة "إعلان بيني" (Interstitial Ad) يظهر فقط عند شاشة "Game Over"
 لضمان عدم إزعاج اللاعب أثناء الحركة وزيادة أرباحك.




2. كيف أجعل اللعبة تدعم جميع أحجام الشاشات (Responsive Design)؟
السر يكمن في عدم استخدام أرقام ثابتة (Pixels). في كود الـ Canvas، قم بجلب
 أبعاد الشاشة برمجياً باستخدام getWidth() و getHeight()، ثم اجعل حجم
 مربعات الثعبان نسبة مئوية من عرض الشاشة.

3. هل لغة Java لا تزال مناسبة لتطوير الألعاب في 2026؟
نعم، لا تزال Java هي اللغة الأم لنظام أندرويد. رغم صعود Kotlin، إلا أن
 مكتبات الرسم ومعالجة البيانات في الألعاب البسيطة (2D) لا تزال تعمل بكفاءة مذهلة 
واستقرار تام مع جافا، وهي الأسهل للمبتدئين لفهم منطق البرمجة الكائني (OOP).

4. لماذا ترتفع حرارة الهاتف أحياناً عند تشغيل اللعبة؟
يحدث هذا غالباً بسبب "حلقة اللعبة" (Game Loop) التي تعمل بسرعة مفرطة. 
تأكد من استخدام postDelayed كما شرحنا في القسم الثالث لتقييد عدد الإطارات 
في الثانية (FPS)، مما يوفر استهلاك المعالج والبطارية.

5. هل يمكنني تحويل اللعبة لتعمل بنظام اللعب الجماعي (Multiplayer)؟
نعم، ولكن ذلك سيتطلب استخدام Firebase Realtime Database أو
 Google Play Games Services لمزامنة إحداثيات الثعبانين بين جهازين مختلفين،
 وهو موضوع متقدم سنغطيه في مقالاتنا القادمة.

6. هل أحتاج لمصمم جرافيك لإنشاء واجهة اللعبة؟
ليس بالضرورة. ألعاب مثل "Snake" تعتمد على أسلوب Minimalist Design.
 يمكنك الاعتماد على الألوان البرمجية (Color Codes) داخل
 الـ Paint Class كما فعلنا، وستبدو اللعبة عصرية وجذابة جداً.

الخاتمة: ابدأ مغامرتك البرمجية الآن
وصلنا إلى نهاية رحلتنا في برمجة واحدة من أشهر الألعاب في التاريخ. 
تذكر أن الهدف من هذا الدليل ليس مجرد "نسخ الكود"، بل فهم المنطق وراء كل سطر برمجي كتبته. 
عالم تطوير الألعاب في Android Studio واسع جداً، ولعبة الثعبان هي مجرد البداية.
 ندعوك لتجربة تغيير الألوان، إضافة عوائق جديدة، أو حتى ابتكار نظام مكافآت خاص بك. 
البرمجة هي فن التجربة والخطأ، وكل "خطأ" تكتشفه اليوم هو خطوة لتصبح مطوراً محترفاً غداً.



جدول المحتويات