TLDR Here is code to show how 9-slicing can be done in Mini Micro: https://github.com/shellrider-games/ms-Image9Slice
When creating game UIs a feature I need pretty regularly is 9-slicing. 9 slicing is a technique used to resize images that aims to prevent distortions due to scaling by ensuring that the image corners do not scale and only the middle part of an image is resized. It may sound a little unintuitive. Why we would want that behaviour? But it is a concept best understood through a visual explanation.
This works by cutting the source image into 9 different parts and scaling the individual pieces differently. The 4 corners are not scaled (1, 3, 7, 9), the border pieces are either scaled vertically (4, 6) or horizontally (2, 8), and the middle part is scaled in both directions (5).
Mini Micro does not provide this functionality out of the box (Well I was wrong there, actually there is an Image9Slice
class in /sys/lib/gui
). This gives us the opportunity to implement 9-slicing ourselves and understand the topic even better.
To solve this in MiniMicro I created a module called Image9Slice.
Image9Slice = {}
Image9Slice.src = null
Image9Slice.left = 0
Image9Slice.bottom = 0
Image9Slice.right = 0
Image9Slice.top = 0
First thing I did is setup a Image9Slice
class with src, which represents an Image
object and left, bottom, right and top for the margins.
I also added a create
function, which allows me to create new instances of my class, kinda like a constructor in other languages.
Image9Slice.create = function(src, left, bottom, right, top)
noob = new Image9Slice
noob.src = src
noob.left = left
noob.bottom = bottom
noob.right = right
noob.top = top
return noob
end function
The final magic happens in the draw
function, in which I use an Image9Slice
object, the position on the screen as left and bottom, the width and height of the drawn image, a pixelDisplay which is the display and an optional parameter scale which allows us to scale the source image. The scale parameter is very useful in case you want to use this technique for pixel-art UIs.
draw = function(image, left, bottom, width, height, pixelDisplay, scale=1)
qa.assert(
image isa Image9Slice,
"image must be of type Image9Slice")
qa.assert(
pixelDisplay isa Display and pixelDisplay.mode == 3,
"pixelDisplay must be a PixelDisplay")
middleHeight = height - image.bottom * scale - image.top * scale
srcHeight = image.src.height - image.bottom - image.top
topStop = bottom + height - image.top * scale
srcTopStop = image.src.height - image.top
middleWidth = width - image.left * scale - image.right * scale
srcWidth = image.src.width - image.left - image.right
rightStop = left + width - image.right * scale
srcRightStop = image.src.width - image.right
pixelDisplay.drawImage image.src,
left, bottom, image.left * scale, image.bottom * scale,
0, 0, image.left, image.bottom
pixelDisplay.drawImage image.src,
left, bottom + image.bottom * scale, image.left * scale, middleHeight,
0, image.bottom, image.left, srcHeight
pixelDisplay.drawImage image.src,
left, topStop, image.left * scale, image.top * scale,
0, srcTopStop, image.left, image.top
pixelDisplay.drawImage image.src,
left + image.left * scale, bottom, middleWidth, image.bottom * scale,
image.left, 0, srcWidth, image.bottom
pixelDisplay.drawImage image.src,
left + image.left * scale, bottom + image.bottom * scale, middleWidth, middleHeight,
image.left, image.bottom, srcWidth, srcHeight
pixelDisplay.drawImage image.src,
left + image.left * scale, topStop, middleWidth, image.top * scale,
image.left, srcTopStop, srcWidth, image.top
pixelDisplay.drawImage image.src,
rightStop, bottom, image.right * scale, image.bottom * scale,
srcRightStop, 0, image.right, image.bottom
pixelDisplay.drawImage image.src,
rightStop, bottom + image.bottom * scale, image.right * scale, middleHeight,
srcRightStop, image.bottom, image.right, srcHeight
pixelDisplay.drawImage image.src,
rightStop, topStop, image.right * scale, image.top *scale,
srcRightStop, srcTopStop, image.right, image.top
end function
The bulk of the function performs calculations to figure out where on the screen to draw the 9 image slices and which pixels of the source image to use. In my demo code that runs if you clone the repo from Github (https://github.com/shellrider-games/ms-Image9Slice), I use this function to draw 2 panels from a 16 x 16 pixel source image upscaled by a factor of 3.
I hope you found this useful and maybe, next time you create an UI you can use 9-slicing as the basis for creating your own custom, reusable widgets.
Top comments (0)