2011-06-13 11 views
5

हर बार एक बार जब मैं एक और मजेदार प्रोजेक्ट के रूप में क्लासिक एडवेंचर टेक्स्ट-आधारित-गेम (पायथन में, इस बार) बनाने की कोशिश करने के लिए अपनी अन्य परियोजनाओं से ब्रेक लेना चाहता हूं, लेकिन मेरे पास हमेशा आइटम सिस्टम को लागू करने के लिए डिज़ाइन समस्याएं होती हैं Iकिसी ऑब्जेक्ट ओरिएंटेड गेम में आइटम प्रबंधित करना

मैं खेल के आइटमों को एक आधार Item कक्षा से उतरने के लिए चाहता हूं, जिसमें कुछ आइटम हैं, जिनमें हर वस्तु है, जैसे क्षति और वजन। मेरी समस्या तब शुरू होती है जब मैं इन वस्तुओं में कुछ कार्यक्षमता जोड़ने की कोशिश करता हूं। जब किसी वस्तु का नुकसान एक सीमा से पहले हो जाता है, तो इसे नष्ट किया जाना चाहिए। और मेरी समस्या है: मुझे वास्तव में यह नहीं पता कि इसे कैसे पूरा किया जाए।

के बाद से del self एक लाख विभिन्न कारणों से, (संपादन के लिए काम नहीं करेगा:। मैं जानबूझकर 'डेल' के उपयोग के कुछ मुझे पता है कि गलत है के रूप में उपलब्ध कराने हूँ मुझे पता है कि कचरा संग्रहण है, और यह कैसे नहीं है मैं क्या चाहता हूं।) मुझे यह कैसे करना चाहिए (और अन्य समान कार्य)? क्या प्रत्येक आइटम में इसके कंटेनर (प्लेयर, मुझे लगता है) के किसी प्रकार का संदर्भ होना चाहिए और खुद को हटाने के लिए 'पूछें'?

पहली बात जो दिमाग में आती है वह एक बड़ा शब्दकोश है जिसमें गेम में प्रत्येक आइटम होता है, और प्रत्येक ऑब्जेक्ट का इस सूची का संदर्भ होगा, और दोनों के पास यह अपनी अनूठी आईडी है और पता है। मुझे यह समाधान बिल्कुल पसंद नहीं है और मुझे नहीं लगता कि यह बिल्कुल सही तरीका है। क्या किसी के पास कोई सुझाव है?

संपादित करें: मुझे बहुत से लोग यह सोच रहे हैं कि मैं कचरा संग्रह के बारे में चिंतित हूं। मैं किस बारे में बात कर रहा हूं कचरा संग्रह नहीं है, लेकिन वास्तव में गेमप्ले से ऑब्जेक्ट को हटा रहा है। मुझे यकीन नहीं है कि किस वस्तु को हटाने की शुरुआत की जानी चाहिए, आदि

उत्तर

0

मान लें कि आइटम का उपयोग होने पर आप एक विधि को कॉल करते हैं, तो आप हमेशा एक बूलियन मान वापस कर सकते हैं जो यह इंगित करता है कि यह टूटा हुआ है या नहीं।

1

आप "नष्ट करने" विचार के दो अर्थों को स्वीकार कर रहे हैं। आइटम को "गेमप्ले" भावना में नष्ट किया जाना चाहिए। कचरा कलेक्टर को किसी ऑब्जेक्ट के रूप में इसे नष्ट करने के बारे में चिंता करने दें।

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

ऑब्जेक्ट उन्मुख प्रोग्रामिंग की सुंदरता यह है कि आप इन प्रक्रियाओं को आइटम से दूर कर सकते हैं: संदेशों को पास करने के लिए जिन्हें भी जानना है, उन्हें भेज दें, और उन्हें नष्ट करने के लिए इसका अर्थ क्या है ।

+0

मैं उलझन में नहीं हूँ। मैं दोनों के बीच का अंतर समझता हूं। मैं यह दिखाने के लिए 'डेल' उदाहरण का उपयोग कर रहा था कि क्या काम नहीं करता है, और मैं क्या _didn't_ चाहता हूं। मुझे अब एहसास है कि यह सिर्फ भ्रम का कारण बनता है। –

-1
पहली बार में

: मैं किसी भी अजगर अनुभव की जरूरत नहीं है, इसलिए एक अधिक सामान्य तरीके से इस बारे में सोचते हैं

अपने मद न पता है या परवाह ... अपने आइटम एक अंतरफलक है कि कहते हैं होना चाहिए यह कुछ है चाहिए destroyable।कंटेनर और अन्य वस्तुओं है कि चीजें हैं जो नष्ट किया जा सकता, कि इंटरफ़ेस का उपयोग कर सकते के बारे में परवाह

destroyable इंटरफेस लेने वाली वस्तुओं एक कॉलबैक या घटना रजिस्टर करने के लिए के लिए कुछ विकल्प हो सकता है, शुरू हो रहा है जब आइटम को नष्ट कर दिया जाता है

0

कैसे:

from collections import defaultdict 

_items = defaultdict(set) 
_owner = {} 

class CanHaveItems(object): 
    @property 
    def items(self): 
     return iter(_items[self]) 
    def take(self, item): 
     item.change_owner(self) 
    def lose(self, item): 
     """ local cleanup """ 

class _nobody(CanHaveItems): 
    def __repr__(self): 
     return '_nobody' 
_nobody = _nobody() 

class Destroyed(object): 
    def __repr__(self): 
     return 'This is an ex-item!' 

class Item(object): 
    def __new__(cls, *a, **k): 
     self = object.__new__(cls) 
     _owner[self] = _nobody 
     _items[_nobody].add(self) 
     self._damage = .0 
     return self 
    def destroy(self): 
     self.change_owner(_nobody) 
     self.__class__ = Destroyed 
    @property 
    def damage(self): 
     return self._damage 
    @damage.setter 
    def damage(self, value): 
     self._damage = value 
     if self._damage >= 1.: 
      self.destroy() 
    def change_owner(self, new_owner): 
     old_owner = _owner[self] 
     old_owner.lose(self) 
     _items[old_owner].discard(self) 
     _owner[self] = new_owner 
     _items[new_owner].add(self) 


class Ball(Item): 
    def __init__(self, color): 
     self.color = color 
    def __repr__(self): 
     return 'Ball(%s)' % self.color 

class Player(CanHaveItems): 
    def __init__(self, name): 
     self.name = name 
    def __repr__(self): 
     return 'Player(%s)' % self.name 

ball = Ball('red') 
ball = Ball('blue') 

joe = Player('joe') 
jim = Player('jim') 

print list(joe.items), ':', list(jim.items) 
joe.take(ball) 
print list(joe.items), ':', list(jim.items) 
jim.take(ball) 
print list(joe.items), ':', list(jim.items) 

print ball, ':', _owner[ball], ':', list(jim.items) 
ball.damage += 2 
print ball, ':', _owner[ball], ':', list(jim.items) 

print _items, ':', _owner 
2

मैं आपका ऑब्जेक्ट अपने सभी माता-पिता का संदर्भ रखूंगा। फिर, जब इसे नष्ट किया जाना चाहिए, तो यह अपने माता-पिता को सूचित करेगा। यदि आप पहले से ही एक ईवेंट सिस्टम का उपयोग कर रहे हैं, तो इसे शेष खेल के साथ अच्छी तरह से एकीकृत करना चाहिए।

जब भी संदर्भ ड्रॉप या जोड़ा जाता है तो वस्तु को स्पष्ट रूप से सूचित करने के लिए अपने माता-पिता को मजबूर करने से बचने का एक अच्छा तरीका किसी प्रकार की प्रॉक्सी का उपयोग करना है। पायथन properties का समर्थन करता है जो self.weapon = Weapon() जैसे कोड के लिए अनुमति देता है ताकि वास्तव में उपयोगकर्ता को परिभाषित फ़ंक्शन में नए हथियार पर हथियार विशेषता सेट करने का कर्तव्य सौंप दिया जा सके।

class Weapon(object): 
    def __init__(self, name): 
     self.name = name 
     self.parent = None 
    def destroy(self): 
     if self.parent: 
      self.parent.weaponDestroyed() 

def WeaponRef(): 
    def getWeapon(self): 
     return self._weapon 
    def setWeapon(self, newWeapon): 
     if newWeapon == None: #ensure that this is a valid weapon 
      delWeapon(self) 
      return 
     if hasattr(self, "weapon"): #remove old weapon's reference to us 
      self._weapon.parent = None 
     self._weapon = newWeapon 
     newWeapon.parent = self 
    def delWeapon(self): 
     if hasattr(self, "weapon"): 
      self._weapon.parent = None 
      del self._weapon 
    return property(getWeapon, setWeapon, delWeapon) 

class Parent(object): 
    weapon = WeaponRef() 
    def __init__(self, name, weapon=None): 
     self.name = name 
     self.weapon = weapon 
    def weaponDestroyed(self): 
     print "%s deleting reference to %s" %(self.name, self.weapon.name) 
     del self.weapon 


w1 = Weapon("weapon 1") 
w2 = Weapon("weapon 2") 
w3 = Weapon("weapon 3") 
p1 = Parent("parent 1", w1) 
p2 = Parent("parent 2") 

w1.destroy() 

p2.weapon = w2 
w2.destroy() 

p2.weapon = w3 
w3.destroy() 

अब आप सूची प्रणाली है, जहां एक खिलाड़ी 1 से अधिक हथियार और उनमें से किसी एक हो सकता है किसी भी समय नष्ट हो सकता है किसी प्रकार का कर रहे हैं:

यहाँ गुणों का उपयोग करके कुछ उदाहरण कोड है , तो आपको अपनी खुद की संग्रह कक्षा लिखनी होगी।
ऐसा ही कुछ के लिए, बस यह ध्यान रखें कि x[2] कॉल x.__getitem__(2), x[2] = 5 कॉल x.__setitem__(2, 5) और del x[2] कॉल x.__delitem__(2)

1

एक विकल्प एक संकेत प्रणाली

सबसे पहले उपयोग करने के लिए किया जाएगा, हम एक पुन: प्रयोज्य वर्ग देता है कि आप एक सिग्नल परिभाषित करें

class Signal(object): 
    def __init__(self): 
     self._handlers = [] 

    def connect(self, handler): 
     self._handlers.append(handler) 

    def fire(self, *args): 
     for handler in self._handlers: 
      handler(*args) 

आपकी आइटम क्लास इस सिग्नल का उपयोग एक नष्ट सिग्नल बनाने के लिए करती है जो अन्य कक्षाएं सुन सकती हैं।

class Item(object): 
    def __init__(self): 
     self.destroyed = Signal() 

    def destroy(self): 
     self.destroyed.fire(self) 

और सूची आइटम से संकेत को सुनता है और इसकी आंतरिक स्थिति को अद्यतन करता तदनुसार

class Inventory(object): 
    def __init__(self): 
     self._items = [] 

    def add(self, item): 
     item.destroyed.connect(self.on_destroyed) 
     self._items.add(item) 

    def on_destroyed(self, item): 
     self._items.remove(item) 
+0

सिग्नल क्लास के लिए अतिरिक्त उपयोग मामलों के साथ यह एक शानदार दृष्टिकोण है। – Jared

संबंधित मुद्दे