Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Хранение и вывод иллюстраций для игры (http://www.flasher.ru/forum/showthread.php?t=214902)

Wolsh 06.05.2018 13:11

Цитата:

как мне вернуть битмапку из метода getLoadedAsset, когда она становится доступной только в методе completeHandler?
Ответ содержится в вопросе. Никак.

Непонятно, зачем использовать асинхронный Loader в AIR-приложении для чтения файлов с диска. Есть же FileStream.

Appleman 06.05.2018 15:27

Да, я так и думал :) Мне тут страницей выше рекомендовали Loader, т.к. FileStream, мол, больше для потокового аудио и видео. Ща попробуем, спасибо.

Добавлено через 46 минут
Вот до такого доковырялся сам.

Код AS3:

public function getLoadedAsset(fileID: String) : Bitmap // Загружает и возвращает asset
                {
                        var file: File = File.applicationDirectory.resolvePath("assets" + File.separator + "backgrounds" + File.separator + fileID + PNG);
                        var filestream: FileStream = new FileStream;
                        var bytes: ByteArray = new ByteArray;
                        var data: BitmapData = new BitmapData(800,600);
                        var rect: Rectangle = new Rectangle(0, 0, 800, 600);
 
                        trace(file.url);
 
                        filestream.open(file, FileMode.READ);
                        filestream.position = 0;
                        filestream.readBytes(bytes);
 
                        data.setPixels(rect, bytes);
 
                        var result: Bitmap = new Bitmap(data);
                        trace (result);
 
                        return result;                       
                }

Проблемных точек три:
Во-первых, периодически получаю ошибку [Fault] exception, information=Error: Error #2030: End of file was encountered.
Во-вторых, надо как-то заранее получать разрешение загружаемого файла. Я пока для теста написал в лоб 800*600, то это не дело.
Наконец, даже если всё получается без ошибок, то на экран какая-то каша выходит :)

И вообще, в правильном направлении двигаюсь?

Wolsh 06.05.2018 18:41

1. Стрим надо закрывать после чтения методом close();
2. B setPixels() нужно передавать пиксели, как ни странно, а не файл. Подсказка: файл изображения содержит еще кучу данных кроме собственно пикселей, а собственно "пиксели" в файле могут содержаться в сжатой архиватором форме, а то и вообще быть "вычисляемыми" в процессе декодирования изображения кодеком.
Резюме: нужен декодер, точнее декодерЫ основных форматов (либо один, если все изображения будут в одном формате). Годный декодер примет файл и выдаст битмапдату ее собственного размера синхронно. Насколько я помню, нативный набор AS3 предоставляет только асинхронный декодер в виде загрузки байтЭррей в Лоадер)) круг замкнулся.
Ищи кастомный декодер.
Ну, например https://github.com/furusystems/Aishi.../PNGDecoder.as

Appleman 06.05.2018 19:21

Хм... А стоит ли игра свеч, если есть нативный loader, который на раз-два всё загружает и отдаёт? В чём его такое подавляющее преимущество? Уже придумался рабочий вариант - при заходе в локацию сразу загружать пачку картинок от этой локации и с данными персонажами (и первое, и второе известно, файлов не должно быть много), забивая BitmapDat-ы в Dictionary, а потом просто отдавать по идентификатору. А при смене локации - убивать старые и заполнять новые.

Wolsh 06.05.2018 19:38

Это уж как вам нравится) Мое дело отвечать на поставленные вопросы)

ZergMaster 06.05.2018 23:26

Цитата:

Сообщение от Appleman (Сообщение 1205118)
Друзья!

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

Код AS3:

public function getLoadedAsset(fileID: String) : Bitmap 
                {
                        var file: File = File.applicationDirectory.resolvePath("assets" + File.separator + "backgrounds" + File.separator + fileID + PNG);
                        var request: URLRequest = new URLRequest(file.url);
 
                        trace(file.url); // Показывает правильный путь
 
                        var loader: Loader = new Loader();
                        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
                        loader.load(request);
                        trace(loader.content); // null                       
                }
 
                private function completeHandler(e: Event) : void
                {
                        var loader: Loader = Loader(e.target.loader);
                        var image: Bitmap = Bitmap(loader.content);
                        trace(image); // [object Bitmap]
                }

То есть как мне вернуть битмапку из метода getLoadedAsset, когда она становится доступной только в методе completeHandler?

Не совсем православный, но самый очевидный и рабочий вариант - через функцию-callback
Код AS3:

public function getLoadedAsset(fileID: String, callback:Function) : void
                {
                        var file: File = File.applicationDirectory.resolvePath("assets" + File.separator + "backgrounds" + File.separator + fileID + PNG);
                        var request: URLRequest = new URLRequest(file.url);
 
                        var loader: Loader = new Loader();
                        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function():void
                            {
                                var loader: Loader = Loader(e.target.loader);
                                var image: Bitmap = Bitmap(loader.content);
                                callback(image);
                            });
                        loader.load(request);               
                }


Appleman 07.05.2018 00:05

ZergMaster, спасибо. Даже не знал, что так можно. А почему не православный?

Wolsh, я тогда с позволения поставлю вопрос, почему ты ратуешь на использование FileStream-а для AIR как альтернативы Loader-у. Кстати, я данную ветку сначала перечитал, вспомнил твою идею не выкладывать графические файлы как есть, а закатать их в один не-пойми-какой-снаружи файл, и оттуда при загрузке уже в программе нарезать картинки. С точки зрения такого подхода, есть какие-то аргументы "за" и "против" каждого из вариантов?

Wolsh 07.05.2018 07:09

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

Еще раз: выбор подхода зависит от особенностей проекта. Есть например такое понятие в UX, как ожидаемая задержка. То есть пользователь, взаимодействуя с программой, в какие-то моменты ДОПУСКАЕТ, что программа будет выполнять действие, не реагируя на него — например, при переходе между уровнями игры или при открытии дополнительного окна (инвентаря например). В другие моменты такая задержка пугала и раздражала бы, вызывая ощущение что программа "виснет" и "тормозит". Загружать иконки предметов при открытии Инвентаря — это нормально, но совершенно неприемлемо подгружать изображение пули в момент выстрела)) Надо учитывать эти моменты, решая что когда грузить — и то лишь в том случае, когда загрузить все заранее невозможно (например, просто нет такого понятия как элементы уровня: на любом уровне может понадобиться любой "предмет" игры, неизвестно заранее какой, а все ассеты весят столько, что памяти для нормальной работы не хватит).

ZergMaster 07.05.2018 12:40

Цитата:

Сообщение от Wolsh (Сообщение 1205131)
И эта колбэк-функция понятия не имеет, что за файл в нее свалился: если у "заказчика картинок" будет один такой приемный пункт, а картинок заказано несколько, то он точно так же не будет знать, в каком порядке они поступят в приемник (колбэк), то есть буквально про каждую картинку будет неизвестно, что это такое, что за файл.

да, поэтому на этот случай правильней было бы, конечно, сделать так
Код AS3:

callback(fileID, image);

Цитата:

А почему не православный?
Потому что безымянная функция, над которой мы не имеем никакой власти. Если ими пользоваться бездумно, то начинает происходить всякая чертовщина. Иногда её удобно использовать, если компактно и пока никто не видит. Но если не чувствуешь в себе силы джедая, то правильней оформлять callback через private переменную, тогда и от безымянной функции можно избавиться.

Appleman 08.05.2018 00:57

Пока забил болт и Loader-ом сделал, как и планировал: при выборе персонажа - забиваем в Dictionary графику для персонажа, при выборе локации - картинки от данной локации и т.п.

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

Плюс есть ещё пара вопросов крупных, пойду с ними в тему про MVC. :)


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

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