ساخت بازی در اندروید قسمت سوم

1395/1/12 هرمن حیدری 3353

سلام به همه دوستان

جلسه سوم آموزش بازی سازی در اندروید (البته با مقدمه ای از جاوا!) رو شروع میکنم. این جلسه مطالب مختلفی رو قراره بگم از جاوا؛ همونطور که جلسه پیشم گفتم برای اینکه سریع تر بتونیم پیش بریم و زودتر به بحث اصلیمون نزدیک شیم یه کم فشرده تر مطالب جاوارو میگم. البته معنیش این نیست که قراره قید گفتن یه سری چیزارو بزنم؛ منظور از "فشرده" بیان گستره وسیع تری از مطالب در همون تایم ثابت 1 ساعتیمونه! احتمالا جلسه بعدی رو طی 3 یا 4 روز آینده برگزار میکنم.

جلسه قبل رو دوتا برنامه ساده کار کردیم و خیلی مختصر با یک سری از ویژگی های زبان جاوا آشنا شدید. برای مثال اینکه چجوری میتونید متنی رو به جریان خروجی استاندارد ببرید. همینطور مشاهده کردید که این جریان خروجی به طور پیش فرض به صفحه نمایش متصل شده، ولی بهتون نشون دادم که میشه این مسیر رو تغییر داد و اون متن رو داخل یک فایل ذخیره کرد! به عنوان نمونه آخر یک سری از ویژگی های جدید زبان جاوارو بهتون معرفی میکنم و بهتون نشون میدم چجوری میتونید متن رو از جریان ورودی استاندارد بخونید و علاوه بر اون متن رو به جریان خروجی استاندارد خطا ( standard error stream) ببرید.


public class EchoText
{
  public static void main(String[] args)
  {
    boolean isRedirect = false;
    if (args.length != 0)
      isRedirect = true;
    int ch;
    try
    {
      while ((ch = System.in.read()) != ((isRedirect) ? -1 : 'n'))
        System.out.print((char) ch);
    }
    catch (java.io.IOException ioe)
    {
      System.err.println("I/O error");
}
    System.out.println();
}
}

این برنامه نسبت به 2تا برنامه قبلی کمی پیچیده تره! داخل متد main ابتدا یک متغیر از نوع boolean به نام isRedirect تعریف شده؛ متغیرهای نوع boolean تنها میتونن دو مقدار true یا false رو ذخیره کنن! متغیر isRedirect قراره به برنامه مون بگه که آیا ورودی ما داره از صفحه کلید سرچشمه میگیره یا از یک فایل؛ اگه این ورودی از صفحه کلید باشه مقدار isRedirect نادرست یا false و در صورتی که از فایل باشه مقدار این متغیر true خواهد بود. ما مقدار اولیه ی isRedirect رو false تعریف کردیم برای اینکه برنامه مون با این پیش فرض که ورودی قراره از صفحه کلید باشه شروع شه! اگه یه کم به اسم متغیرمون دقت کنید متوجه منظورم میشید؛ منظور از is redirect اینه که آیا مسیر دریافت ورودی تغییر کرده؟ (از مسیر پیش فرض یا صفحه کلید، به فایل) که اگه جواب بله یا true باشه یعنی ورودی مون رو از یک فایل دریافت کردیم!

متاسفانه هیچ راه ساده ای برای تعیین اینکه آیا این مسیر تغییر کرده یا نه وجود نداره؛ به همین خاطر برنامه نیاز داره که خود کاربر این مسئله رو با مشخص کردن یک یا چند آگورمان خط فرمان بهش اطلاع بده! ساختار تصمیم گیری if قراره وظیفه این کار رو به عهده بگیره و پارامتر args رو ارزیابی کنه که آیا آرگومانی از خط فرمان بهش پاس داده شده یا خیر! عملکرد این ساختار به این شکله که یک عبارت بولی (عبارتی که میتونه حاصل ارزیابیش true یا false باشه!) بین پرانتزهای if مورد ارزیابی قرار میگیره؛ اگه حاصل ارزیابی این عبارت true یا درست بود خط بعد از if (یا بلاک if که اینجا باهاش سروکار نداریم!) اجرا میشه، وگرنه کنترل اجرای برنامه از روی این خط (یا بلاک) رد شده و به اولین خط بعد از اون منتقل میشه!

عبارت بولینی که ما اینجا باهاش سروکار داریم args.length != 0 هستش. عملگر =! نامساوی بودن عملوند سمت چپ با عملوند سمت راست خودش رو بررسی میکنه؛ یعنی اگه args.length با 0 نامساوی بود این عملگر مقدار true و در غیر این صورت مقدار false رو برمیگردونه. پس اگه حداقل یدونه آرگومان خط فرمان به برنامه پاس داده شه، دیگه args.length مساوی 0 نیست و در نتیجه حاصل ارزیابی عبارت بولی ما true خواهد بود! و چون در این صورت خواهیم داشت if true، پس statement یا دستور بعد از خط if اجرا میشه؛ یعنی مقدار isRedirect برابر با true قرار میگیره! و این همون چیزی بود که میخواستیم؛ قرار بود اگه آرگومانی از خط فرمان پاس داده شه به برنامه، معنیش این باشه که مسیر دریافت ورودی تغییر کرده! بله این اتفاق افتاد، چون با این کار مقدار isRedirect از false به true تغییر پیدا کرد!

تو خط بعد متد main، متغیری از نوع int به نام ch تعریف شده. این متغیر قراره مقدار عددی هر کاراکتر که از جریان ورودی خونده میشه رو ذخیره کنه! (فعلا در نظر داشته باشید که به ازای هر کاراکتر، یک مقدار عددی صحیح، نامنفی و معین وجود داره!)

عد از این ماجراها، سورس کدمون وارد دنباله ای از کد میشه که توسط کلمه کلیدی try و آکولادهای باز و بسته ایشون احاطه شده! کدی رو داخل بلاک try مینویسیم که ممکنه تولید یک استثنا (exception) کنه! منظور از یک استثنا، شی یا objectی هستش که مشکلی رو توصیف میکنه؛ و کدی که داخل بلاک catch مینویسیم قراره این مشکل رو اداره کنه، یا در واقع به ما یا برنامه مون بگه که این مشکل از کجا بوده! (در آینده ای نزدیک در رابطه با exceptionها به قدر کافی صحبت خواهم کرد!) تو این برنامه، بلاک try شامل یک حلقه while هستش که وظیفه خوندن و نمایش دادن کاراکترهارو به عهده داره! حلقه while چیه؟ یک حلقه تکرار شبیه به حلقه for، اما با یک تفاوت کلیدی؛ غالبا از حلقه for زمانی استفاده میشه که تعداد دفعات تکرار حلقه از قبل مشخص و معین باشه (اگه یادتون باشه برای حلقه forمون تو برنامه قبلی یک متغیر به نام i تعریف کردیم، و مقدار اولیه و نهاییش رو هم بین پرانتزای for تعیین کردیم تا تعداد دفعات تکرار حلقه با مقدار متغیر i ست شه!) اما while یک حلقه وابسته به شرطه، که تعداد دفعات تکرار در اون اهمیتی نداره! عبارتی که بین پرانتزهای while قرار میگیره (شرط حلقه) یک عبارت بولی هستش (مثل ساختار if) و تا زمانی که حاصل ارزیابی این عبارت true باشه حلقه while به اجرای دستور یا دستورات بلاک خودش ادامه میده. "هر" حلقه forی رو میشه با while نوشت و برعکس! اما اگه قرار بود این دو به جای هم به کار برن نیازی نبود به طور مجزا به وجود بیان!

خب بپردازیم به شرط حلقه whileمون:

 ( ch = System.in.read() )   !=   ( (isRedirect)  ?   -1  :  'n' )

همونطور که گفتم این عبارت یک عبارت بولیه؛ عملگر =! عدم تساوی عملوندهای سمت راست و چپ خودش رو بررسی میکنه و با توجه به نتیجه ارزیابی، یکی از مقادیر true (در صورت عدم تساوی) یا false (در صوت تساوی) رو برمیگردونه! همچنین

ch  =  System.in.read()

و

(isRedirect)  ?   -1  :  'n'

عملوندهای این عملگرن!

هر دو عملوند عملگرمون خودشون نوعی expression یا عبارتن، پس ابتدا به طور مجزا مورد ارزیابی قرار میگیرن، و در نهایت مقادیر حاصل از ارزیابی اون ها در اختیار عملگرمون (=!) قرار میگیره تا عدم تساویشون بررسی شه!

عملوند سمت چپ، متد از پیش ساخته شده read رو فراخوانی میکنه؛ همونطور که System.out رو تو برنامه قبلی شی ای معرفی کردم که ما ازش برای اتصال به جریان خروجی استاندارد استفاده میکنیم، اینجا هم System.in رو شی ای در نظر بگیرید که برای اتصال به جریان ورودی استاندارد ازش استفاده میشه! متد read توانایی خوندن دقیقا "یک کاراکتر" رو از جریان ورودی استاندارد داره، و به ازای هر کاراکتر خونده شده، مقدار عددی صحیح اون کاراکتر رو برمیگردونه (تو بازه 0 تا 255)، که ما این مقدار بازگشتی رو با استفاده از عملگر انتساب (=) داخل متغیر ch، که اون رو هم از نوع صحیح یا int تعریف کرده بودیم، ذخیره میکنیم! (در رابطه با نحوه عملکرد عملگر = (انتساب) باید بدونید که این عملگر مقدار عملوند سمت راست خودش رو داخل متغیر سمت چپش ذخیره میکنه!) پس، عملوند سمت چپ عملگرمون برابر شد با مقدار عددی صحیح ذخیره شده داخل متغیر ch. این نکته رو هم باید بدونید که اگه متد read کاراکتر دیگه ای برای خوندن یافت نکنه، مقدار 1- رو برمیگردونه!

عملوند سمت راست، یک عبارت شرطیست که از عملگر شرطی :? استفاده کرده! این عملگر بر خلاف عملگرهایی که تا اینجا باهاشون کار کردیم و 2 عملوند میگرفتن (بهشون عملگرهای دودویی هم میگیم!) 3تا عملوند میگیره! به این شکل

1 ? 2 : 3

عملوند 1، شرط عبارت ماست که به صورت عبارتی بولی ظاهر میشه؛ عملوند 2، مقدار کل عبارت شرطی در صورت درست بودن شرط؛ و عملوند 3، مقدار کل عبارت شرطی در صورت نادرست بودن شرط هستش! یعنی شما یک شرط میذارید، و به عملگر میگید اگه این شرط درست بود، "این" مقدار (عملوند 2) به عنوان حاصل ارزیابی عبارت شرطی برگردونده شه، و اگه درست نبود، "اون" مقدار (عملوند 3)!

اینجا شرط عبارت شرطیمون isRedirect تعیین شده؛ اگه isRedirect درست یا true باشه، در این صورت عملگر، مقدار 1-، و در غیر این صورت، کاراکتر n رو برمیگردونه! (دقت کنید که کاراکترها بین دوتا کوتیشن ' نوشته میشن!) کاراکتر n به معنی newline (یا نوسطر!!) هستش؛ این کاراکتر باعث میشه cursor یا همون مکان نمامون به ابتدای خط بعدی بره! یه چی شبیه به عملکرد کلید enter رو صفحه کلیدتون!

حالا میتونید the big picture رو درک کنید هر کاراکتری که توسط متد read از جریان ورودی خونده میشه، مقدار عددی صحیحش داخل متغیر ch قرار میگیره؛ اگه این مقدار با مقدار حاصل از ارزیابی عبارت شرطیمون نابرابر باشه، عملگر =! مقدار true و در غیر این صورت مقدار false رو برمیگردونه! تا زمانی که شرط حلقه whileمون true ارزیابی شه، حلقه به اجرای دستور خودش، یعنی (System.out.print((char) ch، ادامه میده! با این دستور هم آشنایید؛ تنها تفاوت print با println که تو برنامه قبلی ازش استفاده کردیم، اینه که println بعد از چاپ آرگومان یا آرگومان های خودش، کاراکتر n رو هم چاپ میکنه (ln به معنی line هستش)، اما print خیر! منظور از (char) متغیر ch هم اینه که کاراکتر هم ارز با عدد صحیحی که داخل متغیر ch ذخیره شده رو میخوام! همونطور که گفتم متد read به ازای هر کاراکتر، مقدار صحیح هم ارز با اون کاراکتر رو برمیگردونه، و ما اینجا برای چاپ خود کاراکتر نیاز به خود کاراکتر داریم!!

خب یه کم فکر کنید، چه زمانی اجرای حلقه while متوقف میشه؟! آفرین! (مثلا فکر کردید!) زمانی که مقدار متغیر ch برابر با 1- (یعنی ورودی از فایل بوده، و هیچ کاراکتر دیگه ای از فایل برای خوندن باقی نمونده!) یا کاراکتر n (یعنی ورودی از صفحه کلید بوده، و رفته باشیم سطر بعد!) بشه!

اما داستان ساختار try و catch چیه این وسط؟!

شرایطی رو در نظر بگیرید که مسیر جریان ورودی استاندارد، به فایل تغییر کرده باشه، و System.in.read قادر به خوندن هیچ متنی از فایل نباشه (مثلا شاید اون فایل روی یک فلش مموری ذخیره شده باشه، اما قبل از اینکه برنامه شروع به خوندن فایل کنه شما سهوا(!) فلش مموری رو برداشته باشید!)، در این صورت System.in.read شی ای رو پرتاب میکنه (اصطلاحا از فعل throw استفاده میشه، به معنی پرتاب کردن!) از کلاس IOException (کلاس مربوط به استثناهای ورودی و خروجی، که تو پکیج java.io موجوده!) که این مشکل رو توصیف میکنه! و شما با استفاده از بند catch شی پرتاب شده رو دریافت میکنید! (یکی پرتاپ میکنه یکی هم باید دریافت کنه!) بند catch مثل یک متد کوچیک میمونه که تنها یک و فقط یک پارامتر از یک نوع خاص داره، و شی پرتاب شده هم در واقع تنها آرگومان فرستاده شده به این متد محسوب میشه! شما میتونید با توجه به نیازتون از این پارامتر داخل بلاک catch استفاده کنید یا نکنید! (مثل پارامتر args برای متد main)

در نهایت تنها دستور موجود درون بلاک catch اجرا میشه که رشته "I/O error" رو به جریان خروجی استاندارد خطا میبره! System.err دقیقا همون خانواده از متدهای print و printlnی رو فراهم میکنه که System.out شامل میشه، پس هروقت خواستید پیغام خطایی رو به خروجی ببرید کافیه از System.out به System.err سوییچ کنید تا پیغام خطاتون روی صفحه نمایش، نمایش داده شه؛ حتی در صورتی که مسیر جریان خروجی استاندارد (System.out) رو به فایل تغییر داده باشید! (یعنی دو جریان مجزا هستن!)

ساخت بازی در اندروید

وقتی شما برنامه رو اجرا میکنید هیچگونه اتفاقی نمی افته و مکان نما سرجاش در حال فلش زدنه

چرا؟ چون برنامه به متد read رسیده و اینجا ازتون انتظار داره که متنی رو وارد کنید و enter بزنید تا این متد شروع کنه به خوندن متن!

ساخت بازی در اندروید

برای مثال متن This is a test رو تایپ کنید و enter بزنید

اجرای حلقه while آغاز میشه و کاراکترها دونه به دونه خونده شده و نمایش داده میشن، تا جایی که به کاراکتر 'n' برسیم؛ یعنی سطر به پایان برسه! دقت کنید که اینجا مقدار isRedirect همچنان false هستش، در نتیجه حلقه while زمانی به پایان میرسه که کاراکتر خونده شده با کاراکتر 'n' برابر بشه!

ساخت بازی در اندروید

و در نتیجه دقیقا همون متن دوباره چاپ میشه و دنباش برنامه به پایان میرسه !

ساخت بازی در اندروید

این بار برنامه رو با تغییر مسیر منبع دریافت ورودی از صفحه کلید به یک فایل اجرا میکنیم !

برای این کار از کاراکتر > استفاده میکنیم و به دنبالش اسم فایل رو میاریم! من خود فایل سورس کد رو انتخاب کردم برای این کار! همونطور که پیشتر گفتم برای این که برنامه متوجه شه که مسیر دریافت ورودی تغییر کرده، نیاز داره که ما حداقل یک آرگومان از خط فرمان بهش پاس بدیم؛ آرگومان x رو هم به همین منظور در نظر گرفتیم!

ساخت بازی در اندروید

اگه enter بزنید این بار محتویات فایل EchoText.java به طور کامل خونده شده و براتون نمایش داده میشه

دقت کنید که اینجا چون args.length برابر با 1 هستش، پس isRedirect برابر با true قرار میگیره، و در نتیجه حلقه while تا زمانی اجرا میشه که هیچ کاراکتری باقی نمونده باشه! در واقع دیگه مثل حالت قبل نیست که اگه به 'n' رسیدیم، اجرای حلقه while متوقف شه!

ساخت بازی در اندروید

برای اینکه منظورمو بهتر متوجه شید این حالت رو هم براتون اجرا کردم

اینجا هیچ آگومانی به برنامه پاس ندادیم، در نتیجه برنامه هم متوجه نمیشه که منبع دریافت ورودی ما قراره از یک فایل باشه! به همین خاطر با مقدار false برای isRedirect کارشو ادامه میده؛ در نتیجه حلقه while زمانی به پایان میرسه که کاراکتر 'n' خونده شه، پس تنها خط اول فایلمون به عنوان خروجی چاپ میشه!

برای ادامه این جلسه میخوام راجع به documentation و کامنت ها صحبت کنم، و بعدش هم درباره شناسه ها و کمی هم درباره typeها بهتون میگم! بحث مفصل تر typeهارو میذارم برای جلسه بعد. علاوه بر اون جلسه آینده بحث expressionها رو شروع میکنم و بعد از اون انواع statementها رو بررسی میکنیم و بعدش هم وارد مفاهیم شی گرایی میشیم! شاید 2 الی 3 جلسه (البته با فاصله کم) تا شروع شی گرایی! لطفا صبور باشید! مطمئن باشید به صبرتون می ارزه :)

خب؛ اما documentation! بببینید دوستان، هر سورس کدی نیاز داره که مستندسازی بشه، تا خود شما، چه الان و چه در آینده، بتونید درکش کنید! البته حرفم به این معنی نیست که وقتی شما سورس کدتون رو نوشتید و کارتون باهاش تموم شد، بعدش بیاید یه وقت جداگانه اختصاص بدید و شروع به مستندسازی کنید! خیر! باید به قدری این کار براتون عادت شه که هم زمان با ایجاد سورس کد، مستندسازیش رو هم انجام بدید! یا اگه هر زمانی هر تغییری تو سورس کد ایجاد کردید، که مستندسازی فعلی رو تحت تاثیر قرار میده، باید documentation رو به دقت به روزرسانی کنید تا بتونه کد رو کامل توضیح بده!

برای تعبیه documentation داخل سورس کد، جاوا ویژگی comment رو برامون فراهم کرده! زمانی که سورس کد کامپایل میشه، کامپایلر جاوا تمامی کامنت هایی که شما داخل سورس کدتون نوشتید رو نادیده میگیره، و هیچ بایتکدی به ازای اون ها تولید نمیکنه!

جاوا از 3 نوع کامنت پشتیبانی میکنه؛ تک خطی، چند خطی و Javadoc.

کامنت تک خطی، تمام و یا بخشی از یک خط سورس کد رو اشغال میکنه! این نوع از کامنت با دنباله کاراکتری // شروع میشه و با متنی توضیحی ادامه پیدا میکنه! کامپایلر همه چیز رو از // تا پایان خطی که توش // ظاهر شده، نادیده میگیره! برای مثال:

System.out.println(Math.sqrt(10 * 10 + 20 * 20)); // Output distance from (0, 0) to (10, 20).

تو این مثال فاصله بین مبدا (0,0) و نقطه (10,20) رو صفحه دکارتی x/y داره محاسبه میشه! همون فرمول معروف:

distance = square root(x*x+y*y)

که اینجا x برابر با 10 و y برابر با 20 هستش! جاوا کلاسی از پیش ساخته شده به نام Math برامون فراهم کرده که متد sqrt این کلاس، ریشه دوم (جذر با فرجه 2) تنها آرگومان عددی خودش رو به عنوان مقدار بازگشتی برمیگردونه!

کامنت های تک خطی برای قرار دادن توضیحات کوتاه اما پرمعنی(!) از سورس کد مفید هستن. ازش برای مستندسازی ای که کمکی نمیکنه استفاده نکنید! برای مثال وقتی دارید یک متغیر اعلان میکنید، کامنت بی معنی ای مثل This variable stores integer values قرار ندید!!

یک کامنت چند خطی، میتونه یک یا چند خط از سورس کد رو اشغال کنه! این کامنت با دنباله کاراکتری */ شروع میشه، با متنی توضیحی ادامه پیدا میکنه، و با دنباله کاراکتری /* به پایان میرسه! هر چیزی از */ تا /* توسط کامپایلر نادیده گرفته میشه! حتی اگه 10000 خط هم باشه! برای مثال:

A year is a leap year when it's divisible by 400, or divisible by 4 and
not also divisible by 100.
*/
System.out.println(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0));

تو این مثال وجود یک متغیر از نوع صحیح یا int به نام year فرض شده، که توانایی ذخیره یک سال 4-رقمی دلخواه رو داره! یک عبارت تقریبا پیچیده مورد ارزیابی قرار میگیره برای تعیین اینکه آیا این سال، یک سال کبیسه هستش یا خیر! این عبارت مقدار true رو در صورت کبیسه بودن، و در غیر این صورت مقدار false رو برمیگردونه، که توسط System.out.println به خروجی برده شده و چاپ میشه! کامنت چند خطی ما هم داره توضیح میده که چه سالی سال کبیسه هست! و هر کسی با خوندن این کامنت میتونه خیلی راحت عبارت نسبتا پیچیده ای که باهاش روبه رو میشه رو تحلیل کنه!

جاوا از یک نوع سوم کامنت هم پشتیبانی میکنه به نام Javadoc (ابزار Javadoc درون jdk موجوده!)، که تعیینِ مستندسازیِ خارجیِ مبتنی بر HTML رو ساده میکنه! در واقع زمانی شما این ویژگی کامنت Javadoc رو مفید ارزیابی میکنید، که بخواید مستنداتی فنی رو برای توسعه دهنده های دیگه ای که روی برنامه ها، کتابخونه ها و سایر محصولات مبتنی بر جاوای شما تکیه کردن، آماده کنید!

یک کامنت Javadoc، میتونه یک یا چند خط از سورس کد رو اشغال کنه! این کامنت با دنباله کاراکتری **/ شروع میشه، با متنی توضیحی ادامه پیدا میکنه، و با دنباله کاراکتری /* به پایان میرسه! طبق روال قبلی، هر چیزی از **/ و /* توسط کامپایلر نادیده گرفته میشه! به عنوان مثال:


* Application entry point
*
* @param args array of command-line arguments passed to this method
*/
public static void main(String[] args)
}
// TODO code application logic here
{

این مثال با یک کامنت Javadoc شروع شده که متد main رو توصیف میکنه! عبارت بین **/ و /* یک توصیف از متد و تگ Javadocی به نام param@ هستش! (تگ Javadoc در واقع دستورالعملی برای ابزار Javadoc محسوب میشه!)

تو لیست پایین توضیح چندتا از تگ هایی که معمولا زیاد استفاده میشن رو آوردم:

@author

نویسنده سورس کد رو تعیین میکنه.

@deprecated

یک موجودیت از سورس کد (مثل یک متد) رو تعیین میکنه که دیگه نباید استفاده شه.

@param

یکی از پارامترهای متد رو تعیین میکنه.

@see

یک مرجع see-also رو فراهم میکنه.

@since

نسخه ای از برنامه رو تعیین میکنه که یک موجودیت خاص برای اولین بار تو اون نسخه به وجود اومده.

@return

نوع مقدار بازگشتی از یک متد رو تعیین میکنه.

@throws

استثنایی رو مستندسازی میکنه که یک متد پرتاب کرده.

همونطور که میبینید تمامی این tagها تو تلگرام حضور دارن، میتونید رو userشون کلیک کنید و اگه خواستید، بیشتر باهاشون آشنا شید

/**
  Dump all command-line arguments to standard output.
  @author WhoMan
*/
public class DumpArgs
}
  /**
    Application entry point.
    @param args array of command-line arguments.
  */
  public static void main(String[] args)
}
    System.out.println("Passed arguments:");
    for (int i = 0; i < args.length; i++)
      System.out.println(args[i]);
  {
{

این همون برنامه DumpArgs ماست که قبلا باهاش کار کردیم؛ به علاوه کامنت های Javadoc که کلاس DumpArgs و متد mainش رو توصیف میکنن بهش اضافه شده!

شما میتونید این کامنت های documentation رو درون یک مجموعه از فایل های HTML اکسترکت کنید! کافیه از دستور javadoc استفاده کنید؛

ساخت بازی در اندروید

Javadoc DumpArgs.java

یه سری پیاما براتون نمایش داده میشه

]

ساخت بازی در اندروید

و در نهایت چندین فایل براتون ایجاد میکنه که نقطه شروعش فایل index.html هستش ! میتونید با هر مرورگری بازش کنید .

خب بریم سراغ شناسه ها! همونطور که میدونید تمامی موجودیت های سورس کد نیاز دارن که نامگذاری شن، تا ما بتونم از جاهای دیگه ای داخل سورس کد بهشون دسترسی داشته باشیم! برای این منظور، جاوا ویژگی "شناسه ها" یا identifiers رو فراهم کرده! هر شناسه ای تشکیل شده از حروف (A-Z، a-z، یا حروف بزرگ/کوچک معادل از زبان های مختلف!)، ارقام (0 تا 9، و یا ارقام معادل از زبان های مختلف!)، کاراکترهای متصل کننده مثل undersore ( _ ) و علامت های ارزی مثل $. هر شناسه ای حتما باید با یک حرف، یک کاراکتر متصل کننده و یا یک علامت ارزی شروع شه! پس شما نمیتونید نامتون رو با عدد آغاز کنید! همچنین طول شناسه تون نمیتونه از خطی که توش ظاهر شده تجاوز کنه!

چند نمونه از شناسه های معتبر (قابل استفاده!):

i

counter

j2

first$name

_for

و نمونه های نامعتبر:

1name

first#name

یادآوری: قبلا بهتون گفته بودم که جاوا به بزرگی/کوچکی حروف حساسه! پس counter و Counter دو شناسه یکسان نیستند!

تقریبا هر شناسه معتبری رو میتونید برای نامگذاری یک کلاس، یک متد، یا هر موجودیت دیگه ای داخل سورس کدتون انتخاب کنید. اما، همونطور که قبلا هم اشاره داشتم، بعضی از شناسه ها برای زبان جاوا رزرو شدن؛ همون کلمات رزرو شده یا reserved words! زمانی که شما سعی به استفاده از هر کدوم از این شناسه ها، خارج از زمینه های استفاده شون، داشته باشید، کامپایلر با یک ارور مسیج به خدمتتون میرسه!

ساخت بازی در اندروید

جاوا این شناسه ها رو برای خودش رزرو کرده

خیلی کوتاه یه مقدمه هم از typeها بهتون میگم تا جلسه بعد ادامه ش بدیم :)

هر برنامه ای آیتم هایی از داده ها رو مورد پردازش قرار میده؛ مثل اعداد صحیح، مقادیر اعشاری، کاراکترها و رشته ها! این آیتم ها، با توجه به ویژگی های مختلفشون دسته بندی شدن! برای مثال، اعداد صحیح اعدادی هستند بدون کسر. یا هر رشته ای، یک دنباله از کاراکترهاست که به عنوان "یک واحد مستقل" باهاش رفتار میشه، و دارای طولیست که تعداد کاراکترهای موجود در دنباله رو تعیین میکنه!

جاوا از اصطلاح type یا نوع برای توصیف طبقه بندی این آیتم ها استفاده میکنه! در واقع هر type تعیین کننده یک مجموعه از داده ها، و یک مجموعه از عملیات هایی است که این داده ها رو به داده هایی دیگه تو همون مجموعه تبدیل میکنن! به عنوان مثال، نوع عدد صحیح، تعیین کننده ی مقادیری عددی بدون هرگونه قسمت کسری، و عملیات های ریاضی صحیح-گرا هستش! (مثل جمع دو عدد صحیح که حاصلش باز هم عددی صحیح میشه!)

نکته مهمی که باید بدونید اینه که جاوا به شدت نوع گذاری شده؛ یعنی هر عبارتی، هر متغیری و ... برای کامپایلر یک نوع مشخص دارند! این قابلیت به کامپایلر کمک میکنه تا بتونه خطاهای مبتنی بر type رو هنگام کامپایل پیدا کنه، به جای این که این خطاها خودشون رو در زمان اجرا آشکار کنن!

جاوا 3 نوع اصلی یا primitive، تعریف شده توسط کاربر یا user-defined، و آرایه رو تشخیص میده! که من هرکدومشون رو جداگانه توضیح میدم! فعلا برای این جلسه فقط کمی راجع به نوع اصلی صحبت میکنم.

نوع اصلی یا primitive، نوعی هستش که توسط خود زیان تعریف شده و مقدار اون یک object یا شی نیست! جاوا از انواع اصلی

Boolean

Character

Byte integer

Short integer

Integer

Long integer

Floating-point

Double precision floating-point

پشتیبانی میکنه!

ساخت بازی در اندروید

تمامی انواع اصلی تو این جدول توصیف شدن

این جدول هر نوع اصلی رو با توجه کلمه رزرو شده، سایز، مقدار min و مقدار max ش توصیف میکنه! منظور از قسمت هایی که "--" گذاشته شده اینه که اون ستون قابل اطلاق به type اون سطر نیست! ستون size تعیین کننده سایز هر کدوم از انواع اصلی بر حسب تعداد بیت هایی ست (0 یا 1) که یک مقدار از اون تایپ، در حافظه اشغال میکنه! جز نوع boolean، هر پیاده سازی از یک نوع اصلی سایز مخصوصی داره! اما سایز نوع boolean وابسته به پیاده سازیست! یک پیاده سازی در جاوا ممکنه یک مقدار نوع boolean رو در یک بیت ذخیره کنه، و یک پیاده سازی دیگه ممکنه احتیاج به 8 بیت یا یک بایت برای ذخیره یک مقدار boolean داشته باشه! دلیل؟ بهبود راندمان عملکرد!

جلسه آینده این بحثو باز میکنم و در مورد انواع اصلی و بقیه typeها بیشتر توضیح میدم

دانلود دانلود PDF قسمت سوم آموزش بازی سازی در اندروید

قسمت بعدی قسمت چهارم آموزش بازی سازی در اندروید