luxe alpha-2.0+0010 recap

sign up sign in

It's been fun, alpha-2.0 - it's been fun.

Here's the original focus sheet.

This alpha was named after 0010 games, and they have been earning it (a joke). Since the initial post, they have taken the game to GDC, PAX, gotten coverage in multiple print magazines in different countries as well as numerous online articles, all of which you find on their twitter profile.

The game is coming along in strides, and I can't wait to play it properly myself. This is from their twitter, a WIP trailer:


For this focus sheet,

I had a lot more deliberating and distractions than I imagined. I covered a lot of the stuff that I was thinking over in the dev logs and ended up on a few different places than I suggested previously - I'll go over those later but let's have a look at what happened in alpha-2.0.

noteable new features

While a lot of the stuff in alpha-2.0 was specifically resolving issues and problems with the code, there were still some nice new things along the way.

  • cross platform key:value store

    Implemented in snow and exposed via Luxe.io.string_save(key, value, slot=0) and Luxe.io.string_load('key', slot=0). These do what you'd expect, and they save the data in a platform consistent way (web using local storage, etc).

    They use your package id (com.luxeengine.blah) - so follow the general “Reverse DNS” naming conventions. They are stored with relatively useful obfuscation - which prevents the most basic abuse of the save data by the largest majority of users. You can always pass already encoded/encrypted/whatever strings, if you feel the need.

    This is a decent solution for save games, preferences and more, so use it as you see fit. The slots aren't a limited number they just append an integer to the end of your id's, so you could even use the slots as a subset of data. i.e inventory is slot 0, message history in slot 1. It's up to you.

  • asset reloading and such

    While there are not automatic systems handling this for you, you can now at any time grab a Resource and call reload. This only applies if the resource actually comes from a reloadable source, like a file based id. If you create a Texture from pixels and call reload, it's going to give you trouble because it would be doing what you told it to, but you would be making an error.

    Future additions will compliment this system nicely, and flow sync command was added already to keep your assets synced from your project folder (i.e /assets) to your output folder (i.e /bin/target/assets). Try it out by running flow run --sync on a native build, and modify the source asset. It will pull the changes as soon as it sees them into the running folder, so the game can see it. It doesn't prompt btw, so be wary that it does things you tell it to as well.

    Since snow already supports file change notifications on native desktop platforms, you could easily hook the 3 together, to have automatically reloading assets while you work. Even though this API and that API aren't 100% complete, you can still really easily use them. Here's a simple example:

    • call this somewhere before hand (like ready) #if desktop Luxe.snow.io.module.watch_add('assets/'); #end
    • add this in your luxe.Game main class, and that's it:
      override function onevent( e:snow.types.Types.SystemEvent ) {
        if(e.type == snow.types.Types.SystemEventType.file) {
            var resource = Luxe.resources.get(e.file.path);
            if(resource != null) resource.reload();
        }
    } //onevent

Actually...

Writing out all the changes this way will take forever. Take a look at the list of changes in the most recent commit for alpha-2.0 below.

Only some of these are aligned with the actual task list : which has it's own 25 tasks that were almost all done (some were moved forward, with reasons logged on each issue). That doesn't even cover all the stuff that was fixed or added for LD (mentioned further below). There's a whole lot of commits in between all that, which you can always view here. There's a bunch of things like accelerometer fixes, and all sorts.

I'll try to get into more detail in the dev logs, but there's a lot to cover so I may gloss over a few lesser notes.
Even the resource stats view got a nice clean up in passing!

Parcel:
  • new Parcel implementation
  • update options and creation options for all new resource types and settings
  • initial work toward parcel diff loading
  • add parcel event endpoints, for progress, complete, failed events
  • added ParcelChange type for information on progress or failure events
  • added length properties for counting resources
  • added state, for unloaded loading loaded
  • added listed which returns an array of resource id's in the parcel
  • added loaded which returns an array of resource id's that are loaded by this parcel
  • added oncomplete, onfailed and onprogress handlers in options
  • added bytes, texts, jsons, textures, fonts, shaders, sounds for constructor options
  • added is_loaded(id)
  • added skipping of already loaded assets
  • removed manual add_* api's
    • modify list
  • ParcelProgress
    • added no_visuals to bypass the default geometries for custom implementations
    • complete handler called before fade completes, not after
      • prevents "seeing" load complete responses happening
    • update for new Parcel event api instead of hijacking the onload/onprogress callbacks
Resources:
  • changed ResourceType.data to ResourceType.bytes and all associated calls/types
  • added new resource load/fetch api
  • all load actions return a Promise
  • all fetch actions return a strong type
  • added has, get for general queries
  • added invalidate(id)/destroy(id)
  • added a complete set of events for all resources
    • unknown / listed / loading / loaded / failed / destroyed / invalidated
  • added handling of reference counters from load calls
Resource:
  • added reload api handled by all resource types
  • added TextResource JSONResource BytesResource
    • these all contain a snow Asset type
    • which means:
      • previously res.text, res.json and res.bytes becomes
      • res.asset.text, res.asset.json and res.asset.bytes
  • added reference counting for handling destroy and sharing
    • tracked by Resources for you on load calls
    • will be used in subsequent additions re: parcel diff features
  • added resource state property, for listed, loading, loaded, failed etc
  • added invalidation and clearing
    • invalidate triggers an event, usually from some other event (like file change, context loss)
    • clear destroys asset/gpu/memory/other resources and slims down the instance to just state
    • clear is auto handled on reload, invalidate, and others
Texture:
  • implement new resource api
    • reload()/clear()
  • clearer toString details
  • Add Texture.defaultfilter and Texture.defaultclamp #246
    • this is not retroactive
    • only textures created after this will be affected
  • Add Texture.max_size():Int
    • returns hardware max width/height
  • filter and clamp represented by their proper parts
    • reduces chance of state desync errors
    • to update, set both at once:
      • filter = becomes filter_min = filter_mag =
      • clamp = becomes clamp_s = clamp_t =
  • removed asset from texture resource
    • texture resource contains gpu resource only,
    • it shouldn't have been hanging ram references
  • removed onload handlers as resources are now imperative
    • use a parcel, the preload parcel, or use
    • Luxe.resources.load_texture(id, options).then(function(texture) { }
  • removed frompixel, frombytes creation conveniences
    • only from pixels because it's not managing a resource
    • use new Texture({ id:.., width:..., height:..., pixels:Uint8Array });
    • use Luxe.snow.assets.image(id) to get an AssetImage which gives you the bytes api's if needed
    • use texture.submit(pixels) if updating texture pixels
  • added submit/fetch clarity
    • fetch downloads the texture pixels into a given array
    • submit uploads the pixels from the given array
    • submits includes TextureSubmitTarget for uploading cubemap faces
  • bind state cached in ResourceState so that multiple binds have no real effect
  • initial pass on abstractions/flexibility
    • add border parameter used in submit
    • add format parameter to configure the gpu format (i.e GL.RGBA)
    • add type parameter to configure the gpu type, enabling 2D textures or Cube Maps (and future 3D texture types)
    • add data_type parameter to configure the gpu data type (i.e GL.UNSIGNED_BYTE)
    • add compressed flag for handling compressed formats.
      • only useful right now if you know what you're doing!
      • when submitting, compressedTexImage2D would be used instead of texImage2D
Screen:
  • changed w and h to Int type
  • added width and height to Float if needed
  • removed redundant cache values and error prone sync code
  • added bounds getter, returns a luxe.Rectangle for convenience
  • clarified that mid, size, bounds will return new instances
    • this is because cached values get modified by user code
    • immutability is in the new vector code for later alpha
Shaders:
  • implement new resource api
    • reload() / clear()
  • only set uniforms that are found (not all 8 for no reason)
  • added luxe_no_shader_prefix define short term
    • you don't need to define this unless you need to
  • clone requires an id for the clone (see below)
  • removed all inconsistent verbose flags and fixed error logging to be more logical
  • unified naming of vert_id and frag_id
  • gave a proper resource id, must be unique like all resource id's
    • that means the | combined stop gap is gone
  • when creating or specifying for loading, vertid, fragid and id are required
    • move to be explicit for usage code clarity
    • in the cases where you left one out:
      • use 'default' for vert_id
      • use 'default' for untextured and 'textured' otherwise
BitmapFont:
  • implement new resource api
    • reload() / clear()
  • remove from_string and other static api's
    • use new BitmapFont({ id:, pages:[], font_data:string });
  • moved parser and types into luxe/importers/
RenderState:
  • add bindTexture( type, tex ) abstraction
  • add bindTexture2D/bindTextureCube implementation
  • add ResourceState.boundtexture2D/boundtexturecube
    • for cases where the currently bound TextureID may be useful

Deliberating

A lot of the time spent on this alpha was mostly implementing things and seeing that the ideas weren't lining up, or that the implementation was backwards and inflexible, but the outcomes are good.

I felt a little unsure at times, about what road would be best for things like the load/fetch changes to the resources but once I had it working and the code became much more explicit and clear and the concept of “You must have a resource in order to use it” just makes things a heck of a lot cleaner and simpler all round.

In the end, I am quite happy with where all the changes landed, and I have already tested a couple of the new features in a few projects already, most of which are already rolling on cubemaps and live reloading and the works.

There are still a few things to be done, that's for sure, but the direction is a good one, and I feel confident that when the last of the resource management features like tagging and parcel diff system (unload unused, load new, keep shared) come into play, and the parcel backgrounding and streaming facilitation these efforts are going to work out great.


Distractions..?

Distractions is an odd word, it sounds quite negative, probably because it is a ... let's use “detours”.

Ludumdare 32

This last ludumdare was really fun, there was a lot of interesting bug fixes, and a lot of interesting games to come of it. A special thanks to all that participated, files reports, and those that supported others on the chat during the jam. All of you made it excellent.

You can view the full recap and play all the games here

(image chosen at random from the list):

Pre-LD bugs fixes and features
Since the jam was a mini milestone there are some things to note.

  • Web audio fixes
    • bugs with pitch, volume, pan not updating realtime were fixed
    • bugs with playback loops that were found in newer browser updates were fixed
    • more test features (sliders!) were added to the debug test, you can play with it here.
    • this brings web audio back to parity with native, which somehow got buggy along the way
  • New collision features
    • remember: luxe.collision == differ, you use it from luxe.collision!
    • The previously named “hxcollision” got a name, “differ”
    • 1.2.0 update of differ includes lots of ray casting features like intersection points and ray vs ray intersections and more, view the demo here but the luxe local version (tests/features/collision) is a little ahead thanks to bug sleuthing by NicoM and bug fixes and test additions by joeld42
    • lots of api refactoring and clean up

Ahead!

This post is already over 2000 words, and there is still a dev log and an alpha-3.0 sample + post incoming. I'm excited to share some stuff that I've worked on over ludumdare weekend as well, so let's keep this one on point.

So keep an eye on snowkit.org or twitter, or repos. I'll be posting alpha-3.0 tasks and milestone, so we can forge on ahead.

Onward we go! If you have issues, questions or feedback don't hesistate.

Community

Jump in, share your work, see what others are up to:

Chat : http://snowkit.org/chat
News & Updates : http://snowkit.org/
News & projects : http://twitter.com/snowkitorg
Hashtag : http://twitter.com/hashtag/luxeengine?f=realtime

Tags
luxealphafocuschangeschangenotesalpha-2.0alpha-2.0+0010