Platform (1-2): TileMap quick test.

I was working hard in the last couple of days trying to figure out the best way to layout the components in order to create the UI as described in my last post.

What I've done so far is I've created a JFrame with a single JSGPanel as it's content pane.

At first, I had a separate node for each of the components:

  • Main View
  • Message View
  • Mini Map View
  • Status View

However, as I will explain, this didn't work out so great.

I created a TileMap which extended from SGGroup, and this TileMap contained a collection of Tiles (Tile extended SGImage).

public class TileMap extends SGGroup {
 
   /**
    * How many tiles high is this map.
    */
   private int height;
 
   /**
    * A Quick fix for holding our test images.
    */
   private Map<Character, Image> imageMap;
 
   /**
    * The set of tiles that composes this map.
    */
   private Set<Tile> tiles;
 
   /**
    * How many tiles wide is this map.
    */
   private int width;
 
	// parses a map string into tiles.
   public void parse(String map) {
      ...
   }
}

I added my TileMap to the JSGPanel as the MainView component. The map filled the entire frame, when I wanted it to only occupy a certain section of the frame. This is because the TileMap's size is derived from it's children - in this case all the Tiles laid out to create a playing field. Take a quick look at the SGNode and SGGroup Javadocs and you'll notice that there isn't any way to actually set the size or even a clipping area (as with FXNode). Well that's not so cool.

I know! I'll add the map to another JSGPanel and use the panel as the MainView component.

   private static void createMainView(SGGroup gameScene) {
 
      TileMap map = new TileMap(27, 13);
      // making it final so I can use it in the SGKeyListener below.
      final SGTransform.Translate mapTranslation = SGTransform.createTranslation(0, 0, map);
 
      /* ... Create the map string and parse it ... */
 
      JSGPanel mainViewPanel = new JSGPanel();
      mainViewPanel.setScene(mapTranslation);
 
      SGComponent mainViewComponent = new SGComponent();
      mainViewComponent.setComponent(mainViewPanel);
      mainViewComponent.setSize(LEFT_WIDTH, 400);
 
      SGTransform.Translate mainViewComponentTranslation = SGTransform.createTranslation(5, 5, mainViewComponent);
 
      gameScene.add(mainViewComponentTranslation);
   }

Voila! Now, I can set the size of the panel.

At this point, I was hoping that the JSGPanel's fixed size would translate down to it's children. Therefore making it smart enough not to paint the Tiles that aren't visible inside the view. I was wrong.

I added a quick SGKeyListener to the Map allowing some navigating of the tiles. In the listener, I added a print loop which shows the visibility of the tiles themselves. What I found was that all the tiles were marked as visible, which means they were being painted.

Oh well, back to the drawing board. I guess I'll have to write some of the hiding/showing logic myself.

Here's what I got out of this exercise though. I learned that SGNode and SGGroup do not have clipping capabilities (ouch). The size of the JSGPanel containing the nodes does not translate downwards to it's children. If I'm going to use JSGPanels for all the individual components, I might as well have a JPanel act as the frame's content pane, and then lay out the JSGPanels using one of Java's standard layout managers. This way, at least, the MainView can expand as the frame is re sized.

Now that I have some more understanding of the limitations of Scenegraph I can move forward with the laying out of components.

Images used can be found at Lost Garden (CuteGod: A prototyping challenge).

Cheers,
Eric

PS - Sorry, no code this time, it was pretty much all throw-away code and doesn't deserve a downloadable zip file.