2

如果这是不正确的地方,请道歉;我是一个非常新的爱好者程序员。

我目前在业余时间从事一个小型自上而下的射击游戏,只不过是一个简单的自我驱动项目来学习和娱乐。我使用 C# 和 XNA 作为框架,我试图通过选择 gameObjects 添加到库存中来为游戏添加一些变化。

目前我有一个List<GamePlayObjects>“WorldObjects”,我有一个ObjectManager类来管理所有对象的更新、碰撞和绘制功能,我对我目前所拥有的感到满意。在与 GamePlayObject 碰撞时(例如小行星爆炸后的一小块铁矿石),它会从主列表“WorldObjects”中删除该对象并将其添加到另一个名为List<GamePlayObjects> inventory

现在我要做的是在屏幕上绘制一个小区域,其中包含项目精灵和我收集的该项目的总数。我对绘图方面并不真正感兴趣,更多的是从库存中提取数据。

我已经阅读了几个线程,可能HashSet用于从我的库存中获取唯一项目,然后从 中提取每个项目的总数HashSet,但我现在很难理解这一点,因此我访问这里寻求帮助。

我的代码示例以及我试图实现的目标。

我有一个我所有 WorldObjects 的列表,每个世界对象都是一个类,其中包含与该 worlObject 相关的所有内容。

private List<GamePlayObject> gameObjects = new List<GamePlayObject>();

当一个对象,让我们说“玩家”与另一个对象“铁矿石”发生碰撞时,我从以下位置移除 IronOre 世界对象:

private List<GamePlayObject> gameObjects = new List<GamePlayObject>();

并将其添加到一个名为 Inventory 的新列表中

private List<GamePlayObject> playerInventory = new List<GamePlayObject>();

现在,随着越来越多的对象被收集并添加到我的库存中,我想提取信息并将有关我的库存的信息显示到屏幕上。

例如,在我的屏幕右侧,我想显示我在我的库存中拥有的项目列表以及每个项目的总量,这些数据应该从我的库存列表中获取。

所以它可能看起来像这样:

Iron Ore x 3
Steel x 10
Gold x 18
Uranium x 12
4

4 回答 4

1

现在我要做的是在屏幕上绘制一个小区域,其中包含项目精灵和我收集的该项目的总数。我对绘图方面并不真正感兴趣,更多的是从库存中提取数据。

听起来您想使用 linq 计数。

InventoryObjects.Count(inventoryObject => inventoryObject.Type == ObjectTypes.Asteroid);
WorldObjects.Count(worldObject => worldObject.Type == ObjectTypes.Asteroid);

你可以把它想象成 SQL

SELECT COUNT([dbo].[World Objects].[Object]) WHERE [dbo].[World Objects].[Type]='Asteroid'

但是,如果您想提取一个项目并将其添加到另一个列表中,您应该听取 Reed Copsey 的建议。


编辑

所以假设你有一个Player类,那么它的结构可能是这样的,

Public Class Player {
    public List<GamePlayObject> Inventory {get; set;}
}

你也有一个World类,也许它有类似的,

Public Class World {
    public List<GamePlayObject> Objects {get; set;}
}

GamePlayObject可能看起来像这样,

Public Class GamePlayObject {
    public ObjectType Type {get; set;}
}

所以假设你已经初始化了你的世界并且它有几个对象,并且你知道你想从所说的世界中删除哪个对象。就资源和优化而言,这肯定不是最好的方法,(这将是 Reed Copsey 的答案派上用场的地方)但是,你可以......

var targetObject = World.Where(gamePlayObject => (DesiredConditions))
World.Objects.Remove(targetObject);
Player.Inventory.Add(targetObject);

哪里DesiredConditions可能是这样的gamePlayObject.IsCollidedWith

完成此操作后,您可以查询Player' 库存。

var IronCount = Player.Inventory.Count(gamePlayObject => gamePlayObject.Type == ObjectType.Iron);

希望这可以解决问题。

于 2013-01-25T16:39:42.197 回答
1

您可以使用List<T>, 并使用List<T>.Remove. 但是,使用List<T>这样的问题是Remove必须搜索整个列表,一次一个项目,才能找到要删除的项目。这也将导致出现大副本,因为您删除的元素之后的元素需要在内部数组中向下移动。

但是,像 之类的集合HashSet<T>可以非常快速地找到并删除项目,而无需副本。这需要您的类型 implement GetHashCode,但如果您总是想要独特的项目,效果会更好。

对于您的两个收藏,一个潜在的选择是使用 a Dictionary<GamePlayObject, int>,这将允许您快速查找并更改该类型对象在世界和库存中的数量。同样,这将要求您的GamePlayObject类覆盖object.GetHashCodeand object.Equals,并实现IEquatable<GamePlayObject>

于 2013-01-25T16:39:59.137 回答
0

It sounds to me that you probably should not be using a list. Meaning why iterate to and from one list to the order when what it seems like is you need to keep counts of the different gameplay objects. I am presuming you have a fixed set of game play objects and they are uniquely named. You can have a fixed dictionaryof elements where you add or subtract counts meaning you would probably be doing something like this gameObjects ["ironore"]++ or playerInventory ["ironore"]--. And then you can use to linq to show all keys whose values are greater than zero.

于 2013-01-25T20:23:58.233 回答
0

这听起来像是一个用 linq 解决的好问题!如果您是 linq 新手,那么我会为您提供一个很好的资源 - 101 个 linq 示例:http ://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

针对您的特定问题!由于List<T>implements IEnumerable<T>,您可以在其上运行 linq 查询。最有趣的是分组运算符。

如果您的GamePlayObject班级有一个Type属性,那么您可以执行以下操作:

var items = from o in playerInventory
    group o by o.Type into g
    select new { ItemType = g.Key, Items = g };
foreach (var g in items)
{
    string s = string.Format("{0} x {1}", g.ItemType.ToString(), g.Items.Count());
    //now do whatever you want with the string, which will contain, eg, Iron Ore x 3
}
于 2013-01-25T18:24:57.917 回答