После добавления скорости в мою игру, я чувствую, что мои текстуры дергаются. Я думал, что это были только мои глаза, пока я наконец не захватил это на скриншоте:
Слева - то, что рендерит в моей игре; тот, что справа - это оригинальный спрайт, оклеенный. (Это скриншот из Photoshop, увеличенный в 6 раз.)
Обратите внимание, что края имеют псевдонимы - это выглядит почти как субпиксельный рендеринг. На самом деле, если бы я не заставлял свои спрайты (которые имеют положение и скорость в виде целых чисел) рисовать, используя целочисленные значения, я бы поклялся, что MonoGame рисует со значениями с плавающей запятой. Но это не так.
Что может быть причиной того, что эти вещи выглядят размытыми? Это не происходит без применения скорости.
Если быть точным, у моего SpriteComponent
класса есть Vector2 Position
поле. Когда я звоню Draw
, я по существу использую new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))
для позиции.
У меня была ошибка , перед которой даже неподвижные объекты будут дрожать - это было из - за меня , используя прямой Position
вектор , а не округление значения ints
. Если я использую Floor
/ Ceiling
вместо округления, спрайт падает / зависает (разница в один пиксель в любом случае), но все равно рисует размыто.
Ответы:
Ну, это неудобно.
Оказывается, я рисовал не с использованием целочисленных позиций, а с плавающей точкой. Арчи указал мне правильный путь своим комментарием
@ashes999 did you debug this call and checked this.X, this.Y and this.origin?
Как только я добавил трассировку, я заметил, что ничего не прослеживается. Оказывается, мой
SpriteComponent
класс правильно использовал целочисленные значения, но моиSpriteSheetComponent
все еще использовали значения с плавающей точкой из необработанныхVector2 Position
.Хотя я не пробовал текстурную фильтрацию и фиксацию, я подозревал, что это неправильные изменения, потому что я рисовал 2D-изображение с той же шириной и высотой, что и исходное изображение (без масштабирования).
источник
XNA использует DirectX9, который использует центр пикселя в качестве своего местоположения. Это заметно при использовании перегрузок на основе Vector2 класса draw. Я считаю, что вычитание (.5, .5) должно решить вашу проблему.
Больше информации здесь.
источник
int, int
аргументами. Кроме того, все выглядит отлично, когда у меня нет движущихся объектов.SpriteComponent
имеетVector2
позицию, которая увеличивается по мере плавания в зависимости от скорости; когда я рисую, я создаю новуюVector2
с целочисленными (округленными) версиями моихposition
X и Y. Это не проблема, так как неподвижные объекты без скорости выглядят нормально.p += v
во времяUpdate
, и рендеринг сnew Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y)))
.Рендеринг ничего не знает о вашей скорости, поэтому либо позиция, размер или что-то еще, когда вы проходили через SpriteBatch.Draw, отличаются, либо до того, как вы добавили скорость, возникла ошибка. Как вы называете SpriteBatch.Draw точно?
Вы отладили этот вызов и проверили this.X, this.Y и this.origin? На что установлен this.origin? В принципе, результат рендеринга со скоростью не отличается, если этот вызов Draw одинаков.
источник
Проблема, вероятно, в том, что включена фильтрация текстур. Если вы не уверены, что это значит, рассмотрите ситуацию, когда у вас есть изображение шириной 2 пикселя: первый пиксель черный, второй пиксель белый. Если вы увеличите эту текстуру, если включена фильтрация текстур, вы увидите, что она становится размытой и что область между черным и белым пикселем использует градиентный серый цвет.
Классическим примером игр с фильтрацией и без нее является Super Mario 64, в котором была фильтрация, а в Doom - нет.
Когда вы не используете скорость, ваш Sprite, скорее всего, расположен так, что центр текстуры находится в точке выборки, которую XNA (или любой другой используемый API-интерфейс) захватывает цвет. Когда вы двигаетесь с плавающей скоростью, положение вашего спрайта изменяется, поэтому точка выборки может не совпадать непосредственно с центром пикселя, поэтому в результате получается, что цвет, который является средним из ближайших пикселей, используется для визуализации.
Вы можете проверить, включена ли фильтрация, просто отобразив ваш Sprite очень большим на экране. Если это размыто, то это проблема.
Если вы хотите иметь точную пиксельную точность при рендеринге, вам нужно иметь плавающее значение для позиции, сохраненной где-то, но использовать целочисленные значения для позиции рендеринга объекта ... или, конечно, вы можете просто отключить фильтрацию если ваша игра не нуждается в этом.
Вы также можете прочитать это .
источник
Draw
. Так что я не уверен, как это могло быть, но я попробую отрисовать в большом масштабе и посмотреть, поможет ли отключение фильтрации текстур.Попробуйте установить SamplerState в SamplerState.PointClamp в вызове SpriteBatch.Begin.
источник