بازی 404 Power App یافت نشد

بهترین راه برای یادگیری انجام دادن است، و گاهی اوقات کاری که انجام می دهید برای چیزی که می خواهید یاد بگیرید کاملاً مناسب نیست. در این موارد، پروژه های شخصی همان چیزی است که ما به آن نیاز داریم، برای خود یک هدف ایجاد کنید که شما را مجبور به یادگیری کند. این مهارتهای توسعهدهنده شما را تازه نگه میدارد و میتواند سرگرمی را به روز شما اضافه کند.
ساختن بازیها در Power Apps را یک پروژه آموزشی عالی یافتم، زیرا طبیعتاً من باید خلاق باشم زیرا Power Apps برای ساخت بازی ساخته نشده است.
من قبلاً یک وبلاگ در مورد بازیها در اینجا Flappy-app و دیگری در مورد ساخت ماشینحسابهای مختلف Power-app-calculator اگر میخواهید بیشتر ببینید، انجام دادهام.
بنابراین پروژه امروز چیست، خوب من اینترنت خود را چند روز پیش از دست دادم و به یاد بازی Google Chromes Dinasaur در حال اجرا افتادم و از Appy Dino الهام گرفتم.
چیزی که دوست داشتم این بود که فکر میکردم باید یک میخ مربع (بازی) را در یک سوراخ گرد (برنامههای قدرت) انجام دهم، در نهایت به 4 چالش اصلی رسیدم:
- انیمیشن حلقه زدن
- انیمیشن متحرک
- تولید مولفه تصادفی
- برخورد
انیمیشن حلقه زدن
دو منطقه وجود داشت که میخواستم آن را متحرک کنم، جن دایناسور و حرکت پشت زمین.
برای اسپرایت 6 فریم مختلف بارگذاری کردم
و سپس به 2 رویکرد مختلف نگاه کردم
هر تصویر را در یک آرایه ذخیره کنید:
ClearCollect(colSprites,['1','2','3','4','5','6']);
Sprite را به عنوان یک جزء تصویر با یک متغیر به عنوان تصویر تنظیم کنید
سپس در یک تایمر «OnTimerEnd» متغیر شمارنده و متغیر تصویر تنظیم شده را به تصویر بعدی در مجموعه به روز کردم (با بازنشانی اگر در پایان مجموعه باشد).
If(viIndex=6,
Set(viIndex,1);
,
Set(viIndex,viIndex+1);
);
Set(voSprite,Index(colSprites,viIndex).Value);
روش دوم اساسی تر بود، من هر 6 تصویر را به عنوان جزء تصویر خود اضافه می کنم:
سپس یک شی ایجاد کردم که وضعیت دید هر تصویر را نگه می دارد. سپس در هر «OnTimerEnd» از یک سوئیچ برای بهروزرسانی شی با قابلیت مشاهده تصویر بعدی استفاده میکنم
If(viIndex=6,
Set(viIndex,1);
,
Set(viIndex,viIndex+1);
);
Switch(viIndex,
1,Set(voVis,{one:true,two:false,three:false,four:false,five:false,six:false}),
2,Set(voVis,{one:false,two:true,three:false,four:false,five:false,six:false}),
3,Set(voVis,{one:false,two:false,three:true,four:false,five:false,six:false}),
4,Set(voVis,{one:false,two:false,three:false,four:true,five:false,six:false}),
5,Set(voVis,{one:false,two:false,three:false,four:false,five:true,six:false}),
6,Set(voVis,{one:false,two:false,three:false,four:false,five:false,six:true})
);
به نظر میرسید که کاملاً کار میکند، با تنها مشکلی که یک قاب خالی چند بار هنگام شروع کار ظاهر میشود (تقریباً یکسان کار میکنند، اما به نظر میرسد رویکرد sprite فریمهای خالی بیشتری را نشان میدهد).
رویکرد sprite راه حلی مقیاس پذیرتر و ساده تر است.
مورد بعدی پسزمینه بود، و من میتوانستم همان راهحل را مثل اسپرایت تکرار کنم، اما برای انجام کار دیگری (و سادهتر) با یک GIF متحرک رفتم.
آخرین چالش این بود که چگونه گیف را متوقف کنم، در نهایت تصمیم گرفتم یک تصویر جلوی گیف داشته باشم و آن را محو کنم.
این راه حل بسیار ساده تر از sprite بود، باعث شد فکر کنم که باید یک GIF نیز برای آن استفاده کنم. اما استاپ استارت به خوبی اسپرایت نبود، بنابراین تا زمانی که فریمهای زیادی وجود نداشته باشد، همچنان ابتدا با رویکرد اسپرایت پیش میروم.
2. انیمیشن متحرک
برای پرش دایناسور باید جن را به بالا و سپس پایین متحرک کنیم.
ابتدا ارتفاع پرش را به عنوان متغیری به نام viLeap و متغیر دوم viJump را به عنوان همان viLeap تنظیم کردم.
سپس در عمل پرش، viJump را روی 0 قرار می دهیم.
در نهایت روی تایمری که شرط دارد اگر viJump برابر با viLeap نباشد 20 را به viJump اضافه کنید. همچنین متغیر sprites Y را روی سطح زمین منهای viJump قرار دادیم.
If(viJump<viLeap,
Set(viJump,viJump+20);
Set(viSpriteY,viY-viJump);
);
این انیمیشن بالا را حل می کند، بعد انیمیشن پایین است. در تایمر یک شرط داریم که بررسی می کند اسپرایت بالای زمین است و viJump برابر با viLeap است (بالا متوقف شده است). در شرایطی که برعکس می کنیم و 20 را اضافه می کنیم (Y = 0 بالای صفحه است).
If(viSpriteY<>viY && viJump=viLeap,
Set(viSpriteY,viSpriteY+20);
);
بنابراین اکنون اسپرایت بالا می رود، می ایستد و سپس پایین می رود تا به زمین برسد.
3. تولید مولفه تصادفی
منظور من از ژنراتور تصادفی چیست، خوب میخواهم موانع بهطور تصادفی پیش بیایند، اما بتوانم به مرور زمان احتمال وجود آنها را افزایش دهم.
در بازی قبلی خود (Flappy App) از رویکرد convayabelt استفاده کرده بودم:
اما این برای فاصله و الگوهای ثابت خوب بود، بنابراین چیزی که من نیاز داشتم نیست.
بعد این بود که از یک گالری استفاده کنم، ایده من این بود که در یک حلقه می توانم اولین مورد از یک مجموعه را حذف کنم و یک مورد جدید را در پایان اضافه کنم. گالری از مجموعه به عنوان منبع داده خود استفاده می کند، بنابراین هر بار که اولین مورد حذف می شود، گالری را مجبور به حرکت می کند.
ClearCollect(colGalleryTest,[
{id:1,visability:true},
{id:2,visability:true},
{id:3,visability:true},
{id:4,visability:true},
{id:5,visability:true},
{id:6,visability:true},
{id:7,visability:true},
{id:8,visability:true},
{id:9,visability:true},
{id:10,visability:true},
{id:11,visability:true},
{id:12,visability:true}
]);
OnTimerEnd
Remove(colGalleryTest,First(colGalleryTest));
Collect(colGalleryTest,{id:Last(colGalleryTest).id+1});
متأسفانه همانطور که می بینید کار نکرد، با این که گالری فقط در یک فریم به روز می شود، بنابراین هیچ انیمیشنی وجود ندارد.
بنابراین رویکرد بعدی با الهام از رویکرد convayabelt من بود، من از همان عمل بازنشانی استفاده میکردم، اما بهجای یک الگوی ثابت، بهطور تصادفی یک مانع را رها میکردم.
شانس انتشار تصادفی باید در طول زمان افزایش می یافت، بنابراین رویکردی که من پیش بردم یک مجموعه بود.
این مجموعه 4 رکورد با موانع و 10 رکورد بدون. یک عدد تصادفی رکورد را با شاخص خود انتخاب می کند و اگر مانعی بود آن را آزاد می کند. رکورد شامل فیلدهای زیر بود:
- id – برای آسان کردن وصله کردن
- تصویر – بنابراین ما می توانیم موانع مختلف داشته باشیم
- x – بنابراین می توانیم x آن را به روز کنیم و آن را از راست به چپ حرکت دهیم
- فعال – اگر انتخاب شده باشد و در حال حرکت باشد زیرا نمی خواهیم آن را دو بار انتخاب کنیم
- obs – مانع است یا بدون آن
- comp – کامپوننت تا اندازه و ابعاد آن را برای تأثیرگذاری بدانیم (قبل از اینکه بتوانیم مؤلفهها را در مجموعهها ذخیره کنیم نمیدانستم)
ClearCollect(colObstacles,[
{id:1,x:800,image:pbi,active:false, obs:true, comp:imObsticle_1},
{id:2,x:800,image:pbi,active:false, obs:true, comp:imObsticle_2},
{id:3,x:800,image:pbi,active:false, obs:true, comp:imObsticle_3},
{id:4,x:800,image:pbi,active:false, obs:true, comp:imObsticle_4},
{id:5,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:6,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:7,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:8,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:9,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:10,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:11,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:12,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:13,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1},
{id:14,x:800,image:pbi,active:false, obs:false, comp:imObsticle_1}
]);
برای انتشار بررسی میکنیم که آیا رکورد ایندکسشده فعال نیست و شکاف به اندازه کافی بزرگ است (من نمیخواستم چندین مؤلفه با هم باشند، زیرا دایناسور ممکن است نتواند از روی همه آنها بپرد) سپس آن را به فعال وصله میکنیم.
///random index
Set(viRandom,RandBetween(1,CountRows(colObstacles)));
///check if record is obsticle and we are not to close to last obsticle
If(Index(colObstacles,viRandom).obs && viGapCount=0,
Patch(colObsticles, {id:viRandom},{
active:true
}
);
Set(viGapCount,viGap);
);
آخرین مرحله این است که همه موانع فعال حرکت کنند و موانعی که از صفحه خارج شده اند را بازنشانی کنیم، برای این کار از UpdateIf استفاده می کنیم.
///all active obstacles move left 10 pixels
UpdateIf(colObstacles,active,{x:x-10});
//// all off the screen reset
UpdateIf(colObstacles,x<-200,{x:800,active:false});
اکنون ارزش واقعی رویکرد مجموعه را می توان در مرحله سطح بالا یافت. میتوانیم یکی از رکوردهای بدون مانع را حذف کنیم، بنابراین شانس یک مانع را از 4/14 به 4/13 و غیره افزایش میدهیم.
4. برخورد
آخرین باری که تشخیص برخورد را انجام دادم، مجبور شدم کدی را بنویسم و هر مؤلفه را با sprite بررسی کنم، نمیخواستم دوباره این کار را انجام دهم.
خوشبختانه رویکرد مجموعه جدید من همه چیز را آسان تر کرد.
شرط اول این است که بررسی کنید اسپرایت کمتر از ارتفاع موانع باشد (Y آن ارتفاع آن را اضافه کنید)، گویی در حال پریدن از گاوصندوق است.
سپس مجموعه را با x آن فیلتر می کنم و بررسی می کنم که آیا در ناحیه sprites قرار دارد یا خیر. سپس میتوانیم ردیفها را بشماریم، و اگر بزرگتر از 0 باشد، تأثیر خواهیم داشت.
If((imSprite.Y+imSprite.Height)>viY,
If(CountRows(Filter(colObstacles,x+comp.Width>=(viAdjustSprite+viX) && x<=(viXsprite-viAdjustSprite)))>0,
Set(vbGameOver,true);
Set(viTransparency,0);
,
If(viTransparency<100,Set(viTransparency,viTransparency+10));
)
);
متغیر viAdjustSprite برای تنظیم برخورد برای فضای خالی اطراف تصاویر استفاده می شود. همانطور که اگر مربع کامل آن نباشد، برخوردهای ما ممکن است بیش از حد تهاجمی باشد
و بس، نمرات و جداول با امتیاز بالا اضافه می شود، اما من به این موضوع نمی پردازم زیرا مطمئن هستم که همه می توانند این کار را انجام دهند.
چیزی که من از آن لذت بردم آزمایش محدودیت های Power FX و یادگیری بود (قبلا نمی دانستم می توانید اجزا را در مجموعه ها قرار دهید).
پیوند به صادرات: https://github.com/wyattdave/Power-Platform