ActionScript, Flex, PushButton Engine Angry Explanations #1: How to draw a freaking image with PBE!

5 Comments

(Thanks to Ben G. for that humorous title! :D And just to be super clear–I’m not angry at all about PBE. The anger is entirely tongue-in-cheek.)

So, yeah, I got started with PBE at a bad time, I think.

It’s in transition between some major changes, and so all the docs and tutorials to this point are out of sync and kind of very… confusing. Because of that, I really struggled to figure this out, and in fact couldn’t get an image on the screen without professional help (I’ll let you interpret that however you’d like).

This information is relevant for PBE r625 and up.

(This isn’t to say the engine is poorly designed–it’s simply not accurately documented in places because it has been changing so quickly. And to be fair, it’s still in beta. I wouldn’t use the engine if I didn’t think it was great.)

A frustrated noob’s guide to getting a freakin’ image on the dang screen using Flex 3

Here’s the MXML which will reference the code.

<?xml version="1.0" encoding="utf-8"?>
<game:Game
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:game="com.yourcompany.yourgame.*"
	width="750"
	height="600"
	layout="absolute">

</game:Game>

Now define a resource in a ResourceBundle subclass, which is the image you want to display, and let PBE automagically make it accessible through the resource manager.

package com.yourcompany.yourgame
{
	import com.pblabs.engine.resource.ResourceBundle;

	public class EmbeddedResources extends ResourceBundle
	{
		// The path is magically also the name of the resource.
		[Embed(source="../assets/images/logo.png", mimeType="application/octet-stream")]
		public var logoImage:Class;
	}
}

Put that image into action! It’s a simple notion, but somewhat complicated if you’re new to the engine and its gooey innards.

package com.yourcompany.yourgame
{
	import com.pblabs.engine.PBE;
	import com.pblabs.engine.entity.IEntity;
	import com.pblabs.engine.resource.ImageResource;
	import com.pblabs.engine.resource.ResourceManager;
	import com.pblabs.rendering2D.DisplayObjectScene;
	import com.pblabs.rendering2D.SpriteRenderer;
	import com.pblabs.rendering2D.ui.FlexSceneView;

	import mx.containers.Canvas;
	import mx.core.Application;
	import mx.events.FlexEvent;

	public class Game extends Application
	{
		public var resources:EmbeddedResources;

		// We need access to this in a couple of functions.
		private var _scene:DisplayObjectScene;

		public function Game()
		{
			super();

			// Let the Flex Application initialize fully before we muck with it.
			addEventListener( FlexEvent.APPLICATION_COMPLETE, onStartup );
		}

		// This is called once the Flex app (stage, in particular) is initialized.
		private function onStartup( e:FlexEvent ) : void
		{
			// Load our embedded resources (the image to show).
			resources = new EmbeddedResources();

			// Tell PBE to initialize and pass it our instance so it can get the stage.
			// (Remember, Application is a subclass of Sprite, which PBE needs.)
			PBE.startup( this );

			createPbeScene();

			showLogo();
		}

		private function createPbeScene():void
		{
			// Create a new IEntity for the scene view.
			var sceneEntity:IEntity = PBE.allocateEntity();
			sceneEntity.initialize( "sceneEntity" );

			_scene = new DisplayObjectScene();

			// Since this is Flex, we need the appropriate scene view class.
			var sceneView:FlexSceneView = new FlexSceneView();

			// Set up the view size.
			sceneView.width = 750;
			sceneView.height = 600;

			// FREAKIN' IMPORTANT: add the view as a child to our display list!
			this.addChild( sceneView );

			// Connect the view to the display object scene (a component).
			_scene.sceneView = sceneView;

			// Add the display object scene to the scene entity.
			sceneEntity.addComponent( _scene, "renderer" );
		}

		private function showLogo():void
		{
			// Create a new IEntity instance for the sprite to be displayed.
			var spriteEntity:IEntity = PBE.allocateEntity();
			spriteEntity.initialize( "logoEntity" );

			// Add a sprite rendering component.
			var sprite:SpriteRenderer = new SpriteRenderer();

			// Tell the renderer to draw (and load) this image resource.
			sprite.fileName = "../assets/images/logo.png";

			// Tell the renderer to draw to the display object scene.
			sprite.scene = _scene;

			// Add the component to the sprite entity.
			spriteEntity.addComponent( sprite, "sprite" );
		}
	}
}

So, what the heck just happened? Pfft! Don’t ask me! I’m still a freakin’ noob! :)

I know a couple of things, though. The SceneView is like a “canvas” where all DisplayObjectRenderers are drawn. So you create entities and fill them with components (like a SpriteRenderer) and tell the renderer component about the scene view. Magically, the sprite appears! It’s not too much to understand if you just want to know the API and how to use it.

To really understand it, you’ll need to look under the hood and figure out the connections. A good bit of hidden work is being done to simplify the API, but possibly at the expense of understanding. It’s neither good nor bad. It’s just The Way of PBE (for now).

Feel free to post here to help fill my gaps in comprehension. I haven’t used the engine enough to write a thorough explanation, and I’m not too proud to accept help. :)

5 Responses to “Angry Explanations #1: How to draw a freaking image with PBE!”

  1. axcho Says:

    Ha, I tried PBE several months ago and I thought that was a bad time too! :p The documentation will catch up eventually, I guess… Thanks for helping the process along.

    I’m not sure if I can say anything in just a few sentences that will help fill your comprehension gaps. But if you have any specific questions I could probably help. :)

  2. Ben Garney Says:

    Awesome writeup, Jason, and thanks for keeping your sense of humor through the whole process. I’m glad the IRC denizens were able to help you out! :)

    One thing to keep in mind is that PBE has a lot of moving parts because it is designed for full games. So using it for a logo is a bit like using Unreal 3 to run a slideshow – kind of overkill. I only mention this so that people aren’t surprised at how many lines it takes to put an image on screen. ;)

    BTW you could also use the ImageScreen and the ScreenManager to show your logo, which would be a great deal simpler.

  3. Egogo Says:

    You’re a fing godsend.

    Next, do a “how to make clicking on an IEntity do something” and I’ll kiss your feet.

    PBE would have a TON more followers and a TON more community added features / documentation / example if they would just get some basic documentation and examples in place so people could at least get a start.

  4. jason Says:

    axcho: I’ll keep your offer in mind–and hold ya to it!

    Ben: “…you could also use the ImageScreen and the ScreenManager to show your logo, which would be a great deal simpler.” Well, the logo really was just handy art I had laying around, but the real goal was to get a sprite on the screen. :) This post is by no means a complaint about PBE. I really like it!

    Egogo: that might be coming up, because I’m considering doing some GUI-ish stuff with PBE entities in lieu of heavy Flex components (where prudent). Research continues.

    Thanks for the comments, everyone!

  5. jason Says:

    Egogo: I have a hunch that you could get the (Flash) Sprite from (PBE’s) SpriteRenderer, and then add event listeners just like with any InteractiveObject (from which Sprite inherits by way of DisplayObject). You would get the Sprite by doing something like:

    var flashSprite:Sprite = yourSpriteRenderer.displayObject;

    With that reference in hand, you could then listen for mouse events on the Sprite and handle accordingly. You’d just want to make sure you remove the listeners when you’re done (or the renderer gets disposed).

    I haven’t tried this yet, but that’s the first approach I’m going to take.

    Thanks for reading!

Leave a Reply