Creating 9-Patch Textures in SDL - Game DevLog Series #2
Last week I wrote a bit about everything and my progress so far. I just want to continue this series and write loosely about my experience in writing my own little game engine.
What is working right now:
- Game-Loop
- Command-Pattern (described here: Link)
- Random Map Generation with Noise (FastNoise)
- "Infinite"-Map with Chunks which get rendered when you're near.
- Fast text rendering with sprite sheet
- *.tmx/xml importer for maps made with Tiled
- Camera movement on the map (of course)
This week I worked a bit on the GUI. I really was not looking forward to this, but there comes a time you just need some buttons, health-bars etc.
At first I was thinking of just taking a "ready" to use GUI-Library. But I was thinking I don't need everything they provide.
Here is a little list of SDL Gui Libraries so you don't have to google them... (write in the comments if you've found some more)
- https://github.com/actsl/kiss_sdl
- https://github.com/wjakob/nanogui
- https://github.com/kallisti5/guisan
- https://github.com/mozeal/SDL_gui
So I went with my own implementation. Currently I have some basics functionality, creating layout containers (which can rearrange their child elements), buttons and also an text input field.
Right now I was working on an 9-Patch texture for my UI-Elements. Basically you have a texture like:
And then you patch them all together to an button with your desired width and height.
For the corners and edges the coordinates are like this:
//CORNERS
int x_np = ninePatch->x;
int y_np = ninePatch->y;
int x_r = ninePatch->w - nine_patch_tile_s + x_np;
int y_bot = ninePatch->h - nine_patch_tile_s + y_np;
int xw_tile = x_np + ((ninePatch->w/2) - (tile_size / 2));
int yh_tile = y_np + ((ninePatch->h/2) - (tile_size / 2));
src_rects[NW].x = x_np;
src_rects[NW].y = y_np;
src_rects[N].x = xw_tile;
src_rects[N].y = y_np;
src_rects[NE].x = x_r;
src_rects[NE].y = y_np;
src_rects[E].x = x_r;
src_rects[E].y = yh_tile;
src_rects[SE].x = x_r;
src_rects[SE].y = y_bot;
src_rects[S].x = xw_tile;
src_rects[S].y = y_bot;
src_rects[SW].x = x_np;
src_rects[SW].y = y_bot;
src_rects[W].x = x_np;
src_rects[W].y = yh_tile;
src_rects[CENTER] = {xw_tile, yh_tile, tile_size, tile_size};
with:
SDL_Rect src_rects[9]{};
enum orientation { ///< clockwise then center
NW,
N,
NE,
E,
SE,
S,
SW,
W,
CENTER
};
I put this all in a class called NinePatchDrawable
. Do this at your liking, my NinePatchDrawable
has a Texture
and what I do is I check if I need a resize or if the texture has never been created, I then render the different little edges on a texture. I do it like this:
target_texture->setBlendMode(SDL_BLENDMODE_BLEND);
auto *sdl_renderer = renderer->getSDLRenderer();
auto *sdl_target = target_texture->getSDLTexture();
auto *sdl_src = src_texture->getSDLTexture();
//Setting Render Target
if(SDL_SetRenderTarget(sdl_renderer, sdl_target) < 0) {
spdlog::error("[NinePatchDrawable] could not set texture as rendering target");
}
SDL_RenderClear(sdl_renderer);
calc_size();
SDL_Rect dest;
dest.w = step_x;
dest.h = step_y;
for (int y_l = 0; y_l < y_max_step ; ++y_l) {
for(int x_l = 0; x_l < x_max_step; ++x_l) {
dest.x = step_x * x_l;
dest.y = step_y * y_l;
orientation o = get_orientation(x_l, y_l);
SDL_RenderCopyEx(sdl_renderer, sdl_src,
&src_rects[o], &dest,
0.0, nullptr, SDL_FLIP_NONE);
}
}
SDL_SetRenderTarget(sdl_renderer, nullptr); // reset Render Target
spdlog::info("[NinePatchDrawable] rendering ninePatch");
There are different, and I bet better methods of doing this. If you do this in any other way just comment this blog post :) I'm really happy for your feedback.
Future Ideas are that you also define a tile with a width=1 for the edges so you can size the textures with pixel resolution. I have to define a button with a multiple of the tile size of my edges/corners. But for me that's enough :) I don't want to over engineer this, If I really don't need it.
So if you like this series to continue please write a comment below :)
The Texture I used can be found on https://www.kenney.nl/ he does a great job and I use the textures from him for prototyping. Really awesome work there.
9-Patch Android: https://developer.android.com/studio/write/draw9patch
More on 9-Patches for Android: https://developer.android.com/guide/topics/graphics/drawables#nine-patch