Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > С миру по нитке

Рейтинг: 5.00. Голосов: 6.

Немного о создании своей игры. Часть первая.

Запись от Hauts размещена 19.04.2013 в 23:34
Обновил(-а) Hauts 22.04.2013 в 09:53

В качестве предисловия

Я очень много времени провожу за компьютером. Работаю, читаю, смотрю... Но не играю. Точнее я не фанат игр. Так уж исторически сложилось, что мне интереснее создавать, чем пользоваться созданным. А создавать, в силу профессии, приходится много и весьма разнообразные вещи. Но это работа.

В какой-то момент получилось так, что я и мои друзья (дизайнер и иллюстратор / аниматор) решили создать свою первую игру. Для меня причин этому несколько. Во-первых, мне не хватает практики с as3. Во-вторых — уж очень заманчивыми кажутся новые возможности платформы, их хочется "пощупать" в боевых условиях. В-третьих, постоянно делая "вкусные" штуки для клиентов, в какой-то момент начинаешь задумываться над своим проектом. Тем более, есть поддержка профессиональных дизайнера и аниматора.



Идея

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



Конкретнее

На данный момент я собираю прототип игрушки-платформера, показывающей (это, наверное, банально) приключения воина-викинга по пути из далеких от его родины мест в сторону дома (семьи, счастья). Ему будут противостоять всякого рода агрессивно настроенные мистические существа, с разными игровыми поведениями, динамикой действий и размерами (от сравнимых с персонажем до тех, которые крупнее его в несколько раз). Весь "путь" будет представлен в виде нескольких уровней, графика которых будет соответствовать "этапу" прохождения. Например, в самом начале, персонаж окажется у разбитого корабля, скалистого побережья, плавно перетекающего в густой лес, населенный всякими монстрами. В качестве оружия — нечто среднее между самострелом и дробовиком.

Возможно когда-нибудь я буду дополнять игрушку возможностью мультиплеерного режима. Но об этом пока рано говорить.

gfx_player.swf   (14.0 Кб)


Нажмите на изображение для увеличения
Название: design.jpg
Просмотров: 252
Размер:	166.8 Кб
ID:	355

Предварительный дизайн. Рисовал очень классный иллюстратор oneappleinbox



Программное устройство

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

Так как, я не знаю, в каком виде игра будет работать (в браузере, десктопно или на девайсах), я решил использовать Starling для рендеринга, Nape для физики и не фиксировать экранные размеры игры. Таким образом, я могу спокойно растягивать окно игры, которая, в свою очередь, адекватно смасштабируется. Естественно, это работает для разумных размеров.

Технически игра представляет собой основную флэшку и несколько подгружаемых. Подгружаемые флэшки — это уровни. Основная флэшка — это игровой движок. Далее я постараюсь расписать работу программных частей игры в последовательности их использования в игре.

Если не брать в расчет стандартный для FD класс Preloader, то стартовой точкой в игре являются два класса — Main и GameSettings.


GameSettings

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

Вот небольшой кусочек кода для наглядности:

Код AS3:
static public const PHYSICS_GRAVITY:Vec2 = new Vec2(0, 1200);
static public const PHYSICS_VELOCITY_ITERATIONS:int = 5;
static public const PHYSICS_POSITION_ITERATIONS:int = 5;
static public const PHYSICS_BROADPHASE:Broadphase = Broadphase.DYNAMIC_AABB_TREE
 
static public const RENDER_LANDSCAPE_BLOCKS:Boolean = false;
static public const RENDER_ANIMATED_ELEMENTS_FRAMERATE:int = 20;
static public const RENDER_ANIMATED_ELEMENTS_FROM_RANDOM_FRAME:Boolean = false;
 
static public const RENDER_TEXTURE_SMOOTHING:String = TextureSmoothing.NONE;
static public const RENDER_ANTIALIASING:int = 0;	
 
static public const RENDER_ATLAS_SIZE:int = 2048;
static public const RENDER_SUBTEXTURE_SUBSIZE:int = 1;
static public const RENDER_SUBTEXTURE_SIZE:int = 256;
static public const RENDER_SUBTEXTURE_PACK_MARGIN:int = 1;
 
static public const RENDER_USE_BLENDMODE:Boolean = true;
 
static public const TEST_ELEMENTS_VISIBILITY:Boolean = true;
static public const TEST_BACKGROUND_PARTS_VISIBILITY:Boolean = true;
static public const STOP_INVISIBLE_PARTICLES:Boolean = true;

Main

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

В общем, вот те самые классы, которые инициализируются в мэйне (их назначение очевидно из названия, как мне кажется):
  • KeyInputManager
  • SoundManager
  • GameController
  • LevelLoader
  • ScreenManager

Так вот на старте игры, в мэйне, я инициализирую все эти классы. Некоторым я передаю ссылку на стэйдж, некоторым передаю в параметры ссылку на метод, который должен быть запущен после того, как класс инициализируется (callback). Последний случай — это класс GameController.


GameController

Это основной класс игры. Он контролирует запуск игрового процесса, паузу при неактивности, выход из режима игры (когда переходим к стартовому экрану) и так далее. На старте он инициализирует и "связывает" четыре важнейших компонента — GameRenderer, GamePhysics, PlayerController и EnemiesController. О них чуть позже.


GameRenderer

Этот класс обеспечивает отображение игры на экране и предоставляет доступ до всяких эффектов, например эффект вспышки или эффект "встряхивания" экрана. На старте он создает игровые слои — несколько старлинговых спрайтов, в которые будут добавляться игровые элементы. Фон, например, на самый нижний слой. Эффекты (партиклы) — на самый высший. Для рендеринга с помощью старлинга, этот класс инициализирует класс StarlingRenderer.


StarlingRenderer

Вопреки тому, как рекомендуют использовать старлинг, когда старлинг инициализирует главный класс приложения ( new Starling(StarlingMain, ...) ), я его использую только для экрана с игрой. Все остальные экраны (меню, помощь, загрузка и так далее) сделаны нативными дисплэйобджектами.

StarlingRenderer — это класс-оболочка, который инициализирует старлинг и имеет статические методы типа addChild, addChildAt, start, stop, show, hide и так далее. Так же класс автоматически подписывается на ресайз стэйджа и подгоняет стэйдж старлинга до необходимых размеров.

Я посчитал такое решение наиболее удачным для моих целей, так как я максимально изолировал старлинг (который мне во многих моментах не нравится, хоть его и преподносят, как, чуть ли, не промышленный стандарт) от других частей программы и мне достаточно только "кинуть" старлинговый дисплэйобджект в статичный метод StarlingRenderer`а addChild и насладиться его изображением на экране. Если кодом, то это выглядело бы так:


Код AS3:
StarlingRenderer.init( stage, onStarlingReady );
 
...
 
private function onStarlingReady():void{
	StarlingRenderer.addChild(new Image(Texture.fromColor(100, 100, 0xFFFF0000))
}
Чтобы была понятна структура на данном этапе рассказа, приведу иллюстрацию:

Название: 1.png
Просмотров: 1854

Размер: 15.5 Кб

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

Игровой уровень — это .swf-файл с экспортной графикой и несколькими строчками кода. Фактически, это флэшка, скомпилированная из Flash IDE, у которой в библиотеке лежат несколько десятков мувиклипов (с проставленными "Export for ActionScript") и есть код в первом кадре основной временной шкалы.

Итак, по-порядку.

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

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

Мне довольно сложно описать это словами, поэтому чуть ниже прилагаю поясняющие картинки.

Первый вариант — используем блоки:

Нажмите на изображение для увеличения
Название: 2.png
Просмотров: 264
Размер:	18.6 Кб
ID:	351

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

Из минусов — очевидно, что будут отсутствовать наклонные поверхности, да и произвольную графику (по размерам) было бы проблематично внедрять.

Второй вариант — используем большую картинку для уровня и физическую модель (карту):

Нажмите на изображение для увеличения
Название: 3.png
Просмотров: 238
Размер:	95.7 Кб
ID:	350

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

Так, как я хочу получить относительно простыми средствами довольно разнообразную картинку, да и, к тому же, с различными физическими поведениями элементов, я использовал такой способ: создаю в исходнике уровня новый мувиклип, рисую в нем несколько кадров примерно одинакового размера и задаю этому мувиклипу экспортное имя класса, например, "gfx_dynamic_transparent_box_2". Приставка "gfx_" в данном случае нужна мне для "фильтрации" реальной игровой графики от возможного "мусора" на карте уровня. После приставки идет часть названия класса, которая точно характеризует физическое поведение объекта, который будет создан движком. "dynamic_transparent" означает, что этот объект будет динамическим и прозрачным для игрока и противников. Последняя часть названия — произвольная и ассоциативная. Если коробка — так и назову, "box".

Движок, после того, как загрузит уровень, первым делом "полезет" в код первого кадра. Так как флэш обернет этот код в автоматически создаваемый класс, то все переменные, которые в этом коде прописаны, автоматически станут public-свойствами класса. Одно из таких свойств — "levelMapClass". В коде это прописано таким образом:

Код AS3:
this.levelMapClass = gfx_level;
Значение этой переменной, соответственно, ссылается на экспортное название класса мувиклипа, в котором лежит графика уровня именно в тех местах, в которых она должна находиться уже в игре.

Далее движок, точнее та его часть, которая отвечает за парсинг уровня, создает несколько "экстракторов". Так я назвал классы, чья задача сводится к тому, чтобы распарсить отдельный тип данных карты и создать элементы уже в игровом пространстве. Из-за того, что моментальный парсинг был бы слишком ресурсоемким и мог бы просто "подвесить" флэшку, я написал вспомогательный класс для отложенного выполнения действий, TaskChainResolver. Его работа довольно простая и, думаю, станет понятна после описания методов:

Код AS3:
addTask(method:Function, repeatsPerFrame:int = 1, methodArguments:Array = null):void
 
start(allCompleteCallBack:Function = null):void
 
abort():void
Все экстракторы наследуются от BaseExtractor`а, в конструкторе которого создается новый TaskChainResolver. Таким образом, для каждого типа элементов уровня у меня задействован свой экстрактор, который парсит свою задачу не моментально, а течение некоторого времени. Это время зависит от количества элементов на уровне и количества повторений метода парсинга за один проход TaskChainResolver`а. Это количество повторений для разных по сложности задач, я вынес в GameSettings, где они выглядят следующим образом:

Код AS3:
static private const TASKS_COUNTER_COEFF:int = 5;
static public const HARD_TASKS_COUNTER:int = 1 * TASKS_COUNTER_COEFF;
static public const NORMAL_TASKS_COUNTER:int = 5 * TASKS_COUNTER_COEFF;
static public const EASY_TASKS_COUNTER:int = 10 * TASKS_COUNTER_COEFF;
Тут TASKS_COUNTER_COEFF используется как коэффициент для значений количества итераций. Тестирую на компьютере — выставляю в 1000 и получаю почти моментальный запуск игры, но с небольшим подвисанием флэшки.

Распределение по сложности задач (HARD, NORMAL и EASY) весьма условно и я толком еще не тестировал оптимальность выбранных значений.

В общей сложности я использую пять экстракторов:
  • BackgroundExtractor
  • ElementsExtractor
  • ParallaxExtractor
  • ForegroundExtractor
  • SettingsExtractor

Работа каждого из них в коде выглядит аналогичным образом:

Код AS3:
_elementsExtractor = new ElementsExtractor();
_elementsExtractor.setLevelData(_levelData, _levelInstance);
_elementsExtractor.setCallbacks(_nextTaskCallback, _onExtractElement, _onExtractProgress);
_elementsExtractor.startExtract();
Каждый из них во время своей работы запускает колбэк _onExtractElement который ссылается на метод manageNewLevelElement у основного класса игры GameController`а и передает в него новую игровую сущность наследуемую от GameElement.

GameElement — это основополагающий класс любого игрового элемента, будь то фон или коробка на земле или сам персонаж. Из всего разнообразия возможных элементов я выделил ключевые и общие свойства (сеттеры в данном случае представлены как паблик-свойства):

Код AS3:
public var isDead:Boolean;
public var body:Body;
public var image:DisplayObject;
public var type:String;
public var atlasId:int;
public var speed:Number;
public var usePhysics:Boolean;
public var useGraphics:Boolean;
public var useJuggler:Boolean;
public var lifes:Number;
Из представленного списка, думаю, что самыми интересными являются speed и atlasId. В игре я планирую использовать динамическое течение времени, от буллет-тайма до 150-процентного ускорения (естественно, параметры скорости будут подобраны). В динамичные моменты игры (во время боя с двумя или более противниками) будет включаться ускорение, во время разрушений или "контузии" (это уж как сделаю) — торможение.

В прототипе, например, при клике я создаю "взрыв" с последующим замедлением времени (восстанавливающимся):

— в физическом мире "раздаю" импульсов динамическим объектам, которые находятся близко к эпицентру взрыва (сила импульса квадратично убывает в зависимости от расстояния от центра)

— происходит вспышка экрана (накладывается starling.display.Quad с BlendMode.ADD у которого снижается прозрачность)

— встряска экрана

— уменьшение параметра deltaTime у метода step (nape)

— торможение фоновой музыки

— торможение анимаций старлинг-мувиклипов и партиклов

Что касается atlasId — для каждого отображаемого элемента это номер текстурного атласа, из которого он использует свою текстуру. Этот параметр создан для того, чтобы снизить количество обращений на отрисовку к видеокарте (drawCall), сортируя элементы по глубине. Эта возможность так же может быть отключена из GameSettings. Для меня это было неочевидно,так как я не сразу нашел необходимую информацию о том, что "extra draw calls" бывают, если перемешать по глубине элементы с разными текстурными атласами.


Экстракторы

SettingsExtractor

— этот экстрактор запускается первым и не создает каких-либо игровых элементов. Он занимается тем, что "достает" все настройки уровня и записывает их в экземпляр актуального класса с описанием уровня (LevelData).


BackgroundExtractor

— экстрактор, который создает на уровне статическую картинку фона, которая масштабируется аналогично с флэшовым стэйджем с настройкой StageScaleMode.NO_BORDER


ElementsExtractor

— экстрактор, который создает элементы уровня. Упрощенная последовательность его работы следующая:

1. Временно создает экземпляр мувиклипа с элементами игры.

2. Создает список разных элементов, которые есть на уровне.

3. Каждому элементу обнуляет матрицу трансформаций и отрисовывает каждый его кадр в битмапдату.

4. Анализирует элемент. Если в нем есть вложенный прямоугольник gfx_bounds_clip, то использует этот элемента как маску для графики.

5. Анализирует прозрачные области полученных битмапдат и, по необходимости, обрезает ненужные прозрачные участки.

6. Собирает все битмапдаты и упаковывает их в большие битмапдаты с помощью алгоритма max rects (добавляя пробелы исходя из настроек).

7. Параллельно с предыдущим пунктом, заполняет хмл-ки для текстурных атласов.

8. Создает текстурные атласы с соответствующими хмл-ками из больших битмапдат.

9. Заново проходит по всем элементам уровня и для каждого создает игровой элемент, сохраняя матрицы трансформаций и свойства наложения (для сопоставления флэшового блендмода и старлинг-блендмада написан отдельный класс). Если элемент на карте уровня имеет несколько кадров, то выбирается произвильный кадр. Физическое представление элемента, то есть, прямоугольник, подгоняется под размеры изображения. Класс игрового элемента, который создается, выбирается из соображений максимального вхождения названия класса в название класса элемента. Таким образом, имея классы StaticBlock и StaticTransparentBlock и элемент с названием класса "gfx_static_transparent_box_2", будет использован класс StaticTranspanretBlock, так, как он наиболее полно соответствует названию.

10. Обнуляет ссылки и уничтожает промежуточные битмапдаты.

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

Все размеры для текстурных атласов, а так же размеры отступов и параметры из серии "делать или не делать" (ну или "проверять или нет") вынесены в GameSettings.

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

Упрощенный принцип его работы:

Нажмите на изображение для увеличения
Название: 5.png
Просмотров: 310
Размер:	100.8 Кб
ID:	353

ParallaxExtractor

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

Код AS3:
this.levelParallaxClasses = [ gfx_level_bg_4, gfx_level_bg_3, gfx_level_bg_2, gfx_level_bg_1 ];
this.levelParallaxSettings = [ 2.5, 2.15, 1.75, 1.5 ];
Соответственно, я указываю массив классов с картинками для фонов и настройки динамики их сдвига. Для первого параллакс-фона торможение составляет 2,5 раза. То есть, при перемещении персонажа на 250 пикселей вправо, этот фон подвинется на 100 в ту же сторону.

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

Принцип работы такого экстрактора схож с предыдущим. Он создает экземпляр фона, условно делит его на множество "кусочков", проверяет каждый кусочек на прозрачности, создает текстурный атлас и элементы для каждого из кусочков. Создаваемые элементы являются частью игрового элемента Parallax. Во время игры, при перемещении, происходит проверка видимости "кусочков", исходя из результатов которой, те "кусочки", которые находятся вне игрового вьюпорта, исчезают. Относительно производительности такого подхода — я пока не проводил тесты.

ForegroundExtractor

— экстрактор, работа которого полностью аналогична работе ParallaxExtractor`а, за исключением того, что обрабатывается один фон, а его элемент создается поверх слоя с элементами игры (динамические блоки, противники, персонаж и т.д.).

Чтобы было понятнее, как выглядит уровень, приведу иллюстрацию (здесь два параллакс-фона):

Нажмите на изображение для увеличения
Название: 4.png
Просмотров: 241
Размер:	63.3 Кб
ID:	352



Заключение

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

И да, я прекрасно понимаю, что у меня не идеальные знания, во многих вещах я могу ошибаться (в том числе в терминологии, именовании классов и грамматике), так что если у вас есть замечания — буду только рад. Ибо пока только учусь делать игрушки.

P.S. Прототип пока не буду показывать.
Вложения
Тип файла: swf gfx_player.swf (14.0 Кб, 1022 просмотров)
Всего комментариев 21

Комментарии

Старый 20.04.2013 01:27 iNils вне форума
iNils
 
Аватар для iNils
Отличная статья! И очень радует оформление, прямо образцово-показательное
Старый 20.04.2013 14:28 Hauts вне форума
Hauts
 
Аватар для Hauts
Спасибо, вождь! Было бы очень здорово wmode='direct' сделать для встраиваемых флэшек.
Старый 20.04.2013 14:49 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Выбор Stage3D для Flash-игры (не для девайсов) все еще является ошибкой, которая скорее всего всплывет на этапе продажи.
Старый 20.04.2013 15:13 Hauts вне форума
Hauts
 
Аватар для Hauts
Zebestov, я не для продажи делаю. Можно описать подробнее, почему так?
Старый 20.04.2013 15:37 samana вне форума
samana
 
Аватар для samana
Спасибо за статью! Прочитал с удовольствием!
Старый 20.04.2013 16:10 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Hauts, среди многочисленных порталов (даже крупных) все еще много слоупоков, неспособных прописать в своих движках wmode direct. А это сильно бьет по распространению игры, ради которого, главным образом, ее и покупают. Есть исключения, но это и игры исключительные, как по качеству, так и по масштабу реализации всяких ништяков наподобие мультиплеера, интеграции в социальные сети и т.п.
Старый 20.04.2013 16:11 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
А статья хорошая.
Старый 20.04.2013 17:25 Tails вне форума
Tails
 
Аватар для Tails
Zebestov,
wmode direct. А у каких из крупных порталов проблемы с этим?
Старый 20.04.2013 18:15 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Tails, сейчас точно не скажу. Поддержка direct на своем портале — это еще даже не полдела. Необходимо, чтобы игра разлетелась по средним/мелким порталам и корректно запускалась именно там. С этим по-прежнему затык.
Старый 20.04.2013 19:52 Hauts вне форума
Hauts
 
Аватар для Hauts
Можно, наверное, попробовать вариант с автоподменой wmode с помощью ExternalInterface.
Старый 20.04.2013 22:45 Inet_PC вне форума
Inet_PC
 
Аватар для Inet_PC
Спасибо за статью, понравилась. Жду продолжения, ну и результат конечно тоже.
Старый 22.04.2013 01:37 zuxul вне форума
zuxul
Никто Вам не даст права изменять способ вывода флешки, в том-то и затык. Только по благововению сверху. На самом деле, это не должно быть уже проблемой - время идет вперед, все меняется, и порталам все равно придется изменяться.
Старый 22.04.2013 18:55 PainKiller вне форума
PainKiller
 
Аватар для PainKiller
Статья супер, большое спасибо, жду продолжения. Я тоже подумывал о написании платформера, для себя, но я бы писал на цитрус энжин, а у вас все свое и это интересней. Что же касается wmode, то поменять его JS-инъекцией действительно не проблема (если конечно allowScriptAccess == true), но не знаю как к этому отнесется администрация этих порталом, если попробуете расскажите про их реакцию.
Старый 22.04.2013 19:34 Hauts вне форума
Hauts
 
Аватар для Hauts
PainKiller, спасибо. Я пока не думал над тем, что с игрой делать дальше, после того, как я ее доделаю. Да и доделаю ли я ее — тот еще вопрос.
Старый 22.04.2013 22:32 alatar вне форума
alatar
 
Аватар для alatar
Как минимум половину логики ElementsExtractor имеет смысл вынести в редактор уровней или отдельной утилитой сделать, чем каждый раз запускать генерацию атласов на клиенте.
Старый 22.04.2013 22:59 Hauts вне форума
Hauts
 
Аватар для Hauts
Верно. Так и планировал. Только не на данном этапе, сейчас мне главное доделать, а подменить модуль уже не проблема будет, как мне кажется.

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

А относительно уровней и генерации атласов на клиенте — мне, в какой-то момент, показалось это весьма удобным. Например, я могу хранить уровень на своем сервере, периодически обновлять его. Так же могу, например, добавлять новые уровни (ведь список доступных уровней так же подгружаем).

Если использовать какую-либо утилиту для "упаковки" уровней — у меня получится еще один технологический процесс между исходником во флэше и самим игровым движком. Мне это кажется избыточным на данном этапе.

[ флэш — сфв уровня — утилита — тестирование ] — и так пока не получится хороший уровень.

А сечас у меня получается так:

[ флэш — сфв уровня — тестирование ]

Ну и, тем более, что я получу в итоге? Сразу готовые пнг для атласов, хмл-ки для них же и... всё. Просто, получается, пропускаю отрисовку разных элементов в их битмапдаты и упаковку этих битмапдат в атласы. Меня эти действия не сильно расстраивают, дело в нескольких секундах. Утечек памяти я стараюсь избегать, очень старательно следя за всеми ссылками и объектами во время распаковки и парсинга, ну да, потребление памяти подскакивает под 100Мб в этот момент, но потом до ~25 спадает, как игра начинается.

Да, это заманчиво, будет шустро работать на клиенте (подготовлено же всё будет). Но и значительно усложнит мою разработку, как мне кажется, и по времени и по сложности. А это для меня, одни из самых решающих факторов, которые постоянно пытаются одержать верх над моим желанием и умением.
Обновил(-а) Hauts 23.04.2013 в 08:54
Старый 23.04.2013 15:22 Котяра вне форума
Котяра
 
Аватар для Котяра
Проблема может быть в iOS. Просто так подгружать уровни с swf они не дают.
Даже в последней версии всё равно будет
[ флэш — сфв уровня — упаковка кода и обрезание swf - тестирование ]
Старый 23.04.2013 15:29 alatar вне форума
alatar
 
Аватар для alatar
Цитата:
Например, я могу хранить уровень на своем сервере, периодически обновлять его. Так же могу, например, добавлять новые уровни (ведь список доступных уровней так же подгружаем).
Это никак не зависит от того где генерируются атласы. Но при генерации на клиенте (в вашей реализации), атласы будут генерироваться при каждом запуске уровня, даже если он не менялся и лежит в кеше браузера.
Цитата:
[ флэш — сфв уровня — утилита — тестирование ] — и так пока не получится хороший уровень.
Как насчет [подготовка графики (в любой программе) — редактор уровней — тестирование в редакторе уровней, пока не получится хороший уровень — упаковка уровня]?
Старый 23.04.2013 17:30 Hauts вне форума
Hauts
 
Аватар для Hauts
Котяра, спасибо больше, учту. А можно ли какую-нибудь ссылку на хорошую статью про это? Или вся информация, как часто бывает, раскидана по кусочкам в поиске гугла?

alatar, я как-то не в тему написал про хранение на сервере, да
Цитата:
Это никак не зависит от того где генерируются атласы. Но при генерации на клиенте (в вашей реализации), атласы будут генерироваться при каждом запуске уровня, даже если он не менялся и лежит в кеше браузера.
Это верно, именно так.

Цитата:
Как насчет [подготовка графики (в любой программе) — редактор уровней — тестирование в редакторе уровней, пока не получится хороший уровень — упаковка уровня]?
Тут, в общем-то, вопрос в том, что является тестированием. Графика элементов уровня — это половина. Вторая половина — их поведение, которое обеспечивается с помощью физики. Поэтому тестирование для меня — это натуральный многократный запуск игры. Даже, скорее, отладочной версии игры.

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

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

Да и редактор для уровня — вполне себе так полноценная серьезная задача. Рисуем с полтысячи всевозможных элементов, обрезаем их по габаритам, чтобы не было прозрачных областей, загружаем в редактор, там множество элементов объединяем по типам игровых элементов (например, у меня 15 вариантов внешнего вида сундука), потом расставляем элементы (вращаем, масштабируем, меняем прозрачности, свойства наложения, искажения), потом собираем в текстурные атласы... Уф. В общем, это не менее простая (в т.ч. и по времени) задача для меня.
Старый 23.04.2013 20:01 alatar вне форума
alatar
 
Аватар для alatar
Цитата:
Вторая половина — их поведение, которое обеспечивается с помощью физики. Поэтому тестирование для меня — это натуральный многократный запуск игры. Даже, скорее, отладочной версии игры.
Поясню подробнее. В моем понимании редактор уровня содержит движок игры и позволяет запустить редактируемый уровень непосредственно в редакторе (или из редактора). Под тестированием я имел ввиду именно запуск игры.
Цитата:
Рисуем с полтысячи всевозможных элементов
Они в любом случае рисуются.
Цитата:
обрезаем их по габаритам, чтобы не было прозрачных областей, загружаем в редактор...
Эти алгоритмы у вас уже есть, можете запускать их на этапе загрузки ресурсов в редактор уровней.
Цитата:
например, у меня 15 вариантов внешнего вида сундука
Большинство элементов одинаковы для всех уровней, как правило, их выносят в отдельный файл ресурсов, для уменьшения загружаемых объемов данных.
Старый 23.04.2013 20:51 Hauts вне форума
Hauts
 
Аватар для Hauts
alatar, я вас понял, спасибо за разъяснение!

Да, хорошая штука была бы. Но мне пока не до нее
 
Последние записи от Hauts

 


Часовой пояс GMT +4, время: 13:20.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.