Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   API приложений и сред (http://www.flasher.ru/forum/forumdisplay.php?f=61)
-   -   [Starling] Загрузка текстур в риалтайме (http://www.flasher.ru/forum/showthread.php?t=211652)

AlexCooper 09.10.2015 04:29

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

Код AS3:

override public function run():void {
 
        types = model.types;
 
        EmbeddedAssets.initialize();
 
        var loader:Load = new Load(types.assetPath(types.logo));
                loader.addEventListener(Event.COMPLETE, completeHandler );
                loader.start();
}
 
protected function completeHandler(event:Event):void
{
        var loader:Load = event.currentTarget as Load;
 
        AssetManager.instance.uploadByteArray( types.logo, loader.data );
 
        AssetManager.instance.loadQueue( release );
}

Код AS3:

package net.alexscript.worker.file
{
        import flash.events.EventDispatcher;
        import flash.net.URLRequest;
        import flash.net.URLLoader;
        import flash.net.URLLoaderDataFormat;
        import flash.events.Event;
        import flash.events.ProgressEvent;
        import flash.events.IOErrorEvent;
        import flash.utils.ByteArray;
 
        public class Load extends EventDispatcher {
 
 
                private var _file:String;
 
                public function Load(file:String) {
                        _file = file;
 
                }
 
                public var data:ByteArray = new ByteArray();
 
                public function start():void{
 
                        trace('start load: '+_file);
                        var request:URLRequest = new URLRequest(_file);
 
                        var urlLoader:URLLoader = new URLLoader(request);
                                urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
                                urlLoader.addEventListener(IOErrorEvent.IO_ERROR, completeError);
                                urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler );
                                urlLoader.addEventListener(Event.COMPLETE, onLoadedAndSave);
                }
 
                private function completeError(e:IOErrorEvent):void {
                        trace('error load: '+_file);
                        dispatchEvent(new Event(Event.COMPLETE));
 
                }
 
                private function onLoadedAndSave(e:Event):void {
                        data.writeBytes(e.currentTarget.data,0,e.currentTarget.data.length);
                        trace('complete load: '+_file);
                        dispatchEvent(new Event(Event.COMPLETE));
                }
 
                private function progressHandler(e:ProgressEvent):void {
                        dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS,false,false,e.bytesLoaded+data.length,e.bytesTotal));
                }
        }
}

Код AS3:

package com.state.model
{
        import flash.events.EventDispatcher;
        import flash.utils.ByteArray;
 
        import starling.textures.Texture;
        import starling.utils.AssetManager;
 
        public class AssetManager extends EventDispatcher
        {
 
                public static function get instance():com.state.model.AssetManager
                {
                        if (!_instance) _instance = new com.state.model.AssetManager();
 
                        return _instance;
                }
 
                private static var _instance:com.state.model.AssetManager;
 
                public function AssetManager()
                {
                        if (!_instance) {
                                super();
                                _instance = this;
                                png = new PNGDecoder();
                        }
                }
 
                public function uploadByteArray( key:String, byteArray:ByteArray ):void {
                        assetsMgr.addTexture( key, Texture.fromBitmapData(png.decode(byteArray)) );
                }
 
                public function loadQueue(_callback:Function):void
                {
                        assetsMgr.loadQueue(function(ratio:Number):void
                        {
                                Debug.log(' texture load '+ratio);
                                if (ratio == 1.0)
                                        _callback();
                        });
                }
 
                public function get assetsMgr():starling.utils.AssetManager {
 
                        if (!assets) assets = new starling.utils.AssetManager();
 
                        return assets;
                }
 
                private var assets:starling.utils.AssetManager;
                private var png:PNGDecoder;
 
        }
}

Код AS3:

package
{
        import flash.display.BitmapData;
        import flash.utils.ByteArray;
        import flash.geom.Matrix;
        import flash.geom.Rectangle;
 
        /*******************************
        PNGDecoder
        Author: Jerion
 
        A class that decodes png byte arrays and generates a bitmapdata.
        This is my first attempt at decoding images, so there are a lot of
        things that are not implemented.
 
        So far, it can only decode truecolour with alpha png images with
        no interlacing, no filter, and bit depth of 8.
        ********************************/

 
        public class PNGDecoder {
                private const IHDR:uint = 0x49484452;
                private const PLTE:uint = 0x504c5445;
                private const IDAT:uint = 0x49444154;
                private const IEND:uint = 0x49454e44;
 
                private var imgWidth:uint = 0;
                private var imgHeight:uint = 0;
 
                //file info, but not used yet.
                private var bitDepth:uint = 0;
                private var colourType:uint = 0;
                private var compressionMethod:uint = 0;
                private var filterMethod:uint = 0;
                private var interlaceMethod:uint = 0;
 
                private var chunks:Array;
                private var input:ByteArray;
                private var output:ByteArray;
 
                //recieves the bytearray and returns a bitmapdata
                public function decode(ba:ByteArray):BitmapData {
                        chunks = new Array();
                        input = new ByteArray();
                        output = new ByteArray();
 
                        input = ba;
 
                        input.position = 0;
 
                        if (!readSignature()) throw new Error("wrong signature");
 
                        getChunks();
 
                        for (var i:int = 0; i < chunks.length; ++i) {
                                switch(chunks[i].type) {
                                        case IHDR: processIHDR(i); break;
                                        //case PLTE: processPLTE(i); break;
                                        case IDAT: processIDAT(i); break;
                                        //case IEND: processIEND(i); break;
                                }
                        }
 
                        //Since the image is inverted in x and y, I have to flip it using a Matrix object. There should be a better solution for this..
                        var bd0:BitmapData = new BitmapData(imgWidth, imgHeight);
                        var bd1:BitmapData = new BitmapData(imgWidth, imgHeight, true, 0xffffff);
 
                        if (output.length > 0 && (imgWidth * imgHeight * 4) == output.length) {
                                output.position = 0;
                                bd0.setPixels(new Rectangle(0,0,imgWidth,imgHeight), output);
 
                                var mat:Matrix = new Matrix();
                                mat.scale(-1,-1);
                                mat.translate(imgWidth, imgHeight);
 
                                bd1.draw(bd0, mat);
                        }
 
                        return bd1;
                }
 
                //read the header of the image
                private function processIHDR(index:uint):void {
                        input.position = chunks[index].position;
 
                        imgWidth = input.readUnsignedInt();
                        imgHeight = input.readUnsignedInt();
 
                        //file info, but is not used yet
                        bitDepth = input.readUnsignedByte();
                        colourType = input.readUnsignedByte();
                        compressionMethod = input.readUnsignedByte();
                        filterMethod = input.readUnsignedByte();
                        interlaceMethod = input.readUnsignedByte();
                }
 
                //This can't handle multiple IDATs yet, and it can only decode filter 0 scanlines.
                private function processIDAT(index:uint):void {
                        var tmp:ByteArray = new ByteArray();
 
                        var pixw:uint = imgWidth * 4;
 
                        tmp.writeBytes(input, chunks[index].position, chunks[index].length);
                        tmp.uncompress();
 
                        for (var i:int = tmp.length - 1; i > 0; --i) {
                                if (i % (pixw + 1) != 0) {
                                        var a:uint = tmp[i];
                                        var b:uint = tmp[i-1];
                                        var g:uint = tmp[i-2];
                                        var r:uint = tmp[i-3];
 
                                        output.writeByte(a);
                                        output.writeByte(r);
                                        output.writeByte(g);
                                        output.writeByte(b);
 
                                        i -= 3;
                                }
                        }
                }
 
                private function getChunks():void {
                        var pos:uint = 0;
                        var len:uint = 0;
                        var type:uint = 0;
 
                        var loopEnd:int = input.length;
 
                        while (input.position < loopEnd) {
                                len = input.readUnsignedInt();
                                type = input.readUnsignedInt();
                                pos = input.position;
 
                                input.position += len;
                                input.position += 4; //crc block. It is ignored right now, but if you want to retrieve it, replace this line with "input.readUnsignedInt()"
 
                                chunks.push({position: pos, length: len, type: type});
                        }
                }
 
                private function readSignature():Boolean {
                        return (input.readUnsignedInt() == 0x89504e47 && input.readUnsignedInt() == 0x0D0A1A0A);
                }
 
                //transform the chunk type to a string representation
                private function fixType(num:uint):String {
                        var ret:String = "";
                        var str:String = num.toString(16);
 
                        while (str.length < 8) str = "0" + str;
 
                        ret += String.fromCharCode(parseInt(str.substr(0,2), 16));
                        ret += String.fromCharCode(parseInt(str.substr(2,2), 16));
                        ret += String.fromCharCode(parseInt(str.substr(4,2), 16));
                        ret += String.fromCharCode(parseInt(str.substr(6,2), 16));
 
                        return ret;
                }
 
        }
}

Вопрос в том, на сколько это оправданно со сторонны поддержки проекта, или же стоит смотреть в сторону ATF, без этих всех велосипедов.

caseyryan 09.10.2015 06:39

Цитата:

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

По поводу вопроса: зачем вообще это нужно? Чем старлинговский ассет менеджер не устраивает? Отличная штука. Я всегда пользуюсь только им и все отлично. Так же можно хоть когда по запросу подгрузить нужную текстуру

Zebestov 09.10.2015 11:15

ATF, если я не ошибаюсь (а я могу!), шикарен тем, что в GPU хранится сжатым(?).
Но если это не так (ответа в свое время в "ленивом режиме" я так и не нашел), то да, ATF — вообще какая-то лажа.

illuzor 09.10.2015 16:09

Цитата:

Нормальных инструментов для создания нет
Что понимается под нормальными инструментами? adobe даёт отличные тулзы с подробной документацией, которые с лёгкостью оборачиваются в bat/ant/gradle (нужное подчеркнуть). К тому же, TexturePacker давно умеет экспортировать в atf.
Цитата:

ATF, если я не ошибаюсь (а я могу!), шикарен тем, что в GPU хранится сжатым(?).
Размер atf файла меньше, чем размер аналогичного png, он грузится в gpu память быстрей, чем png и рендерится тоже быстрей. И да, он занимает меньше памяти gpu. Если для проектов с парой атласов это не критично, то для игр с большим количеством графики выгода очень заметна. Вплоть до того, что игра с png, вылетающая на слабых девайсах, при использовании atf работает нормально.
Также atf использует разные "родные" типы сжатия для разных платформ. Можно включить в файлы только версии для используемых платформ, что ещё уменьшит вес файла.

Zebestov 09.10.2015 16:22

Вот! Если таки да, то гут. Иначе — фигня какая-то битая.

AlexCooper 09.10.2015 17:27

Цитата:

Сообщение от caseyryan (Сообщение 1187842)
Нормальных инструментов для создания нет, все на уровне командной строки

Командная строка тоже программируется) Была мысль поднять на ейре автобилдер для ане с селектором sdk, вернее батник на msdos'e уже написал, только Воздух подключить, но для кмд у меня фикс есть и она мне не страшна)

Цитата:

Сообщение от caseyryan (Сообщение 1187842)
Чем старлинговский ассет менеджер не устраивает?

Если оставлю png, байтеррей нужен не по прямому назначению.


Цитата:

Сообщение от Zebestov (Сообщение 1187850)
ATF — вообще какая-то лажа.

Есть какие-то особенности?

Zebestov 09.10.2015 17:31

Выше написали про плюс — компактность размещения в памяти GPU.
Минус — как минимум джипежность. Целые семинары о том, как делать так, чтобы ATF-картинку мылом не покрыло.

AlexCooper 09.10.2015 17:45

Цитата:

Сообщение от illuzor (Сообщение 1187867)
TexturePacker

Как на меня он шикарен ( единственно что напрягает - пустые места )

Zebestov 09.10.2015 17:57

В смысле "пустые места"?

AlexCooper 09.10.2015 18:29

Цитата:

Сообщение от Zebestov (Сообщение 1187880)
В смысле "пустые места"?

Как мувиклипах, при не парном количестве кадров ( возможно рукикрюки )


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

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