(June 2021) Monthly WIP Screenshot Thread

Hi there !

HybridJme is a project aiming to provide jme-awt-swing-jfx gui bindings, through the javafx.embed.swing.JFXPanel & the NullLayout or the absolute positioning of awt.Component on other Container, So now jfxParentNodes can be inflated easily either from code or fxml files, (you can use SceneBuilder freely for GUI) :

Controller class of jfx can be used also without Platform.runLater() if you are outside of jme-context.

Example 1, shows 3 UiStates at different positions in immersive mode & 1-pop-up UiScene:

Example 2, shows 3 UiStates & 1 inflated UiState from fxml (made with SceneBuilder) :

In code, i have made sure that the panels get managed by UiStateManager class which is very similar to its relative on android, so coding stack is similar :

package test;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetKey;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.debug.WireSphere;
import core.uiStates.JfxUiState;
import core.uiStates.UiStateManager;
import core.window.HybridWindow;
import javafx.embed.swing.JFXPanel;
import java.io.IOException;
import java.nio.file.FileSystems;

/**
 * Test Jme-Canvas inside a Hybrid Window. (WIP)
 * @author pavl_g
 */
public class TestHybridWindow extends SimpleApplication {
    @Override
    public void simpleInitApp() {
        flyCam.setDragToRotate(true);
        WireSphere wireSphere=new WireSphere(50);
        Geometry geometry = new Geometry("wireSphere", wireSphere);
        geometry.setLocalScale(0.05f);
        Material material = new Material(assetManager.loadAsset(new AssetKey<>("Common/MatDefs/Misc/Unshaded.j3md")));
        material.setColor("Color", ColorRGBA.randomColor().mult(2f));
        geometry.setMaterial(material);
        rootNode.attachChild(geometry);

    }

    public static void main(String[] args) throws IOException {
        HybridWindow hybridWindow = new HybridWindow(new TestHybridWindow());
        UiStateManager uiStateManager = new UiStateManager(hybridWindow);
        /*test immersive mode on the primary screen*/
        hybridWindow.setImmersiveMode(0);
        /*test attach UiStates*/
        JFXPanel jfxUiState1 = uiStateManager.attachUiState(new TestCase().attachJfxTest(), 222);
        JFXPanel jfxUiState2 = uiStateManager.attachUiState(new TestCase().attachJfxTest(), 223);
        JFXPanel jfxUiState3 = uiStateManager.attachUiState(new TestCase().attachJfxTest(), 224);
        /*test jfxUiStates, inflation from XML*/
        JfxUiState jfxStateTest = new JfxUiState(uiStateManager.fromXML(FileSystems.getDefault().getPath("src/main/java/test/Options.fxml").toUri().toURL()) , 0,0,800,800);
        uiStateManager.attachUiState(jfxStateTest, 225);
        /*test change size on JFXPanels*/
        jfxUiState1.setSize(200,200);
        jfxUiState2.setSize(200,200);
        jfxUiState3.setSize(200,500);
        /*test initialize the hybrid window*/
        hybridWindow.init(800,800, uiStateManager);
        /*test setBounds, location, sizes*/
        /*test immersion on upper-left corner*/
        jfxUiState1.setBounds(uiStateManager.getWidth()-jfxUiState1.getWidth(),0,200,200);
        /*full immersion on screen-end, lower-left corner*/
        jfxUiState2.setBounds(uiStateManager.getWidth()-jfxUiState2.getWidth(),
                uiStateManager.getHeight()-jfxUiState2.getHeight(),200,200);
        /*test middle positioning*/
        jfxUiState3.setBounds(uiStateManager.getWidth()/2 - jfxUiState3.getWidth()/2
                ,uiStateManager.getHeight()/2 - jfxUiState3.getHeight()/2,jfxUiState3.getWidth(),jfxUiState3.getHeight());
    }

}

Current Features :

  • Inflation of AWT-Swing-Jfx Ui is available.
  • Listeners & focus are working fine in both the GUI & Jme.
  • No problems from threads incompatibility so far.
  • Layout Inflating from XML for jfx is available.
  • default null layout is guarded against Ui & window update.
  • Swing LayoutManager is also accessible.
  • Immersive mode is available for all screens connected to the laptop.

Current Limitations :

  • No support for Lwjgl-3.
  • Prolonged loading time if you are attaching too much UiStates at the start-up.
  • Testing within jme3 update() & BaseAppState, Stills WIP.
6 Likes

The past two weeks I’ve been working on porting the random building generation from the old Mythruna engine. The building generation there was never really finished some I’m trying to formalize it and build a tool for making the parts database that drives it.

Here we see the beginnings of just getting the algorithm working again with the stand-in open source materials (not real Mythruna materials) and a few parts. The center was left out to check vertical alignment.

The initial problem that the original Mythruna version never got around to solving: too many of a particular feature. Here too many stairs:

That was pretty easily fixed. Now each floor can specify minimums/maximums of certain features and parts will be selected accordingly. Really the only thing left to do is to make sure all parts of the building are actually reachable. Right now some floors will generate with rooms that you can’t get to because they are walled off.

In the mean time, it’s fun to play with the parameters and generate ridiculous buildings even with this limited part set.

From relatively normal sized ones:



To small ones:

To weird ones:

To giant crazy ones:

It can even sort of do non-rectangular templates:

Also fun to walk around inside and explore the giant ones:




Giant attics get a little busy with this part set:

With some lights:


Pleased with the results so far and I’m on the way to fixing the reachability issues.

14 Likes

This sounds really great. :slightly_smiling_face: I think in the future I could really use this to build UIs for my JMonkey Game. The only downside is, that JavaFX probably doesn’t support the cool BitmapFont I currently use in my game. :confused:

1 Like

Thanks, i think you may not have heard of jme-jfx-11, it’s already another project porting jfx to jme :

The only thing that i have added in my project may be :

  • java 8 backward compatibility.
  • supporting awt-swing components together along with jfx.

But, i am still not sure if that would offer the same performance as jme-jfx-11 or not.

Major Differencies :

  • Jme-jfx-11 uses jfx-scene to render jme.
  • HybridJme uses AWT canvas to render jme, so it’s swing-awt in core, jme canvas is then displaced over a GamePanel (UiStateManager) of absolute positioning, so JFXPanels can be used also along with AWT-Components & JPanels.
4 Likes

Small follow-up. I spent this weekend building connectivity constraints into the building generators. This is what keeps walls from blocking off doorways or being placed right at the bottom of stairs, etc…

It still generates unreachable areas (mostly in larger floorplans than I will actually use) but at least nothing blocks the required doorways:

You can see a room in the lower left that is unreachable.

The connectivity information used for resolving the constraints is also what will be used to calculate reachability and then flip some parts to open passages. But that may be next weekend’s project.

9 Likes

Nice, what kind of algorithms are you using here in general to generate those random cells ?

I may put a video together in the future. It assembles levels from random parts with desired characteristics.

Edit: getting some time to work on connectivity tonight. Generating some unrealistically giant floors and marking reachable areas:

…next step to randomly swap out border tiles to make new connections.

3 Likes

Ok, hacking that in wasn’t TOO bad. I’ll integrate it more correctly over the rest of the week.

Full reachability for the win:




And of course it has no problem with more reasonably sized buildings, too.

6 Likes

@pspeed I really like your work but I do not understand how you guarantee connectivity between all rooms - This makes your work even more admirable however :wink:

To stay on the topic of houses: I am currently implementing an algorithm to show houses from OpenStreetMap and try to find a solution which places an appropriate house type based on the size, number of levels, landuse etc. It looks good from above already and the performance cost is minimal. Houses in a 2.5 x 2.5 km cell will be rendered with a single draw call! Next WIP screenshot will probably show the houses from ground level.

17 Likes

Looks insanely good! Very nice job :o

1 Like

It’s one of those things that magic is not all that impressive if you know it. I guess the trick is figuring out all of the simple magic to put together.

In this case, the floors are made of random tile pieces. If I start from a particular “cell” I can traverse through all of the connection points. Anything left is unconnected so I find a random border cell that is not connected, find one of its connected neighbors and then swap out one or both tiles that have the existing connectivity but also open the wall between them.

If the tile set always has at least one tile that matches the cell rules with all directions open then it’s guaranteed to eventually find a good one. But it may pick better ones.

Then the connectivity traversal is continued and if there are still unvisited tiles it repeats.

Usually it only takes 1-2 passes to connect everything. In realistically sized buildings (ie: the ones I will actually use in towns and such) 2x2, 2x3, 3x5, etc. it’s rare enough that there are disconnected areas in the first place… so it’s almost always only 1 pass when triggered at all.

Out of curiosity: I understand that swapping preserves a maze-like structure, rather than just opening the wall between two unconnected tiles. Is this correct or why do you swap tiles at all?

The algorithm doesn’t know what a door should look like. That’s artist created in the tile itself. So I can’t just punch through a wall. I have to find a tile that has an opening (and preserves at least the existing openings).

1 Like

Time Pilot

Here is my test project for JME, I wanted to try out JME to see if my main project would be an easy switch over. I did Time Pilot from the 80s. It worked out pretty nicely, once I got use to JME coding style.

I found it weird that it does not support sprite sheets, that you have to create it. I would think that would be a pretty common thing to have. The particle effect handles sprite sheets, but the main engine didn’t. Weird, it was not expanded for support.

I don’t like that you really can’t have a window size and a different canvas size. Not truely. The canvas keeps being updated to match the window size in the main engine.

But here is my work in progress. Level 5 of the game is not complete, I’ve not tested looping on levels getting harder.

11 Likes

Nice! why did you choose JME for a 2D game? and the last part of the video looks like a different game… isn’t it?

The end of the video is why. I did a remake on 3D grid based Alternate Reality. The video at the end shows the game in my own engine and was thinking about switching to JME.

But is not a full 3d game. It is more a DOOM 3d game. So so many things are just QUADS in a 3d world. So the use of sprite sheets and some 2D features are heavily used. JME doesn’t support those thing very much.

1 Like

Nice work!
Your CRT+scanlines shader looks much better than those ones in most emulators.

I remember seeing a nice sprite lib for JME. Personally I’m using a simple sprites shader for 2D sprite animation. It’s primitive but works fine for me.

Edit: here is the 2D lib: View Page - jMonkeyEngine - Store

Yeah, sprites almost never come up in 3D games and when they do it only takes a few lines of code to do something simple or just use one of the external libraries from the store.

…if you use JME and ignore the store then you are really missing out.

BTW, I remembered seeing the mentioned sprites lib in the store but there was no way I could find it using the store’s interface. Not even when clicking on “Browse All”. Maybe it’s a defect which needs to be addressed.

1 Like