2D scene representation and storage

Hi

I’ve googled and searched the forums, so I hope its ok asking for directions here. I’m trying to develop a top-down space shooter (very much inspired by Subspace Continuum and the Neon Vector Shooter on Tuts+), and I’m wondering how to store/save/prepare level information. It’s all 2D action, and I know I can use collision groups with players/level boundaries/level maze etc, however, I’m wondering how to prepare and store this information.

Best case scenario, the level would be a 2D representation of vectors including texture, mass (can I pass through it) and other information for the whole level.

Thinking it through, perhaps every object on the level can be represented by bit-wise information (concatenating the various combinations of texture/material/mass/gravity etc. into one number, along with information on the mesh. I would not mind simplifying things, to say every wall is x pixels thick, always represented by y number of coordinates that the wall passes through etc.

Looking for pointers to documentation that could give me an overview of different methods/perspectives/alternatives.

Kind regards
Asser

Hey, you can store your data in .j3o files. One option might be, that you create your own “data” class where all relevant information is stored in and save and load this one. This class has to implement the com.jme3.export.Savable interface.

Further information can be found here:
https://jmonkeyengine.github.io/wiki/jme3/advanced/save_and_load.html#toolbar

Hopefully I could help you or at least gave you some ideas which you can use.

I’ve actually been kinda playing with this sort of thing for a wee while, trying out a few ways of representing top-down 2d levels. I ultimately failed but my goal wasn’t quite the same as yours!

Anyway, looking at subspace continuum videos I think you could probably just use an image. The simplest way to explain would be imagine a black image with white lines on it. You open the image in jmonkeyengine and iterate over it building the level - ignoring black pixels and creating a box for white pixels. The box would be created at the x,y position of the image and at 0 height in 3d space.

If you wanted different walls, use a different colour, and have that represent different stuff.

The advantage of this approach is that its easy to build levels since you can use any image editor that can save png’s or whatever.

Here is some code that may help:

/**
     * 2. Create the map
     */
    Texture theMap = assetManager.loadTexture("Scenes/ahouse2.png");

    Image colorImage = theMap.getImage();

    int imageWidth = colorImage.getWidth();
    int imageHeight = colorImage.getHeight();

    if (imageWidth != imageHeight) {
        throw new RuntimeException("imageWidth: " + imageWidth
                + " != imageHeight: " + imageHeight);
    }
    System.out.println("number of thingys " + imageWidth * imageHeight);
    ImageRaster raster = ImageRaster.create(colorImage);

    ColorRGBA colorStore = new ColorRGBA();

    for (int h = imageHeight - 1; h >= 0; --h) {

        for (int w = 0; w < imageWidth; ++w) {
            float blue = raster.getPixel(w, h, colorStore).getBlue();
            float red = raster.getPixel(w, h, colorStore).getRed();
            float green = raster.getPixel(w, h, colorStore).getGreen();

            float colour = blue + red + green;

            if (colour == 3.0) {
                addFloor(w, h, environment);
            } else if (colour == 0.0) {
               addWall(w, h, environment);
            } else {
                addObstacle(w, h, environment);
            }

        }

    }
   ...
   ...
  rootNode.attach(environment);
   ...
   ...

private void addFloor(int w, int h, Node aNode) {
    Quad quad = new Quad(0.1f, 0.1f);

    Geometry geo = new Geometry(w + "," + h, quad);
    geo.rotate((float) (Math.PI / 2) * 3, 0, 0);
    /* we add/remove 0.05 because the rotation isn't about the centre, I think its off to one side */
    geo.setLocalTranslation((w * 0.1f) - 0.05f, 0f, (h * 0.1f) + 0.05f);
    
    geo.setMaterial(mat_terrain);
    aNode.attachChild(geo);
}

private void addWall(int w, int h, Node aNode) {
    Geometry geo = new Geometry(w + "," + h, new Box(0.05f, 0.05f, 0.05f));
    geo.setLocalTranslation(w * 0.1f, 0f, h * 0.1f);
    geo.setMaterial(mat_wall);
    aNode.attachChild(geo);
}

private void addObstacle(int w, int h, Node aNode) {
    Geometry geo = new Geometry(w + "," + h, new Box(0.05f, 0.125f, 0.05f));
    geo.setLocalTranslation(w * 0.1f, 0f, h * 0.1f);
    geo.setMaterial(mat_obstacle);
    aNode.attachChild(geo);
}

Full file here:

https://bitbucket.org/jakebriggs/modeltest/src/aaa111ed962322ffc4af5f135fafbe6c6bdb2dce/src/mygame/Main.java?fileviewer=file-view-default

Now the code above is messy as fuck and I am placing a floor and walls and obstacles based on the colour, and I am probably not working the colours out correctly, and I found out later you don’t need to make your own ColorStore object, and I was using xml files to position NPC’s in the level (you could define starting positions with a colour pixel if you don’t need a floor which you don’t).

Also I am just spitting out boxes, and this would leave a lot of faces never seen so I guess there are inefficiencies in the above code, but you could easily change the addWall method to create quads and assemble your own wall.