PDA

Просмотр полной версии : стандартный preloader с FlashDevelop


pomuс
26.04.2013, 15:29
День добрый

Я всегда делал прелодер отдельным файлом swf. Сейчас мне понадобилось до начала добавления главной флешки подгрузить все внешние файлы из папки проекта и поместить их в Dictionary, а потом уже загрузить саму главную флешку.
Так вот нашел в FD возможность создания проекта с прелодером- мне как раз подходит, чтобы все классы( Dictionary например) передались для главной флешки.

Сам код прелодера копировать наверное нет смысла, т.к. он стандартный, единственно что я изменил, так это перенес слушатель на прогресс в условие ,когда все мои картинки подгрузились
if (counter == loaderArray.length) {
loaderArray.length = 0;
done = true;
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
}

но получается так что после этого ничего не происходит. Я пробовал поиграться со слушателями, ставить их в разных фазах, ловить трейсы, но так и не понял схемы.
Особенно мне не понятен поставленный слушатель в конструкторе прелодера на EnterFrame и сама функция
private function checkFrame(e:Event):void
{
if (currentFrame == totalFrames)
{
stop();
loadingFinished();
}
}
трейсы выдаю что просто идет переход на второй кадр, и все, практически мгновенно, как если бы запустить таймлайн. И это логично, ведь по логике просится чтобы где то после окончания загрузки шел этот переход, а он идут сразу.
Как же оформить это злосчастный прелодер?

GBee
26.04.2013, 15:33
так надо запускать главвный класс. а не класс прелоадера. У вас все прописано в главном?
[Frame(factoryClass = "Preloader")].

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

pomuс
26.04.2013, 15:41
GBee да, все прописано также, как если создать проект с прелодером изначально.
На форумах девелопера вычитал также что надо указать прелодер как главный класс проекта, а в Project Options --> Compiler Options ==> additional options прописать
-frame main Main
В общем что я там только не читал... не выходит ничего

да и вообще муть какая то, я когда делала прелодер сам, ставил еще слушатель на COMPLETE, и после него уже удалял все что нужно. Ну ладно, можно также и на прогресс, но только когда bytes.loaded == bytes.total.
А тут все действие происходит сразу же, так как висит EnterFrame... где смысл???

illuzor
26.04.2013, 17:03
Не уверен, что поможет, но можно попробовать так:
- правый клик по классу прелоадера: set document class
- удаляем из класса Main метатег: [Frame(factoryClass = "Preloader")]
- в параметрах компилятора пишем -frame two Main

А вообще, что мешает загрузить и распарсить данные в Main, и уже после этого спрятать прелоадер?

Wolsh
26.04.2013, 20:20
Сейчас мне понадобилось до начала добавления главной флешки подгрузить все внешние файлы из папки проекта и поместить их в Dictionary, а потом уже загрузить саму главную флешку....нашел в FD возможность создания проекта с прелодером- мне как раз подходитВы вообще понимаете разницу между внутренним и внешним прелоадером? Внутренний прелоадер показывает процесс загрузки того swf-файла, в котором он же и находится. А никаких не внешних файлов из папок и других флэшек.
Особенно мне не понятен поставленный слушатель в конструкторе прелодера на EnterFrame и сама функцияА тут все действие происходит сразу же, так как висит EnterFrame... где смысл???Смысл очень простой. Формат SWF устроен так, что подобно анимированному GIF, может начинать воспроизведение, не дожидаясь полной загрузки. Кадр загрузился — кадр показался. Но пока следующий кадр полностью не загрузится (то есть все что нужно для его отображения — классы, изображения, звуки и прочее), он не будет отображен, и переход на следующий кадр не произойдет. Если это вывернуть по смыслу, то получится что переход на следующий кадр является сигналом, что этот кадр полностью загружен. Итак, сначала загружается кадр, в котором находится прелоадер. Прелоадер ничего не знает об основном классе и всех ресурсах, которые ему нужны. Прелоадер максимально легкий, он быстренько загружается и отображается. Начинается загрузка следующего кадра, в котором как раз находится основной класс и тонны ресурсов. Он грузится долго, а прелоадер получает события прогресса и отображает загрузку. Загрузку того файла, частью которого сам же и является, это важно понять. Просто он УЖЕ заскочил и работает, а остальной хлам еще в пути. Как только все ресурсы второго кадра загрузятся, будет послано событие ENTER_FRAME, на которое (вместо COMPLETE) и подписан наш прелоадер.

pomuс
27.04.2013, 11:53
Вы вообще понимаете разницу между внутренним и внешним прелоадером? Внутренний прелоадер показывает процесс загрузки того swf-файла, в котором он же и находится. А никаких не внешних файлов из папок и других флэшек.
Так, вот теперь с вашей помощью понял. Просто с внутренним не сталкивался раньше вообще.
А как мне тогда грамотно организовать подгрузку элементов до начала главной флешки? Как я уже писал я решил пойти путем загрузки всех картинок в Dictionary и потом уже брать оттуда когда мне надо в проекте. В Данном случае у меня получается что картинки понадобятся только через несколько действий пользователя, поэтому они успевают подгрузиться, но что делать если мне они нужны будут сразу же при запуске главной флешки?
Стоит как то переписать внутренний прелодер(например самостоятельно сменить кадр после загрузки всех картинок) или есть какой то другой способ?
illuzor
не помогло.
А вообще, что мешает загрузить и распарсить данные в Main, и уже после этого спрятать прелоадер?
не очень понял, что вы имели ввиду

illuzor
27.04.2013, 15:57
pomuс, покажите весь ваш код прелоадера

pomuс
27.04.2013, 19:52
package
{
import com.FilesDictionary;
import com.InitArray;
import com.MyBitmap;
import com.XMLLoader;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.getDefinitionByName;

/**
* ...
* @author Ma3
*/
public class Preloader extends MovieClip
{
private var initArr:InitArray = new InitArray();
private var loaderArray:Array = new Array();
private var intervalArray:Array = new Array();
private var xmlList:XMLList;
private var counter:int = 0;
private var text:TextField = new TextField();
private var bar:Shape = new Shape();
private var done:Boolean = false;

public function Preloader()
{
if (stage) {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
}
addEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);

var xml:XMLLoader = new XMLLoader("xml/allBlocks.xml");
xml.addEventListener(XMLLoader.LOADED, fillDictionary);
xml.addEventListener(IOErrorEvent.IO_ERROR, ioError);

addChild(text);
text.selectable = false;
var myFormat:TextFormat = new TextFormat();
myFormat.size = 50;
myFormat.color = 0x222222;
myFormat.font = "PT Sans"
text.defaultTextFormat = myFormat;


bar.graphics.beginFill(0xD0AA66);
bar.graphics.drawRect(0, 0, 200, 3);
bar.graphics.endFill();
addChild(bar);
bar.x = stage.stageWidth / 2 - bar.width / 2 ;
bar.y = stage.stageHeight / 2 +15;
bar.scaleX = 0;

}

private function fillDictionary(e:Event):void
{

xmlList = e.target.xmlData.children();
for (var i:int = 0; i < xmlList.length(); i++) {
var loader:Loader = new Loader();
loader.load(new URLRequest(xmlList.@url[i]));

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
//loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
loaderArray.push(loader.contentLoaderInfo);
intervalArray.push(xmlList.@out[i]);
}
}

private function loadComplete(e:Event):void {
counter++;
var i:int = loaderArray.indexOf(e.currentTarget);
e.currentTarget.removeEventListener(Event.COMPLETE, loadComplete);

var name:String = xmlList.@url[i];
var bd:BitmapData = new BitmapData(e.currentTarget.content.width, e.currentTarget.content.height, true, 0x00FFFFFF);
bd.draw(e.currentTarget.content);
//var bitmap:Bitmap = Bitmap(e.currentTarget.content);
//var bitmap:Bitmap = new Bitmap(bd);
var bitmap:MyBitmap = new MyBitmap(bd);
bitmap.inter = intervalArray[i];
bitmap.smoothing = true;
//addChild(bitmap);
initArr.blockAll.sort();

FilesDictionary.instance.addFile(name.slice(7, -4), bitmap);

if (counter == loaderArray.length) {
loaderArray.length = 0;
done = true;
}
}

private function ioError(e:IOErrorEvent):void
{
trace(e.text);
}

private function progress(e:ProgressEvent):void
{
var percent:Number = Math.round(e.bytesLoaded / e.bytesTotal * 100);
var str:String = percent.toString();
text.text = str;
text.x = stage.stageWidth / 2 - text.width / 2 ;
text.y = stage.stageHeight / 2 - text.height / 2 ;
bar.scaleX = percent / 100;
/*if (e.bytesLoaded == e.bytesTotal && done) {
}*/
}

private function checkFrame(e:Event):void
{
if (currentFrame == totalFrames)
{
stop();
loadingFinished();
}
}

private function loadingFinished():void
{
removeEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
removeChild(text);
removeChild(bar);
startup();
}

private function startup():void
{
var mainClass:Class = getDefinitionByName("Main") as Class;
addChild(new mainClass() as DisplayObject);
gotoAndStop(2);
}

}

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

illuzor
27.04.2013, 20:04
Функцию startup() нужно запускать после того, как загружен воторой кадр (!)и обработан xml.

Лично я бы занялся обработкой xml уже в классе Main.

pomuс
27.04.2013, 21:03
illuzor каким же образом? До инициализации addedtoStage? мне же данные зачастую будут нужны уже в main.as и всех задействованных

Wolsh
27.04.2013, 22:20
pomuс, знаете, почему никто не понимает Вашей проблемы?
Потому что ее нет.
Все что Вам нужно это инициализировать тот класс, который Вы называете Main, после того как все будет загружено. То есть тупо создать его экземпляр после того, как настоящий документ-класс (точка входа в приложение) загрузит все ресурсы. Так в чем проблема то?

pomuс
28.04.2013, 11:25
illuzor, Wolsh
спасибо за очередное содействие, и прошу прощения если уже задаю какие то абсурдные вопросы..