Laying out the Resources Window

I’ve been thinking about the layout issues I mentioned in the last post so over the weekend I’ve been trying to fix the minor interface issues I mentioned in the previous post.

Ordering the Items

The first of the problems I looked was that the items were not always in the correct order. This is a natural consequence of using a map to store the resources, and internally we really don’t care what order they are stored in. But we do care in the UI!

My plan is to have a predefined ordering rather than alphabetical ordering; This is partly because it allows me to categorise them, and partly because of localisation; If the resources are Aubergines and Coriander, in US English we’d need to sort them in the other order as they’d be Eggplant and Cilantro. The order I will have will be in categories, and then in order of expected acquisition. In the future, I can add a feature to sort, if needed.

To do this in the UI code I define a list of the order items based on resource ID. This will point to a small structure that contains UI specific data – the (local) name of the resource, and the icon. In kotlin, this is also specified as maintaining the order they were defined, so we have our order; and at the same time we have name and icon data.

    val resourceData = mapOf(
        ResourceType.HERB to ResourceData("Herb", herbImage),
        ResourceType.FLOWER to ResourceData("Flower", unknownImage),
        ResourceType.MUSHROOM to ResourceData("Mushroom", unknownImage),
        ResourceType.PUMPKIN to ResourceData("Pumpkin", unknownImage)
    )

One final thing; we need to have a default value for resources in case I forget to add to this list. So for this we find all the resources that don’t have a key in resourceData and just put them at the end. If these aren’t right, it’s not the worst thing as they should have been in the resource list in the first place – it’s a fallback that will make it clear that there’s a UI bug and will still be usable.

Layout and Alignment

After this, the next problem is trying to make a table-like layout. For this I’ve been looking at using a CSS Flexbox for layout. While this doesn’t support IE 10 or lower, I’m really not too worried about this; this project will take some time and I suspect by the time I’m done IE 10 will be a very rare browser for game players!

In this case we need two boxes: firstly a vertical container for each line, then a horizontal box for each line with the three items – the icon, the display name and the current value. We declare these using Kotlin, inside a loop over each relevant which is inside the outer div(“Resources”):

    div("Resources-row") {
        img(classes = "Resources-image", alt = resData.name, src = resData.graphic) {}
        span("Resources-text") {
           +"${resData.name}"
        }
        span("Resources-value") {
            +"${props.resources[resData.key]?.amount}"
        }
    }

After this we need to think about styling. The resources container is a column of boxes rather than row. Each of the rows is also a flexbox in its own right – for these ones we want to make sure the items within are centered (this covers vertical centering):

.Resources {
display: flex;
flex-direction: column;
}

.Resources-row {
display: flex;
align-items: center;
}

The image is always 32px wide, so has shrink and grow values of 0 to stop it being resized, and is the first on each row. It has a small margin to the right to stop the text butting up against it.

.Resources-image {
flex: 0 0 32px;
order: 0;
margin-right: 5px;
}

The label text is the middle on the row, left aligned. This has a flex value of 1 1 100px, as we want it to be roughly 100px wide, but it can shrink or grow if needed.

.Resources-text {
flex: 1 1 100px;
order: 1;
text-align: left;
}

The value is the next item in the row, again with a resizable shrink and grow values and right aligned. I used 63px as that is the remaining pixels assuming a 200px width, but the flexbox will stretch or shrink this. This might need some adjustment later.

.Resources-value {
flex: 1 1 63px;
order: 2;
text-align: right;
}

The end result has one issue that I need to consider: the rows are configured first rather than the rows, which means that the column boundaries may be different for each row between the number and the name. This might cause issues if I have a long name for a resource, or a large number. It’s not a problem yet though!

Results

After doing the resource window I used more flexboxes to align the main window components. The end results are here:

Which looks pretty reasonable – we’ve fixed all the interface issues raised in the previous post.

Next steps here then will be to bring the buildings UI here, as well as the player action UI. This will be the first part of actual user interaction, so this should be an interesting test to using React and Kotlin!


Leave a Reply

Your email address will not be published. Required fields are marked *