2

我正在为游戏开发玩家库存系统。

我有一个 struct Slot,它有一个 List<Loot> 集合,表示其中允许使用哪些类型的项目。抽象类Loot是所有可抢劫物品的子类 - 即:将是Slot结构的有效内容值。

我想表达的是,一个Slot可以限制它可以包含哪些Loot子类。例如,如果Slot代表一个弹药容器,我希望它只包含作为弹药容器的Loot子类,例如“Quivers”和“Shot Pouches”(它将沿线某处子类化Container )。

战利品类

public abstract class Loot : GameEntity, ILootable
{
    public int MaxUnitsPerStack { get; set; }
    public int MaxUnitsCarriable { get; set; }
    public int MaxUnitsOwnable { get; set; }

    public void Stack() { }
    public void Split() { }
    public void Scrap() { }
}

容器类

public abstract class Container : Loot
{
    public List<Slot> Slots { get; set; }

    public Container(int slots)
    {
        this.Slots = new List<Slot>(slots);
    }
}

插槽结构

public struct Slot
{
    public Loot Content;
    public int Count;
    public List<Loot> ExclusiveLootTypes;

    public Slot(Loot[] exclusiveLootTypes)
    {
        this.Content = null;
        this.Count = 0;

        List<Loot> newList;
        if (exclusiveLootTypes.Count() > 0)
        {
            newList = new List<Loot>(exclusiveLootTypes.Count());
            foreach (Loot l in exclusiveLootTypes)
            {
                newList.Add(l);
            }
        }
        else { newList = new List<Loot>(); }
        this.ExclusiveLootTypes = newList;
    }
}

玩家库存

public struct PlayerInventory
{
    static Dictionary<Slot, string> Slots;

    static void Main()
    {
        Slots = new Dictionary<Slot, string>();

        /* Add a bunch of slots */
        Slots.Add(new Slot(/* I don't know the
                              syntax for this:
                              Quiver, Backpack */), "Backpack"); // Container
    }

}

我不知道如何在PlayerInventory类的 Main 方法中的Slot构造函数调用中为 Loot 子类提供参数。

我希望这很清楚。提前致谢。

编辑

我能够使用 David Sieler 的方法和一些反射来解决这个问题(我的意思是让它编译)。

插槽结构


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

    public struct Slot
    {
        private Loot _content;
        private int _count;
        public List ExclusiveLootTypes;

        public Loot Content
        {
            get { return _content; }
            private set
            {
                if ((ExclusiveLootTypes.Contains(value.GetType())) && (value.GetType().IsSubclassOf(Type.GetType("Loot"))))
                {
                    _content = value;
                }
            }
        }

        public int Count
        {
            get { return _count; }
            set { _count = value; }
        }

        public Slot(params Type[] exclusiveLootTypes)
        {
            this._content = null;
            this._count = 0;

            List newList;
            if (exclusiveLootTypes.Count() > 0)
            {
                newList = new List(exclusiveLootTypes.Count());
                foreach (Type l in exclusiveLootTypes)
                {
                    newList.Add(l);
                }
            }
            else { newList = new List(); }
            this.ExclusiveLootTypes = newList;
        }
    }

PlayerInventory 调用 Slot 构造函数


Slots.Add(new Slot(typeof(Backpack)));

再次感谢大家的讨论。

4

4 回答 4

2

您可能会发现params在 Slot 构造函数的定义中使用它更容易:

Slot(params Loot[] exclusiveLootTypes)

这将允许您将其称为:

new Slot(lootItem1, lootItem2, lootItem2 /*...etc*/);

否则,您需要创建一个数组并将其传入。

于 2009-12-13T00:39:52.350 回答
2

听起来您的对象设计需要稍作调整。

如果战利品的类型也是接口怎么办,例如,所有弹药战利品都继承自 IAmmoContainer。

然后你可以传入 IAmmoContainer 类型来限制插槽。

public class Quiver : Container, IAmmoContainer
public class ShotPouch : Container, IAmmoContainer
// ...
new Slot(typeof(IAmmoContainer))

编辑

根据评论中的讨论,我将如何设计这个系统。

Loot课很好。它代表了战利品等级的基础。

然后为项目可以占用的“槽”定义接口。例如:

public class LongSword : Loot, IRightHandItem
public class ShortSword : Loot, IRightHandItem, ILeftHandItem

然后 PlayerInventory 类具有“插槽”作为属性,这些属性被限制为适当的类型。

public class PlayerInventory
{
    public List<IRightHandItem> RightHandSlot { get; private set; }
    public List<ILeftHandItem> LeftHandSlot { get; private set; }
    // etc...
}
于 2009-12-13T01:10:01.080 回答
1

一种方法是将对象数组传递Type给 Slot 构造函数:

public Slot(Type[] exclusiveLootTypes) {
    // be sure and check that each Type is a subtype of Loot!
}

// Construction looks like:
new Slot(new[] {GetType(AmmoContainer), GetType(GemContainer) /* or whatever */});

然后编写一个属性设置器来Content检查分配对象的类型,如果该类型不包含在 ExclusiveLootTypes 中,则会发出某种错误信号。

于 2009-12-13T00:43:05.720 回答
1

并结合之前使用参数的建议,您可以使用 LINQ 扩展一步将参数转换为列表:

public Slot(params Type[] exclusiveLootTypes)
{
    this.Content = null;
    this.Count = 0;

    this.ExclusiveLootTypes = exclusiveLootTypes.ToList();
}
于 2009-12-13T00:53:30.470 回答