...
В копилку Игрока
Использование преобразования спрайтов может отрицательно сказаться на реалистичности некоторых элементов графики игры. Например, пиратский корабль в игре High Seas 2 показывает лицевую и обратную стороны паруса, а также тень, отбрасываемую кораблем. Хотя эти детали незначительны, они теряются, если использовать описанную выше методику (рис. 17.2). В результате пиратский корабль выглядит менее реалистично.
Основной недостаток использования преобразований спрайтов – снижение скорости при снижении размера. Для того чтобы преобразовать спрайт, требуется немного больше времени, чем просто вывести его на экран, однако при этом выигрыш в размере значителен.
Приемы оптимизации Java-кода
Пока мы обсудили оптимизацию, не рассматривая конкретные примеры. В последующих разделах я продемонстрирую вам методы написания кода, которые вы можете применять в разрабатываемых играх для увеличения быстродействия. Большая часть приводимого кода позволяет увеличить скорость выполнения приложения, а не сократить необходимый объем памяти.
Вы не должны задумываться об оптимизации скорости каждого бита создаваемого вами кода. Некоторые части кода вызываются чаще других. Зная это, вы должны оптимизировать именно такие фрагменты. Помните, что нереально оптимизировать каждую строку медленного кода игры. Ваша цель – оптимизировать те фрагменты, в которых это можно сделать, не прикладывая много усилий. Чуть позже вы узнаете, как выделить фрагменты кода, которым следует уделить особое внимание при оптимизации.
...
Совет Разработчику
Не думайте об оптимизации игрового кода по скорости или размеру до тех пор, пока игра не заработала. Оптимизированный код зачастую может содержать хитрые алгоритмы, сложные для отладки. Следовательно, всегда следует начинать с работающего кода, когда приходит время внедрять приемы оптимизации.
Компиляция без отладочной информации
Возможно, самая простая оптимизация не подразумевает программирования вообще. Я говорю об исключении отладочной информации, которая по умолчанию включается в состав классов при использовании стандартного компилятора (javac). По умолчанию Java-компилятор включает дополнительную отладочную информацию в классы файлов, которая помогает отладчикам анализировать и идентифицировать код. По окончании отладки игры важно отключить отладочную информацию в компиляторе, используя ключ – g: none. Ниже приведен пример использования этого ключа:
javac -g:none MyMIDlet.java
К счастью, все примеры в этой книге, расположенные на прилагаемом компакт-диске, откомпилированы с выключенной отладочной информацией. Вам придется отключить опцию – g: none, если вы планируете отладить какой-либо из примеров.
Исключение ненужных вычислений
Следующая методика оптимизации – это простой прием программирования, исключающий ненужные вычисления. Такие вычисления проблематичны, поскольку они занимают время процессора. Ниже приведен пример кода, который выполняет ненужные вычисления:
for (int i = 0; i < size(); i++) a = (b + c)/i;
Несмотря на то что сложение (b + c) – это весьма эффективный фрагмент кода, лучше вынести его за пределы цикла:
int tmp = b + c;
for (int i = 0; i < size(); i++)
a = tmp/i;
Такое простое изменение может иметь значительный эффект, в зависимости от числа повторов выполнения цикла. Есть еще один прием оптимизации, который вы, вероятно, могли упустить. Обратите внимание на вызов метода size(). С точки зрения производительности, лучше сохранить возвращаемое им значение в отдельную переменную, чтобы избежать вызова метода при каждом повторе цикла:
int s = size();
int tmp = b + c;
for (int i = 0; i < s; i++)
a = tmp/i;
Исключение общих выражений
Говоря об оптимизации выражений, рассмотрим еще одну проблему, которая снижает скорость выполнения кода: общие выражения. Вы можете часто использовать выражения в коде, не осознавая последствий. В разгар работы можно использовать одно и то же выражение повторно, вместо того чтобы вычислить его значение однажды и присвоить переменной:
b = Math.abs(a) * c; d = e / (Math.abs(a) + b);
Повторный вызов метода abs() – трудоемкая операция, вместо этого лучше вызвать метод однократно, а результат сохранить во временной переменной:
int tmp = Math.abs(a);
b = tmp * c;
d = e / (tmp + b);
Преимущества локальных переменных
Возможно, вы не задумывались, но Java-коду требуется больше времени обратиться к переменным класса, чем к локальным переменным. Это связано с тем, как осуществляется доступ к двум различным типам данных. На практике следует использовать локальные переменные, а не переменные класса, если вопрос производительности критичен. Например, если внутри цикла происходит постоянное обращение к переменной класса, то целесообразно присвоить локальной переменной значение переменной класса и внутри цикла работать с локальной переменной. Ниже приведен пример кода:
for (int i = 0; i < 1000; i++) a = obj.b * i;
Читать дальше
Конец ознакомительного отрывка
Купить книгу