এটি আমার 4 পর্বের সিরিজের শেষ অংশ যেখানে আমি শিখেছি কিভাবে Flame ইঞ্জিন দিয়ে একটি সাধারণ প্ল্যাটফর্মার গেম তৈরি করতে হয়। আমরা ইতিমধ্যে জানি কিভাবে একটি অ্যানিমেটেড প্লেয়ার চরিত্র যোগ করতে হয় যার নাম আমি দ্য বয় দিয়েছি, কীভাবে টাইলড এডিটর ব্যবহার করে একটি স্ক্রোলযোগ্য গেম লেভেল তৈরি করতে হয় এবং কীভাবে সংঘর্ষ সনাক্তকরণের সাহায্যে মাধ্যাকর্ষণ এবং জাম্পিং যোগ করতে হয় (অংশ 1 , 2 , 3 )।
এই অংশে, আমরা কয়েন যোগ করব, যা চরিত্র দ্বারা সংগ্রহ করা যেতে পারে, প্লেয়ারের কতগুলি কয়েন আছে তা প্রদর্শন করার জন্য HUD এবং একটি বিজয়ের পর্দা, যা আমরা সমস্ত কয়েন সংগ্রহ করার পরে দেখাব।
আমাদের গেমটিকে বলতে হবে কোথায় কয়েন তৈরি করতে হবে (বা সেই বিষয়ে অন্য কোনও গেম অবজেক্ট)। আপনি যেমন অনুমান করেছেন, আমরা টাইলড এডিটর ব্যবহার করব অন্য একটি অবজেক্ট লেয়ার যোগ করার জন্য, একইভাবে আমরা প্লাটফর্ম যোগ করেছি, কিন্তু দুটি পার্থক্য সহ:
প্ল্যাটফর্মগুলির সাথে, আমরা স্তরের ডেটাতে স্প্রাইট চিত্রগুলি বেক করেছি। এই পদ্ধতিটি কয়েনের জন্য খুব উপযুক্ত নয়, কারণ প্লেয়ার এটি সংগ্রহ করার পরে আমরা বস্তুটি সরাতে চাই। তাই গেমে কয়েনগুলি কোথায় উপস্থিত হওয়া উচিত তা জানতে আমরা কেবল স্পন পয়েন্ট যোগ করব এবং ফ্লেম উপাদানগুলি ব্যবহার করে রেন্ডারিং করা হবে।
প্ল্যাটফর্মের জন্য, আমরা যেকোন আকারের আয়তক্ষেত্র ব্যবহার করেছি, কিন্তু কয়েনের জন্য, আমরা 1 টালির আকারের স্পন পয়েন্ট যোগ করব। যদিও, আপনি যদি একের পর এক কয়েনের লাইন যোগ করতে চান (হাই মারিও), আপনি সহজেই গেম কোড পরিবর্তন করে এবং কয়েন অবজেক্ট যোগ করার সময় স্পন পয়েন্টের আকার বিবেচনা করে তা করতে পারেন। কিন্তু এই সিরিজের উদ্দেশ্যে, আমরা অনুমান করি যে কয়েন স্পন পয়েন্ট 1x1।
টাইলড এডিটরে আমাদের লেভেল খুলুন এবং কয়েন নামে একটি নতুন অবজেক্ট লেয়ার তৈরি করুন। তারপর আয়তক্ষেত্রাকার টুল ব্যবহার করে গেম ইঞ্জিন ব্যবহার করে কয়েনের উপাদান যোগ করার জন্য ম্যাপ জুড়ে বেশ কয়েকটি স্পন পয়েন্ট যোগ করুন। আমার স্তর এখন এই মত দেখায়:
আমার যোগ করা উচিত যে আমাদের গেমটি বেশ সহজ এবং আমরা জানি যে এই খালি আয়তক্ষেত্রগুলি গেম রানটাইমে কয়েনে পরিণত হবে। কিন্তু আমরা যদি আরও অবজেক্টের ধরন যোগ করতে চাই, তাহলে তাদের আলাদা করা কঠিন হয়ে যাবে। সৌভাগ্যবশত, টাইলডের এর জন্য একটি টুল রয়েছে, যাকে "টাইল সন্নিবেশ করান" বলা হয় যা প্রতিটি বস্তুর জন্য চাক্ষুষ সংকেত যোগ করতে পারে, কিন্তু এই চিত্রগুলি গেমে রেন্ডার করা হবে না।
ঠিক আছে, স্তরটি সংরক্ষণ করুন এবং IDE-এ ফিরে যান। আসুন /objects/
ফোল্ডারে আমাদের Coin
ক্লাস যোগ করি।
class Coin extends SpriteAnimationComponent with HasGameRef<PlatformerGame> { late final SpriteAnimation spinAnimation; late final SpriteAnimation collectAnimation; Coin(Vector2 position) : super(position: position, size: Vector2.all(48)); @override Future<void> onLoad() async { spinAnimation = SpriteAnimation.fromFrameData( game.images.fromCache(Assets.COIN), SpriteAnimationData.sequenced( amount: 4, textureSize: Vector2.all(16), stepTime: 0.12, ), ); collectAnimation = SpriteAnimation.fromFrameData( game.images.fromCache(Assets.COIN), SpriteAnimationData.range( start: 4, end: 7, amount: 8, textureSize: Vector2.all(16), stepTimes: List.filled(4, 0.12), loop: false ), ); animation = spinAnimation; final hitbox = RectangleHitbox() ..collisionType = CollisionType.passive; add(hitbox); return super.onLoad(); } }
আমাদের কাছে স্পিনিং এবং সংগ্রহের জন্য 2টি ভিন্ন অ্যানিমেশন এবং একটি RectangleHitbox
আছে, যাতে পরবর্তীতে প্লেয়ারের সাথে সংঘর্ষ হয় কিনা।
এরপর, game.dart
এ ফিরে যান এবং আমাদের কয়েন তৈরি করতে spawnObjects
পদ্ধতি পরিবর্তন করুন:
final coins = tileMap.getLayer<ObjectGroup>("Coins"); for (final coin in coins!.objects) { add(Coin(Vector2(coin.x, coin.y))); }
গেমটি চালান এবং যোগ করা কয়েন দেখুন:
coin.dart
এ ফিরে যান এবং collect
পদ্ধতি যোগ করুন:
void collect() { animation = collectAnimation; collectAnimation.onComplete = () => { removeFromParent() }; }
যখন এই পদ্ধতিটি বলা হয়, তখন আমরা স্পিনিং অ্যানিমেশনটিকে সংগ্রহকারীতে স্যুইচ করব এবং এটি শেষ হলে আমরা গেম থেকে এই উপাদানটি সরিয়ে ফেলব।
তারপর, theboy.dart
ক্লাসে যান এবং onCollisionStart
পদ্ধতি ওভাররাইড করুন:
@override void onCollisionStart(Set<Vector2> intersectionPoints, PositionComponent other) { if (other is Coin) { other.collect(); } super.onCollisionStart(intersectionPoints, other); }
কেন আমরা onCollision
এর পরিবর্তে onCollisionStart
ব্যবহার করি তা হল আমরা চাই যে সংঘর্ষ কলব্যাক শুধুমাত্র একবার ট্রিগার করুক।
দ্য বয়ের সাথে সংঘর্ষে কয়েনগুলি এখন অদৃশ্য হয়ে যাচ্ছে। সংগৃহীত কয়েনের সংখ্যা ট্র্যাক করতে ইউজার ইন্টারফেস যোগ করা যাক।
এইচইউডি, বা হেড-আপ ডিসপ্লে, হল একটি স্ট্যাটাস বার যা গেম সম্পর্কে যেকোনো তথ্য প্রদর্শন করে: হিট পয়েন্ট, বারুদ ইত্যাদি। আমরা প্রতিটি সংগৃহীত মুদ্রার জন্য একটি মুদ্রা আইকন প্রদর্শন করব।
সরলতার জন্য, আমি একটি ভেরিয়েবলে কয়েনের সংখ্যা সংরক্ষণ করতে যাচ্ছি, কিন্তু আরও জটিল ইন্টারফেসের জন্য, একটি flame_bloc প্যাকেজ ব্যবহার করার কথা বিবেচনা করুন, যা আপনাকে একটি সুবিধাজনক উপায়ে গেমের অবস্থা আপডেট এবং পর্যবেক্ষণ করতে দেয়।
একটি নতুন ক্লাস যুক্ত করুন যাতে HUD লজিক থাকবে: lib/hud.dart
class Hud extends PositionComponent with HasGameRef<PlatformerGame> { Hud() { positionType = PositionType.viewport; } void onCoinsNumberUpdated(int total) { final coin = SpriteComponent.fromImage( game.images.fromCache(Assets.HUD), position: Vector2((50 * total).toDouble(), 50), size: Vector2.all(48)); add(coin); } }
এখানে দুটি আকর্ষণীয় জিনিস:
PositionType.viewport
এ positionType
সেট করেছি। যদি আমরা তা না করি, ক্যামেরা আন্দোলনের কারণে, HUD স্তরের সাথে চলন্ত হবে।onCoinsNumberUpdated
বলা হবে। এটি পরবর্তী মুদ্রা আইকনের অফসেট গণনা করতে total
প্যারাম ব্যবহার করে এবং তারপর গণনাকৃত অবস্থানে একটি নতুন মুদ্রা স্প্রাইট যোগ করে।
এরপর, game.dart
ফাইলে ফিরে যান এবং নতুন ক্লাস ভেরিয়েবল যোগ করুন:
int _coins = 0; // Keeps track of collected coins late final Hud hud; // Reference to the HUD, to update it when the player collects a coin
তারপর onLoad
পদ্ধতির নীচে Hud
উপাদান যোগ করুন :
hud = Hud(); add(hud);
এবং একটি নতুন পদ্ধতি যোগ করুন:
void onCoinCollected() { _coins++; hud.onCoinsNumberUpdated(_coins); }
অবশেষে, Coin
collect
পদ্ধতি থেকে কল করুন :
void collect() { game.onCoinCollected(); animation = collectAnimation; collectAnimation.onComplete = () => { removeFromParent() }; }
উজ্জ্বল, আমাদের HUD এখন দেখায় আমরা কত কয়েন সংগ্রহ করেছি!
সর্বশেষ যে জিনিসটি আমি যোগ করতে চাই তা হল উইন স্ক্রীন, যা প্লেয়ারের সমস্ত কয়েন সংগ্রহ করার পরে প্রদর্শিত হবে।
PlatformerGame
ক্লাসে একটি নতুন কনস্ট যোগ করুন :
late int _totalCoins;
এবং এটিকে বরাদ্দ করুন আমাদের স্তরের কয়েনের সংখ্যা। spawnObjects
পদ্ধতির নীচে এই লাইনটি যোগ করুন :
_totalCoins = coins.objects.length;
এবং এটি onCoinCollected
পদ্ধতির নীচে যোগ করুন।
মনে রাখবেন যে আপনাকে import 'package:flutter/material.dart';
ম্যানুয়ালি
if (_coins == _totalCoins) { final text = TextComponent( text: 'U WIN!', textRenderer: TextPaint( style: TextStyle( fontSize: 200, fontWeight: FontWeight.bold, color: Colors.white, ), ), anchor: Anchor.center, position: camera.viewport.effectiveSize / 2, )..positionType = PositionType.viewport; add(text); Future.delayed(Duration(milliseconds: 200), () => { pauseEngine() }); }
এখানে, আমি চেক করি যে কয়েন কাউন্টারটি স্তরের কয়েনের সংখ্যার সমান কিনা এবং এটি গেমের স্ক্রিনের উপরে একটি উইন লেবেল যোগ করে কিনা। তারপর প্লেয়ার আন্দোলন থামাতে খেলা বিরতি. বিরাম দেওয়ার আগে লেবেল রেন্ডার করার জন্য আমি 200 ms বিলম্বও যোগ করেছি।
এটিকে ঐটির মত দেখতে হবে:
আর এটাই খেলা! অবশ্যই, এটি এখন একটি সমাপ্ত খেলার মতো দেখাচ্ছে না, তবে আমি যা ব্যাখ্যা করেছি তার সাথে আরও স্তর, শত্রু বা অন্যান্য সংগ্রহযোগ্য আইটেম যোগ করা মোটামুটি সহজ হওয়া উচিত।
এই অংশ সিরিজের সমাপ্তি.
ফ্লেম ইঞ্জিনের অফার করার জন্য আরও অনেক কিছু রয়েছে যা আমি কভার করিনি, যার মধ্যে রয়েছে পদার্থবিদ্যা ইঞ্জিন Forge2D, কণা, প্রভাব, গেম মেনু, অডিও ইত্যাদি। কিন্তু এই সিরিজটি শেষ করার পরে আমি ইঞ্জিনটি কেমন তা বুঝতে পেরেছি এবং আমি আরও জটিল গেমগুলি কীভাবে তৈরি করা যায় সে সম্পর্কে একটি ধারণা রয়েছে।
শিখা একটি শক্তিশালী কিন্তু সহজে ব্যবহার করা এবং শেখার টুল। এটি মডুলার, যা Box2D এর মতো অন্যান্য দুর্দান্ত জিনিস আনার অনুমতি দেয় এবং এটি সক্রিয়ভাবে রক্ষণাবেক্ষণ করা হয়। তবে ফ্লেমের সবচেয়ে বড় সুবিধা হল এটি ফ্লটারের উপরে তৈরি করা হয়েছে, যার মানে এটি সামান্য অতিরিক্ত কাজের সাথে মাল্টিপ্ল্যাটফর্ম সমর্থন প্রদান করে। যাইহোক, একটি ফ্লাটার এক্সটেনশন হওয়ার মানে হল যে সমস্ত ফ্লাটার সমস্যা শিখায়ও টিকে থাকে। উদাহরণস্বরূপ, Flutter-এর অ্যান্টিলিয়াসিং বাগ রেজোলিউশন ছাড়াই বেশ কয়েক বছর ধরে খোলা আছে, এবং আপনি এটি আমাদের তৈরি করা গেমেও লক্ষ্য করতে পারেন। তবে সামগ্রিকভাবে, এটি গেম তৈরির জন্য একটি দুর্দান্ত সরঞ্জাম যা চেষ্টা করার মতো।
এই টিউটোরিয়ালের জন্য সম্পূর্ণ কোড, আপনি আমার github এ খুঁজে পেতে পারেন
প্রতিটি অংশের শেষে, আমি অসাধারণ সৃষ্টিকর্তা এবং সম্পদের একটি তালিকা যোগ করব যা থেকে আমি শিখেছি।