- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试找到一种方法来存储对大约 7000 万个 texture2d/vector2 集的引用。为了澄清一点,我需要能够使用 100 个左右的 texture2d,然后为它们分配一个 vector2 XY 值,以获得大约有 7000 万个图 block 的图 block map 。我只需要一个 texture2d 与 vector2 对应的引用。我将动态地/程序地生成瓦片/坐标集我现在只需要一种方法来存储所有它们,这不会炸毁我的 ram。我尝试使用以 vector2 为键、以 texture2d 为值的字典,但它因 OutOfMemoryException 而让我丧命。所以我随后尝试了 Wintellect Power Collections 并使用了他们的 MultiDictionary。但是,即使我将 texture2d 指定为唯一的键并使用 vector2 作为该键的 7000 万个值,它仍然会因相同的异常而终止。
所以我不知道现在应该如何进行。我只需要存储引用以供以后访问。我并没有试图将它们绘制到屏幕或类似的东西上,所以我不明白为什么仅仅为了字典就需要 700mb 的内存。事后我才意识到我一直在让这些词典自行调整大小。这可能是问题所在吗?
我希望这是足够具体的,我已经整夜未眠,所以我现在不会打扰清理和发布任何代码。如果您认为我的代码而不是我的方法是罪魁祸首,请告诉我,我会为您发布。期待您的回答。
编辑:好的,这是我现在正在使用的代码。我稍微清理了一下,但我知道它不是最好看的代码。如果您发现任何明显的问题或什至效率低下,我很乐意听到这些问题。只是不要打击我,因为这是我第一次使用 c# :)
当 WorldWidth 和 WorldHeight 分别设置为 8400 时,7000 万个图 block 开始发挥作用。
class MapMaker
{
SpriteSheet spriteSheetMap;
SpriteSheet spriteSheet1;
SpriteSheet spriteSheet2;
SpriteSheet spriteSheet3;
SpriteSheet spriteSheet4;
SpriteSheet spriteSheet5;
SpriteSheet spriteSheet6;
SpriteSheet spriteSheet7;
SpriteSheet spriteSheet8;
SpriteSheet spriteSheet9;
SpriteSheet spriteSheet10;
SpriteSheet spriteSheet11;
SpriteSheet spriteSheet12;
SpriteSheet spriteSheet13;
SpriteSheet spriteSheet14;
SpriteSheet spriteSheet15;
SpriteSheet spriteSheet16;
SpriteSheet spriteSheet17;
SpriteSheet spriteSheet18;
SpriteSheet spriteSheet19;
SpriteSheet spriteSheet20;
SpriteSheet spriteSheet21;
SpriteSheet spriteSheet22;
SpriteSheet spriteSheet23;
Random rnd = new Random();
int WorldWidth = 250;
int WorldHeight = 250;
List<int> sprites = new List<int>();
int[][] TheGrid = new int[10][];
int posX = 0, posY = 0, gridX = 0, gridY = 0;
Dictionary<int, Texture2D> TileStorage = new Dictionary<int, Texture2D>();
Dictionary<Vector2, Texture2D> SineSaver = new Dictionary<Vector2, Texture2D>();
public void loadTiles(ContentManager Content)
{
spriteSheetMap = new SpriteSheet();
spriteSheet1 = new SpriteSheet();
spriteSheet2 = new SpriteSheet();
spriteSheet3 = new SpriteSheet();
spriteSheet4 = new SpriteSheet();
spriteSheet5 = new SpriteSheet();
spriteSheet6 = new SpriteSheet();
spriteSheet7 = new SpriteSheet();
spriteSheet8 = new SpriteSheet();
spriteSheet9 = new SpriteSheet();
spriteSheet10 = new SpriteSheet();
spriteSheet11 = new SpriteSheet();
spriteSheet12 = new SpriteSheet();
spriteSheet13 = new SpriteSheet();
spriteSheet14 = new SpriteSheet();
spriteSheet15 = new SpriteSheet();
spriteSheet16 = new SpriteSheet();
spriteSheet17 = new SpriteSheet();
spriteSheet18 = new SpriteSheet();
spriteSheet19 = new SpriteSheet();
spriteSheet20 = new SpriteSheet();
spriteSheet21 = new SpriteSheet();
spriteSheet22 = new SpriteSheet();
spriteSheet23 = new SpriteSheet();
spriteSheetMap.Map = Content.Load<Dictionary<string, Rectangle>>("Tiles/Map");
TileStorage.Add(0, spriteSheet1.Sheet = Content.Load<Texture2D>("test2"));
TileStorage.Add(1, spriteSheet1.Sheet = Content.Load<Texture2D>("Tiles/Amethyst"));
TileStorage.Add(2, spriteSheet2.Sheet = Content.Load<Texture2D>("Tiles/Amethyst_N"));
TileStorage.Add(3, spriteSheet3.Sheet = Content.Load<Texture2D>("Tiles/Aquamarine"));
TileStorage.Add(4, spriteSheet4.Sheet = Content.Load<Texture2D>("Tiles/Aquamarine_N"));
TileStorage.Add(5, spriteSheet5.Sheet = Content.Load<Texture2D>("Tiles/Citrine"));
TileStorage.Add(6, spriteSheet6.Sheet = Content.Load<Texture2D>("Tiles/Citrine_N"));
TileStorage.Add(7, spriteSheet7.Sheet = Content.Load<Texture2D>("Tiles/Diamond"));
TileStorage.Add(8, spriteSheet8.Sheet = Content.Load<Texture2D>("Tiles/Diamond_N"));
TileStorage.Add(9, spriteSheet9.Sheet = Content.Load<Texture2D>("Tiles/Dirt1"));
TileStorage.Add(10, spriteSheet10.Sheet = Content.Load<Texture2D>("Tiles/Dirt2"));
TileStorage.Add(11, spriteSheet11.Sheet = Content.Load<Texture2D>("Tiles/Emerald"));
TileStorage.Add(12, spriteSheet12.Sheet = Content.Load<Texture2D>("Tiles/Emerald_N"));
TileStorage.Add(13, spriteSheet13.Sheet = Content.Load<Texture2D>("Tiles/Peridot"));
TileStorage.Add(14, spriteSheet14.Sheet = Content.Load<Texture2D>("Tiles/Peridot_N"));
TileStorage.Add(15, spriteSheet15.Sheet = Content.Load<Texture2D>("Tiles/Ruby"));
TileStorage.Add(16, spriteSheet16.Sheet = Content.Load<Texture2D>("Tiles/Ruby_N"));
TileStorage.Add(17, spriteSheet17.Sheet = Content.Load<Texture2D>("Tiles/Sand"));
TileStorage.Add(18, spriteSheet18.Sheet = Content.Load<Texture2D>("Tiles/Sapphire"));
TileStorage.Add(19, spriteSheet19.Sheet = Content.Load<Texture2D>("Tiles/Stone1"));
TileStorage.Add(20, spriteSheet20.Sheet = Content.Load<Texture2D>("Tiles/Stone2"));
TileStorage.Add(21, spriteSheet21.Sheet = Content.Load<Texture2D>("Tiles/Stone3"));
TileStorage.Add(22, spriteSheet22.Sheet = Content.Load<Texture2D>("Tiles/Topaz"));
TileStorage.Add(23, spriteSheet23.Sheet = Content.Load<Texture2D>("Tiles/Topaz_N"));
CreateMapKey();
}
private void CreateMapKey()
{
TheGrid[0] = new int[] { 0, 3, 14, 25, 36, 47, 58, 69, 80, 91 };
TheGrid[1] = new int[] { 12, 4, 15, 26, 37, 48, 59, 70, 81, 92 };
TheGrid[2] = new int[] { 23, 5, 16, 27, 38, 49, 60, 71, 82, 93 };
TheGrid[3] = new int[] { 34, 6, 17, 28, 39, 50, 61, 72, 83, 94 };
TheGrid[4] = new int[] { 45, 7, 18, 29, 40, 51, 62, 73, 84, 95 };
TheGrid[5] = new int[] { 56, 8, 19, 30, 41, 52, 63, 74, 85, 96 };
TheGrid[6] = new int[] { 67, 9, 20, 31, 42, 53, 64, 75, 86, 97 };
TheGrid[7] = new int[] { 78, 10, 21, 32, 43, 54, 65, 76, 87, 98 };
TheGrid[8] = new int[] { 89, 11, 22, 33, 44, 55, 66, 77, 88, 99 };
TheGrid[9] = new int[] { 1, 13, 24, 35, 46, 57, 68, 79, 90, 2 };
BaseTileset();
}
private void BaseTileset()
{
int hillLocation = 300, hillWidth = 120, hillHeight = 10;
for (int i = 0; i < WorldHeight * WorldWidth; i++)
{
if (i % WorldHeight * 5 == 0)
{
hillLocation += rnd.Next(-40, 40);
hillWidth += rnd.Next(-10, 10);
if (hillWidth == 0) { hillWidth = 1; }
hillHeight += rnd.Next(-5, 5);
}
Vector2 position = new Vector2(posX, posY);
Texture2D tile = TileStorage[9];
double sine = hillLocation + Math.Sin(posX / hillWidth) * hillHeight;
double cosine = hillLocation + Math.Cos(posX / hillWidth) * hillHeight / 2;
if (posY <= sine || posY < cosine)
{
tile = null;
}
if (tile != null)
{
SineSaver.Add(position, tile);
sprites.Add(TheGrid[gridY][gridX]);
}
posY += 20;
if (posY > (WorldHeight - 1) * 20) { posY = 0; posX += 20; }
gridX = posX / 20 % 10;
gridY = posY / 20 % 10;
}
}
public void DrawLevel(SpriteBatch spriteBatch, GraphicsDeviceManager graphics)
{
spriteBatch.Begin();
int i = 0;
foreach (KeyValuePair<Vector2, Texture2D> entry in SineSaver)
{
spriteBatch.Draw(entry.Value, entry.Key, spriteSheetMap[sprites[i]], Color.White);
i++;
}
spriteBatch.End();
}
}
最佳答案
我建议研究享元模式 ( http://en.wikipedia.org/wiki/Flyweight_pattern )
如果您知道每个图 block 的宽度和高度,则可以计算每个图 block 的 Vector2 位置 - 它是基于索引确定的,因此不需要存储。每个图 block 所需的唯一数据是一个用于索引的 int 和一个可以小到单个字节的“类型”标识符。
7000 万 * (4 + 1 ) 字节 = 333.786011 兆字节
编辑 1: 稍微详细说明..
假设我们有一个 3x3 的图 block 网格 - 我们知道总共有 9 个图 block ,所以我们为每个图 block 分配一个索引 0-8..
Tile[] tiles = new Tile[9]
for (int i = 0; i < 9; i++)
tiles[i].Index = i;
知道每个网格行横跨 3 个图 block ,每列向下 3 个图 block ,我们可以使用模和除运算符来获取任何图 block 索引的行和列...
Tile tile = getSomeTile();
int column = tile.Index % 3; // = column 1
int row = tile.Index \ 3; // = row 1 - tile 4 is in the middle :)
知道每个图 block 的宽度和高度(比如说 10 个像素),我们现在可以计算图 block 4 的确切位置:
Vector2 position = new Vector2
{
X = 10f * column,
Y = 10f * row
};
编辑 2: 回应评论...
您的 Tile 对象需要包含一个类型标识符,如下所示:
struct Tile
{
int Index; // The tiles index in the map [0 - 70 million].
byte TileTypeId; // An identifier for a tile type.
}
class TileType // This is the flyweight object..
{
Texture2D Texture; // Gets the texture reference for the tile type...
// any other information about the tile ie. is it collidable? is it water? etc..
}
然后在绘制瓷砖时......
Tile tile = tiles[someIndex];
TileType type = tileTypes[tile.TileTypeId]; // tileTypes could be a dictionary...
Vector2 position = this.CalculateTilePosition(tile.Index); // Calculate the position as above...
spriteBatch.Draw(type.Texture, position);
编辑 3: 作为对序列化评论的回应......
序列化 tile grid 应该很容易,它只是一个很长的字节序列。假设瓦片是按顺序存储的,我们已经知道瓦片索引号,因此不需要将其存储在文件中。
回到 3x3 网格示例:
Example binary data file:
0xF4 0x15 0x5A 0xB5 0x00 0x61 0xEE 0xA3 0x39
BinaryReader reader = OpenSomeBinaryFile();
for (int i = 0; i < (3 * 3); i++)
tiles[i] = new Tile { Index = i, TileTypeId= reader.ReadByte() };
// easy to optimize by reading bigger binary chunks (say an Int64) and bit shifting to get the individual bytes...
// If you happen to have reasonbly large series of tiles with the same type id (byte), the file will be quite well suited to compression on disk, which is a bonus :)
关于c# - 我需要一个可以引用超过 7000 万个 texture2d/vector2 对象集的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6279519/
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我试图用这种形式简单地获取数字 28 integer+space+integer+integer+space+integer我试过这个正则表达式 \\s\\d\\d\\s 但我得到了两个数字11 和
最近一直在学习D语言。我一直对运行时感到困惑。 从我能收集到的关于它的信息中,(这不是很多)我知道它是一种有助于 D 的一些特性的运行时。像垃圾收集一样,它与您自己的程序一起运行。但是既然 D 是编译
想问一下这两个正则表达式有区别吗? \d\d\d 与 \d{3} 我已经在我的本地机器上使用 Java 和 Windows 操作系统对此进行了测试,两者都工作正常并且结果相同。但是,当在 linux
我正在学习 Go,而且我坚持使用 Go 之旅(exercise-stringer.go:https://tour.golang.org/methods/7)。 这是一些代码: type IPAddr
我在Java正则表达式中发现了一段令我困惑的代码: Pattern.compile( "J.*\\d[0-35-9]-\\d\\d-\\d\\d" ); 要编译的字符串是: String string
我在 ruby 代码上偶然发现了这个。我知道\d{4})\/(\d\d)\/(\d\d)\/(.*)/是什么意思,但是\1-\2-\3-\4 是什么意思? 最佳答案 \1-\2-\3-\4 是 b
我一直在努力解决这个问题,这让我很恼火。我了解 D 运行时库。它是什么,它做什么。我也明白你可以在没有它的情况下编译 D 应用程序。就像 XoMB 所做的那样。好吧,XoMB 定义了自己的运行时,但是
我有两个列表列表,子列表代表路径。我想找到所有路径。 List> pathList1 List> pathList2 当然是天真的解决方案: List> result = new ArrayList>
我需要使用 Regex 格式化一个字符串,该字符串包含数字、字母 a-z 和 A-Z,同时还包含破折号和空格。 从用户输入我有02-219 8 53 24 输出应该是022 198 53 24 我正在
目标是达到与this C++ example相同的效果: 避免创建临时文件。我曾尝试将 C++ 示例翻译为 D,但没有成功。我也尝试过不同的方法。 import std.datetime : benc
tl;dr:你好吗perfect forwarding在 D? 该链接有一个很好的解释,但例如,假设我有这个方法: void foo(T)(in int a, out int b, ref int c
有什么方法可以在 D 中使用abstract auto 函数吗? 如果我声明一个类如下: class MyClass { abstract auto foo(); } 我收到以下错误: mai
有没有人为内存中重叠的数组切片实现交集?算法在没有重叠时返回 []。 当 pretty-print (使用重叠缩进)内存中重叠的数组切片时,我想要这个。 最佳答案 如果您确定它们是数组,那么只需取 p
我已经开始学习 D,但我在使用 Andrei Alexandrescu 所著的 The D Programming Language 一书中提供的示例时遇到了一些麻烦。由于 int 和 ulong 类
如何创建一个不可变的类? 我的目标是创建一个实例始终不可变的类。现在我只是用不可变的方法和构造函数创建了一个“可变”类。我将其称为 mData,m 表示可变。然后我创建一个别名 alias immut
不久前我买了《The D Programming Language》。好书,很有教育意义。但是,我在尝试编译书中列出的语言功能时遇到了麻烦:扩展函数。 在这本书中,Andrei 写了任何可以像这样调用
我在 D http://www.digitalmars.com/d/2.0/lazy-evaluation.html 中找到了函数参数的惰性求值示例 我想知道如何在 D 中实现可能的无限数据结构,就像
这个问题在这里已经有了答案: 12 年前关闭。 Possible Duplicate: Could anyone explain these undefined behaviors (i = i++
当前是否可以跨模块扫描/查询/迭代具有某些属性的所有函数(或类)? 例如: source/packageA/something.d: @sillyWalk(10) void doSomething()
我是一名优秀的程序员,十分优秀!