(July 2020) Monthly WIP Screenshot Thread

My first fighting game. Improving the opponent’s AI, added music sound, changed the opponent model and added a tiger to the scene.

16 Likes

“Van Gogh would’ve sold more than one painting if he’d put tigers in them.”

― Bill Watterson

9 Likes


Currently working on a card game, still very prototype-ish to get a feel for how to do ‘things’.
Screenshot is of me losing against my MCTS-AI running on a remote server.

15 Likes

Imgur

Imgur

I added the ability to create platforms to my doom-like editor.
A platform is a geometry that follows the shape of a sector and is suspended between the floor and the ceiling of that sector. Any number of platforms can be stacked on top of each other.
Here I made a simple staircase to a place that we could crawl beneath with some static lightmap effect.

8 Likes

Well, not much to show as I am still working on engine related stuff, but my OutsideEngine project is going well.
I built a simple loading screen app state for it this morning while drinking my coffee:

For anyone interested, here is the code, very portable.

package io.tlf.outside.client.appstate;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.BaseAppState;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.jme3.ui.Picture;
import io.tlf.outside.client.Config;

public class LoadingScreen extends BaseAppState {
    private Picture pic;
    private volatile SimpleApplication sapp;
    private BitmapFont font;
    private Geometry pane;
    private Geometry bar;
    private BitmapText statusLabel;
    private volatile int prog = 0;
    private volatile String msg = "Loading...";
    private float originalPaneX;
    private float originalPaneY;
    private float originalBarX;

    @Override
    protected void initialize(Application app) {
        sapp = (SimpleApplication) app;
        //Build background image
        pic = new Picture("load-pic");
        pic.setImage(app.getAssetManager(), Config.LOADING_IMAGE, false);
        pic.setWidth(app.getCamera().getWidth());
        pic.setHeight(app.getCamera().getHeight());
        pic.setLocalTranslation(0, 0, 1);
        //Build Loading Bar
        Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
        mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
        originalPaneX = app.getCamera().getWidth();
        originalPaneY = app.getCamera().getHeight() / 8;
        pane = new Geometry("load-pane", new Quad(originalPaneX, originalPaneY));
        pane.setMaterial(mat);
        pane.setLocalTranslation(0, 0, 2);

        Material matBar = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        matBar.setColor("Color", new ColorRGBA(0.9f, 0.9f, 0.9f, 0.8f));
        matBar.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
        originalBarX = app.getCamera().getWidth();
        bar = new Geometry("load-bar", new Quad(originalBarX, 10f));
        bar.setMaterial(matBar);
        bar.setLocalTranslation(0, 0f + ((app.getCamera().getHeight() / 8f) * .20f), 3f);

        //Build Text
        font = app.getAssetManager().loadFont("Interface/Fonts/Default.fnt");
        statusLabel = new BitmapText(font);
        statusLabel.setSize(20f);
        statusLabel.setText("Loading...");
        sapp.getGuiNode().attachChild(statusLabel);
        statusLabel.setLocalTranslation((float) (app.getCamera().getWidth() / 2), 0f + (float) ((app.getCamera().getHeight() / 8f) * .80), 4f);
    }

    public void setProgress(String text, int prog) {
        if (sapp == null) {
            return;
        }
        msg = text;
        this.prog = prog;
    }

    @Override
    protected void cleanup(Application app) {

    }

    @Override
    public void update(float tpf) {
        statusLabel.setLocalTranslation((float) (sapp.getCamera().getWidth() / 2f) - (statusLabel.getLineWidth() / 2), 0f + (float) ((sapp.getCamera().getHeight() / 8f) * .80), statusLabel.getLocalTranslation().z);
        statusLabel.setText(msg);
        bar.setLocalTranslation(
                (0f - ((float) sapp.getCamera().getWidth() * ((100f - (float) prog) / 100f))), //RIGHT/LEFT
                0f + ((sapp.getCamera().getHeight() / 8f) * .20f), //UP/DOWN
                bar.getLocalTranslation().z
        );
        pic.setWidth(sapp.getCamera().getWidth());
        pic.setHeight(sapp.getCamera().getHeight());
        pic.setLocalTranslation(0, 0, 1);
        float newPaneY = sapp.getCamera().getHeight() / 8;
        pane.setLocalScale(sapp.getCamera().getWidth() / originalPaneX, newPaneY / originalPaneY, 1);
        bar.setLocalScale(sapp.getCamera().getWidth() / originalBarX, 1, 1);
    }

    @Override
    protected void onEnable() {
        sapp.getGuiNode().attachChild(pic);
        sapp.getGuiNode().attachChild(statusLabel);
        sapp.getGuiNode().attachChild(pane);
        sapp.getGuiNode().attachChild(bar);
    }

    @Override
    protected void onDisable() {
        sapp.getGuiNode().detachChild(pic);
        sapp.getGuiNode().detachChild(statusLabel);
        sapp.getGuiNode().detachChild(pane);
        sapp.getGuiNode().detachChild(bar);
    }
}

EDIT: Code edited to handle window resize, and to be non-blocking.

6 Likes

@tlf30 I am interested to know more about your OutsideEngine.

Is it designed to fit into specific game genera? i.e RPG, FPS,…
Is it ES based?
Has it built-in game mechanics? i.e for lobby, combat, story, crafting, quest, dialogs, terrain…

Do you also have a master server? if so what are the features?

I am interested as I am also working on an own engine specifically designing for Multiplayer RPG.

@Ali_RS it is a MMO RPG engine. It uses an in-house component engine I designed. Networking is done with Netty.io using concurrent TCP and UDP channels to each client. The server uses a postgres database. Each server can host one or more worlds, servers can be clustered to allow world to fail-over between them, and allow clients to ‘jump’ between worlds on different servers. The client uses JavaFX for the UI. Game assets are hosted on a HTTP server that is embedded in each game server using NanoHttpd. The game world by default is a isosurface transvoxel terrain, but the engine supports height map terrains as well, or any custom terrain by using scripts.

The engine has a built in system for quests, items, world objects, dialogs, crafting, trading, character creator, world editor, etc, that is fully extensible using groovy scripts. Everything can be edited at runtime from the client by a game master. Any edits are broadcast out to clients immediately. All game assets are managed by the servers, which allows the server to dynamically generate collision meshes, and nav meshes.

If you have any questions, feel free to PM me and we can discuss the implementation details of the engine.

4 Likes

That’s cool, really. :+1:

Clustering between game servers is yet a dark area for me. :sweat_smile:

Can clients host a game server or you are going to host them only on your VPSs?

We are planning on releasing the engine, and letting the game developer decide. It is setup so that the server can be run in the background of the client to allow for single player or LAN. When the server is hosted in the background of the client, the postgres server interface is disabled, and the engine saves data to and from files on disk. The http asset server is disabled, along with several other engine components. A game developer can choose to keep these enabled or not, but recommended use is to keep them disabled.

2 Likes

Been toying with the idea of creating “non-infinite” worlds of huge sizes that don’t page terrain (though they do page other things like buildings and detail) - a lot like Ark or Red Dead, etc…

The image shows a 16x16 + 1 grid of 128x128 cells (4224 wu in size) with some crazy cool LOD at just shy of 1000 fps. You can see my target LODs in the code behind the game window - with the most aggressive LOD hitting just 5% of the full-res meshes.

It’s not the hugest world I’ve ever seen, but not bad I guess.

11 Likes

That is really cool. Is it a height map based terrain?

Yes this is heightmap-based, but the LOD works for any terrain that uses world coordinates as texture coords - i.e. triplanar mapping.

It’s just the SimplifyMesh class that does the LOD. The trick is memory management. I save each mesh (the full-res mesh and each LOD individually) as seperate files using JMEs BinaryExporter and load the mesh I want based on simple cell-distance using the BinaryImporter (threaded to avoid stuttering).

You can actually get distances a lot further than I did in that screenshot. In that instance I loaded all the LODs at once and used CullHint to show/hide the lods (and quickly ran out of memory). If you just load the LOD you need it’s a lot more economical.

4 Likes

Just a quick video of the test application I was using for dynamic object attachments.

Lots of tricky things to get working including parent/child relationships through SimEthereal and all of the interesting ECS component bits to go with that. Fixed a few bugs and limitations in the physics engine while I was in there, too.

This stuff has been kicking my butt for two months so I’m happy to have it all working this well now.

Edit: in case there are still folks here who don’t know what MOSS is… a handy link: https://www.patreon.com/posts/moss-initiative-25193330

16 Likes

A tentative game cover.

This is the most complex drawing I’ve ever made.

7 Likes

Marching Squares! A pretty cool algorithm to generate 2D worlds like Terraria, Binding of Isaac, etc. I’m trying to gather as many mesh generation techniques as I can to publish a mesh library, and this is one of them.

14 Likes

Cool :slightly_smiling_face:

Yes, it is an amazing algorithm, I got to know about Marching Squares last week from this cool video.

1 Like

Looks cool! Can probably use this in my game at some point to auto-generate maps.

This is the latest from my game. Getting (MOSS, through patroenage) block physics working with 2d-tile graphics

9 Likes

It’s been fun watching this one develop. You ended up using a lot more of MOSS than I thought you originally would. Cool to see the progress. :slight_smile:

1 Like

@asser_fahrenholz does client load the blocks data from server through the network?