Minimap

hi :slight_smile:

I need a minimap where you can see the whole terrain and the units as little points but I am not sure weather I should use a Viewport or a BufferedImage. I thought rendering the terrain in the viewport would be slow and therefore I wrote a small class which makes a screenshot of the terrain and returns the image. But i could also use this image in a viewport.

After this I tried Graphics2D because I thought it would be faster but atm I am failing at streaming the BufferedImage to the Texture.

What do you think?

http://hub.jmonkeyengine.org/groups/import-assets/forum/topic/exporting-texture-from-assets/

Camera/viewport would work in some instances, however… in a building, in a dungeon, etc. with multiple levels… not so much. As for the BufferedImage to Texture. Post what your doing now… Are you using Texture2D? Or?

I have a minimap class which creates the BufferedImage. Now I use the AWTLoader but the texture is not refreshed when I draw on on the image later. (cause I need a buffer and not a converter)

[java] public Minimap()

{

BufferedImage img = null;

try {

img = ImageIO.read(new File("assets/Textures/Minimap/minimap.png"));

} catch (IOException e) {

}



Graphics2D g = (Graphics2D)img.getGraphics();



Image i = new AWTLoader().load(img, true);

texture = new Texture2D(i);



g.drawString("Test", 50, 50); //Not Displayed yet

}



public Texture getTexture()

{

return texture;

}[/java]



And then I am adding the texture to nifty:

[java] public void addMinimap()

{

Minimap minimap = new Minimap();

ImageRenderer mm = nifty.getScreen("start").findElementByName("minimap").getRenderer(ImageRenderer.class);

((DesktopAssetManager) gameApp.getAssetManager()).addToCache(new TextureKey("minimapkey"), minimap.getTexture());

NiftyImage img = nifty.getRenderEngine().createImage("minimapkey", false);

mm.setImage(img);

}[/java]

I found in the JME2 documentation(https://wiki.jmonkeyengine.org/legacy/doku.php/jme2:using_java2d_to_create_the_hud_texture) a PaintableImage class and with a few changes it works with JME3:



[java] import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import java.nio.ByteBuffer;

import com.jme3.texture.Image;





public abstract class PaintableImage extends Image {

private BufferedImage backImg;

private ByteBuffer scratch;





public PaintableImage(int width, int height) {

super();

try {

backImg = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);



setFormat(Format.ABGR8);

setWidth(backImg.getWidth());

setHeight(backImg.getHeight());

scratch = ByteBuffer.allocateDirect(4 * backImg.getWidth()

  • backImg.getHeight());

    } catch (IllegalArgumentException e) {

    }

    }



    public void refreshImage() {

    Graphics2D g = backImg.createGraphics();

    paint(g);

    g.dispose();



    /* get the image data /

    byte data[] = (byte[]) backImg.getRaster().getDataElements(0, 0,

    backImg.getWidth(), backImg.getHeight(), null);

    scratch.clear();

    scratch.put(data, 0, data.length);

    scratch.rewind();

    setData(scratch);

    }





    public abstract void paint(Graphics2D graphicsContext);

    }[/java]



    And here is the example:

    [java] import java.awt.Color;

    import java.awt.Graphics2D;



    public class PaintedGauge extends PaintableImage {

    private static final int MAXIMUM = 100;

    private int value = 0;



    public PaintedGauge() {

    super(64, 64);

    refreshImage();

    }



    public void setValue(int newValue) {

    newValue %= MAXIMUM;

    if (newValue != value) {

    value = newValue;

    refreshImage();

    }

    }



    public void paint(Graphics2D g) {

    g.setBackground(new Color(0f, 0f, 0f, 0f));

    g.clearRect(0, 0, getWidth(), getHeight());

    g.setColor(new Color(1f, 0f, 1f, 1f));

    g.fillRect(0, 0, value * getWidth() / MAXIMUM, getHeight());

    }

    }[/java]



    [java]import com.jme3.app.SimpleApplication;

    import com.jme3.texture.Image.Format;

    import com.jme3.texture.Texture2D;

    import com.jme3.texture.Texture;

    import com.jme3.ui.Picture;





    public class HelloBufferedImage extends SimpleApplication {



    private float value=0;

    private PaintedGauge gaugeImage;



    public static void main(String[] args){

    HelloBufferedImage app = new HelloBufferedImage();

    app.start(); // start the game

    }



    public void simpleInitApp() {

    gaugeImage = new PaintedGauge();

    gaugeImage.setValue(99);



    Picture pic = new Picture("HUD Picture");



    Texture2D texture = new Texture2D(64, 64, Format.ABGR8);

    texture.setMinFilter(Texture.MinFilter.Trilinear);

    texture.setMagFilter(Texture.MagFilter.Bilinear);

    texture.setImage(gaugeImage);

    pic.setTexture(assetManager, texture, true);



    pic.setWidth(64);

    pic.setHeight(64);

    pic.setPosition(settings.getWidth()/4, settings.getHeight()/4);

    guiNode.attachChild(pic);

    }



    public void simpleUpdate(float tpf)

    {

    value += tpf
    10;



    if(value >= 100)

    {

    value=0;

    }

    gaugeImage.setValue((int)value);

    }

    }[/java]



    Now I will try to use this to draw on a nifty image. (I think it should work.)

http://hub.jmonkeyengine.org/groups/contribution-depot-jme3/snippets/14/ ?

I would need to write my own methods loading images, drawing circles,lines and rectangles.

Yeah, but it would be more efficient and the java code for that is available. Plus it would make a nice contribution :stuck_out_tongue:

I think I will continue using Graphics2D. One last question:

When I use the PaintableImage like in my example and draw an image via Graphics the colors are changed. This is because the color order of the image is something like RGBA and not ABGR. Now i want to change this order but I am confused, the constructor of the BufferedImage only supports BufferedImage.TYPE_4BYTE_ABGR. But now i created an empty image, used ImageIO.read() to load the picture instead of the constructor and now everything works fine because the images is load as RGBA. WTF?



Solved:

backImg = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);

setFormat(Format.RGBA8);