воскресенье, 27 февраля 2011 г.

Глобальное хранилище

Глобальное хранилище:

При разработке всегда хочется создать некий удобный сундучек, куда можно было бы складывать часто используемые вещи, то есть указатели на экземпляры классов или их методов для быстрого доступа к ним. И вот сегодня я хочу поделиться с вами таким сундучком [...]

пятница, 25 февраля 2011 г.

Апельсины недоумевают или немного про деньги

Апельсины недоумевают или немного про деньги:

Cover Orange никак не определится, где ему быть в топах. То пробирается на хорошие места, то вовсе вылетает из топов. Издатели суетятся, предпринимают какие-то попытки, в середине марта даже предпримут сразу несколько попыток в одно время. Должно помочь, а то ведь непонятно. Не гоже.

Вот малость статистики: версию для айфона скачали (и заплатили за это) почти 130 тысяч человек. Версию для айпада скачали (это я за все время имею ввиду) 100 тысяч человек. Сюда же засуну и про Physics GameBox - 100 тысяч купивших. Итого – всего заработано играми на айдевайсах – 400 тысяч долларов с гаком. От этой цифры откусывает свою долю Эппл (хорошо живут), оставшееся делим мы с издателем.

Суточные платные скачивания на сейчас – 2000-3000 штук в среднем. В выходные и до 4000 доходит (рекорд – 13 тысяч), в понедельники и до 1500 скачавших [...]

среда, 23 февраля 2011 г.

Аддиктивность

Аддиктивность:

АддиктивностьАддикция - навязчивая потребность, ощущаемая человеком, подвигающая к определенной деятельности. Это зависимость от интернета, курения, телевизора, постоянных покупок, игр, влюбленности и т.д.

Но у себя в блоге я использую немного другое понятие – аддиктивность. В этой заметке я хочу объяснить, что имею в виду, употребляя это слово, так как в будущем еще буду рассказывать об аддиктивности.


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

 

Внутренняя аддиктивность

…возникает во время игры. Игрок просто не может остановиться играть. Но если уж остановился, то вернуться в игру особо не стремиться (если нет внешней аддиктивности).

Каждый образованный игрок может назвать минимум одну игру, которая не позволяла оторваться от игрового процесса. Мой топ – Civilization. Фраза “еще один ход, и ложусь спать” возникла, наверное, именно в этой игре. Вообще пошаговые игры типа HoMM имеют довольно сильную внутреннюю аддиктивность. Игры, основанные на рандомном дропе (Diablo) также заставляют постоянно играть. “Однорукие бандиты” тоже, кстати, основаны на рандомном дропе :) Сокровища Монтесумы – игра, отлично демонстрирующая наличие внутренней аддиктивности и отсутствие внешней. Пока играешь – оторваться невозможно. А оторвавшись можно забыть об игре до следующей игровой сессии [...]

понедельник, 21 февраля 2011 г.

Видеоурок №3

Видеоурок №3:

Урок №3 по Box2d

Урок про создание тел в Box2d, в том числе — невыпуклых полигонов, а также, про отображение тел Box2d мира при помощи спрайтов.

Видео отныне на Vimeo. Архив проекта. Приятного просмотра! )

воскресенье, 20 февраля 2011 г.

TowerDefence #6. Редактор уровней

TowerDefence #6. Редактор уровней:

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

четверг, 17 февраля 2011 г.

Не программные примеры шаблонов проектирования программного обеспечения

Не программные примеры шаблонов проектирования программного обеспечения:

Шаблоны проектирования программного обеспечения уходят корнями в архитектурные шаблоны Кристофера Александера, и в вопросы перехода к объектам. Согласно Александеру, шаблоны повторяют самих себя, поскольку они являются обобщенным решением для задаваемой системы сил. Вопросы перехода к объектам рассматривается в реальном мире для того, чтобы проникнуть в суть взаимоотношений при моделировании программного обеспечения. С такими двойственными корнями, вполне логичным будет найти повторяемость шаблонов проектирования программного обеспечения в объектах реального мира. В этой статье представлен реальный мир, не программные экземпляры каждого шаблона проектирования из книги «Приемы объектно-ориентированного проектирования. Шаблоны проектирования» [13]. В статье также приводятся выводы о не программных примерах как эффективной основе языка шаблонов для взаимообщения и обучения проектированию шаблонов.

1. Введение

В индустрии программного обеспечения существует растущее сообщество сторонников применения шаблонов. Корни перехода к шаблонам можно найти в работах архитектора Кристофера Александера, который описывал шаблоны как обобщенное решение для задаваемой системы сил в мире [1]. Шаблоны Александера можно обнаружить в повседневных структурах. Каждый из шаблонов в «Языке шаблонов» [2], включает в себя картину архетипического примера шаблона.

Поскольку объекты были преобладающим взглядом на мир в то время, когда мир программного обеспечения знакомился с шаблонами, они тоже имеют корни в переходе к объектам [9]. К сожалению примеров шаблонов моделирования программного обеспечения было не так много как у Александера, а они представляли собой более элегантные модели, в отличие от моделей, что люди генерировали в самом начале [13]. Доступ к элегантным моделям часто ограничивался в связи с проприетарным характером большей части программного обеспечения, разработанного сегодня.

Согласно Александеру, реальный мир шаблонов всегда повторяет самого себя, поскольку в соответствии с заданным набором обстоятельств, всегда существует определенные поля взаимосвязей, которые являются наиболее хорошо приспособленными к силам, которые уже существуют [1]. В программном обеспечении, задачи реального мира либо моделируются целиком, либо объекты реального мира сводят к аппаратному программному обеспечению, а программы выводят результаты реального мира [5]. Поскольку шаблоны моделирования программного обеспечения имеют корни как в шаблонах Александера, так и в вопросах перехода к объектам, представляется вполне логичным, что шаблоны моделирования программного обеспечения могут быть найдены и в объектах реального мира. Это не означает, что шаблонам моделирования программного обеспечения необходимы модели объектов реального мира, но взаимосвязи между объектами, которые приспособлены для работы с определенными силами, могут быть обнаружены как в «реальном мире», так и в объектах программного обеспечения. Чтобы проверить эту гипотезу, были найдены примеры из реального мира для каждого из 23 шаблонов «Банды Четырех» [13]. Эти примеры приводятся далее в разделах со 2 по 4.

2. Порождающие шаблоны

Пять порождающих шаблонов были задокументированы группой авторов, называвших себя «Бандой Четырех». Примеры таких порождающих шаблонов могут быть найдены в обрабатывающей промышленности, на предприятиях быстрого питания, в биологии и в политических институтах [...]

Биндинг в ActionScript проектах. Часть 1

Биндинг в ActionScript проектах. Часть 1:

Перед разработчиками часто встает вопрос о взамодействии различных классов в приложении. Как классы приложения будут обмениваться информацией между собой, сообщать о тех или иных изменениях? Это должно происходить своевременно. Для этих целей во Flex-фреймворке есть замечательный инструмент, значительно облегчающий жизнь разработчику – биндинг (binding). И как оказалось этой возможностью можно с успехом пользоваться и без использования Flex-фреймворка. Начиная с какой-то-там одной из третьих версий SDK адобовцы постарались максимально изолировать биндинг и все что с ним связано, и теперь его использование добавляет приложению считанные килобайты.

Как бы мы сделали

Немного отвлечемся и поговорим о частном случае. Когда же нам может все это дело пригодиться? Например, при разработке с использованием паттерна MVC встает вопрос о своевременном реагировании компонентов отображения на изменения в модели.

Как известно в MVC классы модели ничего не должны знать и не иметь ссылок ни на классы контроллера, ни на классы отображения. А вот на модель имеют ссылку и контроллер и отображение. Контроллеру нужна ссылка для того чтобы изменить модель, отображению – чтобы отреагировать на изменения. С изменением модели вроде все понятно – нужно поменять свойство. Но как отображение узнает о том что данные были изменены, чтобы самому измениться? Как правило для этих целей используются события. Мы создаем в модели сеттер на нужное нам свойство и в тот момент когда свойство меняется – посылаем соответствующее событие:

1
2
3
4
5
6
7
8
9
private var _text:String;

public function set text (value:String):void{
    if (value == _text){
        return;
    }
    _text = value;
    dispatchEvent(new Event("textChanged"));
}

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

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

Как это делается с помощью биндинга

А как же все таки было бы здорово просто написать в классе отображения: “при изменении вот этого свойства вон в том экземпляре класса изменить вот это свойство” или вот так: “при изменении вот этого свойства вон в том экземпляре класса вызвать вот этот метод для обработки”. Так вот стандартный флэксовый биндинг работает именно так.

Давайте посмотрим как это будет выглядеть непосредственно в коде. То свойство за которым нам необходимо пристально следить нужно пометить как bindable. Делается это очень просто, с помощью метатега [Bindable]:

1
2
3
4
5
6
7
8
9
package{
    import flash.events.EventDispatcher;

    // Класс который использует метатег [Bindable] должен обязательно расширяться от EventDispatcher
    public class ClassWithTextProperty extends EventDispatcher{
        [Bindable]
        public var text:String;
    }
}

В классе который должен следить за свойством text в другом классе будет написано следующее [...]

Сортировка массива объектов по нескольким полям

Сортировка массива объектов по нескольким полям:

Иногда возникает необходимость отсортировать некоторый массив объектов сразу по нескольким полям. Например, есть список пользователей. Каждый из них в текущий момент может быть в онлайне. Наша задача - отсортировать список таким образом, чтобы сначала показывались по алфавиту пользователи в онлайне, а за ними - те, кто в оффлайне. Это можно сделать так:

 
package {
import flash.display.Sprite;
import flash.utils.getTimer;
 
public class VectorSorting extends Sprite {
 
    private var players:Vector.<Player> = new Vector.<Player>();
 
    public function VectorSorting() {
        // Заполняем массив данными
        addPlayers(50);
 
        // Выводим начальный массив
        playersTrace();
 
        // Засекаем время
        var current:int = getTimer();
 
        // Cортируем массив
        players.sort(
            function(a:Player, b:Player):Number {
                if (a.online == b.online) {
                    return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
                } else {
                    return a.online ? -1 : 1;
                }
            }
        );
 
        // Выводим время, затраченное на выполнение сортировки
        trace("Сортировка заняла",String(getTimer()-current),"миллисекунд");
 
        // Выводим отсортированный массив
        playersTrace();
    }
 
    /**
     * Вывод содержимого массива
     */
    private function playersTrace():void {
        trace("--------------------------");
        for each (var player:Player in players) {
            trace(player.toString());
        }
        trace("--------------------------");
    }
 
    /**
     * Заполнение массива начальными данными
     */
    private function addPlayers(numPlayers:int):void {
        for (var i:int = 0; i < numPlayers; i++) {
            var rName:String = "Player " + String(int(Math.random() * 100));
            var rOnline:Boolean = Boolean(Math.random() > .5);
            var currentPlayer:Player = new Player(i, rName, rOnline);
            players.push(currentPlayer);
        }
    }
}
}
 
class Player {
    public var id:int;
    public var name:String;
    public var online:Boolean;
 
    public function Player(id:int, name:String, online:Boolean) {
        this.id = id;
        this.name = name;
        this.online = online;
    }
 
    public function toString():String {
        return "Player{id="+String(id)+",name="+String(name)+",online="+String(online)+"}";
    }
}

Исходники демо-игры. Alternativa3d и физика Jiglib

Исходники демо-игры. Alternativa3d и физика Jiglib: "

Alternativa3d

JigLib

Alternativa3d и физика Jiglib

Всем добрый день! Очень хорошо заметно, что в последнее время все больше и больше флешеров начинают разрабатывать 3д игры, сайты, демонстрации и т.д. и т.п. И приходит все больше и больше писем, с просьбой о помощи в настройке и использовании JigLib с Alternativa3d. Я решил выложить довольно большой кусок моей работы, в которой задействован JigLib и A3D. Это один из самых первых тестов разрабатываемой мной ранее 3д-игры(видео с ней публиковал в свой блог с названием «;)») Так вот, решил выложить сорсы, чтобы в рунете был хоть один толковый пример использования данных движков + большой профит разработчикам, использовать как обучающий материал. Надеюсь вам понравится, и вы найдете много чего интересного для себя [...]

четверг, 10 февраля 2011 г.

Релиз! Релиз! Релиз!

Релиз! Релиз! Релиз!:

Релиз
Доброго времени суток, друзья!
Спешу сообщить радостную новость: нежданно и негаданно, буквально в пол-второго ночи к  нам явился такой зверь, как релиз. На самом-то деле уже даже и не верится: проект стал таким долгостроем, что его кодинг, дизайн, тестинг стали неотемлемой частью моего каждодневного ToDO-листа. Но, как и дети когда-то уходят от своих родителей, так и игры рано или поздно уходят от разработчиков к издателю. Остается лишь пожелать ей удачи в этом, вздохнуть и вспомнить, как все было. Поэтому сегодня я хочу поделиться с вами небольшим "постмортемом", ну или "дневником разработки". Полноценный постмортем будет чуть позже на FlashGameBlogs, здесь он тоже, разумеется, будет продублирован.
Итак, начнем?

Недостаток свежих концептов или 'Идеи живут в дУше'

Многие из вас наверняка испытывали такое состояние, когда в голове пусто, а новые идеи витают где-то в облаках. Или же в голове полно концептов, но они вторичны. Обычная практика в таких случаях - закупить в магазине пива, достать планшет и сесть творить :) Чем я, собственно и занялся. В поисках оригинального геймплея в голову пришла мысль: а что, если игрок будет вулканом, которому нужно уничтожать жалких людишек и их бронетехнику? Сказано - сделано. Уже через час был готов концепт. Но практически сразу же вылез существенный недостаток - управлять массивной стационарной штукой, которая, к тому же, не является пулеметом или иной быстро стреляющей пушкой, не интересно. Фана нет. Ну а если нет фана - сами понимаете...

Откровение поджидало в дУше. Вообще, как я заметил, в дУше идеи приходят в голову очень часто. Не знаю что тут является ключевым фактором: вода, расслабленность или какие-нибудь торсионные поля и прочий атсрал. Но факт остается фактом. Который и на этот раз меня не подвел. 'А что, если вы большой желтый круг? (с)' - цитата из Конференции Разработчиков Видеоигр 1979 пришла в голову и прочно там поселилась. Круг постепенно трансформировался в шар, у которого есть 4 слота под оружие с каждой стороны. Возможно, какую-то роль в формировании идеи сыграл Hammerfall или, как он сейчас называется, Hammerflight. В моем воображении шарик, экипированный пушками, молотами, топорами и мечами уже крошил супостатов. Ну а если так, то чего же ждать? :)

Реализация идеи или 'На ошибках учатся'

Обычно я концепт каждой идеи скидываю на оценку Ахуре или Хвосту. В этот раз Хвост где-то пропал, поэтому идея отправилась прямиком к Ахуре. Открыв фотошоп и сделав там набросок концепта, я постучался к нему в аську. Честно говоря, по-моему он сначала даже не понял о чем я говорю :)
Концепт gunball [...]

среда, 9 февраля 2011 г.

Проблема дисконнекта

Проблема дисконнекта:

Tags:

При работе с медиа серверами (да и вообще с TCP соединением) нужно решить одну важную, но не очевидную проблему. И проблема эта -- нестабильное соединение. Увы, соединение клиента с сервером иногда рвется. Это случается относительно редко, но в крупном проекте с большим числом пользователей вы будете регулярно получать жалобы от них.

С самими разрывами соединений ничего сделать нельзя, но можно сделать грамотный реконнект. В идеале реконнект вообще должен быть незаметен для пользователя. Но тут уж много зависит от конкретного приложения. (rtmp-service-mate-ext поддерживает реконнект по дефолту.)

К сожалению, идеальный реконнект со стороны клиента -- это еще не все. Проблема еще в том, что при разрыве соединения клиент об этом узнает сразу, а вот сервер не сразу. Серверу нужно на это 60 секунд (wowza и red5 сами пингуют клиента и определяют этот момент, на fms такое нужно реализовать вручную).

Итак, когда клиент реконнектится и пытается авторизоваться, оказывается, что пользовательский аккаунт уже связан с другим клиентом, с которым соединение потеряно, но сервер об этом еще не знает. Если у нас система спроектирована так, что одному пользователю соответствует один клиент (одно соединение с клиентским приложением), то вот сейчас нужно решать, а к какому из двух (или даже больше) клиентов привязать данного пользователя? Может быть, предыдущий клиент — зомби, потерявший соединение, но мы об этом пока не знаем? А может быть, предыдущий клиент — нормальный, активный клиент. А новый клиент — кто-то другой, пытающийся зайти под тем же аккаунтом? [...]

Скроллинг плиточного мира

Скроллинг плиточного мира.:

Представляю вашему вниманию перевод серии статей «Tutorial: N-way tile-based blit fine scrolling in AS3».

Мы обсудим теорию и практику скроллинга блитированной битмапдаты в любом направлении. Что это значит? Скроллинг это средство, с помощью которого вы можете передвинуть свой игровой экран в любом направлении, которое определяется углом поворота вашего персонажа. Здесь, в качестве примера мы рассмотрим двухмерную симуляцию автогонки с видом сверху, но техника, которую мы здесь рассмотрим, может применяться и в других играх. В нашем примере автомобиль всегда остается в центре экрана, а фон под ним прокручивается. Наш пример может быть легко сведен к скроллингу в 4-х и 8-ми направлениях, и хотя движение в таких играх не основано на направлении поворота, но способ скроллинга идентичен. Примеры скроллинга в 4-х и 8-ми направлениях мы также рассмотрим.

Что собой представляет скроллинг блитированного мира?

Скроллинг – это метод, с помощью которого мы показываем и обновляем только ту часть тайловой карты, которая видна на экране. Это не то же самое, что и хранение всего мира как одного большого объекта BitmapData и отображение только той части, которая нам нужна. Конечно, такой метод имеет право на жизнь, но он ограничивает физический размер мира, который мы можем создать. С помощью скроллинга тайлового мира, мы можем создать безграничный игровой мир. Мы можем представить его, например, как двухмерный массив (считываемый из xml) размером 100х100. Каждый элемент нашего массива представляет собой целое число, которое соответствует определенному тайлу на тайловом листе (можно посмотреть этот перевод). Мы показываем только то, что помещается на экране, но обновляем в буфере скроллинга область большую на один тайл в каждом направлении (влево, вправо, вверх, вниз), чем размер видимой области.

Мир, окно и буфер

Мир ссылается на всю карту тайлов, которую игрок может прокрутить. Окно – это текущий набор тайлов, который видит игрок. Буфер – набор тайлов больше размера окна на один тайл в каждом направлении. Сначала мы отрисовываем буфер, затем выясняем, какая граница будет видна игроку и отрисовываем область, ограниченную этой границей в окно. Пока мы здесь не говорим о коде, но когда я говорю «отрисовываем» и «прокрутить» я имею ввиду метод copyPixel() класса BitmapData и экземпляры класса Point и Rectangle необходимых для выполнения этого метода.

Точный скроллинг

Точный скроллинг дает нам возможность прокрутить экран на 1 пиксель за единицу времени в любом направлении. Это противоположность «тайловому скроллингу», когда экран прокручивается вверх, вниз, влево или вправо на целый тайл за один раз [...]

суббота, 5 февраля 2011 г.

Preloader (прелоадер) для игр на AS3.

Preloader (прелоадер) для игр на AS3.:
'Не пустят на банкет, когда прелоадера нет!'



Всем привет!
Это снова я, со своей писаниной! :)

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

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



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


Разделим прелоадеры на два класса:
  • Внешние
  • Встроенные

Встроенный прелоадер образует единое целое с SWF файлом игры, в то время как внешний прелоадер хранится в отдельном SWF файле или реализован другими средствами.

Внешние прелоадеры я не буду рассматривать (там все не так просто из-за системы безопасности), скажу лишь, что нужно использовать образец класса flash.display.Loader и после того, как внешняя флешка будет загружена, прикрепляете этот образец к stage. Загруженная флешка будет чем-то вроде клипа.

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

*** 

Встроенный прелоадер - это класс или алгоритм (если написан внутри кадров FlashIDE) контролирующий процесс загрузки SWF файла и определенным образом показывающий пользователю прогресс в загрузке. 
Но реализацию прелоадера мы не можем рассматривать, пока не разберемся в структуре SWF файла (что собственно грузим, то?).

Давайте одним глазком заглянем под капот SWF файла.
  • Первое, что нам нужно знать - SWF файл состоит из множества тегов (Tags) идущих друг за другом. Каждый тег содержит кусочек данных (описание клипа, код класса, команда плейеру).
  • Второе, что мы должны знать - теги грузятся пачками и разделяют эти пачки контрольные теги ShowFrame.
Структура SWF файла

При инициализации тегов ShowFrame плейер помещает загруженную порцию клипов в рендеринг конвейер и инициализирует загруженные классы (например, класс-документ), а потом ожидает команды на загрузку следующей пачки тегов и обрабатывает события.

Из сказанного выше мы делаем вывод - флешка грузиться поэтапно и в конце каждого этапа мы можем выполнить определенные действия [...]