Tamam, size belirli XNA kodu vermediğiniz için beni affetmeniz gerekecek, çünkü o platformda bilgili değilim, ama size söyleyeceğim şey sprite çekmenize izin veren herhangi bir oyun motoru üzerinde çalışmalıdır.
Yazı tipleri tek probleminiz değil, bu yüzden size bir tavsiye vereceğim ve sonra sorunuza cevap vereceğim. Bu iki şeyle, GUI tasarımcınızla lovey-dovey ilişkisi kurabilmelisiniz ve her ikiniz de çok mutlu bir şekilde oyun yapabileceksiniz.
İlk şey, tasarımcınızla oturacaksınız ve ondan size iki dosya seti vermesini isteyeceksiniz. Birincisi, GUI'nizi oluşturan bir dizi şeffaf dosyadır (en iyi PSD veya DXT formatında). Her düğme, sabit etiket, arka plan, kenarlık ve metin kutusu için bir dosya alırsınız (doku atlaslaması da yapabilirsiniz, ancak GUI'nizi oluşturduktan ve blitting yaparken kaynak koordinatlarınızı ayarladıktan sonra bunu yapmanızı tavsiye ederim). Statik olmayan metin bu noktada bırakılmalıdır (bunu daha sonra tekrar ziyaret edeceğim).
Alacağınız ikinci şey, bu sefer Photoshop formatında gerçek GUI tasarımıdır. Bu dosya için, tasarımcıdan yalnızca önceden size verdiği dosyaları kullanarak GUI tasarımının tamamını yapmasını isteyeceksiniz .
Daha sonra, her GUI öğesini ayrı bir katmana koyacak ve hiçbir etki yaratmayacak. Ona bu pikseli mükemmel yapmasını söyleyeceksiniz, çünkü her şeyi koyacağı yerler, aslında her şeyin nihai oyunda olacağı yerdir.
Bunu aldıktan sonra, her katman için Ctrl-T'ye basacaksınız ve Bilgi bölmesinde (F8), her öğe için X ve Y koordinatlarını not edeceksiniz. Birimlerinizin piksel olarak ayarlandığından emin olun (Tercihler-> Birimler ve Cetveller>> Birimler). Bunlar spritelarınızı çizerken kullanacağınız konumlardır.
Şimdi, fontlar için, şimdi açıkça bildiğiniz gibi, fontlarınızı metin oluşturma API'larını kullanarak Photoshop'ta gördüğünüz gibi görünmesini sağlayamazsınız. Gliflerinizi önceden oluşturmanız ve ardından metinlerinizi programlı olarak birleştirmeniz gerekir. Bunu yapmanın birçok yolu var ve kullandığımdan bahsedeceğim.
İlk şey, tüm gliflerinizi bir veya daha fazla dosyaya dönüştürmektir. Yalnızca İngilizce'yi önemsiyorsanız, tüm glifler için bir doku yeterli olacaktır, ancak daha geniş bir karakter kümesine sahip olmak istiyorsanız, birkaç dosya kullanabilirsiniz. İstediğiniz tüm gliflerin tasarımcınızın seçtiği yazı tipinde mevcut olduğundan emin olun.
Böylece, glifleri oluşturmak için System.Drawing
yazı tipi metriklerini almak ve gliflerinizi çizmek için özelliklerini kullanabilirsiniz:
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());
Bununla, bir dizi PNG dosyasında saydam bir arka plan üzerine beyaz glifler çizdiniz ve glifin bulunduğu dosyanın yerini, konumunu ve boyutlarını gösteren her kod noktası için size bir dizin dosyası hazırladınız. Her bir glifi ayırmak için iki ek piksel daha eklediğime dikkat edin (daha fazla efekt için)
Şimdi, bu dosyaların her biri için onu photoshop'a koyar ve istediğiniz tüm filtreleri yaparsınız. Renkleri, kenarlıkları, gölgeleri, anahatları ve istediğiniz herhangi bir şeyi ayarlayabilirsiniz. Sadece efektlerin gliflerin çakışmamasına dikkat edin. Öyleyse, aralığı ayarlayın, yeniden oluşturun, durulayın ve tekrarlayın. PNG veya DXT olarak kaydedin ve dizin dosyasıyla birlikte projenize her şeyi koyun.
Çizim metni çok basit olmalıdır. Yazdırmak istediğiniz her karakter için dizinini kullanarak konumunu bulun, çizin, konumu ilerletin ve tekrarlayın. Ayrıca aralık, karakter aralığı (zor), dikey aralık ve hatta renklendirme için de ayarlayabilirsiniz. Lua'da:
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
Ve işte gidiyorsun. Diğer tüm yazı tipleri için tekrarlayın (ve en uygun boyutta)
Düzenleme : İkisini de farklı ölçüm sistemleri kullanmak Graphics.MeasureString
yerine kullanmak için kodu değiştirdim ve TextRenderer.MeasureText()
özellikle bazı yazı tiplerinde bulunan sarkan glifler ile ölçülen glif ve çizilmiş olan arasında tutarsızlıklara yol açabilir. Daha fazla bilgi burada .