2
\$\begingroup\$

So in games where there are textboxes with different sizes appearing, how does one actually render them efficiently? Games like Final Fantasy IX have dynamically sized speechbubbles for example, each with a size so it exactly matches the rendered text.

I know the basic idea is to render the frame around the bounding box of the text and with different images for each component of a box: corners, edges, center. Though how should one design that rendering if the edges aren't of 1 pixel in size when one has to compute how often an edge piece needs to be drawn next to each other to form the whole edge of the box.

Here is my naive implementation of a hopefully good enough abstracted method:

public void drawBox(Renderer renderer, int x, int y, int width, int height){
    int es = this.components.getEdgeSize();
    renderer.renderSprite(this.components.getTopLeftCorner(), x, y);
    /* Render top edge of box */
    int i;
    for(i = es; i < width - es; i += this.components.getTop().getWidth()){
        renderer.renderSprite(this.components.getTop(), x + i, y);
    }
    renderer.renderSprite(this.components.getTopRightCorner(), x + i, y);
    /* Render left edge of box */
    int j;
    for(j = es; j < height - es; j += this.components.getLeft().getHeight()){
        renderer.renderSprite(this.components.getLeft(), x, y + j);
    }
    renderer.renderSprite(this.components.getBottomLeftCorner(), x, y + j);
    /*Render bottom edge of box */
    for(i = es; i < width - es; i += this.components.getBottom().getWidth()){
        renderer.renderSprite(this.components.getBottom(), x + i, y + j);
    }
    renderer.renderSprite(this.components.getBottomRightCorner(), x + i, y + j);
    /*Render right edge of box */
    for(j = es; j < height - es; j += this.components.getRight().getHeight()){
        renderer.renderSprite(this.components.getLeft(), x + i, y + j);
    }
    int k = i;
    int l = j;
    for(i = es; i < k; i+= this.components.getCenter().getWidth()){
        for(j = es; j < l; j += this.components.getCenter().getHeight()){
            renderer.renderSprite(this.components.getCenter(), x + i, y + j);
        }
    }
}

I feel that some loops did not have to be done and the loop filling the center feels like it could potentially kill the framerate.

\$\endgroup\$
1
\$\begingroup\$

A good way to think about it is this. You can always break the textbox up into 9 bits, top left, top center, top right, etc.

Now the corners will basically always be the same size the top and bottom side will be stretched along the x axis and the left and right sides will be stretched along the y-axis. The center will be stretched along both axis obviously.

So the question is then how do you draw each of those.

Drawing the corners is easy since they always have the same dimensions. But for the sides and the centers you have a few choices.
If the textures for them tile you can just scale the sides and their texture coordinates up to fit and use sampler state wrap so that it tiles naturally. You want to make sure to round your scaling so your highest uv coordinates are integers, so that the tiling continues properly towards the corners. You could also not scale your uv coordinates and just let the image be stretched if it isn't (too) noticeable.
And for the center you can do essentially the same thing.

TL;DR: You don't really need to figure out how many of those pieces to draw. Instead thing of just 9 parts that make up a box and draw each of the parts appropriately.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The problem is, if the pieces of the box are within a single texture, I can not use texture wrapping because it would lead to, for example the center, having pieces of the rest of the box texture visible. Stretching is also a bad idea because if I have a seamless transition between the center and it's borders or between border pieces I always want to have the pieces align accordingly. That is why I always "overdraw" by one piece of border in the code above so I am sure that the box is large enough but the pieces ALWAYS align perfectly. I doubt it would look good using stretching \$\endgroup\$ – salbeira Jan 25 '16 at 13:54
  • \$\begingroup\$ So just split the pieces into different textures so you can loop them using texture wrap. \$\endgroup\$ – Nils Ole Timm Jan 25 '16 at 17:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.