2012-01-18 10 views
5

में 2 डी दुनिया का मॉडल कैसे करें मैं एक गेम बना रहा हूं। खेल में एक अनंत विमान शामिल है। इकाइयों को एक अलग वर्ग पर होना चाहिए, इसलिए वे एक साधारण Location { x :: Int, y :: Int }हास्केल

के साथ स्थित हो सकते हैं Unit एस के कई प्रकार हो सकते हैं। कुछ प्राणी हो सकते हैं, और कुछ पत्थर, या लकड़ी के ब्लॉक की तरह वस्तुएं हैं (वहां 2 डी Minecraft सोचें)। बहुत खाली होंगे (बस घास या जो कुछ भी)।

हास्केल में आप इसे कैसे मॉडल करेंगे? मैंने नीचे करने पर विचार किया है, लेकिन ऑब्जेक्ट बनाम प्राणी के बारे में क्या? उनके पास अलग-अलग फ़ील्ड हो सकते हैं? यूनिट पर उन सभी को सामान्यीकृत करें?

data Unit = Unit { x :: Int, y :: Int, type :: String, ... many shared properties... } 

मैं भी एक स्थान प्रकार

data Location = Location { x :: Int, y :: Int, unit :: Unit } 
-- or this 
data Location = Location { x :: Int, y :: Int } 
data Unit = Unit { unitFields... , location :: Location } 

आप किसी भी विचार है होने पर विचार किया है? ओओ भाषा में, शायद मुझे Location या Unit दूसरे से प्राप्त होता, और विशिष्ट प्रकार के यूनिट को एक-दूसरे से प्राप्त किया जाता।

एक और विचार यह है कि यह तार पर इन वस्तुओं को बहुत से भेज देगा, इसलिए मुझे क्लाइंट पर उपयोग के लिए JSON पर क्रमबद्ध करने की आवश्यकता होगी, और कई पार्सिंग बॉयलरप्लेट लिखना नहीं चाहते हैं।

+1

अपने ग्रिड के रूप में 'Data.Map.Map' का उपयोग करें। –

+0

तो क्या एक्स एक y मानचित्र में एक कुंजी से अधिक नहीं है, और इकाइयों के पास उनके विभिन्न फ़ील्ड हैं? जब ग्राहक को उन्हें भेजने के लिए समय आता है, तो क्या मुझे वहां एक नक्शा/हैश भी भेजना चाहिए? –

उत्तर

7

Location सिर्फ एक साधारण द्वि-आयामी Point प्रकार है।

मैं Unit एस को उस स्थान पर रखने के खिलाफ सलाह दूंगा; ग्रिड पर स्थितियों के बीच मानचित्र को संभालने के लिए बस Map Location Unit का उपयोग करें और क्या (यदि कुछ भी) मौजूद है।

जहां तक ​​Unit के विशिष्ट प्रकार जाओ, मैं, कम से कम, एक डेटा प्रकार में सामान्य फ़ील्ड बाहर बाँटे की सिफारिश करेंगे:

data UnitInfo = UnitInfo { ... } 

data BlockType = Grass | Wood | ... 

data Unit 
    = NPC UnitInfo AgentID 
    | Player UnitInfo PlayerID 
    | Block UnitInfo BlockType 

या इसी तरह की।

आम तौर पर, अपने स्वयं के डेटा प्रकार में फर्क पड़ता आम बातें बाहर है, और सरल रूप में डेटा रखने के लिए और संभव के रूप में "पृथक" (यानी अलग संरचनाओं दो जोड़ में तरह बातें ले जाएँ "क्या स्थान पर इस इकाई है?" , ताकि व्यक्तिगत डेटा-प्रकार "कालातीत", पुन: प्रयोज्य और यथासंभव सार के रूप में हो)।

Unit के "प्रकार" के लिए String होने के बाद हास्केल में एक मजबूत एंटीपाटरन है; यह आम तौर पर इंगित करता है कि आप गतिशील टाइपिंग या ओओपी संरचनाओं को डेटा प्रकारों के साथ कार्यान्वित करने की कोशिश कर रहे हैं, जो एक खराब फिट है।

आपका JSON आवश्यकता बातें पेचीदा हो, लेकिन this FAQ entry कैसे मुहावरे, कोई String टाइपिंग या फैंसी प्रकार स्तरीय हैक्स के साथ हास्केल में genericity इस तरह की प्राप्त करने के लिए अमूर्त के प्राथमिक इकाइयों के रूप में कार्य करता है और डेटा-प्रकार का उपयोग कर का एक अच्छा उदाहरण से पता चलता । बेशक, पूर्व कारण आपको यहां समस्याएं हैं; जेएसओएन के रूप में कार्यों को क्रमबद्ध करना मुश्किल है।

-- records containing functions to describe arbitrary behaviour; see FAQ entry 
data BlockOps = BlockOps { ... } 
data CreatureOps = CreatureOps { ... } 
data Block = Block { ... } 
data Creature = Creature { ... } 
data Unit = BlockUnit Block | CreatureUnit Creature 
newtype GameField = GameField (Map Point Unit) 

-- these types are sent over the network, and mapped *back* to the "rich" but 
-- non-transferable structures describing their behaviour; of course, this means 
-- that BlockOps and CreatureOps must contain a BlockType/CreatureType to map 
-- them back to this representation 
data BlockType = Grass | Wood | ... 
data CreatureType = ... 
blockTypes :: Map BlockType BlockOps 
creatureTypes :: Map CreatureType CreatureOps 

यह आप सभी तानाना है और नहीं है-दोहराने खुद कर सकते हैं: हालांकि, अगर आप एक प्राणी या ब्लॉक, आदि के "प्रकार" का प्रतिनिधित्व एक एडीटी से एक नक्शे के अपने वास्तविक क्रियान्वयन बनाये रख सकता है, और ठेठ सादगी को बनाए रखने और गेम राज्यों के सरल नेटवर्क हस्तांतरण की अनुमति देते हुए, सामान्य ओओपी संरचनाओं की प्रकृति।

आम तौर पर, आपको विरासत और अन्य ओओपी अवधारणाओं के संदर्भ में सोचने से बचना चाहिए; इसके बजाय, सरल संरचनाओं के कार्यों और संरचना के संदर्भ में गतिशील व्यवहार के बारे में सोचने का प्रयास करें। एक समारोह कार्यात्मक प्रोग्रामिंग में सबसे शक्तिशाली उपकरण है, इसलिए नाम, और व्यवहार के किसी भी जटिल पैटर्न का प्रतिनिधित्व कर सकता है। यह भी सबसे अच्छा है कि नेटवर्क खेलने जैसी आवश्यकताओं को आपके मूल डिजाइन को प्रभावित न करें; ऊपर दिए गए उदाहरण की तरह, इन चीजों को संचार प्रारूप जैसे बाधाओं के बजाय अभिव्यक्ति और सादगी के लिए बनाए गए डिज़ाइन के शीर्ष पर ले जाना लगभग हमेशा संभव है।

+0

अभी भी पचाने, लेकिन बहुत उपयोगी है। धन्यवाद! –

+0

एक चीज जो मुझे लूप के लिए फेंक रही है वह एक आईडी फ़ील्ड है। मैं रेडिस में राज्य भंडार करने की योजना बना रहा हूं, और जेएसओएन एपीआई को आईडी के संदर्भ में कुछ संचार की आवश्यकता होगी। क्या मुझे अपने इकाइयों में एक आईडी फ़ील्ड जोड़ना चाहिए, या इसे किसी भी तरह से जोड़ना चाहिए? उदाहरण के लिए, एक नया ग्राहक यह कहना चाहता है कि "मैं नया हूं! मुझे अपना प्लेयर ऑब्जेक्ट वापस दो!" वे अपनी आईडी चाहते हैं, लेकिन वे अपने खिलाड़ी के बारे में निर्दिष्ट करने के लिए कुछ फ़ील्ड भेज देंगे। सर्वर इसे उत्पन्न करता है और इसे वापस करता है। तो उनके ऑब्जेक्ट में एक नहीं है, जिसे मैं वापस करता हूं। –

+0

@ सेन क्लार्कहेस: हां, एक 'इंटैप यूनिट' या इकाइयों के साथ पहचानकर्ताओं को जोड़ने के लिए कुछ प्रकार शायद सबसे अच्छा विकल्प है; 'यूनिट' में पहचानकर्ता स्वयं भी उचित है। मैं ग्राहक द्वारा अपनी संरचना में निर्दिष्ट फ़ील्ड को फैक्टरिंग करने पर विचार करता हूं, और इसे 'प्राणी' में शामिल करता हूं, ताकि क्लाइंट तय कर सकें कि "हानिरहित" बिट्स उन चीज़ों से अलग हैं जिन्हें वे स्पर्श नहीं कर पाएंगे (जैसे स्वास्थ्य बिंदु); 'CreatureTemplate' कहें। – ehird