آموزش های این وب سایت به صورت رایگان در دسترس است. اطلاعات بیشتر
مشکل عدم دسترسی خریداران پیشین به برخی آموزش ها برطرف شد
بروز خطا
   [message]
اشتراک در سوال
رای ها
[dataList]

آشنایی با کتابخانه AndEngine (موتور بازی سازی) + آموزش

Criss  8 سال پیش  4 سال پیش
+54 0

 

http://dchabmztumu0g.cloudfront.net/wp-content/uploads/2012/12/logoimage.png

 

Nicolas Gramlich

andengine.org

Forums

نصب APK از مثال ها (این نسخه قدیمی هست و آپدیت نشده !)

تعداد از بازی های ساخته شده با AndEngine از جمله عنکبوت حریص و Noogra Nuts

 Blog (پیشنهاد میکنم تغییر آیپی بدید < که بتونید کلیپ های یوتیوب توی این آدرس رو ببینید)

از بازی هایی که سازنده AndEngine یعنی (Nicolas Gramlich) برای نمونه ساخته (به کم حجم بودن بازی ها دقت کنید)

این بازی هم با AndEngine نوشته شده

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

استخدام برنامه نویس AndEngine در ایران ! ! ! (لینک های بیشتر)

منابع آموزشی :

//


 

از تمام دوستانی که این موضوع براشون جالب هست و علاقه به یادگیری دارند دعوت میکنم در تولید مقاله های آموزشی کمک کنند < ، سعی میکنم انجمنی رو برای یادگیری AndEngine شروع کنیم ، باید ببینم شرایط چطور پیش میره ، به احتمال زیاد تاپیک پرسش و پاسخ AndEngine و آموزش ها در همین Uncocoder ادامه پیدا میکنه و از اینجا خارج نشیم


# بر چسب :

AndEngine ، آموزش AndEngine ، فارسی AndEngine ، اندروید ، بازی سازی ، بازی اندروید ، ساخت بازی ، اندانجین ، AndEngine Toturial ، android game ، game maker android

AndEngine for Android Game Development Cookbook

Learning Android Game Programming

+1 0
ممنون بابت آموزش ها و وقتی که گذاشتی و میخوای بزاری ، در مورد خود این andEngine بیشتر توضیح بدید ، مثلا اینکه برای ساخت بازی andEngine بهتر هست یا OpenGL (8 سال پیش)
+1 0
خیلی ممنون (8 سال پیش)
+1 0
ولی بهتر نبود یه دفعه یونیتی رو شروع میکردیم هرچیزی را بهره کاری ساختند... (8 سال پیش)
+1 0
سلام آقا criss خسته نباشید با آموزش خوبتون . من یه بازی ساختم 90 درصد کار رو رفتم و یکمی پیچیده شده و باب دلم در نیومده و از اونجایی ک قراره چند تا بازی دوبعدی دیگه طراحی کنم و با توجه به این که زحمت کشیدید آموزش AndEngine رو قرار دادید . خواستم یه نگاهی به بازی منم بندازی با تجربه ای ک تا الان کسب کردی نظرت رو درباره این که این بازی رو با AndEngine طراحی کنم چیه ؟ لینک ویدئو بازی لینک (8 سال پیش)
+1 0
البته این بازی بیش از 30 مرحله داره و نمیخوام زیاد سنگین بشه . (8 سال پیش)
0 0
@علی : پیام خصوصی شد (8 سال پیش)
0 0
با سلام ، تشکر از زحمات شما (7 سال پیش)
 برای این سوال 48 پاسخ وجود دارد.
پاسخ به سوال 
Criss  8 سال پیش
+15 0

توی این پست سعی میکنم راجب AndEngine سرچ کنم و هرچی نتیجه گرفتم اینجا توضیح بدم < (پس صحت و دقت این اطلاعاتی که اینجا میزارم بر اساس برداشت هایی هست که بعد از سرچ نتیجه گرفتم و هیچ تجربه مستقیم و عملی ندارم )


 

با استفاده از این موتور بازی سازی چیکار میتونیم کنیم ؟

  • با استفاده از موتور بازی سازی حرکت دادن یک کاراکتر روی صفحه خیلی راحت تر میشه ، میتونید برخورد کردن دو شی با هم ، ضربه زدن ها ، پرتاب شدن ها و . . . راحتر بسازید
  • حجم تصاویر در مصرف حافظه بهینه میشه
  • از مهمترین موارد موتور بازی سازی این هست که شما میتونید فیزیک رو بکار بگیرید وزن ، سرعت قدرت ضربه زدن ، گرانش و ... رو میشه شبیه سازی و استفاده کرد < مثلا جاذبه زمین رو شبیه سازی کنید و تمام کاراکترهای موجود رو به سمت دلخواه بکشید ، بازی انگری برد نمونه کاملی از استفاده از فیزیک توسط موتور بازی سازی هست
  •  و . . .

AndEngine یک موتور بازی سازی دو بعدی فقط برای اندروید هست ، که از (OpenGL ES or GLES) استفاده میکنه ، تفاوت هایی بین OpenGL , OpenGL ES وجود داره ، از اونجایی که اطلاعی در این زمینه ندارم نمیدونم چقدر این دو متفاوت هستند < ولی در مورد OpenGl ES درحال حاضر 3 نسخه موجود هست  که AndEngine از نسخه 2 استفاده میکنه البته نسخه قبلی AndEngine بر اساس GLES 1 بود :

  • OpenGL ES 1.1  : برای اندروید 1 و بالاتر .
  • OpenGL ES 2.0 :  از اندروید 2 (API Level 8) و بالاتر .
  • OpenGL ES 3.0 : این نسخه از OpenGL ES از اندروید 4.3 (API Level 18) و بالاتر .

 

یک مثال کوچیک از OpenGL : در پروژه های OpenGL بصورت معمول دو کلاس های GLSurfaceView و GLSurfaceView.Renderer استافده یجورایی این دو کلاس برای OpenGL شبیه همون ActivityMain خودمون میمونه ! برای آشنایی با OpenGL این پروژه رو به Eclipse اضافه کنید < (اصلا خودتون رو درگیر OpenGL نکنید < من چون دوستون بالاتر درخواست داده بودند سرچ کردن و اینجا قرار دادم < اصلا قرار نیست درگیر OpenGL بشیم)

لینک پروژه OpenGL Sample

کلمه عبور : uncox.com


  •  خب توضیحی که بالا دادم برای این بود که بدونید در حالی که AndEngine از OpenGL استفاده میکنه اما نیازی به دانش استفاده از OpenGL نیست
  • AndEngine برای توسعه دهندگان OpenSource هست (که اگر برنامه نویس خیلی خوبی باشید میتونید  در این موضوع دخالت کنید)
  • در AndEngine محیط گرافیکی نداریم و تمام قسمت های بازی با نوشتن کد پیش میره
  • یکی از نکات خوبی که بر خلاف Unity داره این هست که حجم بازی خیلی کم هست ، در حالی که برای Unity فک میکنم حداقل یک بازی ساده 10 مگابایت حجم داشته باشه (خب یونیتی فقط برای اندروید نیست و میتونید  ازش خروجی های متفاوت بگیرید ، ولی ما هدفمون اندروید هست)
  • من اعتقاد دارم با BatchFile ها میشه botnet طراحی کرد ، نبابراین در مورد قدرت و توانایی های این موتور که بعضی ها میگند متوسط هست نمیشه تصمیم گرفت ، چون خیلی ها هم این موتور رو حرفه ایی میدونند بلاخره باید دقت کنید این موتور دوبعدی و فقط برای اندروید هست ، در نهایت همه چیز به برنامه نویس بستگی داره که چقدر قدرت رو به نمایش بزاره
  • AndEngine تعدادی افزونه (Extention) داره که همانند خود AndEngine کتابخانه هستند و در کنار AndEngine به اکلیپس اضافه می شوند و توانایی های شما اضافه میکنند

 

AndEnginePhysicsBox2DExtension - برای بکارگیری فیزیک دو بعدی 
AndEngineMultiplayerExtension - زمانی که نیاز داشته باشید بازی چند نفره بازی بشه
AndEngineMultiTouchExtension - برای چند لمس همزمان روی صفحه
AndEngineLiveWallpaperExtension - فک کنم طبق اسمش برای ساخت LiveWallpaper باشه
AndEngineSVGTextureRegionExtension - اگر از فایل ها برداری همون تصاویر وکتور و "اس وی جی" استفاده میکنید
AndEngineTexturePackerExtension - برای انتخاب و برش زدن یک قسمت از اسپرایت شیت ها
AndEngineMODPlayerExtension - فکر میکنم برای اجرای فایل های صوتی 8 بیتی باشه
AndEngineTMXTiledMapExtension - فکر میکنم به شما کمک میکنه یه نقشه بزرگتر از اسکرین کوشی داشته باشید و با حرکت کردن به اطراف قسمت های بیشتر نمایش داده بشه و ساخت نشقه با تصاویر تکرای
//این موارد زیر رو هم نمیدونم چی هستند
AndEngineAugmentedRealityExtension
AndEngineRobotiumExtension
AndEngineScriptingExtension
AndEngineScriptingExtensionGenerator

سایت هایی که به بررسی موتور های بازی سازی پرداخته اند و  AndEngine هم در بین آنها دیده میشود :

http://www.slant.co/topics/1476/~2d-game-engines-for-android
https://software.intel.com/en-us/android/blogs/2012/03/13/game-engines-for-android
https://software.intel.com/en-us/blogs/2012/05/14/eight-popular-open-source-android-game-engines

در حال ویرایش . . .

پاسخ به سوال 
Criss  8 سال پیش
+14 0

نحوه اضافه کردن این کتابخانه به اکلیپس 

  • از همین ابتدا تاکید میکنم :
  • از اونجایی که هنوز به اندازه کافی تجربه کار رو ندارم و همراه با شما دارم هرچیزی رو که یاد میگیرم رو اینجا قرار میدم < حتما از لینک هایی که معرفی میکنم < استفاده کنید < به دلیل اینکه توی نسخه های مختلف ناپایداری های مختلفی وجود داره و ممکنه توی اکلیپس شما رو اذیت کنه < که در آینده با کسب تجربه ی بیشتر میتونیم این موضوع رو هم حل کنیم
  • برای خود AndEngine و تمام Extention ها نسخه JavaCompiler باید 1.6 باشه

 

برای اضاف کردن AndEngine به این آدرس گیت هاب برید فایل ZIP رو دانلود کنید بعد از Extract کردن اون رو به اکلیپس Import کنید < در صورتی که از پروژه ارور گرفتید < روی پروژه راست کلیک کرده < Properties و JavaCompiler رو 1.6 قرار بدید < از قسمت Android هم IsLibery رو تیک بزنید <

آموزش تصویری

کلمه عبور : uncox.com

0 0
cooooooooooool (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+11 0

Extentions (افزونه ها)

آموزش تصویری

کلمه عبور : uncox.com

از این آدرس Extention هایی که زیر لیست کردم رو دانلود کنید <

AndEngineAugmentedRealityExtension
AndEngineDebugDrawExtension
AndEngineExamples
AndEngineLiveWallpaperExtension
AndEngineMODPlayerExtension
AndEngineMultiplayerExtension
AndEnginePhysicsBox2DExtension
AndEngineSVGTextureRegionExtension
AndEngineTexturePackerExtension
AndEngineTMXTiledMapExtension

البته به تمام این Extention ها نیاز نداریم < بعدا تاپیک رو ویرایش کنم و توضیحات رو اضاف میکنم

 در حال ویرایش  . . .

پاسخ به سوال 
Criss  8 سال پیش
+11 0

ساخت یک پروژه

کافیه یک پروژه اندروید بسازیم < AndEngine رو به عنوان کتابخانه بهش معرفی کنیم < و  extends BaseGameActivity کنیم اکلیپس به ما هشدار میده که متدهای مورد نیاز رو استفاده نکردیم پس  Add unplemented metohds رو میزنیم

آموزش تصویری

کلمه عبور : uncox.com

public class MainActivity extends BaseGameActivity {

@Override
public EngineOptions onCreateEngineOptions() {
return null;
}

@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {

}

@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {

}

@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {

}
}

 

بجای BaseGameActivity  میتونستیم از SimpleBaseGameActivity هم استفاده کنیم که در نهایت کدهامون به شکل زیر میشد ، البته مورد های دیگه هم برای extends شدن هست که نمیدونم چنتا هستن ، دقیقا چی هستن و یا کجاها استفاده میشن !

 public class MainActivity extends SimpleBaseGameActivity {

@Override
public EngineOptions onCreateEngineOptions() {
return null;
}

@Override
protected void onCreateResources() {

}

@Override
protected Scene onCreateScene() {
return null;
}
}

هنوز تفاوت BaseGameActivity  و  SimpleBaseGameActivity رو نمیدونم ولی معلومه یکیش کاملتره و اونیکی ساده تر یکی دیگه از تفاوت های مهمشون هم در متد ها هست که یکی void هست و اون یکی خروجی داره

پاسخ به سوال 
Criss  8 سال پیش
+14 0

استفاده از AndEngineExamples

 توی پست اول این رو به عنوان نصب APK از مثال ها معرفی کردم و اگر برنامه رو دانلود و دیده باشید ، متوجه میشید چیزی که قراره الان باهاش کار کنیم همون پروژه هست < در نهایت Sample ها رو بیرون میکشیم < و خروجی رو تست میکنم < بعدا میتونیم با بررسی کردن سورس ها < AndEngine رو خیلی ساده تر یاد بگیریم

آموزش تصویری

کلمه عبور : uncox.com

 

0 0
درود دوست من. یه سوال. تا چه حد این کتابخونه انعطاف داره؟؟ برای مثال میشه ازش در لیست ویوو یا ایمیج ویوو یا موارد مشابه استفاده کرد؟؟ (8 سال پیش)
+2 0
@ Possible : همونطور که گفتم هیچ تجربه ی قبلی در این زمینه ندارم و هرچیزی رو که دارم یاد میگیرم اینجا به اشتراک میزارم < احساس میکنم شما موضوع رو به درستی درک نکردید ویا من منظورتون رو درست متوجه نمیشم ، ولی چیزی که فعلا مشخصه این هست که AndEngine اکتیویتی خاص خودش رو داره < بنابر این شما میتونید از توی لیست ویو و یا ImageView با استفاده از intent به این اکتیویتی منتقل بشید و بازی رو نمایش بدید (8 سال پیش)
+1 0
ممنون دوست من. منظور من این بود که یه انیمیشن خاص رو در یه اپلیکیشن معمولی ( نه بازی ) پیاده کنیم. فرض کنید همین قوانین فیزیک رو برای یک دکمه تعریف کنیم. آیا امکان همچین جیزی هست؟؟ (8 سال پیش)
+2 0
فک میکنم ممکن باشه ، البته هنوز اطلاع دقیقی ندارم ، ولی چیزی که تا الان متوجه شدم کد های مربوط به قوانین فیزیک و غیره فقط در اکتیویتی ها خاص خودشون اجرا میشند < پس شما باید اونهارو در View ها خاص خودتون نمایش بدید (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+10 0

  • ساخت یک پروژه ساده در SimpleBaseGameActivity : (هر پروژه ایی به Camera , Sence نیاز داره)
  • رنگ دادن به BackGround
  • اضافه کردن Line
  • Camera = که اندازه صفحه رو نمایش میدیم < دراقع اگر ما اندازه رو 1080*1980 قرار بدیم یک بازی FullHD داریم (فکر میکنم درست گفته باشم !)
  • Sence = همون سن نمایش ، صحنه  اصلی بازی که همه چیز رو نمایش میده <
  • در متد onCreateScene ما Scence رو return میکنیم
 
public class T1_BackGround extends SimpleBaseGameActivity {

private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;


@Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}


@Override
protected void onCreateResources() {

}


@Override
protected Scene onCreateScene() {
Scene scene = new Scene();
// ترسیم یک خط از نقظه 0 و 0 تا وسط صفحه
Line line = new Line(0, 0, (CAMERA_WIDTH / 2), (CAMERA_HEIGHT / 2), this.getVertexBufferObjectManager());
scene.setBackground(new Background(1f, 0f, 0f)); // مقادیر 0 تا 1
scene.attachChild(line);
return scene;
}

}

در رابطه با this.getVertexBufferObjectManager() هنوز چیزی نمیدونم ولی لازمه فعلا به چشم Context بهش نگاه کنید :D ، بعدا سرچ میکنم راجبش اینجا توضیح میدم

 

پاسخ به سوال 
Criss  8 سال پیش
+11 0

ساخت یک پروژه ساده در BaseGameActivity

 

  • در onCreateResources مانند زیر  onCreateResourcesFinished میکنیم ، به منظور اتمام لود کردن منابع از قبیل فایل های صوتی و تصویری
  • در onCreateScene بر خلاف کد های بالا خروجی نداریم پس صحنه رو روی mEngine ست میکنیم
  • mEngine نیازی به تعریف از قبل نداره در در متد onCreateScene قابل شناسایی هست ء کافیه بنویسیدش و صحنه رو بهش ست کنید
  • همونطور که میبینید ما یک بک گراند صورتی با یک خط رو در صحنه ترسیم کردیم و نمایش دادیم
public class T2_BackGround extends BaseGameActivity {

Camera camera;
Scene mainScene;


@Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, 800, 480);
EngineOptions engineOption = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(800, 480), camera);
return engineOption;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scence = new Scene();
scence.setBackground(new Background(Color.PINK));
Line line = new Line(0, 0, 250, 250, this.getVertexBufferObjectManager());
scence.attachChild(line);
mEngine.setScene(scence);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {

}

 

پاسخ به سوال 
Criss  8 سال پیش
+11 0

آشنایی با مفاهیم بنیادی و پایه

ITextureRegion  TiledTextureRegion 
ITexture BitmapTextureAtlas
Sprite AnimatedSprite

برای نمایش تصاویر بر روی Scene باید چهار مرحله مرحله انجام بشه :

1- انتخاب تصویر از Asset و تعیین Region

2- اضافه کردن اون تصویر به BitmapTextureAtlas و لود کردن روی حافظه

3-ساخت یک Sprite از روی Region و نمایش دادن روی Scene

فرض کنید در AndEngine با دو نوع تصویر ثابت و متحرک سرو کار داریم که در زیر میبینید

برای نمایش دادن تصویر اول ابتدا باید اون رو توی یک ITextureRegion از Asset به کمک BitmapTextureAtlas لود کنیم و بعدا اون رو به یک Sprite وصل کنیم و حالا میتونید Sprite را روی Scene نمایش بدیم در نهایت یک تصویر ثابت داریم (پس برای ساخت یک تصویر ثابت از ITextureRegion و Sprite استفاده میکنیم این وسط BitmapTextureAtlas  تنها به مصرف بهینه حافظه کمک میکنه)

برای نمایش دادن تصویر دوم به یک TiledTextureRegion نیاز داریم که از Asset به کمک BitmapTextureAtlas اون رو لود کنیم و بعدا اون رو به یک AnimateSprite وصل کنیم و متدهای لازم برای تنظیمات و نحوه نمایش متحرک بودن این تصویر روی AnimatedSprite ست کنیم ،  حالا میتونید AnimateSprite را روی Scene نمایش بدیم و یک تصویر متحرک داشته باشیم (پس برای ساخت یک تصویر متحرک از TiledTextureRegion و AnimateSprite استفاده میکنیم این وسط BitmapTextureAtlas  تنها به مصرف بهینه حافظه کمک میکنه)

 

با توضیحاتی که دادم ممکنه هنوز برای شما مطلب گنگ باشه (مهم نیست که چیزی تا به اینجا متوجه نشدید ، فقط نیاز بود پیش زمینه ایی در ذهن شما شکل بگیره ، حداقل میدونید نمایش تصویر 4 مرحله نیاز داره همچنین نمایش تصویر های متحرک و ثابت شیوه خودش رو داره) تمام مفاهیمی که بالا نام بردن رو توضیح دادم و فقط مونده ITexture .

ITexture یکی از ساده ترین روش هایی هست که به کمک اون تصویری رو از روی Asset میتونیم Load کنیم ، توی این روش که کاملا ساده هست ، اثری از BitmapTextureAtlas  نیست در واقع هر دوی ITexture  و BitmapTextureAtlas  به ما کمک میکنند که تصویری رو از روی Asset لود کنیم ، اما استفاده از ITexture اصلا بهینه نیست و در ادامه و  آینده اصلا از اون استفاده نمیکنم و بجای ITextur  همیشه از BitmapTextureAtlas استفاده میکنیم چون به ما کمک میکنه مصرف حافظه خیلی بهینه تر باشه دلیل اینکه راجبش اینجا توضیح میدیم این هست که حداقل اون رو بشناسید و با سورس هایی که در کلاس SpriteExample وجود داره گیج نشید که اونجا فقط یک مثال ساده زده شده

اما چرا ITexture بهینه نیست و از  BitmapTextureAtlas استفاده میکنیم ؟ خودتون فکرش رو کنید توی یک بازی قرار بشه 10 تصویر داشته باشید چقدر حافظه مصرف میشه ؟ کاری که ITexture انجام میده ، این هست که تمامی تصاویر رو بصورت جداگانه روی حافظه لود میکنه ، اما BitmapTextureAtlas اینطوری عمل نمیکنه و تمامی تصاویر رو تحت یک تصویر قرار میده و فقط یک تصویر رو روی حافظه Load میکنه


هنوز برای کد زدن و توضیح دادن سورس کد ها نیاز به پیش زمینه های بیشتری دارید که در پست های بعدی توضیح میدم (این ابتدایی ترین موضوع در AndEngine هست پس چرا اینهمه پیش زمینه و توضیحات اضافه و بلند ؟ بله ساده هست ولی تا جایی که توانایی داشته باشم سعی میکنم جزئیات ساده و کامل بیان کنم و پس به اشتباه فکر نکنید که توضیحات به این بلندی حتما مطلب سختی رو در خودش داره ! )

 

پاسخ به سوال 
Criss  8 سال پیش
+11 0

توضیحات تکمیلی از BaseGameActivity و SimpleBaseGameActivity

در پست های قبلی با BaseGameActivity و SimpleBaseGameActivity  آشنا شدید از این به بعد فقط از BaseGameActivity استفاده میکنیم

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

هر Activity که میسازیم و به دلخواه هرکدوم رو که از BaseGameActivity و SimpleBaseGameActivity مشتق میکنیم همیشه با متد های اصلی سر و کار داریم

onCreateEngineOptions
onCreateResources
onCreateScene

در SimpleBaseGameActivity میبینم که جنس یا همون نوع متد ها مشخص شده بنابراین نیاز به این داره که در نهایت  متد Return داشته باشه

 public Scene onCreateScene() { 

در تمامی Activity ها که از جنس SimpleBaseGameActivity هستند متد onCreateScene همیشه  return میشوند همچنین متد onCreateResources که Void هست فقط منابع در اون Load میشوند و هیچ چیز خاص دیگه ایی نداره

در BaseGameActivity متد ها Void هستند اما تمامی آنها CallBack هایی دارند (همون طور که میدونید CallBack ها شباهتی مانند لیستنر ها و AsynTask ها دارند و میتونند نتیجه پردازش شده رو ارسال کنند ونتیجه رو به جایی که صدا زده شده تحویل دهند)

  public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {

توی پست های قبلی شما فقط نمونه ی ساده ایی از BaseGameActivity رو دیدید ، بنابر این در اینجا BaseGameActivity رو کامل تر توضیح میدم ، در BaseGameActivity شما باید تمام این CallBackهارو فعال کنید و خروجی های اونهارو صدا بزنید که AndEngine متوجه پایان کار متد بشه

 public class BaseGameSample extends BaseGameActivity {

@Override
public EngineOptions onCreateEngineOptions() {
// TODO Auto-generated method stub
return null;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

تفاوت دیگری که در BaseGameAcivity وجود داره این هست که یک متد اضافی به اسم onPopulateScene داره که فکر میکنم بعد از اتمام کار در متد onCreateScene این متد شروع به کار میکنه (در آینده که بیشتر یاد بگیرم اطلاعاتی در مورد onPopulateScene قرار میدم)

نکته دیگه ایی که وجود داره این هست که در پست قبلی که از BaseGameActivtiy داشتیم خروجی متد onCreateScene بصورت زیر تعریف شده بود

 mEngine.setScene(scene);

اینکه mEngine در AndEngine دقیقا این وسط بدون اینکه از قبل تعریف شده باشه چیکار میکنه رو نمیدونم ولی مشخصه یکی از متغیرهایی هست که همیشه میتونید در AndEngine ازش استفاده کنید بدون اینکه اون رو تعریف کنید ، چیزی که من تجربه کردم در مورد mEngine این هست که نیاز نیست نگرانش باشید اون هم یکی از روش های ساده برای ارسال خروجی و نمایش روی Scene هست دقیقا چیزی شبیه به ITexture هست که قبلا راجبش گفته بودم و هیچوقت دوباره ازش استفاده نمیکنیم ، چیزی که من تجربه کردم این بود :

یک اکتیوتی داشتم که با کلیک کردن روی صفحه کاراکتر مورد نظر (Sprite) باید به محلی که کلیک کرده بودم حرکت میکرد ، با اینکه همه چیز درست بود اما چون Scene رو با mEngine.setScene(scene); ست کرده بودم به کلیک هایی که روی صفحه میشد و پاسخ ها باید CallBack میشدند جواب نمیداد و خروجی برای من صحیح نمایش داده نمی شد بنابر این سورس رو به شکل زیر تغییر دادم و نتیجه حاصل شد

  pOnCreateSceneCallback.onCreateSceneFinished(scene);
//mEngine.setScene(scene);

 

چند نکته ی دیگه هم وجود داره که مانند متد زیر که میشه به BaseGameActivity و SimpleBaseGameActivity اضافه کرد مشخص میکنه که در هر ثانیه چند فریم از بازی نمایش داده بشه (از اونجایی که تجربه ایی ندارم نمیتونم بیشتر و کاربردی تر در این مورد بهتون توضیح بدم)

     @Override
public Engine onCreateEngine(EngineOptions pEngineOptions) {
return new LimitedFPSEngine(pEngineOptions, 60);
}

و متد زیر در onCreateScene که این مورد ور کاملا نمیدونم کارش چی هست !

    @Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
this.mEngine.registerUpdateHandler(new FPSLogger());
Scene scene = new Scene();
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}

 

0 0
در مورد AndEngine سوال کردم : و آقای رمضان زاده به این شکل جواب داد : mEngine همون موتور اصلی بازیه که اول ساخته میشه و ما تنظیمات خاصی رو روش اعمال می کنیم (مثلاً تنظیمات توی onCreateEngine) و خب چون بازی فقط یک موتور بازی می تونه داشته باشه (که کل دنیا و فیزیک و اشیا و زمان بندی و فریم بندی و غیره رو کنترل کنه) بهتره که بدین شکل همه جا قابل دسترسی باشه. (عاخه چرا الکی به یه چیزی گیر میدم که باعث میشه فکر و دیدم بسته بشه ، خب این کاملا مشخص بود ما بیشتر از یک انجین که نداریم :| ) (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+11 0

محور مختصات در AndEngine

محور مختصات در AndEngine بصورت زیر هست ، حتی اون Camera و EngineOption هم که مختصات 800*480  رو داره از این مختصات تبعیت میکنن ، برای اینکه در پست بعدی قرار هست BitmapTextureAtlas رو توضیح بدیم شما باید این محور مختصات رو بدونید

کافیه این قائده رو بدونید < همه چیز از نقطه 0 و 0 با توجه به مقداری که برای عرض و طول دربافت میکنه رسم میشه

این عرض و ارتفاع میتونه خود Camera و یا Scene و یا یک کاراکتر بازی 32*32 و هرچیزی باشه

پس فراموش نکنید ترسیم هرچیزی از نقطه 0 و 0 شروع میشه و با توجه به مقدار عرض و مقدار طول ترسیم میشه

حالا اگر مقدار عرض و طول منفی باشه چی میشه ؟ خب تصویر در جهت عکس رسم میشه یعنی اگر در نقطه 0 و 0 رسمش کنید چیزی ازش نمیبینید < اما اگر در مرکز صفحه قرار بدید کمی متوجه موضوع میشید

 

 

پاسخ به سوال 
Criss  8 سال پیش
+12 0

که بود وچه کرد ؟ :دی  BitmapTextureAtlas

پیشنهاد میکنم برای فهم بهتر این موضوع به آموزش های آقای سیف الله رمضان زاده مراجعه کنید (اگر منبعی که معرفی کردم رو مطالعه نکنید BitmapTextureAtlas رو متوجه  نمیشید و نمیتونید ادامه آموزش رو درک کنید !)

 در ادامه یک مثال از نمونه های کاربرد BitmapTextureAtlas در استفاده از Region و Load کردن اونهارو مثال میزنم

ابتدا یک تصویر ثابت رو در در BitmapTextureAtlas اضافه میکنیم و BitmapTextureAtlas رو Load میکنیم، بنابر این یک Activity به شکل زیر میسازیم

 public class LoadSprite extends BaseGameActivity {

ITextureRegion faceRegion;
BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, 800, 480);
EngineOptions engineOption = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(800, 480), camera);
return engineOption;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 64);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(Color.CYAN));
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

 

خب تمام موارد موجود در این Activity رو بلد هستید من فقط در مورد متد onCreateResources توضیح میدم :

        BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 64);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();

با خط اول مسیر منابع رو مشخص میکنیم که در یک فولدر به نام res در فولدر asset وجود داره

در خط بعدی BitmapTextureAtlas رو میسازیم و اندازه اون رو 64*64 قرار میدیم (امیدوارم در مورد BitmapTextureAtlas مطالعه کرده باشید ، پس حتما میدونید که ما میتونستیم این رو 32*32 تعریف کنیم چون تصویری که ما داریم همین اندازه رو داره و هیچ تصویر اضافه ایی هم نمیخوایم به BitmapTextureAtlas اضافه کنیم ، ولی من دوست دارم 64 رو انتخاب کنم !! ) ، خب این BitmapTextureAtlas که ساخته میشه در واقع یک تصویر خالی هست بصورت Transparent (کاملا شفاف) که در خطوط بعدی تصاویر دیگری بهش اضافه میشه و این عکس Transparent کم کم سکل به خودش میگیره و هر چقدر که اندازه داشته باشه میتونیم بهش تصویر اضافه کنیم در اینجا 64*64 پیکسل فضا داریم بنابر این میتونیم حداکثر 4 تصویر مختلف با اندازه 32*32 رو روی اون قرار بدیم در این مثال فقط یک تصویر 32*32 پیکسل داریم . که با توجه به خط زیر به BitmapTextureAtlas اضافه میشه

 faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);

خب میبینید که بعد از اسم تصویری که انتخاب کردیم یک مختصات 0 و 0 هم وجود داره که این مختصات مربوط میشه به BitmapTextureAtlas که در کل 64*64 هست و ما در نقطه 0 و 0 اون یک تصویر به اندازه 32*32  قرار دادیم

در مسیر یادگیری AndEngine شدیدا نیاز دارید که پارامترهای ورودی متدهارو چک کنید و با توجه به اونها مقدار دهی کنید

در ادامه فرض میکنیم که 2 تصویر دیگر با اندازه های 32*32 و 32*64 هم داریم ، در این روشی که یاد گرفتید باید دقت کنید که تصاویر روی یک دیگر قرار نگیرند (بعد از یاد گیری این مورد میتونید خودتون تست کنید که اگر مختصات تصاور روی هم قرار بگیرند در زمان Load کردن یک تصویر روی Scene چه اتفاقی میوفته !)

خب فرض میکنیم در کل 3 تصویر داریم با با اندازه های 32*32 و 32*32 و 64*32 که یکی از تصاویر روی BitmapTextureAtlas در مختصات 0 و 0 قرار گرفته

تصویر دوم که 32*32 هست رو باید در چه مختصاتی رسم کنیم که به مشکل بر نخوریم ؟ باید برابر با تصویر زیر مختصات رو از روی BitmapTextureAtlas  انتخاب کنیم

خب بزارید کمی شما رو به چالش بکشم همونطور که میبینید با استفاده از یک BitmapTextureAtlas  با اندازه 64*64 میتونیم 4 تصویر با اندازه 32*32 رو Load کنیم ، حالا اگر بخوایم 8 تصویر یعنی دوبرابر رو لود کنیم باید اندازه ها BitmapTextureAtlas  رو چقدر انتخاب کنیم ؟ اگر به نتیجه 128*128 رسیدید ؟ یعنی 64 رو دو برابر کردید باید بگم که اشتباه کردید در اندازه ایی برابر با 128*128  فضا برای 16 تصویر با اندازه 32*32 وجود داره برای لود کردن 8 تصویر باید BitmapTextureAtlas  رو برابر با 64*32 انتخاب کنیم ، یعنی فقط در یکی از جهات X , Y باید محور BitmapTextureAtlas  رو گسترش بدیم ، کمی در مورد فکر کنید به درک بهتری میرسید که در ادامه شدیدا به این درک نیاز دارید

 


در ادامه باید بگم که علاوه بر روش بالا که برای BitmapTextureAtlas مختصات وارد میکنیم و همیشه باید برای تصاویر بعدی که Load میکنیم هم مختصات دقیق و صحیحی وارد کنید که این ممکنه باعث اشتباه بشه روشی دیگر هم بجای استفاده از BitmapTextureAtlas وجود داره که توی آموزش های آقای سیف الله رمضان زاده بهش اشاره شده ، و اون هم استفاده از BuildableBitmapTextureAtlas بجای BitmapTextureAtlas هست در آینده در مورد صحبت میکنیم برای لود کردن تصاویر متحرک واقعا کار مارو راحت میکنه بعدا خودتون متوجه میشید چرا گفتم در تصاویر متحرک به کارمون میاد ، برای اینکه با BuildableBitmapTextureAtlas بیشتر آشنا بشید ، میتونید علاوه بر آموزش هایی آقای رمضان زاده باتوجه به آموزشی که بالاتر "استفاده از AndEngineExamples" دادم برید و کلاس AnimatedSpritesExampl.java رو کپی کنید و سورس قسمت مربوط به onCreateResure رو ببینید که از BuildableBitmapTextureAtlas در اونجا استفاده شده

 

علاه بر موضوع بالا نکته ایی دیگه هم وجود داره که مربوط به RGB 8888 , RGB 4444 میشه (کیفیت عکس هارو مشخص میکنه و همچنین میزان حافظه) این موضوع رو در کتاب COOKBOOK اموزش AndEngine دیدم ولی حالا چطور میهشه ازش استفاده کرد رو نمیدونم (منابع آموزشی رو در آینده معرفی میکنم)

 BitmapTextureFormat.RGBA_8888.

در حال ویرایش . . .

پاسخ به سوال 
Criss  8 سال پیش
+10 0

ادامه آموزش قبل
BitmapTextureAtlas تصاویر متحرک و

خب توی آموزش قبلی به خوبی با BitmapTextureAtlas آشنا شدید و همچنین یاد گرفتید که چطور از ITextureRegion  استفاده کنید و یک تصویر ثابت 32*32 رو با کمک ITextureRegion  و BitmapTextureAtlas رو Load کنید

در ادامه یاد میگیریم که چطور یک تصویر متحرک رو با کمک TiledTextureRegion روی BitmapTextureAtlas لود کنیم

قبل از هرچیز لازم هست دقت کنیم که در اینجا ما دو تصویر 32*32 و 132*70 داریم بنابر این باید اندازه BitmapTextureAtlas  حداقل 164*70 باشه (درواقع همیشه نیاز دارید که دقت کنید که تصاویر شما چه سایزی رو دارند و چند در چند هستند چون در آینده که بحث فیزیک و برخورد دو شی به هم و حرکت و انتقال Sprite روی صفحه رو داریم به این مختصات احتیاج پیدا میکنید)

خط زیر رو همراه با قسمت های مختلفی که داره بخوبی میشناسید

faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);

با خط زیر مقایسه کنید و متوجه متفاوت بودن Load کردن یک تصویر ثابت و یک تصویر متحرک میشید

ذananaRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "banana_tiled.png", 32, 0, 4, 2);

خب همون طور که قبلا بهتون گفته بودم همیشه نیاز دارید که پارامترهای ورودی متد هارو چک کنید و با توجه به اونها مقدار دهی کنید 

در تصویر بالا میبینیم که باید تعداد Column ها و Row هارو وارد کنید تصویری که از banana در بالا میبینید دارای 4 ستون و 2 سطر هست

 public class LoadSprite extends BaseGameActivity {

private ITextureRegion faceRegion;
private TiledTextureRegion bananaRegion;
private BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, 800, 480);
EngineOptions engineOption = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(800, 480), camera);
return engineOption;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 164, 70);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);
bananaRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "banana_tiled.png", 32, 0, 4, 2);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}

اگر توی هر کدام از مرحله های بالا اشتباهی در اندازه BitmapTextureAtlas انجام میداد (کوچکتر از اندازه مورد نیاز) و یا تعداد سطر و ستون تصویر متحرک رو اشتباه وارد میکردید < و یا مختصات اون رو بجای 32و0 مثلا 32و32 وارد میکردید (که قسمتی از تصویر banaana از BitmapTextureAtlas بزنه بیرون) تصویر در Scene کاملا سیاه نمایش داده میشد پس حتما همیشه بعد از لود کردن منابع Activity رو تست کنید

 

پاسخ به سوال 
Criss  8 سال پیش
+11 0

استفاده از Sprite ها و نمایش در Scene

Sprite اون چیزی هست که نهایتا روی Scene به نمایش گذاشته میشه Sprite از روی ITextureRegion ساخته میشه ، به اشتباه فکر نکنید که برای هر Sprite نیاز به یک ITextureRegion داریم ؟! خیر به اینصورت نیست ! در واقع شما میتونید یک ITextureRegion داشته باشید و از روی اون چندیدن Sprite تولید کنید و روی Scene به نمایش بزارید

در مثال های قبلی 90% کار رو پیش بردید و برای نمایش دادن یک Sprite کد زیادی نمونده ، دقت کنید که هنوز صحبتی از AnimatedSprite نشده و تنها داریم ازSprite  مثال میزنیم

کل پروژه ایی که تا به اینجا اومدیم بصورت زیر هست :

 public class LoadSprite extends BaseGameActivity {

private ITextureRegion faceRegion;
private TiledTextureRegion bananaRegion;
private BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, 800, 480);
EngineOptions engineOption = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(800, 480), camera);
return engineOption;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 164, 70);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);
bananaRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "banana_tiled.png", 32, 0, 4, 2);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(Color.CYAN));

Sprite sprite1 = new Sprite(0, 0, faceRegion, getVertexBufferObjectManager());
scene.attachChild(sprite1);

pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

از کد های بالا همه اش رو بلد هستید و میشناسید و فقط onCreateScene رو توضیح میدم

        Scene scene = new Scene();
scene.setBackground(new Background(Color.CYAN));

Sprite sprite1 = new Sprite(0, 0, faceRegion, getVertexBufferObjectManager());
scene.attachChild(sprite1);

pOnCreateSceneCallback.onCreateSceneFinished(scene);

از کد بالا هم تمام گزینه هارو میشناسید و فقط نحوه ساخت یک Sprite برای شما جدید هست که اون هم پارامترهای ورودی زیر رو داره که در کل چیز ساده هست ، در مورد getVertexBufferObjectManager هم اگر سوالی دارید قبلا هم گفتم هرجا بهش نیاز بود یه همین روش مقدارش رو بهش ست کنید ، در مورد float pX, float pY هم باید مختصاتی بدید که Sprite شما از اونجا شروع به ترسیم میکنه

 org.andengine.entity.sprite.Sprite.Sprite(float pX, float pY, ITextureRegion pTextureRegion, VertexBufferObjectManager pVertexBufferObjectManager)

یک نکته : قبلا بهتون گفته بودم که نیاز دارید حتما اندازه تصاویری که در ITextureRegion قرار میدید رو بدونید ، الان این گزینه به چه درد ما میخوره ؟ اگر اکتیویتی رو Run کنید میبیند که تصویر در نقطه 0 و 0 ترسیم شده در ظاهر شما متوجه این تفاوت نمیشید (اما اگر قرار باشه با کلیک شدن روی صفحه و یا با دستور کردن دادن یک Sprite رو ترسیم کنیم اونجا هست که بخوبی متوجه این تغییر میشید)

در واقع چیزی که میخوام بهتون بگم این هست که وقتی ما میگیم تصویر در نقطه 0 و 0 رسم بشه انتظار دارید مرکز تصویر در نقطه 0 و 0 قرار گرفته باشه ، ولی در اینجا میبینیم که گوشه بالا سمت چپ تصویر روی نقطه 0 و 0 از  Scene قرار گرفته !

همونطور که قبلا هم گفته بودم همه چیز در AndEngine از محور مختصات تبعیت میکنه بنابر این کاملا طبیعی هست که وقتی میگید در نقطه 0 و 0 ، ترسیم شکل به این صورت نمایش داده بشه

حالا برای اینکه مرکز Sprite روی نقطه 0 و 0 قرار بگیره باید چه کنم ؟ کد زیر مشکل رو حل میکنه

 Sprite sprite1 = new Sprite(0 - faceRegion.getWidth() / 2, 0 - faceRegion.getHeight() / 2, faceRegion, getVertexBufferObjectManager());

خب همونطور که در ابتدای این پست گفتم شما میتونید چندید Sprite از روی ITextureRegion بسازید و نمایش بدید

 Sprite sprite1 = new Sprite(0 - faceRegion.getWidth() / 2, 0 - faceRegion.getHeight() / 2, faceRegion, getVertexBufferObjectManager());
Sprite sprite2 = new Sprite(32, 32, faceRegion, getVertexBufferObjectManager());
Sprite sprite3 = new Sprite(64, 64, faceRegion, getVertexBufferObjectManager());
scene.attachChild(sprite1);
scene.attachChild(sprite2);
scene.attachChild(sprite3);
پاسخ به سوال 
Criss  8 سال پیش
+11 0

جنبه های مختلف و اطلاعات تکمیلی از Sprite ها

استفاده از  AnimateSprite ها بصورت ساده

 در آموزش قبلی به خوبی تونستید یک Sprite رو در Scene نمایش بدید ، توی این پست جنبه های مختلف و اطلاعات تکمیلی رو توضیح میدیم که بهتر موضوع رو درک کنید

شاید برای شما هم سوال بشه اگر تصویر موز رو بجای اینکه با TiledTextureRegion لود کنیم اون رو با ITextureRegion   لود میکردیم چه اتفاقی می افتاد ؟ (پیشنهاد میکنم ادامه آموزش رو دنبال نکنید و خودتون دست بکار بشید و سعی کن)

احتمالا با اولین اجرای Activity با یک تصویر سیاه مواجه میشید ، کمی فکر میکنید و متوجه میشید که باید اندازه Atlas رو افزایش میداد و باید از نظر عرضی برای نقطه y حداقل 70 پیکسل پایین تر مختصات رو انتخاب کنید

ممکنه جاهایی دگه ایی هم به مشکل بر بخورید پس بهتر بهش فکر کنید که در نتیجه درکتون در یادگیری AndEngine افزایش پیدا کنه

در نهایت میتونید مثل من زیاد خودتون رو درگیر محاسبات دقیق نکنید و اندازه Atlas رو 500*500 در نظر بگیرید

 public class LoadSprite extends BaseGameActivity {

private ITextureRegion faceRegion;
private TiledTextureRegion bananaRegion;
private ITextureRegion bananaRegion2;
private BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, 800, 480);
EngineOptions engineOption = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(800, 480), camera);
return engineOption;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 500, 500);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);
bananaRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "banana_tiled.png", 32, 0, 4, 2);
bananaRegion2 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "banana_tiled.png", 0, 200);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}

حالا میتونید یک Sprite درست کنید و اون رو روی Scene نمایش بدید < تصویر جدیدی که نمایش داده میشه یک تصویر کامل از تمام 8 تا banana ها هست

مورد دوم که میتونید تست کنید این هست که مختصات مختلفی به این bananaRegion2  بدید میبینید که توی بعضی مختصات که روی دیگر Region ها رسمش کردید در موقع نمایش دادن روی Scene تصویر اصلی زیر تصویری قرار مییگیره که مختصات اشتباهی بهش داده شده و دیده نمیشه !

خب بهتره که banana رو با TiledTextureRegion لود کنید و اون روی به یک Sprite وصل کنید و روی Scene نمایش بدید ، میبینید که بخوبی نمایش داده میشه ، نمیدونم چی انتظار داشتید ولی شاید یادتون باشه که در بالا من گفته بودم برای نمایش تصاویر متحرک از TiledTextureRegion استفاده میکنیم و برای نمایش TiledTextureRegion از AnimateSprite استفاده میکنیم ولی میبینید که اینجا خلاف حرف من ثابت شده و شما تونستید banana رو که یک TiledTextureRegion هست بوسیله یک Sprite نمایش بدید

اگر کمی تیز باشید حتما میرید و با AnimateSprite هم تست میکینم و باز هم میبینید که خروجی همون چیزی هست که با Sprite نمایش داده میشه !

   @Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(Color.CYAN));

Sprite sprite1 = new Sprite(0 - faceRegion.getWidth() / 2, 0 - faceRegion.getHeight() / 2, faceRegion, getVertexBufferObjectManager());
Sprite sprite2 = new Sprite(32, 32, faceRegion, getVertexBufferObjectManager());
Sprite sprite3 = new Sprite(64, 64, faceRegion, getVertexBufferObjectManager());
Sprite sprite4 = new Sprite(0, 150, bananaRegion2, getVertexBufferObjectManager());
AnimatedSprite bananaAnimateSprite = new AnimatedSprite(250, 250, bananaRegion, getVertexBufferObjectManager());
Sprite bananaSprite = new Sprite(300, 300, bananaRegion, getVertexBufferObjectManager());
scene.attachChild(sprite1);
scene.attachChild(sprite2);
scene.attachChild(sprite3);
scene.attachChild(sprite4);
scene.attachChild(bananaSprite);
scene.attachChild(bananaAnimateSprite);

pOnCreateSceneCallback.onCreateSceneFinished(scene);
}

خب بله باید هم خروجی به این صورت باشه به این دلیل که شما به AnimateSprite تنظیمات مربوط به نحوه نماش متحرک بودن تصویر  رو ست نکردید عین  جمله ایی که گفتم رو اینجا براتون دوباره قرار میدم

برای نمایش دادن تصویر دوم به یک TiledTextureRegion نیاز داریم که از Asset به کمک BitmapTextureAtlas اون رو لود کنیم و بعدا اون رو به یک AnimateSprite وصل کنیم و متدهای لازم برای تنظیمات و نحوه نمایش متحرک بودن این تصویر روی AnimatedSprite ست کنیم ،  حالا میتونید AnimateSprite را روی Scene نمایش بدیم و یک تصویر متحرک داشته باشیم (پس برای ساخت یک تصویر متحرک از TiledTextureRegion و AnimateSprite استفاده میکنیم این وسط BitmapTextureAtlas  تنها به مصرف بهینه حافظه کمک میکنه)


 

شاید براتون جالب باشه که چرا تصویر banana که TiledTextureRegionبود با اینکه ما بهش طول و عرض خاصی ست نکردیم و چطور داره اولین تصویر از مجموع 8 تصویر دیگه رو نمایش میده ؟ ول اگر دقت کنید ما  یکبار تعداد ستون ها و تعداد سطر ها رو بهش ست کرده بودیم بنابر این حداقل مقدار سطر و ستون اول رو در خودش نگه میداره و نمایش میده

پاسخ به سوال 
Criss  8 سال پیش
+10 0

پایان AnimatedSprite و نمایش یک تصویر متحرک

 خب حالا چطور میتونیم یک تصویر متحرک روی Scene اضاف کنیم

با اینکه حالت ها و روش های مختلفی وجود داره که در ادامه بهش می پردازیم اما در ساده ترین حالت ممکن کافیه کافیه کد زیر رو بزنید :

 bananaAnimateSprite.animate(100);

 

مقدار 100 در بالا تعیین میکنه که از تصویر از 8 تصویر بالا 100 میلی ثانیه نمایش داده بشه بنابر این اگر بجای 100 عدد 1000 رو وارد کنید هر تصویر 1 ثانیه طول میکشه و در کل که 8 تصویر داریم 8 ثانیه به طول می انجامد اگر من بودم روی 125 قرار میدادم تا کلا 1 ثانیه اجرای این انیمیشن متحرک زمان صرف کنه (ازاین به بعد بجای استفاده از عبارت تصویر ، میگیم فریم)

 @Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(Color.CYAN));

Sprite sprite1 = new Sprite(0 - faceRegion.getWidth() / 2, 0 - faceRegion.getHeight() / 2, faceRegion, getVertexBufferObjectManager());
Sprite sprite2 = new Sprite(32, 32, faceRegion, getVertexBufferObjectManager());
Sprite sprite3 = new Sprite(64, 64, faceRegion, getVertexBufferObjectManager());
Sprite sprite4 = new Sprite(0, 150, bananaRegion2, getVertexBufferObjectManager());
AnimatedSprite bananaAnimateSprite = new AnimatedSprite(250, 250, bananaRegion, getVertexBufferObjectManager());
Sprite bananaSprite = new Sprite(300, 300, bananaRegion, getVertexBufferObjectManager());
scene.attachChild(sprite1);
scene.attachChild(sprite2);
scene.attachChild(sprite3);
scene.attachChild(sprite4);
scene.attachChild(bananaSprite);
scene.attachChild(bananaAnimateSprite);
bananaAnimateSprite.animate(125);

pOnCreateSceneCallback.onCreateSceneFinished(scene);
}

( برای خود من سواله اگر bananaAnimateSprite رو به Scene اضاف کنیم مقدار animate رو بعدا بهش بدیم مانند کد بالا و یا قبل از اینکه به Scene اضاف کنیم مقدار animate بهش چه تفاوتی داره ؟ احتمالا اینجا چون داریم از CallBack استفاده میکنیم هیچ تفاوتی نداره! )

خب برای اینکه با نحوه AnimateSprite ها بهتر آشنا بشید پیشنهاد میکنم طبق آموزشی که بالاتر گذاشتم "استفاده از AndEngineExamples" کلاس AnimatedSpritesExample.java رو پیدا کنید < کپی کنید و اجرا کنید اونجا هست که متونید یاد بگیرید این AnimateSprite ها چقدر میتونه انعطاف پذیر باشه

خب اینجا یک نمونه از animate رو توضیح دادم نمونه دوم رو هم توضیح میدم نمونه ی دیگه ایی تست نکردم و ندیده ام البته که نمونه های مختلف دیگه ای هم وجود داره < کافیه جلوی متد animate یک CTRL+SPACE بزنید <

خب متد های ورودی animate قبلی به شرح زیر بود فقط یک مقدار  FrameDuration هست !

 org.andengine.entity.sprite.AnimatedSprite.animate(long pFrameDurationEach)

اما یک animate دیگه هم داریم با مقادیر های زیر

 org.andengine.entity.sprite.AnimatedSprite.animate(long[] pFrameDurations, int pFirstTileIndex, int pLastTileIndex, boolean pLoop)

که به شکل زیر مقادیر بهش ست میشه

// bananaAnimateSprite.animate(125);
bananaAnimateSprite.animate(new long[]{ 100, 100, 100, 100, 100, 100, 100, 100 }, 0, 7, true);

تصویر ما 8 قسمت داشت که ما باید یک آرایه  8 عنصری رو معرفی کنیم که مشخص میکنه هر فریم در چند میلی ثانیه نمایش داده بشه < قسمت دوم بهش میگیم که از index 0 تا index 7 که تعدادشون میشه 8 تا رو باید animate کنه index0 تا index7 همون سطر و ستون های هستند که توی آموزش قبلی دیدید که وقتی از Sprite استفاده میکنید < بصورت پیشفرض index0 رو نمایش میده و در آخر مقدار true میزاریم مبنی بر اینکه آیا این انیمیشن تکرار بشه یا خیر !

خب اونجایی که گفتم SpriteAnimate ها میتونه منعطف باشه این مثال هست : که تنها index1 , index2 رو نمایش میده

        //bananaAnimateSprite.animate(125);
//bananaAnimateSprite.animate(new long[]{ 100, 100, 100, 100, 100, 100, 100, 100 }, 0, 7, true);
bananaAnimateSprite.animate(new long[]{ 100, 100 }, 1, 2, true);

 

در حال ویرایش . . .

 

پاسخ به سوال 
Criss  8 سال پیش
+11 0

EntityModifier

خب موضوع بعدی ModiFire ها هستند که این موضوع هم واقعا ساده هست

پیشنهاد میکنم با توجه به آموزش های آقای سیف الله رمضان زاده که به ترتیب بهتون معرفی میکنم مطالعه ایی رو انجام بدید که درک کافی در ذهنتون شکل بگیره

MoveModifier
LoopEntityModifier

همچنین با توجه به آموزش "استفاده از AndEngineExamples" که بالاتر تصویری آموزش دادیم کلاس های زیر رو استفاده کنید میتونید با دیدن کد ها همه چیز رو یاد بگیرید

EntityModifierExample.java

EntityModifierIrregularExample.java

در ادامه یافته های خودم رو براتون مثال میزنم : یک پروژه بصورت زیر میسازیم < دیگه همه چیزش رو بلدید

 

 public class Modifire extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private ITextureRegion faceRegion;
private TiledTextureRegion bananaRegion;
private BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
EngineOptions engineOption = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
return engineOption;
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");
atlas = new BitmapTextureAtlas(getTextureManager(), 256, 256);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "face_box.png", 0, 0);
bananaRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "banana_tiled.png", 32, 0, 4, 2);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.5f, 0.5f, 0.5f));
Sprite face = new Sprite((WIDTH / 2) - 100, (HEIGHT / 2), faceRegion, getVertexBufferObjectManager());
AnimatedSprite happyBanana = new AnimatedSprite((WIDTH / 2) + 100, (HEIGHT / 2), bananaRegion, getVertexBufferObjectManager());
happyBanana.animate(125);

scene.attachChild(face);
scene.attachChild(happyBanana);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

 خب همه چیز آماده هست که یک Modifier رو تست کنیم برای اعمال Modifier ها باید از متد _ برای Sprite ها استفاده کنیم

 sprite.registerEntityModifier

برای اویل مثال از Modifier مربوط به Scale (سایز و اندازه) استفاده میکنم

new ScaleModifier(pDuration, pFromScale, pToScale)
 andengine.entity.modifier.ScaleModifier.ScaleModifier(float pDuration, float pFromScale, float pToScale)

که مقدار اول زمان هست و مقدار 2 رو وارد میکنیم یعنی این Modifier باید در مدت زمان 2 ثانیه انجام بشه مقدار دوم این و سوم هم مشخص هست از چه اندازه ایی به چه اندازه ایی Scale انجام بشه

 ScaleModifier scale = new ScaleModifier(2, 1f, 2f);
face.registerEntityModifier(scale);

برای اندازه ها اگر 1 رو وارد کنید برابر اندازه طبیعی ،  مقدار 2 و دوبرابر اندازه عادی و هر چی بیشتر به همون برابر تصویر تغییر میکنه ، اندازه 0.5 هم ندازه رو نصف میکنه

برای Modifier ها میشه Listener تعریف کرد که وقتی کار به اتمام رسید به شما خبر بده ما بعد از اینکه اندازه تصویر 2 برابر شد لون رو به حالت اولش بر میگردونیم

 ScaleModifier scale = new ScaleModifier(2, 1, 2);
face.registerEntityModifier(scale);
scale.addModifierListener(new IModifierListener<IEntity>() {

@Override
public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {}


@Override
public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
face.registerEntityModifier(new ScaleModifier(2, 2, 1));
}
});

Modifier رو هم به شکل زیر میتونید استفاده کنید (میدونید دوتا Modifier رو باهم ست کنید)

 AlphaModifier alpha = new AlphaModifier(2, 1, 0.2f);


ScaleModifier scale = new ScaleModifier(2, 1, 2);
AlphaModifier alpha = new AlphaModifier(2, 1, 0.2f);
face.registerEntityModifier(scale);
face.registerEntityModifier(alpha);

Modifier ها در صورتی که با هم منافاتی نداشته باشند میتونید چندتارو با هم ست کنید اما توی مثال زیر میبیند که Modifier  دوم اعمال نمیشه

        ScaleModifier scale = new ScaleModifier(2, 1, 2);
ScaleModifier scale2 = new ScaleModifier(2, 2, 1);
face.registerEntityModifier(scale);
face.registerEntityModifier(scale2);

چند نمونه از Modifier ها رو که تست کردم رو اینجا میزارم خودتون خروجی بگیرید و ببینید

                               //new JumpModifier(2, 50, 50, 300, 300, 2) // این رو خودم هرچی تست متوجه نشدم !
new ColorModifier(2, Color.RED, Color.BLUE)
new ScaleModifier(1, 2, 1)
new ScaleModifier(1, 1, 2)
new AlphaModifier(1, 1, 0.4f)

در حال ویرایش . . .

پاسخ به سوال 
Criss  8 سال پیش
+11 0

LoopEntityModifier و SequenceEntityModifier و ParallelEntityModifier

همونطور که در LoopEntityModifier توضیح داده شد :

 LoopEntityModifier : این Entity Modifier به ما اجازه می دهد تا یک Modifier را به صورت نامحدود یا N  بار تکرار کنیم.

  • ParallelEntityModifier : این Entity Modifier به ما اجازه می دهد تا چندین Modifier را همزمان استفاده کنیم و انیمیشن های پیچیده ای ایجاد کنیم.
  • SequenceEntityModifier : این Entity Modifier به ما اجازه می دهد تا زنجیره از Modifier ها را به وجود بیاوریم و چندین Modifier را پشت سر هم بر روی یک Entity اعمال کنیم ، استفاده از DelayModifier هنگام استفاده از SequenceEntityModifier می تواند مفید و جذاب واقع شود.

 تا اینجا یاد گرفتید که چطور بصورت خیلی ساده با استفاده از registerEntityModifier یک Modifier شاده رو استفاده کنید ، در اینجا با استفاده از  SequenceEntityModifier میتونید چندین Modifier ساده رو با هم به ترتیب استفاده کنید

با استفاده از ParallelEntityModifier میتونید از چندین SequenceEntityModifier که استفاده کنید (که SequenceEntityModifier  خودش چندین Modifier رو داره )

LoopEntityModifier هم به شما کمک میکنه که بتونید بصورت پیاپی Modifier هارو تکرار کنید

یک مثال از SequenceEntityModifier :

        //> SequenceEntityModifier
ColorModifier colorModifier = new ColorModifier(2, Color.RED, Color.BLUE);
face.registerEntityModifier(
new SequenceEntityModifier(
//new ColorModifier(2, Color.RED, Color.BLUE),
colorModifier,
new DelayModifier(0.5f),
new ScaleModifier(1, 1, 2),
new DelayModifier(0.5f),
new ScaleModifier(1, 2, 1),
new DelayModifier(0.5f),
new AlphaModifier(1, 1, 0.4f),
new DelayModifier(0.5f),
new AlphaModifier(1, 0.4f, 1)));

یک مثال از ParallelEntityModifier :

        //> ParallelEntityModifier
SequenceEntityModifier seModifier1 = new SequenceEntityModifier(new ScaleModifier(1, 1, 2),
new DelayModifier(0.5f),
new ScaleModifier(1, 2, 1));
SequenceEntityModifier seModifier2 = new SequenceEntityModifier(new AlphaModifier(1, 1, 0.4f),
new DelayModifier(0.5f),
new AlphaModifier(1, 0.4f, 1));

face.registerEntityModifier(new ParallelEntityModifier(seModifier1, seModifier2));

مثال از LoopEntityModifier :

برای LoopEntityModifier شما میتونید تعیین کنید که Modifier ها چه به تعداد تکرار بشوند و یا اینکه بصورت نامحدود همیشه در حال حرکت باشند :

 face.registerEntityModifier(new LoopEntityModifier(new ParallelEntityModifier(seModifier1, seModifier2), 3));

نمونه ایی از تکرار بی نهایت :

 face.registerEntityModifier(
new LoopEntityModifier(
new SequenceEntityModifier(
new ColorModifier(2, Color.RED, Color.BLUE),
new DelayModifier(0.5f),
new ScaleModifier(1, 1, 2),
new DelayModifier(0.5f),
new ScaleModifier(1, 2, 1),
new DelayModifier(0.5f),
new AlphaModifier(1, 1, 0.4f),
new DelayModifier(0.5f),
new AlphaModifier(1, 0.4f, 1))));

ا

پاسخ به سوال 
Criss  8 سال پیش
+10 0

MoveModifier و PathModifier

استفاده از EaseFunction ها

همونطور که در آموزش های آقای رمضان زاده گفته شد Modifier ها به همین جا ختم نمیشوند در ادامه آخرین چیزهایی که از Modifier ها بلد هستم رو به اشتراک میزارم

 MoveModifier :

این Modifier به شما کمک میکنه که تعیین کنید یک Sprite از یک نقطه X,Y به یک نقطه X,Y در زمان مشخصی حرکت کنه

//MoveModifier(pDuration, pFromX, pToX, pFromY, pToY) 

 MoveModifier moveModifer = new MoveModifier(5, 0, 800, 0, 480);
face.registerEntityModifier(moveModifer);

حتما متوجه این موضوع شدید که بعد از اتمام MoveModifier که در بالا ست کردیم Sprite از تصویر خارج میشه ، خب این کاملا طبیعی هست < همونطر که بهتون گفتم همه چیز از محور مختصات تبعیت میکنه و در محور مختصات همه چیز ار نقطه 0 و 0 در جهت عرض و طول ترسیم میشه < بنابراین تصویر ما از نقطه 800*480  شروع به ترسیم میکنه درحالی که به سمت خارج از Camera و Scene ترسیم میشه ، کد رو به شکل زیر تصحیح میکنیم

 MoveModifier moveModifer = new MoveModifier(5, 0, 800 - (face.getWidth() / 2), 0, 480 - (face.getHeight() / 2));
face.registerEntityModifier(moveModifer);

PathModifier :
این Modifier کمک میکنه چندیدن نقطه مختلف از مختصات برای حرکت کردن به Sprite ست کنید در تصویر نمونه ایی که قرار هست اجرا کنیم رو میبینید : (شروع از 0*0  پایان در 800*480)

Path path = new Path(5).to(0, 0).to(400, 0).to(400, 240).to(800, 240).to(800 - (face.getWidth()), 480 - (face.getHeight()));
face.registerEntityModifier(new PathModifier(5, path));

در مثال بالا PathModifier از دوقسمت تشکیل شده یکی مدت زمان هست و دومی Path هست ،  PathModifier بیشتر از این نیازی به توضیح نداره ، در مورد Path که از دو بخش تشکل شده بخش اول تعداد حرکت ها هست که در اینجا 5 هست ، حداقل تعدادی که میشه تعیین کرد هم 2 هست ، بخش دوم تشکیل میشه از مختصاتی از X,Y که باید به تعداد 5 بار تعریف بشه

EaseFunction :

AndEngine استفاده از EaseFunction ها رو خیلی راحت کرده ، برای اینکه با EaseFunction ها آشنا بشید برید Example اصلی AndEngine رو اجرا کنید و نمونه های مختلفش رو خودتون تست کنید در کلاس EaseFunctionExample.java به تعداد 36 نمونه مختلف رو مثال زده

 

برای ترکیب کردن EaseFunction با PathModifier و MoveModifier بصورت زیر کد میزنیم :

MoveModifier moveModifer = new MoveModifier(5, 0, 800 - (face.getWidth() / 2), 0, 480 - (face.getHeight() / 2), EaseBounceInOut.getInstance());
face.registerEntityModifier(moveModifer);

Path path = new Path(5).to(0, 0).to(400, 0).to(400, 240).to(800, 240).to(800 - (face.getWidth()), 480 - (face.getHeight()));
face.registerEntityModifier(new PathModifier(5, path, EaseBackIn.getInstance()));

 

در حال ویرایش . . .

پاسخ به سوال 
Criss  8 سال پیش
+10 0

تشخیص Touch روی Scene

 برای تشخیص کلیک شدن روی Scene باید اکتیویتی رو impelement کنیم از IOnSceneTouchListener و در این شرایط یک متد جدید به اسم onSceneTouchEvent به اکتیویتی اضافه میشه

public class TouchSceneAndArea extends BaseGameActivity implements IOnSceneTouchListener {

متد جدید :

  @Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
return false;
}

برای اینکه بتونیم از این متد استفاده کنیم لازم هست که که متد زیر رو در onCreateScene استفاده کنیم :

 scene.setOnSceneTouchListener(this);

بعد از این میتونیم مقدار X و Y در محل کلیک شده رو بدست بیاریم :

  @Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
pSceneTouchEvent.getX();
pSceneTouchEvent.getY();
return false;
}

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

 public class TouchSceneAndArea extends BaseGameActivity implements IOnSceneTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.8f, 0.8f, 0.8f));

scene.setOnSceneTouchListener(this);

pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
Log.i("TOUCH", pSceneTouchEvent.getX() + " " + pSceneTouchEvent.getY());
return false;
}
}

حتما متوجه این موضوع شدید که با هر بار کلیک روی Scene کلی لاگ در خروجی نمایش داده میشه ، به این دلیل هست که این یک onClickListener ساده برای یک Button نیست ، در اینجا ما با Event سرو کار داریم ، Event ها مشخص میکنه که چه نوع کلیک شدنی روی Scene انجام شده

بصورت زیر کد بزنید اکتیویتی رو اجرا کنید و تست کنید خودتون متوجه میشید چه اتفاقی افتاده :

    @Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionDown()) {
Log.i("TOUCH", pSceneTouchEvent.getX() + " " + pSceneTouchEvent.getY());
return true;
}
return false;
}

 در بالا میبینید که بعد از گرفتن Log مقدار true  رو Return کردیم ، شیوه صحیح کد زدن این هست چون نوع متد Boolean هست ، اما هنوز اینکه از نظر کاربردی چطور میتونه به ما کمک کنه رو نمیدونم ، و  نمیتونم مثال خوبی بزنم

پاسخ به سوال 
Criss  8 سال پیش
+10 0

تشخیص Touch روی یک Sprite

 برای تشخیص کلیک شدن روی یک Sprite اکتیوتی رو از IOnAreaTouchListener بصورت زیر Impelement میکنیم و متد جدیدی به اکتیویتی اضافه میشه

public class TouchArea extends BaseGameActivity implements IOnAreaTouchListener {

در ادامه مقدمات استفاده از متد onAreaTouched که جدیدا به اکتیویتی اضاف شده رو طی میکنیم : اکتیوتی به شکل زیر داریم

public class TouchArea extends BaseGameActivity implements IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

TiledTextureRegion faceRegion;
BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");
atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.6f, 0.8f, 0.2f));

AnimatedSprite faceSprite = new AnimatedSprite((WIDTH / 2) - (faceRegion.getWidth() / 2), (HEIGHT / 2) - (faceRegion.getHeight() / 2), faceRegion, getVertexBufferObjectManager());
faceSprite.animate(100);
scene.attachChild(faceSprite);

pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
// TODO Auto-generated method stub
return false;
}
}

خب در ادامه ابتدا باید به متد onCreateScene متد زیر رو استفاده کنیم :

scene.setOnAreaTouchListener(this);

برای اینکه کلیک شدن روی هر Sprite تشخیص داده بشه ، باید مشخص کنیم که کدوم Sprite قراره روش کلیک بشه :

 scene.registerTouchArea(faceSprite);

 در نهایت اکتیوتی به شکل زیر داریم :

 public class TouchArea extends BaseGameActivity implements IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

TiledTextureRegion faceRegion;
BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");
atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.6f, 0.8f, 0.2f));
scene.setOnAreaTouchListener(this);

AnimatedSprite faceSprite = new AnimatedSprite((WIDTH / 2) - (faceRegion.getWidth() / 2), (HEIGHT / 2) - (faceRegion.getHeight() / 2), faceRegion, getVertexBufferObjectManager());
faceSprite.animate(100);

scene.attachChild(faceSprite);
scene.registerTouchArea(faceSprite);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
Log.i("TouchArea", "New Event On Sprite");
return false;
}
}

 

پاسخ به سوال 
Criss  8 سال پیش
+10 0

ساخت یک بازی ساده

توی مثال سعی میکنیم یک بازه ساده بسازیم : قرار هست در این بازی یک Sprite داشته باشیم که هرجایی که روی صفحه کلیک میکنیم به اون نقطه حرکت کنه

همچین اگر روی خودش کلیک کنیم یک Modifier رو نمایش میدیم که sprite به مرور غیب میشه و دوباره ظاهر میشه :

اکتیویتی به شکل زیر باید ساخت بشه:

 public class TouchGame extends BaseGameActivity implements IOnSceneTouchListener, IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion faceTileRegion;
private AnimatedSprite faceSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
faceTileRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.7f, 0.8f, 0.1f));
scene.setOnAreaTouchListener(this);
scene.setOnSceneTouchListener(this);

faceSprite = new AnimatedSprite(0, 0, faceTileRegion, getVertexBufferObjectManager());
faceSprite.animate(100);

scene.registerTouchArea(faceSprite);
scene.attachChild(faceSprite);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionDown()) {
AnimatedSprite sprite = (AnimatedSprite) pTouchArea;
SequenceEntityModifier seModifier = new SequenceEntityModifier(new FadeOutModifier(1),
new DelayModifier(0.5f),
new FadeInModifier(1));
sprite.registerEntityModifier(seModifier);
return true;
}
return false;
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionDown()) {
MoveModifier move = new MoveModifier(2, faceSprite.getX(), pSceneTouchEvent.getX(), faceSprite.getY(), pSceneTouchEvent.getY());
faceSprite.registerEntityModifier(move);
return true;
}
return false;
}
}

تمام کد بالا رو بلد هستید و تنها نکته ایی که در کد وجود داره مربوط به متد onAreaTouched هست در خط زیر

 AnimatedSprite sprite = (AnimatedSprite) pTouchArea;

اینقدر ساده و شفاف هست که که فکر میکنم نیاز به توضیح نداشته باشه ، در واقع با استفاده از pTouchArea میتونیم اون Sprite که روش کلیک رو شده کست کنیم و بگیریم (هنوز در مورد اینکه چطور میشه بصورت داینامیک Sprite , AnimateSprite در یافت کرد چیزی نمیدونم)

پاسخ به سوال 
Criss  8 سال پیش
+9 0

IPathModifierListener ، آموزش های تکمیلی از PathModifier و AnimateSprite های حرفه ایی تر !

خب با دیدین تصویر بالا میدونید که برای نمایش دادنش به TiledTuxtureRegion و AnimateSprite نیاز داریم . مشکلی که وجود داره این هست که این Sprite مثل تصویر Banana نیست و نمیشه فریم های index صفر تا index  یازدهم رو به پشت سر هم نمایش داد و حتی اگر اونهارو پشت سر هم اجرا کنیم اصلا جالب نیست و انیمیشن خروجی اصلا جالب نمیشه

برای SpriteSheet که در بالا میبینید ما به ROW 1 (سطر اول) نیاز داریم که تشکیل شده از سه فریم هست برای زمانی که به سمت بالا حرکت میکنه و بقیه ROW ها هم برای زمانی هست که Sprite در جهات دیگر در حال حرکت باشه  (قبلا بهتون یاد دادم که چطور نمایش فریم هارو محدود کنید)

در ادامه به معرفی IPathModifierListene  میپردازیم که یک لیستنر برای PathModifier هست و همچنین یادمیگیریم که چطور از روش دوم animate شدن یک AnimateSprite به که قبلا هم باهاش آشنا شدیم  به شیوه درست استفاده کنیم

همونطور که میدونید برای استفاده از PathModifier نیاز بود که یک Path از قبل براش مشخص کنیم ، این Path از دو بخش تشکیل میشد بخش اول که تعداد و اندازه (Lenght) بود و بخش دوم به همون اندازه نقاط X,Y

کاری که IPathModifierListene  انجام میده این هست که به ما خبر میده در حال حاضر کدوم یکی از Pathدر حال اجرا هست

 Path path = new Path(5).to(0, 0).to(400, 0).to(400, 240).to(800, 240).to(800 - (face.getWidth()), 480 - (face.getHeight()));

اگر یک path به شکل بالا داشته باشیم در لحظه اجرا IPathModifierListene  به ما Index 0 رو خروجی میشه یعنی 0و0 که در بالا میبینید بعد از اون Index1 که مربوط به 400,0 هست و به همین ترتیب که در آخرین نقطه 4 رو به ما خروجی میده

از اونجایی که PathModifierیک شیوه ساده برای حرکت دادن Sprite هست و مسیر های مشخصی داره پس ما از قبل میدونیم که مسیر حرکت این Sprite به چه شکل هست یعنی وقتی IPathModifierListene  داره خروجی های 0 تا 4 رو به ما نشون میده دقیقا میدونیم که Sprite داره در کدوم جهت حرکت میکنه و این به ما کمک میکنه که در این لحظه تعیین کنید که کدون ROW باید روی Sprite باید animate بشه

خب دیگه خودتون همه چیز رو بلد هست یک Path بسازید که Sprite شروع کنه چهار گوشه Scene رو بصورت نامحدود حرکت کنه

فایل player.png در آدرس gfx در asset از پروژه AndEngineExample وجود داره همونجا برش دارید تست کنید < کد هارو به کلاس Modifiere که قبلا آموزش داده بودیدم اضاف کنید و تست کنید : (دیگه خودتون باید بدونید جای هرکدوم از کدهای زیر کجای اکتیویتی هست)

private TiledTextureRegion playerRegion;
playerRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "player.png", 0, 70, 3, 4);
AnimatedSprite spritePlayer= new AnimatedSprite(50, 50, playerRegion, getVertexBufferObjectManager());
spritePlayer.animate(170);
scene.attachChild(spritePlayer);

خب بعد از اجرا کردن کدهای بالا میبینید که این player در حال قدم زدن هست و بدنش رو در جهت های مختلف تغییر جهت میده در حالی که حرکت نمیکنه و داره درجا میزنه ، بصورت زیر کاری میکنیم که player در چهار طرف Scene بصورت نامحدود در حال حرکت باشه

Path pathPlayer = new Path(5).to(50, 50).to(750, 50).to(750, 430).to(50, 430).to(50, 50);
spritePlayer.registerEntityModifier(new LoopEntityModifier(new PathModifier(12, pathPlayer)));

همونطور که در کد بالا میبینید بدون استفاده از EaseFunction ها Sprite موقع تغییر جهت دادن به یک باره تغییر جهت میده و اصلا جالب نیست و حالت مصنوعی بودن اون زیاد هست با استفاده از EaseSineInOut.getInstance() این حالت رو کمی طبیعی تر میکنیم

spritePlayer.registerEntityModifier(new LoopEntityModifier(new PathModifier(12, pathPlayer, EaseSineInOut.getInstance())));

در ادامه میریم که از IPathModifierListene استفاده کنیم یک لیستنر خشک و خالی بصورت زیر ایجاد میکنیم

 IPathModifierListener listener = new IPathModifierListener() {

@Override
public void onPathStarted(final PathModifier pPathModifier, final IEntity pEntity) {
Debug.d("onPathStarted");
}


@Override
public void onPathWaypointStarted(final PathModifier pPathModifier, final IEntity pEntity, final int pWaypointIndex) {
Log.i("LOG", "onPathWaypointStarted: " + pWaypointIndex);

}


@Override
public void onPathWaypointFinished(final PathModifier pPathModifier, final IEntity pEntity, final int pWaypointIndex) {
Debug.d("onPathWaypointFinished: " + pWaypointIndex);
}


@Override
public void onPathFinished(final PathModifier pPathModifier, final IEntity pEntity) {
Debug.d("onPathFinished");
}
};

این لیستنر رو باید کجا استفاده کرد ؟ طریقه استفاده از اون رو در زیر میبینید :

 

0 0
این پست دیگه ظرفیت اضافه کردن کارکارتر نداره و ادامه رو در زیر میزارم < ! (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+10 0

این لیستنر رو باید کجا استفاده کرد ؟ طریقه استفاده از اون رو در زیر میبینید :

 spritePlayer.registerEntityModifier(new LoopEntityModifier(new PathModifier(12, pathPlayer, listener, EaseSineInOut.getInstance())));

تنها نکته جدیدی که به چشم میاد Debug هست که این برای AndEngine هست برای نمایش LOG با تگ پیشفرض AndEngine ، خودتون هم میدتوید براش تگ تعریف کنید و هم میتونید لولش رو تغییر بدید < بهتر کم کم راه بیوفتید و این چیزهای ساده رو خودتون تست کنید و سرو ته قضیه رو متوجه بشید .

خب در ادامه باید باتوجه به حالت هایی که Listener به ما خبر میده تصمیم بگیریم حتما خودتون دیگه اون LOG ایی که توی لیستنر گذاشته بودم رو چک کردید و متوجه موضوع شدید ، قبل از هر چیز باید خط زیر رو کامنت کنید

//spritePlayer.animate(170);

کد به شکل زیر میشه :

 IPathModifierListener listener = new IPathModifierListener() {

@Override
public void onPathStarted(final PathModifier pPathModifier, final IEntity pEntity) {
Debug.d("onPathStarted");
}


@Override
public void onPathWaypointStarted(final PathModifier pPathModifier, final IEntity pEntity, final int pWaypointIndex) {
Log.i("LOG", "onPathWaypointStarted: " + pWaypointIndex);
switch (pWaypointIndex) {
case 0:
spritePlayer.animate(new long[]{ 200, 200, 200 }, 3, 5, true); //RIGHT
break;
case 1:
spritePlayer.animate(new long[]{ 200, 200, 200 }, 6, 8, true); //DOWN
break;
case 2:
spritePlayer.animate(new long[]{ 200, 200, 200 }, 9, 11, true); //LEFT
break;
case 3:
spritePlayer.animate(new long[]{ 200, 200, 200 }, 0, 2, true); //UP
break;
}
}


@Override
public void onPathWaypointFinished(final PathModifier pPathModifier, final IEntity pEntity, final int pWaypointIndex) {
Debug.d("onPathWaypointFinished: " + pWaypointIndex);
}


@Override
public void onPathFinished(final PathModifier pPathModifier, final IEntity pEntity) {
Debug.d("onPathFinished");
}
};
Path pathPlayer = new Path(5).to(50, 50).to(750, 50).to(750, 430).to(50, 430).to(50, 50);
spritePlayer.registerEntityModifier(new LoopEntityModifier(new PathModifier(12, pathPlayer, listener, EaseSineInOut.getInstance())));

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

خب یک نکته دیگه هم میتونم اینجا بهتون یاد بدم ، اون هم اینکه ، اندازه spritePlayer ما توی صفحه کمی کوچیک دیده میشه ، شاید فکر کنیم که میشه بهش Scale داد ولی این موضوع رو به روشی دیگه و ساده تر هم میشه انجام داد : دو خط زیر رو با هم مقایسه کنید پارامترهای ورودی متدهارو بخونید که چی هستند ، متوجه موضوع میشید : دیگه بیشتر توضیح نمیدم

//final AnimatedSprite spritePlayer = new AnimatedSprite(50, 50, playerRegion, getVertexBufferObjectManager());
final AnimatedSprite spritePlayer = new AnimatedSprite(50, 50, 48, 64, playerRegion, getVertexBufferObjectManager());

 بعد از تست خط بالا حتما متوجه شدید که این Sprite ما داره از نقطه 0 و 0 ترسیم میشه و کمی از صفحه بیرون میزنه و یا دقیقا روی نقاط تعریف شده حرکت نمیکنه ، خودتون باید مسیر های Path رو ویرایش کنید و به اندازه نصف ارتفاع و عرض Region تصمیم بگیرید

پاسخ به سوال 
Criss  8 سال پیش
+10 0

ساخت یک بک گراند تکرار شونده در بازی (ساخت زمینی پر از چمن)

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

برای یاد گیری این موضوع میتونید کلاس های زیر رو در AndEngineExamples پیدا کنید و سورس هارو نیگاه کنید پارامترهای ورودی متدهارو چک کنید و یاد بگیرید

PathModifierExample.java

RepeatingSpriteBackgroundExample.java

در نهایت باید بتونید خروجی زیر رو تولید کنید

 

+1 0
Criss جان ، گذری نگاهی به مطالب تاپیکت کردم ، مطالب جالبی رو بارگذاری و به اشتراک گذاشتی ، فعلا فکر نمی کنم به سمت بازی سازی حرکت کنم ، اما حیفم اومد برای چنین زحمتی تشکر نکنم ، موفق باشی. (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+9 0

ساخت یک بازی دیگر

قبل از اینکه وارد بحث فیزیک بشیم همین الان یه مورد به ذهنم رسید گفتم برای اینکه هم خودم بهتر یاد بگیرم و هم شما ، این رو هم تست کنم ،  قراره وقتی روی Scene کلیک میکنیم یک Sprite اضافه بشه و وقتی روی Sprite کلیک میکنیم از بازی حذف بشه ، من برم ببینم چ میکنم ، نتیجه رو اینجا میزارم

در حال کد زدن . . . ;

خب نتیجه حاصل شد : (دیگه سعی میکنم مسائل ساده رو توضیح ندم)

 public class TouchGameSpriteAdd extends BaseGameActivity implements IOnSceneTouchListener, IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Scene scene;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
scene = new Scene();
scene.setBackground(new Background(0.8f, 0.7f, 0.1f));
scene.setOnAreaTouchListener(this);
scene.setOnSceneTouchListener(this);

pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionDown()) {
AnimatedSprite sprite = (AnimatedSprite) pTouchArea;
scene.unregisterTouchArea(sprite);
scene.detachChild(sprite);
return true;
}
return false;
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionDown()) {
float x = pSceneTouchEvent.getX();
float y = pSceneTouchEvent.getY();
AnimatedSprite sprite = new AnimatedSprite(x - (regionSprite.getWidth() / 2), y - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(100);
scene.registerTouchArea(sprite);
scene.attachChild(sprite);
return true;
}
return false;
}
}

اگر قصد دارید موقع کلیک شدن روی Sprite ها صدا هم داشته باشید ، به پروژه AndEngineExamples برید و پروژه مربوط به تولید صدا رو پیدا کنید و خودتون قبل از اینکه اینجا آموزش بدیم ، یادش بگیرید

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

خودم قصد دارم موقع یاد گرفتن Phisycs و Velocity یه بازی بدم بازار (شایدم فقط بزارم اینجا) ، برم ببینم این Velocity چی هست

پاسخ به سوال 
Criss  8 سال پیش
+9 0

حرکت طبیعی اجسام استفاده از Physics و Velocity

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

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

این رو هم بگم که Velocity یعنی سرعت حدود 10 سال بعد دارم میفهمم چرا V توی فیزیک سرعت بود و چرا S یعنی speed برای سرعت نبود ! و یجای دیگه V ولت بود حالا volt (اختلاف پتانسیل) رو میشد فهمید به هرحال ولت با V شروع میشد ، ولی سرعت (speed) با S (به هر حال من از این نظام آموزشی متنفرم و علم واقعی رو باید از گوگل یاد گرفت ، مثل همین الان که جهت یاد آوری V دوم یعنی اختلاف پتانسیل از گوگل و ویکی کمک گرفتم )

خب ساده ترین روش ممکن برای اینکه یک جسم با سرعت ثابت حرکت کنه به شکل زیر هست :

 public class PhysicsSimpleVelocity extends BaseGameActivity implements IOnSceneTouchListener, IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Scene scene;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;
private AnimatedSprite sprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();

}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
scene = new Scene();
scene.setBackground(new Background(0.9f, 0.7f, 0.2f));

sprite = new AnimatedSprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

scene.attachChild(sprite);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
PhysicsHandler mPhysicsHandler;
mPhysicsHandler = new PhysicsHandler(sprite);
sprite.registerUpdateHandler(mPhysicsHandler);
mPhysicsHandler.setVelocity(100, 0);
//mPhysicsHandler.setAngularVelocity(50);

pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
// TODO Auto-generated method stub
return false;
}

باید بگم که اگر تا به اینجا تمام کد هارو در onCreateScene میزدیم شیوی درستی نبوده و من برای راحتی کار اینکارو میکردم و اینکه میخواستم ذهنتون اصلا طرف متد onPopulateScene نره و اینکه در زمان مشخصی بعد از اینکه از AndEngine به درک کافی رسیدید با استفاده از یک مثال مفهوم onPopulateScene رو بهتون بفهمونم .

تمام آپدیت ها و فعالیت های روی Scene بعد از اجرای  خط زیر معنی پیدا میکنه : که توی متد onPopulateScene هست

 pOnPopulateSceneCallback.onPopulateSceneFinished();

کافیه توی تمام مثال هایی که تا به الان داشتیم خط زیر رو بردارید میبینید که هیچکدوم از AnimatedSprite ها انیمیشن نمیشوند ، فکر کنم همین مثال کمک کرده باشه که به کاربرد onPopulateScene پی ببرید ، توی این کد بالا هم همچنان شما میتونستید کدهای استفاده شده رو در onCreateScene هم بکار ببرید ، به این خاطر که CallBack های این دو متد صدا زده شده هستند .

اگر ذهنتون با این مورد جدیدی که طرح کردم به چالش کشیده شده که کدهارو از کجا باید زد ؟ و با یک چیز جدید آشنا شدید که براتون عجیبه کافیه به این موضوع هم دقت کنید که از معنی اسم onCreateScene هم مشخصه که این متد فقط برای ساخت Scene (صحنه نمایش) هست و نه برای رندر کردن فعالیت های رو اون در واقع خط زیر که در onCreateScene صدا زده میشه اتمام کار رو به onPopulateScene خبر میده و این متد شروع به کار میکنه (تمام چیزی که راجب onPopulateScene  میدونستم رو با تمام صحیح و غلط و یا ناقص بودنش رو بهتون گفتم)

 pOnCreateSceneCallback.onCreateSceneFinished(scene);

حتما متوجه شدید که Sprite ما از اونور Scene میزنه بیرون ؟ بلاخره بحث فیزیک هست و همه چیز رو طبیعی میکنه وقتی شا به یک جسم قوانین فیزیک وارد میکنید باتوجه به شرایط پیش رو رفتار میکنه (برم ببینم چطور میتونم این مشکل رو حل نم و از توش یه آموزش در بیارم !)

 

ادامه در پست بعد <

+1 0
coooooooooooooooooooooooooooooooooooooooooooooooooooooooooooool......... (8 سال پیش)
+1 0
coooooooooooooooooooooooooooooooooooooooooooooooooooooooooooool......... (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+8 0

ادامه حرکت طبیعی اجسام استفاده از Physics و Velocity (رفع مشکل بیرون رفتن از Scene)

( آموزش این قسمت با توجه به اطلاعات ناقص داده میشه ! البته تمام آموزش هااز بالا تا اینجا با توجه به اطلاعات ناقص بود :D ولی خودم نسبت به این پست احساس خوبی ندارم )

این چیزی که در بالا دیدید با استفاده از سورس های موجود در کلاس MovingBallExample.java آموزش داده شده بود ، باید این رو بگم که حتی سورس های موجود در این کلاس هم با این که حرکت رو طبیعی تر کرده اما همچنان با استفاده از فیزیک میشه این حرکت رو طبیعی تر هم جلوه داد ، دلیل این حرفم اینه که برای مدیریت Sprite که از صفحه خارج نشه فقط سرعتی که به فیزیک داده شده رو به جهت عکس تبدیل میکنند و به Sprite وارد میکنند بنابر این Sprite موقع خروج از صفحه در جهت عکس حرکت میکنه ، در حالی که در حالت طبیعی باید یک جسم با توجه به وزن ، سرعت حرکت ، سطح اصطکاک و مهمتر از همه چه شکلی بودن Body که داره (شکل دایره ایی ، چهارگوش ، مثلثی ، بیضی ، خطی ، شش گوش و . . .) به یک سطح برخورد کنه و به توجه به قوانین فیزیک رفتار کنه

خب ، برای مدیریت کردن حرکت یک Sprite باید از onManagedUpdate استفاده کرد ، onManagedUpdate یک متد Override شده از زیر کلاس Entitiy هست (دقیقا نمیتونم Entity رو بهتون توضیح بدم اما AnimatedSprite یک Entity هست) اگر بیشتر دقت کرده باشید میبینید که متد زیر یک پارامتر Entitiy میگیره که ما بهش یک AnimatedSprite دادیم

 mPhysicsHandler = new PhysicsHandler(sprite);

زیر کلاس هایی از Entitiy ها به ما کمک میکنند که روی Sprite ها مدیریت داشته باشیم ، فرض کنید قرار باشه به یک Sprite مقدار Life رو 10 بدید ، خب این Sprite باید بعد از 10 ضربه بمیره و از بازی حذف بشه ، مدیریت تعداد Life های یک کارکاتر کار سختی هست ، اینجاست که باید از زیر کلاس های Entitiy ها استفاده کرد ، ظاهرا این زیر کلاس های دنیایی دارند که من هیچ اطلاعی ازشون ندارم

یک زیر کلاس به شکل زیر بسازید :

  private class mySprite extends AnimatedSprite {


}

میبینید که باید Constractor هارو اضاف کنید : بعد از اضافه شدن میبیند که این ورودی ها شبیه به ورودی هایی هست که یک AnimateSprite میساختید ، خب بخاطر این هست که این کلاس از AnimatedSprite مشتق شده دیگه ! :D

  private class mySprite extends AnimatedSprite {

public mySprite(float pX, float pY, ITiledTextureRegion pTiledTextureRegion, VertexBufferObjectManager vertexBufferObjectManager) {
super(pX, pY, pTiledTextureRegion, vertexBufferObjectManager);
// TODO Auto-generated constructor stub
}

}

حالا متد onManagedUpdate رو Override کنید :

 private class mySprite extends AnimatedSprite {

public mySprite(float pX, float pY, ITiledTextureRegion pTiledTextureRegion, VertexBufferObjectManager vertexBufferObjectManager) {
super(pX, pY, pTiledTextureRegion, vertexBufferObjectManager);
// TODO Auto-generated constructor stub
}


@Override
protected void onManagedUpdate(float pSecondsElapsed) {
// TODO Auto-generated method stub
super.onManagedUpdate(pSecondsElapsed);
}
}

قبل از این یک AnimatedSprite رو به شکل زیر میساختید :

 sprite = new AnimatedSprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());

یعنی یک شی جدید از AnimatedSprite میساختید ، باز هم قراره یک شی از AnimatedSprite ساخته بشه اما اینبار از mySprite  ساخته میشه (امیدارم قضیه رو گرفته باشید)

قضیه این هست که برای مدیریت یک Sprite روی Scene یک new AnimatedSprite ساده و خشک و خالی نمیتونه به ما کمک کنه ،  برای این چنین قابلیت هایی ما باید از زیر کلاس های ما باید خودمون یک کلاس از AnimatedSprite رو بسازیم و اون رو کامل تر از new AnimatedSprite قرار بدیم که بشه ازش قابلیت های بیشتری استفاده کرد و اینجاست که میشه Sprite روی Scene رو مدیریت کرد و قبالیت های بیشتری رو داشت

 خب در ادامه خط زیر رو به این شکل ویرایش میکنیم : (خودم برم یه F5 بزنم ببینم این همه که حرف زدم درست گفتم یا نه ! ، یعنی اطلاعاتی که در اختیارتون میزارم در همین حد اعتبار داره :D)

//sprite = new AnimatedSprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite = new mySprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());

در کمال تعجب درست داره کار میکنه :D

https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQA058UQfXqXbJYV-NkMEg0MlOpnrNYs1YbbDX0nVjbyVLl5Y45

ادامه در پست بعد <

 

0 0
انجمن هم باگ داره ها ، نصف آموزش های بالا نیست ! یادمم نمیاد چی گفته بودم ! (8 سال پیش)
پاسخ به سوال 
Criss  8 سال پیش
+8 0

ادامه ! ادامه حرکت طبیعی اجسام استفاده از Physics و Velocity ( پایان رفع مشکل بیرون رفتن از Scene)

خب تا به اینجای کار کد ما به شکل زیر شد و کمی هم تغییر کرد  :

تغییرات : رنگ بک گراند عوض شد + قوانین فیزیک رفت یجایی دیگه استفاده شد با توجه به شرایط هم ورودی خودش رو گرفت < همچنین private AnimatedSprite     sprite دیگه لازم نیست fild باشه

 public class PhysicsSimpleVelocity extends BaseGameActivity implements IOnSceneTouchListener, IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Scene scene;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();

}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
scene = new Scene();
scene.setBackground(new Background(0.3f, 0.3f, 0.1f));

//sprite = new AnimatedSprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
mySprite sprite = new mySprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

scene.attachChild(sprite);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
// TODO Auto-generated method stub
return false;
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
// TODO Auto-generated method stub
return false;
}


private class mySprite extends AnimatedSprite {

public mySprite(float pX, float pY, ITiledTextureRegion pTiledTextureRegion, VertexBufferObjectManager vertexBufferObjectManager) {
super(pX, pY, pTiledTextureRegion, vertexBufferObjectManager);

mPhysicsHandler = new PhysicsHandler(this);
this.registerUpdateHandler(mPhysicsHandler);
mPhysicsHandler.setVelocity(100, 100);
//mPhysicsHandler.setAngularVelocity(50);
}


@Override
protected void onManagedUpdate(float pSecondsElapsed) {
// TODO Auto-generated method stub
super.onManagedUpdate(pSecondsElapsed);
}
}
}

 خب بریم بررسی کنیم onManagedUpdate چی هست و چیا داره ! (من برم کد بزنم برگردم . . .)

خب چیزی متوجه نشدم ، کد های کلاس MovingBallExample.java رو کپی کردم که مشخصه داره چیکار میکنه :

  @Override
protected void onManagedUpdate(float pSecondsElapsed) {
float mySpriteX = mX;
float mySpriteY = mY;
if (mySpriteX < 0) {
this.mPhysicsHandler.setVelocityX(100);
} else if (mySpriteX + this.getWidth() > WIDTH) {
this.mPhysicsHandler.setVelocityX( -100);
}

if (mySpriteY < 0) {
this.mPhysicsHandler.setVelocityY(100);
} else if (this.mY + this.getHeight() > HEIGHT) {
this.mPhysicsHandler.setVelocityY( -100);
}
super.onManagedUpdate(pSecondsElapsed);
}

در آخر هم احساس میکنم شاید از خط زیر چیزی متوجه نشده باشید

 mPhysicsHandler.setAngularVelocity(50);

خب این باعث میشه یک جسم چرخش داشته باشه ، کاربردش چی هست ؟ درواقع برخورد یک جسم به در و دیوار توی حالتی که داره دور خودش میچرخه با حالتی که مستقیم با کله داره به سمت دیوار میره فرق داره ، که اینجا فرقش برای ما مشخص نیست چون از فیزیک بصورت کامل استفاده نکردیم !

در حال ویرایش . . .

پاسخ به سوال 
Criss  8 سال پیش
+9 0

ساخت یک بازی با استفاده از آموزش های قبلی

کلیک کنید روی صفحه Sprite ها شروع میکنند که حرکت کردن ، روی خود Sprite ها بزنید از صفحه روزگار حذف میشوند ! اشتباه کنید کارتون اضاف میشه

 public class PhysicsVelocity extends BaseGameActivity implements IOnSceneTouchListener, IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Scene scene;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();

}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
scene = new Scene();
scene.setBackground(new Background(0.3f, 0.3f, 0.1f));
scene.setOnAreaTouchListener(this);
scene.setOnSceneTouchListener(this);

//sprite = new AnimatedSprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
mySprite sprite = new mySprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

scene.attachChild(sprite);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionDown()) {
AnimatedSprite sprite = (AnimatedSprite) pTouchArea;
scene.unregisterTouchArea(sprite);
scene.detachChild(sprite);
return true;
}
return false;
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionDown()) {
float x = pSceneTouchEvent.getX();
float y = pSceneTouchEvent.getY();
mySprite sprite = new mySprite(x - (regionSprite.getWidth() / 2), y - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(100);
scene.registerTouchArea(sprite);
scene.attachChild(sprite);
return true;
}
return false;
}


private class mySprite extends AnimatedSprite {

PhysicsHandler mPhysicsHandler;


public mySprite(float pX, float pY, ITiledTextureRegion pTiledTextureRegion, VertexBufferObjectManager vertexBufferObjectManager) {
super(pX, pY, pTiledTextureRegion, vertexBufferObjectManager);

mPhysicsHandler = new PhysicsHandler(this);
this.registerUpdateHandler(mPhysicsHandler);
mPhysicsHandler.setVelocity(100, 100);
//mPhysicsHandler.setAngularVelocity(50);
}


@Override
protected void onManagedUpdate(float pSecondsElapsed) {
float mySpriteX = mX;
float mySpriteY = mY;
if (mySpriteX < 0) {
this.mPhysicsHandler.setVelocityX(100);
} else if (mySpriteX + this.getWidth() > WIDTH) {
this.mPhysicsHandler.setVelocityX( -100);
}

if (mySpriteY < 0) {
this.mPhysicsHandler.setVelocityY(100);
} else if (this.mY + this.getHeight() > HEIGHT) {
this.mPhysicsHandler.setVelocityY( -100);
}
super.onManagedUpdate(pSecondsElapsed);
}
}
}

ایندفعه که دیگه واغعا این تصویر زیر جا داره استفاده بشه :D :)) ، عجب چیزی ساخته شد تا اینجا :D

https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQA058UQfXqXbJYV-NkMEg0MlOpnrNYs1YbbDX0nVjbyVLl5Y45

همین جا اعلام میکنم هرگونه کپی برداری از ایده بالا نامردیه :D ولی شما راحت باشید ( بالاتر که گفته بودم قراره بازی بدم ) با همین میشه یه بازی با 150 تا مرحله ساخت بازار که هیچی گوگل پلی هم میشه داد ، فوقالعاده هم اعتیاد آور می باشد :D ، فقط یه باگ کوچیک داره که میشه تو بازی تقلب کرد :D

پاسخ به سوال 
Criss  8 سال پیش
+8 0

آموزش های کاربردی

*** آموزش مهم ***

( استفاده کاربردی از Camera ! )

پیدا کردن متد جدید <

زیر سوال رفتن آموزش قبلی :D

مگه میشه Camera که همیشه اون بالا تعریف میشد و هیچ کار هم باهاش نداشتیم ! ، خب عاره همین الان یه چیز جدید ازش یاد گرفتم که چیز خوبیه یه آموزش داشتیم بالاتر به اسم حرکت طبیعی اجسام استفاده از Physics و Velocity ، اونجا گفتیم که ساده ترین روش ممکن برای اینکه یک جسم با سرعت ثابت حرکت کنه به شکل زیر هست : ( با همون سورس کار مکنیم )

 برم ببینم این چیزی که میگ جواب میده یا نه ! جواب داد پست رو ادامه میدم ، جواب نداد پست رو ویرایش میکنم یه طور دیگه این قابلیت رو توضیح میدم :D (فک کنم توانایی این رو پیدا کردم که یک چیز اشتباه رو به صحیح ترین شکل ممکن به شما توضیح بدم و شما هم قبولش کنید دیگه :D چون خروجی کدش صحیح کار میکنه :)) ، یادش بخیر یه زمانی  Emoji های یاهو معروف بود )

خب ظاهرا نتیجه داره حاصل میشه ، باید بگم که اون آموزشی که اولش گفته بودم اطلاعات ناقص هست ، اینجا ثابت میشه که واقعا اطلاعات ناقص بود ولی شیوه کار بالا کاملا صحیح بود دیگه خدارو شکر تا خوردم اعتراف نکنم شما هم چیزی متوجه نمیشید :)) ، یه جای دیگه هم عین جمله زیر گفته بودم که انتظار داشتم چیزی رو پیدا کنم که بشه ازش توی متد onCreateScene یا توی onPopulateScene ازش استفاده کرد که الان اون چیزی که میخواستم رو پیدا کردم :D

 خب بریم بررسی کنیم onManagedUpdate چی هست و چیا داره ! (من برم کد بزنم برگردم . . .)

خب چیزی متوجه نشدم ، کد های کلاس MovingBallExample.java رو کپی کردم که مشخصه داره چیکار میکنه :

خب بریم ببینیم چی پیدا کردم ^_^ ، متد زیر رو پیدا کردم :D

 scene.registerUpdateHandler(new IUpdateHandler() {

@Override
public void reset() {
// TODO Auto-generated method stub

}


@Override
public void onUpdate(float pSecondsElapsed) {
Log.i("X", "" + sprite.getX());
}
});

همونطور که میبینید یه Log هم وسط متد هست که همون تمام فعالیت های خیر خواهانه مارو زیر سوال برد ، متد جدید این بالایی بود

قابلیت کاربردی هم که از Camera پیدا کردیم بصورت زیر هست :

 camera.isRectangularShapeVisible(pRectangularShape)

خب اون کدی که بالا داشتیم و قبلا آموزش داده بودیم به شکل زیر تغییر میکنه :

 public class PhysicsSimpleVelocity extends BaseGameActivity implements IOnSceneTouchListener, IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Scene scene;
private Camera camera;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;
private AnimatedSprite sprite;


@Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();

}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
scene = new Scene();
scene.setBackground(new Background(0.9f, 0.7f, 0.2f));

sprite = new AnimatedSprite(50 - (regionSprite.getWidth() / 2), 240 - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

scene.attachChild(sprite);

scene.registerUpdateHandler(new IUpdateHandler() {

@Override
public void reset() {
// TODO Auto-generated method stub

}


@Override
public void onUpdate(float pSecondsElapsed) {
Log.i("X", "" + sprite.getX());
if ( !camera.isRectangularShapeVisible(sprite)) {
scene.setBackground(new Background(0.9f, 0.0f, 0.2f));
}
}
});
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
PhysicsHandler mPhysicsHandler;
mPhysicsHandler = new PhysicsHandler(sprite);
sprite.registerUpdateHandler(mPhysicsHandler);
mPhysicsHandler.setVelocity(100, 0);
mPhysicsHandler.setAngularVelocity(50);
// TODO Auto-generated method stub
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
// TODO Auto-generated method stub
return false;
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
// TODO Auto-generated method stub
return false;
}
}

خب دیگه چون آموزش ها فی البداهه هست این چیزها هم داره دیگه ، من یه چیزی میگم باید کدش هم زده بشه بعدا میریم جلوتر میبینیم پیوستگی آموزش ها حفظ نشده ، خب تا اینجا خیلی از آموزش هارو از قبل بلد بودم میشد پیوسته وار گذاشت پست سر هم ، ولی از اینجا به بعد دیگه کلا هرچی یاد میگیرم جدید هست ، مجبورا بزاریم اینجا که امکان داره به موضوعات قبلی ربطی نداشته باشه !

 

در حال کد زدن . . .

پاسخ به سوال 
Criss  8 سال پیش
+9 0

 آموزش جدید (تشخیص Touch روی Sprite)

 توی این روش نیازی به استفاده از Interface ها نیست و Override کردن متد جدید نیست :

همچنین توی این متد یاد میگیرد چطور یک Toast رو نمایش بدید ، یک روش جدید نمایش animate هم رو میبینید که انتظار دارم این رو خودتون از قبل بلد باشید

   AnimatedSprite spritebanana = new AnimatedSprite(100, 100, regionBanana, getVertexBufferObjectManager()) {

@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float X, float Y) {
if (pSceneTouchEvent.isActionUp()) {
this.animate(100, false);
runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(getApplicationContext(), "Banana", Toast.LENGTH_SHORT).show();

}
});
}
return true;
};
};

scene.registerTouchArea(spritebanana);
scene.attachChild(spritebanana);

کد هارو به آموزش قبلی مربوط به تشخیص TOUCH روی Sprite اضاف  کنید ؛ در کل کار به شکل زیر میشه :

 public class TouchArea extends BaseGameActivity implements IOnAreaTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

TiledTextureRegion faceRegion;
TiledTextureRegion regionBanana;
BitmapTextureAtlas atlas;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");
atlas = new BitmapTextureAtlas(getTextureManager(), 256, 256);
faceRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
regionBanana = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "banana_tiled.png", 32, 32, 4, 2);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.6f, 0.8f, 0.2f));
scene.setOnAreaTouchListener(this);

AnimatedSprite faceSprite = new AnimatedSprite((WIDTH / 2) - (faceRegion.getWidth() / 2), (HEIGHT / 2) - (faceRegion.getHeight() / 2), faceRegion, getVertexBufferObjectManager());
faceSprite.animate(100);

scene.attachChild(faceSprite);
scene.registerTouchArea(faceSprite);

AnimatedSprite spritebanana = new AnimatedSprite(100, 100, regionBanana, getVertexBufferObjectManager()) {

@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float X, float Y) {
if (pSceneTouchEvent.isActionUp()) {
this.animate(100, false);
runOnUiThread(new Runnable() {

@Override
public void run() {
Toast.makeText(getApplicationContext(), "Banana", Toast.LENGTH_SHORT).show();

}
});
}
return true;
};
};

scene.registerTouchArea(spritebanana);
scene.attachChild(spritebanana);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
Log.i("TouchArea", "New Event On Sprite");
return false;
}
}

 

پاسخ به سوال 
Criss  8 سال پیش
+8 0

اصلاح و توضیحات صحیحتر از آموزش های قبلی

 درواقع اصلاح نیست ، آموزش های قبلی کاملا درست بود اما با چیزهایی که تا قبل از این توضیح دادم ظاهرا شما فکر میکنید برای حذف کردن یک Sprite کد های زیر کافی باشه

scene.unregisterTouchArea(sprite);
scene.detachChild(sprite);

در حالی که در واقعیت کدهای زیر صحیح هستند و یک Entity به روش زیر کاملا حذف میشه :

scene.unregisterTouchArea(sprite);
scene.detachChild(sprite);
sprite.detachSelf();
sprite.dispose();

 

پاسخ به سوال 
Criss  8 سال پیش
+8 0

ساخت یک بازی ( دشمن هوشمند )

قبل از آموزش دادن بخش جدید ، به ذهنم رسید که میشه با توجه به چیزهایی که تا به الان یاد گرفتیم یک نمونه دشمن هوشمند بسازیم : کار این کارکاتر دشمن ، این هست که کاراکتر اصلی مارو تعقیب میکنه و هرجا که اون باشه دنبالش میره

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

 public class FollowSprite extends BaseGameActivity implements IOnSceneTouchListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;
private AnimatedSprite sprite;
private Rectangle fallowRect;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.7f, 0.9f, 0.1f));
scene.setOnSceneTouchListener(this);

sprite = new AnimatedSprite(50, (HEIGHT / 2) - (regionSprite.getHeight() / 2), regionSprite, getVertexBufferObjectManager());
sprite.animate(150);
fallowRect = new Rectangle(750, (HEIGHT / 2) - 8, 16, 16, getVertexBufferObjectManager());
fallowRect.setColor(Color.RED);

scene.attachChild(sprite);
scene.attachChild(fallowRect);

scene.registerUpdateHandler(new IUpdateHandler() {

@Override
public void reset() {}


@Override
public void onUpdate(float pSecondsElapsed) {
MoveModifier moveModifer = new MoveModifier(1, fallowRect.getX(), sprite.getX() + 8, fallowRect.getY(), sprite.getY() + 8);
fallowRect.registerEntityModifier(moveModifer);
}
});
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionDown()) {
MoveModifier moveModifer = new MoveModifier(2, sprite.getX(), pSceneTouchEvent.getX() - 16, sprite.getY(), pSceneTouchEvent.getY() - 16);
moveModifer.setAutoUnregisterWhenFinished(true);
sprite.registerEntityModifier(moveModifer);
}
return false;
}
}

تنها نکته جدید توی کد های بالا Rectangle هست که اگر اولین آموزش ها رو دیده باشید ، در اونجا یاد گرفته بودید که چطور یک Line رو رسم کنید < این هم رسم یگ Rectangle (چهارگوش) هست ، اگر دارید فکر میکنید که چرا به atlas اضافه نشده و . . .  ، باید بگم که این یک Rectangle هست و یک تصویر ثابت و یا یک تصویر متحرک نیست ! پس آموزشهارو قاطی نکنید :D ، مستقیم میشه به Scene اضاف کرد و باهاش رفتار کرد .توی آموزش بعد از ساخت Rectangle چندین بار از عدد 8 و 16 استفاده شده که بهتره ارتفاع و عرض Sprite رو بگیریم و تقسیم کنیم که مرکز رو بدست بیاریم

من قصد دارم کمی دشمنون رو هوشمند کنم ، و همچنین از فیزیک بجای MoveModifire برای حرکت تعیین کنم ، و تعیین کنم که اگر فاصله بین کاراکتر اصلی بازی و این دشمن از یک فاصله کمتر شد تعقیب صورت بگیره و اگر ما موفق شدیم  فاصلمون رو بیشتر کنیم دشمن کاراکتر رو گم کنه و تعقیب رو ادامه نده !

 

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

 

ادامه در دپست بعد

پاسخ به سوال 
Criss  8 سال پیش
+8 0

ساخت دشمن هوشمند - استفاده از فیزیک

خب در این بخش همون سناریوی بالارو پیاده میکنیم ، فقط بجای استفاده از Modifier از Physics استفاده میکنیم و هنوز اون قسمت جالب تعقیب و گریز رو ننوشتیم !  هوشمندتر شدن رو ننوشتیم

چالشی که پیش رو داریم این هست که در فیزیک ما فعلا فقط میتونیم سرعت ست کنیم و بگیم که در جهت X , Y با چه سرعتی حرکت کنه باید دقت کنید که در اینجا که از فیزیک استفاده میکنیم سرعت متر بر ثانیه (m/s) هست ، مشکل ما از اونجا هستش که چطور با توجه به این تعیین کنیم که Sprite ما از یک نقطه به یک نقطه دلخواه حرکت کنه ، نقطه دلخواه نقطه ایی هست که روی Scene کلیک میکنیم ، احتمالا استفاده از رابطه فیثاغورث به ما کمک میکنه

خب از رابطه فیثافورث هم نتونستم کمک بگیرم  ، هنوز هیچ کدوم از این چیزهایی که گفتم رو نمیشه با استفاده از Physics راه انداخت کار خیلی پیچیده میشه و نیاز به کد نویسی های زیاد و خشک داره که فقط روی دوتا کارکاتر ست میشه ! و در آینده به هیچ درد ما نمیخوره !

شاید این لینک ها به ما کمک کنه :

__1

__2

این پروژه رو میزاریم برای آینده . . .

قسمت دوم هوشمندی هم که قرار بود بنویسیم باید فاصله بین دو کاراکتر رو به دست میاوردیم ، در حالت عادی مقدار X,Y رو محاسبه میکردیم اما در حالت واقعی و صحیح باید شعاعی رو از مرکز کاراکتر در نظر بگیریم ، البته روش های دیگه ایی هم وجود داره !

ساخت دشمن هوشمند در همینجا شکست خورد ، به دلیل اینکه هنوز به دانسته های بیشتری نیاز داریم

نمونه این دشمن هوشمند که قرار بود بسازیم رو میتونید در بازی AttackWave که با  AndEngine ساخته شده در GoolePlay ببینید

 

پاسخ به سوال 
Criss  8 سال پیش
+9 0

تشخیص برخورد دو جسم به یک دیگر

collisions (برخورد ، تصادف ، تلاقی)

نیاز به توضیح نداره ، چیز ساده ایی هست : خروجی این متد boolean هست

 if (sprite1.collidesWith(sprite2)) {

}

 

 public class Collision extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");
atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();
pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
final Scene scene = new Scene();
scene.setBackground(new Background(0.2f, 0.4f, 0.1f));
float centerX = (WIDTH / 2) - (regionSprite.getWidth() / 2);
float centerY = (HEIGHT / 2) - (regionSprite.getWidth() / 2);
final AnimatedSprite sprite1 = new AnimatedSprite(centerX - 250, centerY, regionSprite, getVertexBufferObjectManager());
final AnimatedSprite sprite2 = new AnimatedSprite(centerX + 250, centerY, regionSprite, getVertexBufferObjectManager());
scene.attachChild(sprite1);
scene.attachChild(sprite2);
Path path1 = new Path(3).to(centerX - 250, centerY).to(centerX + 250, centerY).to(centerX - 250, centerY);
Path path2 = new Path(3).to(centerX + 250, centerY).to(centerX - 250, centerY).to(centerX + 250, centerY);
sprite1.registerEntityModifier(new LoopEntityModifier(new PathModifier(2, path1, EaseBackIn.getInstance())));
sprite2.registerEntityModifier(new LoopEntityModifier(new PathModifier(2, path2, EaseBackIn.getInstance())));
scene.registerUpdateHandler(new IUpdateHandler() {

@Override
public void reset() {}

boolean bool = true;


@Override
public void onUpdate(float pSecondsElapsed) {
if (sprite1.collidesWith(sprite2)) {
if (bool) {
bool = false;
scene.setBackground(new Background(0.4f, 0.2f, 0.1f));
} else {
bool = true;
scene.setBackground(new Background(0.2f, 0.4f, 0.1f));
}
}
}
});
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

 

پاسخ به سوال 
Criss  8 سال پیش
+8 0

Touch & Drag
توی این آموزش یاد گرفتیم که نیازی به استفاده از این دو دیگه نیست و روی Scene اینهارو پیاده میکنیم :
 implementsIOnSceneTouchListener,IOnAreaTouchListener
کد به شرح زیر :
public class TouchAndDrag extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("res/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.6f, 0.8f, 0.1f));

scene.setOnSceneTouchListener(new IOnSceneTouchListener() {

@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionUp()) {
AnimatedSprite sprite = new AnimatedSprite(pSceneTouchEvent.getX() - (regionSprite.getWidth() / 2), pSceneTouchEvent.getY() - (regionSprite.getHeight() / 2), regionSprite,
getVertexBufferObjectManager());
sprite.animate(150);
pScene.registerTouchArea(sprite);
pScene.attachChild(sprite);
return true;
}
return false;
}
});
scene.setOnAreaTouchListener(new IOnAreaTouchListener() {

@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionMove()) {
AnimatedSprite sprite = (AnimatedSprite) pTouchArea;
sprite.setPosition(pSceneTouchEvent.getX() - (regionSprite.getWidth() / 2), pSceneTouchEvent.getY() - (regionSprite.getHeight() / 2));
return true;
}
return false;
}
});
scene.setTouchAreaBindingOnActionDownEnabled(true);
scene.setTouchAreaBindingOnActionMoveEnabled(true);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}
 چقدر خوب شد که setPosition آشنا شدیم
برای فهم متدهای زیر پیشنهاد میکنم اونهارو کامنت کنید و بازی رو تست کنید :
scene.setTouchAreaBindingOnActionDownEnabled(true);
scene.setTouchAreaBindingOnActionMoveEnabled(true);
 هیچ چیز جدید دیگه ایی وجود نداره!
 متاسفانه بعد از اینکه Sptire رو Drag میکنیم ActionUp روی Scene انجام میشه و یک Sprite روی این Sprite قبلی اضاف میشه ! خب اگر وسط بازی بودیم این رو باید boolean ، تعداد سکه و هرچیز دیگه ایی مدیریت میکردیم
 
پاسخ به سوال 
Criss  8 سال پیش
+7 0

استفاده از AnalogOnScreenControl جهت حرکت دادن Sprite

کد :

 public class Analog extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Camera camera;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;

private ITextureRegion regionAnalogBase;
private ITextureRegion regionAnalogKnob;


@Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 260, 260, TextureOptions.BILINEAR);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);

regionAnalogBase = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_base.png", 33, 33);
regionAnalogKnob = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_knob.png", 162, 162);

atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.5f, 0.6f, 0.1f));

final AnimatedSprite sprite = new AnimatedSprite(250, 0, regionSprite, getVertexBufferObjectManager());
sprite.animate(150);
final PhysicsHandler physicsHandler = new PhysicsHandler(sprite);
sprite.registerUpdateHandler(physicsHandler);

AnalogOnScreenControl alanogLeft = new AnalogOnScreenControl(0, HEIGHT - regionAnalogBase.getHeight(), camera,
regionAnalogBase, regionAnalogKnob, 0.1f, 200, this.getVertexBufferObjectManager(),
new IAnalogOnScreenControlListener() {

@Override
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
physicsHandler.setVelocity(pValueX * 100, pValueY * 100);
}


@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
sprite.registerEntityModifier(new SequenceEntityModifier(new ScaleModifier(0.25f, 1, 1.5f), new ScaleModifier(0.25f, 1.5f, 1)));
}
});
alanogLeft.getControlBase().setAlpha(0.2f);
alanogLeft.getControlKnob().setAlpha(0.2f);
alanogLeft.getControlBase().setScaleCenter(0, 128);
alanogLeft.refreshControlKnobPosition();

scene.setChildScene(alanogLeft);

scene.attachChild(sprite);
scene.attachChild(alanogLeft);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

توضیحات :

تعریف AnalogOnScreenControl به لیستنر هم نیاز داره ، همون لحظه تعریف باید براش لیستنر تعریف کنید که این لیستنر دارای دو متد onControlChange و onControlClick هست اولی برای زمانی که اهرم رو حرکت میدیم و دومی برای زمانی که روی اهرم کلیک میکنیم

alanogLeft.getControlBase().setAlpha(0.2f);
alanogLeft.getControlKnob().setAlpha(0.2f);
alanogLeft.getControlBase().setScaleCenter(0, 128);
alanogLeft.refreshControlKnobPosition();

در مورد خطوط بالا ، خط اول و دوم شفافیت رو تنظیم میکنیم ، هرچی شفاف تر بهتر ، خط سوم مرکز و وسط اهرم رو مشخص میکنیم ، کاربردش رو نمیدونم ! ، خط آخر که از همه مهمتر هست کار رفرش رو انجام میده یعنی زمانی که شما دستتون رو از روی اهرم برمیدارید این دسته اهرم به جای اولش بر میگرده

برای دیدن نمونه هایی دیگه از بکارگیری اهرم میتونید کلاس های زیر رو ببینید : مخصوصا AnalogOnScreenControlsExample که یک نمونه استفاده کاربردی رو به شما نشون میده که میتونید مختصات اهرم رو به درجه تبدیل کنید و استفاده کاربردی اون در اینجا میشه setRotate روی sprite ولی استفاده کاربردی واقعی از تبدیل مقادیر به درجه رو میتونید در RacerGameActivity ببینید

AnalogOnScreenControlExample

AnalogOnScreenControlsExample

RacerGameActivity

 

 

پاسخ به سوال 
Criss  8 سال پیش
+6 0

استفاده از فیزیک واقعی

گرانش ، جرم ، چگالی ، اصطکاک ، سرعت ،  اجسام dynamic  , اجسام static ، نوع Body و خیلی چیزهای دیگه ایی که هنوز بلد نیستیم

آاشنایی با مفاهیم جدید : FixtureDef و Body و FixedStepPhysicsWorld و Vector2 و PhysicsWorld

 PhysicsWorld یک نمونه ساده از FixedStepPhysicsWorld هست که در ادامه ازش استفاده نمیکنیم و FixedStepPhysicsWorld همیشه کار مارو راه میندازه

FixedStepPhysicsWorld  همون PhysicsWorld هست با این تفاوت که بهینه هست و میشه تعیین کرد هر گام از اجرای فیزیک رو در چند گام نمایش بده ، درواقع کمک میکنه که منابع سخت افزاری کمتری مصرف بشه ، همونطور که میدونید حداقل 33 فریم بر ثانیه مقدار مناسبی هست برای اینکه کاربر رضایت داشته باشه ، پس ما همیشه مقدار PhysicsStep رو روی 60 قرار میدیم این کمک میکنه که در هر ثانیه فقط 60 مختصات محاسبه شده و استفاده بشه در حالی که شاید در حالت عادی 300 بار نمایش بکار برده میشد و این باعث هدر رفتن منابع و استفاده بی مورد از CPU میشه ، (دیگه از این بهتر نمیتونستم توضیح بدم ، اطلاعات دقیقی ندارم و با اینکه ممکنه بعضی چیزهارو اشتباه و غلط گفته باشم ولی امیدوارم مفهوم رو به شما رسونده باشم)

Vector2  یک مختصات دو بعدی هست در ساخت گرانش کمک میکنه و با استفاده از مختصات X , Y که میگیره مشخص میشه از کدوم طرف باید گرانش اعمال بشه زمانی که از سنسور های گوشی استفاده میکنیم ، میتونیم با چرخش گوشی و تغییر سنسور ها جهت گرانش تغییر کنه

Body  خیلی مهمه فرض کنید که شما یک در بازی یک سطح با شیب دلخواه دارید در واقعیت قرار گرفتن یک جسم دایره و قرار گرفتن یک جسم چهار گوش روی این سطح شیب دار رفتار های متفاوتی از خودش نشون میده ، در AndEngine هم به همین صورت هست شما اگر دو جسم دایره و چهار گوش روی یک سطح شیب دار داشته باشید جسم دایره به سمت پایین حرکت میکنه ، Body میتونه توی برخورد کردن دو جسم به هم و خیلی چیزهای دیگه تعیین کننه باشه ، در مورد Body باید گم که در AndEngine کاملا دست شما باز هست و شما میتونید هر Body رو بسازید حتی Body به شکل T , W

طبق آموزش های اقای رمضان زاده سه نوع Body داریم :

 انواع Body :

سه نوع Body در AndEngine داریم که عبارتند از BodyType.DynamicBody و BodyType.StaticBody و BodyType.KinematicBody .

BodyType.DynamicBody : این نوع اجسام در مقابل نیروها  (جاذبه و غیره) و اشیای دیگر واکنش نشان میدهند.

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

BodyType.KinematicBody : این نوع اجسام در مقابل سایر اجسام و نیرو ها واکنش نشان نمی دهند ولی می توانند دارای حرکت باشند.

FixtureDef  نقش مهمی داره برای استفاده از فیزیک واقعی هر جسم باید حداقل یک Body داشه باشه که Body به وسیله  FixtureDef ساخته میشه ، FixtureDef تعیین میکنه که یک جسم خاصیت های چگالی ، الاستیکی و اصطکاک رو به چه صورت در بر داشته باشه

اجسام dynamic  , اجسام static  برای ساخت یک جسم static مثل دیوار باید نوع خاصی از Body و همچنین خاصیت های FixtrueDef رو که برای اجسامی مثل دیوار تعریف میکنیم آنچنان کاربردی نداره ، چون یک دیوار که همیشه ثابت هست چه فرقی میکنه که جرمش چقدر باشه ! ، برای ساخت یک جسم Dynamic و متحرک که روی Scene حرکت میکنه و جاذبه روی اون تاثیر میذاره قضیه متفاوت هست

 

در آخر برای آشنایی بهتر با این مفاهیم بهتره این آموزش رو مطالعه کنید

 

پاسخ به سوال 
Criss  8 سال پیش
+7 0

قدم اول ساخت ظاهر و دیوار در چهار طرف بازی

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

 کد :

 public class PhysicsBodys extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.4f, 0.5f, 0.1f));
int CenterX = WIDTH / 2;
int CenterY = HEIGHT / 2;
AnimatedSprite sprite = new AnimatedSprite(CenterX - regionSprite.getWidth() / 2, CenterY - regionSprite.getHeight() / 2, regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

Rectangle ground = new Rectangle(0, HEIGHT - 6, WIDTH, 6, getVertexBufferObjectManager());
ground.setColor(Color.RED);
Rectangle left = new Rectangle(0, 0, 6, HEIGHT - 6, getVertexBufferObjectManager());
left.setColor(Color.BLUE);
Rectangle roof = new Rectangle(6, 0, WIDTH, 6, getVertexBufferObjectManager());
roof.setColor(Color.GREEN);
Rectangle right = new Rectangle(WIDTH - 6, 6, 6, HEIGHT - 12, getVertexBufferObjectManager());
right.setColor(Color.YELLOW);

scene.attachChild(sprite);
scene.attachChild(ground);
scene.attachChild(left);
scene.attachChild(roof);
scene.attachChild(right);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

همه ی کدهای بالا رو بلد هستید

در این شرایط اگر جاذبه زمین رو بسازیم ، هیچ چیزی رو هس نمیکنیم چه هیچ کدوم از اشیا ما در بازی خاصیت های فیزیکی براشون تعریف نشده و نسبت به قوانین فیزیک بی معنی هستند ، در این شرایط اگر به sprite شرایط فیزیکی (جرم و . . .) ست کنیم  و جاذبه زمین رو شبیه سازی کنیم Sprite از روی دیوار های چهار گوشه بازی رد میشه ، و به اونها برخورد نمیکنه چون تنها فیزیک رو برای Sprite تعریف کردیم و برای اونها نه ! اگر هم فیزیک رو فقط یه دیوار ها بدیم هیچ چیزی رو حس نمیکنیم ، چون چیزی نیست که جاذبه روش تاثیر بزاره و در ظاهر پیدا باشه

پاسخ به سوال 
Criss  8 سال پیش
+7 0

قدم دوم ساخت جاذبه و ساخت Body به واسطه FixtureDef

 public class PhysicsBodys extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.4f, 0.5f, 0.1f));
int CenterX = WIDTH / 2;
int CenterY = HEIGHT / 2;

AnimatedSprite sprite = new AnimatedSprite(CenterX - regionSprite.getWidth() / 2, CenterY - regionSprite.getHeight() / 2, regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

Rectangle ground = new Rectangle(0, HEIGHT - 6, WIDTH, 6, getVertexBufferObjectManager());
ground.setColor(Color.RED);
Rectangle left = new Rectangle(0, 0, 6, HEIGHT - 6, getVertexBufferObjectManager());
left.setColor(Color.BLUE);
Rectangle roof = new Rectangle(6, 0, WIDTH, 6, getVertexBufferObjectManager());
roof.setColor(Color.GREEN);
Rectangle right = new Rectangle(WIDTH - 6, 6, 6, HEIGHT - 12, getVertexBufferObjectManager());
right.setColor(Color.YELLOW);

FixedStepPhysicsWorld myPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0f, SensorManager.GRAVITY_EARTH), false, 8, 3);
scene.registerUpdateHandler(myPhysicsWorld);

FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.1f, 0.5f);
FixtureDef BOX_BODY_FIXTURE_DEF = PhysicsFactory.createFixtureDef(20f, 0.35f, 0.5f);

PhysicsFactory.createBoxBody(myPhysicsWorld, ground, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, roof, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, left, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, right, BodyType.StaticBody, WALL_FIXTURE_DEF);

Body dynamicBoxBody = PhysicsFactory.createBoxBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BOX_BODY_FIXTURE_DEF);

myPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, dynamicBoxBody, PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));

scene.attachChild(sprite);
scene.attachChild(ground);
scene.attachChild(left);
scene.attachChild(roof);
scene.attachChild(right);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

توضیحات :


FixedStepPhysicsWorld(int pStepsPerSecond, Vector2 pGravity, boolean pAllowSleep, int pVelocityIterations, int pPositionIterations)

FixedStepPhysicsWorld
myPhysicsWorld =newFixedStepPhysicsWorld(60,newVector2(0f,SensorManager.GRAVITY_EARTH),false,8,3);
scene.registerUpdateHandler(myPhysicsWorld);

پارامتر های ورودی 60 در هر ثانیه 60 گام از فیزیک نمایش داده میشه ، Vector2 که بهش گفتیم جاذبه فقط به سمت پایین باشه همون طور که میبیند شما میتونید جاذبه زمین ، مریخ ، مشتری ، ماه و غیره رو ست کنید پارامتد بعدی این هست که اجازه نمیدیم این جاذبه بخواب بره !! در دو مقدار آخر که سرعت تکرار و تعداد تکرار موقعیت ها هست ، هرچی این مقادیر بیشتر باشه فیزیک نرم تری رو دارریم که بیشتر کردن این دو مقدار مصرف CPU رو افزایش میده پس بهتره بهینه عمل کنید ، بعد از اتمام این مورد فیزیک رو به Scene اضاف میکنیم حالا جاذبه وجود داره اما هنوز هیچ عنصر فیزیکی وجود نداره !

FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.1f, 0.5f);
FixtureDef BOX_BODY_FIXTURE_DEF = PhysicsFactory.createFixtureDef(20f, 0.35f, 0.5f);

در مورد FixtureDef توضیح دادیم که چی هست برای Wall ها که در چهار طرف بازی قرار دارند تعریف جرم معنایی نداره پس 0 قرار میدیم تعریف الاستیکی هم معنایی نداره (البته آنچنان مطمئن نیستم !)، تنها تعریف اصطکاک میتونه معنی داشته باشه (اما کاربردش رو هنوز بهش شک دارم) ، چرا تعریف جرم معنایی نداره ؟ در ادامه که Body میسازیم متوجه این موضوع میشید ، در واقع چون Body این دیوار ها از نوع static تعریف میکنیم پس گرانش بر اونها تاثیری نداره پس تعریف جرم هم معنایی نداره

PhysicsFactory.createBoxBody(myPhysicsWorld, ground, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, roof, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, left, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, right, BodyType.StaticBody, WALL_FIXTURE_DEF);

ساخت body از نوع Box (چهارگوش) برای دیوار ها نوع body از نوع ثابت (static) و مقدار FixtureDef هم که مشخص هست ، خروجی متد های createBoxBody برابر با Body هست ولی چون به خروجی اونها نیازی نداریم خروجی هم نمیگیریم اما میبینید که برای جسم محترک (Dynamic) مقدار Body رو دریافت میکنیم چون بهش نیاز داریم

Body dynamicBoxBody = PhysicsFactory.createBoxBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BOX_BODY_FIXTURE_DEF);

در بالا هم یک Body.dynamic تعریف میکنیم

myPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, dynamicBoxBody, PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));

PhysicsConnector شکل ساخته شده در Scene را به Body مورد نظر لینک می دهد و از این طریق با جا به جا شدن Body شکل مرتبط با آن نیز جا به جا می شود. (طبق گفته های این لینک)، گزینه آخر هم تبدیل pixel به متر هست

 

پیشنهاد میکنم مقادیر جرم و الاستیکی و اصطکاک رو در FixtureDef  برای BOX_BODY_FIXTURE_DEF تغییر بدید و  تست کنید

پاسخ به سوال 
Criss  8 سال پیش
+7 0

تست و یادگیری بهتر

توی این قسمت سعی میکینم با کلیک شدن روی Scene یک sprite رو اضاف کنیم که تحت تاثیر جاذبه قرار بگیره توی این قسمت علاوه بر createBoxBody های  که داشتیم ، body های دایره ایی هم میسازیم (createCircleBody) < همچنین EngineOptions رو از نوع Portrait انتخاب میکنیم ( اگر کمی خلاقیت داشته باشید میتونید مقادیر FixtureDef رو بصورت Random ست کنید )

 public class PhysicsBoxBody extends BaseGameActivity {

private static final int WIDTH = 480;
private static final int HEIGHT = 800;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionBoxSprite;
private TiledTextureRegion regionCircleSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 64);
regionBoxSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
regionCircleSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_circle_tiled.png", 0, 32, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.4f, 0.5f, 0.1f));

Rectangle ground = new Rectangle(0, HEIGHT - 6, WIDTH, 6, getVertexBufferObjectManager());
ground.setColor(Color.RED);
Rectangle left = new Rectangle(0, 0, 6, HEIGHT - 6, getVertexBufferObjectManager());
left.setColor(Color.BLUE);
Rectangle roof = new Rectangle(6, 0, WIDTH, 6, getVertexBufferObjectManager());
roof.setColor(Color.GREEN);
Rectangle right = new Rectangle(WIDTH - 6, 6, 6, HEIGHT - 12, getVertexBufferObjectManager());
right.setColor(Color.YELLOW);

final FixedStepPhysicsWorld myPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0f, SensorManager.GRAVITY_EARTH), false, 10, 5);
scene.registerUpdateHandler(myPhysicsWorld);

FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.1f, 0.5f);

PhysicsFactory.createBoxBody(myPhysicsWorld, ground, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, roof, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, left, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, right, BodyType.StaticBody, WALL_FIXTURE_DEF);

scene.setOnSceneTouchListener(new IOnSceneTouchListener() {

boolean bool = true;


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionUp()) {
FixtureDef BODY_FIXTURE_DEF = PhysicsFactory.createFixtureDef(20f, 0.35f, 0.5f);
AnimatedSprite sprite = null;
Body dynamicBoxOrCircleBody = null;
if (bool) {
bool = false;
sprite = new AnimatedSprite(pSceneTouchEvent.getX() - regionCircleSprite.getWidth() / 2, pSceneTouchEvent.getY() - regionCircleSprite.getHeight() / 2, regionCircleSprite,
getVertexBufferObjectManager());
dynamicBoxOrCircleBody = PhysicsFactory.createCircleBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BODY_FIXTURE_DEF);
} else {
bool = true;
sprite = new AnimatedSprite(pSceneTouchEvent.getX() - regionBoxSprite.getWidth() / 2, pSceneTouchEvent.getY() - regionBoxSprite.getHeight() / 2, regionBoxSprite,
getVertexBufferObjectManager());
dynamicBoxOrCircleBody = PhysicsFactory.createBoxBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BODY_FIXTURE_DEF);
}
sprite.animate(150);
myPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, dynamicBoxOrCircleBody, PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));
pScene.attachChild(sprite);
}
return false;
}
});

scene.attachChild(ground);
scene.attachChild(left);
scene.attachChild(roof);
scene.attachChild(right);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

چیز جدیدی برای توضیح وجود نداره !

پاسخ به سوال 
Criss  8 سال پیش
+7 0

استفاده از سنسور و تغییر جاذبه

کافیه از Interface زیر implement کنیم

implements IAccelerationListener

 دیگه فکر میکنم خودتون بتونید کد رو تحلیل کنید

 public class PhysicsBodysAndSensor extends BaseGameActivity implements IAccelerationListener {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionBoxSprite;
private TiledTextureRegion regionCircleSprite;

private FixedStepPhysicsWorld myPhysicsWorld;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 64);
regionBoxSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
regionCircleSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_circle_tiled.png", 0, 32, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.4f, 0.5f, 0.1f));

Rectangle ground = new Rectangle(0, HEIGHT - 6, WIDTH, 6, getVertexBufferObjectManager());
ground.setColor(Color.RED);
Rectangle left = new Rectangle(0, 0, 6, HEIGHT - 6, getVertexBufferObjectManager());
left.setColor(Color.BLUE);
Rectangle roof = new Rectangle(6, 0, WIDTH, 6, getVertexBufferObjectManager());
roof.setColor(Color.GREEN);
Rectangle right = new Rectangle(WIDTH - 6, 6, 6, HEIGHT - 12, getVertexBufferObjectManager());
right.setColor(Color.YELLOW);

myPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0f, SensorManager.GRAVITY_EARTH), false, 10, 5);
scene.registerUpdateHandler(myPhysicsWorld);

FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.1f, 0.5f);

PhysicsFactory.createBoxBody(myPhysicsWorld, ground, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, roof, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, left, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, right, BodyType.StaticBody, WALL_FIXTURE_DEF);

scene.setOnSceneTouchListener(new IOnSceneTouchListener() {

boolean bool = true;


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionUp()) {
FixtureDef BODY_FIXTURE_DEF = PhysicsFactory.createFixtureDef(20f, 0.35f, 0.5f);
AnimatedSprite sprite = null;
Body dynamicBoxOrCircleBody = null;
if (bool) {
bool = false;
sprite = new AnimatedSprite(pSceneTouchEvent.getX() - regionCircleSprite.getWidth() / 2, pSceneTouchEvent.getY() - regionCircleSprite.getHeight() / 2, regionCircleSprite,
getVertexBufferObjectManager());
dynamicBoxOrCircleBody = PhysicsFactory.createCircleBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BODY_FIXTURE_DEF);
} else {
bool = true;
sprite = new AnimatedSprite(pSceneTouchEvent.getX() - regionBoxSprite.getWidth() / 2, pSceneTouchEvent.getY() - regionBoxSprite.getHeight() / 2, regionBoxSprite,
getVertexBufferObjectManager());
dynamicBoxOrCircleBody = PhysicsFactory.createBoxBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BODY_FIXTURE_DEF);
}
sprite.animate(150);
myPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, dynamicBoxOrCircleBody, PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));
pScene.attachChild(sprite);
}
return false;
}
});

scene.attachChild(ground);
scene.attachChild(left);
scene.attachChild(roof);
scene.attachChild(right);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}


@Override
public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {

}


@Override
public void onAccelerationChanged(AccelerationData pAccelerationData) {
Vector2 gravity = Vector2Pool.obtain(pAccelerationData.getX(), pAccelerationData.getY());
myPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}


@Override
public synchronized void onResumeGame() {
enableAccelerationSensor(this);
super.onResumeGame();
}


@Override
public synchronized void onPauseGame() {
disableAccelerationSensor();
super.onPauseGame();
}
}

 

 

پاسخ به سوال 
Criss  8 سال پیش
+8 0

تست و یادگیری بهتر

توی این تست سعی میکنیم از یک AnalogOnScreenContrlo استفاده کنیم و با کمک اون جاذبه رو تغییر بدیم ! چه بازی هایی که نمیشه با این ساخت !

 public class PhysicsBodysGravityAnalog extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Camera camera;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionBoxSprite;
private TiledTextureRegion regionCircleSprite;
private ITextureRegion regionAnalogBase;
private ITextureRegion regionAnalogKnob;

private FixedStepPhysicsWorld myPhysicsWorld;


@Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 256, 164);
regionBoxSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
regionCircleSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_circle_tiled.png", 0, 32, 2, 1);
regionAnalogBase = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_base.png", 64, 0);
regionAnalogKnob = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_knob.png", 192, 0);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.4f, 0.5f, 0.1f));

Rectangle ground = new Rectangle(0, HEIGHT - 6, WIDTH, 6, getVertexBufferObjectManager());
ground.setColor(Color.RED);
Rectangle left = new Rectangle(0, 0, 6, HEIGHT - 6, getVertexBufferObjectManager());
left.setColor(Color.BLUE);
Rectangle roof = new Rectangle(6, 0, WIDTH, 6, getVertexBufferObjectManager());
roof.setColor(Color.GREEN);
Rectangle right = new Rectangle(WIDTH - 6, 6, 6, HEIGHT - 12, getVertexBufferObjectManager());
right.setColor(Color.YELLOW);

myPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0f, SensorManager.GRAVITY_EARTH), false, 10, 5);
scene.registerUpdateHandler(myPhysicsWorld);

FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.1f, 0.5f);

PhysicsFactory.createBoxBody(myPhysicsWorld, ground, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, roof, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, left, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, right, BodyType.StaticBody, WALL_FIXTURE_DEF);

scene.setOnSceneTouchListener(new IOnSceneTouchListener() {

boolean bool = true;


@Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionUp()) {
FixtureDef BODY_FIXTURE_DEF = PhysicsFactory.createFixtureDef(20f, 0.35f, 0.5f);
AnimatedSprite sprite = null;
Body dynamicBoxOrCircleBody = null;
if (bool) {
bool = false;
sprite = new AnimatedSprite(pSceneTouchEvent.getX() - regionCircleSprite.getWidth() / 2, pSceneTouchEvent.getY() - regionCircleSprite.getHeight() / 2, regionCircleSprite,
getVertexBufferObjectManager());
dynamicBoxOrCircleBody = PhysicsFactory.createCircleBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BODY_FIXTURE_DEF);
} else {
bool = true;
sprite = new AnimatedSprite(pSceneTouchEvent.getX() - regionBoxSprite.getWidth() / 2, pSceneTouchEvent.getY() - regionBoxSprite.getHeight() / 2, regionBoxSprite,
getVertexBufferObjectManager());
dynamicBoxOrCircleBody = PhysicsFactory.createBoxBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BODY_FIXTURE_DEF);
}
sprite.animate(150);
myPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, dynamicBoxOrCircleBody, PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));
pScene.attachChild(sprite);
}
return false;
}
});

AnalogOnScreenControl alanogLeft = new AnalogOnScreenControl(0, HEIGHT - regionAnalogBase.getHeight(), camera,
regionAnalogBase, regionAnalogKnob, 0.1f, 200, this.getVertexBufferObjectManager(),
new IAnalogOnScreenControlListener() {

@Override
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
Vector2 gravity = Vector2Pool.obtain(0, 3);
if (pValueX != 0 || pValueY != 0) {
gravity = Vector2Pool.obtain(pValueX * 10, pValueY * 10);
}
myPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}


@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {}
});
alanogLeft.getControlBase().setAlpha(0.2f);
alanogLeft.getControlKnob().setAlpha(0.2f);
alanogLeft.getControlBase().setScaleCenter(0, 128);
alanogLeft.refreshControlKnobPosition();

scene.setChildScene(alanogLeft);

scene.attachChild(ground);
scene.attachChild(left);
scene.attachChild(roof);
scene.attachChild(right);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

 

پاسخ به سوال 
Criss  8 سال پیش
+8 0

LinearVelocity

این قابلیت رو میشه به body ست کرد این رو به آموزشی که قبلا توی کلاس PhysicsBoxBody  توضیح داده بودم اضاف میکنیم

کد جدید به شکل زیر هست

  scene.setOnAreaTouchListener(new IOnAreaTouchListener() {

@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionUp()) {
dynamicBoxBody.setLinearVelocity(10, 20);
}
return false;
}
});

scene.registerTouchArea(sprite);

تمام کد :

 public class PhysicsLinearVelocity extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;

private BitmapTextureAtlas atlas;
private TiledTextureRegion regionSprite;


@Override
public EngineOptions onCreateEngineOptions() {
Camera camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 64, 32);
regionSprite = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlas, this, "face_box_tiled.png", 0, 0, 2, 1);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.4f, 0.5f, 0.1f));
int CenterX = WIDTH / 2;
int CenterY = HEIGHT / 2;

AnimatedSprite sprite = new AnimatedSprite(CenterX - regionSprite.getWidth() / 2, CenterY - regionSprite.getHeight() / 2, regionSprite, getVertexBufferObjectManager());
sprite.animate(150);

Rectangle ground = new Rectangle(0, HEIGHT - 6, WIDTH, 6, getVertexBufferObjectManager());
ground.setColor(Color.RED);
Rectangle left = new Rectangle(0, 0, 6, HEIGHT - 6, getVertexBufferObjectManager());
left.setColor(Color.BLUE);
Rectangle roof = new Rectangle(6, 0, WIDTH, 6, getVertexBufferObjectManager());
roof.setColor(Color.GREEN);
Rectangle right = new Rectangle(WIDTH - 6, 6, 6, HEIGHT - 12, getVertexBufferObjectManager());
right.setColor(Color.YELLOW);

FixedStepPhysicsWorld myPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0f, SensorManager.GRAVITY_EARTH), false, 8, 3);
scene.registerUpdateHandler(myPhysicsWorld);

FixtureDef WALL_FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.1f, 0.5f);
FixtureDef BOX_BODY_FIXTURE_DEF = PhysicsFactory.createFixtureDef(20f, 0.35f, 0.5f);

PhysicsFactory.createBoxBody(myPhysicsWorld, ground, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, roof, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, left, BodyType.StaticBody, WALL_FIXTURE_DEF);
PhysicsFactory.createBoxBody(myPhysicsWorld, right, BodyType.StaticBody, WALL_FIXTURE_DEF);

final Body dynamicBoxBody = PhysicsFactory.createBoxBody(myPhysicsWorld, sprite, BodyType.DynamicBody, BOX_BODY_FIXTURE_DEF);

myPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, dynamicBoxBody, PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));

scene.setOnAreaTouchListener(new IOnAreaTouchListener() {

@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (pSceneTouchEvent.isActionUp()) {
dynamicBoxBody.setLinearVelocity(10, 20);
}
return false;
}
});

scene.registerTouchArea(sprite);
scene.attachChild(sprite);
scene.attachChild(ground);
scene.attachChild(left);
scene.attachChild(roof);
scene.attachChild(right);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

در آخر برای یادگیری بهتر و کاربردی کلاس PhysicsJumpExample رو هم ببینید

پاسخ به سوال 
Criss  8 سال پیش
+8 0

تعقیب کردن یک کاراکتر متحرک با دوربین

طبق این آموزش تنها به یک متد موجود در Camera نیاز داریم :

 camera.setChaseEntity(myrec);

کد کامل به شکل زیر :

 public class CameraFollowSprite extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Camera camera;

private BitmapTextureAtlas atlas;
private ITextureRegion regionAnalogBase;
private ITextureRegion regionAnalogKnob;


@Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, WIDTH, HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

atlas = new BitmapTextureAtlas(getTextureManager(), 128, 192);
regionAnalogBase = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_base.png", 0, 0);
regionAnalogKnob = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_knob.png", 0, 128);

atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.3f, 0.35f, 0.0f));

final Rectangle myrec = new Rectangle(WIDTH / 2, HEIGHT / 2, 48, 48, getVertexBufferObjectManager());
myrec.setColor(Color.BLACK);
Rectangle rec1 = new Rectangle(50, HEIGHT / 2, 48, 48, getVertexBufferObjectManager());
rec1.setColor(Color.RED);
Rectangle rec2 = new Rectangle(850, HEIGHT / 2, 48, 48, getVertexBufferObjectManager());
rec2.setColor(Color.BLUE);
Rectangle rec3 = new Rectangle(1250, HEIGHT / 2, 48, 48, getVertexBufferObjectManager());
rec3.setColor(Color.YELLOW);

camera.setChaseEntity(myrec);

final PhysicsHandler physicsHandler = new PhysicsHandler(myrec);
myrec.registerUpdateHandler(physicsHandler);

AnalogOnScreenControl alanogLeft = new AnalogOnScreenControl(400 - regionAnalogBase.getWidth() / 2, HEIGHT - regionAnalogBase.getHeight() - 50, camera,
regionAnalogBase, regionAnalogKnob, 0.1f, 200, this.getVertexBufferObjectManager(),
new IAnalogOnScreenControlListener() {

@Override
public void onControlChange(BaseOnScreenControl pBaseOnScreenControl, float pValueX, float pValueY) {
physicsHandler.setVelocity(pValueX * 250, pValueY * 250);
}


@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
myrec.registerEntityModifier(new SequenceEntityModifier(new ScaleModifier(0.25f, 1, 1.5f), new ScaleModifier(0.25f, 1.5f, 1)));
}
});
alanogLeft.getControlBase().setAlpha(0.2f);
alanogLeft.getControlKnob().setAlpha(0.2f);
alanogLeft.getControlBase().setScaleCenter(0, 128);
alanogLeft.refreshControlKnobPosition();

scene.setChildScene(alanogLeft);

scene.attachChild(myrec);
scene.attachChild(rec1);
scene.attachChild(rec2);
scene.attachChild(rec3);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

برای حرکت در جهت X به EngineOption کد های زیر رو اضاف کنید :

 @Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, WIDTH, HEIGHT) {

IEntity ie;


@Override
public void setChaseEntity(IEntity pChaseEntity) {
ie = pChaseEntity;
super.setChaseEntity(pChaseEntity);
}


@Override
public void updateChaseEntity() {
if (ie != null) {
float cord[] = ie.getSceneCenterCoordinates();
setCenter(cord[0], getCenterY());
}
}

};
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}

 

 

پاسخ به سوال 
Criss  8 سال پیش
+7 0

CameraBound

توی آموزش های قبل دیدید که این Rectangle ما تا بینهایت میتونه ادامه پیدا کنه و همه جا سرک بشه ، به همراهش دوربین هم تعقیبش میکنه اما اگر قرار باشه با استفاده از دیوار مراحل بازی رو محدود کنیم که کاراکتر ما از بازی بیرون نره < باید دوربین رو هم براش مرز تعریف کنیم که تا یجایی به بعد دیگه کاراکتر رو هی تعقیب نکنه و اینجا آخر خط هستش

 public class CameraBound extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private BoundCamera camera;

private ITextureRegion regionAnalogBase;
private ITextureRegion regionAnalogKnob;


@Override
public EngineOptions onCreateEngineOptions() {
camera = new BoundCamera(0, 0, 800, 480);
camera.setBounds(0, 0, 1024, 800);
camera.setBoundsEnabled(true);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(WIDTH, HEIGHT), camera);
}


@Override
public void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) throws Exception {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

BitmapTextureAtlas atlas = new BitmapTextureAtlas(getTextureManager(), 168, 192);
regionAnalogBase = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_base.png", 0, 0);
regionAnalogKnob = BitmapTextureAtlasTextureRegionFactory.createFromAsset(atlas, this, "onscreen_control_knob.png", 0, 128);
atlas.load();

pOnCreateResourcesCallback.onCreateResourcesFinished();
}


@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws Exception {
Scene scene = new Scene();
scene.setBackground(new Background(0.2f, 0.3f, 0.0f));

Rectangle rect = new Rectangle(50, HEIGHT / 2, 48, 48, getVertexBufferObjectManager());
Rectangle area = new Rectangle(0, 0, WIDTH, HEIGHT, getVertexBufferObjectManager());
area.setAlpha(0.2f);

camera.setChaseEntity(rect);

final PhysicsHandler physicsHandler = new PhysicsHandler(rect);
rect.registerUpdateHandler(physicsHandler);
AnalogOnScreenControl alanogLeft = new AnalogOnScreenControl(0, HEIGHT - regionAnalogBase.getHeight(), camera,
regionAnalogBase, regionAnalogKnob, 0.1f, 200, this.getVertexBufferObjectManager(),
new IAnalogOnScreenControlListener() {

@Override
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
physicsHandler.setVelocity(pValueX * 100, pValueY * 100);
}


@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {}
});
alanogLeft.getControlBase().setAlpha(0.2f);
alanogLeft.getControlKnob().setAlpha(0.2f);
alanogLeft.getControlBase().setScaleCenter(0, 128);
alanogLeft.refreshControlKnobPosition();

scene.setChildScene(alanogLeft);
scene.attachChild(rect);
scene.attachChild(area);
pOnCreateSceneCallback.onCreateSceneFinished(scene);
}


@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}
}

 

پاسخ به سوال 
Criss  8 سال پیش
+4 0

 

تست و یادگیری بهتر

ساخت دشمن هوشمند به روش صحیح

محاسبه و نمایش فاصله طی شده از نقطه شروع در HUD

نشانه گیری به سمت کاراکتر متحرک (چالش نیاز به وقت و تست ، محاسبه زاویه بین وتر و یک ضلع)

Draw On Scene (چالش ، نیاز به بررسی)

 Health for each enemy

دشمن هوشمند ، محاسبه فاصله شعاعی یا ابداع روشی دیگر

معرفی بازی های ساخته شده با AndEngine و الهام گرفتن از ایده ها و طرح ها

و . . .

پاسخ به سوال 
Criss  8 سال پیش
+3 0

اشتباه در آموزش ها :

توی آموزش های قبلی به اشتباه خط زیر وجود داره : (که همشون رو اصلاح کردم !!)

 AnimatedSprite sprite = new mySprite

که باید بصورت زیر باشه :

 mySprite sprite = new mySprite

اگر شما ازش استفاده کردید < اصلاحش کنید

0 0
سلام ، اگه الان از شما سوال شه که اگه به قبل برمیگشتید و این تجربیات رو داشتید ، دوباره به سراغ andEngine میرفتید ؟ (5 سال پیش)
0 0
لطفا پاسخ بدید ، یا حداقل آلترناتیو AndEngine چی بود برای شما ؟ کدوم رو پیش میگرفتید جای این برنامه ؟ یا واقعا هنوز هم حامیش هستید (4 سال پیش)

پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .