post

تضمين إعلانات Admob داخل Unity

سنأخذكم في هذا الدرس في جولة سريعة لنتعرف معاً كيف نقوم بوضع الإعلانات في ألعابنا ، سواء كانت للـ Android أو لـ IOS ، فنحن كما نعلم أن الإعلانات حالياً هي اكثر مصدر للدخل في الألعاب، و هناك العديد من المزودين الذين بإمكانك بواسطتهم عرض الإعلانات داخل لعبتك ، و سنقوم في هذا الدرس ان شاء الله بالتعامل مع google AdMob

تهئية وعمل حساب على Admob

في البداية هناك أمور يجب أن تكون موجودة مسبقاً ، ألا و هي حساب AdMob ، و إذا لم تكن تمتلك حساب AdMob ، يمكنك بسهولة التوجه إلى admob.google.com و عمل حساب جديد ، بعد عمل حساب جديد ستحصل على واجهة جديدة ، بإمكانك من هذه الواجهة من خلال قائمة الـ Ads إضافة اعلان جديد ، و يجب أن نعلم أنه في كل الإعلانات يجب فصل الـ Android و الـ IOS ، فمثلاً إذا أردت عمل إعلانات لنسخة IOS يجب أن تمتلك ID مختلف عن الـ ID الخاص بنسخة الـ Android ، بعد الضغط على new Ad سيسأل هل اللعبة موجودة على متجر Google Play أو IOS ، سوف نختار لا . في الصفحة التالية سيطلب كتابة معلومات عن اللعبة ، سنقوم بكتابة اسم اللعبة ،و نختار نسخة اللعبة ، (IOS / Android) و سنختار في هذا الفيديو Android و نضغط Add

أهم شيء هنا هو الـ App ID ، بإمكاننا الذهاب إلى App settings و سنجد الـ App ID ، الخطوات موجودة في الرابط https://developers.google.com/admob/unity/start بشكل مرتب ، لاحظ أنه يتطلب منك خطوات متعددة مثل انشاء حساب AdMob

إضافة دوال Admob إلى Unity

يجب أن نقوم بتحميل Mobile Ads Unity plugin ، الذي يحتوي على المكتبة الخاصة بعملية Show Ads و هو موجود في الرابط السابق ، نضغط تحميل و سنجد أن الباقة موجودة و قابلة للتحميل هنا :
https://github.com/googleads/googleads-mobile-plugins/releases/latest

و من Unity سأقوم بالذهاب إلى Assets > Import Package > Custom Package ، و نختار الباقة التي قمنا بتحميلها و نقوم بعمل import لكل شيء ، ثم نقوم بعمل resolve ، نذهب إلى Assets > Play Services Resolver > Android Resolver > Resolve ، عندها ستظهر رسالة تخبرنا باكتمال دمج الباقة ، الآن أصبحت الـ APIs و المكتبة التي تدعم Google جاهزة و متاحة للتحكم ، يتبقى علينا أن نقوم بتغيير الـ Application ID الخاص بنا في منطقة معينة ، Assets/Plugins/Android/GoogleMobileAdsPlugin ، سنجد الملف AndroidManifest.xml ، نضغط الزر الأيمن للماوس و نختار show in explorer ، ثم نقوم بعمل تحرير للملف لتعديله ، نقوم بنسخ الـ App ID السابق و لصقه في مكانه كما هو مذكور في البند android:value ، ثم نقوم بحفظ الملف ، الآن بعد أن قمنا بعمل هذا ، يتقبقى أن نقوم بتفعيل عملية الضغط أو اخراج و عرض الفيديو

<manifest>
    <application>
        <!-- Your AdMob app ID will look similar to this
        sample ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="YOUR_ADMOB_APP_ID"/>
    </application>
</manifest>

تفعيل مكتبة Admob وتهيئتها داخل Unity

نعود إلى الـ Documentation السابق ، نلاحظ أنه يتبقى علينا عمل Initialize للـ Mobile Ad ، نلاحظ أن لدينا 3 أنواع و الإعلانات و هي Banner / Interstitial / Rewarded
– الـ Banner يكون موجوداً طيلة وقت اللعب ، في أسفل أو أعلى الشاشة
– الـ Interstitial يقوم بعرض إعلانات عندما يتنقل اللاعب من واجهة إلى واجهة أخرى (تحميل المستوى أو العودة إلى الصفحة الرئيسية …. الخ)
– الـ Rewarded ، و يقوم بعرض فيديو ، و يتوجب على اللاعب مشاهدته كاملاً ليحصل على الجائزة ،و لا يحتوي على زر اغلاق للفيديو .
في البداية سنتعامل مع النوع Rewarded ، سأذهب إلى حسابي على AdMob ثم إلى Ad units سنقوم بـ create ad unit ، سيطلب اختيار نوع الإعلان ، سنختار Rewarded . في الشاشة التالية يطلب الاسم ، سنكتب أي شيء ، ثم نضغط Create ad unit. نلاخحظ أنه قام بعرض الـ Ad Unit ID ، نعود إلى الـ Documentation ثم إلى Implement rewarded ads لمعرفة كيفية استخدامه
في البداية يجب إن نقوم بعمل Initialize للـMobile Ads فنأخذ الكود ، من اليونيتي سنذهب إلى مجلد الـ Scripts و نقوم بعمل سكريبت جديد ثم نقوم بوضع الكود الذي قمنا بأخذه ، و لاننسى استبدال الـ App ID بالـ ID الخاص بنا ، الان سنقوم بسحب هذا السكريبت و وضعه على أي شيء ليتم تنفيذه مباشرة عند البدء ، الإن بمجرد الضغط على زر play لن يظهر شيء لأننا لم نقم ببرمجة شيء بعد ، و لكن إذا اذا ذهبنا إلى الـ Console سنجد أنه قام بعملية Initialize و هنا لا يوجد أي مشكلة ـ و هذا يطمئننا أن امورنا صحيحة ولا يوجد مشاكل ، بقي علينا أن نقوم بجعل الزر يجعلنا نشاهد الإعلان ، سنعود إلى ال Documentation مرة أخرى ، ثم إلى قسم الـ Rewarded ، لنشاهد كيف يمكننا إظهار الإعلان ، و نلاحظ هنا أننا سنقوم بتعريف متغير من النوع rewarded بحيث أن نقوم بعمل Initialize للـ adUnitId الذي سنستخدمه بعد قليل ، سنأخذ هذا المتغير و هذا السطر ، نلاحظ بعد الـ Initialize الـ Unit ID التي نحصل عليها من صفحة الـ Ad units

ضرورة التجربة بإعلانات Google وليس بإعلاناتك

هنا يوجد قضية علينا الانتباه إليها ، نلاحظ هنا في Google يقول “always test with test ads” ، هذا الكود الموجود هنا سيعرض فيديو من شركة Google ، فعندما تقوم بتجربة الإعلانات لا تضع الكود الخاص بك لأن هناك سياسة في الشركة تمنع المطور من استخدام الإعلانات ، و كأنه يقوم بعرض إعلانات لنفسه ليكسب المال ، و اذا قمت باستخدام كود على جهازك كمطور و قمت بعرض الإعلانات على جهازك ، فهناك إمكانية لعمل lock لحسابك ، و نحن لا نريد هذا الشيء ، إذا سوف نأخذ هذا الكود و نقم بلصقه ، بعد أن نقوم بعملية الاسناد للـ ID نقوم بعمل Request ليقم بعرض الإعلان ، إذاً بعد إضافة الكود الأخير يجب أن نقوم بعمل دوال تفيد في عمل ال Callback للـ Events ، فعندما ينجح أو يفشل الإعلان أو عندما يحصل شيء معين ، يقوم بتفعيل أو استدعاء هذا الـ event ، سنذهب إلى الـ Documentation ، سنجد أنه يوجد العديد من الدوال الموجودة مسبقاً ، سنقوم بأخذها و وضعها في السكريبت الخاص ، بعد أن قمنا بتصحيح الأخطاء ، إذا قمنا بتعريف الـ Rewarded Ads بهذا الـ ID الخاص بـ Google ، و الذي سيعرض لنا شيء خاص بـ Google و ليس اعلاناتنا ، طبعا عند الانتهاء ستقوم باستبداله بشيء خاص بك ، لاحظوا أنه عندما يتم استدعاء الكود بشكل صحيح سيقوم بإظهار الفيديو ، هنا لدينا عندما يتم تحميل الفيديو من الانترنت ، يجب أن نقوم بعمل عرض للفيديو ، فهو يقوم بالتحميل فقط ، فيجب أن نضع جملة شرطية ، عند نهاية التحميل قم بعرض الفيديو ، سنقوم بالحفظ و نعود إلى يونيتي ، بالضغط على زر شاهد سيظهر معلومات أنه لا يوجد أي مشكلة
لزيادة عدد الـ coins التي يكسبها المستخدم نذهب للدالة HandleUserEarnedReward ، في هذه الدالة اللاعب قام بمشاهدة الفيديو كاملاً فيجب أن نقوم بإعطائه coins ، هنا قمنا بتعرف المتغير coins
نذهب إلى build and run لنقوم بتشغيل اللعبة ، نلاحظ أن الـCoins عددها 0 ، بالضغط على الزر شاهد سيقوم بعرض الفيديو، و عند الانتهاء سيقوم بإضافة الـ Coins ، نقوم بالضغط مرة أخرى على الزر شاهد و نقوم بإغلاق الفيديو و نلاحظ أنه لن يقوم بمنحنا الـ Coins ، فيجب على اللاعب انهاء الفيديو ليحصل على الجائزة ، هذا كان بشكل سريع عن كيفية إضافة الـ AdMob داخل اللعبة على محرك الألعاب Unity

الأسطر البرمجية المستخدمة في هذا الدرس

using GoogleMobileAds.Api;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GoogleAds : MonoBehaviour
{
    private RewardedAd rewardedAd;


    // Start is called before the first frame update
    void Start()
    {
#if UNITY_ANDROID
        string appId = "ca-app-pub-3062555098484328~2649488225";
#elif UNITY_IPHONE
            string appId = "ca-app-pub-3940256099942544~1458002511";
#else
            string appId = "unexpected_platform";
#endif

        // Initialize the Google Mobile Ads SDK.
        MobileAds.Initialize(appId);
        
        

    }

    public void ShowAds()
    {
        this.rewardedAd = new RewardedAd("ca-app-pub-3940256099942544/5224354917");

        // Called when an ad request has successfully loaded.
        this.rewardedAd.OnAdLoaded += HandleRewardedAdLoaded;
        // Called when an ad request failed to load.
        this.rewardedAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;
        // Called when an ad is shown.
        this.rewardedAd.OnAdOpening += HandleRewardedAdOpening;
        // Called when an ad request failed to show.
        this.rewardedAd.OnAdFailedToShow += HandleRewardedAdFailedToShow;
        // Called when the user should be rewarded for interacting with the ad.
        this.rewardedAd.OnUserEarnedReward += HandleUserEarnedReward;
        // Called when the ad is closed.
        this.rewardedAd.OnAdClosed += HandleRewardedAdClosed;


        // Create an empty ad request.
        AdRequest request = new AdRequest.Builder().Build();
        // Load the rewarded ad with the request.
        this.rewardedAd.LoadAd(request);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void HandleRewardedAdLoaded(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdLoaded event received");
        if (this.rewardedAd.IsLoaded())
        {
            this.rewardedAd.Show();
        }
    }

    public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args)
    {
        MonoBehaviour.print(
            "HandleRewardedAdFailedToLoad event received with message: "
                             + args.Message);
    }

    public void HandleRewardedAdOpening(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdOpening event received");
    }

    public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args)
    {
        MonoBehaviour.print(
            "HandleRewardedAdFailedToShow event received with message: "
                             + args.Message);
    }

    public void HandleRewardedAdClosed(object sender, EventArgs args)
    {
        MonoBehaviour.print("HandleRewardedAdClosed event received");
    }

    public void HandleUserEarnedReward(object sender, Reward args)
    {
        GameLogic.coins += 150;

        string type = args.Type;
        double amount = args.Amount;
        MonoBehaviour.print(
            "HandleRewardedAdRewarded event received for "
                        + amount.ToString() + " " + type);
    }


}

post

#21 التغليف Encapsulation – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : RSJ

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C – التغليف Encapsulation

ما معنى Encapsulation ؟ و كيف يمكننا حماية اسطر برمجية معينة من التحكم بها و من القراءة بها ؟ ما هي درجات كلمات private و public ؟

تكلمنا سابقاً عن البرمجة كائنية التوجه أن لها ميزات و خصائص معينة و من ضمنها التغليف Encapsulation ، مفهوم Encapsulation ببساطة هو حماية أجزاء معينة من الكود من الوصول إليها من قبل المبرمجين أو الزبائن ، لنعطي مثالاً واقعيا بسيطاً بحيث نوضح موضوع Encapsulation ، تخيل أنك تجلس أمام التلفاز و بيدك جهاز التحكم ، بإمكانك ببساطة الضغط على أحد الازرار ليحدث شيء معين (رفع الصوت ، تغيير القناة ، تغيير الإضاءة ) ، هذه الامور تقسم إلى قسمين :
– القسم الأول هو شيء public و هو متاح لك ، و هو الازرار الموجودة على جهاز التحكم
– القسم الثاني هو private و هو كيفية عمل الأزرار ، عندما نضغط على زر يحدث أمر معين ، نحن لا ندري ما الذي حدث ، فهو قسم مخفي يستخدمه الصانعين
إذا لدينا قسمين ، قسم متاح ، و قسم غير متاح ، نأخذ الآن كود سريع لنوضح الفكرة . نقوم بتعريف كلاس جديد باسم something و نعرف داخله دالتين :

Public void DoSomething()
{

}
Private void HelperMethod()
{

}

في الدالة الـ private سنقوم بطلب طباعة Hello world! ، و في الدالة الـ public سوف نقوم باستدعاء الدالة الـ private
الآن لدي في التطبيق الخاص بي عندما أقوم بتعريف متغير أو object من النوع something
Something s1 = new Something();
لاحظوا إذا كتبت s1 و قمت بالضغط على dot سيعطيني الدالة التي اسمها DoSomething و ليس لدي إمكانية التعامل مع الدالة HelperMethod لأن هذ شيء خاص و داخلي لا يمكنني الوصول إليه، الآن لو تابعنا
S1.DoSomething();
Condole.ReadLine();
و حاولنا تشغيل التطبيق سنلاحظ أنه سيقوم بطباعة الجملة الموجودة في HelperMethod

إستخدام التغليف لتطوير التطبيق

من الممكن أن نرغب بمعرفة عدد ضغطات المستخدم أو معرفة ما قام الزبون باستدعائه ، هنا سنقوم بتعريف متغير من النوع int باسم clickCount ، و نقوم بجعلها في الدالة private
clickCount ++;
لتعتبر الزيادة ، مثلاً عندما يقوم بعمل شيء معين أو يستدعي أداة معينة يزداد هذا العداد بدون معرفة الزبون ، فهو أمر غير مهم بالنسبة له ، كل ما يهتم به هو النتيجة النهائية ، أما أنا كمطور قد يهمني معرفة هذه الأمور و ربما أرغب بعمل تحليل للبرنامج الخاص بي
هناك أنواع أخرى غير public و private و هي protected و internal ، و هما متقدمين على هذه الدورة ، و بإمكانك البحث عنهما بشكل موسع
هذا كان بشكل سريع شرح لدرس اليوم encapsulation و نلقاكم في درس قادم إن شاء الله

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PrivatePublic
{
    class Program
    {
        private static string k = "";
        static void Main(string[] args)
        {
            Something s1 = new Something();
            s1.DoSomething();
            Console.ReadLine();
        }
    }

    class Something
    {
        static int clickCount;
        public void DoSomething()
        {
             HelperMethod();
        }
        private void HelperMethod()
        {
            Console.WriteLine("Hello World!");
        }
    }
}

post

#20 النطاق Scope – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : BVP

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  النطاق Scope

لماذا عندما نقوم بتتعريف متغير جديد ، لان نستطيع استخدامه في كل التطبيق ؟ ما هو الـ scope ؟ و ما هو النطاق الخاص بالمتغير ؟ و متى ينتهي المتغير و يتم حذفه من الذاكرة ؟

في درس اليوم سوف نتكلم عن النطاقات Scopes و أهميتها ، و ذكرنا سابقاً أننا سنقوم بشرحها مستقبلاً بشكل مكثف ، لدينا الآن برنامج Visual Studio 2019 Community و هو مجاني كما ذكرنا سابقاً، بإمكاننا عمل مشروع جديد من خلال Create new project و نقوم باختيار الـ Console app ثم الضغط على next و في الصفحة التالية نقوم بكتابة اسم مشروع ، و ليكن UnderstandingSscope ، سيفتح لنا النافذة الرئيسية للكود

الشيء الذي نريد إيصاله أنه عندما نقوم بتعريف متغير جديد ، فإنه سيكون متاحاً في القطعة البرمجية الموجود فيها حصراً ، أو كل القطع البرمجية الموجودة داخلها . و قد تكلمنا سابقاً أن القطعة البرمجية هي القطعة المحصورة بين القوسين { } ، سنقوم الآن بعمل حلقة for loop

 for (int i=0 ; i<10 ; i++)
 {
      Console.WriteLine(i.ToString());
 }
 Console.ReadLine(); 

فهم النطاق

اذا قمنا بتنفيذ المشروع ، فسنرى أنه قام بطباعة الأعداد من 0 إلى 9 كما هو المعتاد ، لكن لنلاحظ التالي ، لو قمنا بأخذ الجملة Console.WriteLine(i.ToString()); و كتابتها خارج القطعة البرمجية الموجودة فيها ( أي خارج القطعة الخاصة بالحلقة for loop ) ، يصبح الكود بالشكل :

 for (int i=0 ; i<10 ; i++)
 {
      Console.WriteLine(i.ToString());
 }
 Console.WriteLine(i.ToString());
 Console.ReadLine(); 

فنلاحظ أنه مباشرة سيظهر لدينا خطأ في قائمة الأخطاء ، و يقول الخطأ ، “the name does not exist in current context” ، بما معناه أن المتغير لا يمكن التعرف عليه في هذه المنطقة لأن الـ i حصراً لتلك القطعة البرمجية لأنها داخل نطاق الحلقة التكرارية ، بالتالي فإنه فعلياً غير موجود في القطعة البرمجية الأخرى ، و لن يتم التعامل معه .
سنقوم بجعل الجملة الخاطئة جملة تعليق . و سنقوم بعمل متغير جديد باسم j في القطعة الأولى ، و التي تحتوي على الحلقة for loop و نقوم بإسناده داخل القطعة البرمجية التابعة للحلقة for loop ، ثم نقوم بكتابة الجملة لتقوم بطباعة المتغير j خارج الحلقة for loop ليصبح الكود كالتالي :

{
     string j =” “ ;
     for (int i=0 ; i<10 ; i++)
     {
          Console.WriteLine(i.ToString());
          j = i.ToString();
     }
     // Console.WriteLine(i.ToString());
     Console.WriteLine(“j = “ + j.ToString());
     Console.ReadLine();
}

ثم نقوم بتنفيذ البرنامج … نلاحظ أنه يخبرنا في النهاية أن j تحصل على القيمة 9 ، نلاحظ أنه قمنا بتعريف المتغير j في القطعة الخارجية .. إذا لن يحدث أي خلل سواء استعملته في القطعة الداخلية أو في نفس القطعة التي قمت بتعريفه داخلها .

النطاق على مستوى ال Class

سنقوم بتعريف property جديدة من النوع String
Private static string k =” “ ;
و في الداخل ستكون قيمة k الجديدة ستكون هي قيمة i ، و سنقوم في الخارج بطباعة قيمة k الجديدة كما قمنا بطباعة قيمة j سابقاً ، بتنفيذ البرنامج نلاحظ أنه يعطيني نفس النتيجة النهائية . الشيء الذي نريد توضيحه أنه بحال قمت بتعريف method على مستوى الكلاس ، مثلا :

static void HelperMethod()
{
    K = “10” ;
}

و قمنا باستدعاء الـ HelperMethod في الأعلى ، ثم قمت بتنفيذ المشروع ، نلاحظ أن القيمة النهائية هي 10 ، لأن المتغير k على مستوى الكلاس ، فيمكنني استخدامه في أي منطقة داخل الكلاس ، و أنا قمت باستخدامه داخل method لأقوم بالتعديل عليه ، أيضا في جملة التكرار for سأقوم بوضع جملة شرطية ، في حال كان قيمة i هي 9 قم بتعريف متغير ، string l =” “ ; ، ثم نقوم مباشرة بطباعة هذا المتغير خارج اقواس الحلقة for loop ، مباشرة سيعطيني أن هناك خطأ … فهذا المتغير تم تعريفه في قطعة برمجية داخلية ، فهذا المتغير عندما يصل إلى نهاية القوس سينتهي و يختفي من الذاكرة ويكون خارج النطاق فلا يمكن استخدامه خارج هذه الاقواس . اذاً هناك نطاق لكل متغير ، ولا يمكن استخدامه خارج هذا النطاق ، و هذا الكلام ليس محصوراً فقط للمتغيرات ، فعندما نقوم باستنساخ مجسم من كلاس ، ينطبق عليه كل ما قمنا بتطبيقه في هذا الدرس ، هذا كان بشكل سريع ملخص لمفهوم النطاقات scopes .
نراكم ان شاء الله في درس قادم قريباً . السلام عليكم .

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnderstandingScope
{
    class Program
    {
        private static string k = "";
        static void Main(string[] args)
        {
            string j = "";
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
                j = i.ToString();
                k = i.ToString();

                if (i == 9)
                {
                    string l = "";
                }
                //Console.WriteLine(l);
            }
            //Console.WriteLine(i.ToString());
            Console.WriteLine("j = " + j.ToString());
            HelperMethod();
            Console.WriteLine("k = " + k.ToString());
            Console.ReadLine();
        }

        static void HelperMethod()
        {
            k = "10";
        }
    }
}

post

لمحة حول ميزات 2019.2 Unity النسخة التجريبية

السلام عليكم ورحمة الله وبركاته ، طرحت شركة unity تسخة تجريبية للإصدار الجديد لمحركها لعام 2019 تحت رقم إصدار 2019.2 ، حيث قامت بذكر أهم الأجزاء التي سيحتويه والتي ستكون مضمنة في النسخة النهائية من الإصدار، حيث سيحتوي الإصدار على الكثير من التحسينات والإضافات الجديدة مثل تحسين الأداء لأجهزة المحمول، وإضافة أداة Polybrush وتسهيل نشر اللعبة على متاجر متعددة بواسطة The Unity Distribution Portal للوصول إلى عدد أكبر من اللاعبين، وتحسين الإضاءة وأدوات الواقع الإفتراضي والمعزز وغيرها الكثير.
يمكن تنزيل النسخة التجريبية من خلال Unity Hub البرنامج المسؤول عن التحكم في النسخ الموجودة في جهازك، مع الأخذ بالحسبان أن هذه النسخة التجريبية قد تحتوي على مشاكل تقنية معينة، حيث تطرح الشركة النسخة ليقوم المطورين بتجريبها وإيجاد أي مشكلة فيها لحلها قبل الإعلان النهائي عن النسخة المستقرة منها.
هنا ذكر لأهم الميزات لهذه النسخة :

تحسينات للأجهزة المحمولة


قامت الشركة بالتعاون مع فريق من شركة Google بتقديم تحسين للألعاب لتبقى على Frame ثابت وهو ما يعرف بإسم Frame Pacing ، وذلك بجعل الفرق بين عدد ال Frames المحسوبة أقل. والنتيجة كانت الحصول على smoother gameplay experience .


بالإضافة إلى ذلك تم تقديم إمكانية تفتيح الشاشة من خلال الخاصية Screen.brightness ، وقامو بإضافة تحديد لحجم الشاشة التي يمكن عرض اللعبة عليها من غير قص منها من خلال خاصية Screen.cutouts ، وهذه الميزة ستكون مفيدة مع الهواتف الجديدة مثل Samsung S10e .

تم إضافة أداة Polybrush


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

مزايا جديدة في إضاءة الـ 2D


تم تحديث وتطوير نظام الإضاءة Lightweight Render Pipeline (LWRP) ، حيث تم إضافة 2D Pixel Perfect وإضافة أنواع إضاءة خاصة بالمجسمات ثنائية الأبعاد، وتم إضافتها أيضاً إلى الـ Shader Graph الخاص بها. وقد تم تفصيل هذا المزايا في مؤتمر GDC 2019


تحديثات الإضاءة


الميزة الخاصة بإزالة ال Noise وبما يعرف بال Denoise الآن أصبحت تعمل على كل الكروت، حيث سابقاً كان بعض الأنواع تعاني منها وبعضها لا يعاني، ايضاً تم تغيير طريقة حساب خرائط الضوء Lightmaps ، حيث بإمكان أي مجسم موجود في المشهد المشاركة في حساب الإضاءة الغير مباشرة global illumination bake ، وتم زيادة سرعة الحسابات خصوصاً إذا تم إستخدام كرت الشاشة في ذلك.

صورة توضح الفرق بين ال Denoising وعدمه
الميزة الجديدة لتفعيل المجسمات من إستقبال الحسابات الخاصة بالإضاءة


أما بالنسبة لتحديثات خرائط الضوء بواسطة كروت الشاشة فهي أصبحت تمتلك الآن :
1 – أكثر من Importance Sampling support لإضاءة المحيط
2 – أصبحت تدعم NVIDIA OptiX denoising
3 – زيادة سرعة الحسابات عندما تستخدم النوع view prioritization او للمجسمات الصغيرة


متاجر عالمية لزيادة اللاعبين


أصبحت يونيتي تدعم بعض المتاجر العالمية لتساعدك بنشر ألعابك عليها وهي ما يعرف بإسم The Unity Distribution Portal (UDP) ، حيث تم التعاقد من بعض المتاجر الكبيرة التي تنافس جوجل ستور وأبل ستور مثل : Catappult/Aptoide, MOO Store, ONE Store, Jio Games Store
مع العلم أن جميع هذه المتاجر تعمل على نظام Android فقط، بمعنى أنك في حال قمت بتطوير لعبة للأندرويد يمكنك ببضع خطوات أن تقوم بإنزال لعبتك على المتاجر المذكورة


AR Foundation


في هذه النسخة هناك العديد من الميزات التي تم إضافتها مثل : face-tracking, 2D image-tracking, 3D object-tracking, and environment probes


هناك العديد من الميزات الأخرى التي يمكنك مشاهدتها في الرابط الأصلي للإعلان عن النسخة هنا :
https://blogs.unity3d.com/2019/05/09/unity-2019-2-beta-is-now-available/

post

لمحة حول ميزات 2018.1 Unity النسخة التجريبية

السلام عليكم ورحمة الله وبركاته ، طرحت شركة unity تسخة تجريبية للإصدار الجديد لمحركها لعام 2018 تحت رقم إصدار 2018.1 ، حيث قامت بذكر أهم الأجزاء التي سيحتويه والتي ستكون مضمنة في النسخة النهائية من الإصدار، حيث سيحتوي الإصدار على الكثير من التحسينات والإضافات الجديدة مثل نظام التفاصيل الزائدة Tessellation for Metal و إستحدام كرت الشاشة في الإضاءة غير المباشرة GPU Instancing ، إضافة منظور ال PS4 لنافذة Game Resolution وتحسينات على نظام الجزئيات Particle system والتحسين على بلجت التصدير FBX وغيرها الكثير. وهنا ذكر لأهم الميزات لهذه النسخة :

* نظام تصيير جديد  Scriptable Render Pipeline

حيث قدمت الشركة في هذه النسخة نظام إظهار آني real-time rendering ذو الإختصار SRP ، حيث أنه تم تصميمه خصيصاً لمواكبة الأجهزة الحديثة وكروت الشاشة السريعة جداً ، فبدلاً من النظر إلى ملايين أسطر البرمجة بلغة السي ++ أصبح الآن بالإمكان التعامل معه بواسطة لغة السي شارب و عمل شيدرز سريع للمواد Material Shaders بسهولة. حيث ستقوم الشركة بوضع أنظمة جاهزة Templates تستطيع من خلالها إختيار طريقة العرض التي ستلائم مشروعك بتقسيمين : Lightweight  حيث سيكون مثالي لأجهزة الموبايل والأجهزة الخفيفة و High-Definition حيث سيكون ملائم للمواصفات العالية جداً مثل أجهزة الحاسوب وغيرها.

* أداة visual shader creation

حيث تم تطوير هذه الأداة خصيصاً للمصممين والرسامين ، فبواسطة هذه الأداة يمكنك عمل مواد معقدة من خلال طريقة ال Graph Nodes  ،  فبدلاً من كتابة Shaders خاصة بواسطة الأسطر البرمجية أصبح بإمكانك عمل Shader كامل بواسطة ربط ال Nodes ببعضها لتحصل على الشكل النهائي الذي تريده ، وهذه الميزة كانت من أكثر الميزات طلباً من جمهور المطورين وتم الإستجابة لهم من الشركة .

* قريباً C# Job System

تحسينات وتطويرات ستكون متاحة قريباً تزيد من كفاءة اللعبة خاصة لمن يقوم بكتابة الأسطر البرمجة بلغة السي شارب

* تعديل على المواصفات الدنيا System Requirements

قامت الشركة بحذف العديد من الأمور التي كانت ضمنياً متاحة داخل المحرك وذلك بهدف جعل المحرك أكثر مرونة، وتركت باب الحصول على الميزات السابقة متاحة بتنزيلها منفصلة عن المحرك ، فقد قامت بفصل إمكانية إستيراد مواد Substance Designer materials وفصل Wii U  و فصل Windows XP in standalone player و فصل محرر MonoDevelop حيث أنها تنصح بإستخدام فيجوال ستوديو من شركة مايكروسوفت ، وقامت بزيادة مواصفات macOS إلى النسخة 10.11 على الأقل ، وهي تعمل على فصل نظام الجزئيات التقليدي  Legacy Particle System في النسخة القادمة وإستبداله بنظام جديد

يجدر بالذكر أن النسخة هي نسخة تجريبية ويمكنك تنزيلها والمشاركة بها من خلال هذا الرابط : https://unity3d.com/unity/beta

 

 

post

#19 مواضيع متقدمة عن Classes – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : MRE

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  مواضيع متقدمة حول الفئات Classes

مواضيع متقدمة حول الفئات Classes :

ما هو الـ Garbage Collector ، و ما هي دلالات كلمة  new التس نستخدمها عند الاشتقاق من الكلاس الرئيسي ، ما هي الـ Static ، و ما هو الـ Constructer الدالة التي تقوم بتنفيذ أسطر برمجية عند الاستنساخ من كلاس رئيسي ؟

هذا كله سنتعرف عليه في هذا الدرس بعد الفاصل إن شاء الله .

 

السلام عليكم و رحمة الله و بركاته ، و أهلاً و سهلاً بكم في درس جديد من دروس سلسلة تعلم البرمجة للمبتدئين كلياً بواسطة السي شارب

بسم الله الرحمن الرحيم ، في الدرس الماضي تحدثنا عن مدخل إلى البرمجة كائنية التوجه OOP و التي هي اختصار لـ Object Oriented Programming ، و تعلمنا كيفية بناء Class ، و التي  أصبحنا نعلم أنه يمكن ترجمة الـ Class إلى العربية بكلمة ” الفئة ” ، و تكلمنا كيف يمكنك بناء فئات أو Classes تحوي معلومات مشتركة ، و رأينا كيف يمكننا تعريف الـ Property  و رأينا كيف يمكننا استنساخ Object من هذا الـ Class

في هذا الدرس سنتكلم إن شاء الله عن أمور و تطبيقات إضافية للـ Classes و الـ Method نفسها ، و سنتكلم عن مفهوم الـ Object نفسه ، فما هو مفهوم الـ Object عندما نقوم باشتقاقه من الـ  Class ، و كيف يتم تخزينه و استدعائه ، و ماهي حلقة الوصل بينه و بين الذاكرة ، سيتم مناقشة هذا في القسم الأول من الدرس ، و سنراجع معاً ما هو دور الـ Dot Net Runtime في عملية إدارة الذاكرة .

 

تكلمنا في البداية أن الـ Dot Net له أقسام معينة و هو مسؤول عن تحويل أمور معينة و تعرفنا على Common Language Runtime و اختصارها CLR ، حيث سنأخذ فكرةً عنها ، و كيف ستساعدنا هذه الأمور في انتاج برامج قوية قادرة على إدارة الـ Data  ، و قادرة على إدارة عمل البرنامج بشكل افضل .

و سنتكلم أيضاً عن شيء يسمّى Constructer  ؛ و هو Method خاصة يتم استدعاؤها عندما يتم استنساخ Object من الـ Class ، و سنتكلم أيضاً عن معنى كلمة Static ، و التي رافقتنا من أول درس إلى هذا الدرس .

 

كالعادة نقوم بإنشاء مشروع جديد بلغة c# من النوع Console App

في الدرس الماضي تكلمنا عن المكان المناسب لتعريف الـ Class ، حيث قلنا أنه يجب أن يكون موازياً للـ Class الرئيسي ، في المنطقة الواقعة داخل الحافظة الرئيسية namespace  ؛ و التي تحتوي على مجموعة من الكلاسات .

 

في البداية هناك قضية أودُّ التنويه لها ، و هي إمكانية كتابة Class ضمن كلاس آخر ، أو ما يعرف بالـ Nested Class ، لكننا لن نتعمق في هذا الموضوع ، و سنتعلم الـ Class بمفهومه البسيط ، و الذي يمكن استخدامه في أي مكان .

إذا لكتابة Class جديد نذهب لأي منطقة موازية لأي كلاس آخر ، و يمكن كتابة الـ Class فوق الكلاس الرئيسي أو تحته ، فلا مشكلة في هذه النقطة ، إذا سننتقل إلى السطر رقم 15 ، و أقوم بكتابة نفس الـ Class الذي تعاملنا معه في الدرس الماضي .

لاحظوا أن هذا الـ Class المسمّى Car يحتوي على 4 خصائص ، كل منها لديه نوع خاص ، فالشركة المصنعة لديها النوع string و سنة التصنيع من النوع int .

اشتقاق Object من Class معين :

و لاشتقاق Object من هذا الـ Class تعرفنا أنه يمكننا كتابة اسم الـ Class الرئيسي أولاً ، ثم نقوم بتعريف متغير جديد myCar على سبيل المثال ، ثم وضع إشارة المساواة ، ثم new ثم اسم الكلاس مرة أخرى ، مع وضع اقواس () و الفاصلة المنقوطة ، حيث قمنا هكذا بجعل هذا الـ Object مستنسخاً من الـ Class الذي اسمه Car ؛ لاحظوا في هذه الجملة قمنا بتعريف متغير نستطيع أن نقول عنه أنه Object من النوع Car ، و لاحظوا أنه عندما قمت بوضع كلمة new فهناك عمليات موجودة خلف هذه الكلمة .

 

ما معنى كلمة new ؟

عندما تقوم بعملية استنساخ أو بناء مجسم جديد ، فأنت فعلياً قمت بربط هذا المجسم و معلوماته بمكان معين في الذاكرة ، Address  معين في الـ Memory ، و هذا المكان في البداية هو مكان فارغ عندما قمنا بكتابة Car myCar ، و لكن عندما قمنا بكتابة new Car قمت بإضافة المعلومات الأساسية التي يتكون منها هذا الكائن ، فعندنا في البداية كائن قمنا بتعريفه فارغاً و لكن عندما قمنا بعملية ربطه بكلمة new قام فعلياً بعملية انشاءه و تهيئته بالشكل الذي قمنا بكتابته في الـ Class ، و سنتعرف بعد قليل على ميزة خاصة بعملية الـ new Car الموجودة هنا .

يمكن أيضا تشبيه هذا الموضوع بالبالون ، حيث نفترض بالون معين يطير في الهواء ؛ هذا البالون له خيط ، هذا الخيط هو عبارة عن الـ myCar ، و هو اسم المتغير  ، أما المعلومات الموجودة به فهي موجودة على البالون ، فالمتغير يدل على المنطقة في الذاكرة التي تحتوي المعلومات الكاملة .

 

القضية التي نودُّ شرحها هنا أنه بإمكاننا كما تعرفنا في الدرس السابق ، بإمكاننا إضافة المعلومات الموجودة بداخله ، حيث نضيف معلومات اللون و الخصائص السابقة ،

يمكننا أيضاً إضافة Object آخر من نفس النوع Car و جعله يشير إلى نفس المكان الموجود في الذاكرة ، بمعنى … سنقوم بإضافة متغير جديد باسم myOtherCar ، و لاحظوا أنني في هذه الجملة قمت بتعريف Object لكنه فارغ ، لا يشير إلى مكان في الذاكرة ، أو ليس له محتويات يشير إليها ، فإن قلت له في السطر التالي ، myOtherCar = myCar ، ففعلياً في هذا السطر جعلت الـ Object يشير إلى المكان الذي يشير إليه myCar

نعود لمفهوم البالون لتوضيح الصورة أكثر .

لدينا البالون الذي اتفقنا سابقاً أن له خيطاً و اعتبرناه myCar ، بالجملة التي كتبناها قمنا بعمل خيط آخر ، و الذي هو myOtherCar و الخيطين يشيران إلى نفس البالون ، و لاحظوا أنني لم أقم بإسناد أي قيمة للمتغير ، بل جعلته مساوياً للـ Object السابق .

بمعنى أنني إذا قمت بعمل طباعة الجملة التالية ، فعندها سيقوم بطباعة Black ، على الرغم من أنني قمت بطباعة myOtherCar  و ليس myCar ، إذا فعليا في المتغير myOtherCar قمت بالإشارة إلى نفس البالون الذي يحمله الـ myCar و لتتأكدوا أكثر أن الاثنان مرتبطان بنفس المنطقة في الذاكرة ، سأقول له
;”myOtherCar .color = “Red
أنا فعلياً هنا قمت بتغيير اللون لـ myOtherCar و ليس myCar ، و سأقوم مباشرة بطباعة myCar.color
و للتوضيح باختصار : انا قمت بتعريف متغير myCar و قمت بوضع اللون الأسود له ، ثم قمت بتعريف Object آخر من النوع Car و قمت بإسناد موقع الـ myCar إلى myOtherCar ، و قمت بتغيير myOtherCar.color ،و سأقوم بطباعة الـ myCar الأولى ، عند التشغيل سيظهر Red المعدلة و ليس Black ، لأنه كما ذكرنا أنه عبارة عن مكان موجود في الذاكرة و هناك أكثر من خيط يشير له ، فأي تعديل على أحدهما يؤثر على الآخر ، فـ myCar و myOtherCar هما عبارة عن خيوط للمكان المحجوز في الذاكرة نفسه .

 

ماذا لو أردت أن أقطع هذا الخيط ، بمعنى أريد فصل myOtherCar عن المكان الذي قمت بتعريفه في الأعلى . بمعنى أن تنفصل myOtherCar عن myCar ، فأنا أريد جعلها تشير إلى مكان آخر في الذاكرة ، فعلياً في السطر 17 أنت تعرف خيطاً فقط لا يشير إلى شيء ، و لا يوجد معلومات به ، و لا نعرف كيف سيكون و ما هي محتوياته ، لذلك يوجد جملة myOtherCar = null هذه القيمة null فعلياً فارغة ، و بذلك في السطر 20 قلت له أن يقوم بفصل myOtherCar عن أي شيء آخر ، و اجعله فارغاً لا يحوي أي شيء ، و بذلك ، و بدءاً من هذا السطر لو قمت بعملية طباعة أي معلومة من معلومات  myOtherCar فسنلاحظ أنه سيظهر مشكلة و خطأ برمجي ، و هو : myOtherCar was null  أي أنه فارغ !! و لا أعرف ما هو الـ color الذي تريده ، و لذلك لا اعرف كيفية طباعة هذه الجملة ، و بالتالي يظهر الخطأ .

إذاُ .. فعليا في السطر 20 قمت بقطع الحبل الخاص بـ myOtherCar الذي كان يربطه بالبالون ؛ و عند هذا السطر ، فقط myCar هو الذي يحتوي الوصلة للبالون .

 

إذا قمت بعد ذلك بقص الخيط الثاني  و ذلك بجعل myCar  تساوي null أيضاً ، و لاحظوا أنني هنا بعد تعريف الـ  Object و اضافته أن هناك بالون معين و يحتوي على المعلومات القيمة التي أريدها . و بعد السطرين 20 و 21 قمت بقطع الشريطين ، و طار البالون في الهواء و المعلومات فعلياً ذهبت إلى الأعلى و انفجرت !!

إذاً القضية التي أريد أن اوضحها لكم أن في هذه الخطوات هي فعلياً عملية ربط Object معين بموقع ، و عندما تقوم بفصله ، أو عندما يصل إلى نهاية الـ Block الذ تم تعريفه داخله فإنه فعلياً يصبح null  أي فارغاً بغض النظر عن السطرين 20 و 21 .

 

هنا يأتي دور Dot Net Runtime فماذا يفعل ؟؟

هناك معلومات قيمة و معلومات كثيرة ، فنحن الآن نتكلم عن كلمتين أو خمس حروف و هكذا ، و لكن ماذا عن المشاريع الكبيرة ، عندنا كم هائل من الـ  Data و هذه البيانات إذا بقيت في الذاكرة و لم يتم التحكم بها ، فسيكون هناك مشاكل كبيرة نحن بغنى عنها ، و هنا يأتي دور الـ Dot Net Runtime  و الذي قلنا سابقاً أن اختصاره هو CLR سيقوم بالتالي :

ستذهب و تبحث في جميع الأكواد التي قمنا بكتابتها في هذا البرنامج ، و ستجد أن هناك بالون فارغ لا يوجد أي وصلة له ، و تقوم بالبحث إن كان هناك خيوط مرتبطة بهذا البالون أم لا ، و فعلياً لن تجد أي وصلة له ، و تقول : ” أنت يا بالون خارج  التغطية و لا أريدك ، سأقوم بتهيئة مكانك ، قم باستخدامه لمتغير آخر استفيد منه خلال البرنامج ”

إذا هذا الموضوع الذي يقوم بحذف و إدارة الذاكرة شيء يسمى Garbage Collector ، هو شيء خاص بـ CLR ، و يقوم بالبحث عن المناطق أو الـ Object  التي تم فصل الارتباط بها ، و يقوم بتهيئتها لاستخدامها بشيء آخر ، هذا المصطلح يجب أن تكونوا على اطلاع عليه ، و نحن عندما نقول أن لغة السي شارب هي لغة managed  يعني أنه يوجد شيء وسيط بينك و بين الآلة يقوم بإدارة أمور معينة أنت في غنى عنها ، و لكن لاحظوا أننا عندما نقول عن لغة السي و السي بلس بلس هي لغة unmanaged  ، فإنك عندما تقوم بالتعامل مع هذه اللغات فأنت مضطر لمتابعة المتغيرات و الذاكرة و مواضيع أخرى ، فأنت مجبر أن تقوم يدوياً بعمل تفرغ لكل Object  قمت بالانتهاء منه ، كي لا تحدث مشاكل في الذاكرة و حجم البرامج ، و مشاكل كبيرة أنت في غنىً عنها .

لماذا اخترنا السي شارب ؟؟
لأنها لغة managed ، حيث توفر لنا إمكانيات و أدوات نحن في غنىً عن الغوص في تفاصيلها ، فنحن نريد أن نركز على فكرة التطبيق الذي نريد عمله

 

الآن في السطر رقم 13 عند تعريف Object  جديد قمت باستخدام قوسي الدالة () ، الحقيقة هنا يتم استدعاء  Method داخل الكلاس حتى و إن لم تقم بكتابتها و تعريفها ، ألا و هي دالة الـ Constructer  ، و هي دالة يتم استدعاؤها عندما تقوم بعمل initialize  للـ Object ، بمعنى أنه عندما تقوم بعمل فتح و اغلاق قوس يتم تنفيذ شيء معين ، و فعلياً هنا لأننا لم نقم بكتابة شيء ، هو قام بمناداته ، و لكنه ضمنياً فارغ .

لكي نتعامل مع هذا الموضوع و نتعرف عليه أكثر ، سنقوم الآن بالتعرف على كيفية كتابة الـ constructer  .

شكلها كالتالي :

()public Car

{
}

و اسمها طبق الأصل مع اسم الكلاس ..
هذه الأسطر من 29 إلى 32 ضمنياً موجودة ، و لكنها فارغة ، طالما قمت بكتابتها ، فالأولوية لما قمت بكتابته ، سأقوم بعمل التالي :

سأقول له عندما تقوم بعمل Object  جديد ضع الشركة مثلا Nissan  و سأقوم بالرجوع إلى الأسطر في الأسفل و اجعلها جمل ملاحظات .

أنا فعلياً قمت بتعريف الـ Object ، و لكن لم أقم بإسناد أي قيمة ، فقط قم بطباعة الـ Make  و عندما أقوم بتنفيذ التطبيق سيقوم بطباعة كلمة Nissan  ؛ من أين أتت هذه الكلمة !!!!

هذه الكلمة أتت من الـ Constructer    و هو كما قلت يتم استدعاؤه ضمنياً عندما تقوم بعملية استنساخ Object  جديد ،

هنا أيضاً مفهوم آخر ذكرناه في الMethods و سنعيده مرة أخرى  ، ألا و هو الـ Overload ، و هو إمكانية كتابة نفس الـ Method بنفس الاسم ، لكن مع اختلاف عدد الـ Parameter الموجود بداخلها ، لاحظوا أننا تكلمنا أنه داخل الـ Method بإمكانك إضافة  Parameter معينة  يتم اسنادها من خارج الدالة و يتم التعامل معها من داخل الدالة .

سنقوم بإضافة دالة جديدة و هي عبارة عن public Car و لكن سنقوم بإضافة Parameter  من خارج الدالة ، و تسمى هذه العملية Overload ، فسأقول له مثلاً string make  و string model  و int year و string color  ، و لاحظوا أن الكلمة make  تختلف تماما عن الكلمة Make لأننا تكلمنا أن لغة سي شارب هي لغة Case sensitive  فالحرف الصغير يختلف عن الكبير ، إذا في الـ overload هذه هنا سأقوم بعمل التالي ، حيث أنني في السطر رقم 13 ثمت بتعريف Object  جديد و القوسين فارغين ، فعليا قام باستدعاء الدالة التي قمنا بكتابتها ، و لكن أريد منه أن يقوم في عملية الـ Initialization أن أسند إليه قيماً و يقوم مباشرة بوضعها داخل كيان الـ Object  للتعامل معها لاحقاً .

فمثلاً سأقول له كالتالي :

الـ Make ذات الحرف الكبير اجعلها الـ make ذات الحرف الصغير ،  و التي أرسلتها من خارج الدالة

و كذلك بالنسبة للـ Model & Year & Color ، نعود للأعلى في السطر 13 ، بمجرد فتح القوس الأول يقوم بإظهار خيارات ، و بالضغط على الأسهم الظاهرة ، ستلاحظ أنه يوجد أكثر من Method يمكن استدعاؤها ، و هنا الأولى لا تحتاج أي Parameter و التي استخدمناها في السطر السابق ، و لكن هنا أريد استخدام الثانية ، حيث أريد اسناد الشركة و الموديل و السنة و اللون في نفس السطر ، فسأقول له  BMW مثلا , و كذلك الموديل و السنة و اللون ، إذا قمت بإنشاء Object جديد و قمت باستدعاء دالة البناء التي تحتوي على Parameter .

إذا عندما أقوم بعمل طباعة لنوع الشركة ، لن يقوم بإعادة اسناد Nissan بل سيقوم بطباعة BMW لأني قمت بإسنادها في بداية انشاء التطبيق  .

فهذا هو مفهوم الـ Constructer ، و هو مميز جداً   ، و استخدامه مفيد جداً في حالات كثيرة .

 

كلمة Static :

القسم الرابع من درسنا هو كلمة Static  ، لاحظوا أننا من أول تطبيق و حتى الآن ، كانت ترافقنا كلمة static الموجودة في الـ voidMain ، فقد تكلمنا عن int و string و void و تحدثنا عن الـ Class و كيف يمكننا استخدامه  و تحدثنا عن كلمةnew و تعلمنا كيف يمكن استخدامها  .

لطن ما معنى كلمة static ، و لماذا ترافقنا دائماً ، و لماذا في درس الدوال عندما قمنا بإضافة دالة ، وضعناها أيضاً من النوع Static كي نتمكن من استخدامها داخل الـ  voidMain ؟

الحقيقة أن كلمة static هي شيء يكون standard في كل الكلاس ، فكلمة Make و Model و Year و Color هي لا تتبع للكلاس ،هذه تتبع للـ Object المستنسخ من الكلاس ، فإن قمت بكتابة Car و بعدها نقطة ، فلن أجد الـ property السابقة ، لماذا ؟؟

لأن الـ Property الموجودة هنا تكون تابعة للـ Object الذي يأتي بعد عملية الاستنساخ ، فهنا عندما قمت باستنساخ Object جديد و وضعت myCar و النقطة ، حصلت على كل الـ Property الموجودة فيه ، و لدي أيضاً دوال ستكون متاحة هنا ، لماذا؟

لأنها ليست من النوع static

أما عندما أقوم بتعريف متغير جديد من النوع static ، لاحظوا أنني قمت بتعريف Property جديدة و لكنها من النوع static ، فهي تعني أن هذه الـ Property يمكن استدعاؤها من الكلاس نفسه ، بذكر اسم الكلاس قم ارفاقه مباشرة و ارفاق اسم الـ static ، إذاً عندما أكتب Car و هي اسم الكلاس بالحرف الكبير ، و اضع النقطة ، مباشرة أصبح لدي Property يمكن استخدامها على مستوى الـ Class .

 

دعونا الآن نتعامل مع الكلمة static بشكل أكبر .

لاحظوا هنا في داخل الكلاس ، وضعت أنه عند تعريف متغير جديد سيقوم بتغيير الـ Make ، مبدئياً سأقوم بعملها جملة ملاحظة ، و سأضع ، عندما يتم انشاء Object جديد ، قم بزيادة الـ Count برقم 1 ، فإذا قمت بطباعة Car.Count ، فعملية الزيادة لا تتم في الـ Constructer الذي يقوم بإعطاء parameter ، فأنا عندما قمت بإنشاء مجسم جديد ، لم أقم باستخدام هذا الـ Constructer ، بل قمت باستخدام الثاني ، و الذي يقوم بإعطاء وParameter ، ففعلياً هنا لا يوجد زيادة ، فبالتالي تظهر القيمة 0 ، لذلك سنقوم بعمل جملة الزيادة جملة ملاحظة و وضعها في الـ  Constructer الثاني ، و نجعل السيارة الثانية فارغة تستدعي الـ Constructer الأول ، و بذلك تكون السيارة الأولى و الثالثة تستدعي الـ Constructer الثاني ، أما الثالثة ، فتقوم باستدعاء الأول ، و عندها في كل Constructer يتم زيادة القيمة بواحد ، و لدي 3 سيارات ، فعندما أقوم بطباعة الـ Count يجب أن يظهر الرقم 3 .

 

موضوع الـ static  ليس حصرياً على الـ Property بل يمكن استخدامه كذلك في الـ Method .

لاحظواً أننا طول الوقت ، و من أول سطر لم نقم باستنساخ مجسم من الـ Console Class ، لم نقل له أعطني مجسم جديد و اريد استخدام هذه الدالة .

لاحظوا أن الـ Method ذات الاسم WriteLine تابعة مباشرة لاسم الكلاس ، و ليست تابعة لـ Object يتم اشتقاقه من الكلاس .

ايضاً مر معنا في درس التاريخ و الوقت أننا قمنا بالتعامل مع هذه الـ Property المسماة Now ، و هي لا تحتاج لعملي اشتقاق من الـ Data Type المسماة DateTime ، فقد حصلت عليها مباشرة من خلال النقطة ، لأن هذه الProperty عبارة عن static .

أيضاً لو لاحظتم في درس المصفوفات ، حيث تعاملنا مع دالة Reverse ، و هي ايضاً لا تحتاج لعملية اشتقاق من الكلاس Array .

إذا بالمثل سأقوم بإنشاء Method جديدة ، هذه الدالة من النوع static  أي أنها تابعة للكلاس بشكل كامل ، و سأقوم باستدعائها بالكلاس الرئيسي ، و حيث أن هذه الدالة تقوم بطباعة Count
و لو قمت بتنفيذ التطبيق سيقوم بطباعة عدد السيارات التي قمت بإنشائها من هذا الكلاس .

 

مصطلحات الدرس :

Garbage Collector :

Static :

Constructer :

Object Oriented Programming (OOP) :

Property   :

Object :

Class :

Dot Net Runtime :

Common Language Runtime (CLR) :

namespace   :

Nested Class :

null   :

managed   :

unmanaged  :

initialize   :

Initialization :

Parameter :

Reverse :

Count :

Public  :

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObjectLifeTime
{
    class Program
    {
        static void Main(string[] args)
        {
            //Car myCar = new Car();
            Car myCar = new Car("BMW","Z",1990,"Yellow");
            Car myCar2 = new Car();
            Car myCar3 = new Car("BMW","Z",1990,"Yellow");
            
            Car.PrintCount();
            //myCar.Color = "Black";

            //Car myOtherCar;
            //myOtherCar = myCar;
            //myOtherCar.Color = "Red";
            //myOtherCar = null;
            //myCar = null;
            
            //Console.WriteLine("{0}", Car.Count);
            Console.ReadLine();
            
        }
    }
    class Car
    {
        public Car()
        {
            //Make = "Nissan";
            Count++;
        }
        public Car(string make,string model,int year,string color)
        {
            Make = make;
            Model = model;
            Year = year;
            Color = color;
            Count++;
        }

        public static void PrintCount()
        {
            Console.WriteLine("{0}", Count);
        }

        public static int Count { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
        public int Year { get; set; }
        public string Color { get; set; }
    }
}

post

البرمجة كائنية التوجه OOP – الجزء الأول

البرمجة كائنية التوجه OOP :

السلام عليكم ورحمة الله وبركاته، عندما تم تطوير البرمجة كائنية التوجه Object Oriented Programming المعروفة بالإختصار OOP أحدثت ثورة كبيرة في علم البرمجة، فلقد قامت بحل العديد من الإشكاليات والمعضلات التي كانت تؤرق المطورين أنفسهم، سنأخذكم في جولة سريعة نشرح فيها أهم المبادئ للبرمجة كائنية التوجه ومن ثم نتطرق إلى كيفية إستخدامها داخل لغة #C مباشرة، فمن أهم مبادئها :

التغليف (Encapsulation ):

وتعني ببساطة منع الوصول إلى المتغيرات الموجودة داخل الكلاس بشكلٍ مباشر، والسماح بتعديلها أو استرجاعها من خلال دوال مخصصة لذلك، وتبرز أهمية التغليف في قدرتنا على وضع قواعد معينة للتعامل مع المتغيرات، مثلا لنفرض ان هناك متغير لتخزين عمر الشخص، لو أتحنا الوصول المباشر لهذا المتغير سنفقد أي تحكم بالقيمة التي سيدخلها الشخص الذي يستخدم هذه الفئة Class (مبرمج آخر)، ولربما لن يكون لديه معرفة كافية عن طريقة عمل هذه الفئة Class فربما سيفترض أن إدخاله للعمر 0 لن يسبب اي مشاكل، لكن هذا افتراض خاطئ، ربما في أحد دوال هذه الكلاس هناك عملية قسمة لمتغير آخر على هذا العمر، و القسمة على صفر تؤدي إلى حدوث خطأ، والمشكلة أن مثل هذه الأخطاء عادةً لا تظهر مباشرة لـ مستخدم الفئة Class، إنما يظهر الخطأ فيما بعد وربما أثناء عمل البرنامج لدى المستخدم النهائي وهي ما تعرف بإسم Run-Time Error، لكن لو قمنا بالسماح باستخدام هذا المتغير من خلال دالة فنستطيع التحكم وتنبيه المطور مباشرة عند ادخاله للرقم 0 للعمر، أو تحويل الـ 0 الى 1 او غيرها .. ولأن مطور الفئة Class يعرف آلية عملها بالتفصيل فيجب أن يحمي المتغيرات الموجودة داخلها.

الوراثة (Inheritance):

الوراثة هي عملية إنشاء كلاس جديد بنائاً على كلاس سابق، أو بمعنى آخر اشتقاق، وتبرز أهمية الوراثة في تمكيننا من إعادة استخدام أكواد مكتوبة سابقاً، وتعديل بعضها أو إضافة خصائص جديدة بدل من إعادة كتابتها كل مرة، وتسمى الفئة Class التي نرث منها بالأب Parent والتي نُورِّثُ إليها بالابن Son . لنفهم أهمية الوراثة نأخذ المثال التالي، لنفرض أن هناك فئة Class تقوم باستخدامها لإظهار زر على الشاشة، وهذه الفئة كتبها مبرمج غيرك وهي تعمل بكفائة، وداخل تطبيقك تحتاج لإضافة خصائص إضافية لهذا الزر ، أو خصائص غير موجودة حالياً، لنقل مثلاً خاصية النقر المزدوج، في هذه الحالة لديك عدة خيارات قد تستطيع القيام بها:
1 – الدخول إلى تلك الكلاس والقيام بتعديله وقد تقوم بتعطيل شيء فيها دون قصد.
2 – القيام بنسخ الكود الخاص بهذه الكلاس ولصقها ثم إجراء التعديلات واستخدام هذه الكلاس الجديدة، لكن في هذه الحالة أي شيء نقوم بتغييره او تطويره، او اصلاح بعض الاخطاء على الكلاس الأصلية يجب أن نغيره على هذه ايضاً، وهذا فيه إضاعة كبيرة للوقت.
3 – الوراثة ! عمل كلاس جديدة ترث الكلاس القديمة بكامل خصائصها، ثم تقوم بإضافة الخاصية الجديدة فقط، وبهذه الطريقة نتأكد من استمرارية عمل الكلاس القديمة بلا اي مشاكل، واي تطويرات على الكلاس القديمة ستنعكس ضمنياً على هذه الكلاس.

تعدد الأشكال (Polymorphism):

ويعني أن الكائن يمكن أن يتخذ أكثر من شكل، والفكرة ببساطة أن مجموعة كائنات ترث خصائصها من أب واحد، لكن كل منهم يقوم بتعديل هذه الخصائص لـ تقوم بأمر مختلف.
ومن أهم استخداماته هو القدرة على تمرير هذه الكائنات المختلفة إلى نفس الدالة، أي لو كان لدينا الكائنات التالية: مربع، مستطيل و مثلث، ولدينا كلاس اسمه Area للتعامل مع المساحات وفيها خاصية طباعة مساحة الشكل على الشاشة، بدون مفهوم تعدد الأشكال سيكون علينا أن نقوم بعمل ثلاث دوال لطباعة مساحة كل شكل من هذه الاشكال، مثلا PrintSquareArea و PrintTriangleArea و PrintRectangleArea لكن بتطبيق مبدأ تعدد الأشكال بإمكاننا الاكتفاء بـ دالة واحدة مثلا PrintArea وتستطيع استقبال جميع الاشكال، لانهم بالنهاية مشتقين من كائن واحد، وهذا ممكن ببساطة لان جميع الكلاسات الخاصة بهذه الاشكال يجب ان ترث من كلاس أب يمتلك الخصائص التي نحتاجها وليكن اسمه Shape مثلاً ولديه دالة CalculateArea لحساب المساحة، ثم تقوم كل كلاس ترث منه بتعديل طريقة حساب المساحة بما يناسبها، لكن المهم انها تمتلك هذه الدالة ! فتستطيع دالة الطباعة استدعاء الدالة على أي شكل يمرر لها دون الاهتمام بـ نوعه، المهم أنه يرث من اب يمتلك هذه الدالة فبالتأكيد أن الكائن الابن يمتلكها ايضاً.

تطبيق البرمجة كائنية التوجه OOP بواسطة #C

هناك بعض المصطلحات المرافقة للبرمجة كائنية التوجه التي يجب عليك كمطور الإلمام بها ومعرفتها، سنقوم بالتعرف عليها وإستخدامها مباشرة بشكل أسطر برمجة بإستخدام لغة C# ، وهنا  أهمها تباعاً :

1 – الفئات والكائنات (Classes and Objects)

الفئة هي عبارة عن نموذج أو وصف للكائن (blueprint)، أما الكائن فهو عبارة عن نسخة من هذه الفئة (instance)، على سبيل المثال، لو كان لدينا فئة Student فإننا نقوم بإنشاء كائنات من هذه الفئة كما يلي:

Student std = new Student();

فهنا لدينا Student هي النموذج العام، ثم قمنا بإنشاء كائن Std وهو مستقل بذاته، أي إذا قمنا بانشاء 10 كائنات، فإن التعديل على خصائص أحدهما لا يؤثر في الآخر، لكن التعديل على الفئة نفسها ينعكس على جميع الكائنات المنشئة منها. وهنا طريقة إنشاء الفئة Class في لغة #C :

Class Student
{
}

تتكون الفئة Class من التالي :
الخصائص والمتغيرات (properties): وهي عبارة عن البيانات التي يتم تخزينها داخل الفئة Class
الدوال (methods): ويمكن ان نقول انها تمثل سلوك هذه الكلاس أو بعبارة أبسط المهام والأمور التي تقوم بها هذه الكلاس، مثلا دالة Max لإيجاد الأكبر بين رقمين.
الأحداث (events): والأحداث عبارة عن قنوات للتواصل بين الفئات والكائنات المختلفة.

2 – الخصائص والمتغيرات Properties & Variables

يمكن أن نقوم بإضافة متغيرات Variables للفئات Classes في لغة ال #C كما يلي :

Class Student
{ 
       public int age;
}

لكن كما تلاحظ فقد قمنا بانتهاك أحد مبادئ البرمجة كائنية التوجه، والتي تم شرحها في بداية المقالة، وهو التغليف Encapsulation ، لذلك يجب أن نحول متغير العمر الى شيء محمي ويبقى داخل الفئة وهو ما يعرف بالإسم private  كما يلي :

Class Student
{ 
      private int age;
}

هنا يأتي دور الخصائص Properties والتي تقوم بتعديل أو طباعة قيمة هذا المتغير وتحافظ عليه من أي تعديل خارجي، حيث يمكننا تعريفها داخل لغة #C كالتالي :

Class Student
{
	private int _age;
	public int Age
	{
		get {return _age;}
		set 
		{
			if(value <= 0)
				_age = 1;
			else 
				_age = value;
		}
	}
}

وكما تلاحظ هنا، فإننا نملك تحكم كامل بالقيم المدخلة أو المرتجعة من هذا المتغير، أي أننا قمنا بتغليفه، وفي حال أننا رغبنا بتمكين لغة السي شارب من العمليات الداخلية لهذا المتغير يمكن تعريفها بصيغة مختصرة جداً كالتالي :

Class Student
{
	Public int Age { get; set; };
}

3 – الدوال Methods

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

public int Method(string param)
{
// code
}

ويمكن للفئة Class امتلاك أكثر من دالة تحمل نفس الاسم، لكن بشرط اختلاف عدد المتغيرات الممررة لها Parameters او اختلاف نوعها، وهو ما يعرف ب overloading ، كالتالي :

public int Method(string param) {};
public int Method(int param) {};

4 – دوال البناء Constructors

دالة البناء هي دالة يتم استدعائها بشكل تلقائي عند إنشاء الكائن باستخدام new ويجب ألا تقوم بإرجاع أي قيمة، وان يكون اسمها نفس اسم الفئة Class، كما يمكنك انشاء اكثر من دالة بناء من خلال ال overloading وعادة تستخدم دالة البناء لتهيئة الكلاس ووضع قيم أولية لـ متغيراتها قبل البدء باستخدامه.وهذا مثال عليها

public class SampleClass 
{
	public SampleClass()
	{
	}
	public SampleClass(int age)
	{
	}
}

كما تلاحظ، قمنا بإنشاء دالتي بناء، الاولى سيتم استدعائها عندما ننشئ كائن بهذا الشكل

SampleClass sc1 = new SampleClass();

والثانية عند تمرير قيمة مثل

SampleClass sc1 = new SampleClass(22);

5 – الكلاسات المتداخلة Nested Class

بإمكاننا تعريف فئة Class داخل فئة أخرى، وتسمى nested class اي فئة داخلية أو متداخلة

class Main
{
	Class Nested
	{
	}
}

كما نلاحظ هنا الكلاس Nested موجودة داخل الكلاس Main ونستطيع استخدامها بهذا الشكل

Main.Nested nested = new Main.Nested();

6 – سماحية الوصول (Access Modifiers)

نستطيع التحكم بإمكانية الوصول إلى المتغيرات والدوال داخل الكلاس عن طريق ال Access Modifiers ، وهناك خمس أنواع :
عام (public): نستطيع الوصول إلى هذا المتغير أو الدالة من اي مكان في المشروع، او حتى من خلال مشروع آخر يعتمد على هذا المشروع.
خاص (private): نستطيع الوصول إلى هذا المتغير أو الدالة من خلال نفس الكلاس فقط، وليس من أي مكان آخر.
محمي (protected): نستطيع الوصول إلى هذا المتغير أو الدالة من نفس الكلاس او من كلاس أخرى مشتقة منها (أي ترث منها كما شرحنا سابقاً).
داخلي (internal): نستطيع الوصول إلى المتغير أو الدالة من نفس المشروع فقط، أي أن المشاريع الأخرى التي تعتمد على هذا المشروع لا تستطيع الوصول اليه.
داخلي محمي (protected internal): نستطيع الوصول إلى هذا المتغير أو الدالة من نفس المشروع أو من كلاس موجودة في مشروع آخر تشتق (ترث) من هذه الكلاس.

تم كتابة الجزء الاول من المقالة بواسطة Ward Mahmoud وترجمتها إستناداً إلى مقالة أصلية هنا، نلقاكم في الجزء الثاني قريباً إن شاء الله.

post

بولي Poly مقصدك للمجسمات الخاصة بالواقع الإفتراضي

السلام عليك ورحمة الله وبركاته، أطلقت شركة Google موقع متخصص بتحميل المجسمات القليلة التفاصيل والتي قامت بتسميته Poly ، حيث أنها أعطت الفرصة لمن يقومون بتطوير تطبيقات الواقع الإفتراضي Virtual Reality المعروف بالإختصار VR والواقع المعزز Augmented Reality المعروف بالإختصار AR ،بإستخدام ألاف النماذج 3D Models القابلة للتحميل المباشر والإستخدام في تطوير التطبيقات السابقة.

استخدم Poly في كل مكان:

من الجدير بالذكر أن معظم التصاميم الموجودة هي من خلال تطبيقي  Tilt Brush  و Blocks  التي تمكنك من تصميم النموذج داخل الواقع الإفتراضي، بالتالي يمكنك تصديره ليراه الجميع، حيث قامت شركة Google  بإيجاد خدمة Poly خصيصاً لرفع تصاميمك من التطبيقين السابقين، لكن هناك إمكانية لرفع النماذج التي قمت بصنعها خارج هذين التطبيقات بواسطة الإمتداد OBJ وملف الخامة الخاصة به MTL . أيضاً يمكنك إستدعاء أي نموذج للتعديل عليه أو إستخدامه في التطبيقين السابقين أو حتى في تطوير لعبتك على محرك الألعاب Unity.

ألاف النماذج تنتظرك:

يمكنك زيارة الموقع poly.google.com لتجد العديد من النماذج، فإن قمت بالبحث عن طائرة مثلاً ووضعت Plane ستجد عشرات النماذج، قم بإختيار أي واحدة منها وقم بتصديرها لتستخدمها في مشاريعك، لكن إنتبه أن هناك بعض النماذج يشترط عليك أن تقوم بذكر إسم صاحبه في حال إستخدمته في مشروعك. ليس هذا فحسب، بل يمكنك تحويل أي مجسم أعجبك إلى صورة متحرك Gif لتستطيع نقلها لأي مكان آخر بعد ذلك، كما في الصورة التالية:

 

 

post

#16 التعامل مع النصوص Strings – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : KUT

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  التعامل مع النصوص Strings

كيفَ يُمْكِنُنا التَّعامُلُ مَع النُّصوصِ المُخْتَلِفة ، و كَيْفَ يُمْكِنُنا اقْتِباسُ جُزْءٍ مُعَيَّنٍ مِنْ نَصٍّ كامِلٍ ، و كيف يمكننا استبدال أحرف معينة في نص كامل ، و كيف يمكننا أيضاً معرفة عدد خانات الحروف في نص ما ؛ هذا ما سوف نعرفه في هذا الدرس بعد الفاصل إن شاء الله .

 

السلام عليكم و رحمة الله و بركاته ، و أهلاً بكم في درس جديد من دروس سلسلة تعلم البرمجة للمبتدئين كلياً بواسطة السي شارب .

بسم الله الرحمن الرحيم

التعامل مع النصوص هو أمر أساسي في التطبيقات المستخدمة ، ففي كل مشروع يجب أن يكون هناك نصوص متداولة

و من خلالها يتم استخدامها في أمور معينة ، و عمل تعديلات عليها ، لذلك يجب أن يكون عندك معرفة بالأدوات و الـ Methods التي بإمكانك استخدامها للحصول على نص أو جزء من نص  ، و تعديل نص معين يمكنك استخدامه في البرنامد الخاص بك

 

نبدأ بإنشاء مشروع جديد بلغة #C من النوع Console App

في البداية سأكتب الأسطر التالية لأننا سنستخدمها بشكل أساسي

نلاحظ الآن أننا إذا قمنا بتشغيل البرنامج فلن يظهر شيء

حسناً ، إذا توجب علينا في حالة ما استخدام علامتي التنصيص في نص معين ، فإذا حاولت إضافة علامتي تنصيص فسيحدث مشكلة ، لماذا ؟

لأن الـ Compiler أخذ الجزء الأول و اعتبر العلامة الثانية في المنتصف هي نهاية النص الأول .

لذلك إذا أردت استخدامها فبإمكانك وضع Back Slash قبلها لكي تخبر الـ Compiler  أن هذه العلامة هي فعلاً رمز  سيستخدم داخل النص

نوضح الفرق بين الـ Slash و الـ Back Slash حتى لا يحصل التباس ، فالـ Slash  هي التي تكتب بالشكل (  /  )

أما الـ Back Slash فتكتب (  \  )

و نلاحظ أن الـ Slash /    لا تعمل عمل الـ Back Slash

الآن بعد إضافة الـ Back Slash و تشغيل التطبيق سنلاحظ أن البرنامج قام بطباعة علامتي التنصيص بشكل صحيح

و هذا هو أول استخدام للـ Back Slash

نقوم بتحويل الجملة السابقة إلى جملة ملاحظة .

 

الآن في هذه الجملة الجديدة أحتاج إلى النزول إلى سطر جديد … فإنني إن قمت بطباعتها فستظهر ف نفس السطر

لذلك إن أردنا النزول لسطر جديد فسنكتب   (Back Slash + n)      ، و عندها سيفهم الـ Compiler أنه عند هذه النقطة قم بالنزول إلى سطر جديد . و بتنفيذ البرنامج نرى أن المطلوب قد حدث فعلاً

 

نقوم بتحويل الجملة السابقة أيضاً إلى جملة ملاحظة .

 

الآن ماذا لو أردنا طباعة الـ Back Slash  في النص المراد طباعته ، فبوضعها مباشرة ضمن التطبيق ستظهر مشكلة في تطبيقنا ، و السبب أن الـ Compiler افترض أن هذا الـ Back Slash سيأتي بعده Character  معين لكي يقوم بعملية معينة ، لكن هنا في مثالنا الـCharacter التالي للـ Back Slash  هو مسافة فارغة

لذلك إن أردت استخدام الـ Back Slash قم بوضع Back Slash قبلها مباشرةً ، بالتالي فإن الـ Back Slash  الذي سيأتي ثانياً هو الذي سيتم طباعته ، أما المكتوب قبله مباشرة سيخبر الـ Compiler أن التالي هو عبارة عن نص وليس Back Slash escape Character

نلاحظ أننا إذا قمنا بتشغيل التطبيق سيقوم بطباعة المطلوب بشكل صحيح و دون مشاكل أو أخطاء

حسناً .. ماذا لو كان لدينا أكثر من Back Slash  في ذات النص ، فهل سأذهب إلى كل واحد منها و أضع قبله Back Slash إضافي ؟؟

بالطبع لا ، فبإمكانك الذهاب إلى ما قبل علامة التنصيص التي في بداية النص و إضافة الرمز @ ، و التي بدورها ستخبر الـ Compiler أن يعتبر كل رموز Back Slash الموجودة ضمن النص عبارة عن Character  عادي و ليس Back Slash Escape Character، و بالتالي تخبره أن يقوم بطباعة هذا الرمز

 

تكلمنا سابقاً عن :

;string myString = string.Format(“{0} = {1}” ,”First” , “Second” )

و كما تحدثنا ، إن أردت وضع قيمة معينة داخل نص فلا داعي لكتابة الجملة ثم أقوم بإنهائها ثم أضع القيمة ثم أعود لمتابعة الجملة ، بدلاً من ذلك سأقوم بوضع index  ، بحيث يقوم الصفر بأخذ أول خانة مباشرةً بعد الـ string

و الرقم 1 يقوم بأخذ الخانة رقم 2 ، و يتم فصل الخانات بفاصلة

بتشغيل التطبيق نلاحظ أنه أخذ أول قيمة بعد الـ string عند الرقم 0 ، ثم قام بأخذ القيم الثانية عند الرقم 1

و ليس من الضروري أن نقوم باستخدام 0 ثم 1 ثم 2 …. ، فبإمكاننا أخذ القيمة الأولى مرتين ، أو نقوم بطباعة القيمة الثانية ثم القيمة الأولى .

 

حسناً.. هذا المكان الموحود في الكود السابق {…}  له Format خاصة به ، من الممكن أن نقوم باستخدامها للتأثير على القيمة الموجودة هنا بطريقة معينة

نقوم بطباعة جملة جديدة و وضعنا بعد الرقم الحرف C فسيقوم بتحويل القيمة إلى الموجودة إلى قيمة عملة ، حيث سيضع قبلها علامة العملة الخاصة ببلد معين ، فإن قمت تستخدم الدولار فسيقوم بوضع العلامة $ ، و تتغير بحسب العملة المتبعة في بلدك ، لكن في جهازي أنا استخدم الليرة التركية ، فسيظهر علامة استفهام لأن رمز الليرة التركية غير معرف

 

الآن إذا كان لدينا رقم طويل بحيث يكون صعب القراءة ، كما تعلمنا في دراستنا فإن الرقم عادة يقسم بحيث يوجد فاصلة بين كل 3 خانات ، فإذا أردت أن يكون الرقم مفصولاً كذلك فيمكن أن نستخدم الحرف N ، عندها سيقوم بوضع الفواصل و النقط و عند التنفيذ نلاحظ أنه أضاف النقط بحيث يقسم كل 3 منازل ، و يضيف الفاصلة العشرية حتى لو لم تكن موجودة ، و يضيف الصفر إلى يمينها

 

ماذا لو أردنا استخدام النسبة المئوية percentage ، مثلا 20% , 30%

فيمكنك استخراجها باستخدام الحرف P و سنكتب في البداية كلمة percentage أو أي نص آخر

عندها سيقوم بتحويل الرقم  251. إلى 25.10%

 

ماذا لو أردت استخدام Format خاص بي

حيث سأقوم بإضافة الفواصل و النقاط و الشرطات بحسب رغبتي ، فيمكن عمل ذلك كما يلي،

ليكن لدي الرقم 1234567890 و اريد أن أحوله إلى رقم هاتف

لاحظو بعد النقطتين يمكننا طباعة الرقم كما نريد

فنضيف (###) ###-####)

كل إشارة من الإشارات السابقة هي عبارة عن خانة ، و بذلك قمنا بتنسيق الرقم كما أردنا ، و بتطبيق البرنامج سيطبع الرقم (123) 456-7890

و هذا يعد Format خاص

 

ماذا لو أردت التعامل مع نص حقيقي

لدي جملة و أريد أن آخذ أجزاء منها أو أقوم بعمليات عليها فماذا أفعل

سنعرف المتغير myString من النوع string  ثم أقول له

myString القديم سيصبح muString نفسه و اضع نقطة ، و بمجرد وضع النقطة ، و لأنه متغير نصي سيظهر لديك جميع الـ Methods الخاصة بـ string ، و بالطبع لكل نوع من أنواع البيانات Methods  خاصة به

يمكنني هنا أن أقوم بعملية قص عن طريق اختيار الدالة Substring التي اخترناها بعد النقطة

نفتح قوسي الدالة و نكتب 5 على سبيل المثال ، عندها سيقوم بقص أول 5 خانات و يطبع الباقي

يمكننا عن طريق إضافة فاصلة و رقم آخر إلى المثال السابق ، و عندها سيقوم بطباعة ما بين الخانة 5 و 11 ، و يقوم بحذف الباقي

 

ماذا لو أردت أن تحول كل أحرف الـ string إلى حروف كبيرة

عندها سنستخدم الدالة ToUpper بدلاً عن الدالة Substring ، و بعندها سيقوم بطباعة الخانات كلها مع تغيير حالة الحروف إلى حروف كبيرة

 

ماذا لو أردت استبدال خانة أو حرف بخانة أخرى ،

مثلا في النص السابق أريد استبدال خانة المسافة بخانة أخرى ، فعندها سنستخدم الدالة Replace ،

و هذه الدالة تحتاج إلى قيمتين ، فالأولى هي Old Character  و الثانية هي New Character

نكتب كل قيمة بين علامتي تنصيص ، و يفصل بين القيمتين بفاصلة

ندخل القيمة الأولى هي المسافة ، أما الثانية نجعلها الرمز –   ، عندها سنرى أن التطبيق استبدال المسافة بالرمز –

 

ماذا لو اردنا حذف جزء من الكلمة الموجودة ، فيمكن استخدام الدالة Remove  ، و لهذه الدالة أكثر من استخدام

فلو أدخلنا رقم واحد فقط ،  و ليكن الرقم 5 ، فسنلاحظ أنه أخذ أول 5 خانات و حذف الباقي

و لو قمنا بوضع قيمتين فسيقوم بحذف ما بين الخانة 5 و 11 و يطبع كل ما تبقى

 

استخدام الـ StringBuilder :

هناك قضية يجب أن ننوه لها ، فاستخدامك للـ string مكلف فعليا ، و نعني بذلك ، حاول قدر الإمكان التقليل من استخدامك للـ string

فاستخدامك له و تخزين Data  كبيرة داخله يحجز مساحات كبيرة في الذاكرة ، و هناك فرق شاسع بي تخزينك للـ integer  و تخزينك للـ string

لذلك حاول أن تكون حذراً و دقيقاً في استخدامه

 

لاحظ الآن سأقوم بمحاولة طباعة لـ string ضخم جداً ، و أقوم باستخدامه بطريقة غير مجدية

لاحظو هذه الطريقة في كتابة الحلقة for  ،

نكتب كلمة for و لا نكتب مسافة بعدها ، ثم نضغط Double Tab فسيقوم بوضع الهيكل الخاص بحلقة for

و هذه الميزة غير موجودة في كافة المحررات

بعد وضعه للهيكل الخاص يمكن التعديل عليه

 

سنشرح قضية هنا مهمة

لاحظو هنا القيم الموجودة قيمة integer  و في بعض الأحيان لا يقبل وضع قيمة int في متغير string

فمن الممكن تحويل أي متغير يمكن تحويله مهما كان نوعه  إلى string عن طريق الدالة ToString ،

الآن سيقوم البرنامج بعملية يأخذ القيمة الجديدة و وضعها في مكان معين ثم أخذ هذا المتغير مرة أخرى ،

و هذه العملية غير صحيحة كما تعلمنا ، فهي تقوم بعملية إضاعة

نحن هنانقوم بعملية 100 حلقة ، لكن تخيل لو كان لدينا 1000 حلقة أو مليون حلقة ، فسيكون مكلفاً جداً و سيقوم التطبيق باستهلاك مساحات كبيرة

لذلك لو كان لدينا string  كبير و يحتوي على أمور تجعلك بحاجة إلى القيام بعملية إضافة قيم له

فيفضل استخدام نوع جديد اسمه StringBuilder ، هذا النوع جداً مميز لاستخدام النصوص الكبيرة و عملية إضافة القيم إلى المتغير

لاحظو في المثال السابق كان يقوم بالإضافة بأسلوب غير مجدِ ، لذلك سنقوم بتحويل السابق إلى جمل ملاحظة

و مثلا هنا سنقوم بتعريف متغير من النوع StringBuilder باسم myString

 

لو قمنا بتطبيق البرنامج سيقوم تماما بعمل البرنامج السابق ، لكن قام بتقليل المساحة المستخدمة و لم يقم بوضعها في مكان و نقلها إلى مكان آخر ، بل قام بعمليات خاصة و مميزة للتقليل من حجم الذاكرة ،

 

إذا يفضل استخدام الـ StringBuilder إذا كان لدينا نص كبير يتم قراءته ، كملف تقوم بتخزين نصوص عليه ، و تحتاج لقراءته مرة أخرى ، يفضل وضعه بـ StringBuilder لأنه مخصص للنصوص الكبيرة

 

و إلى هنا نصل إلى نهاية درسنا :

تعلمنا طريقة استخدام الـ Back Slash Escabe Character

يمكنكم الاطلاع على  Standard Numeric Format String من شركة Microsoft

ستجدون بها جميع الخانات التي يمكن استخدامها

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

ملخص الدرس

مقدمة:

السلامُ عليكم ورحمةُ اللهِ وبركاته، وأهلاً بكمْ في الدرسِ السادس عشر من دروسِ سلسلةِ، تَعلُمِ البرمجةِ للمبتدئينَ كلياً بواسطةِ السي شارب، في هذا الدرس سنتعرف على كيفية التعامل بشكل أكبر مع النصوص، كونها شيء أساسي في كل المشاريع، سنتعلم كيف نقوم بقص جزء معين من جملة، وكيف نقوم بطباعة أرقام بهئية خاصة نقوم بتعريفها.

التعامل مع النصوص Strings :

لا يخلو تطبيق صغير أو كبير من إستخدام النصوص والتعامل معها، لذلك هناك عدد كبير من الدوال للنوع النصي String يمكنك معرفة المزيد عن الدوال التي تقوم بوظائف معينة، هنا شرح لبعضها :

رموز خاصة Escape Character : ويتم بإضافة \ وبعدها خانة مثل : n لسطر جديد ، ” لطباعة التنصيص داخل نص، \ لطباعته داخل نص، القائمة الكاملة للحروف هنا.
تهيئة النص string.Format : وذلك بإستخدام أرقام Index ويمكن إضافة تخصيص لها مثل : N لطباعة الأرقام بالفواصل ، P لطباعة قيمة مئوية، القائمة الكاملة هنا.
Substring : تقوم بعمل قص للنص.
ToUpper : تقوم بتحويل جميع الأحرف إلى أحرف كبيرة Capital letter .
Replace : إستبدال نص بنص آخر.

 

مصطلحات الدرس :

Compiler :

Back Slash :

Character :

Back Slash Escape Character :

index :

Format :

Percentage :

Substring :

ToUpper :

Replace :

StringBuilder :

Double Tab :

Standard Escape Format String :

 

تجد في الأسفل الأسطر البرمجية التي قمنا بكتابتها خلال شرح الدرس.

post

النسخة 2017.2 من محرك Unity متاحة الآن!

السلام عليكم ورحمة الله وبركاته

عن النسخة :

النسخة التي وُعدنا بها من شركة Unity لمحركها الشهير Unity Engine أصبحت متاحة الآن! نعم النسخة 2017.2 أصبحت قابلة للتحميل، وبإمكانك الحصول عليها من هنا. التي تحتوي على العديد من الميزات الجديدة والتحديثات وحلول لمشاكل كانت تؤرق المطورين.

العناوين الرئيسية :

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

  • محرر المراحل Tilemap : 

  • أو يمكن أن نطلق عليه باني الخرائط، فهي أداة مميزة تعطيك تحكم كامل لبناء خرائط لعبتك ثنائية البعد، فسابقاً كان العمل أصعب من حيث أنك مضطر لوضع المربع الواحد Sprite واحداً تلو الأخر بطريقة يدوية، على الرغم من وجود أدوات مساعدة مثل ال Snap وغيرها، إلا أن هذه الميزة ستوفر الكثير من الوقت على المطورين.

مدير الإنتاج cinemachine الثنائي الأبعاد:

شهدنا في الإصدارات السابقة تواجد مدير الإنتاح الغني عن التعريف cinemachine للألعاب ثلاثية البعد 3D والتي بإمكانك التحكم في الكاميرات الموجودة في لعبتك وعمل الكثير من الميزات الحصرية التي تختصر عليه المئات من الساعات لعملها بمفردك، في هذه النسخة أصبحت الميزة متاحة لألعاب البعد الثاني 2D أيضاً، كما هو موضح في الفيديو السابق.

الدروس التفاعلية Interactive Tutorials :

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

ميزة إستيرا المجسمات Asset Management :

أو ما يعرف بالـ DCC المختصر من Digital Content Creation ، فالآن أصبح من السهل التعامل مع التطبيقات المختلفة مثل Autodesk وغيرها، ليس فقط إضافة ميزات لما تحويه هذه الملفات مثل الملف الشهير FBX الذي يحوي المجسمات والصور والحركة فحسب، بل إمتد الموضوع لإضافة مجسم جديد يمكنك إنشاءه وربطه لاحقاً بملف من تلك البرامج مما يتيح لك التعديل الآني ومن غير معاناة من إنتظار الوقت الكثير لإنعكاس التعديلات بين البرامج، فلقد تم إضافة Linked Prefabs  إلى قائمة الإنشاء كما هو موضح في هذا الفيديو :

إضافات للواقع الإفتراضي/المعزز XR :

يتضح جلياً تركيز المحرك على إعطاء القدرة القصوى لمطوريه للتماشي مع أكثر التطبيقات طلباً في الوقت الحالي، فقد إعتبرت كبرى الشركات مثل Microsoft و Sony و Google سنة 2016 على أنها سنة الواقع الإفتراضي VR المختصر من Virtual Reality والواقع المعزز AR المختصر من Argumented Reality بجدارة، أو ما يعرف كليهما بالإختصار XR ، فهناك العديد من الميزات التي تم إضافتها لتسهل العمل مع هذه التطبيقات، فها هي تضيف Vuforia  إلى محركها ضمنياً، وتدعم OpenVR و Google ARCore كما في الفيديو التالي :

ليس هذا فحسب، فهناك بعض الإضافات والتحسينات كالتالي :

+ ميزة Timeline للأصوات : بإمكانك الآن التعامل مع الأصوات أيضاً
+ تحديثات بالـ Profiler لتحليل اللعبة بشكل أكثر تفصيلاً
+ ميزة Lightmap background لإضافة لايت ماب للأماكن الفارغ سابقاً
+ أصبحت الأشجار يتم حساب ال Lightmap الخاص بها أيضاً
+ تحسينات على نظام ال Particle System

 

الخلاصة

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