#c# #monogame
Вопрос:
Я пытаюсь сделать rougelike на C #, используя Monogame и RogueSharp.
вот часть кода, который у меня есть в Draw ()
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
int sizeOfSprites = 64;
float scale = .25f;
foreach (Cell cell in _map.GetAllCells())
{
// error in the line below
Microsoft.Xna.Framework.Rectangle position = new Microsoft.Xna.Framework.Rectangle(cell.X * sizeOfSprites * scale, cell.Y * sizeOfSprites * scale);
if (cell.IsWalkable)
{
_spriteBatch.Draw(floorSprite, position, null, Color.White, 0f, new Vector2(scale, scale), 0.0f, 0f);
}
else
{
_spriteBatch.Draw(wallSprite, position, null, Color.White, 0f, new Vector2(scale, scale), 0.0f, 0f);
}
}
_spriteBatch.End();
base.Draw(gameTime);
}
ВОЗВРАТ:
Аргумент 2: не удается преобразовать из ‘float’ в ‘Microsoft.Xna.Framework.Точка’
Аргумент 1: не удается преобразовать из ‘float’ в ‘Microsoft.Xna.Framework.Точка’
Ответ №1:
Rectangle
Конструктор либо принимает (Point location, Point size)
, либо (Int32 x, Int32 y, Int32 width, Int32 height)
нет (Float, Float)
(что бы это вообще значило?) — см. Документы.
Итак, здесь два вопроса:
- Вам нужно четыре значения, чтобы однозначно указать прямоугольник в 2D-пространстве, а не два.
Rectangle
делает это, используя X и Y верхнего левого угла, а также ширину и высоту. Rectangle
Конструктор ожидает, что эти значения будут целыми числами, а не плавающими.
Глядя на ваш код, я предполагаю, что вы хотите создать прямоугольник, длина которого sizeOfSprites * scale
равна длине обеих сторон, и в этом случае вам нужно будет указать размер следующим образом:
int scaledSize = (int)(sizeOfSprites * scale);
Microsoft.Xna.Framework.Rectangle position = new Microsoft.Xna.Framework.Rectangle(
cell.X * scaledSize,
cell.Y * scaledSize,
scaledSize,
scaledSize
);
Я заметил Cell
, что также имеет целочисленные координаты, и вы используете только числа с плавающей запятой для части 0.25, поэтому вы можете просто сохранить размер как целое число. Если вы не собираетесь позже делать эти переменные динамическими, самым быстрым способом было бы использовать const int scaledSize = 16;
в первую очередь.
Комментарии:
1. Теперь это работает! тысяча!
2.
(int)Math.Floor()
Вызов является избыточным. Используйте только приведение(int)
. Отрицательные позиции находятся за пределами экрана и не имеют значения. В играх скорость выполнения, менее 16 мс, имеет первостепенное значение. Субпиксельная точность необходима только для сглаживания, а не для общего рисования.
Ответ №2:
Вы хотите свести к минимуму операции, выполняемые в Draw()
. Draw()
это блокирующий вызов, означающий, что процесс будет ждать (т.Е. Зависать) его завершения.
Я бы предложил предварительное мультиплицирование sizeOfSprites * scale
как константу, если оно не изменится:
const int SIZE = 16; // 64 * .25
Microsoft.Xna.Framework.Rectangle position = new Microsoft.Xna.Framework.Rectangle(
(int)(cell.X * SIZE), (int)(cell.Y * SIZE), SIZE, SIZE);
);
Для простых игр ограничение по времени в 16.6666667 мс (60 кадров в секунду) на кадр не является проблемой, но по мере роста игр они могут достигать предела.
Я не выступаю за чрезмерную оптимизацию. Скорее всего, в этом случае на процессоре X86 / X64 поиск в памяти может быть кэширован, но как насчет мобильных или консольных приложений, где структура / расположение кэша могут отличаться?
Выполнение ненужных вызовов функций только увеличивает бюджет времени.( Floor()
и Round()
)
Каждый вызов функции обязательно добавляет контекст текущего состояния, копируя все переданные переменные и отображая состояние контекста результаты. Много ненужных обращений к памяти.