Author Topic: FlxSWFStates - Level creation in Flash/FLAs!  (Read 2214 times)


  • Gamewright
  • Member
  • **
  • Posts: 39
  • Karma: +2/-0
    • View Profile
    • Deep Plaid Games
FlxSWFStates - Level creation in Flash/FLAs!
« on: Fri, Aug 24, 2012 »
I meant to share this before... luckily that means it's *fairly* mature, or at least I've been using it a lot and I see few or no bugs with it. My friend Chris is participating in Ludum Dare (I'm jealous, I wish I had time) and is going to use Flixel... I packaged this up a bit to share it with him, and thought I might at least share it with others.

I've tried DAME and looked at Ogmo and just didn't feel like it was worth my going through the learning curve. I realized that what I really wanted was simple: WYSIWYG (What You See Is What You Get) level design, putting things in 2D space... and that was all. And the frustrating thing was that I can do that easily in other Flash work I do: just make an FLA with the content I want, bam, done.

But Flixel doesn't use the Flash display list and is just a different world from anything you can make with an FLA, right? It seemed like an easy gap to bridge, so I tried bridging it.

FlxSWFStates will:
1. Load a SWF file
2. Look at all the DisplayObjects on the "stage" (root display list) of that SWF
3. Create an FlxSprite OR ANY OTHER DERIVED CLASS from each DisplayObject
4. Give the new FlxSprite the x/y/width/height of the original DisplayObject
5. Optionally give the new FlxSprite the pixels of the original DisplayObject [no, animations are totally unsupported, sorry; rotation also not supported yet]
6. Assign any variables to the new FlxSprite, which you can define in Flash using the Component Inspector (e.g. you can set "vector.x => 50" and the object will have its vector.x value initialized to 50 when created... works for any variable names on your custom classes too).
7. It will then add this FlxSprite to your FlxState. If your FlxState defines a certain custom function, it will go through that function, otherwise it falls back on simply calling add().

There are "Dynamic" and "Embedded" implementations of the Populator which you can use. Embedded uses a SWF that has been compiled (longer compilations, faster at runtime); Dynamic uses a SWF file that's loaded in on-the-fly at runtime (faster compilations, slower at runtime). I prefer Dynamic because you can reload your level's SWF without having to restart the game, allowing for super-fast iteration (which I am addicted to).

Here's the library itself, which is meant be put under the flixel "plugin" folder (though I'm not sure if this is the right place for it at all, oh well):

And here's a minimalist example project that uses it:

(This game was originally something I created in 20 minutes in a nightclub during GDC with Robin Arnott and Rodain Joubert... it's terrible... but at least it can serve as a demo of this plug-in now!)

Here's a bunch more details on where things live in the test project, copied from the email I sent to my friend earlier....

- The FLA file for the level lives in data/levels. Its publish settings are set to publish a SWF under bin-debug/levels/. This is a weird setup for FLA/SWFs, but I had problems getting dynamic-SWF-loading working unless the level SWFs were underneath the same folder (bin-debug) as the game SWF.
- The FLA also includes the libsrc folder, there are a couple of my classes that it has to be aware of.
- Note the component settings on every object in the level. You can set what class a MovieClip should be turned into in Flixel (in this case "Sun" or "Planet"); and you can put arbitrary name/val pairs that will be set on the object at initialization. One planet starts out with a velocity.x = 50 name/val pair.
- Note that BaseSWFLevel takes care of identifying what type of object is being added, and putting it in the right group. Good place to hook up other massaging/handling of those things.
- There's also a hook for after the entire SWF has been loaded in.
- Note that the SWF is loaded in AT RUNTIME so you can totally do the following for maximum productivity:
   - Play the level, and find there's a change you want to make
   - Go to the level FLA, make the change, republish the level SWF.
   - Reload the level (you don't even have to relaunch the game!!!), for instance by stepping out to the main menu and back in, or with a dev hotkey
   - Bam, you're running the changed level, no need to rebuild or relaunch whooo
- The actual SWFState code lives under libsrc/org/flixel/plugin/FlxSWFStates. Note that two classes in there (ObjectProxy and ObjectProxyParent) are things that can be used for Components in the FLA. Note how the object linkage and component setup in the FLA library is setup for the Sun and Planets in there. These examples all use ObjectProxy I think; if you want to do parenting, it works, but you have to make the parent objects be ObjectProxyParent components for the code to recurse into them and find the ObjectProxy children at runtime. I know that this makes no sense, so ask me for more details/examples if you're really curious about this capability... basically it lets you use the Flash MovieClip hierarchy for more modular setup.
- The actual pixels of the thing in the FLA will be used on the sprite created, by default. Making this a great prototype art tool. Zero support for animations though. You can always uncheck "use pixels" on any element's component settings, if you want to set up its visuals in code instead.

Hopefully that's more than enough to get people started. My hope is that this can be a significant alternative for a way to design levels for Flixel, even though it will clearly have some pros/cons compared to the other methods (this has absolutely zero special support for Tilemaps, I've never used them, yes I know they're a popular Flixel feature, sorry). And of course this isn't helpful to indies who don't have Flash, I know.

But hopefully it's useful to the community! Enjoy and let me know if you add capabilities, or discover major bugs, etc.
I'm just one guy trying to make some interesting decisions!