Я хочу разработать огромную карту мира; размером не менее 8000 × 6000 пикселей. Я разбил его на 10 × 10 сетку PNG-изображений размером 800 × 600 пикселей. Чтобы избежать загрузки всего в память, изображения должны быть загружены и выгружены в зависимости от положения игрока в сетке.
Например, вот игрок на позиции (3,3)
:
Когда он движется вправо (4,3)
, три изображения в крайнем левом положении освобождаются, а три изображения справа выделяются:
Вероятно, должен быть порог внутри каждой ячейки сетки, запускающий загрузку и выгрузку. Загрузка, вероятно, должна происходить в отдельном потоке.
Как мне спроектировать такую систему?
Ответы:
Здесь есть несколько проблем, которые нужно решить. Во-первых, как загружать и выгружать плитки. ContentManager по умолчанию не позволяет вам выгружать определенные фрагменты контента. Однако индивидуальная реализация этого будет:
Вторая проблема заключается в том, как решить, какие плитки загружать и выгружать. Следующее решило бы эту проблему:
Последний вопрос - как решить, когда загружать и выгружать. Это, наверное, самая легкая часть. Это можно просто сделать в методе Update () после определения положения экрана игрока:
Конечно, вам также нужно будет рисовать плитки, но с учетом tileWidth, tileHeight и массива Tiles [] это должно быть тривиально.
источник
То, что вы хотите сделать, довольно распространено. Для хорошего руководства по этой и другим распространенным методикам, посмотрите эту серию движков плиток .
Если вы не сделали ничего подобного раньше, я рекомендую посмотреть сериал. Однако, если вы хотите, вы можете получить последний учебник код. Если вы делаете позже, проверьте метод розыгрыша.
Короче говоря, вам нужно найти свои минимальные и максимальные X / Y очки вокруг игрока. Когда у вас есть это, вы просто просматриваете каждый из них и рисуете эту плитку.
Как видите, многое происходит. Вам нужна камера, которая будет создавать вашу матрицу, вам нужно преобразовать ваше текущее местоположение в пикселях в индекс плитки, вы найдете ваши минимальные / максимальные точки (я немного добавляю к своему МАКСУ, чтобы он немного выходил за пределы видимого экрана) ), а затем вы можете нарисовать его.
Я действительно предлагаю посмотреть серию уроков. Он освещает вашу текущую проблему, как создать редактор плиток, держать игрока в пределах границ, спрайтовую анимацию, взаимодействие с ИИ и т.д. ...
На стороне записки TiledLib имеет эту встроенную. Вы можете изучить их код , а также.
источник
Я работал над чем-то очень похожим для моего текущего проекта. Это краткое изложение того, как я это делаю, с некоторыми примечаниями о том, как сделать вещи немного проще для себя.
Для меня первая проблема состояла в том, чтобы разбить мир на более мелкие куски, которые бы подходили для загрузки и выгрузки на лету. Поскольку вы используете карту на основе плитки, этот шаг становится значительно проще. Вместо того, чтобы учитывать положение каждого 3D-объекта на уровне, у вас уже есть свой уровень, аккуратно разделенный на плитки. Это позволяет вам просто разбить мир на X на Y фрагментов плитки и загрузить их.
Вы захотите сделать это автоматически, а не вручную. Поскольку вы используете XNA, у вас есть возможность использовать конвейер содержимого с настраиваемым экспортером для содержимого вашего уровня. Если вы не знаете какой-либо способ запуска процесса экспорта без перекомпиляции, я бы честно рекомендовал это сделать. Хотя компиляция C # не так медленна, как в C ++, вам все равно не нужно загружать Visual Studio и перекомпилировать игру каждый раз, когда вы вносите небольшие изменения в карту.
Еще одна важная вещь - убедиться, что вы используете хорошее соглашение об именах для файлов, содержащих чанки вашего уровня. Вы хотите знать, что хотите загрузить или выгрузить блок C, а затем сгенерировать имя файла, которое вам нужно загрузить, чтобы сделать это во время выполнения. Наконец, подумайте о любых мелочах, которые могут помочь вам в будущем. Очень приятно иметь возможность изменить размер блока, выполнить реэкспорт и сразу же увидеть его влияние на производительность.
Во время выполнения это все еще довольно просто. Вам понадобится какой-нибудь способ асинхронной загрузки и выгрузки блоков, но это сильно зависит от того, как работает ваша игра или движок. Ваше второе изображение в точности правильное - вам нужно определить, какие чанки должны быть загружены или выгружены, и сделать соответствующие запросы, если это не так. В зависимости от того, сколько чанков вы загрузили за один раз, вы можете делать это всякий раз, когда игрок пересекает границу от одного чанка к другому. В конце концов, в любом случае, вы хотите убедиться, что загружено достаточно, чтобы даже в наихудшее (разумное) время загрузки блок все еще загружался, прежде чем игрок сможет его увидеть. Возможно, вы захотите много играть с этим числом, пока не получите хороший баланс между производительностью и потреблением памяти.
Что касается фактической архитектуры, вы захотите абстрагировать процесс фактической загрузки и выгрузки данных из памяти от процесса определения того, что следует загружать / выгружать. Для вашей первой итерации я бы даже не беспокоился о производительности загрузки / выгрузки, а просто получил бы простейшую вещь, которая могла бы работать, и гарантировал, что вы генерируете соответствующие запросы в подходящее время. После этого вы можете посмотреть, как оптимизировать загрузку, чтобы свести к минимуму мусор.
Я столкнулся с множеством дополнительных сложностей из-за движка, который использовал, но это довольно специфично для конкретной реализации. Если у вас есть какие-либо вопросы о том, что я сделал, пожалуйста, прокомментируйте, и я сделаю все возможное, чтобы помочь.
источник