Синхронизированные анимированные плитки в 2-й веб-игре - PullRequest
2 голосов
/ 03 октября 2011

Я создаю стратегическую игру в браузере 2 года назад. Его уже активно играет небольшая толпа людей, так что это рабочая игра. Наша проблема в том, что его ресурс голоден. В основном вы хотите оперу или хром. IE9 более или менее неиграбелен, и Firefox может быть довольно медленным на некоторых картах.

Игра представляет собой игру сверху вниз с использованием плиток, использующих 64x64-пиксельные DIV для карты.

В настоящее время мы находимся в завершающей фазе и сосредоточены на оптимизации. Одной из вещей, которые питаются ресурсами, является наша оживленная вода. У нас есть 32 различных плитки воды, разделенные на 15 кадров каждая. Таким образом, 480 64x64 изображений в одном файле .gif, который составляет 1,1 МБ.

Вот ссылка на воду: http://www.warbarons.com/beta5/terrain/water/water2.gif

Наша игра использует Fog of War, чтобы скрыть вражеские юниты и замки, которые вы не можете увидеть, как и в любой другой игре RTS. Так что поверх .gif обычно есть слой с прозрачным PNG.

Похоже, что это решение довольно требовательно для браузера. Когда я прокручиваю карту, чтобы показать, что вода в FireFox ЦП поднимается до 25%, а около 4-5%, когда воды не видно.

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

Проблема, которую я вижу с этими двумя вариантами, заключается в том, что все тайлы воды должны оставаться синхронизированными. Если один начнет играть раньше другого, волны не будут синхронизированы, что нарушит цельный вид.

Интересно, есть ли у кого-нибудь идея решить эту проблему? Я знаю, что наличие нескольких gif-анимаций приведет к проблеме несинхронизации.

Есть ли какой-нибудь умный способ использовать canvas для этого? Можно ли даже смешать холст с элементами div или для этого потребуется изменить весь движок карты?

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 02 января 2012

Немного начинающего обходного и длинного, но: Для подготовки сделайте спрайт-лист всех различных типов водных плиток, с первым кадром слева, с новым рядом для каждого типа, опускающимся вниз.

  • Создание <div> с атрибутом «переполнение» «скрыто» за холстом
  • Сделать фон холста прозрачным
  • Внутри div, вы можете использовать <div> s для тайлов воды и настроить их атрибуты 'margin', чтобы они соответствовали положению карты
  • Дайте им всем обозначение класса «вода», а также класс, соответствующий типу плитки для воды (например, «док-левый», «пляжный» и т. Д.)
  • В элементе <style> создайте правило класса '.water'
  • Дайте правилу атрибут 'background-image', связывая его с тем, где и где находится ваш спрайт-лист
  • Для каждого типа плитки для воды создайте правило класса, соответствующее каждому типу плитки, и дайте им соответствующую позицию y для листа спрайта
  • Создайте новый <style> элемент с идентификатором, который будет содержать background-position всех кадров
  • Создать переменную javascript для определения положения x всех фонов
  • Внутри игрового цикла уменьшайте переменную на 64, если хотите, чтобы спрайт изменился (до тех пор, пока он не станет равен 960, затем установите его в 0)
  • Когда переменная изменяется, установите для нового элемента <style> новое правило CSS для его 'background-position-x', используя переменную

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

<script type="text/javascript">
    var pos = 0; // background-position-x variable

    function loop() {
        document.getElementById('changeMe').innerHTML = ".water{background-position-x:" + pos + "px;}"; //changes the contents of the <style> with the id 'changeMe'
        //changes the <style> with id 'Change'
        pos -= (pos == 960) ? -960 : 64; //assuming your sprite-sheet is oriented horizontally
        setTimeout('loop();', 100);
    }
</script>


<style type="text/css">
    /* Remains unchanged */
    .water {
        width: 64px;
        height: 64px;
    background-image: url('spriteSheet.png');
    }
    .dockleft{
        background-position-y: 420px;

        /* If all of your sprites are on one sheet, you can set the
        'background-position-y' attribute for each type of water tile and 
        give the 'water' class one sprite-sheet url for all of the types */
    }
</style>


<style id="changeMe" type="text/css">
    /* Changed by 'loop()' */
</style>


<body onload="loop();">
    <div class="water dockleft"></div>
</body>
...