This article is currently in the process of being translated into Arabic (~95% done).
In this article series, we're building a complete Snake game from scratch. It makes sense to start with the Introduction and then work your way through the articles one by one, to get the full understanding.
If you want to get the complete source code for the game at once, to get started modifying and learning from it right now, consider downloading all our samples!
Creating the game area
لكي نبدأ بصنع اللعبة يجب علينا اولا صنع الخريطة. ستكون خريطة محدودة حيث يمكن للافعى التنقل خلالها. وقد خطر في بالي ان اجعل خريطة الافعى مشابهة لطاولة الشطرنج, حيث المربعات تكون متساوية الحجم. ويكون ابعادها كأبعاد جسم الافعى. سنقوم ببناء الخريطة على وجهين: قسم منها سيحرر بلغة XAML لانها سهلة, بينما سيتم رسم مربعات الخلفية بالكود البرمجي لان هذه العملية متكررة وديناميكية.
مساحة اللعبة بلغة XAML
اذن لنبدأ بالعمل مع XAML - واجهة بسيطة تحتوي على Canvas panel داخل Border control لخلق مساحة مغلقة ومحددة:
<Window x:Class="WpfTutorialSamples.Games.SnakeWPFSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTutorialSamples.Games"
mc:Ignorable="d"
Title="SnakeWPF - Score: 0" SizeToContent="WidthAndHeight">
<Border BorderBrush="Black" BorderThickness="5">
<Canvas Name="GameArea" ClipToBounds="True" Width="400" Height="400">
</Canvas>
</Border>
</Window>
اللعبة الان تبدو هكذا :
سنستخدم الـ Canvas كمساحة للعبة لانها تسمح لنا باضافة المتحكمات لها وبالتالي تمنحنا تحكم كامل بالاماكن. سنستخدم ذلك لاحقا اما الان فانتبه الى الاتي:
- لا يوجد عرض وارتفاع لنافذة التطبيق وبدلا من ذلك عرفنا الابعاد للـ Canvas لانه نحتاج الى التحكم الكامل باللعبة. وبذلك نضمن ان ابعاد النافذة ستعدل وفقا لاعدادات الخاصية SizeToContent وتضبط على WidthAndHeight. وبذلك المساحة المتوفرة داخل ابعاد النافذة ستعتمد على الحدود المستخدمة من نظام التشغيل في الويندوز والتي بدورها ستعتمد على الثيمات .. الخ.
- استخدمنا خاصية ClipToBounds وجعلناها مفعلة True للـ Canvas لانه في حالة اضافة المتحكمات سيكون قادر على التوسع خارج حدود الـ Canvas panel
تخطيط ورسم الخلفية بالاكواد
كما اسلفنا, سنستخدم رقعة الشطرنج كخلفية للعبة. وتحتوي على مربعات كثيرة. لذلك من السهل عملها من خلال الكود (او يمكننا استخدام صورة لذلك ولكن لن تكون ديناميكية!). ويجب استخدام الكود حالما تعرف المتحكمات داخل النافذة, ولحسن حظنا فانه يوجد حدث event لهذا الغرض : حدث The ContentRendered . سنشرك الحدث مع التصريح عن النافذة Window :
Title="SnakeWPF - Score: 0" SizeToContent="WidthAndHeight" ContentRendered="Window_ContentRendered"
الان لننتقل الى الكود ولنبدأ. اول شيء يجب ان نعرف الحجم لاستخدامه عند رسم الافعى او الخلفية .. الخ. يمكن عمل ذلك عند Window class:
public partial class SnakeWPFSample : Window
{
const int SnakeSquareSize = 20;
.....
الان في الحدث ContentRendered سنستدعي دالة الـDrawGameArea() والتي ستنجز العمل الاصعب. وهي كما موضحة :
private void Window_ContentRendered(object sender, EventArgs e)
{
DrawGameArea();
}
private void DrawGameArea()
{
bool doneDrawingBackground = false;
int nextX = 0, nextY = 0;
int rowCounter = 0;
bool nextIsOdd = false;
while(doneDrawingBackground == false)
{
Rectangle rect = new Rectangle
{
Width = SnakeSquareSize,
Height = SnakeSquareSize,
Fill = nextIsOdd ? Brushes.White : Brushes.Black
};
GameArea.Children.Add(rect);
Canvas.SetTop(rect, nextY);
Canvas.SetLeft(rect, nextX);
nextIsOdd = !nextIsOdd;
nextX += SnakeSquareSize;
if(nextX >= GameArea.ActualWidth)
{
nextX = 0;
nextY += SnakeSquareSize;
rowCounter++;
nextIsOdd = (rowCounter % 2 != 0);
}
if(nextY >= GameArea.ActualHeight)
doneDrawingBackground = true;
}
}
كما اشرنا سابقا, فان هذا القسم من الدرس يتطلب معرفة بـ #C اكثر بقليل من بقية الاقسام, لذلك لن اخوض في كل السطور البرمجية. هاك شرح عام عما فعلناه في الكود: في داخل دالة التكرار While loop صنعنا نسخا (instances) من الكلاس Rectangle باستمرار داخل الـ Canvas والتي هي (GameArea) . ملأنا المربعات باللون الاسود والابيض باستخدام الـ Brush, وكذلك باستخدام الثابت SnakeSquareSize لطول المربع وعرضه. وبكل لفة (تكرار) استخدمنا المتغيرات nextX و nextY للتحكم بتحركات المربعات متى يتجه يمينا(لاقصى يمين الحدود التي وضعناها مسبقا) ومتى يتجه للاسفل(لاقصى اسفل الحدود التي وضعناها مسبقا ) وعندها سيتوقف الرسم.
اليك النتيجة:
ملخص
في هذه المقالة عملنا على تعريف كود XAML لاستخدامه كمضيف لمحتوى اللعبة ورسمنا رقعة الشطرنج عى المساحة المخصصة للعبة باستخدام المتحكم Rectangle الخاص بـ WPF بالاسود والابيض. الخطوة التي بعدها ستكون اضافة الافعى للعبة وكذلك اضافة الطعام التي ستأكله.