โอเคคุณจะต้องยกโทษให้ฉันโดยไม่ให้รหัส XNA เฉพาะคุณเพราะฉันไม่รู้ในแพลตฟอร์มนั้น แต่สิ่งที่ฉันจะบอกคุณควรทำงานกับเอ็นจิ้นเกมใด ๆ ที่ช่วยให้คุณสามารถวาดสไปรต์ได้
แบบอักษรไม่ใช่ปัญหาของคุณเท่านั้นดังนั้นฉันจะให้คำแนะนำแก่คุณและจากนั้นฉันจะตอบคำถามของคุณ ด้วยสองสิ่งเหล่านี้คุณควรจะสามารถสร้างความสัมพันธ์ที่น่ารักกับนักออกแบบ GUI ของคุณและคุณทั้งคู่จะสามารถสร้างเกมได้อย่างมีความสุข
สิ่งแรกคือคุณจะนั่งลงกับนักออกแบบของคุณและคุณจะขอให้เธอมอบไฟล์สองชุดให้คุณ ที่แรกก็คือชุดของไฟล์โปร่งใสที่ทำขึ้น GUI ของคุณ (อย่างดีที่สุดในรูปแบบ PSD หรือ DXT) สำหรับปุ่มทุกปุ่มเลเบลพื้นหลังเส้นขอบและกล่องข้อความคุณจะได้รับไฟล์เดียว (คุณยังสามารถทำการแก้ไขพื้นผิวได้ แต่ฉันขอแนะนำให้คุณทำหลังจากที่คุณรวบรวม GUI ของคุณแล้วจึงปรับพิกัดแหล่งที่มาของคุณเมื่อเกิดการชน) ข้อความที่ไม่คงที่ควรถูกทิ้งไว้ ณ จุดนี้ (ฉันจะกลับมาดูอีกครั้งในภายหลัง)
สิ่งที่สองที่คุณจะได้รับคือการออกแบบ GUI จริงในครั้งนี้ในรูปแบบ Photoshop สำหรับไฟล์นี้คุณกำลังจะไปขอให้นักออกแบบของคุณที่จะทำให้การออกแบบ GUI ทั้งหมดโดยใช้เพียงไฟล์ที่เธอก่อนหน้านี้ให้คุณ
จากนั้นเธอจะใส่องค์ประกอบ GUI ลงในเลเยอร์แยกต่างหากโดยไม่มีผลกระทบใด ๆ คุณกำลังจะบอกให้เธอทำพิกเซลนี้ให้สมบูรณ์แบบเพราะสถานที่ที่เธอจะใส่ทุกอย่างเป็นที่ที่ทุกอย่างจะเข้าสู่เกมสุดท้าย
เมื่อคุณได้รับสิ่งนั้นแล้วในแต่ละเลเยอร์คุณจะกด Ctrl-T และในบานหน้าต่างข้อมูล (F8) คุณจะจดบันทึกพิกัด X และ Y สำหรับแต่ละองค์ประกอบ ตรวจสอบให้แน่ใจว่าหน่วยของคุณตั้งค่าเป็นพิกเซล (ค่ากำหนด -> หน่วย & ผู้ปกครอง -> หน่วย) นี่คือตำแหน่งที่คุณจะใช้เมื่อวาดสไปรต์ของคุณ
ตอนนี้สำหรับฟอนต์ดังที่คุณอาจทราบได้อย่างชัดเจนในตอนนี้คุณจะไม่สามารถทำให้ฟอนต์ของคุณดูแบบเดียวกับที่คุณเห็นใน Photoshop โดยใช้ API การแสดงผลข้อความ คุณจะต้องแสดงร่ายมนตร์ล่วงหน้าของคุณก่อนแล้วจึงรวบรวมข้อความของคุณโดยทางโปรแกรม มีหลายวิธีในการทำเช่นนี้และฉันจะพูดถึงวิธีที่ฉันใช้
สิ่งแรกคือการแสดงร่ายมนตร์ทั้งหมดของคุณเป็นหนึ่งหรือมากกว่าหนึ่งไฟล์ หากคุณสนใจภาษาอังกฤษเพียงหนึ่งพื้นผิวสำหรับร่ายมนตร์ทั้งหมดจะพอเพียง แต่ถ้าคุณต้องการมีชุดอักขระที่ขยายเพิ่มขึ้นคุณสามารถใช้หลายไฟล์ได้ เพียงตรวจสอบให้แน่ใจว่าสัญลักษณ์ทั้งหมดที่คุณต้องการนั้นมีอยู่ในแบบอักษรที่นักออกแบบของคุณเลือก
ดังนั้นในการแสดงร่ายมนตร์คุณสามารถใช้เครื่องมืออำนวยความสะดวกในSystem.Drawing
การรับเมตริกแบบอักษรและวาดร่ายมนตร์ของคุณ:
Color clearColor = Color.Transparent;
Color drawColor = Color.White;
Brush brush = new SolidBrush(drawColor);
TextRenderingHint renderingType = TextRenderingHint.AntiAliasGridFit; // Antialias is fine, but be careful with ClearType, which can blergh your renders when you apply effects
StringFormat stringFormat = StringFormat.GenericTypographic;
string fileNameFormat = "helvetica14_{0}.png";
string mapFileFormat = "helvetica14.txt";
string fontName = "Helvetica";
string fontPath = @"c:\windows\fonts\helvetica.ttf";
float fontSize = 14.3f;
int spacing = 2;
Font font = new Font(fontName, fontSize);
int x = 0;
int y = 0;
int width = 1024; // Force a maximum texture size
int height = 1024;
StringBuilder data = new StringBuilder();
int lineHeight = 0;
int currentPage = 1;
var families = Fonts.GetFontFamilies(fontPath);
List<char> codepoints = new List<char>();
HashSet<char> usedCodepoints = new HashSet<char>();
foreach (FontFamily family in families)
{
var typefaces = family.GetTypefaces();
foreach (Typeface typeface in typefaces)
{
GlyphTypeface glyph;
typeface.TryGetGlyphTypeface(out glyph);
foreach (KeyValuePair<int, ushort> kvp in glyph.CharacterToGlyphMap) // Render all available glyps
{
char c = (char)kvp.Key;
if (!usedCodepoints.Contains(c))
{
codepoints.Add(c);
usedCodepoints.Add(c);
}
}
}
}
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bitmap);
g.Clear(clearColor);
g.TextRenderingHint = renderingType;
foreach (char c in codepoints)
{
string thisChar = c.ToString();
Size s = g.MeasureString(thisChar, font); // Use this instead of MeasureText()
if (s.Width > 0)
{
s.Width += (spacing * 2);
s.Height += (spacing * 2);
if (s.Height > lineHeight)
lineHeight = s.Height;
if (x + s.Width >= width)
{
x = 0;
y += lineHeight;
lineHeight = 0;
if (y + s.Height >= height)
{
y = 0;
g.Dispose();
bitmap.Save(string.Format(fileNameFormat, currentPage));
bitmap.Dispose();
bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
g = Graphics.FromImage(bitmap);
g.Clear(clearColor);
g.TextRenderingHint = renderingType;
currentPage++;
}
}
g.DrawString(thisChar, font, brush, new PointF((float)x + spacing, (float)y + spacing), stringFormat);
data.AppendFormat("{0} {1} {2} {3} {4} {5}\n", (int)c, currentPage, x, y, s.Width, s.Height);
x += s.Width;
}
}
g.Dispose();
bitmap.Save(string.Format(fileNameFormat, currentPage));
bitmap.Dispose();
File.WriteAllText(mapFileFormat, data.ToString());
ด้วยสิ่งนี้คุณได้วาดร่ายมนตร์สีขาวบนพื้นหลังโปร่งใสในไฟล์ PNG หลาย ๆ ไฟล์และสร้างไฟล์ดัชนีซึ่งจะบอกคุณเกี่ยวกับ codepoint แต่ละอันซึ่งไฟล์ glyph นั้นอยู่ตำแหน่งและขนาดของมัน โปรดสังเกตว่าฉันยังใส่พิกเซลเพิ่มเติมสองพิกเซลเพื่อแยกแต่ละสัญลักษณ์ (เพื่อรองรับเอฟเฟกต์เพิ่มเติม)
ทีนี้สำหรับไฟล์แต่ละไฟล์คุณใส่ไว้ใน photoshop และทำฟิลเตอร์ทั้งหมดที่คุณต้องการ คุณสามารถตั้งค่าสีเส้นขอบเงาโครงร่างและสิ่งอื่น ๆ ที่คุณต้องการ เพียงตรวจสอบให้แน่ใจว่าเอฟเฟกต์ไม่ทำให้ร่ายมนตร์ซ้อนกัน ถ้าเป็นเช่นนั้นให้ปรับระยะห่าง, แสดงใหม่, ล้างและทำซ้ำ บันทึกเป็น PNG หรือ DXT และพร้อมกับไฟล์ดัชนีใส่ทุกอย่างในโครงการของคุณ
ข้อความการวาดควรจะง่ายมาก สำหรับอักขระแต่ละตัวที่คุณต้องการพิมพ์ให้ค้นหาตำแหน่งโดยใช้ดัชนีวาดมันเลื่อนตำแหน่งและทำซ้ำ คุณยังสามารถปรับระยะห่างการจัดช่องไฟ (หากิน) ระยะห่างแนวตั้งและแม้แต่การระบายสี ใน lua:
function load_font(name)
local font = {}
font.name = name
font.height = 0
font.max_page = 0
font.glyphs = {}
font.pages = {}
font_definition = read_all_text("font/" .. name .. ".txt")
for codepoint, page, x, y, width, height in string.gmatch(font_definition, "(%d+) (%d+) (%d+) (%d+) (%d+) (%d+)") do
local page = tonumber(page)
local height_num = tonumber(height)
if height_num > font.height then
font.height = height_num
end
font.glyphs[tonumber(codepoint)] = { page=tonumber(page), x=tonumber(x), y=tonumber(y), width=tonumber(width), height=height_num }
if font.max_page < page then
font.max_page = page
end
end
for page = 1, font.max_page do
font.pages[page] = load_image("font/" .. name .. "_" .. page .. ".png")
end
return font
end
function draw_text(font, chars, range, initial_x, initial_y, width, color, spacing)
local x = initial_x - spacing
local y = initial_y - spacing
if range == nil then
range = { from=1, to=#chars }
end
for i = 1, range.to do
local char = chars[i]
local glyph = font.glyphs[char]
if char == 10 then -- line break
x = initial_x - spacing
y = y + ((font.height - (spacing * 2)) * 1.4)
elseif glyph == nil then
if unavailable_glyphs[char] == nil then
unavailable_glyphs[char] = true
end
else
if x + glyph.width - spacing > initial_x + width then
x = initial_x - spacing
y = y + ((font.height - (spacing * 2)) * 1.4)
end
if i >= range.from then
draw_sprite(font.pages[glyph.page], x, y, glyph.x, glyph.y, glyph.width, glyph.height, color)
end
x = x + glyph.width - (spacing * 2)
end
end
end
และคุณไป ทำซ้ำสำหรับแบบอักษรอื่น ๆ (และปรับขนาดให้เหมาะสมด้วย)
แก้ไข : ฉันเปลี่ยนรหัสเพื่อใช้Graphics.MeasureString
แทนที่จะเป็น TextRenderer.MeasureText()
เพราะทั้งคู่ใช้ระบบการวัดที่แตกต่างกันและอาจนำไปสู่ความไม่สอดคล้องระหว่างร่ายมนตร์ที่วัดกับที่วาดโดยเฉพาะกับร่ายมนตร์ที่พบในแบบอักษรบางแบบ ข้อมูลเพิ่มเติมที่นี่