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

А теперь о деталях

Во первых я решил уменьшить масштаб всех объектов в 2 раза. Благодаря этому, на игровом поле теперь может вместиться больше врагов, и башня игрока теперь не занимает треть экрана, что очень радует. Да, сложность попадания увеличилась, но вскоре я планирую добавить небольшой расчет траектории выстрела, чтобы было видно в каком направлении полетит шар. Слева вы видите как сделано сейчас, а справа - как это было.

Анимация и взрывы

Решил наконец-то заняться анимациями. В принципе, ничего сложного там нет, но на данный момент требуется оптимизация данного процесса, ибо создавать каждый раз описание анимации для нового объекта не дело. Но мне просто хотелось посмотреть на результат и принцип работы, поэтому пока что так.
Первый спрайт с анимацией был нарисован во время передвижения в автобусе. По мне так, получилось достаточно забавно. Хоть и всего 4 кадра, но смотрится весьма эффектно. После добавления нужного класса для взрыва, я сделал чтобы робот при смерти не просто исчезал, а именно взрывался. Получилось весьма не плохо. А после того, как я добавил взрывы при попадании ракеты в башню, то игра достаточно оживилась и теперь смотрится куда лучше. Ах да, я еще нарисовал новый снаряд для роботов. Наслаждайтесь скриншотом:

Про улучшения в ИИ

Старый ИИ предвещал много проблем, потому что все враги были настырными и шли напролом и им было пофиг на то, что их пытались оттолкнуть другие роботы или шар при столкновении. Но после небольшой модификации ИИ движения все стало очень красиво. По скольку я не могу тут поделиться скриншотами, ибо ничего не понятно будет, я просто поделюсь парой строчек кода. Как было сделано:
if (d > unit.info.AttackRadius)
      body.setLinearVelocity(unit.info.Speed * dx, unit.info.Speed * dy);
else
      body.setLinearVelocity(0.0f, 0.0f);
Где dx и dy была разница в координатах между юнитом и целью, причем нормированны, то есть по сути это cos и sin. Как видно скорость не зависела от предыдущего состояния скорости движения юнита. Она всегда устанавливалась до нужного значения и все. Сейчас же я сделал немного иначе
Vector2 currentVelocity = body.getLinearVelocity();
Vector2 targetVelocity = new Vector2(0.0f, 0.0f);
if (d > unit.info.AttackRadius)
      targetVelocity.set(unit.info.Speed * dx, unit.info.Speed * dy);

body.setLinearVelocity(currentVelocity.lerp(targetVelocity, unit.info.MovementPower * dt));
Теперь новое значение скорости зависит от текущего значения скорости. Метод lerp - смешивает вектора с нужным коэффициентом, который задается как мощность движения. И теперь роботы стартуют и останавливаются плавно, а не мгновенно, что очень даже забавно. И при столкновении ведут себя правильно, отлетают и пытаются остановиться.

Немного о мелочах

Мелочь 1. Удаление объекта

Недавно я заметил, что все что вылетает за пределы игрового поля продолжает функционировать, а конкретно шары летели до бесконечности, а это не есть хорошо, ибо это дополнительная нагрузка на систему. Тогда мне пришлось добавить границы, после которых все объекты бы уничтожались. Сперва я удалял только физические тела и после этого у меня посыпались кучу ошибок, из-за того, что я не удалил актера (Actor) на сцене. Потом я сделал наоборот, но тело то не удалялось. И тут я понял, что надо бы перегрузить метод remove у Actor'а. В принципе идея хорошая. Вызываем где надо remove и со сцены удаляется актер и все не нужные для него данные. Но я столкнулся с очень не приятной вещью. После такого кода:
stage.addActor(new RobotEnemy(x, y, 180.0f));
у меня всегда срабатывал remove, который удалял все внутренние данные объекта. Трассировка не помогла. Решил перегружать finalize у объектов, но он срабатывал не сразу и поэтому данные еще долго весели и мешались. Потом все же вернулся к remove и начал разбираться. Сперва я думал, что этот метод вызывается при удалении объекта, а как оказалось он вызывался при удалении родителя группы. Конечно я делаю не правильно, когда очищаю данные объекта в этом методе, но в данном случае это не критично. Проблему обошел таким образом
if (getParent() == null) {
...
}
return super.remove();

Мелочь 2. Экспорт в *.jar

Так же вчера я решил попробовать экспортировать проект в jar архив. Я долго, долго мучался и не понимал, что я делал не так. Сперва у меня получилось лишь собрать jar архив, распаковать его и запускать вручную через bat файл, с указанием правильного classpath при запуске. Как ни странно, но исправление в манифесте Class-Path до нужного, тоже не помогло. Но благодаря советам эвила, и собственной интуиции мне таки удалось собрать jar архив проекта и запустить его.

Немного о дальнейших планах

В дальнейшем я хочу заняться небольшой оптимизацией систем, в частности это ИИ и Анимации. Возможно сделаю систему прицеливания, если успею (но рано или поздно она все равно должна появиться). Возможно к следующему разу появиться счетчик очков, которые начисляются за убийство врагов.
На этом пока что все. До скорых встреч и всем удачи ;)
`
ОЖИДАНИЕ РЕКЛАМЫ...