यह मेरी 4 भाग श्रृंखला का अंतिम भाग है जहाँ मैं सीखता हूँ कि फ्लेम इंजन के साथ एक सरल प्लेटफ़ॉर्मर गेम कैसे बनाया जाता है। हम पहले से ही जानते हैं कि एक एनिमेटेड प्लेयर चरित्र को कैसे जोड़ा जाए, जिसका नाम मैंने द बॉय रखा है, टाइल वाले संपादक का उपयोग करके स्क्रॉल करने योग्य गेम स्तर कैसे बनाया जाए, और टक्कर का पता लगाने (भाग 1 , 2 , 3 ) की मदद से ग्रेविटी और जंपिंग कैसे जोड़ें।
इस भाग में, हम सिक्के जोड़ने जा रहे हैं, जिन्हें चरित्र द्वारा एकत्र किया जा सकता है, एचयूडी यह प्रदर्शित करने के लिए कि खिलाड़ी के पास कितने सिक्के हैं, और एक जीत स्क्रीन, जिसे हम सभी सिक्कों को एकत्र करने के बाद दिखाने जा रहे हैं।
हमें खेल को यह बताने की जरूरत है कि सिक्कों को कहां फेंकना है (या उस मामले के लिए कोई अन्य खेल वस्तु)। जैसा कि आपने अनुमान लगाया होगा, हम एक अन्य ऑब्जेक्ट परत जोड़ने के लिए टाइल वाले संपादक का उपयोग करने जा रहे हैं, ठीक उसी तरह जैसे हमने प्लेटफ़ॉर्म जोड़े, लेकिन दो अंतरों के साथ:
प्लेटफ़ॉर्म के साथ, हमने स्प्राइट इमेज को लेवल डेटा में बेक किया। यह विधि सिक्कों के लिए बहुत उपयुक्त नहीं है, क्योंकि एक बार जब खिलाड़ी इसे एकत्र कर लेता है तो हम वस्तु को हटाना चाहते हैं। इसलिए हम केवल स्पॉन पॉइंट जोड़ेंगे, यह जानने के लिए कि गेम में सिक्के कहाँ दिखाई देने चाहिए, और फ्लेम घटकों का उपयोग करके रेंडरिंग की जाएगी।
प्लेटफार्मों के लिए, हम किसी भी आकार के आयतों का उपयोग करते हैं, लेकिन सिक्कों के लिए, हम 1 टाइल के आकार के स्पॉन पॉइंट जोड़ेंगे। हालाँकि, यदि आप सिक्कों की एक पंक्ति को एक के बाद एक (हाय मारियो) जोड़ना चाहते हैं, तो आप गेम कोड को संशोधित करके और सिक्का वस्तुओं को जोड़ते समय स्पॉन पॉइंट के आकार पर विचार करके आसानी से ऐसा कर सकते हैं। लेकिन इस श्रृंखला के प्रयोजनों के लिए, हम मानते हैं कि सिक्के स्पॉन पॉइंट 1x1 हैं।
हमारे स्तर को टाइल वाले संपादक में खोलें और सिक्के नामक एक नई वस्तु परत बनाएं। फिर आयताकार उपकरण का उपयोग करके गेम इंजन का उपयोग करके सिक्का घटकों को जोड़ने के लिए मानचित्र पर कई स्पॉन पॉइंट जोड़ें। मेरा स्तर अब इस तरह दिखता है:
मुझे यह जोड़ना चाहिए कि हमारा खेल अपेक्षाकृत सरल है और हम जानते हैं कि ये खाली आयत खेल के समय में सिक्कों में बदल जाएंगे। लेकिन अगर हम और अधिक वस्तु प्रकार जोड़ना चाहते हैं, तो उन्हें अलग करना कठिन हो जाएगा। सौभाग्य से, टाइल के पास इसके लिए एक उपकरण है, जिसे "इन्सर्ट टाइल" कहा जाता है, जो हर वस्तु के लिए दृश्य संकेत जोड़ सकता है, लेकिन इन छवियों को खेल में प्रस्तुत नहीं किया जाएगा।
ठीक है, लेवल सेव करें और IDE पर वापस लौटें। चलिए अपने Coin
क्लास को /objects/
फोल्डर में जोड़ते हैं।
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
उपयोग क्यों करते हैं इसका कारण यह है कि हम चाहते हैं कि टक्कर कॉलबैक केवल एक बार ट्रिगर हो।
द बॉय से टकराने पर अब सिक्के गायब हो रहे हैं। आइए एकत्र किए गए सिक्कों की संख्या को ट्रैक करने के लिए यूजर इंटरफेस जोड़ें।
HUD, या हेड-अप डिस्प्ले, बस एक स्टेटस बार है जो गेम के बारे में कोई भी जानकारी प्रदर्शित करता है: हिट पॉइंट, बारूद, आदि। हम प्रत्येक एकत्रित सिक्के के लिए एक सिक्का आइकन प्रदर्शित करने वाले हैं।
सादगी के लिए, मैं एक वेरिएबल में सिक्कों की संख्या को स्टोर करने जा रहा हूं, लेकिन अधिक जटिल इंटरफेस के लिए, एक 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
को PositionType.viewport
पर सेट करते हैं। अगर हम ऐसा नहीं करते हैं, तो कैमरा मूवमेंट के कारण, 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 एमएस की देरी भी जोड़ी है, ताकि लेबल रुकने से पहले प्रस्तुत किया जा सके।
इसे ऐसा दिखना चाहिए:
और वह खेल है! बेशक, यह अब एक समाप्त खेल की तरह नहीं दिखता है, लेकिन मैंने जो कुछ भी समझाया है, उसमें अधिक स्तर, दुश्मन या अन्य संग्रहणीय वस्तुओं को जोड़ना काफी आसान होना चाहिए।
यह भाग श्रृंखला का समापन करता है।
फ्लेम इंजन के पास पेश करने के लिए और भी बहुत कुछ है जिसे मैंने कवर नहीं किया, जिसमें भौतिकी इंजन फोर्ज2डी, पार्टिकल्स, इफेक्ट्स, गेम मेन्यू, ऑडियो आदि शामिल हैं। अधिक जटिल गेम बनाने के तरीके की समझ है।
फ्लेम एक शक्तिशाली लेकिन उपयोग में आसान और सीखने वाला उपकरण है। यह मॉड्यूलर है, जो Box2D जैसी अन्य अच्छी चीजें लाने की अनुमति देता है और इसे सक्रिय रूप से बनाए रखा जाता है। लेकिन फ्लेम का एक सबसे बड़ा फायदा यह है कि यह फ्लटर के ऊपर बनाया गया है, जिसका अर्थ है कि यह थोड़े अतिरिक्त काम के साथ मल्टीप्लाफ्फ़्ट समर्थन प्रदान करता है। हालाँकि, स्पंदन विस्तार होने का अर्थ है कि फ़्लटर की सभी समस्याएँ लौ में भी बनी रहती हैं। उदाहरण के लिए, फ़्लटर का एंटीअलियासिंग बग कई वर्षों से बिना किसी समाधान के खुला है, और आप इसे हमारे द्वारा बनाए गए गेम में भी देख सकते हैं। लेकिन कुल मिलाकर, यह गेम बनाने के लिए एक बढ़िया उपकरण है जो आजमाने लायक है।
इस ट्यूटोरियल का पूरा कोड, आप मेरे जीथब में पा सकते हैं
हर भाग के अंत में, मैं बेहतरीन क्रिएटर्स और संसाधनों की एक सूची जोड़ूंगा जिनसे मैंने सीखा है।