דוגמאות

בדוגמאות ל-Android Game Development Extension מוצג איך להשתמש בתכונות המרכזיות של התוסף. כאן מתוארות הדוגמאות וההגדרות הנדרשות להרצה שלהן.

הדוגמאות הבאות זמינות בדף ההורדות:

  • HelloJNI: פרויקט מבוא.
  • Endless-Tunnel: פרויקט ל-Android בלבד.
  • Teapot: פרויקט בפלטפורמות שונות ל-Windows ול-Android.
  • AssemblyCode-Link-Objects: תבנית לפרויקט עם קוד מקור של אסמבלר.

לפני שמתחילים

  • מתקינים את התוסף Android Game Development Extension ואת הדוגמאות. פרטים נוספים זמינים במדריך למתחילים. בנושא הזה מוסבר גם איך ליצור ולהריץ דוגמה, תוך שימוש בגרסה ל-Android של הדוגמה Teapot.

  • במדריך הגדרת פרויקט מוסבר איך מגדירים את ההגדרות של פרויקט שמשתמש בתוסף, למשל הוספת פלטפורמת Android ו-APK.

HelloJNI

הדוגמה HelloJNI היא פרויקט פשוט שמציג את ההודעה 'Hello From JNI' בחלון של האפליקציה. בפרויקט נעשה שימוש בקבוצה שונה של קוד מקור ל-Windows ול-Android.

  • ספריית קוד המקור של Android וסקריפטים ל-build של Gradle: HelloJNI\AndroidPackaging
  • קוד המקור של Windows וספריית הפרויקט ב-Visual Studio: HelloJNI

כשמפתחים את הפרויקט, Visual Studio מעביר את ההגדרות הבאות לקובץ build.gradle ברמת האפליקציה. כדי לשנות את ההגדרות האלה, צריך לשנות את סקריפט ה-build של Gradle.

  • MSBUILD_NDK_VERSION
  • MSBUILD_MIN_SDK_VERSION
  • MSBUILD_JNI_LIBS_SRC_DIR
  • MSBUILD_ANDROID_OUTPUT_APK_NAME
  • MSBUILD_ANDROID_GRADLE_BUILD_OUTPUT_DIR

כדי להגדיר ולהריץ את הדוגמה:

  1. ב-Visual Studio, פותחים את הדוגמה HelloJNI ובונים אותה.
  2. מוסיפים פלטפורמה מסוג Android arm64-v8a. למידע נוסף, ראו הוספת פלטפורמת Android.
  3. מוסיפים לפלפורמה החדשה פריט APK ל-Android.
  4. מריצים את הידור הפרויקט.
  5. מוסיפים את פלטפורמות Android הבאות ואז מוסיפים לכל אחת מהן פריט APK ל-Android: Android-armeabi-v7a,‏ Android-x86 ו-Android-x86_64.
  6. יוצרים ומריצים את הדוגמה.

Endless-Tunnel

הדוגמה Endless-Tunnel היא משחק ל-Android שבו השחקן אוסף קוביות לבנות ומנסה להגיע לסוף המנהרה. הוא הועבר מדוגמה של OpenGL במאגר Android NDK ב-GitHub. הדוגמה לא מספקת גרסה של המשחק ל-Windows.

ההגדרות והפלטפורמות של Android כבר מוגדרות בדוגמה, כך שתוכלו ליצור ולהריץ את הפרויקט ב-Visual Studio בלי שינויים. כשפותחים את הפתרון, ב-Solution Explorer מוצגים המודולים הבאים:

  • endless-tunnel: מודול האפליקציה שמוצגת בו הלוגיקה של המשחק.
  • glm: קובץ snapshot של מאגר OpenGL Math שנוצר כספרייה סטטית.
  • native_app_glue: מעטפת NDK שמתקשרת עם האובייקט NativeActivity.

Teapot

בדוגמה Teapot מוצגת קטגוריה קלאסית של תה, שעבר רינדור באמצעות OpenGL ES והוענק ל-Android Game Development Extension כדי להדגים את התכונות הבאות:

  • פיתוח פרויקטים בפלטפורמות שונות: אפשר ליצור את הדוגמה Teapot ל-Windows ול-Android.
  • שימוש בהתאמה אישית של אריזות ל-Android: סקריפטים של build ב-Gradle הועברו לספריית השורש של הדוגמה, שבה נמצא הקובץ Teapot.sln.
  • הגדרות מותאמות אישית של Android שממחישות איך להשתמש ב-Address Sanitizer‏ (ASan) וב-Hardware Address Sanitizer‏ (HWASan).

ההטמעה של הדוגמה Teapot מחולקת למספר חלקים, כפי שמקובל במשחקים ובאפליקציות גדולים בפלטפורמות שונות:

  • מודול GameApplication: מגדיר פעולות של משתמשים ומצבים של אפליקציות, כמו תנועת סיבוב של משתמש בתרמוסטט או עדכון נתונים סטטיסטיים של האפליקציה.
  • מודול GameEngine: הטמעת מודול העיבוד של הליבה.

כדי להגדיר את הדוגמה ולהריץ אותה ב-Android, אפשר לעיין במדריך למתחילים. כדי להגדיר את הדוגמה ולהריץ אותה ב-Windows:

  1. מתקינים את GLEW:
    1. מורידים את GLEW ומפרקים את הקובץ.
    2. מעתיקים את הקבצים הבינאריים מ-$your-glew-directory\bin\Release\x64 אל %SystemRoot%\system32.
  2. התקנת freeglut:
    1. מורידים את freeglut ומפרקים את הקובץ.
    2. מעתיקים את $your-freeglut-directory\bin\x86\freeglut.dll אל %SystemRoot%\system32.
  3. מוסיפים את יחסי התלות של פרויקט freeglut:
    1. פותחים את Teapot.sln ב-Visual Studio.
    2. בתפריט, לוחצים על ניפוי באגים > x64 > Local Windows Debugger.
    3. ב-Solution Explorer, לוחצים לחיצה ימנית על GameApplication ובוחרים באפשרות Properties > C/C++ > General > Additional Include Directories.
    4. מוסיפים את $your-freeglut-dir\include לנתיב.
      צילום מסך של תיבת הדו-שיח Additional Include Directories.
    5. לוחצים על אישור.
    6. בוחרים באפשרות Linker > General > Additional Library Directories.
    7. מוסיפים את $your-freeglut-dir\lib\x64 לנתיב. צילום מסך של תיבת הדו-שיח 'ספריות נוספות'.
    8. לוחצים על אישור.
    9. בוחרים באפשרות Linker > General > Additional Library Directories.
    10. מוסיפים את freeglut.lib לנתיב.
    11. לוחצים על אישור.
  4. מוסיפים את יחסי התלות של פרויקט GLEW:
    1. בחלונית Solution Explorer, לוחצים לחיצה ימנית על GameApplication ובוחרים באפשרות Properties > C/C++ > General > Additional Include Directories.
    2. מוסיפים את $your-glew-dir\include לנתיב.
    3. לוחצים על אישור.
    4. בוחרים באפשרות Linker > General > Additional Library Directories.
    5. מוסיפים את $your-glew-dir\lib\Release\x86 לנתיב.
    6. לוחצים על אישור.
    7. בוחרים באפשרות Linker > General > Additional Library Directories.
    8. מוסיפים את glew32.lib לנתיב.
    9. לוחצים על אישור.
  5. מריצים את הדוגמה ב-Windows:
    1. בסרגל הכלים של Visual Studio, לוחצים על לחצן ההפעלה Local Windows Debugger.
    2. הדוגמה אמורה להיראות כך:
      צילום מסך של הדוגמה Teapot שפועלת ב-Windows.

זהו פרויקט תבנית שמראה איך ליצור ספרייה מקומית ל-Android מקוד מקור של אסמבלר ו-C/C++. אלה הרכיבים העיקריים:

  • AssemblyCode-Link-Objects: הספרייה הראשית של Android שנוצרה מקוד מקור של C++‎ ו-assembly.
  • StaticLib: ספרייה סטטית מסייעת שמייצאת את הפונקציה from_static_lib_assembly_code_as.

הפרויקט תומך בכמה ארכיטקטורות. לכל ארכיטקטורה נתמכת יש קובצי מקור משלה שמטמיעים פונקציות שיוצאו מ-StaticLib. צריך לכלול רק את קובצי המקור של האסיפה לפלטפורמות שאתם מפתחים. הפרויקט הזה כולל קובצי הרכבה ב-builds באמצעות כלים מותאמים אישית ל-build.

כדי להגדיר ולבנות את הדוגמה:

  1. ב-Visual Studio, מוודאים שכלי ה-build בהתאמה אישית מוגדרים לקובצי האסיפה:
    1. ב-Solution Explorer, לוחצים לחיצה ימנית על קובץ האסיפה ואז על Properties. תיפתח תיבת הדו-שיח Properties Pages של הקובץ.
    2. בוחרים את ההגדרה והפלטפורמה, למשל All configurations עבור Android-arm64-v8a.
    3. מוודאים שהאפשרות כללי > החרגה מה-Build מוגדרת ל-לא.
    4. מוודאים שבקטע General (כללי) > Item Type (סוג הפריט) מוגדר Custom Build Tool (כלי build מותאם אישית).
    5. לוחצים על אישור אם יש שינויים שרוצים להחיל.
    6. מוודאים שהאפשרות Configuration Properties > Custom Build Tools > Command Line מוגדרת ל-$(AsToolExe) -o "$(IntDir)%(FileName).o" %(FullPath). ‏NDK כולל מאסם נפרד לכל ארכיטקטורת מעבד, ו-$(AsToolExe) ממופה למאסם הנכון. בדוגמה הזו נעשה שימוש בכלי הפיתוח של NDK כדי ליצור פרויקטים של Android ל-x86 ול-x86_64. אם רוצים להשתמש ב-yasm בפלטפורמת Android מסוג x86_64, צריך להשתמש ב-$(YasmToolExe) במקום זאת.
    7. מוודאים שהערך של Configuration Properties > Custom Build Tools > Outputs מוגדר ל-$(IntDir)%(FileName).o. המחרוזת הזו חייבת להיכלל בהגדרה Command Line.
    8. מוודאים שהאפשרות Configuration Properties > Custom Build Tools > Link Objects מוגדרת ל-Yes.

    לדוגמה, ההגדרות של Android-arm64-v8a אמורות להיראות כמו בצילום המסך הבא:

    צילום מסך של דף הנכס של כלי build מותאמים אישית.
  2. מריצים את ה-build של הפרויקט. הפקודה הזו יוצרת את הקובץ libAssmeblyCodeLinkObjects.so:
    1. פותחים את הקובץ AssemblyCode-Link-Objects.sln.
    2. בתפריט, לוחצים על Build > Build Solution.
  3. כדי לוודא שהפונקציות מיוצאות בצורה תקינה לספריית Android, משתמשים בכלי NDK‏ nm.exe:
    1. בשורת הפקודה, עוברים לספריית הדוגמאות.
    2. עוברים למיקום של ספריית Android שנוצרה על ידי ה-build. מיקום ברירת המחדל דומה למיקומים $sample_dir\$solution_configuration\$solution_platform\$platform ו-$sample_dir\Debug\Android-arm64-v8a\arm64-v8a בפלטפורמה arm64-v8a.
    3. מריצים את הפקודה הבאה כדי לוודא שהפונקציות נמצאות בקטע הסמלים המיוצאים:
        \ndk\toolschains\llvm\prebuilt\windows-x86_64\aarch64-linux-android\bin\nm.exe --defined-only \Debug\Android-arm64-v8a\arm64-v8a\libAssmeblyCodeLinkObjects.so

      בפלט אמורה להופיע רשימה של סמלים שכוללת את הסמלים הבאים:

         T from_shared_object_assembly_code_as
         T from_static_lib_assembly_code_as

PoolAllocator

הדוגמה PoolAllocator היא אפליקציה ל-Android עם מנהל זיכרון שמבוסס על מאגר, שמספק בלוקים בגודל קבוע בצורה יעילה מאוד.

מנהל ההקצאות מקצה מראש את כל הזיכרון בזמן האינטליקציה באמצעות mmap. המעקב אחרי בלוקים פנויים מתבצע באמצעות רשימה מקושרת. לאחר מכן, הקצאת זיכרון היא פעולת O(1) מהירה שמחזירה את החלק הקדמי של רשימת הקשרים, והקצאת זיכרון היא גם פעולת O(1) כי היא מוסיפה את הבלוק לחלק האחורי של רשימת הקשרים.

בדוגמה יש שתי הגדרות של פתרונות לשימוש ב-HWASan.

  • HWASan: ההגדרה הזו מדגימה את הגישה הפשוטה ביותר לשימוש ב-HWASan עם מנהלי זיכרון בהתאמה אישית. ההטמעה הפנימית של מנהל הזיכרון מוחלפת בקריאות malloc/free, ש-HWASan עוקב אחריהן באופן אוטומטי. בורר הזיכרון כבר לא פועל בתור בורר שמבוסס על מאגר, אבל HWASan עדיין יכול לעזור לכם לזהות באגים חשובים בזיכרון, כמו use-after-free.

  • HWASan-Advanced: ההגדרה הזו ממחישה איך לשלב את HWASan באופן מלא במקצה זיכרון מותאם אישית, בלי לשנות את מנגנון ההקצאה המקורי שבו המקצה משתמש. הוא משתמש בשיטות תיוג של HWASan כדי לתייג את בלוקי הזיכרון במאגר שהוקצה מראש, מעגל את גודל הבלוק לגודל מינימלי שנדרש על ידי HWASan ומאפס את התגים כשהבלוקים מוחזרים למאגר.

מומלץ להשתמש בהגדרה HWASan כי היא פשוטה יותר ועוזרת לזהות באגים נפוצים בזיכרון. כדאי לבדוק את ההטמעה של ההגדרה HWASan-Advanced כדי להבין איך HWASan פועל או כדי לשמור על הסמנטיקה הפנימית של מנהל הזיכרון בזמן השימוש ב-HWASan.