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

در این مقاله قصد داریم با  sprite ها کار کنیم.
sprite  معانی مختلفی دارد. این کلمه برای مشخص کردن یک تصویر یا یک انیمیشن در یک صحنه و یا برای نشان دادن هر شی متحرکی در بازی مورد استفاده قرار میگیرد.
یکی دیگر از معانی این کلمه ،کپسوله کردن یک کاراکتر در بازی است.

در مثالی که در این آموزش می آوریم ، با استفاده از sprite ها، حرکت اشیا را بررسی میکنیم.
در این مثال ابتدا یک سفینه فضایی خواهیم ساخت و سپس آن را به کمک کلیدهای صفحه کلید ، به حرکت در می آوریم. (یعنی  sprite  را  (که همان سفینه است) به چپ ، راست ، بالا یا پایین حرکت میدهیم.)

طبق روال گذشته پروژه ای ایجاد میکنیم و پیکیجی برای پروژه میسازیم.
به بررسی کلاسهای مورد نیازی که باید در این پکیج ایجاد شوند،میپردازیم.

اولین کلاس، کلاسی به نام craft  است که قرار است چگونگی حرکت را در آن پیاده سازی کنیم.

 

کلاس فوق، کلاس سازنده ی سفینه ی فضایی است. در ابتدا متغییر های مورد نیاز را تعریف کردیم:

متغییرهای x,y  ، مولفه هایی هستند که  میزان فاصله تصویر از board  را مشخص خواهند کردو متغییر های dx ,dy  میزان تغییر مولفه  های  x,y  را مشخص می کنند.
متغییری از نوع image  تعریف کردیم برای  دریافت تصویر مورد نظر، و  رشته ای  که نام این تصویر را در خود دارد.

در تابع craft، تصویر را مطابق گذشته، دریافت و همچنین  آنرا در یک مختصات مشخصی قرار میدهیم. (فاصله ی اولیه ی تصویر از گوشه ی بالای سمت چپ Board را 40 ,40  قرار دادیم.)
(توجه  داشته باشید که در محل ذخیره ی پروژه و در کنار کلاسهای ساخته شده ، تصویرمان را کپی کرده ایم.)
تابع move مختصات  x,y   سفینه را به میزان dx ,dy  تغییر می دهد.
مقادیر x , y تابع move بعدا در تابع paint برای ترسیم تصویر سفینه استفاده خواهند شد.
دو شرط لحاظ شده در تابع move نیز به این منظور است که سفینه هنگام خارج شدن از سمت چپ پنجره یا بالای پنجره، با مقداردهی دوباره ی x یا y  دوباره وارد پنجره شود.
توابع get  تعریف شده برای  هر یک ازمتغییرهای  x,y,image  ، مقدار جدید هر کدام را بر میگرداند.

دو متد دیگر، keyPressed و keyReleased ، مشخص میکنند که سفینه یا همان sprite در حالت حرکت قرار بگیرد و یا در حالت ایستاده.
متد keyPressed برای اینکه sprite  حرکت کند، پیاده سازی شده است.

در این تابع ، مشخص میکنیم که  حرکت sprite  با فشردن هر یک از کلیدهای جهت نمای صفحه کلید، چه تغییری کند.
پس باید برای  ورودی این تابع، کلیدی که فشرده میشود را درنظر بگیریم(یعنی شی ای از نوع keyEvent). سپس با دستور getKeyCode() ،  کد اسکی مربوط به کلیدی که فشرده شده را دریافت میکنیم و آنرا با کداسکی کلیدهای جهت نما مقایسه میکنیم و بسته به اینکه کدامیک از چهار فلش جهت نما فشرده شده اند، دستوری را برای افزایش مولفه ی مربوطه ، قرار میدهیم.

این دستور میگوید که اگر کلید فشرده شده ،فلش سمت چپ باشد ، مختصه ی x  را یک واحد کم کن .(به این معنی که sprite  را یک واحد به سمت چپ حرکت بده.)

مطابق دستور فوق، اگر کلید فشرده شده ،فلش سمت چپ باشد ، مختصه ی x  تصویر یک واحد کم میشود .(به این معنی که sprite  یک واحد به سمت راست حرکت میکند.)

 

به کمک دستورات فوق،اگر کلید جهت نمای پایین فشرده شود ،مختصه ی y  را یک واحد  افزایش میدهیم(به این معنی که sprite  یک واحد به سمت پایین حرکت کند)
و اگر کلید جهت نمای بالا فشرده شود ،مختصه ی y  را یک واحد کاهش میدهیم(به این معنی که sprite  یک واحد به سمت بالا حرکت کند)

 

اما این تغییرات با یکبار فشردن هر کدام از این کلیدها ، بطور مدام ادامه پیدا میکند  و سفینه از حرکت نمی ایستد.
مثلا با یکبار فشردن کلید جهت نمای راست، سفینه بطور مداوم به سمت راست حرکت میکند تا از board خارج شود.

برای حل این مشکل ، متد keyReleased را پیاده سازی کردیم . از این متد برای ایستادنsprite  ، پیاده سازی شده است.
به این معنی که وقتی دستمان از کلیدبرداشته شد ، میزان تغییر در آن جهت، 0 شود.(یعنی سفینه از حرکت بایستد.)

حال، کلاس Board  را پیاده سازی میکنیم:

 

در این کلاس، داخل تابع paint سفینه فضایی را که قبلا تصویرش را دریافت کرده بدیم، ترسیم کردیم . در تابع رسم سفینه ، تصویر سفینه و مختصات آن را بعنوان پارامتر به تابع داده ایم .

 

 

از آنجایی که تصاویر رسم شده قبل از نمایش دادن بر  روی حافظه بار میشوند، باید بعد از هر بار رسم حافظه را خالی کنیم تا حافطه برای رسم های بعدی خالی شود. این کار را با دستورdispose() به شکل زیر انجام میدهیم:

 

تابع actionPerformed را هر 10 میلی ثانیه یکبار فراخوانی می کنیم . در آن ، هم sprite را حرکت می دهیم و هم متد repaint را فراخوانی می کنیم .

در آخر هم کلاس حای متد  main  را ایجاد میکنیم تا به برنامه ، قابلیت اجرا بدهیم:
1
با اجرای برنامه ، خروجی زیر را مشاهده میکنیم.سفینه ،با فشردن کلیدهای جهت نما حرکت میکند.

 

2

 

در این قسمت، قصد داریم یک  sprite  دیگر (گلوله) به برنامه اضافه کنیم. بطوری که وقتی کلید space  را فشار دهیم، شلیک گلوله از سفینه انجام شود.
برای این منظور ، ابتدا یک کلاس جدید در پکیجمان ایجاد میکنیم . این کلاس ، کلاس سازنده ی گلوله خواهد بود:

 

مشاهده میکنید که این کلاس ، تقریبا مشابه کلاس سازنده ی سفینه ، پیاده سازی شده است.
حرکت گلوله باید با یک سرعت ثابتی انجام شود.  مقدار این سرعت را با یک عدد صحیح مشخص کردیم:

در تابعmove ، که تابع پیاده سازی حرکت گلوله است ، این مقدار را به مختصه ی x گلوله ، در زمان حرکت ، نسبت داده ایم.

دقت کنید که وقتی گلوله به حاشیه ی سمت راست پنجره ی خروجی برخورد میکند، باید ناپدید شود. یعنی وقتی مختصه ی x گلوله ، بیشتر از طول پنجره شود( که این مقداررا برابر ;private final int BOARD_WIDTH = 380 قرار دادیم) ، باید گلوله را از لیست  گلوله هایی که در ArrayListتعریف کردیم حذف شوند.(این ارایه را در craft  اضافه خواهیم کرد) این عملیات را به شکل زیر ، به تابع move   اضافه میکنیم:

 

بعد از اضافه کردن این کلاس، تغییراتی را که لازم است ، در کلاسهای قبل ، اعمال میکنیم.

ابتدا به کلاس Craft  میرویم و دستورات لازم را به شکل زیر به آن اضافه میکنیم:

(دقت کنید در اینجا هم ، تصویر گلوله را در محل ذخیره ی پروژه ، کپی کرده ایم)

در ابتدا برای اینکه مشخص کنیم گلوله ، ازچه فاصله ای نسبت به سفینه ، شروع به شلیک شدن کند ، متغییری برای این منظور تعریف میکنیم.

 

 

برای اینکه لیست گلوله ها را ذخیره کنیم ، ارایه ای تعریف میکنیم:

 

و قرار میدهیم :

 

حال کد دکمه ی شلیک گلوله را به متد keyPressed  اضافه میکنیم:

 

مطابق این دستور ، اگر کلید  spaceفشرده شود، متد fire()  ،فراخوانی میشود.

تابع fire هم یک گلوله دیگر تعریف می کند و مکان اولیه ی گلوله را به کمک متغییر CRAFT_SIZE تعریف میکند و در نهایت آن را به لیست گلوله ها اضافه می کند.

حال تغییراتی که در کلاس Board  باید انجام شود را مورد بررسی قرار میدهیم:

تغییرات کلاس Board بدین صورت است که در تابع paint کل گلوله ها را که در یک ArrayList وجود داشتند را  ابتدا توسط دستور getMissiles();  دریافت و سپس در صفحه ترسیم می کنیم.

در تابع  actionPerformed هم،جداگانه تک تک گلوله ها را که در یک arraylist وجود داشتند ، از حیث اینکه قابل دیدن هستند یا خیر، مورد بررسی قرار میدهیم و  آنها را حرکت می دهیم و یا حذف می کنیم.

 

 

 

 

کلاس حاوی main  نیازی به تغییر ندارد.

اگر برنامه را اجرا کنید ، میبینید که سفینه با کلید های جهت نما حرکت کرده ، و با فشردن کلید space ، گلوله شلیک میشود.

3

 

در اینجا ، سومین قسمت از آموزش های ساخت بازی با جاوا  را به پایان میبریم.
دراین مقاله سعی کردیم بحث sprite هارا تا حدی پوشش دهیم.

 

 

ozviiiiiiiat