![]() |
Хранение и вывод иллюстраций для игры
Друзья, вопрос по gui. Спасибо за дельные советы, прекрасно получилось организовывать все мелкие графические объекты (иконки, портреты персонажей, предметы и т.п.) в атласы. Все координаты хранятся в XML, выдаются по строковому идентификатору, загрузить саму BitmapData - дело техники. Красота!
Но вот встал вопрос, что делать с фоновыми картинками. В разрабатываемой мною игре (текстовый квест, под AIR) полноразмерные арты - основной и по сути единственный способ демонстрации происходящего игроку. Их будет много. В отличие от иконок, в спрайт-шит/атлас их не запихаешь. Лобовое решение - Embed-ить их всех и не впечатляться, но смущает ряд моментов. Во-первых, это будет лютый трэш и частокол, не то что аккуратный XML-чик. Во-вторых, не понимаю, как это будет с точки зрения расхода ресурсов. В общем, просьба поделиться опытом, как лучше организовывать хранение большого количества фоновых изображений, при условии, что выводятся они по одному в зависимости от контекста. Спасибо. |
класть рядом и грузить по мере надобности.
|
С помощью Filestream или URLLoader? Сорри за тупые вопросы, я тут совсем плаваю. А у отца родного нашего - Мука - по AIR ничего нет :(
|
стримами обычно грузят потоковые данные(аудио/видео).Для картинок хватит и обычного Loader'а
|
Если не хочется при установке игры выкладывать все изображения в папку игры "как есть", можно попробовать упаковать их в архивы по, например, локациям или уровням, если есть в игре какая-то линейность и можно предполагать, что вот сейчас и в течении какого-то игрового времени понадобятся только вот такие слайды. Затем по мере надобности можно брать нужный архив и распаковывать его во временную директорию (в AIR есть такая возможность, File.createTempDirectory()), чтобы не занимать оперативку, и оттуда уже таскать нужные слайды.
Более сложный вариант — читать изображения в оперативку файлстримом из какого-то общего файла-хранилища-всех-изображений, но для этого надо будет знать position первого байта и длину файла для каждого слайда, и хранить их либо в отдельной описи, либо в этом же файле. Тут уже нужен некоторый опыт ковыряния в файлах и инструмент для сборки этого самого файла. Зато "на выходе" будет какой-то непонятный файл, который никто не сможет запросто посмотреть или отредактировать по своему хотению. |
Так а что за игра то? Под плеер или под AIR?
Если под эйр то под какой, десктоп или мобильный? |
да, и не забудь указать Wolsh-а в команде разработчиков)))
|
Цитата:
Ещё общий краткий вопрос, пока писать не начал. Я правильно понимаю, что когда изображение уже больше не нужно, достаточно его просто убрать из DOC, отменить все висящие на нём слушатели событий и записать null в переменную, в которой оно хранилось? Или ещё что-то, чтобы нормально уходило и не занимало ресурсы? Цитата:
Цитата:
|
Цитата:
"убрать из DOC" ты можешь только Битмап, а он весит около килобайта. Мегабайты весит БитмапДата; указанный метод очищает память от нее. |
Цитата:
Код AS3:
|
Wolsh, спасибо.
caseyryan, спасибо. Я уже методом тыка, совмещённым со свойством nativePath, это место установил :) Туда спрайтшиты складываю. Сейчас подумываю приспособить уже имеющийся файл-менеджер для загрузки картинок. Цитата:
|
Цитата:
Посмотри как в старлинге устроен AssetManager. Это конечно не подойдет тебе с простым дисплей листом на 100%, но может навести на некоторые полезные мысли. Он умеет сам определять что за вид ресурса перед ним (правда простой проверкой расширения, но в обычном случае этого достаточно, если тебе не требуется определять ресурс без расширения, чтением байт заголовков), и сам раскладывает их по нужным массивам |
Цитата:
|
Embed вшивает ресурс в swf, увеличивая его конечный размер, например. А Loader загружает ресурс при исполнении.
|
и в чем разница грузить большую флэшку либо грузить легкую флэшку и потом долго тянуть все ресурсы?Еще раз: грузить надо тогда,когда это требуется и только то,что требуется.
|
Ну, это зависит от задачи.. А так то да, если подгружать, потихонечку надо. Вообще картиночки можно и сразу после загрузки подгружать. Смысл в том, что флешка уже будет работать и пользователь пока может почитать че-нить, как-то уже взаимодействовать даже быть может. Пока контент грузится
|
Цитата:
2) Способом с подгрузкой ты можешь загрузить в каждый момент вермени только те ресурсы, которые требуются в данный момент. Например ты загрузил игру и игроку доступен только первый уровень. Зачем тогда ему грузить второй, третий.. десятый и т.д. 3) Загруженные ресурсы очень сильно жрут оперативку. В случае с Embed, они будут сразу все загружены и будут висеть в памяти. Есть ещё такой момент, на некоторых операционных системах (например андроид) если приложение не ответило на запросы системы в течение какого-то времени, оно считается неактивным и убивается. Хотя такое есть и в винде, но там интервал времени ожидания больше. Embed может вызвать такое поведение. |
caseyryan Подойдет ли вариант, с ручной деактивацией ресурсов в менеджере? Например если какой-то объект не был активен в течении длительного времени. То есть поставить таймер на такие штуки и если они долго не активны, очищаем из менеджера свойства этого объекта. А потом когда опять будет вызов, подгружать заново, ибо Null. Тогда по идее вообще память будет по минимуму нагружаться.
|
Цитата:
Или звук. Может быть это звук удара, а игрок долго никого не бьет. Как ты определишь, нужно его считать неактивным, или нет? Ну и плюс, такое непредсказуемое поведение чревато внезапными включениями сборщика мусора, который будет подтормаживать весь процесс. Тут главное, чтобы оптимизация не доходила до маразма. Нам (современным программистам) повезло, у нас есть в распоряжении довольно много оперативной памяти и процессорных ресурсов. Можно себе позволить не оптимизировать вообще всё и вся. Я думаю, достаточно лишь заранее условно разделить ресурсы (вручную) на те, которые могут потребоваться в данный момент, и те, которые точно не нужны здесь и сейчас. И по этому принципу всё загружать или разгружать |
Друзья!
Вот что у меня получилось по части использования loader-ов. Файл находит по адресу и даже вроде как загружает. Но я никак не могу сообразить, как мне теперь его вернуть. Код AS3:
|
Цитата:
Непонятно, зачем использовать асинхронный Loader в AIR-приложении для чтения файлов с диска. Есть же FileStream. |
Да, я так и думал :) Мне тут страницей выше рекомендовали Loader, т.к. FileStream, мол, больше для потокового аудио и видео. Ща попробуем, спасибо.
Добавлено через 46 минут Вот до такого доковырялся сам. Код AS3:
Во-первых, периодически получаю ошибку [Fault] exception, information=Error: Error #2030: End of file was encountered. Во-вторых, надо как-то заранее получать разрешение загружаемого файла. Я пока для теста написал в лоб 800*600, то это не дело. Наконец, даже если всё получается без ошибок, то на экран какая-то каша выходит :) И вообще, в правильном направлении двигаюсь? |
1. Стрим надо закрывать после чтения методом close();
2. B setPixels() нужно передавать пиксели, как ни странно, а не файл. Подсказка: файл изображения содержит еще кучу данных кроме собственно пикселей, а собственно "пиксели" в файле могут содержаться в сжатой архиватором форме, а то и вообще быть "вычисляемыми" в процессе декодирования изображения кодеком. Резюме: нужен декодер, точнее декодерЫ основных форматов (либо один, если все изображения будут в одном формате). Годный декодер примет файл и выдаст битмапдату ее собственного размера синхронно. Насколько я помню, нативный набор AS3 предоставляет только асинхронный декодер в виде загрузки байтЭррей в Лоадер)) круг замкнулся. Ищи кастомный декодер. Ну, например https://github.com/furusystems/Aishi.../PNGDecoder.as |
Хм... А стоит ли игра свеч, если есть нативный loader, который на раз-два всё загружает и отдаёт? В чём его такое подавляющее преимущество? Уже придумался рабочий вариант - при заходе в локацию сразу загружать пачку картинок от этой локации и с данными персонажами (и первое, и второе известно, файлов не должно быть много), забивая BitmapDat-ы в Dictionary, а потом просто отдавать по идентификатору. А при смене локации - убивать старые и заполнять новые.
|
Это уж как вам нравится) Мое дело отвечать на поставленные вопросы)
|
Цитата:
Код AS3:
|
ZergMaster, спасибо. Даже не знал, что так можно. А почему не православный?
Wolsh, я тогда с позволения поставлю вопрос, почему ты ратуешь на использование FileStream-а для AIR как альтернативы Loader-у. Кстати, я данную ветку сначала перечитал, вспомнил твою идею не выкладывать графические файлы как есть, а закатать их в один не-пойми-какой-снаружи файл, и оттуда при загрузке уже в программе нарезать картинки. С точки зрения такого подхода, есть какие-то аргументы "за" и "против" каждого из вариантов? |
FileStream умеет читать из открытого файла фрагменты "от такого-то байта до такого-то".
Loader, конечно же, так не умеет. Если будет нужна какая-то одна иконка, лоадером придется грузить весь файл и только потом выискивать в нем нужный кусочек. В любом случае асинхронная загрузка требует сложного менеджмента: нужно постоянно точно знать, что это сейчас пришло в лоадер, именно потому, что последовательность получения файлов не совпадает с последовательностью запросов (асинхрон). Так же и вариант ZergMaster, использующий безымянного беса — только делает вид, что возвращает картинку заказчику. На самом-то деле он возвращает ее не в место вызова и уж конечно не сразу после вызова, а в еще одну функцию, колбэк-функцию. И эта колбэк-функция понятия не имеет, что за файл в нее свалился: если у "заказчика картинок" будет один такой приемный пункт, а картинок заказано несколько, то он точно так же не будет знать, в каком порядке они поступят в приемник (колбэк), то есть буквально про каждую картинку будет неизвестно, что это такое, что за файл. Асинхронность никуда не делась (она и не может деться, если используется асинхронная загрузка), проблема осталась такой же, как и была, только перенесена с больной головы на здоровую. Если можно использовать только лоадер (например, если файлы нужно забирать с сервера), то конечно правильный подход твой — загрузить и рассортировать всю пачку для текущего уровня до его активации. Я бы по возможности и при синхронной загрузке делал так же, но это уже зависит от задачи, от особенностей проекта. Синхрон нравится мне тем, что ты получаешь файл тут же, где запросил и точно знаешь что запросил и что с ним делать, не нужно городить систему надсмотрщиков и сортировщиков. Еще раз: выбор подхода зависит от особенностей проекта. Есть например такое понятие в UX, как ожидаемая задержка. То есть пользователь, взаимодействуя с программой, в какие-то моменты ДОПУСКАЕТ, что программа будет выполнять действие, не реагируя на него — например, при переходе между уровнями игры или при открытии дополнительного окна (инвентаря например). В другие моменты такая задержка пугала и раздражала бы, вызывая ощущение что программа "виснет" и "тормозит". Загружать иконки предметов при открытии Инвентаря — это нормально, но совершенно неприемлемо подгружать изображение пули в момент выстрела)) Надо учитывать эти моменты, решая что когда грузить — и то лишь в том случае, когда загрузить все заранее невозможно (например, просто нет такого понятия как элементы уровня: на любом уровне может понадобиться любой "предмет" игры, неизвестно заранее какой, а все ассеты весят столько, что памяти для нормальной работы не хватит). |
Цитата:
Код AS3:
Цитата:
|
Пока забил болт и Loader-ом сделал, как и планировал: при выборе персонажа - забиваем в Dictionary графику для персонажа, при выборе локации - картинки от данной локации и т.п.
У меня ещё тут по ходу мелкий вопрос возник. Я правильно понимаю, что после того, как каждый из Loader-ов закончил работу, с него нужно руками снять слушатели событий? Почему-то в хелпе Adobe-овском об этом ни слова ни в тексте, ни в примерах. Плюс есть ещё пара вопросов крупных, пойду с ними в тему про MVC. :) |
Цитата:
В обработчике нажатия на кнопку ты отписываешься от события? А если кнопка больше не нужна? А если нужна? Так же и с лоадером — кто сказал, что он может грузить только один файл? Тогда про что должен писать хелп? Это твое личное дело, отписываться или использовать лоадер дальше. |
Наверное, правильнее будет сказать, что хелп "не для ламерья" ;)
Я вспомнил, у меня так давеча с таймерами было, когда в теле метода каждый раз создавался новый таймер. Полагаю, при последовательной загрузке файлов, вполне можно создать лоадер на уровне класса, один раз повесить слушатели, а потом убрать, когда вся грядка будет загружена. |
Адобовский хелп всем хелпам хелп. На русском, всё расписано в деталях. Вот бы все хелпы были такими. :)
|
Цитата:
Но если ты будешь использовать локальный слушатель, и обработчик сделаешь анонимный, то время жизни слушателя, вместе с обработчиком будет равно времени его использования. Как только все загрузилось (например картинка) ты передал ее куда-то, не сохраняя ссылок на загрузчик, загрузчик больше не нужен и он становится доступным для сборщика мусора. Но как разработчик игр с 9 летним стажем, могу посоветовать максимально использовать одни и те же ресурсы ;) Делай пулы объектов, не удаляй ничего без надобности. Лучше заведи себе привычку делать ресет состояний старых объектов, чем создавать новые. Новые создавай только в крайнем случае, когда полноценный ресет сделать очень трудно (даже не могу себе представить такой ситуации, если все сделано правильно), либо объектов в пуле просто не хватает. Даже если ты грамотно от всего отписываешься, и сборщик все зачищает по феншую, весь этот процесс приводит к фризам в игре. Если нужен плавный геймплей, то это будет большой такой занозой в заднице, потому что сборщик может начать сборку в самый неожиданный момент Цитата:
|
Цитата:
|
Поясни плиз:
Цитата:
Цитата:
|
Цитата:
Цитата:
Код AS3:
|
caseyryan, спасибо, понятно.
|
| Часовой пояс GMT +4, время: 09:34. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.