Home  Contents

Snake in Mono Winforms

فى هذه الجزئية سننشئ نسخة من لعبة الثعبان

Snake game

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



Development

جزء كل قطع الثعبان 10px ويتم التحكم فيه عن طريق الأسهم، ويبدأ الثعبان ب3 قطع وتبدأ اللعبة بالضغط على اى من الأسهم وعند انتهاء اللعبة نعرض Game Over فى منتصف اللوحة



Board.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;



public class Board : UserControl {

    private const int WIDTH = 300;
    private const int HEIGHT = 300;
    private const int DOT_SIZE = 10;
    private const int ALL_DOTS = 900;
    private const int RAND_POS = 29;

    private int[] x = new int[ALL_DOTS];
    private int[] y = new int[ALL_DOTS];

    private int dots;
    private int apple_x;
    private int apple_y;

    private bool left = false;
    private bool right = true;
    private bool up = false;
    private bool down = false;
    private bool inGame = true;

    private Timer timer;

    private Bitmap dot;
    private Bitmap apple;
    private Bitmap head;

    private IContainer components;

    public Board() {

        components = new Container();
        BackColor = Color.Black;
        DoubleBuffered = true;
        Size = new Size(320, 310);


        try {
            dot = new Bitmap("dot.png");
            apple = new Bitmap("apple.png");
            head = new Bitmap("head.png");

        } catch (Exception e) {
            Console.WriteLine(e.Message);
            Environment.Exit(1);
        } 

        initGame();
    }

    private void OnTick(object sender, EventArgs e) {

        if (inGame) {
            checkApple();
            checkCollision();
            move();
        }
        Refresh();
    }


    private void initGame() {

        dots = 3;

        for (int z = 0; z < dots; z++) {
            x[z] = 50 - z * 10;
            y[z] = 50;
        }

        locateApple();
        KeyUp += new KeyEventHandler(OnKeyUp);


        timer = new Timer(this.components);
        timer.Enabled = true;
        timer.Interval = 100;
        timer.Tick += new System.EventHandler(this.OnTick);

        Paint += new PaintEventHandler(this.OnPaint);


    }


    private void OnPaint(object sender, PaintEventArgs e) {

        Graphics g = e.Graphics;

        if (inGame) {

            g.DrawImage(apple, apple_x, apple_y);

            for (int z = 0; z < dots; z++) {
                if (z == 0) {
                    g.DrawImage(head, x[z], y[z]);
                } else {
                    g.DrawImage(dot, x[z], y[z]);    
                }
            }

        } else {
            gameOver(g);
        }
    }


    private void gameOver(Graphics g) {

        String msg = "Game Over";
        StringFormat format = new StringFormat();
        format.Alignment = StringAlignment.Center;
        format.LineAlignment = StringAlignment.Center;
        
        g.DrawString(msg, Font, Brushes.White, ClientRectangle, format);
        timer.Stop();
    }


    private void checkApple() {

        if ((x[0] == apple_x) && (y[0] == apple_y)) {
            dots++;
            locateApple();
        }
    }

    private void move() {

        for (int z = dots; z > 0; z--) {
            x[z] = x[(z - 1)];
            y[z] = y[(z - 1)];
        }

        if (left) {
            x[0] -= DOT_SIZE;
        }

        if (right) {
            x[0] += DOT_SIZE;
        }

        if (up) {
            y[0] -= DOT_SIZE;
        }

        if (down) {
            y[0] += DOT_SIZE;
        }
    }

    private void checkCollision() {

        for (int z = dots; z > 0; z--) {
            if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
                inGame = false;
            }
        }

        if (y[0] > HEIGHT) {
            inGame = false;
        }

        if (y[0] < 0) {
            inGame = false;
        }

        if (x[0] > WIDTH) {
            inGame = false;
        }

        if (x[0] < 0) {
            inGame = false;
        }
    }

    private void locateApple() {
        Random rand = new Random();
        int r = (int) (rand.Next(RAND_POS));
        apple_x = ((r * DOT_SIZE));
        r = (int) (rand.Next(RAND_POS));
        apple_y = ((r * DOT_SIZE));
    }


    private void OnKeyUp(object sender, KeyEventArgs e) {

        int key = (int) e.KeyCode;

        if ((key == (int) Keys.Left) && (!right)) {
            left = true;
            up = false;
            down = false;
        }

        if ((key == (int) Keys.Right) && (!left)) {
            right = true;
            up = false;
            down = false;
        }

        if ((key == (int) Keys.Up) && (!down)) {
            up = true;
            right = false;
            left = false;
        }

        if ((key == (int) Keys.Down) && (!up)) {
            down = true;
            right = false;
            left = false;
        }
    }
}

اولا، نعرف الثوابت فى اللعبة.

WIDTH, HEIGHT ثوابت العرض والإرتفاع لتحديد مساحة اللوحة

DOT_SIZE لتحديد حجم التفاحة (النقط)

ALL_DOTS اكبر عدد ممكن من النقط

RAND_POS ثابت يحسب موقع عشوائى للتفاحة

DELAY ثابت يحدد سرعة اللعبة



 private int[] x = new int[ALL_DOTS];
 private int[] y = new int[ALL_DOTS];

المصفوفتين يخزنو كل احداثيات ال x, y لمكونات الثعبان

الطريقة Move، فيها نستخدم الأسهم للتحكم فى اتجاه حركة الثعبان (بإستخدام القطعة الأولى للثعبان) ثم يليها القطع الباقية



 for (int z = dots; z > 0; z--) {
     x[z] = x[(z - 1)];
     y[z] = y[(z - 1)];
 }

هذا الكود يحرك المكونات فى سلسلة



 if (left) {
     x[0] -= DOT_SIZE;
 }

يحرك الرأس لليسار

فى الطريقة checkCollision نختبر عملية التصادم (سواء بنفسه او بالحوائط)



 for (int z = dots; z > 0; z--) {

     if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
         inGame = false;
     }
 }

ننهى اللعبة فى حال اصطدام الرأس بأى من مكونات الجسم

 if (y[0] > HEIGHT) {
     inGame = false;
 }

ننهى اللعبة اذا اصطدم الثعبان بأسفل اللوحة

Snake.cs

using System;
using System.Drawing;
using System.Windows.Forms;

class Snake : Form {

    public Snake() {

        Text = "Snake";
        DoubleBuffered = true;
        FormBorderStyle = FormBorderStyle.FixedSingle;

        CenterToScreen();

        Controls.Add(new Board());
    }
}

class MApplication {
    public static void Main() {
        Application.Run(new Snake());
    }
}

هذا هو الصف الأساسى.


Snake

Figure: Snake

دى كانت لعبة الثعبان بإستخدام مكتبة WinForms


Home ‡ Contents ‡ Top of Page