Поворот холста и представление растрового изображения

1

Я пытаюсь сделать игру, в которой планета была бы в центре экрана пользователя и очень медленно вращалась, как планета.. Итак, сначала я решила проверить это, если все будет работать нормально, а это не так... Я получаю простое изображение "планеты", подобное этому:

Bitmap image = BitmapFactory.decodeResource(getResources(),R.mipmap.totone);

У меня также есть переменная, которая хранит угол. Затем в функции рисования я просто вращаю холст, рисую свою планету (теперь повернутую) и поворачиваю холст обратно. как это:

//the planet image is 512x512px
canvas.rotate(ang,256,256); //256, 256 is the center of rotation
canvas.drawBitmap(image, 0,0, null);
canvas.rotate(-ang,256,256); //rotate back

Я понятия не имею, почему, но похоже, что когда изображение поворачивается на 90 и 270 градусов, скорость игры немного замедляется? Я сделал небольшой подарок, чтобы показать проблему. Частота кадров идеально 60, но затем она падает на 50ish в течение пары миллисекунд без причины? Чем это вызвано? Я попытался изменить целевую частоту кадров потока на 30, и похоже, что никаких падений частоты кадров в секунду не произошло... Так что, вероятно, это проблема производительности. Обратите внимание, что я пытался вращать растровое изображение, используя самые разные методы, эффект падения fps все тот же.

Gif

Теги:
frame-rate
rotation
bitmap

1 ответ

0

Скорее всего, это взаимодействие между фиксированной частотой обновления экрана устройства и небольшим изменением времени рисования растрового изображения под определенными углами.

Я предполагаю, что вы увеличиваете ang на постоянную величину в onDraw(). Этот факт можно использовать для объяснения резкого изменения скорости вращения.

ОБЪЯСНЕНИЕ

Ваше устройство обновляет свой экран с частотой 60 Гц. Это означает, что onDraw() Гц в идеальных условиях: примерно раз в 16,7 мс.

Предположим, что для выполнения onDraw() требуется около 15 мс. Осталось 1,7 мс; все в порядке! Вы получаете приятное, плавное вращение с частотой 60 Гц.

Затем предположим, что при определенных значениях ang onDraw() занимает немного больше времени; скажем, 18 мс. (Я буду размышлять о том, почему время выполнения drawBitmap() изменяется в зависимости от угла в данный момент. А сейчас давайте посмотрим, что происходит с этим временем рисования 18 мс.)

В идеале onDraw() Гц. Но теперь ты слишком долго; более 1 цикла. Композитору теперь нужно удалить кадр из вашего приложения, потому что вы не могли предоставить его достаточно быстро! Таким образом, вместо выполнения onDraw() каждые 16,7 мс, теперь он может вызываться только каждые 33,4 мс.

Другими словами, аппаратное обеспечение экрана обновляется с постоянной скоростью, и когда ваш onDraw() пересекает порог в 16,7 мс, частота обновления уменьшается ровно вдвое.

На это намекает ваш GIF. Отображаемая частота смены кадров составляет от 60 до 51, но мне кажется довольно ясным, что фактическая частота вращения падает почти точно на 50%. Я подозреваю, что расхождение просто связано с тем, как вы рассчитали отображаемую частоту кадров.

СПЕКУЛЯЦИЯ ПО ВАРИАЦИИ В drawBitmap() ВРЕМЯ ИСПОЛНЕНИЯ

Может быть производительность кэширования процессора. При определенных углах поворота графическая логика могла бы получать доступ к битовой памяти способом, который не идеален для логики кэша/предварительного просмотра L1. Другими словами, вы могли бы получить много промахов кэша на этих углах.

РЕКОМЕНДУЕМЫЕ ИСПРАВЛЕНИЯ ДЛЯ ВОСПРОИЗВОДИТЕЛЬНОСТИ

  1. Используйте более быстрый графический конвейер, такой как OpenGL, и/или:
  2. Базовый ang на время взлома (uptimeMillis()) вместо приращения. Вы по-прежнему будете сбрасывать кадры, но кажущаяся скорость вращения будет исправлена.
  3. Если вы хотите сойти с ума, вы можете предоставить второе растровое изображение, предварительно повернутое на 90 градусов к первому, и использовать это растровое изображение для рисования, которое происходит под углами, близкими к 90/270 градусам. Если я прав насчет промахов кеша, это уменьшит проблему.
  • 0
    @ Бумага А? Нет? Нет кости?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню