2011-06-13 52 views
5

每隔一段時間,我都喜歡從我的其他項目中休息一下,試圖製作一個經典的冒險基於文本的遊戲(這次是Python,這次)是一個有趣的項目,但我總是有設計問題實施項目系統。在面向對象的遊戲中管理物品

我想在遊戲的項目從一個基站Item類下降,含有一些屬性,每一個項具有,如損壞和重量。當我嘗試向這些項目添加一些功能時,我的問題就開始了。當一件物品的傷害超過閾值時,它應該被銷燬。這就是我的問題:我不知道如何實現這個目標。

由於del self不會爲一百萬個不同的原因,(編輯工作。我有意地設置使用「刪除」作爲我知道錯了東西,我知道垃圾收集是什麼,以及它是如何不我想要什麼。)我該怎麼做(和其他類似的任務)?每件商品是否應該包含某種對它的容器的引用(玩家,我猜),並且「請求」自己被刪除?

首先想到的是一個包含遊戲中每個項目的大字典,每個對象都有一個對這個列表的引用,並且都擁有並知道它是自己的唯一ID。我根本不喜歡這個解決方案,我不認爲這是完全正確的方法。有人有任何建議嗎?

編輯:我看到很多人認爲我很擔心垃圾收集。我所說的不是垃圾收集,而是實際從遊戲中移除對象。我不確定哪些對象應該啓動刪除等。

回答

0

假設您在使用該項目時調用某個方法,則始終可以返回一個指示其是否損壞的布爾值。

1

你在混淆「毀滅」觀念的兩個含義。該項目應該在「遊戲玩法」意義上被銷燬。讓垃圾收集器擔心什麼時候將其作爲對象來銷燬它。

誰對該商品有參考?也許玩家擁有它的存貨,或者它在遊戲房間。無論哪種情況,您的庫存或房間對象都知道該物品。告訴他們物品已經被銷燬(在遊戲玩法上)並讓他們處理。也許他們現在會提到一個「破碎」的物品。也許他們會跟蹤它,但不會顯示給用戶。也許他們會刪除對它的所有引用,在這種情況下,內存中的對象很快就會被刪除。

面向對象編程的優點在於,您可以將這些過程從項目本身抽象出來:將消息傳遞給需要知道的人,並讓他們以自己的方式實現對項目的銷燬意味着什麼。

+0

我不糊塗。我明白兩者的區別。我使用'del'示例來展示什麼_doesn't工作_,以及我不想要的東西。我現在意識到這只是造成混亂。 – 2011-06-13 03:54:28

-1

在第一:我沒有任何蟒蛇的經驗,所以覺得這個更普遍的方式

您的項目應該既不知道也不關心......你的項目應該有,說的接口是什麼並且銷燬。容器和關心的事情是可以被摧毀,可以利用該接口的其它對象

該銷燬的接口可能對消費對象來註冊一個回調或事件的一些選項,觸發時該項目被摧毀

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

我會讓你的對象保持其所有的父母的參考。然後,當它被銷燬時,它會通知其父母。如果你已經使用了一個事件系統,這應該與遊戲的其他部分很好地集成。

避免強制父母在引用被刪除或添加時顯式通知對象的好方法是使用某種代理。 Python支持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

這是一個非常棒的方法,其中包含Signal類的其他用例。 – Jared 2016-02-04 01:05:12