Preloader , now that NMEPreloader is depreciated

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:

10 posts were split to a new topic: Issue with embedded BitmapData

I meant solution - was there a solution to this so far?

Oh, sorry, at moment of writing answer I though about iOS splash screens.

As I know OpenFL doesn’t support android splash screens out of the box, but it is pretty easy to add it, if you have basic knowledge about Android programming.

You have to override Android template - put <template path="templates" /> into project.xml, than create folder templates and put here what you want to override. If you use macOS or *NIX, you can find original templates in /usr/local/lib/haxe/lib/lime/<lime version>/templates or /usr/lib/haxe/lib/lime/<lime version>/templates.

If you want to create splash screen like .gif in your prev. post, you basically need following folder structure:

|- /templates
|  |- /android
|     |- /template
|        |- /app
|           |- /src
|              |- /main
|                 |- /res
|                 |  |- /drawable
|                 |  |  |- splash.xml <- we will create it later
|                 |  |- /drawable-ldpi
|                 |  |  |- ic_splash.png <- we will create it later
|                 |  |- /drawable-mdpi
|                 |  |  |- ic_splash.png <- we will create it later
|                 |  |- /drawable-hdpi
|                 |  |  |- ic_splash.png <- we will create it later
|                 |  |- /drawable-xhdpi
|                 |  |  |- ic_splash.png <- we will create it later
|                 |  |- /drawable-xxhdpi
|                 |  |  |- ic_splash.png <- we will create it later
|                 |  |- /drawable-xxxhdpi
|                 |  |  |- ic_splash.png <- we will create it later
|                 |- /values
|                 |  |- colors.xml <- we will create it later
|                 |  |- styles.xml <- we will create it later
|                 |- AndroidManifest.xml <- copy from lime

Step 1

Modify AndroidManifest.xml - find android:theme="@android:style/Theme.NoTitleBar.Fullscreen" and change it to android:theme="@style/SplashTheme".

Step 2

Create styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="SplashTheme" parent="@android:style/Theme.NoTitleBar.Fullscreen">
        <item name="android:windowBackground">@drawable/splash</item>
    </style>
</resources>

Step 3

Create splash.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
    <item android:drawable="@color/splash_bg" />
    <item>
        <bitmap android:gravity="center" android:src="@drawable/ic_splash" />
    </item>
</layer-list>

Step 4

Create colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
    <color name="splash_bg">#cccccc</color> <!-- or put any color you want -->
</resources>

Step 5

Take an image you want to be in center of splash screen, resize it to several resolutions (ldpi, mdpi, hdpi, xxhdpi, etc) and put to appropriate folders. Probably you can use some online or offline tool to do resizing for you.

Finally

That’s all. Few notes:

  1. I didn’t create additional SplashActivity here, because I think that for OpenFL it should work correctly even without it. But I’m don’t try it myself, so use it at your own risk :slight_smile:
  2. Actually I didn’t test it at all, so probably I can write something stupid here, but basically idea would be the same.
3 Likes

I thought splash screens were deprecated on Android

A pull request for Lime to add splash screen support would be nice if someone wanted to work on one :wink:

Google changed his mind :slight_smile: It called “Launch screen” - https://material.io/guidelines/patterns/launch-screens.html

IMHO lightweight apps doesn’t need splash screen, I never add splash screens to my own Android apps.

1 Like

embedding images using @:bitmap has stopped working for the HTML target using OpenFL 5.0.0 , still working correctly for Flash Neko and Windows targets… !

Could you try this change, and see if it helps?

I’ve tried it - no errors but nothing is loading.

BitmapData.fromBytes won’t work on HTML5 – at least, not instantly. If you do not rely upon bitmapData.width or bitmapData.height, I believe it should work once the image is loaded.

Otherwise, it is important to call loadFromBytes instead to wait asynchronously. I believe the @:bitmap embed adds an “onload” callback parameter as the final argument in the constructor on the HTML5 target, but I’d like to think of a better system long-term

Oh, I almost forgot :slight_smile:

In XML:

<asset path="Assets/preloader" library="preloader" />
<library name="preloader" embed="true" />

Then I believe that should embed the files under “preloader” as it’s own asset library, which you can load inside of your preloader:

Assets.loadLibrary ("preloader").onComplete (function (_) {
    var bitmapData = Assets.getBitmapData ("preloader:image.png");
    ...
});

That’s an alternative to @:bitmap

Because embedding image using @:bitmap is broken for html5 target in openFl 5.x.x, I try to use your suggested method.
It works but with some different info.

<assets path="assets/preloader" library="preloader" />
<library name="preloader"  embed="true" />

But isn’t possible to get image just with

"preloader:image.png"

This works

 Assets.loadLibrary ("preloader").onComplete (function (_) {
		
   var bitmapData:BitmapData = Assets.getBitmapData("preloader:assets/preloader/logo.png");
   var bmp:Bitmap=new Bitmap(bitmapData);
   addChild(bmp);
});	

full path to the bitmap should be written.

Thanks @restorer! Your solution worked nicely

Would be also interesting to see how to “hold” this windowBackground image until the preloader is at a certain stage. Right now basically the image is displayed quickly, and then the background color of openFL kicks in before the preloader is rendered.

Would be nice to be able to hold the graphic until ready for rendering. ( Maybe hold off on draw events or draw app with alpha 0 ? )

I have tried to use this preloader for HTML5 target:

package com;


import openfl.display.Sprite;
import openfl.events.Event;


@:keep class Preloader extends Sprite {
	
	
	private var progress:Sprite;
	
	
	public function new () {
		
		super ();
		
		progress = new Sprite ();
		progress.graphics.beginFill (0xFF0000);
		progress.graphics.drawRect (0, 0, 100, 100);
		addChild (progress);
		
		progress.scaleX = 0;
		
		
	}
	
	
	public function onInit ():Void {
		
		trace ("init");
		
	}
	
	
	public function onLoaded ():Void {
		
		trace ("loaded");
		
		var delay = 60;
		
		addEventListener (Event.ENTER_FRAME, function (_) {
			
			delay--;
			
			if (delay == 0) {
				
				trace ("delayed start");
				dispatchEvent (new Event (Event.COMPLETE));
				
			}
			
		});
		
	}
	
	
	public function onUpdate (bytesLoaded:Int, bytesTotal:Int):Void {
		
		trace ("update: " + bytesLoaded + "/" + bytesTotal);
		
		if (bytesTotal == 0) {
			
			progress.scaleX = 0;
			
		} else {
			
			progress.scaleX = bytesLoaded / bytesTotal;
			
		}
		
	}
	
	
}

and at xml build file, I added <app preloader="com.Preloader" but all I see is a gray background which is defined at <window background="#eeeeee" I am using openFL 6.5.3 , please advice

Just guessing, i am not using a preloader:
Did you try “package;” and <app preloader=“Preloader”

Please look at the CustomPreloader example:

openfl create CustomPreloader
cd CustomPreloader
openfl test html5

It looks like this:

ProgressEvent.PROGRESS then Event.COMPLETE are dispatched as assets are loaded, then if the default is not prevented, Event.UNLOAD is dispatched and your preloader is removed. If you prevent the default, you can delay indefinitely, then dispatch Event.UNLOAD when you ready :slight_smile:

Thanks! by the way, the link above is broken