از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
Phaser 3 و Tiled: ساختن PlatformerPhaser 3 ما را قادر می سازد تا به سرعت بازی ها را در مرورگر خود با جاوا اسکریپت ایجاد کنیم. برخی از بازیهای دو بعدی مورد علاقه ما پلتفرمر هستند – به بازیهایی مانند Mario، Sonic، Super Meat Boy یا Cuphead فکر کنید. Tiled یک ویرایشگر نقشه دو بعدی است که برای ایجاد دنیای بازی استفاده می شود. ما روش ایجاد …
سرفصلهای مطلب
معرفی
Phaser 3 ما را قادر می سازد تا به سرعت در مرورگر خود با جاوا اسکریپت بازی ایجاد کنیم. برخی از بازیهای دو بعدی مورد علاقه ما پلتفرمر هستند – به بازیهایی مانند Mario، Sonic، Super Meat Boy یا Cuphead فکر کنید.
کاشی کاری شده یک ویرایشگر نقشه دو بعدی است که برای ایجاد دنیای بازی استفاده می شود. ما روش ایجاد یک سطح پلتفرمر با Tiled، ادغام آن با Phaser و انیمیشن Sprites را برای ایجاد یک تجربه پلتفرم دو بعدی غنی را بررسی خواهیم کرد.
در این مقاله ما یک بازی پایه پلتفرمر ایجاد می کنیم که بازیکن ما می تواند در آن حرکت کند روی در دنیای ما بپر اگر بازیکن به یک سنبله برخورد کند، موقعیت بازیکن را دوباره تنظیم می کنیم. دموی قابل بازی این بازی را می توانید پیدا کنید اینجا.
این آموزش برای کسانی که با Phaser 3 آشنا هستند نوشته شده است.اگر اینطور نیستید با یکی از مقالات قبلی ما با فریم ورک آشنا شوید. روی فازر.
شروع شدن
برای پیگیری بهتر این آموزش، پروژه را دانلود و از حالت فشرده خارج کنید rasanegar-platformer.zip به فضای کاری شما پوشه باید دارای دارایی های زیر باشد:
- index.html: فاز 3.17 و ما را بارگذاری می کند
game.js
فایل - game.js: حاوی منطق بازی ما است
- دارایی/تصاویر:
background.png
kenney_player.png
kenney_player_atlas.json
spike.png
- دارایی ها/نقشه های کاشی: پوشه خالی، برای ذخیره فایل های Tiled استفاده می شود
- دارایی ها / کاشی ها:
platformPack_tilesheet.png
توجه داشته باشید: در صورت تمایل، می توانید با مشاهده کد پروژه نیز همراه باشید روی ما مخزن GitHub.
فراموش نکنید که یک سرور را در پوشه پروژه خود، با IDE یا حتی با پایتون اجرا کنید: python3 -m http.server
. این برای اینکه Phaser بتواند این دارایی ها را از طریق HTTP بارگیری کند، لازم است. دوباره، برای اطلاعات بیشتر به مقاله قبلی ما مراجعه کنید روی موضوع (در لینک بالا).
همه دارایی های بازی توسط ایجاد و به اشتراک گذاشته شده است کنی. فایل اطلس با بسته بندی اطلس فازر.
ویرایشگر نقشه کاشی
Tiled یک نرم افزار رایگان و متن باز برای ایجاد سطوح بازی است. در دسترس است روی تمام سیستم عامل های اصلی دسکتاپ، بنابراین بازدید کنید تارنما و برای ادامه آن را دانلود کنید.
ایجاد نقشه کاشی
Tiled را باز کرده و کلیک کنید روی “نقشه جدید”. در اعلان، قالب لایه کاشی را به “Base64 (غیر فشرده)”، عرض را به 14 کاشی و ارتفاع را به 7، و اندازه کاشی را به 64 پیکسل تغییر دهید.
فایل را به عنوان “level1.tmx” در “assets/tilemaps” ذخیره کنید.
ایجاد Tileset
در قسمت سمت راست، روی “New Tileset…” کلیک کنید. در پنجره بازشو، مجموعه tileset را “kenny_simple_platformer” نامگذاری کنید. مطمئن شوید که گزینه “Embed in map” وجود دارد انتخاب شده است. بدون آن گزینه، Phaser ممکن است در بارگیری صحیح نقشه شما با مشکل مواجه شود. در “Sourceویژگی، “platformPack_tilesheet.png” را از فهرست “assets/tilesets” انتخاب کنید.
عرض تصویر صفحه کاشی 896 پیکسل و ارتفاع آن 448 پیکسل است. این شامل 98 تصویر در مجموع با اندازه مساوی است که همه آنها در 7 ردیف و 14 ستون قرار می گیرند. با ریاضیات پایه می توانیم استنباط کنیم که هر کاشی 64 پیکسل در عرض و ارتفاع است. اطمینان حاصل کنید که عرض و ارتفاع مجموعه کاشی 64 پیکسل است:
طراحی سطح ما
نقشه ها در Tiled از لایه ها تشکیل شده اند. هر لایه تعدادی طراحی از دنیای بازی را ذخیره می کند. لایه هایی که هستند روی در بالا کاشی های خود را بر روی لایه های زیر نشان داده شده است. با استفاده از آنها به عمق می رسیم. این بازی اصلی تنها دو لایه خواهد داشت:
- پلتفرم: شامل دنیایی است که بازیکن با آن تعامل دارد
- Spikes: شامل میخ های خطرناکی است که می تواند به بازیکن آسیب برساند.
لایه پلت فرم
قبل از اینکه کاشی های خود را به نقشه اضافه کنیم، ابتدا نام لایه را تغییر می دهیم. نام لایه ها در کد Phaser ما ارجاع خواهد شد، بنابراین بیایید “Tiled Layer 1” را به “Platforms” تغییر دهیم:
برای ایجاد یک سطح، به سادگی یک کاشی را از مجموعه کاشی های خود انتخاب کنید و روی جایی که می خواهید آن را قرار دهید کلیک کنید روی نقشه. بیایید همه پلتفرم های خود را ایجاد یا اضافه کنیم:
اسپک در لایه شی
در قسمت لایه ها در سمت راست صفحه، روی دکمه “لایه جدید” کلیک کرده و “لایه شی” را انتخاب کنید. نام لایه را “Spikes” بگذارید.
در نوار ابزار بالا، گزینه “Insert Object” را انتخاب کنید:
اکنون می توانیم کاشی های سنبله را از مجموعه کاشی اضافه کنیم:
ما سطح بازی خود را ایجاد کرده ایم! اکنون باید آن را با Phaser ادغام کنیم.
بارگذاری یک نقشه کاشی کاری شده
Phaser نمی تواند آن را بخواند .tmx
فایلی که Tiled ایجاد کرد. اول، اجازه دهید export نقشه ما به JSON. کلیک روی “File -> Export As”، JSON را به عنوان فرمت انتخاب کنید و نام آن را “level1.json” در tilemaps
پوشه مانند تمام پروژه های Phaser، دارایی های ما باید در ما بارگذاری شوند preload()
تابع:
function preload() {
this.load.image('background', 'assets/images/background.png');
this.load.image('spike', 'assets/images/spike.png');
// At last image must be loaded with its JSON
this.load.atlas('player', 'assets/images/kenney_player.png','assets/images/kenney_player_atlas.json');
this.load.image('tiles', 'assets/tilesets/platformPack_tilesheet.png');
// Load the export Tiled JSON
this.load.tilemapTiledJSON('map', 'assets/tilemaps/level1.json');
}
توجه داشته باشید: ممکن است تعجب کنید که چرا باید تصویر spike را به طور جداگانه بارگذاری کنیم اگر در نقشه tilemap گنجانده شده است. متأسفانه، برای نمایش صحیح اشیا به این مقدار تکرار نیاز است.
در ما create()
تابع، اجازه دهید ابتدا پسزمینه را اضافه کرده و آن را برای وضوح خود مقیاس کنیم:
const backgroundImage = this.add.image(0, 0,'background').setOrigin(0, 0);
backgroundImage.setScale(2, 0.8);
سپس بیایید نقشه خود را اضافه کنیم:
const map = this.make.tilemap({ key: 'map' });
کلید با نام داده شده در مطابقت دارد preload()
عملکرد زمانی که ما Tiled JSON را بارگذاری کردیم. همچنین باید تصویر tileset را به Phaser خود اضافه کنیم map
هدف – شی:
const tileset = map.addTilesetImage('kenney_simple_platformer', 'tiles');
اولین استدلال از addTilesetImage
نام مجموعه کاشی است که ما در کاشی استفاده کردیم. آرگومان دوم کلید تصویری است که در آن بارگذاری کردیم preload()
تابع.
اکنون می توانیم لایه پلتفرم خود را اضافه کنیم:
const platforms = map.createStaticLayer('Platforms', tileset, 0, 200);
و باید این را ببیند:
بهطور پیشفرض، Phaser برخوردهای لایههای کاشیشده ما را مدیریت نمیکند. اگر اکنون پخش کننده خود را اضافه می کردیم، کاملاً از طریق کاشی های پلت فرم می افتاد. بیایید به Phaser بگوییم که این لایه می تواند با اشیاء دیگر برخورد کند:
platforms.setCollisionByExclusion(-1, true);
به هر کاشی در نقشه ما یک نمایه توسط Tiled داده شد تا به آنچه باید در آنجا نشان داده شود اشاره کند. شاخص پلت فرم ما فقط می تواند بزرگتر از 0 باشد. setCollisionByExclusion
به Phaser می گوید که برخوردها را برای هر کاشی که شاخص آن -1 نیست، فعال کند، بنابراین، همه کاشی ها.
اطلس بافت
انیمیشن پخش ما در یک اطلس بافت – تصویری حاوی تصاویر کوچکتر – ذخیره می شود. مشابه شیت های اسپرایت، با بارگذاری یک فایل، فعالیت شبکه را کاهش می دهند. بیشتر اطلس های بافتی حاوی اطلاعات بسیار بیشتری از صرفا sprite هستند.
بیایید نگاهی به فایل تصویری خود بیندازیم: “kenney_player.png”:
اطلس ما شامل 8 فریم است: فریم های 0 تا 3 هستند روی بالا و فریم های 4 تا 7 در زیر آمده است. به خودی خود، این برای Phaser مفید نیست، به همین دلیل است که با یک فایل JSON ارائه شده است: “kenney_player_atlas.json”.
فایل دارای یک frames
آرایه ای که حاوی اطلاعاتی در مورد هر تصویر فردی است که اطلس را می سازد.
برای استفاده از اطلس باید بدانید filename
ویژگی فریم هایی که استفاده می کنید
اضافه کردن یک بازیکن
با راهاندازی دنیای خود، میتوانیم پخشکننده را اضافه کنیم و با پلتفرمهای ما تعامل داشته باشیم. در ما create
تابع بیایید موارد زیر را اضافه کنیم:
this.player = this.physics.add.sprite(50, 300, 'player');
this.player.setBounce(0.1);
this.player.setCollideWorldBounds(true);
this.physics.add.collider(this.player, platforms);
به طور پیش فرض، اگر بخواهیم شروع کنیم، Phaser از اولین فریم اطلس استفاده می کند روی ما می توانستیم یک فریم متفاوت اضافه کنیم next
استدلال به sprite
روش با filename
ویژگی تصویر اطلس به عنوان مثال robo_player_3
.
هنگامی که بازیکن ما میپرد و فرود میآید، ویژگی Bounce کمی نشاط میافزاید. و ما بازیکن را طوری تنظیم می کنیم که با دنیای بازی ما و پلتفرم ها برخورد کند. حالا باید ببینیم بازیکنمان ایستاده است روی پلتفرم های ما:
جعبه بنفش در اطراف بازیکن ما وجود دارد زیرا debug
حالت برای موتورهای فیزیک ما فعال است. حالت اشکال زدایی مرزهایی را نشان می دهد که روش برخورد جن ما را تعیین می کند.
اضافه کردن انیمیشن ها
به یاد بیاورید که اطلس بافت ما 8 فریم برای حرکت بازیکن داشت. Phaser به ما این امکان را می دهد که انیمیشن های مبتنی بر ایجاد کنیم روی فریم های یک تصویر اطلس بیایید با استفاده از دو فریم آخر ردیف اول اطلس، یک انیمیشن برای راه رفتن ایجاد کنیم create()
تابع:
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNames('player', {
prefix: 'robo_player_',
start: 2,
end: 3,
}),
frameRate: 10,
repeat: -1
});
این key
ویژگی رشته ای است که برای پخش انیمیشن بعدا استفاده می کنیم. این frames
ویژگی آرایه ای از فریم ها در فایل JSON اطلس ما است که حاوی انیمیشن است. انیمیشن از اولین فریم آرایه شروع می شود و در آخرین فریم به پایان می رسد. ما از تابع helper استفاده می کنیم generateFrameNames()
برای ایجاد لیستی از نام فریم ها برای ما، یک تابع بسیار مفید برای فایل های اطلس بزرگ.
این frameRate
به طور پیش فرض روی 24 فریم در ثانیه است که ممکن است برای پخش کننده ما کمی سریع باشد، بنابراین آن را روی 10 تنظیم می کنیم. repeat
به -1 به Phaser می گوییم که این انیمیشن را بی نهایت اجرا کند.
بیایید انیمیشن ها را برای اسپرایت بیکارمان، اولین فریم اطلس، اضافه کنیم:
this.anims.create({
key: 'idle',
frames: ({ key: 'player', frame: 'robo_player_0' }),
frameRate: 10,
});
انیمیشن بیکار ما به سادگی یک فریم است. بیایید یک انیمیشن برای زمانی که بازیکنمان می پرد اضافه کنیم که آن هم فقط یک فریم است:
this.anims.create({
key: 'jump',
frames: ({ key: 'player', frame: 'robo_player_1' }),
frameRate: 10,
});
با اضافه شدن انیمیشن هایمان، باید کلیدهای مکان نما را فعال کنیم تا بتوانیم پخش کننده خود را حرکت دهیم:
this.cursors = this.input.keyboard.createCursorKeys();
متحرک سازی بازیکن ما
اگر بازیکن ما به چپ یا راست حرکت کند، ما می خواهیم راه رفتن. اگر فاصله یا بالا را فشار دهیم، می خواهیم پرش. در غیر این صورت، ما در خودمان می مانیم بیکار موقعیت بیایید این را در ما پیاده سازی کنیم update()
تابع:
// Control the player with left or right keys
if (this.cursors.left.isDown) {
this.player.setVelocityX(-200);
if (this.player.body.onFloor()) {
this.player.play('walk', true);
}
} else if (this.cursors.right.isDown) {
this.player.setVelocityX(200);
if (this.player.body.onFloor()) {
this.player.play('walk', true);
}
} else {
// If no keys are pressed, the player keeps still
this.player.setVelocityX(0);
// Only show the idle animation if the player is footed
// If this is not included, the player would look idle while jumping
if (this.player.body.onFloor()) {
this.player.play('idle', true);
}
}
// Player can jump while walking any direction by pressing the space bar
// or the 'UP' arrow
if ((this.cursors.space.isDown || this.cursors.up.isDown) && this.player.body.onFloor()) {
this.player.setVelocityY(-350);
this.player.play('jump', true);
}
متحرک سازی یک اسپرایت به آسانی تنظیم انیمیشن روی آن است true
. اگر دقت کرده باشید، متوجه خواهید شد که اطلس ما فقط دارای حرکات رو به راست است. اگر در حال حرکت به چپ هستیم، چه در حال راه رفتن و چه در حال پریدن، میخواهیم اسپرایت را برگردانیم روی محور x اگر به سمت راست حرکت کنیم، می خواهیم آن را به عقب برگردانیم.
با بیت کد زیر می توانیم به این هدف برسیم:
if (this.player.body.velocity.x > 0) {
this.player.setFlipX(false);
} else if (this.player.body.velocity.x < 0) {
// otherwise, make them face the other side
this.player.setFlipX(true);
}
حالا بازیکن ما به سبک انیمیشنی خوب در بازی حرکت می کند!
اضافه کردن سنبله
Phaser راههای زیادی برای دریافت اسپرایت از لایه شی در اختیار ما قرار میدهد. سنبله ها در یک آرایه در شی نقشه کاشی شده ما ذخیره می شوند. هر سنبله در صورت برخورد به بازیکن ما را مجبور می کند که از نو شروع کند. برای ما منطقی است که همه اسپک ها را در یک گروه اسپرایت قرار دهیم و بین بازیکن و گروه برخورد ایجاد کنیم. هنگامی که یک برخورد با یک گروه sprite تنظیم می شود، برای همه sprite اعمال می شود.
در create()
تابع موارد زیر را اضافه کنید:
// Create a sprite group for all spikes, set common properties to ensure that
// sprites in the group don't move via gravity or by player collisions
this.spikes = this.physics.add.group({
allowGravity: false,
immovable: true
});
// Let's get the spike objects, these are NOT sprites
// We'll create spikes in our sprite group for each object in our map
map.getObjectLayer('Spikes').objects.forEach((spike) => {
// Add new spikes to our sprite group
const spikeSprite = this.spikes.create(spike.x, spike.y + 200 - spike.height, 'spike').setOrigin(0);
});
ما باید این را دریافت کنیم:
مرز برخورد اسپایک بسیار بالاتر از خود سنبله ها است. اگر بدون تغییر باقی بماند، می تواند یک تجربه بازی بد ایجاد کند. بازیکنان بدون ضربه زدن به اسپرایت موقعیت خود را دوباره تنظیم می کنند! بیایید بدن میخ ها را طوری تنظیم کنیم که از نظر اندازه کوچکتر باشند، به خصوص ارتفاع. عوض کن forEach
با این:
map.getObjectLayer('Spikes').objects.forEach((spike) => {
const spikeSprite = this.spikes.create(spike.x, spike.y + 200 - spike.height, 'spike').setOrigin(0);
spikeSprite.body.setSize(spike.width, spike.height - 20).setOffset(0, 20);
});
برای اینکه کادر محدود کننده به درستی میخ ها را در بر بگیرد، یک افست اضافه می کنیم که با کاهش ارتفاع مطابقت دارد. اکنون اسپایک های مناسب تری داریم:
برخورد با بازیکن
اگر بازیکن ما با یک سنبله برخورد کند، موقعیت آنها تنظیم مجدد می شود. در بازیهای پلتفرم معمول است که بازیکنان انیمیشن «بازنده» داشته باشند. بیایید وقتی پخشکنندهمان ریست شد، یک انیمیشن چشمک زن اضافه کنیم. اول، در create()
بیایید برخورد را اضافه کنیم:
this.physics.add.collider(this.player, this.spikes, playerHit, null, this);
منطق بازنشانی بازیکن در این خواهد بود playerHit()
تابع. هر بار که پخش کننده با یک اسپرایت از گروه اسپایک اسپرایت برخورد کند، این تابع فراخوانی می شود. در پایان فایل موارد زیر را اضافه کنید:
function playerHit(player, spike) {
player.setVelocity(0, 0);
player.setX(50);
player.setY(300);
player.play('idle', true);
player.setAlpha(0);
let tw = this.tweens.add({
targets: player,
alpha: 1,
duration: 100,
ease: 'Linear',
repeat: 5,
});
}
خیلی چیزها در اینجا اتفاق می افتد. بیایید هر دستورالعمل را خط به خط در نظر بگیریم:
- سرعت پخش کننده را روی 0 تنظیم کنید. توقف حرکت بازیکن بسیار قابل پیش بینی تر (و ایمن تر) است. روی راه اندازی مجدد
- مختصات X و Y را در موقعیت اول بازیکن قرار دهید
- از انیمیشن بیکار استفاده کنید، درست مانند زمانی که پخش کننده شروع به کار کرد
- این
alpha
ویژگی کدورت یک sprite را کنترل می کند. این مقدار بین 0 و 1 است که در آن 0 کاملاً شفاف و 1 کاملاً مات است - یک tween ایجاد کنید – یک “انیمیشن” از ویژگی یک شی بازی. توئین به شی بازیکنی که با سنبله برخورد کرده اعمال می شود. این ویژگی آلفا را روی 1 قرار می دهد (یعنی پخش کننده ما را کاملاً قابل مشاهده می کند). این توئین 100 میلیثانیه طول میکشد و کدورت بهطور خطی افزایش مییابد، همانطور که توسط نشان داده شده است
ease
ویژگی. همچنین 5 بار تکرار می شود، به همین دلیل به نظر می رسد که چشمک می زند.
حالا بازی ما به این شکل است:
توجه داشته باشید: حتما حذف کنید debug: true
ویژگی از پیکربندی بازی قبل از اینکه آن را با دوستان به اشتراک بگذارید، هرگز حالت اشکال زدایی را در تولید رها نکنید!
نتیجه
با Tiled می توانیم دنیای بازی های دو بعدی کوچک و گسترده را طراحی کنیم. بهترین تمرین ایجاد لایههایی برای عمق در دنیای بازی ما است. سپس دنیایی را که در Tiled ساخته بودیم گرفتیم و به بازی Phaser خود اضافه کردیم.
ما لایه پلتفرم را به عنوان یک لایه استاتیک اضافه کردیم و در هنگام برخورد بازیکن، آن را غیرقابل حرکت می کنیم. سپس یک گروه اسپرایت برای اسپک ها ایجاد کردیم و یک تابع برای رسیدگی به برخورد بین هر اسپیک و بازیکن ایجاد کردیم.
علاوه بر ایجاد یک دنیای بازی پر جنب و جوش، ما یاد گرفتیم که چگونه با استفاده از یک اطلس، شخصیت خود را متحرک کنیم – یک تصویر بزرگ که حاوی چندین تصویر کوچکتر است، همراه با یک فایل JSON که جزئیات تصویر در هر فریم را نشان می دهد. ما همچنین از یک توئین برای تغییر خاصیت اسپرایت خود برای مدت زمان مشخصی استفاده کردیم.
با این تکنیک ها، این شما هستید که بهترین پلتفرمر بعدی را با Phaser بسازید!
می توانید کد منبع حاشیه نویسی بازی را مشاهده کنید اینجا.
(برچسبها به ترجمه)# روش
منتشر شده در 1403-01-25 03:39:05