Akkoard
(Akkoard)
June 18, 2019, 3:26am
#1
So recently I created an alphabet for my sci-fi military group, but that’s not the case here. What I have a problem with is scripting a letter to image converter. There are 24 images and they all have their own letter. So the script should read the player’s phrase and convert them into images that could then be displayed on the board. If any of you know how to do this, please let me know.
I was talking about something similar here:
I have never used spritesheets before, but I can immediately tell you that you would need to play with the ImageRectOffset and ImageRectSize properties of image labels, and you would need to keep the value of each property for each letter in a table:
local Letters = {
-- letter = {position, size}
["a"] = { Vector2.new(0, 0), Vector2.new(10, 15) },
["b"] = { ... },
["c"] = { ... },
...,
["z"] = { ... },
["A"] = { ... },
["B"] = { ... },
...,
["."] = { ... },
["!"] = { ... },
...,
["…
If you happen to use spritesheets, then that will be the topic for you.
Otherwise, I made a function and structure there that will help you with converting them to images displayed on a board.
It's pretty lengthy, so I put it in this details section to shorten the post.
As for indexing the string itself , there is a method for it, string.sub
, and you can interpret entire strings with a numeric for
loop:
function CreatePhrase(str)
Phrase = {}
for i = 1, #str do
local letter = string.sub(str, i, i)
local ImageLetter = CreateLetter(letter)
if ImageLetter then
ImageLetter.LayoutOrder = i -- for the next step
table.insert(Phrase, ImageLetter)
end
end
return Phrase
end
If you want to put these letters beside each other, the best way to do it is probably with a UIListLayout
instance, with the letters listed horizontally and sorting by LayoutOrder.
If you want to put these letters in a frame, the hierarchy in the explorer would probably look like this:
Frame
- UIListLayout
- ImageLabel
- ImageLabel
- ImageLabel
- ...
Edit-edit: UIListLayout
s work for singular lines of text, but not for multi-line text . This could be solved using a double-layered UIListLayout
, one for the frames housing the string, and one for the string itself. A UITableLayout
will not work because it only sorts the rows of frames by LayoutOrder, not the phrase contained inside. A UIGridLayout
will not work because it restricts size as well as position, which is coincidentially very useful for monospace fonts.
The hierarchy in the explorer would look like this:
MasterFrame
- UIListLayout
- Frame
- UIListLayout
- ImageLabel
- ImageLabel
- ...
- Frame
- ...
- ...
This evidently means you will need to use a word-wrapping function to make sure each letter does not trail off to the end of the screen. I think my function (below) is complex, but it does its job properly as long as I didn’t make any logical errors :
function WrapPhrase(str, sizeY, parent) -- string, UDim, GuiObject
local Block = {}
local LtrRelocation = {}
local i = 1
while i <= #str do
-- Create a new frame to house a line
local line = Instance.new("Frame") do
line.Size = UDim2.new(UDim.new(1, 0), sizeY)
local listLayout = Instance.new("UIListLayout") do
listLayout.FillDIrection = Enum.FillDirection.Horizontal
listLayout.SortOrder = Enum.SortOrder.LayoutOrder
listLayout.Parent = line
end
line.Parent = parent -- required to evaluate line.AbsoluteSize
table.insert(Block, line)
end
-- Start generating the phrase
local phrase = {}
local spaceNum
while listLayout.AbsoluteContentSize.X <= line.AbsoluteSize.X and i <= #str do
local ImageLetter = LtrRelocation[i]
if not ImageLetter then
local letter = string.sub(str, i, i)
ImageLetter = CreateLetter(letter)
end
if ImageLetter then
ImageLetter.LayoutOrder = i
table.insert(phrase, i, ImageLetter)
ImageLetter.Parent = line
--listLayout:ApplyLayout() -- just in case
end
if letter == " " then
spaceNum = i
end
i = i + 1
end
-- Go back until the last space character is reached unless there is none
if i <= #str then -- OR the end of the string has been reached
if spaceNum then
while i > spaceNum + 1 do
i = i - 1
table.insert(LtrRelocation, i, phrase[i])
end
else
i = i - 1
table.insert(LtrRelocation, i, phrase[i])
end
end
end
return Block
end