لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 08/31/15 in مقالات البرمجة
-
تعتبر الأزرار من أهم العناصر المستخدمة في صفحات الويب لذا فقد اهتم بها إطار العمل Bootstrap وأعطاها خصائص كثيرة ومتعددة، تستطيع تكوين الأزرار باستخدام الوسم <button></button> أو الوسم <a></a>.فيما يلي عرض للأصناف التي يمكن إضافتها إلى الوسمين السابقين لتخصيص الأزرار حسب الحاجة: .btn وهو الصنف الرئيسي الذي لابد من إضافته في أي زر سواء كان باستخدام الوسم <button> أو <a>..btn-primary ويستخدم مع الزر الأساسي في الصفحة أو النموذج..btn-info ويستخدم مع زر الحصول على المعلومات..btn-warning ويستخدم في حالة كانت هناك احتمالات أخرى وأردت تنبيه المستخدم لذلك..btn-danger ويستخدم في حالة التحذير من عواقب الإقدام على شيء كأن تستخدمه ليكون زر حذف شيء معين من الصفحة..btn-default الزر الافتراضي بدون أي تنسيقات إضافية، ويستخدم في أي حالة أخرى غير الحالات السابقة.مثال يوضح استخدامات الأصناف السابقة وتأثيرها على الأزرار: <button type="button" class="btn">زر بدون تأثير</button> <button type="button" class="btn btn-default">الزر الافتراضي</button> <button type="button" class="btn btn-primary">زر أساسي</button> <button type="button" class="btn btn-info">المزيد من المعلومات</button> <button type="button" class="btn btn-warning">انتبه لهذا</button> <button type="button" class="btn btn-danger">زر الخطر</button> <button type="button" class="btn btn-success">إنهاء بنجاح</button> <button type="button" class="btn btn-link">الزر كارتباط تشعبي</button>ومخرجات الشيفرة السابقة كما يلي: وتنطبق هذه الأصناف أيضا على الوسم <a></a> جرب ذلك واكتشف النتيجة بنفسك. تخصيص الأزرار (الحجم)يوفر إطار العمل Bootstrap عدة مقاسات تستطيع استخدامها وتخصيص الزر بالحجم الذي تريد كما يلي: .btn-lg صنف للشاشات الكبيرة.md. الحجم المُتوسّط (إذا لم تستعمل أي صنف فسيكون الحجم الافتراضي وهو الحجم المتوسط).btn-sm صنف للشاشات الصغيرة..btn-xs صنف للشاشات الصغرى.وهذا الكود يوضح كيفية استخدام هذه الأصناف لتخصيص حجم الأزرار: <button type="button" class="btn btn-primary btn-lg"> زر بدون تأثير وحجم كبير </button> <button type="button" class="btn btn-default"> الزر الافتراضي بالحجم الافتراضي </button> <button type="button" class="btn btn-primary btn-sm"> زر أساسي وحجم صغير </button> <button type="button" class="btn btn-primary btn-xs"> المزيد من المعلومات والحجم الأصغر </button> <button type="button" class="btn btn-warning btn-lg"> انتبه لهذا الحجم الكبير </button> <button type="button" class="btn btn-danger btn-sm"> زر الخطر الحجم الصغير </button>مخرجات الشيفرة السابقة: تجميع الأزرار في مجموعة واحدةيسمح لك الصنف .btn-group بإنشاء مجموعة من الأزرار وتجميعها في صف واحد. لإنشاء ذلك ننشئ تقسيم في الصفحة باستخدام الوسم <div> ونستعمل الصنف .btn-group لهذا الوسم، ومن ثم ننشئ الأزرار داخله كما يلي: <div class="btn-group"> <button type="button" class="btn btn-primary">1</button> <button type="button" class="btn btn-primary">2</button> <button type="button" class="btn btn-primary">3</button> <button type="button" class="btn btn-primary">4</button> </div>مخرجات الشيفرة السابقة: وبإمكانك تخصيص حجم الأزرار كاملة في هذه المجموعة من خلال استخدام الصنف.btn-group-* وتستبدل الرمز * بأي حجم (lg-sm-xs). وتستطيع استخدام الصنف.btn-group-justified لتكون جميع الأزرار متساوية مع بعضها البعض وتتمدد لتشمل كل العرض (width) المتوفر. وهناك صنف آخر وهو .btn-block يمكنك من خلاله أن تجعل الزر يأخذ عرض الصفحة كاملة أو عرض العنصر الأب فإذا وجد في عمود من أعمدة النظام الشبكي Grid system فإنه يأخذ عرض(width) العمود كاملا، وهذا يوضع عادة في المتاجر الإلكترونية عند شراء المنتجات أو يستخدم في صفحات تحميل البرامج وغيرها، مثال: <button type="button" class="btn btn-default btn-lg btn-block"> هذا الزر يأخذ عرض الصفحة كاملا </button> <hr/> <button type="button" class="btn btn-primary btn-lg btn-block"> <span class="glyphicon glyphicon-download"></span> تحميل المرفقات </button> <hr/> <div class="row"> <div class="col-sm-4"> <button type="button" class="btn btn-warning btn-lg btn-block"> <span class="glyphicon glyphicon-credit-card"></span> شراء المنتج </button> </div> <div class="col-sm-8"> <button type="button" class="btn btn-success btn-lg btn-block"> <span class="glyphicon glyphicon-send"></span> ارسل </button> </div> </div>مخرجات الشيفرة السابقة: ملاحظة: بإمكانك الاطلاع على كافة الخصائص والأصناف التي تم شرحها من خلال الأمثلة المرفقة. الأيقوناتتستخدم الأيقونات مع الأزرار والقوائم وأشرطة الأدوات Toolbars، وأدوات التنقل Navigation، والنماذج وغيرها من العناصر الأخرى، وهناك حوالي 200 أيقونة يوفرها Bootstrap. لا يتوجب عليك حفظ أسماء الأيقونات فإذا احتجت إلى اسم أيقونة كل ما عليك فعله هو زيارة الموقع الرسمي لإطار العمل. دائما تستخدم الأيقونات مع الوسم <span> وتستدعى من خلال الصنف.glyphicon والصنف.glyphicon-name حيث أن الصنف الأول لتهيئة التصميم لاستقبال الأيقونات، والصنف الثاني لاستدعاء اسم الأيقونة المراد استخدامها. <span class="glyphicon glyphicon-download"></span> <span class="glyphicon glyphicon-qrcode"></span> <button class="btn btn-primary btn-lg"> <span class="glyphicon glyphicon-search"></span> </button> <button class="btn btn-info btn-md"> <span class="glyphicon glyphicon-envelope"></span> ارسل الرسالة </button> <a href="#" class="btn btn-sucess btn-lg"> <span class="glyphicon glyphicon-comment"></span>إضافة تعليق </a>مخرجات الشيفرة السابقة: النماذج وعناصرها في Bootstrapكان تصميم النماذج وتنسيق كل عنصر داخل النموذج من أصعب الأعمال التي يقوم بها المصمم أثناء العمل على تصميم المواقع، ولكن Bootstrap وفر الكثير من الجهد في هذا الجانب وأعطى تنسيقًا لكل عنصر داخل النموذج. ويقسم Bootstrap النماذج إلى ثلاثة أنواع: النموذج العموديالنموذج الأفقي.نموذج السطر الواحد inline.قبل البدء بتفاصيل كتابة الشيفرة والأصناف المتوفرة لكل نوع من الأنواع السابقة، دعونا نتفق على القواعد التالية: الخاصية <"form role="form> نستخدمها دائما مع النماذج.يجب أن تكون العناصر <"label></label> ،<input type="text/> داخل الوسم <"div class="form-group> وذلك لإعطائها التنسيق المناسب.نستخدم الصنف .form-control مع العناصر <input> ،<textarea> ،<select>.وفيما يلي الأصناف المستخدمة والتنسيق النهائي الذي يظهر على النموذج في كل نوع من الأنواع الثلاثة السابقة: النموذج العموديوهو النموذج الافتراضي الذي تتسلسل فيه الأدوات بشكل عمودي، كما في الشكل التالي: شيفرة النموذج السابق: <form role="form"> <div class="form-group"> <label for="inputtext">اسم المستخدم:</label> <input type="text" id="inputtext" class="form-control" placeholder="اسم المستخدم" /> </div> <div class="form-group"> <label for="password">كلمة المرور:</label> <input type="password" id="password" class="form-control" placeholder="كلمة المرور"/> </div> <div class="checkbox"> <label><input type="checkbox" />تذكرني على هذا المتصفح</label> </div> <input type="button" class="btn btn-primary btn-md" value="تسجيل الدخول"/> </form>وكما تلاحظ يجب أن تلتزم بالقواعد السابقة الذكر لكي يظهر التصميم بالشكل المطلوب. النموذج الأفقيالتنسيق في هذا النموذج مختلف عن تنسيق النموذج السابق حيث يتم وضع كل العناصر المترابطة في ترتيب أفقي كما هو موضح في الشكل التالي:Horizontal-form.png وشيفرة النموذج كما يلي: <form class="form-horizontal" role="form"> <div class="form-group"> <label for="inputtext"class="control-label col-md-2">اسم المستخدم:</label> <div class="col-md-10"> <input type="text" id="inputtext" class="form-control" placeholder="اسم المستخدم" /> </div> </div> <div class="form-group"> <label for="password" class="control-label col-md-2">كلمةالمرور:</label> <div class="col-md-10"> <input type="password" id="password" class="form-control" placeholder="كلمة المرور"/> </div> </div> <div class="form-group"> <div class="col-xs-offset-2 col-xs-10"> <div class="checkbox" class="col-xs-offset-2 col-xs-10"> <label><input type="checkbox"/>تذكرني على هذا المتصفح</label> </div> </div> <div class="col-xs-offset-2 col-xs-10"> <input type="button" class="btn btn-primary btn-md" value="تسجيل الدخول"/> </div> </form>وكذلك هناك اختلاف في شيفرة النموذج والعناصر المكونة له فأولا لابد من إضافة الصنف.form-horizontal إلى وسم النموذج <form class="form-horizontal">، ومن ثم يتم إضافة الصنف , .col-*-* والصنف .control-label إلى كل وسم <label> داخل النموذج، وإضافة تقسيمات <div> في كل عنصر له الوسم <input>. كل عنصر يحتوي على الصنف .col-xs-offset-* فتتم إزاحته بمقدار القيمة التي ستوضع بدلا من الرمز *، كما تلاحظ في صندوق الاختيارcheckbox والزرbutton في النموذج السابق. نموذج السطر الواحد Inline formفي هذا النوع من النماذج يتم تجميع كل عناصر النموذج في سطر واحد، ولكن هذا النوع من النماذج لا يلائم الأجهزة ذات الشاشات الصغيرة كالأجهزة المحمولة، ولكن بمجرد الدخول للموقع من هذه الأجهزة فسيتحول مباشرة إلى النموذج من النوع العمودي الذي تقدم ذكره. وشيفرة تكوينه على النحو التالي: <form class="form-inline" role="form"> <div class="form-group"> <label class="sr-only" for="inputEmail">البريد الإلكتروني</label> <input type="email" class="form-control" id="inputEmail" placeholder="البريد الإلكتروني"> </div> <div class="form-group"> <label class="sr-only" for="inputPassword">كلمة المرور</label> <input type="password" class="form-control" id="inputPassword" placeholder="كلمة المرور"> </div> <div class="checkbox"> <label><input type="checkbox"> تذكرني على هذا الجهاز</label> </div> <button type="submit" class="btn btn-primary">تسجيل دخول</button> </form>ولا تختلف هذه الشيفرة عن الشيفرات السابقة إلا بصنفين هما .form-inline المضاف إلى الوسم<form>والصنف .sry-only المضاف مع الوسم <label>. وتم استخدام الصنف .sry-only لغرض إخفاء هذا العنصر، لأنه من المستحسن دائما عند إضافة عنصر <input> من نوع نص أن يكون الوسم <label> مصاحبًا له دائما لذا ففي الـ Bootstrap تم إضافة الصنف .sry-only لهذا الغرض. قد تلاحظ من خلال الأمثلة السابقة أن حجم العناصر داخل النموذج ثابت وقد لا يكون هذا الحجم مرغوب فيه لديك لذا بإمكانك تغيير أحجام هذه العناصر من خلال النظام الشبكي Grid system ، وهذا مثال يوضح ذلك: <form> <div class="row"> <div class="col-xs-3"> <input type="text" class="form-control"> </div> <div class="col-xs-4"> <input type="text" class="form-control"> </div> <div class="col-xs-5"> <input type="text" class="form-control"> </div> </div> <br> <div class="row"> <div class="col-xs-3"> <textarea class="form-control"></textarea> </div> <div class="col-xs-4"> <textarea class="form-control"></textarea> </div> <div class="col-xs-5"> <textarea class="form-control"></textarea> </div> </div> </form>مخرجات الشيفرة السابقة: خصائص إضافيةكما أسلفنا سابقا بأن إطار العمل وفّر Boostrap الكثير من الميزات في التعامل مع النماذج جعلت من التحكم بالأدوات وتنسيقها شيئا سهلًا جدًا، وأضاف أيضًا ميزات لم تكن موجودة في النماذج مسبقا ومنها: إضافات لمدخلات Input بدلا من أن نضع نصّا توضيحيًا أو أيقونة إضافية، أصبح من المُمكن إضافة أيقونة توضيحية أو زر مناسب مدمج مع المُدخلات<input type="text">و <textarea>، ولا بد أولا من التنبيه إلى اتباع القواعد التالية عند كتابة الشيفرة: الوسم <input> والوسم <span> -الذي سنضع من خلاله الأيقونات- يجب أن يكونا ضمن الوسم <div> والذي يأخذ الصنف .input-groupالوسم <span> يأخذ الصنف .input-group-addonوهذه الشيفرة توضح ذلك: <form> <div class="row"> <div class="col-xs-4"> <div class="input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-user"></span> </span> <input type="text" class="form-control" placeholder="اسم المستخدم"> </div> </div> <div class="col-xs-4"> <div class="input-group"> <input type="text" class="form-control" placeholder="المبلغ"> <span class="input-group-addon">.00</span> </div> </div> <div class="col-xs-4"> <div class="input-group"> <span class="input-group-addon">$</span> <input type="text" class="form-control" placeholder="دولار أمريكي"> <span class="input-group-addon">.00</span> </div> </div> </div> </div> </form>وهذه مخرجات الشيفرة السابقة: ونستطيع أيضا أن نضيف إلى أدوات النصوص الكثير من العناصر الأخرى كأداة الاختيار checkbox أو radio لتصبح بهذا الشكل: وهذه شيفرة الشكل السابق: <form> <div class="row"> <div class="col-xs-6"> <div class="input-group"> <span class="input-group-addon"> <input type="checkbox"> </span> <input type="text" class="form-control"> </div> </div> <div class="col-xs-6"> <div class="input-group"> <span class="input-group-addon"> <input type="radio"> </span> <input type="text" class="form-control"> </div> </div> </div> </form>أو إضافة أزرار جانبية إلى أدوات النصوص أيضا لتكون كما بالشكل التالي: <form> <div class="row"> <div class="col-xs-6"> <div class="input-group"> <input type="text" class="form-control" placeholder="بحث عن…"> <span class="input-group-btn"> <button type="button" class="btn btn-default">ابحث</button> </span> </div> </div> <div class="col-xs-6"> <div class="input-group"> <span class="input-group-btn"> <button type="button" class="btn btn-default">زر حدث</button> <button type="button" class="btn btn-default">زر حدث آخر</button> </span> <input type="text" class="form-control" placeholder="ضع النص الذي تريد …"> </div> </div> </div> </form>ومن خصائص النماذج الإضافية التي توفرها الـ Bootstrap، خاصية إلغاء تفعيل مجموعة من العناصر مرة واحدة، فالأصل كما تعودنا عند التعامل مع النماذج باستخدام الـ html أنه يمكن إلغاء تفعيل عنصر واحد عن طريق الخاصية disabled أو readonly وهنا نستطيع أن نتعامل مع ذلك أيضا وإضافة إلى ذلك فنستطيع إلغاء مجموعة حقول عن طريق تضمينها في وسم <fieldset> ومن ثم إعطائه الخاصية disabled="disabled" أو readonly="readonly"، كما في المثال التالي: <form class="form-horizontal" role="form"> <fieldset disabled="disabled"> <div class="form-group"> <label for="inputtext"class="control-label col-md-2">اسم المستخدم:</label> <div class="col-md-10"> <input type="text" id="inputtext" class="form-control" placeholder="اسم المستخدم" /> </div> </div> <div class="form-group"> <label for="password" class="control-label col-md-2">كلمة المرور:</label> <div class="col-md-10"> <input type="password" id="password" class="form-control" placeholder="كلمة المرور"/> </div> </div> <div class="form-group"> <div class="col-xs-offset-2 col-xs-10"> <div class="checkbox" class="col-xs-offset-2 col-xs-10"> <label><input type="checkbox" />تذكرني على هذا المتصفح</label> </div> </div> </div> <div class="col-xs-offset-2 col-xs-10"> <input type="button" class="btn btn-primary btn-md" value="تسجيل الدخول"/> </div> </fieldset> </form>تنسيق مخصص لعناصر النموذجيوفر إطار العمل Bootstrap للمصمم خيارات متعددة لإعلام المستخدم بحالة الإدخال فمثلا التنبيه في حالة كانت البيانات صحيحة أو خاطئة أو تحذيره من النص المدخل أو اكتمال الإدخال بنجاح والشكل التالي يوضح ذلك: تنبيه المستخدم حسب صحة الإدخال وهذه شيفرة الشكل السابق: <form class="form-horizontal"> <div class="form-group has-success has-feedback"> <label class="col-xs-2 control-label" for="inputSuccess">اسم المستخدم</label> <div class="col-xs-10"> <input type="text" id="inputSuccess" class="form-control" placeholder="في حالة النجاح"> <span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span> </div> </div> <div class="form-group has-warning has-feedback"> <label class="col-xs-2 control-label" for="inputWarning">كلمة المرور</label> <div class="col-xs-10"> <input type="password" id="inputWarning" class="form-control" placeholder="في حالة التحذير "> <span class="glyphicon glyphicon-warning-sign form-control-feedback" aria-hidden="true"></span> </div> </div> <div class="form-group has-error has-feedback"> <label class="col-xs-2 control-label" for="inputError">البريد الإلكتروني</label> <div class="col-xs-10"> <input type="email" id="inputError" class="form-control" placeholder="في حالة الخطأ"> <span class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span> </div> </div> </form>كما تلاحظ في الشيفرة السابقة تم استعمل الصنف .has-* ليدل على حالة أداة النصوص وفي كل مرة استبدل * بالحالة المناسبة (warning- success- error…) واستخدم الصنف .has-feedback ليظهر الأيقونة حسب حالة أداة النص واستعمل الوسم <span> مع كل أداة لتظهر الأيقونة مصاحبة لأدوات الإدخال، بإمكانك الاستغناء عن الأيقونات وذلك بحذف الصنف .has-feedback والوسم <span> الذي يتعامل مع الأيقونة. عناصر النماذج التي يدعمها الـ Bootstrap:يتعامل الـ Bootstrap مع كل عناصر النماذج تقريبا تستطيع استعمال كافة الخصائص السابقة معها فهو يدعم: inputtextareacheckboxradioselectوالآن كل ما عليك فعله هو أن تقوم بفتح محرر النصوص لديك والبدء بمراجعة المقال وكتابة الشيفرة لتجرب أنت بنفسك كيفية التعامل مع العناصر في إطار العمل Bootstrap. يُمكن تحميل أمثلة هذا الدروس كملف مُرفق من هنا.1 نقطة
-
إذا أردت أن تُصمّم موقعًا مُتجاوبًا يسهل تصفّحه أيّا كان المُتصفّح المُستخدم ونظام التّشغيل، فإما أن تختار الطريق الأول والمُتمثّلة في القيام بكل كبيرة وصغيرة بنفسك، أو أن تسلك طريقًا مُختصرة عبر الاعتماد على إطار عمل HTML/CSS يُسهّل عليك المهمة. من بين أشهر أطر العمل التي أصبح تعلّمها وإتقانها ضروريًا نجد إطار عمل Bootstrap 3. سنحاول في هذه السلسلة (التي تقرأ أول دروسها) أن نشرح -ولو بشكل سريع- أهم ما تحتاج معرفته حول إطار عمل Bootstrap 3 لتُصمّم أول موقع لك باستخدامه. ملاحظة: لدى استخدام عبارة Bootstrap في هذه السلسلة فإننا نعني بذلك الإصدار الثالث منه. ما هو Bootstrap؟ Bootstrap عبارة عن إطار عمل HTML /CSS مُتجاوب. يحتوي Bootstrap على الأدوات والعناصر الأساسية التي ستحتاجها في أغلب مشاريعك مثل: الجداول والأزرار وأدوات النصوص والنماذج، والثانوية مثل: العنونة Heading وعناصر التنقل، والخلفيات، وغيرها من الأدوات. ويوفرBootstrap الكثير من الوقت والجهد على المصممين أثناء تصميم الصفحات، فكل ما يحتاجه المصمم هو معرفة أسماء الأصناف Classes التي سيتعامل معها لإعطاء التنسيق المناسب للعنصر الذي يستخدمه. بالإضافة إلى ذلك فإطار العمل Bootstrap يجعل التصميم مُناسبًا ومتجاوبًا مع كافة أحجام الشاشات المُختلفة. مميزات Bootstrap مميزات إطار العمل Bootstrap التي ساهمت في انتشاره: المحافظة على الوقت والجهد، فالتصميم المعد سلفا في إطار العمل هذا جعل كل ما على الصمم فعله هو أن يضع العناصر في المكان المناسب ويخصصها حسب الغرض الذي يريد. تصميم متجاوب Responsive ومتوافق مع كافة المتصفحات، فهذه الميزة تجعل الموقع الذي تقوم بإنشائه يظهر بشكل ملائم لكافة الأجهزة المختلفة في أحجامها وبنفس التنسيق والمظهر الذي تضعه، بالإضافة إلى توافق خصائص الـ CSS مع المتصفحات المختلفة وهذا يعني عدم تعارض أي جزء من التصميم مع المتصفحات، فيعتبر هذا توفيرًا آخر للجهد الذي ستبذله لتجربة التصميم على المتصفحات. سهل الاستخدام وتنسيق ثابت Consistent، فأي شخص لديه بعض الأساسيات في HTML وCSS يستطيع استخدام إطار العمل هذا وبسهولة، فقد لا تضطر إلى كتابة شيفرة CSS واحدة، وتوفر كذلك ميزة التنسيق الثابت في كل أجزاء الموقع، فالعمل على قالب معد مُسبقا لهذا الغرض سيجعل الموقع متناسق في مظهر المكونات بشكل خاص وفي تخطيط الموقع بشكل عام. بالإضافة إلى كل هذا فإطار العمل Bootstrap مفتوح المصدر بإمكانك الاطلاع على مكوناته ومحتوياته. تحميل ملفات الـ Bootstrap يمكنك تحميل آخر إصدار من إطار العمل Bootstrap من خلال الموقع الرسمي ، وأثناء كتابة هذا المقال كان آخر إصدار في الموقع الرسمي هو الإصدار الثالث. وعند تحميل ملف إطار العمل قم بفك الضغط على الملفات، وستجد ثلاثة مجلدات هي التركيبة الكاملة لإطار العمل Bootstrap. سنحتاج أيضا إلى ملف jQuery . قم بتحميل آخر إصدار منه وضعه داخل مجلدjs. الآن بعد حصولك على الملفات الأساسية التي يجب تضمينها في أي مشروع ويب تقوم بإنشائه، يمكننا البدء بإنشاء صفحة ويب بسيطة جدًا وندمج هذه الملفات مع الصفحة الجديدة لنهيء الصفحة وفقا لإطار العمل Bootstrap. تهيئة المشروع ضمن إطار العمل Bootstrap قم بإنشاء مجلد للمشروع الذي تريد أن تبدأ بالعمل عليه، وأنشء صفحة HTML عادية، تتضمن على الأقل المكونات الأساسية من رأس وجسم الصفحة، وهذه شيفرة يمكنك أن تبدأ بها: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>سلسلة مقالات bootstrap3 </title> </head> <body> <h1>مرحبا بالعالم!</h1> </body> </html> والآن لنقم بتعديل شيفرة الصفحة لتضمين ملفات إطار العمل، وأول شيء سنقوم بإضافته هو ملف الـ CSS داخل وسم الرأس <head> ولكن قبل ذلك ولنضمن أن يكون هناك تجاوب متطابق مع الشاشات سنضيف وسم الـ <meta> كما هو موضح في الشيفرة التالية: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"> <title>صفحة متجاوبة مع الأحجام المختلفة</title> </head> ... والآن لابد من تضمين ملفات الـ JavaScript وتوجد ضمن المجلد المسمى js ويتم ربطها بهذه الصفحة من خلال الوسم <script>، وسيتم وضع هذا الوسم قبل إغلاق وسم جسم الصفحة أي قبل الوسم </body> ويفضل أن تضعها ضمن الوسم <head>بعد إضافة روابط ملفات الـ CSS مع مراعاة إضافة ملف الـ jQuery كما يلي: <body> <h1>مرحبا بالعالم!</h1> <script src="js/ jquery-2.1.3.min.js"></script><script src="js/bootstrap.min.js"></script></body> </html> وبهذا تكون قد أعددت صفحتك الأولى لتكون ملائمة لإطار العمل Bootstrap، وهذا في حالة لم تكن متصلا بالإنترنت إما إذا كنت متصلا بالإنترنت أو تريد رفع المشروع إليه فقد ترغب في تغيير هذه الروابط واستبدالها بروابط مباشرة على مكتبات الـ CDN. لربط موقعك بهذه المكتبات سنضع الروابط التالية في كل وسم من الوسوم السابقة كما يلي: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> <title>سلسلة مقالات bootstrap3</title> </head> <body> <h1>مرحبا بالعالم!</h1> <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> </body> </html> إطار العمل Bootstrap ودعم اللغة العربية والتنسيق (rtl) تتوفر نسخة من إطارا لعمل Bootstrap خاصة بالمصممين الذين يصممون بالاتجاه من اليمين إلى اليسارrtl . بإمكانك تحميل الإصدار الأخير من هذه النسخة والعمل عليها إذا كنت تريد التصميم من اليمين إلى اليسار، أو تحميل الإصدار الثالث والمتوافق مع إطار العمل Bootstrap. أما كيفية ربط النسخة العربية مع إطار العمل Bootstrap3 فالشيفرة التالية توضح ذلك: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"> <link rel="stylesheet" type="text/css" href="css/bootstrap-rtl.css"> <title>(صفحة متجاوبة مع الأحجام المختلفة باللغة العربية) - bootstrap3</title> </head> وبهذا نكون قد تعرفنا سويا على إطار العمل Bootstrap3 وأخذت نظرة شاملة حول المميزات التي يقدمها والتسهيلات التي يوفرها، وتعرفت أيضا على كيفية تحميل إطار العمل وكيفية تهيئته وبهذا ستكون مستعد لتصميم مشاريعك بكل سهولة ويسر. وسنتعرف الآن سويا على النظام الذي يتبعه الـ Bootstrap لتقسيم الصفحة. النظام الشبكي Grid system يقسم النظام الشبكي في إطار العمل Bootstrap الصفحة إلى 12 عمودًا أفقيًّا تتناسب ومقاسات الشاشات المختلفة، ويحتوي النظام الشبكي على عدة أحجام مختلفة (xs, sm, md, lg ) مُخصّصة للأجهزة المحمولة والأجهزة اللوحية والمكتبية والشاشات الكبيرة. تستطيع أن تضع العناصر المناسبة داخل كل عمود من هذه الأعمدة. بإمكانك استخدامها كاملة أو أن تستخدم أعمدة لها أحجام مجموعها مساوٍ لـ 12 عمود والشكل التالي يمثل بعض أحجام الأعمدة المستخدمة في تقسيم أجزاء الصفحة. الأصناف المتبعة في النظام الشبكي لـBootstrap هناك عدة أصناف مختلفة تستطيع أن تستخدمها مع كل عمود من أعمدة النظام الشبكي ليُصبح مُتجاوبًا مع كل أحجام الشاشات كما يلي: الصنف xs مخصص للشاشات الصغرى (الهواتف المحمولة) ذات الحجم 768px أو أقل أو أثناء تصغير عرض المتصفح إلى أقصى درجة ممكنة. الصنف sm مخصص للشاشات الصغيرة (الأجهزة اللوحية) ذات الحجم 992px – 768px. الصنف md مخصص للشاشات المتوسطة الحجم (الأجهزة المكتبية والحواسيب المحمولة) ذات الحجم من 1200px – 993px. الصنف lg مخصص للشاشات الكبيرة (الأجهزة المكتبية الكبيرة) ذات حجم أكبر من 1200px. المثال التالي يوضح استخدام النظام الشبكي في إطار العمل Bootstrap: <div class="container"> <div class="row"> <div class="col-sm-6 col-md-7 col-lg-9"> <div class="well"> </div> </div> <div class="col-sm-6 col-md-5 col-lg-3"> <div class="well"></div> </div> </div> <hr /> <div class="row"> <div class="col-sm-6 col-md-2 col-lg-5"> <div class="well"></div> </div> <div class="col-sm-6 col-md-10 col-lg-7"> <div class="well"></div> </div> </div> </div> أولًا، لابد من وضع إطار خارجي يحتوي كل العناصر بداخله ويساعد هذا الإطار في أن تكون العناصر متلائمة مع بعضها ونضع لها حدودًا مع العناصر الأخرى المحيطة ويتم ذلك باستخدام الصنف .container أو .container-fluid في الوسم <div>، ومن ثم نضع صفًا يحوي كل الأعمدة المراد إضافتها وذلك باستخدام الصنف row في وسم <div> آخر، وأخيرا تستطيع أن تضع الأعمدة كل عمود بشكل منفصل في الوسم <div> وتستخدم الصنف .col-*-*، بداية نحدد أي نوع من الأصناف سنختار .col-xs-* أو .col-sm-* أو .col-md-* أو .col-lg-* أو كل هذه الأصناف مجتمعة ومن ثم نحدد حجم كل عمود باستبدال الرمز * بالرقم المناسب. الصنف well. لإعطاء خلفية ومظهر للأعمدة المضافة. قد تلاحظ وجود فواصل بين الأعمدة في حالة أن قمت بتطبيق المثال، وذلك يرجع إلى التقسيم المميز في إطار العمل Bootstrap3. ومما سبق نستنتج أنه للتعامل مع النظام الشبكي يتوجب اتباع القواعد التالية: أن تكون الصفوف ضمن الصنف container. أو container-fluid. لإعطاء النظام الشبكي حدود خارجية ومسافات بين العناصر داخله. نستخدم الصنف.row لإنشاء مجموعات من الأعمدة الأفقية(المتجاورة). الأعمدة هي الأبناء الوحيدة للصفوف أي أن الصفوف لا تحتوي على أي عنصر مباشر غير الأعمدة ويجب أن تكون بقية عناصر الصفحة ضمن الأعمدة. ملاحظة: عندما تبدأ بالتصميم يفضل أن تصمم لأجهزة المستخدمين الأكثر زيارة للموقع حسب توقعاتك، سواء كانت أجهزة الهواتف المحمولة ذات الحجم الصغير أو الأجهزة المكتبية ذات الحجم الكبيرة، وبعد ذلك أضف الأصناف التي تجعل تصميمك متجاوب مع بقية الأجهزة. إذا أردت أن يكون التصميم لحجم شاشة معين اتبع التعليمات التالية: شاشات الأجهزة الصغيرة استعمل النسبة 25%-75% مع الصنف col-sm-*: <div class="col-sm-3"> </div> <div class="col-sm-9"> </div> شاشات الأجهزة اللوحية استعمل النسبة 50%-50% مع الصنف col-md-*: <div class="col-md-6"> </div> <div class="col-md-6"> </div> شاشات الأجهزة المكتبية والأجهزة المحمولة وكذلك شاشة الأجهزة الكبيرة استعمل النسبة 33%-66% مع الصنف col-lg-*: <div class="col-md-4"> </div> <div class="col-md-8"> </div> أما إذا كنت تريد من التصميم أن يكون متجاوبًا مع كافة الأجهزة فقم بدمج جميع الأجزاء السابقة: <div class="col-sm-3 col-md-6 col-lg-4"> </div> <div class="col-sm-9 col-md-6 col-lg-8"> </div> ويوفر إطار العمل Bootstrap ميزة إضافية تستطيع أن تضيفها في النظام الشبكي وهي إظهار أو إخفاء الصفوف، فتستطيع أن تستعمل هذه الميزة لإظهار عمود في الشاشات الكبيرة وإخفائه في الشاشات الصغيرة إذا كان لا يتناسب وحجمها: <div class="visible-sm col-md-6 col-lg-4"> </div> <div class="hide-sm col-md-6 col-lg-8"> </div> إزاحة offset الأعمدة نستطيع تحريك الأعمدة وإزاحتها بمقدار معين لتوفير مسافة كافية بين الأعمدة داخل النظام الشبكي أو بين الأعمدة والعناصر الأخرى، وذلك باستخدام الصنف col-*-offset-*، مثال، col-md-offset-4 إزاحة عمود من نوع md بمقدار 4 أعمدة. لزم التنبيه إلى أن هذه الخاصية لا تدعم الشاشات الصغيرة أي أن الصنف من النوع xs لا يتعامل مع هذه الخاصية لذا يجب مراعاة ذلك في التصميم المتجاوب. <div calss="row"> <div class="col-xs-2 col-md-offset-1"> <div class="well"> <h3>تمت الإزاحة بمقدار عمود واحد من أصل 12</h3> <h5>العمود الأول في الصف</h5> </div> </div> <div class="col-xs-6 col-md-offset-3"> <div class="well"> <h3>وهذا العمود تمت إزاحته أيضا</h3> <h5>لا نستطيع إضافة أي عمود داخل هذا الصف لإن مجموع أحجام الأعمدة ومجموع الإزاحة = 12</h5> <h6>العمود الثاني في الصف</h6> </div> </div> </div> وتكون المخرجات بهذا الشكل: أعمدة داخل أخرى يوفر Bootstsrap3 ميزة أخرى يمكن إضافتها في النظام الشبكي وهي ميزة تداخل الأعمدة، أي نضع عدة أعمدة داخل عمود واحد. في البداية لا بد من إضافة صف يضم الأعمدة الداخلية، وفي هذا الصف يتاح استخدام 12 عمودًا داخليّا أو أعمدة مجموع أحجامها مساوٍ لـ 12 عمودًا كما هو الحال في الصف الخارجي وليس بالضرورة استخدامها جميعا: مثال يوضح تداخل الأعمدة في النظام الشبكي: <div class="row"> <div class="col-md-6"> <div class="well"> <h5>العمود الخارجي</h5> <div class="row"> <div class="col-sm-3 col-md-6 col-lg-4"> <div style="Background-color:Gray;"> <h5>العمود الداخلي 1</h5> <h3>أبجد هوز أبجد هوز أبجد هوز </h3> </div> </div> <div class="col-sm-9 col-md-6 col-lg-8"> <div style="Background-color:Gray;"> <h5>العمود الداخلي 2</h5> <h3>أبجد هوز أبجد هوز أبجد هوز </h3> </div> </div> </div> </div> </div> </div> وتكون المخرجات بهذا الشكل: ترتيب الأعمدة بإمكانك ترتيب الأعمدة في النظام الشبكي باستخدام الصنف col-md-pull-* والصنف col-md-push-*، وترتيب الأعمدة هنا يعني أنك تكتب الشيفرة بترتيب معين ويكون الناتج بترتيب مغاير، أي أن العمود الأول في الشيفرة سيصبح الثاني والعكس صحيح، ويجب مراعاة حجم الأعمدة فإذا كان حجم العمود الأول 4 والعمود الثاني 8 فيجب أن يكون العكس في الصنف المستخدم للترتيب، كما في المثال التالي: <div class="row"> <div class="col-md-4 col-md-push-8"> <div class="well"> <h4>كان هذا العمود في الجهة اليمنىh4> </div> </div> <div class="col-md-8 col-md-pull-4"> <div class="well"> <h4>كان هذا العمود في الجهة اليسرى وأثناء العرض أصبح في الجهة اليسرى </h4> </div> </div> </div> وتكون المخرجات بهذا الشكل: وبهذا نكون قد أخذنا مقدمة تعريفية حول إطار العمل Bootstrap وكيفية استخدام النظام الشبكي.1 نقطة
-
ملاحظة: يمكن تحميل الملفات المصدرية لكامل هذه السلسلة عبر حساب أكاديمية حسوب على Github، يمكن أيضا تحميل ملف APK لتجريب اللعبة على أجهزة Android. استقبال مدخلات شاشة اللمساستقبال المدخلات من شاشة اللمس تختلف عن استقبال مدخلات الفأرة أو لوحة المفاتيح. فأنت هنا تتعامل مع شاشة تستقبل عدة لمسات، وتتعامل مع أحداث مثل وضع الإصبع وتحريكه ورفعه، أو وضع أصبعين وتقريبهما أو إبعادهما عن بعضهما. كل هذه الأنماط من الإدخال سيكون عليك التعرف عليها وتنفيذ ما يناسبها من أوامر. لنبدأ أولا مع مدخلات عناصر واجهة المستخدم مثل الأزرار. ما الذي يجب علينا فعله لاستقبال المدخلات على هذه العناصر؟ لا شيء! فهذا الأمر يقوم به محرك Unity تلقائيا. أي أنك عندما تلمس زرا على الشاشة سيتعرف التطبيق على هذا الأمر كأنك ضغطت على الزر وينفذ الأمر أو الأوامر المرتبطة به. لننتقل الآن للمدخلات الخاصة باللعبة. تذكر أننا قمنا بكتابة 3 بريمجات لاستقبال مدخلات الفأرة، وسنحتاج الآن لكتابة 3 مقابلها لاستقبال مدخلات شاشة اللمس. هذه البريمجات الثلاث هي: CameraMouseInput والذي أضفناه لقوالب عناصر الخلفية والأرضية من أجل تحريك الكاميرا والتحكم بتقريبها وإبعادها.LauncherMouseInput والذي أضفناه على قالب المقلاع بحيث يستقبل مدخلات اللاعب على المقذوفات ويحدد اتجاه التصويب وشدته ويطلق المقذوف حين إفلاته.SpecialAttackMouseInput والذي أضفناه على قوالب المقذوفات من أجل تنفيذ الهجوم الخاص عند الضغط على زر الفأرة بعد الإطلاق.الموضوع ببساطة شديدة أننا مقابل كل بريمج إدخال من الفأرة سنكتب بريمج إدخال من شاشة اللمس ونضيفه على نفس القالب. القاسم المشترك بين قوالب استقبال مدخلات اللمس أنها ستقوم بالتحقق من بيئة تشغيل اللعبة، فإذا وجدت أن نظام التشغيل هو Android ستقوم بتدمير بريمجات استقبال مدخلات الفأرة الموجودة معها على نفس الكائن. أهمية هذه الخطوة تكمن في أن Unity يحاول محاكاة وجود فأرة على شاشات اللمس عن طريق تحويل اللمسات إلى مدخلات فأرة. هذا الأمر يؤدي إلى سلوك غير مرغوب لا يفيد في لعبتنا، لذا نتجنبه عن طريق حذف أي بريمج يقرأ من الفأرة. لنبدأ مع بريمج التحكم بالكاميرا CameraTouchInput والذي سنضيفه على قالبي عنصري الخلفية والأرضية حيث يوجد CameraMouseInput أيضا. هذا البريمج موضح في السرد التالي: using UnityEngine; using System.Collections; public class CameraTouchInput : MonoBehaviour { //سرعة تحريك الكاميرا public float movementSpeed = 0.0075f; //سرعة التقريب والإبعاد public float zoomingSpeed = 0.00075f; //هي يلمس اللاعب الشاشة حاليا بإصبع واحد؟ private bool singleTouch = false; //هل يلمس اللاعب الشاشة حاليا بأصبعين private bool doubleTouch = false; //مرجع لبريمج التحكم بالكاميرا CameraControl camControl; //تستدعى مرة عند بداية التشغيل void Start() { //قم بتدمير بريمج استقبال مدخلات الفأرة إن تم اكتشاف نظام تشغيل الهاتف الذكي if (Application.platform == RuntimePlatform.Android) { CameraMouseInput mouseInput = GetComponent<CameraMouseInput>(); Destroy(mouseInput); } camControl = FindObjectOfType<CameraControl>(); } //يتم استدعاؤها مرة عند تصيير كل إطار في وقت متأخر void LateUpdate() { UpdateSingleTouch(); UpdateDragging(); UpdateDoubleTouch(); UpdateZooming(); } //تتأكد من كون اللاعب يلمس الشاشة بإصبع واحد void UpdateSingleTouch() { if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if (playerTouch.phase == TouchPhase.Began) { //قام اللاعب للتو بوضع إصبعه على الشاشة //هل تم وضع الإصبع على هذا الكائن تحديدا؟ Vector2 touchPos = Camera.main.ScreenToWorldPoint(playerTouch.position); //اجلب مكوّن التصادم الخاص بهذا الكائن Collider2D myCollider = GetComponent<Collider2D>(); //قم بتوليد شعاع قصير جدا ابتداء من موقع اللمس وباتجاه الأعلى واليمين //ومن ثم تحقق من كون هذا الشعاع قد اصطدم بمكوّن التصادم الخاص بهذا الكائن RaycastHit2D hit = Physics2D.Raycast(touchPos, Vector2.one, 0.1f); if (hit.collider == myCollider) { //نعم لقد قام اللاعب بلمس هذا الكائن بإصبع واحد singleTouch = true; } } else if (playerTouch.phase == TouchPhase.Ended || playerTouch.phase == TouchPhase.Canceled) { //قام اللاعب للتو برفع إصبعه عن الشاشة singleTouch = false; } } else { //عدد الأصابع على الشاشة لا يساوي 1 أي أنه //لا يوجد هناك لمسة بإصبع واحد singleTouch = false; } } //تقوم بفحص تحريك اللاعب لإصبع واحد على الشاشة void UpdateDragging() { if (singleTouch) { Touch playerTouch = Input.touches[0]; camControl.Move(playerTouch.deltaPosition * -movementSpeed); } } //تقوم بفحص قيام اللاعب باللمس بأصبعين void UpdateDoubleTouch() { //تأكد من عدم وجود لمسة بإصبع واحد حاليا if (!singleTouch) { if (Input.touchCount == 2) { doubleTouch = true; } else { doubleTouch = false; } } } //تقوم بتحديث التقريب والإبعاد مستخدمة حركة الأصبعين على الشاشة void UpdateZooming() { if (doubleTouch) { //على الشاشة A, Bمواقع الأصبعين المسميين //في كل من الإطار الحالي 2 والإطار السابق 1 Vector2 posA1, posA2, posB1, posB2; Touch a, b; a = Input.touches[0]; b = Input.touches[1]; posA2 = a.position; posB2 = b.position; posA1 = a.position - a.deltaPosition; posB1 = b.position - b.deltaPosition; //تأكد من كون المسافة بين الأصابع قد زادت أو قلت منذ //الإطار السابق float currentDist = Vector2.Distance(posA2, posB2); float prevDist = Vector2.Distance(posA1, posB1); //طرح المسافة السابقة من الحالية سيعطينا //الإشارة الصحيحة للتقريب أو الإبعاد camControl.Zoom((currentDist - prevDist) * zoomingSpeed); } } } آلية عمل هذا البريمج تعتمد على أربعة خطوات رئيسية: التحقق من لمس الشاشة بإصبع واحد.ثم التحقق من تحريك الكاميرا باستخدام الإصبع.ثم التحقق من لمس الشاشة بأصبعين.وأخيرا التأكد من تنفيذ التقريب والإبعاد باستخدام الأصبعين.قراءة مدخلات شاشة اللمس تتم كالآتي: أولا نتعرف على عدد اللمسات على الشاشة عن طريق المتغير Input.touchCount، فإذا كان عدد اللمسات يساوي واحدا، فإن هذا يعني أن اللاعب يضع إصبعا على الشاشة واحتمال أن يقوم بتحريك الكاميرا وارد. نستخدم هنا المتغيرين singleTouch و doubleTouch من أجل تخزين عدد اللمسات التي اكتشفناها. هذه اللمسات تكون مخزنة في المصفوفة Input.touches وهي مصفوفة تحتوي على عناصر من نوع Touch. هذا النوع من المتغيرات يحتوي على معلومات عن كل لمسة على الشاشة. أول هذه المعلومات التي سنتعامل معها هي Touch.phase والتي تمثل المرحلة التي تمر بها اللمسة. فبمجرد أن يضع اللاعب إصبعه على الشاشة ستكون المرحلة هي TouchPhase.Began. اللحظة الأولى للمس الشاشة مهمة جدا، حيث أنها اللحظة التي يجب علينا أن نتحقق من كون اللاعب قد وضع إصبعه على عنصر الخلفية أو الأرضية، وبالتالي نحدد إذا ما كنا سنسمح له بتحريك الكاميرا. فنحن لا نرغب بتحريك الكاميرا إذا كان اللاعب قد وضع إصبعه على المقذوف أو على زر الخروج مثلا. التحقق من كون اللاعب قد وضع يده على عنصر الخلفية أو الأرضية يتم عبر الدّالة ()UpdateSingleTouch، حيث علينا أن نقوم أولا بتحويل موقع الإصبع من إحداثيات الشاشة إلى إحداثيات المشهد تماما كما سبق وفعلنا مع مؤشر الفأرة. بعد ذلك نقوم باستخراج مكوّن التصادم الخاص بهذا العنصر ومن ثم نستخدم بث الأشعة Ray Casting. بث الأشعة طريقة يستخدمها محرك الفيزياء من أجل الكشف عن تقاطع خط مستقيم مع كائن ما في المشهد، وسنستخدمها هنا لنرسم خطا قصيرا جدا من موقع اللمس إلى نقطة شديدة القرب منه، ونرى إن كان هذا الخط يتقاطع مع مكوّن التصادم الذي استخرجناه. يتم تنفيذ بث الأشعة عن طريق الدّالة ()Physics2D.Raycast والتي تأخذ 3 متغيرات: المتغير الأول هو موقع بداية الشعاع، والمتغير الثاني هو الاتجاه الذي سيسير فيه هذا الشعاع، بينما يحدد المتغير الثالث وهو قيمة رقمية أقصى مسافة يمكن أن يقطعها هذا الشعاع. وهنا تلاحظ استخدامنا لمسافة قصيرة جدا، وهي كافية حين يكون موقع البداية موجودا أصلا داخل مكوّن التصادم الذي يتم فحص التصادم معه. القيمة التي ترجعها هذه الدّالة هي من نوع RaycastHit2D، وهي تحتوي على متغير لتخزين مكوّن التصادم الذي اصطدم به الشعاع. بعد ذلك نفحص إذا ما كان المكوّن الذي اصطدم به الشعاع هو نفسه مكوّن التصادم الذي استخرجناه من العنصر الحالي، وإذا تحقق هذا الأمر فإننا نعتمد هذا اللمسة من قبل اللاعب على الخلفية أو الأرضية ونسمح له بالتالي بتحريك الكاميرا عن طريق تغيير قيمة singleTouch إلى true. في حالة كانت اللمسة في مرحلة أخرى مثل TouchPhase.Ended أو TouchPhase.Canceled، فإن هذا يعني أن اللاعب قد رفع إصبعه عن الشاشة، وبالتالي نعيد قيمة singleTouch إلى false. الأمر نفسه سيحدث في حال اكتشفنا أن عدد الأصابع الموجودة على الشاشة Input.touchCount لا يساوي واحدا، بالتالي لن نسمح للاعب في هذه الحالة بتحريك الكاميرا. الدّالة ()UpdateDragging هي المسؤولة عن تحريك الكاميرا، لذا عليها أن تتأكد أولا من قيمة singleTouch وبعد ذلك تقوم بتحريك الكاميرا بالمقدار playerTouch.deltaPosition مضروبا في سرعة الحركة. لاحظ أننا هنا لا نحتاج لتخزين موقع اللمسة السابق حيث أن قيمة الإزاحة تأتينا مباشرة بعكس ما كان عليه الحال حين التعامل مع مؤشر الفأرة. بعد ذلك تقوم الدّالة ()UpdateDoubleTouch بالتحقق من كون اللاعب يضع أصبعين على الشاشة، وفي هذه الحالة تقوم مباشرة بتغيير قيمة doubleTouch إلى true. لاحظ أن اللمس بأصبعين ليس له أي مدلول في اللعبة سوى التقريب والإبعاد بخلاف اللمسة الواحدة التي يمكن أن تستخدم لأكثر من غرض. ولهذا السبب لا نحتاج للتحقق من مواقع الأصبعين بل يكفي وجودهما لمنع أي مدخلات أخرى غير التقريب والإبعاد. أخيرا تقوم الدّالة ()UpdateZooming بالتأكد من وجود أصبعين على الشاشة عبر المتغير doubleTouch وبناء عليها تحسب 4 مواقع وهي كالتالي: posA1: موقع الإصبع الأول خلال الإطار السابق.posA2: موقع الإصبع الأول خلال الإطار الحالي.posB1: موقع الإصبع الثاني خلال الإطار السابق.posB2: موقع الإصبع الثاني خلال الإطار الحالي.لاحظ أننا قمنا بطرح الإزاحة من مواقع الأصابع الحالية حتى نحصل على مواقع الأصابع في الإطار السابق، وذلك لأننا لم نقم بتخزين هذه المواقع من الأساس. بعد ذلك نحسب المسافة بين الأصبعين في الإطار السابق prevDist والإطار الحالي currentDist. تذكر أن الدّالة ()Zoom في البريمج CameraControl تقوم بالتقريب إذا أعطيناها قيمة سالبة وبالإبعاد إذا أعطيناها قيمة موجبة. من أجل ذلك نقوم بطرح المسافة السابقة من المسافة الحالية وضرب الناتج في سرعة التقريب والإبعاد zoomingSpeed. بهذه الطريقة نضمن الحصول على قيمة موجبة إذا حرك اللاعب أصبعيه بعيدا عن بعضهما مما يؤدي للتقريب وقيمة سالبة إذا قرب اللاعب أصبعيه من بعضهما مما يؤدي للإبعاد، وهذا السلوك بطبيعة الحال هو المعتاد عند مستخدمي الهواتف الذكية والأجهزة اللوحية. البريمج الثاني الذي سنتناوله في موضوع استقبال مدخلات شاشة اللمس هو الخاص بإطلاق المقذوفات. تذكر أننا قمنا بإضافة بريمج يسمى LauncherMouseInput على قالب مقلاع إطلاق المقذوفات. البريمج الجديد يسمى LauncherTouchInput وسنقوم بإضافته على نفس القالب من أجل تمكين اللاعب من إطلاق المقذوفات عن طريق اللمس. السرد التالي يوضح هذا البريمج: using UnityEngine; using System.Collections; public class LauncherTouchInput : MonoBehaviour { //مرجع لبريمج إطلاق المقذوفات private Launcher launcher; //تستدعى مرة واحدة عند بداية التشغيل void Start () { //تقوم بتدمير بريمج قراءة مدخلات الفأرة في حال اكتشاف نظام تشغيل الهاتف if (Application.platform == RuntimePlatform.Android) { LauncherMouseInput mouseInput = GetComponent<LauncherMouseInput>(); Destroy(mouseInput); } launcher = GetComponent<Launcher>(); } //تستدعى مرة عند تصيير كل إطار void Update () { UpdateTouchStart(); UpdateDragging(); UpdateRelease(); } //تقوم بالتحقق من كون اللاعب قد وضع اصبعا واحدا //على المقذوف الحالي void UpdateTouchStart() { Projectile currentProj = launcher.currentProjectile; if (currentProj == null) { //لا يوجد ما يمكن فعله return; } if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if (playerTouch.phase == TouchPhase.Began) { //قام اللاعب للتو بلمس الشاشة // تحقق من كون عملية اللمس تمت داخل حدود المقذوف Vector2 touchPos = Camera.main.ScreenToWorldPoint(playerTouch.position); //استخرج مكوّن التصادم الخاص بالمقذوف الحالي Collider2D projectileCollider = currentProj.GetComponent<Collider2D>(); if (projectileCollider.bounds.Contains(touchPos)) { //تمت عملية اللمس داخل حدود المقذوف بالتالي يجب إمساكه launcher.HoldProjectile(); } } } } //تقوم بالتحقق من تحريك اللاعب لإصبعه على الشاشة أثناء إمساك المقذوف void UpdateDragging() { if (Input.touchCount == 1) { Vector2 touchWorldPos = Camera.main.ScreenToWorldPoint(Input.touches[0].position); launcher.DragProjectile(touchWorldPos); } } //تتحقق من رفع اللاعب إصبعه عن الشاشة void UpdateRelease() { if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if (playerTouch.phase == TouchPhase.Ended || playerTouch.phase == TouchPhase.Canceled) { launcher.ReleaseProjectile(); } } } } ينفذ هذا البريمج ثلاث خطوات في كل عملية تحديث: الخطوة الأولى عبر الدّالة ()UpdateTouchStart والتي تتحقق من كون اللاعب قد لمس الشاشة للتو مستخدما إصبعا واحدا. في هذه الحالة تقوم الدّالة بحساب موقع اللمسة في فضاء المشهد ومن ثم فحص ما إذا كان هذا الموقع ضمن حدود مكوّن التصادم الخاص بالمقذوف الحالي المتواجد على مقلاع الإطلاق. إذا كانت هذه اللمسة فعلا داخل حدود المقذوف فهذا يعني أن اللاعب يريد إمساكه، وبالتالي تقوم الدّالة بإمساك المقذوف عبر استدعاء ()HoldProjectile من البريمج Launcher.الخطوة الثانية التي تنفذ عبر ()UpdateDragging تتعلق بوجود إصبع واحد على الشاشة، حيث تقوم بحساب موقع الإصبع في فضاء المشهد وتطلب من البريمج Launcher تحريك المقذوف الحالي إلى هذا الموقع. تذكر أن الأمور الأخرى مثل التأكد من وجود مقذوف أو إذا ما كان ممسوكا أو تم إطلاقه تتم من خلال البريمج Launcher نفسه بالتالي لا نحتاج لفحصها هنا، ولعلك تذكر أننا لم نفحصها أيضا في بريمج قراءة مدخلات الفأرة.أخيرا تقوم الدّالة ()UpdateRelease بالتحقق من كون اللاعب قد رفع إصبعا واحدا عن الشاشة، وذلك من خلال فحص مرحلة اللمس playerTouch.phase إذا ما كانت تساوي Ended أو Canceled وهما الحالتان المتوقعتان حال رفع الإصبع. عند التأكد من هذا الأمر تقوم باستدعاء دالّة إطلاق المقذوف ()ReleaseProjectile.البريمج الأخير الذي يقرأ مدخلات شاشة اللمس هو البريمج الخاص بتنفيذ الهجوم الخاص للمقذوف بعد إطلاقه. هذا الهجوم يتم عبر لمس الشاشة مرة واحدة في أي موقع بعد إطلاق المقذوف. هذا البريمج يسمى SpecialAttackTouchInput ويجب أن تتم إضافته لجميع قوالب المقذوفات التي أنشأناها. هذا البريمج موضح في السرد التالي: using UnityEngine; using System.Collections; public class SpecialAttackTouchInput : MonoBehaviour { //تستدعى مرة واحدة عند بداية التشغيل void Start () { //قم بتدمير بريمج قراءة مدخلات الفأرة في حال اكتشاف نظام تشغيل الهاتف if (Application.platform == RuntimePlatform.Android) { SpecialAttackMouseInput mouseInput = GetComponent<SpecialAttackMouseInput>(); Destroy(mouseInput); } } //تستدعى مرة واحدة عند تصيير كل إطار void Update () { if (Input.touchCount == 1) { Touch playerTouch = Input.touches[0]; if(playerTouch.phase == TouchPhase.Began) { SendMessage("PerformSpecialAttack"); } } } } يمكنك ملاحظة مدى بساطة هذا البريمج، حيث أن كل ما يفعله هو إرسال الرسالة PerformSpecialAttack في حال قام اللاعب بلمس الشاشة مرة واحدة. بهذا تكون اللعبة مكتملة لأجهزة الحاسب والهواتف الذكية، وبقي علينا تصديرها على شكل تطبيق مستقل. تصدير اللعبة بعد إكمالهايوفر محرك Unity إمكانية تصدير الألعاب على مجموعة كبيرة من المنصات، وما يهمنا منها الآن هو منصتا الحاسب الشخصي والهواتف الذكية وتحديدا الأجهزة التي تعمل بنظام Android. تصدير اللعبة يتم عن طريق النافذة التي حددنا منها ترتيب المشاهد وهي: File > Build Settings بالنسبة للتصدير للحواسيب وأجهزة Mac اختر من القائمة اليسرى PC, Max & Linux Standalone لتظهر أمامك الخيارات التالية: أهم هذه الخيارات هو Target Platform والذي تحدد من خلاله نظام التشغيل المستهدف وخيار Architecture والذي يحدد نوع النظام التشغيل سواء كان 32 أو 64 بت. من المهم الانتباه إلى أن الخيار x86_64 يجعل اللعبة تعمل فقط على أنظمة 64 بت حيث أن وجود x86 في الاسم قد يضلل أحيانا فتظن أنه يشمل النظامين. إن كنت تستهدف النظامين 32 و 64 فابق على الخيار الأول x86. بعد ذلك يمكنك الضغط على Build ثم تختار مكان التخزين لتبدأ بعدها عملية التصدير. بالنسبة للتصدير للهواتف الذكية الموضوع أصعب قليلا. سأتحدث هنا بالتفصيل عن طريقة التصدير لمنصة Android فقط لأنني للأسف لا أملك خبرة في التعامل مع أنظمة iOS. قبل التصدير لهذا النظام علينا القيام بتجهيز بعض الأدوات. الخطوة الأولى هو تحميل وتثبيت Android SDK وستحتاج هنا للإصدار الخامس حيث أن الإصدار الخامس من محرك Unity يحتاج لهذه النسخة. يمكنك تحميل المكتبات اللازمة من هذا الرابط https://developer.android.com/sdk/index.html#Other. عند التثبيت يفضل أن تختار موقعا سهلا مثل d:\AndroidSDK. بعد تثبيت Android SDK على جهازك عليك أن تقوم بتنزيل مكتبة واحدة على الأقل عن طريق تشغيل SDK Manager وهو التطبيق المصاحب لـ Android SDK. كل ما تحتاج إليه هنا هو اختيار SDK Platform للإصدار الأخير (حتى كتابة هذه الدروس الإصدار الأخير هو API22 5.1.1). وذلك موضح في الصورة التالة: بعد تنزيل وتثبيت المكتبة علينا أن نخبر Unity عن موقعها وذلك عبر الخيار: Edit > Preferences ومن ثم اختيار External Tools من القائمة اليسرى. بعدها يمكنك تحديد المجلد الذي قمت بتثبيت Android SDK فيه عن طريق الخيار Android SDK Location كما ترى هنا: بما أن اللعبة ستعمل على شاشة الهاتف، يجب علينا أن نجبر النظام على تشغيلها في الوضع الأفقي وليس العمودي. هذا الخيار يمكن ضبطه من خلال القائمة: Edit > Project Settings > Player ومن ثم اختيار رمز نظام Android وفتح مجموعة الإعدادات المسماة Resolution and Presentation. بعدها يجب ضبط Default Orientation على الخيار Landscape Left كما هو موضح في الصورة التالية: الخطوة الأخيرة قبل التصدير هي تحديد معرف الحزمة، وهو عبارة عن اسم على شكل عنوان موقع إنترنت معكوس يبدأ بعنوان موقع الناشر وينتهي باسم المنتج، مثل com.Hsoub.Academy.AngryAnimals. قد تبدو هذه الطريقة في التعريف غريبة بعض الشيء، لكنها موروثة من طريقة تعريف الحزم البرمجية بلغة Java والتي تعتبر اللغة الرئيسية لبرمجة التطبيقات على نظام Android. لا يشترط طبعا أن يكون موقع الإنترنت المستخدم حقيقيا، لكن المهم هو أن تتبع هذا التنسيق في تعريف الحزمة. لإضافة معرّف الحزمة ادخل إلى القائمة: Edit > Project Settings > Player ومن ثم اختر رمز نظام Android من نافذة الخصائص وافتح مجموعة الإعدادات المسماة Other Settings كما هو موضح في الصورة التالية: يمكنك بعدها كتابة معرّف الحزمة في الخانة PlayerSettings.bundleIdentifier كما يمكنك تحديد الإصدار الأدنى الذي يدعمه التطبيق. يستحسن أن تضبط التوافق على الإصدار 4.0 من النظام حيث أنه لا زال شائعا في معظم الأجهزة المتوفرة. بعدها يمكنك أخيرا العودة لشاشة التصدير: File > Build Settings واختيار Android من القائمة اليسرى ومن ثم الضغط على Build واختيار موقع التصدير. سيكون الملف الناتج من نوع APK والذي يمكنك نسخه لجهازك المحمول وتنزيله وتشغيله. قد تضطر لتغيير إعدادات الجهاز حتى يسمح بتنزيل تطبيقات مجهولة المصدر (أي من مصدر غير متجر Google Play) وهذه الإعدادات تختلف من جهاز لآخر. بالنسبة لأجهزة Samsung ستجد هذا الخيار في أعدادات الحماية تحت بند إدارة الجهاز كما هو موضح هنا: تهانينا! لقد قمت ببناء وتصدير لعبة كاملة على هاتفك الذكي أو جهازك اللوحي، ويمكنك الاستمتاع بلعبها ومشاركتها مع أصدقائك.1 نقطة
-
نبذة مختصرة عن صناعة الألعاب وتطويرها لعل صناعة الألعاب هي إحدى أصعب الصناعات في هذا العصر، وذلك من عدة نواح تبدأ بالتحديات التقنية، مرورا بجمهور صعب الإرضاء ولا يرحم حتى كبريات الشركات إن لم تكن منتجاتها بالمستوى المطلوب، وليس انتهاءا بالمنافسة الشرسة ونسب الفشل العالية وصعوبة تحقيق أرباح تغطي تكاليف الإنتاج المرتفعة. على الجانب الآخر يوجد ميزات لهذه الصناعة تجعل من النجاة فيها أمرا ممكنا، فعلى الجانب التقني مثلا، لا تخلوا الغالبية العظمى من الألعاب من وظائف متشابهة وأنماط متكررة من معالجة البيانات، مما يجعل إعادة استخدام الوحدات البرمجية للألعاب السابقة من أجل إنشاء ألعاب جديدة أمرا ممكنا، وهذا بدوره يساهم في تذليل العقبات التقنية واختصار الوقت والجهد. عندما تتحدث عن صناعة لعبة، فأنت هنا تذكر العملية الكبرى والتي تنطوي على عشرات وربما مئات المهام التي يجب أن تنجزها في مجالات عدة. فصناعة لعبة تعني إنتاجها وتسويقها ونشرها وكل ما يتعلق بهذه العمليات من إجراءات وخطوات إدارية وتقنية وفنية ومالية وقانونية. على أية حال فإن ما يهمنا في سلسلة الدروس هذه هو الجانب التقني وهو تطوير اللعبة، وهي عملية بناء المنتج البرمجي النهائي بكافة مكوّناته. هذه العملية لا تشمل بالضرورة تصميم اللعبة، حيث أن عملية التصميم ذات منظور أوسع وتركز على أمور مثل القصة والسمة العامة للعبة وأشكال المراحل وطبيعة الخصوم، بالإضافة إلى قواعد اللعبة وأهدافها وشروط الفوز والخسارة. بالعودة لعملية تطوير اللعبة، نجد أن العديد من الاختصاصات والمهارات تساهم في هذه العملية، فهناك الرسامون ومصممو النماذج وفنيو التحريك ومهندسو الصوت والمخرج، إضافة – بالطبع – للمبرمجين. هذه النظرة الشاملة مهمة لنعرف أن دور المبرمج في إنتاج اللعبة ليس سوى دورا مكمّلا لأدوار غيره من أعضاء الفريق، ولو أن هذه الصورة بدأت تتغير بظهور المطورين المستقلين Indie Developers والذين يقومون بالعديد من المهام إلى جانب البرمجة. لماذا نستخدم محركات الألعاب؟ لو أردنا الحديث بتفصيل أكبر عن دور المبرمجين في صناعة الألعاب، سنجد أنه حتى على مستوى البرمجة نفسها هناك أدوار عديدة يجب القيام بها: فهناك برمجة الرسومات وهناك أنظم الإدخال وأنظمة استيراد الموارد والذكاء الاصطناعي ومحاكاة الفيزياء وغيرها مثل مكتبات الصوت والأدوات المساعدة. كل هذه المهام يمكن إنجازها على شكل وحدات برمجية قابلة لإعادة الاستخدام كما سبق وذكرت، وبالتالي فهذه الوحدات تشكل معا ما يعرف بمحرك الألعاب Game Engine. باستخدامك للمحرك والمكتبات البرمجية التي يتكون منها، فأنت تختصر على نفسك الجهد اللازم لبناء نظام الإدخال والإخراج والاستيراد ومحاكاة الفيزياء، وحتى جزء من الذكاء الاصطناعي. وما يتبقى عليك هو كتابة منطق لعبتك الخاصة وإبداع ما يميزها عن غيرها من الألعاب. هذه النقطة الأخيرة هي ما ستدور حوله سلسلة الدروس القادمة، وبالرغم من أن المهمة تبدو صغيرة جدا مقارنة بتطوير اللعبة كاملة، إلا أنها على صغرها تحتاج لمجهود معتبر في التصميم والتنفيذ كما سنرى. خطوات سريعة لتبدأ مع محرك Unity إن لم تكن ذا خبرة سابقة بهذا المحرك يمكنك قراءة هذه المقدمة السريعة، كما يمكنك تخطيها إن كنت تعاملت مع هذا المحرك سابقا. لن أطيل شرح هذه الخطوات حيث هناك الكثير من الدروس سواء بالعربية أو الإنجليزية تتناولها، لكنها هنا لنتأكد من أن كل قارئ للسلسلة على نفس الدرجة من المعرفة الأولية قبل البدء. الخطوة الأولى: تحميل وتنصيب المحرك لتنزيل الإصدار الأحدث من المحرك وهو 5 ادخل مباشرة إلى الموقع http://unity3d.com ومن ثم قم بتحميل النسخة المناسبة لنظام التشغيل الذي تستخدمه، علما بأن النسخة المجانية من المحرك ذات إمكانات كبيرة وهي تفي بالغرض بالنسبة لمشروعنا في سلسلة الدروس هذه. الخطوة الثانية: إنشاء المشروع بمجرد تشغيل المحرك بعد تنصيبه ستظهر لك شاشة البداية، قم بالضغط على New Project لتظهر لك شاشة كالتي تراها في الصورة أدناه. كل ما عليك هو اختيار النوع 2D ومن ثم اختيار اسم وموقع المشروع الجديد الذي ستقوم بإنشائه، ومن ثم الضغط على Create Project. الخطوة الثالثة: التعرف على نوافذ البرنامج الرئيسية تهمنا في البداية 4 نوافذ رئيسية في محرك Unity، وفيما يلي ملخص لوظائفها: نافذة المشهد Scene: وهي التي تستخدمها لبناء مشهد اللعبة وإضافة الكائنات المختلفة إليه وتوزيعها في الفضاء ثنائي الأبعاد. تحتوي هذه النافذة مبدئيا على كائن واحد وهو الكاميرا. هرمية المشهد Hierarchy: تحتوي على ترتيب شجري يحوي كافة الكائنات التي تمت إضافتها للمشهد ويساعدك في تنظيم العلاقات بينها، حيث أنه من الممكن أن تضيف كائنات كأبناء لكائنات أخرى بحيث يتأثر الكائن الابن بالكائن الأب كما سنرى. تحتوي هذه النافذة مبدئيا على كائن واحد وهو الكاميرا. مستعرض المشروع Project: يقوم بعرض جميع الملفات الموجودة داخل مجلد المشروع، سواء تلك التي تمت إضافتها للمشهد أم التي لم تُضف. يحتوي المشروع مبدئيا على مجلد واحد يسمى Assets، وسنضيف داخله كافة الملفات والمجلدات الأخرى. نافذة الخصائص Inspector: عند اختيار أي كائن من هرمية المشهد أو نافذة المشهد أو مستعرض المشروع، فإن خصائصه ستظهر في هذه النافذة ويمكنك تغييرها من هناك. استعرضنا في هذا الدرس ما يظهر من واجهة Unity3D للوهلة الأولى، مع مقدمة بسيطة حول صناعة الألعاب، سنشرع في الدروس القادمة في مشروع عملي نتعلم من خلاله كيفية صناعة لعبة كاملة حقيقية. فترقبوا!1 نقطة
