ठीक है, आपको मुझे विशिष्ट XNA कोड न देने के लिए मुझे माफ़ करना होगा, क्योंकि मैं उस प्लेटफ़ॉर्म का जानकार नहीं हूं, लेकिन जो मैं आपको बताने जा रहा हूं वह आपको किसी भी गेम इंजन पर काम करना चाहिए जो आपको स्प्राइट्स आकर्षित करने देता है।
फ़ॉन्ट्स आपकी एकमात्र समस्या नहीं है, इसलिए मैं आपको सलाह देने जा रहा हूं, और फिर मैं आपके प्रश्न का उत्तर देने जा रहा हूं। इन दो चीजों के साथ, आपको अपने GUI डिजाइनर के साथ एक लवली-डोवे संबंध बनाने में सक्षम होना चाहिए, और आप दोनों बहुत खुशी से गेम बना पाएंगे।
पहली बात यह है कि आप अपने डिजाइनर के साथ बैठने जा रहे हैं, और आप उससे दो सेट फाइलें देने के लिए कहेंगे। पहला पारदर्शी फाइलों का एक सेट है जो आपके GUI (संभवतः PSD या DXT प्रारूप में) बनाता है। हर बटन, फिक्स्ड लेबल, बैकग्राउंड, बॉर्डर और टेक्स्टबॉक्स के लिए, आपको एक फाइल मिलेगी (आप टेक्सटाइल एटलसिंग भी कर सकते हैं, लेकिन मैं आपको सलाह दूंगा कि आप अपने जीयूआई को इकट्ठा करने के बाद, और फिर ब्लिट करते समय अपने सोर्स कोऑर्डिनेट एडजस्ट करें)। गैर-स्थिर पाठ को इस बिंदु पर छोड़ दिया जाना चाहिए (मैं इसे बाद में फिर से लिखूंगा)।
दूसरी चीज जो आपको मिलेगी वह वास्तविक जीयूआई डिज़ाइन है, इस बार फ़ोटोशॉप प्रारूप में। इस फ़ाइल के लिए, आप अपने डिजाइनर से संपूर्ण GUI डिज़ाइन बनाने के लिए कहने जा रहे हैं, केवल उन्हीं फ़ाइलों का उपयोग करके जो उसने आपको पहले दी थीं।
वह फिर किसी भी प्रभाव का उपयोग करते हुए प्रत्येक GUI तत्व को एक अलग परत में डालने जा रही है। आप उसे इस पिक्सेल को सही करने के लिए बताने जा रहे हैं, क्योंकि वह स्थान जहाँ वह सब कुछ डालने जा रही है, जहाँ वह सब कुछ होगा जो वास्तव में अंतिम रूप से गेम में होगा।
एक बार जब आप इसे प्राप्त कर लेते हैं, प्रत्येक परत के लिए, आप Ctrl-T दबाएंगे, और जानकारी फलक (F8) पर, आप प्रत्येक तत्व के लिए X और Y निर्देशांक पर ध्यान देंगे। सुनिश्चित करें कि आपकी इकाइयाँ पिक्सेल पर सेट हैं (प्राथमिकताएँ-> इकाइयाँ और शासक-> इकाइयाँ)। ये ऐसे स्थान हैं जिनका उपयोग आप अपने स्प्राइट्स को खींचते समय करते हैं।
अब, फोंट के लिए, जैसा कि आप अब स्पष्ट रूप से जान सकते हैं, आप अपने फोंट को ठीक उसी तरह से नहीं देख पाएंगे, जैसा कि आप उन्हें पाठ रेंडरिंग एपीआई का उपयोग करके फ़ोटोशॉप में देखते हैं। आप अपने ग्लिफ़ को पूर्व-रेंडर करने जा रहे हैं, और फिर प्रोग्रामेटिक रूप से अपने ग्रंथों को इकट्ठा करेंगे। ऐसा करने के कई तरीके हैं, और मैं एक का उपयोग करने का उल्लेख करूंगा।
पहली बात यह है कि अपने सभी ग्लिफ़ को एक या अधिक फ़ाइलों में रेंडर करें। यदि आप केवल अंग्रेजी के बारे में परवाह करते हैं, तो सभी ग्लिफ़ के लिए एक बनावट पर्याप्त होगी, लेकिन यदि आप अधिक विस्तारित वर्ण सेट करना चाहते हैं, तो आप कई फ़ाइलों का उपयोग कर सकते हैं। बस यह सुनिश्चित करें कि आपके द्वारा चुने गए सभी ग्लिफ़ को आपके डिजाइनर द्वारा चुने गए फ़ॉन्ट पर उपलब्ध है।
इसलिए, ग्लिफ़ को प्रस्तुत करने के लिए, आप 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 या DXT के रूप में सहेजें, और इंडेक्स फ़ाइल के साथ, अपनी परियोजना में सब कुछ डालें।
ड्राइंग पाठ बहुत सरल होना चाहिए। प्रत्येक चार्ट के लिए जिसे आप प्रिंट करना चाहते हैं, सूचकांक का उपयोग करके उसका स्थान ढूंढें, उसे ड्रा करें, स्थिति को आगे बढ़ाएं और दोहराएं। आप रिक्ति, कर्लिंग (मुश्किल), ऊर्ध्वाधर रिक्ति और यहां तक कि रंग भरने के लिए भी समायोजित कर सकते हैं। लुआ में:
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()
क्योंकि वे दोनों अलग-अलग माप प्रणालियों का उपयोग करते हैं, और मापा ग्लिफ़ और तैयार किए गए एक के बीच विसंगतियों को जन्म दे सकते हैं, विशेष रूप से कुछ फोंट में पाए जाने वाले ओवरहालिंग ग्लिफ़ के साथ। अधिक जानकारी यहाँ ।