# (July 2021) Monthly WIP Screenshot Thread

With 2021 half gone, I’m focusing more on writing apps (instead of libraries). I recently added “props” to jme-vehicles. Props are groups of rigid bodies that you can push around and knock over.

Here, for instance, Nehon’s hovertank faces off against some traffic cones, barrels, and barriers (3-D models by Sabri Ayeş) …

And here’s the “after” screenshot …

20 Likes

Playing around with adding generated rivers this week. Kicked my butt a little but I’ve made progress.

This river calculates in a second or two now and it’s an iterative process so could run in steps in the background:

The red is the actual path of the river. The cyan is the places that the A* algorithm visited to find the path. I’m curious to see if I can use the data in a useful way to make bodies of water along the river.

For reference, that river is ~8 km long “as the crow flies” but the river’s path is actually more like 11 km.

Another example why it’s tempting to capture the visit data:

Finding it’s way around the mountains… even if it has to search a lot to do it:

…those are some of the largest number of iterations to solve.

From above:

It can even find it’s way through the canyons:

I calculate the rivers by finding probable sources within 16 km tiles… but so far I’m just testing one tile at a time. Here is a composite of 5 of the tiles with the “4 best” rivers each.

The real algorithm will use local climate to randomly determine the number of sources to use as well as whether to actually activate a particular source. So hopefully the area in the lower right would get a few more rivers than the dry area in the upper left.

…either way, in the game of procedural generation you learn that overly strict rules will strangle the “fun” out of the terrain where as the imagination can almost always explain weird/random things. So in the end, I often let the algorithm lead me. Better 9 really cool looking things with 1 “That’s kind of weird” versus 10 totally sensible boring things.

22 Likes

Finally was able to implement the wall slide feature. I had no idea how to pull it off. Yet here’s the solution.

I feel confident in implementing a full game physics engine now.

Ignore the jittering introduced during the gif image conversion.

5 Likes

Not JME related, but still cool. For the next major release of the Outside Engine, I am implementing a multi-rendering API backend. This version had a major rewrite of the core API, during the rewrite I slipped in an abstraction layer for rendering.

Here is an in-house OpenGL 4.6 backend using a basic fixed rendering pipeline.

It also has ImGui running. The new backend supports custom rendering, window, input, and ui systems, including a coupler for jme (WIP). Currently a custom glfw window and input system was added. This was a good test for the next phase, which is implementing a Vulkan renderer.

Outside is fully multi-threaded, in this screenshot the client is configured with three threads. One for rendering, one for game events, and one for network communication to the server (which creates several child threads using Netty.IO). The new backend enables the scene graph to be edited by any thread concurrently without any synchronized locking. This is done with very careful management of the scene graph internally for handing off to be renderer.

7 Likes

My fancy farm

Note, low fps is caused by screenshot app.

13 Likes

Great job @Ali_RS, I like how you designed the inventory. Soon I will ask you for advice about it.

1 Like

Hello everybody,
in this month’s video I tried to reproduce the mechanics and effects of the listening mode of the game “The Last of Us”.

Pressing the button to activate listening mode enables the Grayscale filter and the Outliner filter to show the profile of enemies through walls. Player animations automatically change to the stealth profile with reduced and slow movements to emphasize the feeling of focus and caution when perceiving enemies around.

## Edit:

Only enemies within the range of perception are highlighted by the filter. In the original game, in fact, the listening distance can be increased with upgrades to improve the tactical advantage.

I’m doing a lot of testing to improve and debug enemy AI. Updates on this will follow.

The grayscale filter can be found here:

The Ouliner filter can be found here:
https://store.jmonkeyengine.org/5246c9ac-3f4c-4a5d-9fb0-470eb4026246

I reworked the base code a bit and added a fix where the filter doesn’t work when viewport background is not black. Here is the final code:

``````import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme3.app.Application;
import com.jme3.app.state.BaseAppState;
import com.jme3.math.ColorRGBA;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.SceneProcessor;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;

/**
*
* @author capdevon
*/
public class OutlineFilterState extends BaseAppState {

private static final Logger logger = Logger.getLogger(OutlineFilterState.class.getName());

private static final String OutlineSelected = "OutlineSelected";

private ViewPort outlineViewport;
private FilterPostProcessor fpp;
private OutlineFilter outlineFilter;
private int width = 2;
private ColorRGBA color = ColorRGBA.White.clone();

/**
* default Constructor
*/
public OutlineFilterState() {
this(false);
}

public OutlineFilterState(boolean enabled) {
setEnabled(enabled);
}

public OutlineFilterState(int width, ColorRGBA color) {
this.width = width;
this.color = color;
}

@Override
protected void initialize(Application app) {
outlineViewport = app.getRenderManager().createPreView("OutlineViewport", app.getCamera());

//add this to fix the filter doesn't work when viewport background is not black
outlineViewport.setClearFlags(true, false, false);
outlineViewport.setBackgroundColor(ColorRGBA.BlackNoAlpha);
//----

OutlinePreFilter outlinePreFilter = new OutlinePreFilter();
outlineFilter = new OutlineFilter(outlinePreFilter);
outlineFilter.setOutlineColor(color);
outlineFilter.setOutlineWidth(width);

FilterPostProcessor outlinefpp = new FilterPostProcessor(app.getAssetManager());

initFilterPP(app);

logger.log(Level.INFO, "Outliner initialized");
}

private void initFilterPP(Application app) {
// get default viewport
ViewPort viewPort = app.getViewPort();
for (SceneProcessor processor : viewPort.getProcessors()) {
if (processor instanceof FilterPostProcessor) {
fpp = (FilterPostProcessor) processor;
}
}

if (fpp == null) {
}
}

@Override
protected void cleanup(Application app) {
fpp.removeFilter(outlineFilter);
outlineViewport.clearProcessors();
app.getRenderManager().removePreView(outlineViewport);
//logger.log(Level.INFO, "Outliner destroyed");
}

@Override
protected void onEnable() {
setFilterEnabled(true);
//logger.log(Level.INFO, "onEnable");
}

@Override
protected void onDisable() {
setFilterEnabled(false);
//logger.log(Level.INFO, "onDisable");
}

private void setFilterEnabled(boolean enabled) {
outlineFilter.setEnabled(enabled);
outlineFilter.getOutlinePreFilter().setEnabled(enabled);
}

/**
* Register this model to the outline viewport.
* @param model
*/
public void select(Spatial model) {
if (!isSelected(model)) {
outlineViewport.attachScene(model);
model.setUserData(OutlineSelected, true);
//logger.log(Level.INFO, "Model attached: " + model);
}
}

/**
* Unregister this model from the outline viewport.
* @param model
*/
public void deselect(Spatial model) {
if (isSelected(model)) {
outlineViewport.detachScene(model);
model.setUserData(OutlineSelected, false);
//logger.log(Level.INFO, "Model detached: " + model);
}
}

private boolean isSelected(Spatial model) {
return Boolean.TRUE.equals(model.getUserData(OutlineSelected));
}

}
``````

I thank the community for the help they always provide.

Have a great weekend everybody.

13 Likes

Thank you.

And you have done a nice job with remaking that mechanic.

3 Likes

Over the weekend, I more or less finalized river plotting. It was a difficult balance between something that would finish quickly and still produce interesting results. The results are pretty nice and I look forward to (hopefully) being able to float down some of these in a raft some day:

(scale reminder: large hexagons are spaced at 3072 meters and represent about a days worth of daylight walking in Mythruna game time.)

Since that is working on a cached-world scale, I can shift attention back to land types. Here I am nearing final land type classification. I may tweak some of the thresholds but I’m pretty happy with this:

It may be hard to see without zooming but the white vertical line in the center is the spawn point and that serves to mark the 16 km grid square from which the generation will work outwards.

Legend:
green spikes = forest
yellow spikes = ‘landable’ coast line (ie: where the water is deep enough where docks could be built)
pink slashes = flat land
pink dots = shallows (useful for fishing, etc.)
red slashes = cliff tops
cyan dots = ground water
orange crosses = arable land
blue = rivers

These will ultimately affect the probability of different types of settlements and other points of interest. But even aside from that, it’s kind of a satisfying visualization.

12 Likes

I’ve been working on some gun models for an fps the past few days

Groza bullpup

M4 style rifle

And a uzi

Been working on a GunControl class () to handle shooting, recoil, shell ejection, etc. It’s been going fairly well, but I cannot actual control a gun spatial yet because my blender version does not support gltf exporting very well and my jme version doesn’t have the `com.jme3.anim` package.

10 Likes

Used the land types to calculate the probabilities that some kind of a settlement would appear at any given point on the map… then filtered to coast lines and picked the starter coastal towns (red spikes):

…so far so good. May need some more tweaking but now I can move to the inland settlements and major roads.

Edit: note that the little yellow spikes are the plotted probabilities, filtered to the coastlines.

5 Likes

Path finding implemented for Dyn4j. The yellow line in front of the NPC indicates the path.
I can’t stop thinking about how cute is that enemy moving around .

6 Likes

Just gonna reference GitHub - implicit-invocation/jwalkable: Easy 2D polygonal pathfinding for Java. here. It works really well, you just have to maintain your polygons if you change the level - other than that its really easy to work with.

1 Like

Had some setbacks today because a lightning strike took out my main monitor. Fortunately, I had an identical one sitting right next to it but swapping it out was quite destructive (then finding ordering a cheap replacement for the one I Frankensteined, etc.)

Anyway, after coastal towns (see above) I worked out inland towns… which found bugs in the other and fixing the bugs made things lamer… so I had to tweak the algorithms again. Such is the way of things.

White are the main connector roads. The red roads are ones that didn’t fully resolve because I haven’t added bridges and sea routes to the algorithm yet. (I actually hope to do sea trade routes totally separate so hopefully the bridges will connect all of the feeder villages to their main towns… else I may have to side track to connect all of the port towns to each other and then circle back to roads.)

The towns already know what natural resources they have and the graph that connects them via roads… so it will be interesting to someday map out the trade routes to keep all of the settlements balanced.

Edit: implemented bridges and tunnels… though tunnels never activate on this map as they are never cost effective.

Next will be sea routes so that I can balance resource distribution and make determinations about whether a settlement is a city, town, small village, etc…

11 Likes

this is really impressive!
i always did like auto-generated game maps, but in complex way like is is here.

Besides the click-to-move mechanic I had previously, I also added a virtual joystick that shows up when dragging on terrain.

Here is a demo video

Hoeing and planting actions have no animation at the moment just a cooldown timer shown on the action bar for now. Chickens are also static for now.

The coop has no navigation mesh yet, that is the reason the player walks inside to pick up the eggs.

Still, WIP. Stay tuned.

Edit:
Forgot to mention, plants can continue growing offline (i.e when the player is not in the game) that applies for animal product generation as well.

10 Likes

Thanks!

Me, too. Even though this is for generating the terrain/towns/etc. for my block worlds, I fantasize about turning it into a map maker for D&D and the like. So many of them are pretty bad. (And some good ones, too… but so many are not.)

1 Like

What’s up with all the random triangles that are just a longer path to another already connected city? Is that by design or an unintentional side effect of the algorithm used?

Not by design. The algorithm just tries to find the best paths. If you imagine three towns that are about equidistant apart:

…then depending on the terrain, it may be cheaper to connect B and C directly rather than go from B to A to C.

In some cases, it also depends on the order that the roads were built. Port towns will increase the probability of inland villages that can provide them resources that they don’t already have readily available. Consequently, those relationships will get roads before the village to village relationships… but it’s not unrealistic to think that two villages that are less than a day’s travel apart (or some cases closer to half a day) would also connect through roads. That would make a triangle also.

It’s also not yet clear which of these will be official roads (maintained by the government, safe for travel, etc.) and which are more like well-used foot paths because people found them really convenient.

Another thing that I constantly have to balance is what this actually looks like from the player’s perspective “on the ground” and I have a list of a dozen or so ‘rules’ about what the expectations should be from “wherever you are standing”. The game world won’t be very interesting if there are huge portions of continents with nothing but terrain and trees… but neither will it be very interesting if over ever new hill is another sign of civilization.

TL;DR: it’s complicated.

Edit: By the way, Yesterday I plugged in some different world seeds just to see how things were doing. I generally test with the same one because it’s easier to see how tweaks in the algorithm change what is happening. I made a gallery of some of them:

Seeds 0, 1, and 2 are there in addition to seed 123 which I’ve been testing with.

Edit: also note, after making those I found a bug where some of the roads weren’t being rendered correctly. Even so, there is still something I need to fix to get some of the isolated road networks to connect to each other when they are otherwise already really close to connecting. And to change the influences so that more villages spawn up-river on those long winding rivers (especially if there are already villages downstream).

Edit: and these things also seem to happen in the real world… lots of triangles in this map of France for example:

5 Likes

Makes me wonder if any of the seeds will look just like France

1 Like