created my own navigation and focus for gamepad and UI since I needed to focus on a label and the field beside it and add interactivity based on the kind of field.
I am happy with the result
created my own navigation and focus for gamepad and UI since I needed to focus on a label and the field beside it and add interactivity based on the kind of field.
I am happy with the result
Added some Quaternius • Free Game Assets nature assets to my editor. Textures are also packed into these models. Trees, rocks, flowers and bushes.
Hi everyone,
I recently had fun experimenting with the SDK. The goal was to access the resources of the SDK through the AbstractControl
class. By playing around a bit, you can get interesting results from the SDK.
I asked myself this question, “How to access the heap memory to get a reference to a Java class?”
I was able to access the SceneApplication
class and its resources AssetManager
, AppStateManager
, rootNode
, guiNode
etc… via the sun.misc.Unsafe
class.
/**
*
* @author capdevon
*/
public abstract class SceneControl extends AbstractControl {
private static final Logger logger = Logger.getLogger(SceneControl.class.getName());
private static final String APPLICATION_FIELD = "application";
private static final String ROOT_NODE_FIELD = "rootNode";
private static final String GUI_NODE_FIELD = "guiNode";
protected Application app;
protected AssetManager assetManager;
protected Node rootNode;
protected Node guiNode;
public SceneControl() {
try {
String className = "com.jme3.gde.core.scene.SceneApplication";
app = (Application) InMemoryClassAccessor.getObject(className, APPLICATION_FIELD);
assetManager = app.getAssetManager();
rootNode = (Node) getFieldValue(app, ROOT_NODE_FIELD);
logger.log(Level.INFO, "rootNode: {0}", rootNode);
guiNode = (Node) getFieldValue(app, GUI_NODE_FIELD);
logger.log(Level.INFO, "guiNode: {0}", guiNode);
app.getStateManager().attach(new SceneAppState());
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
private Object getFieldValue(Object bean, String name) throws Exception {
for (Class<?> clazz : ClassUtils.hierarchy(bean.getClass())) {
for (Field f : clazz.getDeclaredFields()) {
if (f.getName().equals(name)) {
f.setAccessible(true);
return f.get(bean);
}
}
}
return null;
}
...
}
public class InMemoryClassAccessor {
/**
* Get a static field of a class from heap memory.
*/
public static Object getObject(String className, String fieldName) throws Exception {
Unsafe unsafe = getUnsafe();
Class<?> clazz = Class.forName(className);
...
return unsafe.getObject(clazz, offset);
}
...
}
public class TerrainMapEditorComponent extends SceneControl {
private Node localGuiNode = new Node("localGuiNode");
public TerrainMapEditorComponent() {
super();
guiNode.attachChild(localGuiNode);
}
private void generateHeightMap() {
logger.log(Level.INFO, "generateHeightMap");
...
Texture2D alphaMap = TextureGenerator.textureFromHeightMap(map, REGIONS);
Picture picture = makePicture(alphaMap, ...);
localGuiNode.attachChild(picture);
}
}
In this screenshot I was able to add Picture
objects to the guiNode
, containing the AlphaMap and HeightMap data of the Terrain
in Texture2D
format. This is done by exploiting an access to the SDK via AbstractControls
.
The result is very nice, and I think the SDK is an excellent tool for those new to the engine.
I was also able to add a custom BaseAppState
to the stateManager. The initialize()
and onEnable()
methods are called correctly when the state becomes attached, but the onDisable()
and cleanup()
methods are not called when I close the scene. Perhaps this is a symptom of the bug I reported here, so by changing the background color of the ViewPort
this remains permanent even when opening another j3o
file.
/**
*
* @author capdevon
*/
public class SceneAppState extends BaseAppState {
private static final Logger logger = Logger.getLogger(SceneAppState.class.getName());
@Override
protected void initialize(Application app) {
logger.log(Level.INFO, "SceneAppState initialize");
}
@Override
protected void cleanup(Application app) {
logger.log(Level.INFO, "SceneAppState cleanup");
}
@Override
protected void onEnable() {
logger.log(Level.INFO, "SceneAppState onEnable");
}
@Override
protected void onDisable() {
logger.log(Level.INFO, "SceneAppState onDisable");
}
}
Maybe there are other ways to do what I did, in which case I am curious to hear your ideas.
I wanted to tell you this story because surely all of you programmers set yourselves challenges and tried to tackle them just for fun.
This is so cool. I think the progress you are making to integrate with the SDK is really nice.
Is this editor accessible to download and use?
Nope, not yet.
I made a wiki for Automata4j to harness the power of the Finite-State theory as a Game programming pattern featuring both the deterministic and the non-deterministic finite-state-automaton with implementation examples:
This wiki contains the following:
Next is to work on serializing and deserializing the AutoStates, and binding the TransitionalManager to a BaseAppState.
Hello everyone,
in this video I would like to show you my progress with NavMesh generation. I added lots of new features for NavMeshAgent movement, new graphical debugging tools and wrote a graphical editor integrated in the SDK (and another one with Lemur). The NavMesh is exportable in .obj format to be editable with Blender (watch the end of the video). The configuration parameters are exportable in .json, .xml and .properties formats. I tested the NavMesh generation also on procedurally generated Terrains. I hope you will enjoy it.
Here’s some further progress on lightning generation.
I made less progress than I’d have hoped since my last post, primarily because I ran into an optimization issue that showed up as soon as I added side-bolts branching out of the primary bolt.
It turned out that the mesh generation code I wrote a long time ago for custom Billboarding was creating new mesh Buffers every frame, rather than getting and editing the existing buffers. And this was causing lag spikes from constant garbage collections trying to clean up all the new Buffers I was carelessly creating and throwing away in the update loop.
Now that all the bad bugs appear to be dealt with, I can get back to working on fine-tuning the visual results of the effect, and hopefully not create too many more bugs in the process
You may have already done this research but I find these sorts of videos interesting because they challenge the classic “cartoon view” of how lightning forms:
Tendrils search from top to bottom to find the “shortest path” (resistance-wise) and then the single bolt forms (usually from bottom to top)… and this happens in a split second.
When I implement lightning in Mythruna, I will be borrowing heavily from these sorts of videos.
There are other videos that while accurate, no one would believe in a game:
…that show lightning going from the bottom up (which is how my physics teacher described it all those decades ago).
I think one easy addition to make it more believable is to add a time delay before playing the sound effect (proportional to the camera distance). About 1 sec for each 300 meters, doesn’t have to be exact, play around until it feels ok.
Has anyone ever seen a clickable button from the jme3-nifty library in an editable scene with the SDK ? This hack opens the door to a lot of possibilities…
import com.jme3.app.Application;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyEventSubscriber;
import de.lessvoid.nifty.controls.ButtonClickedEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author capdevon
*/
public class StartScreenController implements ScreenController {
private static final Logger logger = Logger.getLogger(StartScreenController.class.getName());
private final Application application;
/**
* Instantiate a ScreenController for the specified Application.
*
* @param app the Application
*/
public StartScreenController(Application app) {
this.application = app;
}
/**
* Nifty invokes this method when the screen gets enabled for the first
* time.
*
* @param nifty (not null)
* @param screen (not null)
*/
@Override
public void bind(Nifty nifty, Screen screen) {
logger.log(Level.INFO, "bind({0})", screen.getScreenId());
}
/**
* Nifty invokes this method each time the screen starts up.
*/
@Override
public void onStartScreen() {
logger.log(Level.INFO, "onStartScreen");
}
/**
* Nifty invokes this method each time the screen shuts down.
*/
@Override
public void onEndScreen() {
logger.log(Level.INFO, "onEndScreen");
}
@NiftyEventSubscriber(pattern = ".*Button")
public void onButtonClicked(final String id, final ButtonClickedEvent event) {
logger.log(Level.INFO, "Button: {0} - {1}", new Object[]{id, event.toString()});
}
}
Brilliant!
I still feel like it would look better if the title of the game was made out of the blocks you can use ingame
I tried, but it did not look good.
However, in game there is a piece of a single block so technically the letters are made of the one block pieces only