Я работал над мобильными играми Java ... Лучший способ избежать GC'ing-объектов (которые, в свою очередь, должен запускать сборщик мусора в тот или иной момент, а должен убивать производительность вашей игры) просто для того, чтобы вообще не создавать их в вашем основном игровом цикле.
Не существует "чистого" способа справиться с этим, и сначала я приведу пример ...
Обычно у вас, скажем, 4 шара на экране в точках (50,25), (70,32), (16,18), (98,73). Итак, вот ваша абстракция (упрощенная для этого примера):
n = 4;
int[] { 50, 25, 70, 32, 16, 18, 98, 73 }
Вы "выталкиваете" второй шар, который исчезает, ваш int [] становится:
n = 3
int[] { 50, 25, 98, 73, 16, 18, 98, 73 }
(обратите внимание, что мы даже не заботимся об "очистке" 4-й шар (98,73), мы просто отслеживаем количество оставшихся шаров).
К сожалению, ручное отслеживание объектов. Именно так это делается в большинстве современных хорошо работающих Java-игр, выпущенных на мобильных устройствах.
Что касается строк, вот что я бы сделал:
Массив BufferedImage [10]
. BufferedImage
BufferedImage [10]
, где вы их предварительно сохранили.Это дает вам лучшее из обоих миров: вы повторно используете шрифт drawtext (...) , и вы создали ровно ноль объектов во время основного цикла (потому что вы также уклонились вызов drawtext (...) , который сам может очень дрянно генерировать, ну, ненужную чушь).
Еще одно «преимущество» этой «нулевой оценки создания объекта» заключается в том, что тщательное кэширование изображений и повторное использование шрифтов на самом деле не «ручное выделение / освобождение объекта» , это действительно просто аккуратное кеширование.
Это не «чисто», это не «хорошая практика», но именно так это делается в первоклассных мобильных играх (например, Uniwar).
И это быстро. Чертовски быстро. Быстрее, чем что-либо , связанное с созданием объекта.
PS: На самом деле, если вы внимательно посмотрите на несколько мобильных игр, вы заметите, что часто шрифты на самом деле являются не системными / Java-шрифтами, а шрифтами, идеально подходящими для каждой игры (здесь я просто привел пример того, как для кэширования системного / Java-шрифта, но, очевидно, вы также можете кэшировать / повторно использовать пиксельный / растровый шрифт).
Если вы не хотите предварительно отрисовывать текст, как было предложено, drawText
принимает любые CharSequence
, что означает, что мы можем сделать нашу собственную интеллектуальную реализацию:
final class PrefixedInt implements CharSequence {
private final int prefixLen;
private final StringBuilder buf;
private int value;
public PrefixedInt(String prefix) {
this.prefixLen = prefix.length();
this.buf = new StringBuilder(prefix);
}
private boolean hasValue(){
return buf.length() > prefixLen;
}
public void setValue(int value){
if (hasValue() && this.value == value)
return; // no change
this.value = value;
buf.setLength(prefixLen);
buf.append(value);
}
// TODO: Implement all CharSequence methods (including
// toString() for prudence) by delegating to buf
}
// Usage:
private final PrefixedInt scoreText = new PrefixedInt("Your score is: ");
...
scoreText.setValue(Score.points);
canvas.drawText(scoreText, 0, scoreText.length(), x, y, paint);
Теперь рисование счета не вызывает никаких выделений (кроме, может быть, одного или двух в начале, когда внутренний массив buf
, возможно, придется увеличить, и все, что drawText
, может быть увеличено до ).
В ситуации, когда критически важно избегать пауз сборщика мусора, вы можете использовать один трюк, чтобы намеренно запустить сборщик мусора в момент, когда вы знаете, что пауза не неважно.Например, если в конце игры используется функция showScores с интенсивным использованием мусора, пользователя не будет слишком отвлекать дополнительная задержка в 200 мс между отображением экрана счета и началом следующей игры ... так что вы можете позвонить System.gc ()
после закрашивания экрана результатов.
Но если вы прибегнете к этой уловке, вам нужно будет соблюдать осторожность и делать это только в тех местах, где пауза сборщика мусора не будет раздражать. И не делайте этого, если вы беспокоитесь о разрядке аккумулятора телефона.
И не делайте этого в многопользовательских или неинтерактивных приложениях, потому что вы, скорее всего, сделаете это приложение медленнее в целом.