Liquidfun JavaScript - LFJS - [behavior], devlog, ideas, suggestions

  • SIMPLE Games - thank you for the bug report!!

    Update now Beta v1.0.0.2, bugfix: render error when not using tint effect.

    That video is interesting - it looks like the full desktop version of Liquidfun, judging by the performance. The programmer has used a few things that are not currently available in LFJS, if my guess is right.

    1. Assign a color change to an individual particle. This should be possible in LFJS - I will check the source code and write the cpp headers to make it possible.

    2. It is possible that the example uses particle-to-particle collision and collision energy to allow a decision to be made as to whether to change the color of the particles to white. This option will not be available in LFJS because of the massive overhead called during each world step.

    3. Alternatively the programmer has stored the velocities of each particle and made them color white when there is a large velocity change (ie due to an impact).

    4. I don't think the example uses color mixing because the water doesn't get whiter and whiter with time - it always blends back to blue. Which means that the programmer has applied a general blend-back-to-blue color change to the whole particle system/group. That could be very expensive in LFJS because of the calls from JavaScript to webassembly.

    I will see what changes I can make to allow individual particle color-assignment and, maybe, group or system color assignment.

  • And to add to the above:

    In LFJS, particles are referenced each tick by their Index (buffer index). If no changes are made to the number of particles in a system then each Index -should- reference the same particle between ticks. But this is not guaranteed (and is specifically mentioned in the cpp documentation as not being guaranteed - the library might change things around).

    Secure and tick-proof references to a particle do exist and the class is callede b2ParticleHandle. These are a bit like UIDs in that each Handle is unique to the particle system and remains attached to its particle. So far I have tried to avoid using Handles so that the plugin doesn't become overly complicated (ie you couldn't use a Handle in any of the current impulse/velocity actions and, if Handles were introduced, then all of the actions that input a buffer index will have to be duplicated in case you want to use a handle instead).

    Looking through the cpp for Liquidfun and it's clear that the example in the video was highly modified - there are no methods to directly control particle color on an individual basis (after creation), so they must have been programmed by the cpp guru who made the video.

    Not impossible and I'll take a look, but if we are going to track particles between ticks then Handles come into play, with all of the added complexities that this would mean for the plugin.

  • Okay, I thought I missed something that could allow this effect (which would make sense for more realistic water). I'd also like to know, what are some optimisation tips for mobile? Other than setting all iterations to 1, fixed step rate at 30 sps, not using heavy behaviors and, of course, as few particles as possible (therefore bigger radius). Anything else?

  • SIMPLE Games - that's about the sum of it, although small iterations might cause odd behavior (so be careful with those settings). Minimise use of particles and other physics objects and avoid creating/destroying bodies during runtime (no sprite animations on a LFJS body, for example). Optimisation for mobile is a big challenge for a JavaScript game engine, even when webassembly is being used.

    I'm about to write my own cpp methods for changing particle colors. I'll let you know how it goes...

  • The particle handle reference is interesting. As far as I can tell the handle holds the particle index, and then the system updates the index held by the handle whenever it needs to change. Changes being things like the particle being destroyed, cloned or moved in the list. Initially I assumed the index would be static, but it looks like they swap the particles into a new buffer during the deletion phase so living particles would have their index values change. So quite a lot of book keeping to keep the handle valid.

    I spent a bit of time recently looking at generational indexes, and I think they probably solve this problem a little better. Depending on the data layout though it might mess with cache coherency, which would be bad.

    For anyone interested generational indexing basically involves putting a generation field on each entity, then when something wants to hold reference to it you return a value that combines the index and the generation. When that reference needs to be resolved you compare the generations of the entity and the reference, if they match it's still the same entity.

  • Nepeo - indeed - static indexes would be so much easier! I'm still trying to find a better way of keeping track of particles. The handle at first seemed like the answer, but they are only released on demand and only then one at a time. Getting buffer arrays to pass from cpp to JavaScript isn't my strong point, so it'll be a while before I get any success there, I think.

    Update:

    Version 1.0.0.3

    Added feature:

    Action: SetParticleColor(bufferIndex, red, green, blue, alpha)

    Expressions: ParticleRed(bufferIndex), ParticleGreen(bufferIndex), ParticleBlue(bufferIndex) and ParticleAlpha(bufferIndex).

    So now it's possible to change particle colors by reference to their previous color (if required) using their buffer index reference.

  • Yeah a static index for each particle would have worked much better for your situation. You could keep a buffer of handles in cpp land and use your own static id scheme when communicating with JS perhaps?

    Sending anything other than numbers between JS and WASM is still pretty hard at the moment. There's some talk about adding a more advanced interface layer, but it's still quite early. The interfaces would probably be specific to the language and module. Also it would likely be initially limited to basically TypedArrays and Strings.

    I know there's a tool for rust called wasm_bindgen that makes this stuff magically work, I thought there was one for C as well but I can't find any information about it. Although I'm a little questioning of these magic interop layers. If your using emscriptem you can go more basic by using malloc from JS, then pass the pointer and length to wasm via function calls.

    Anyway, the plugin looks really cool. Nice work!

  • Nepeo - thank you, I really appreciate the feedback!

    I must confess to being quite the amateur when it comes to compiling and working with webassembly. I have had some success at writing and building with my own methods that weren't written into the original Liquidfun cpp (like the set particle color as above), but more complex tasks like accessing the particle handle buffer array have proven problematic.

  • Success!! I've written c++ methods to transmit all of the particle handles/UIDs to the plugin in an array. And it's fast (0.1 ms for 3000 particles), so no problem using it during runtime. Now I'm going to attack the ACEs so that the current Actions that use buffer index will become deprecated: in future, the only way you'll be able to identify a particle will be by its handle/UID. This is going to take a little while, so please be patient.

  • Update: Beta v1.0.0.4

    Change: Primary reference to each particle is now the particle UID (an LFJS-unique reference to each particle handle in Liquidfun). The deprecated expressions that change query index to buffer index have been altered so that thier output is compatible with the action changes, so there should be no problem migrating from the previous version.

    Actions changes:

    All of the actions now input particle UID instead of particle buffer index.

    Conditions additions:

    For each particle query loop.

    For each particle in group loop.

    Expressions changes:

    CurrentUID: the UID of a particle in a for-each loop.

    QueryUidsAsArrayJson: the particle query list of UIDs for an array input.

    GroupUidsAsArrayJson: the list of group UIDs for an array input.

    ParticleUidFromSprite: use the particle sprite UID to obtain the particle UID.

    ParticleUidFromBufferIndex: in case you wish to loop through the buffer index, use this to obtain the particle UID.

    Work to do:

    Next is to investigate direct setting of particle velocity via an action. This may not prove viable because the whole library is not designed to work this way. But it might be ok...

    Thanks Nepeo for the inspiration.

  • awesome work! :)

    I am going to have to think of a reason to use this - it looks like a lot more fun than the database work I do!

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Colludium Sounds like you had a productive weekend!

    I wouldn't worry too much about being an amateur, working with WebAssembly is a huge knowledge space. Mainly because it involves the interactions between 2 languages, as well as the quirky code and tools you have to use to glue the stuff together. Depending on what language/tool your using that's going to change as well. So realistically the best you can hope for is to understand the bits your using well!

    You've managed to work through a number of hard to do things here, so you should give yourself a pat on the back.

    Working with existing libraries can be particularly painful... But if your looking to write some new code and experimenting then webassembly.studio is quite useful. I also hear Rust is becoming a good platform for creating WASM projects. Having learnt Rust myself in the last year I can say it's a fairly serious undertaking compared to most languages. Once you've got it down it's generally pleasant to work with though.

  • Having fun with this and I know I have only scratched the surface! Using iPhone accelerometer to control gravity (tilting phone) and use an image to particle spawn, elastic behavior makes for a nice effect. I can see creating an image specifically for this could turn out really well.

  • Mikal - I love that example! I feel inspired to make something using my own plugin!!

  • Colludium - Hi :-) about a year ago I bought your previous plugin Box2D and started creating my first full game. The downside was it has only Construct 2 runtime...

    So is this somethnig like update? Is new plugin supprot C3 runtime? And is it possible made things like with previous plugin? Will this be working on mobile phones after export Android / iOS?

    If yes I definitely buy this one a start refactoring my game :-D

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)