Как я писал Bomberman’а на Android

    День добрый, уважаемые хабражители.
    Писать игры хотел ещё с того момента, когда только начал программировать. И вот, решил всё-таки попробовать себя в написании игр на Android.
    Игру осенью сделал ещё и выложил в маркет. Правда её удалили, так как права на Bomberman'а у Konami. Но статья, естественно, не об этом.

    Параллельно с разработкой игры писал туториалы по LibGDX, и постоянно люди просили выложить исходники. Решил всё-таки поделиться ими и немного рассказать про разработку. Может кому-нибудь и поможет в изучении LibGDX. Ссылка на репозиторий с исходниками внизу статьи.



    Небольшое отступление


    До этого не имел опыта работы с Java, а уж тем более с Android. Решил и то, и другое изучать на практической задаче. Писать на чистом OpenGL свой движок не очень хотелось. Особой разницы не было на каком движке игру разрабатывать. Чем-то приглянулся LibGDX, решил с него и начать. Так что, не судите слишком строго. Особого плана или ТЗ не было. По мере того, как разбирался в либе, потихоньку писал и игру.

    Архитектура


    Для архитектуры, как мне показалось, лучше всего подходит MVC. Я об этом уже рассказывал в статье про архитектуру.

    В целом всё довольно просто и понятно. Основной игровой класс BomberMan наследуется от Game. В нём содержаться ссылки на все возможные экраны игровые: сама игра, главное меню, окно при победе и т.д. Нам необходимо только переключаться между этими классами с помощью метода setScreen().

    В качестве View у нас классы, которые реализуют интерфейсы Screen и InputProcessor (между ними и происходит переключение в классе BomberMan). В классе мы обрабатываем действия пользователя и рендерим объекты. Изменение объектов и последующая отрисовка происходит в одном методе этого класса. Сначала изменяем состояние объектов, если это необходимо (грубо говоря, работаем с физикой), а потом рендерим:
    @Override
    public void render(float delta) {
      controller.update(delta); 
      renderer.render();
    }
    
    


    Контроллер, думаю понятно, работает с моделью. Большая часть логики как раз в нём. Не совсем был уверен в том, куда всё-таки логику запихнуть. В итоге, часть логики перенёс в сами объекты (обработка коллизий), а логику по обработке взрывов, убийств (т.е. когда объектам надо влиять на другие объекты) в контроллере. Была идея реализовать подобное с помощью сообщений. То есть, в каждом объекте определить хэндлер, который будет обрабатывать сообщения и как-то реагировать. Но тогда проблема с синхронизацией возникла. Поэтому решил всё синхронно обрабатывать.
    В итоге в контроллере просто последовательно работаем со всеми объектами мира:
    public void update(float delta) {
    		processInput();
    		checkBombsTimer();
    		if(!world.bonus) destroyBricks();
    		removeDeadNpc();
    		killByBoom();
    		removeHiddenObjects();
    		bomberman.update(delta);
    		for(NpcBase npc : world.getNpcs()){
    			npc.update(delta);
    		}
    		removeBooms();
    	}
    


    Для объяснения модели, думаю, проще диаграмму предоставить:


    World является контейнером, который содержит в себе все объекты: блоки, бонусы, игрока, npc. Никакой логики в нём нет. Лишь в самих объектах часть логики по ним есть (как уже выше писал). Не стал полную диаграмму классов приводить.
    Все типы npc наследуются от NpcBase. Все объекты (дверь, бонусы) от HiddenObject.

    Прототип



    Изначально разбирался с текстурами и атласом. Первоначально все спрайты были в отдельных файлах. После чего объединил всё в один атлас, что ускорило работу. И тут были проблемы. Тестировал на своём телефоне всё (HTC One S) с Android 4.0. Когда пробовал на более ранних версиях, то игра крашилась. Как оказалось, более старые устройства падают из-за ограничений на размер текстуры. К примеру, какие-то не поддерживали спрайты более 1024x1024. К тому же, изначально размеры у атласы были не степенью двойки, что тоже приводило к падениям на многих устройствах.

    Так что:
    1) Не делать слишком большие атласы.
    2) Размеры должны быть степенью двойки.

    Вещи довольно очевидные, но бродя по develop форумам, многие от подобных ошибок страдали). После того, как все собрал в одном атласе и разобрался, как выделять регионы и настроить анимацию, начал обрабатывать коллизии.

    Большинство объектов имеют целочисленные координаты, да и меняются не так часто. Определил массив public int[][] map и обращался к нему, чтобы постоянно не прогонять списки объектов. Суть в том, что все блоки находятся на целочисленных координатах, поэтому использование массива помогло ускорить работу. Когда обновляем физику, просто смотрим расстояние от игрока/npc до окружающих его объектов.
    Что-то вроде:
    if(around[0][1] ==0 && Math.abs(getPosition().x-x1)<SIZE/2 && Math.abs(getPosition().x-x1)>0.05){
    				if(getPosition().x-x1<0){
    					getVelocity().x = +speed; 
    					getVelocity().y = +speed; 
    				}
    				if(getPosition().x-x1>0){
    					getVelocity().x = -speed; 
    					getVelocity().y = +speed; 
    				}
    			}	
    

    Ооочень кривое решение, да. В следующих своих играх вся обработка коллизий основана на delta, которая показывает сколько времени прошло с прошлой отрисовки. Но здесь всё вот так печально =/

    NPC


    После того, как разобрался с текстурами и обработкой коллизий, добавил в игре и npc. Стратегий поведения, в сущности, у них всего три:
    1) Двигаться в случайном направлении. По прошествии определённого времени меняют направление на рэндомное.
    2) Как и первая в целом. Но, если npc видит игрока, то начинает двигаться к нему. Если игрок пропадает из поля зрения, то npc меняет направление движения на случайное.
    3) В целом как вторая стратегия. Вот только, если теряет из вида игрока, всё равно идёт в ту сторону, где последний раз видел игрока.

    Все виды npc наследуются от NpcBase и должны реализовать методы:
    public abstract void changeDirection(float delta);
    public abstract void update(float delta) ;
    


    GUI


    GUI тоже реализовал средствами LibGDX. Все элементы интерфейса представлены в виде классов, экземпляры которых содержаться в классе World. У каждого элемента координаты и размеры есть в свойствах, что позволяет нам определять при тапах по экрану, на какой, собственно, элемент пользователь нажал.

    Реализовал два метода управления:
    1) Стрелками.

    2) Джойстиком.


    В настройках можно задать положение объектов, какое хотим:


    Итог


    Весь процесс разработки в один пост не уместить. Подумал, может люди сами предложат тему для статьи, если им интересен этот движок. Рассказал бы вам о каких-то наиболее интересных аспектах разработки или наиболее интересных моментах при работе с LibGDX.

    Исходники выложил на github.
    Там же можно посмотреть и мои уроки по LibGDX, если кто-то хочет с этим движком работать.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 56

      +1
      А как диаграммы зависимости классов делали?
    • UFO just landed and posted this here
        0
        Много в своё время играл на NES. Вот и решил порадовать людей, которые тоже с ностальгией те времена вспоминают)
          +15
          Хоть кто-то? Да 8/16-бит/пиксели/олдскул — этой мейнстрим инди, как ни каламбурно это звучит.
            –2
            А где каламбур? Или вы считаете, что инди = хипстер?
          –1
          Каждая подобная статья начинается на «До этого не имел опыта работы с Java, а уж тем более с Android». Хотелось бы статью от опытного разработчика игр под андроид.
            +3
            Смысл подобных статей (один из них) в том, чтобы показать, что результата можно достигнуть, приложив достаточно усердия.

            С другой стороны, а что плохого в том, что статья от новичка? Цели достигнуты, результат можно пощупать. С точки зрения паттернов, да, некоторые моменты некрасиво реализованы. Но ведь всё приходит с опытом.
              0
              Мне не хватает статей, где можно чему-то по-настоящему научиться. Как именно надо действовать. У меня почти весь опыт на таком вот самообучении, метод проб и ошибок — «наше всё», а это мне уже очень сильно поднадоело.
              «С точки зрения паттернов, да, некоторые моменты некрасиво реализованы. Но ведь всё приходит с опытом.» — так вот вы увидели, что это плохо реализовано, а другие подумают, что это так и надо. Вот я к чему.
              P.S. В карму зачем срать за мои мысли тоже не пойму.
            +1
            Выложите в маркет!

            Я джва года ждал бомбермена где мобы набигают

            А если серьезно — давно искал реализацию именно этого бомбера, у меня много хороших воспоминаний о нём.
              0
              Была она в маркете, в шапке же упомянул. Права то на материалы, да и на само название у Konami.
              Игра за неделю-две набрала 100к+ загрузок. А потом игру удалили, что было довольно предсказуемо)
                0
                А вы не пробовали связаться с Konami? Может они разместят под своим брендом но с Вашим именем в качестве автора… Или разрешат таки опубликовать? Знаете, у меня бабушка часто говорит: «спрос в лоб не ударит» (всмысле лишне заданный вопрос, хотя в наше время спорно;) )… Удачи, ежели чего :)
                  0
                  Связывался, сказали, что ничем не могут помочь.
                  Та же самая история и с другой моей игрой — Lode Runner. Там не получилось с Tozai договориться. Что-то такое от них получил:
                  Thank you for contacting us about Lode Runner. At this time, we are not
                  licensing or authorizing any remakes of Lode Runner. Again, thank you for
                  your interest
                    0
                    Нда, печально…
                  +1
                  Был б очень благодарен, если б выложили куда-нибудь игру.
                    +3
                    Можно с этой страницы.

                    Или сразу по QR image
                      0
                      Спасибо.
                        0
                        Супер, прям как в детстве.
                          0
                          У вас QR-код битый… Но спасибо.
                          Я бы даже задонатил, куда? :)
                            0
                            Там просто пробелы в ссылке. Не подумал об этом.
                            Донатить не надо. Для меня достаточно, что вам игра пришлась по вкусу (:
                        0
                        У Вас было по 7-10 тысяч загрузок в день? Как Вы это рекламировали?:)
                          0
                          А вот это самое весёлое. Сделал обзор только на 4PDA. Да, портал большой в русскоязычном сегменте, вот только большая часть загрузок приходилась не на страны СНГ, а на Азию (:

                          В последние дни (перед удалением) по 15к в день было. Сам удивился.
                      0
                      А если дизайн немного изменить и название, все равно в маркет не дадут выложить?
                        0
                        Не хочется рисковать что-то, а то при повторном нарушении могут и аккаунт заблокировать.
                          0
                          play.google.com/store/search?q=bomberman&c=apps куча Бомберменов, притом не самого лучшего качества
                            0
                            А вот это довольно забавно, если честно.
                            Игры при нарушениях удаляют по DMCA, но конкретной причины не узнать. Я пытался с тех. поддержкой Google этот вопрос обсудить. Хотел узнать, что именно послужило причиной удаления. Если бы ответили, то я бы мог изменить эти части игры и по новой залить, правилами это разрешается. Но тех. поддержка ничего вразумительного не ответила, каждый раз ссылалась на этот закон.

                            Ну а с Konami нет смысла говорить, они всегда односложно отвечали что-то вроде «мы не разрешим публиковать».

                            Но дело то не в этом. Я хотел игру сделать максимально приближенную к оригиналу. Если я заменю спрайты/музыку, то это уже будет не старый добрый Bomberman )=
                              0
                              Вот вы сами ответили на свой вопрос. Если изменить спрайты, музыку и название игры, то никто её трогать не будет. Разумеется для пользователя это будет совсем другая игра)
                                +1
                                Зато игра будет на маркете, притом качественная
                                  0
                                  Я уже думал над этим. Хотел изменить графику, мултиплейер прикрутить и опубликовать.
                                  Вот только жду, что парни bombermine.com всё-таки под Android сделают)
                                0
                                Разве они могут придраться, если игру не называть «Bomberman» или еще как-то, на что у них есть торговая марка? Ну и графику самому нарисовать (вы же так и делали, да?). Насколько знаю, геймплей запатентовать НЕЛЬЗЯ. Иначе игр-клонов не было бы вообще (да и развитие отрасли остановилось-бы).
                                  0
                                  Придрались не к названию же, а к тому, что использовали материалы из оригинальной игры. То есть, даже если вы сами нарисуете спрайты, которые будут как в оригинале, то могут и удалить.

                                  Бывают случаи, когда удаляют приложения без особой причины после любой жалобы — Google прощу удалить приложение, чем разбираться. Там есть, конечно, возможность обжаловать, но, сами понимаете, шансов маловато.
                                    +1
                                    А если в какой-нибудь яндекс-магазин выложить, просто чтобы иметь возможность установки не из неизвестного apk? Мониторят ли они сторонние магазины?
                                      +1
                                      В Яндексе и в магазине Самсунга выложил)
                          +1
                          Просим продемонстрировать получившийся продукт, просим, просим
                          0
                          А какие затраты были на разработку? Время и деньги.
                            0
                            Всё сам делал по вечерам после работы в течении месяца где-то.
                            +1
                            Так, где скачать ссылку дали, спасибо, а донейты-то кудыть слать? Не нашёл на сайте информации (
                              0
                              Всё безвозмездно и ради фана (:
                              0
                              Лёг таки сайт то ваш
                                0
                                Да нет вроде. Но нагрузка на CPU на хостинге выросла в разы, за «жёсткий лимит» выхожу =/
                                0
                                Зачем вы джойстик разнесли?
                                  0
                                  Вариант со стрелками? По просьбе людей. Я пока игру создавал, советовался с людьми на 4PDA. Оказалось, что многим удобно часть кнопок переместить в левую часть экрана, а часть в правую.
                                  Настраивайте, как вам удобно)
                                    0
                                    Хмм, спорить не буду, но я думал что две руки для бомбермана не особо то и нужны.
                                      0
                                      Каждому своё. Я лично вообще не могу на стрелках играть, с джойстиком удобнее.
                                        0
                                        Я вырос на 8-битной приставке и GameBoy так что привычен к стрелкам) Да и оригинал то был на стрелках)
                                          0
                                          На оригинальном джойстике стрелки хардварные, поэтому на нём удобно играть. Мне лично на сенсоре не удобно, так как не ощущаю кнопок. Такие дела)
                                            0
                                            на этом можно заработать — разработать нажатие, которое бы ощущалось пальцем на touch-экранах!

                                            но это вопрос «железа», нежели софта… хотя…
                                0
                                Уже которую неделю играюсь на html5 bombermine.com/ Проект активно развивается, думаю скоро появятся клиенты под мобильные.
                                  0
                                  Тоже играюсь, когда надо время убить. Помню, как только представили на хабре, как сервак у них лежал)
                                  +1
                                  Привет, прежде всего спасибо за исходники, очень интересно!

                                  Начал пытаться собирать и с сожалением обнаружил что проект не собирается так как:
                                  1. не нашел библиотеки libgdx которая была использована
                                  2. скачал текущую версию
                                  3. в ней произошел ряд изменений из-за которых проект не собирается, например
                                  — убран Vector2.tmp() github.com/libgdx/libgdx/pull/256
                                  — убран ShapeType.Rectangle

                                  Что посоветуете?
                                  Нельзя ли выложить ту версию библиотеки libgdx — c которой проект корректно компиллится? Так как там похоже таких ошибок довольно много, исправил с десяток с ShapeType.Rectangle — вылезло штук 50 с Vector2.tmp(), боюсь исправив их — вылезет еще пару сотен и так до бесконечности(
                                    0
                                    В .gitignore просто были исключены .jar'ники. Закоммитил недостающие файлы. Теперь должно нормально собираться.

                                    P.S.
                                    в ней произошел ряд изменений из-за которых проект не собирается, например

                                    Да, там частенько от версии к версии что-нибудь ломают)

                                      0
                                      Спасибо, у меня уже собралось на послед версии libgdx (менял ShapeType.Rectangle на ShapeType.Fill и velocity.tmp().mul(delta) на velocity.scl(delta))
                                        0
                                        а, не, монстры то не ездиют) чет я не так собрал
                                          0
                                          А не velocity.cpy().scl(delta) надо? Честно признать, с новым билдом не работал, так что сложно что-то посоветовать.

                                    Only users with full accounts can post comments. Log in, please.