Preloader , now that NMEPreloader is depreciated

thanks for update, @:Bitmap working for me within preloader now (where it wasn’t) on html5, windows, neko targets (will test android when i can);
@restorer posted that ProgressEvent.PROGRESS is only firing twice during loading for html target. I’m experience that also.
any event syntax to dismiss the preloader which doesn’t cause confusion would be sufficient i think !.

Oh, forgot those weren’t standard events. Will have to keep thinking

I have just updated the custom preloader behavior

Now the preloader dispatches ProgressEvent.PROGRESS then Event.COMPLETE while loading. The default will dispatch an Event.UNLOAD on COMPLETE to signal the ApplicationMain class to unload the preloader and execute the document (or “main”) class.

If you choose, you can event.preventDefault on Event.COMPLETE, and dispatch Event.UNLOAD at a time of your own choosing. This method allows us to use Event without adding new values to the class, and I think is consistent with the idea that the preloader will be unloaded, and the main application will be run. I agree that dispatching Event.COMPLETE a second time (and therefore having to remove your listener first) is more confusing.

I hope that this will be a better architecture with less special rules. Preloaders on mobile/desktop has been a long-requested feature, and I think the custom preloader extending a generated NMEPreloader class is not as friendly.

2 Likes

In fact, we might even use a separate SWF, JS file or executable to enforce a strict boundary between the preloader and the main application in the future. That would remove some restrictions we currently have (such as maximum SWF size), and perhaps make the preloading even more reliable. This is unimportant right now, but might support the Event.UNLOAD event more

Having a seperate .swf for preloading, wouldn’t really work when flash content is released virally into the wild. the beauty of .swf files is that all content code and assets can be bundled together in one file, and the initial frame (preloader) can be excecuted once its content code and assets are downloaded, which is completed even before even the main class actionscript is available! a seperate swf file wouldn’t give any extra benefits over this, other than mean that 2 .swf files would be needed to bundled together at all times.

The opposite is true of .JS. It would be hugely beneficial to have a seperate .js file for a preloader, which would need to be the only .js file referenced within the html of a page. All ofther .js files could be loaded from within that .js code as part of the preloading process. At the moment the entire .JS of the main project is loaded before a preloader can commence. Other .js files, like howler.min.js are loading synchronously, further delaying the start of the preloader !

Are there any chance to make preloader image to show up on native platforms?
If I do something like this, I can see my Back image on Flash target, but just black or white screen on native:

@:bitmap("assets/preload.jpg") class Back extends BitmapData {}
...
public function new()
{
  var bmpd:BitmapData = new Back(width, height);
  var back:Bitmap = new Bitmap(bmpd, PixelSnapping.AUTO, true);
  addChild(back);

  addEventListener(Event.ADDED_TO_STAGE, onInit);
  addEventListener(ProgressEvent.PROGRESS, onUpdate);
  addEventListener(Event.COMPLETE, onLoaded);
}

I’ve opened a new issue, we’ll try and see what’s up :slight_smile:

1 Like

Thanks a lot!
That the only thing preventing me from releasing the game on Android.

I think there is a crossover here, between “Splash Screen” images for android, and the anticipated use of an early starting preloader screen with progress

how-do-you-add-a-launch-image-splash-image-to-mobile/8628

so am posting this to make the link between the two discussions !

Any update on this? :innocent:

This is working currently on the desktop, I’ll check Android

Is there an @:font in order to show a text with custom font to show progress amount or other kinds of text like “Loading…”?

Tried this:
@:font("Data/Open Sans.ttf") class DefaultFont extends Font {}

Then on constructor:

        Font.registerFont(DefaultFont);
		loadedPercent = new TextField();
		
		var tFormat:TextFormat = new TextFormat();
		tFormat.font  = "Open Sans";
		tFormat.color = 0xAA0000;
		tFormat.size  = 24;
		tFormat.align = TextFormatAlign.CENTER;
		
		loadedPercent.setTextFormat(tFormat);
		loadedPercent.x         = 200;
		loadedPercent.y         = 200;
		loadedPercent.width     = 300;  
		loadedPercent.height    = 300; 
		loadedPercent.textColor = 0x000000;
		loadedPercent.backgroundColor = 0xFFFFFF;
		loadedPercent.text = "TEST";
		loadedPercent.selectable = false;
		loadedPercent.embedFonts = true;
		addChild(loadedPercent);

But seems I get an error in Flash/JS "TypeError: Error #1006: __fromBytes is not a function."

Also will there be a Preloader example that shows progressbar, background splash image, progress text during a preloader in the standard OpenFL examples?

Finally maybe a way to slow down a preloader so we can debug them easier instead of adding custom values and events to see if animations work?

Also I do disagree with splitting the Preloader and Main as two different SWF files, a lot of sites that allow SWF embedding do not support uploading more than 1 file.

I’ll take a look at embedded fonts on Flash

That’s a good idea – a custom preloader as a sample would be a good way to help document and test this :slight_smile:

The preload progress code is quite complex, I’m not sure there’s a way to fully simulate it, but I’m open to ideas for better debugging/testing

One of the older Flash Debug versions used to have a simulate loading option, where you could select the loading speed to test your loading/preloader locally at different download speeds.

edit :
I’ve just searched for this and found something better. There’s a built in Network speed throttle within the Chrome Browser. Press F12 for the Debug/Inspector, go to the network tab, you should see a “no throttling” option on the right of the sub menu - clicking it can change the throttling speed(loading speed) down, to as little as GPRS speed, 20Kb/s . (which is uncanilly the same speed my phone connects at when at home !)

I just added -Dsimulate-preloader=3000 to Lime :wink:

You can use -Dsimulate-preloader for a default simulation of 3 seconds, otherwise you can set a different time using a value.

Hope this is valuable :slight_smile:

Very nice, certainly will be useful!
I can use it as a haxeflag like <haxeflag name="-D simulate-preloader=5000" /> in my project.xml, right?

edit: Just checked and seems to work alright, though in Flash the ProgressEvent etc. seem not to be updated and the COMPLETE event is executed on start. The preloader delay is there though. HTML5 seems more stable.

edit2: I am tinkering with a preloader a little, you can check out the project here
It loads a splash/logo image, adds a percentage text and a progressbar (though doesn’t scale correctly, not sure how to make it scale from center, I am still too used to simple anchor/origin than Matrix manipulation)

Any luck with the @font embeds?

I just got it to work :slight_smile:

First, you should be able to remove “pixijs”, “openfl-tools” and “hxcpp” from the project.xml :slight_smile:

Second, we can’t override Flash’s loaderInfo events, unfortunately. As a result, you’ll need to use addEventListener instead of loaderInfo.addEventListener in your preloader to get our events. Similarly, you should use event.bytesLoaded and bytesTotal from the ProgressEvent rather than checking loaderInfo again

Last, try .defaultTextFormat = fmt instead of setTextFormat, you’ll need to use setTextFormat repeatedly after changing the text in order for it to work properly in Flash :slight_smile:

Here’s my changes to Preloader.hx

package;


import openfl.display.Sprite;
import openfl.display.DisplayObject;

import openfl.events.*;

import openfl.text.Font;
import openfl.text.TextField;
import openfl.text.TextFormat;
import openfl.text.TextFormatAlign;
import openfl.text.TextFieldType;

import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.display.PixelSnapping;

import openfl.geom.Point;
import openfl.geom.Matrix;

import openfl.system.Capabilities;

import openfl.Lib;

@:bitmap("Data/Preload.png") class Splash extends BitmapData {}
@:font("Data/Open Sans.ttf") class DefaultFont extends flash.text.Font {}

@:keep class Preloader extends Sprite {
	
	private var progress:Sprite;
	private var textPercent:TextField;
	private var splashImage:Bitmap;
	
	public function new () {
		
		super();
		preloaderInit();

	}
	
	public function preloaderInit():Void {
		
		// disable default menus
		#if (flash || js)
			Lib.current.stage.showDefaultContextMenu = false;
		#end
		
		#if (flash)
			
			Lib.current.stage.addEventListener(MouseEvent.RIGHT_CLICK, function(e:Event){ });
			
			if (Capabilities.playerType == "StandAlone" || Capabilities.playerType == "External") {
				Lib.fscommand("showmenu",    "false");
				Lib.fscommand("trapallkeys", "true");
			}
			
		#end
		
		Font.registerFont(DefaultFont);
		Lib.current.stage.color     = 0xFAFAFA;
		Lib.current.stage.frameRate = 60;
		
		// splash image
		var splashWidth:Float   = 128;
		var splashHeight:Float  = 128;
		var splashOffsetY:Float = -128;
		
		splashImage = new Bitmap(new Splash(Std.int(splashWidth), Std.int(splashHeight)), PixelSnapping.AUTO, true);
		splashImage.x = (Lib.current.stage.stageWidth/2)-splashWidth/2;
		splashImage.y = ((Lib.current.stage.stageHeight/2)-splashHeight/2) + splashOffsetY;
		addChild(splashImage);
		
		// progress bar
		progress = new Sprite();
		progress.scaleX = 0.0;
		progress.graphics.beginFill (0x29B1FF);
		progress.graphics.drawRect(620, 5, 670, 5);
		addChild(progress);
		
		// progress info text
		textPercent = new TextField();
		
		var textWidth:Float  = 128;
		var textHeight:Float = 128;
		
		var tFormat:TextFormat = new TextFormat();
		tFormat.font           = "Open Sans";
		tFormat.color          = 0xAA0000;
		tFormat.size           = 24;
		tFormat.align          = TextFormatAlign.CENTER;
		
		textPercent.defaultTextFormat = tFormat;
		textPercent.x               = (Lib.current.stage.stageWidth/2)-textWidth/2;
		textPercent.y               = (Lib.current.stage.stageHeight/2)-textHeight/2;
		textPercent.width           = textWidth;  
		textPercent.height          = textHeight; 
		textPercent.textColor       = 0x000000;
		textPercent.backgroundColor = 0x000000;
		textPercent.text            = "";
		textPercent.selectable      = false;
		textPercent.embedFonts      = true;
		addChild(textPercent);
		
		// loading events
		addEventListener(Event.COMPLETE, loaderInfo_onComplete);
		addEventListener(ProgressEvent.PROGRESS, loaderInfo_onUpdate);
		
		trace("LOADING START!");
		
	}
	
	// to test:
	/*
	public function scaleAroundPoint(target:DisplayObject, point:Point, scaleFactor:Float):Void 
	{ 
		  var m:Matrix = target.transform.matrix; 
		  m.translate( -point.x, -point.y ); 
		  m.scale( scaleFactor, scaleFactor); 
		  m.translate( point.x, point.y ); 
		  target.transform.matrix = m; 

	}*/
	
	public function loaderInfo_onComplete(e:Event):Void {
		trace("LOADING COMPLETE!");
	};
	
	public function loaderInfo_onUpdate(e:ProgressEvent):Void {
		
		var _bytesTotal:Float  = e.bytesTotal;
		var _bytesLoaded:Float = e.bytesLoaded;
		
		trace ("LOADING PROGRESS: " + _bytesLoaded + "/" + _bytesTotal + " bytes");
		
		var _loadedPercent:Float = _bytesLoaded/_bytesTotal*100;
		
		if (_bytesTotal == 0) {
			
			progress.scaleX = 0;
			
		} else {
			
			progress.scaleX = (_loadedPercent/100); // needs to scale from center
			
			//trace(_loadedPercent/100);
			
			textPercent.text = "Loading...\n"+Std.string( Std.int(_loadedPercent) )+"%";
			
			//scaleAroundPoint(progress, new Point(64, 64), _loadedPercent);
			
		}
		
	}
	
	// probably needs onResize re-adjustments as well
	// ...
	
}

EDIT: You can use openfl test flash -Dsimulate-preloader on the command-line, or if you wish to hard-code it, <haxeflag /> works, but <haxedef name="simulate-preloader" /> or <haxedef name="simulate-preloader" value="5000" /> (or whatever value you want) might feel a little cleaner

Thanks for sharing your code! Made it a lot easier to debug :grin:

First, you should be able to remove “pixijs”, “openfl-tools” and “hxcpp” from the project.xml

Oops, the project.xml was pretty much taken from my template project, so forgot to comment/remove some stuff out of this test.

Seems it works nicely now. And I prefer the haxeflag hehe, since I plan to have a GUI for this later on and it’d pretty much be a project option.

Thanks for sharing your code! Made it a lot easier to debug

And no problem! Glad the code helped! C:

1 Like

Was there any resolution on Android Splash screens?

Maybe this article might be of some help : https://www.bignerdranch.com/blog/splash-screens-the-right-way/

It can be any resolution and any aspect rate :slight_smile: