UI koduna örnekler


17

UI tasarımcım, kullanıcı arayüzünün ve her şeyin güzel bir photoshop PSD'sini yaptı. Yaşadığım en büyük sorun, kullanılan daha zarif yazı tiplerini oyun içinde yenilenebilir bir şeye dönüştürmektir. Photoshop'taki bu yazı tipi stillerini bir çeşit bitmap yazı tipine dönüştürmenin bir yolu var mı?

Benim kod içinde böyle bir metin oluşturmak gerekir:

resim açıklamasını buraya girin


Böyle siteleri kontrol ettiniz mi? blogs.msdn.com/b/garykac/archive/2006/08/30/732007.aspx
ssb

Ödül için çok teşekkür ederim, ama kabul edilen cevap olarak işaretlemediğini fark ettim. Yanıttan memnun değil misiniz? Farklı bir cevap bekliyordunuz mu? Oyun GUI'lerini günlük işimin bir parçası olarak birleştiriyorum, bu yüzden sorularınızı cevaplayabileceğimizi düşünüyorum. Gerekirse açıklama veya daha ayrıntılı açıklama istemekten çekinmeyin.
Panda Pijama

Benim açımdan sadece bir gözetim. :) Bunu şimdi düzelttim. Zevk ve teşekkür ederim!
Vaughan Hilts

Yanıtlar:


18

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.Drawingyazı 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.MeasureStringyerine 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 .


2
Bu konuda neden bir öneri aldım? Eğer oy kullanacaksanız, lütfen en azından neyi yanlış yaptığım hakkında bir yorum yapın, böylece bir dahaki sefere düzeltebilirim.
Panda Pijama

Ben değilim. Bu mükemmel bir cevap. +1 :-)
Kromster diyor Monica

6

Başka birinin söylediği gibi, XNA'da spritefont sizin için ağır kaldırma yapıyor. içerik oluşturucular kulübü web sitesinde XNA stili yazı tipi görüntülerinde ihracat yapan bir bitmap yazı tipi ihracatçısı var. ( http://xbox.create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker ) Ardından, photoshop'ta veya her neyse onu açabilir ve güzel görünmesini sağlayabilirsiniz. Oradan, dokuyu içerik projenize eklersiniz ve içerik türünde hareketli grafik yazı tipi dokusunu seçersiniz. Kodunuza normal bir hareketli grafik yazı tipi gibi yüklersiniz

(Örnek: http://www.youtube.com/watch?v=SynGWrWYUQI )


Sorun şu ki, stilleri bir Photoshop yazı tipinden nasıl alıp böyle bir dokuya nasıl uygulayabileceğimden tam olarak emin değilim.
Vaughan Hilts

Burada, bir video yapacağım
CobaltHex


BMFont da aynı şeyi yapıyor ama bence daha iyi bir program. angelcode.com/products/bmfont
Cypher

eh, temel bir spritefont'u dışa aktararak, photoshop'ta istediğiniz gibi özelleştirebilirsiniz
CobaltHex

4

Çözüm oldukça basit ve çok sayıda oyun tarafından kullanılıyor. Yapmanız gereken tek şey fontlarınıza sanki sprite gibi davranmak.

Tasarımcınızın oyunda kullanmak istediğiniz tüm sayı ve harfleri çizmesini sağlayın. Ardından, bunları değişen boyutlu statik görüntülere dönüştürün (.png, .bmp, hangi biçimi kullanırsanız kullanın). Bunun gibi bir şey olacak:

resim açıklamasını buraya girin

Şimdi tek yapmanız gereken "font sayfanızdan" her harfi ekrana sanki bir sprite gibi göstermek. Dizeler ve sprite'lar arasında çeviri yapmak için kesinlikle yardımcı bir sınıf oluşturmaya yardımcı olur.

Uygulamam daha karmaşık ama kullanışlı. Yazı tipi sayfası, hepsi bir .png dosyasında birden çok yazı tipiyle yukarıdaki resim gibi oluşturulur. .iniGenişliği ve yüksekliği ile birlikte, her yazı tipi 'mektubu sayfada bir konuma eşleyen bir dosya var. Bu, tasarımcımın (ve kendimin) herhangi bir koda dokunmak zorunda kalmadan harika yazı tipleri oluşturmasını sağlıyor. Ekrana bir dize çizerken, yazı tipi ve char.ini dosyasından yazı tipi sayfasından mektubun konumunu ve sınırlarını almak için bir yöntem var , o zaman ben sadece harfin kaynağını kullanarak Texture2Dile çizin söz konusu.SpriteBatch.Draw()Rectangle


2

Kullanıcı arayüzü geniş ve karmaşık bir konudur. Yazı tipi oluşturma zor bir parçadır. Her şeyi kendiniz yeniden yapmak yerine, Flash veya HTML içeriğini oyun içinde görüntülemenize izin veren önceden var olan bir kitaplığı kullanmanızı öneririm.

Awesomium umut verici görünüyor ve XNA ile çalışmalı , böylece bir deneyebilirsiniz. Ticari olmayan oyunlar için veya tonlarca para kazanmıyorsanız ücretsizdir:

Bağımsız Şirketler İçin Ücretsiz
    Şirketiniz geçen yıl 100 bin dolardan daha az kazanmışsa , hak kazanırsınız!
Ticari Olmayan Kullanım İçin
Ücretsiz Değerlendirme ve Geliştirme için Ücretsiz


Bu oldukça şık bir fikir - sanırım ben de yazmak zorunda olduğum bazı UI kodunu soyutlıyor. Bir deneyeceğim. Teşekkürler!
Vaughan Hilts

Webkit motorunun bir limanı olduğundan, kontur anahatları, alt gölgeler ve degradeler dahil olmak üzere CSS ile ihtiyacınız olan metin stillerinin çoğunu yapabilmeniz gerekir.
ChrisC

basitçe fontları çizmek için karmaşıklaşmanın yoludur
CobaltHex

1
@CobaltHex Bu tutumu pek çok kez gördüm ve ilk "yey sıfırdan bir kullanıcı arayüzü yapalım, bu kolay olmalı, büyüdüğümüzde tekerleği yeniden keşfedeceğiz" bıkmak. Bir alıştırma olarak, OP mock-up resmini kontrol edin ve çeşitli platformlarda, ekran çözünürlüklerinde ve oranlarda tüm bir UI'yi aynı tarzda oluşturmanız gerektiğini hayal edin. Şimdi uygun bir kullanıcı arayüzüne duyulan ihtiyaç netleşiyor, bu yüzden verilen soruna doğrudan bir çözüm olmasa bile bu cevabı yayınlama özgürlüğünü aldım.
Laurent Couvidou

Sıfırdan bir kullanıcı arayüzü yaptığınızı söylemiyorum, ancak sadece bir yazı tipi çizmek istiyorsanız, tüm bir oluşturma motorunu eklemek biraz aşırıya
kaçıyor

1

Düz .spritefont içe aktarıcısından daha ince efektler arıyorsanız, bir "bitmap yazı tipi oluşturucusu" aramayı deneyebilirsiniz.

Şahsen bunu tercih ederim: http://www.ironstarmedia.co.uk/2010/01/free-game-dev-utility-fancy-bitmap-font-generator/

Diğer bazı fikirler:

  • Bir bitmap yazı tipi oluşturucusu kullanın ve daha sonra photoshop'ta vb. Ürettiği bitmap'i düzenleyin.
  • Önceden çizilmiş sprite mümkün olduğunca çok statik metin koyun. Sonra gamertags gibi şeyleri doldurun ve bir bitmap yazı tipi oluşturucusundan oluşturulan .spritefonts veya yazı tiplerini kullanarak toplamları puanlayın.

Bunu kesinlikle gördüm (ve bu arada çok havalı) ama Photoshop metin stillerimi doğrudan kullanılabilir bitmap yazı tiplerine dönüştürmeyi umuyordum.
Vaughan Hilts

0

XNAtüm zor işleri sizin için yapar. Bununla birlikte Spritefont, bir XML dosyasını tanımlayarak makinenizdeki bir yazı tipi dosyasını kolayca istediğiniz bir sprite sayfasına dönüştürebilirsiniz.

XML dosyasını İçerik projenize ekledikten sonra aşağıdakileri yükleyin ContentManager:

ContentManager.Load<SpriteFont>(@"MyFont");

İşte benim içerik projemden bir .spritefont dosyası örneği:

<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains an xml description of a font, and will be read by the XNA
Framework Content Pipeline. Follow the comments to customize the appearance
of the font in your game, and to change the characters which are available to draw
with.
-->
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">

    <!--
Modify this string to change the font that will be imported.
//TODO: A different font should be chosen before shipping for licensing reasons
-->
    <FontName>Pericles</FontName>

    <!--
Size is a float value, measured in points. Modify this value to change
the size of the font.
-->
    <Size>8.5</Size>

    <!--
Spacing is a float value, measured in pixels. Modify this value to change
the amount of spacing in between characters.
-->
    <Spacing>0</Spacing>

    <!--
UseKerning controls the layout of the font. If this value is true, kerning information
will be used when placing characters.
-->
    <UseKerning>true</UseKerning>

    <!--
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
and "Bold, Italic", and are case sensitive.
-->
    <Style>Bold</Style>

    <!--
If you uncomment this line, the default character will be substituted if you draw
or measure text that contains characters which were not included in the font.
-->
    <DefaultCharacter>@</DefaultCharacter>

    <!--
CharacterRegions control what letters are available in the font. Every
character from Start to End will be built and made available for drawing. The
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
character set. The characters are ordered according to the Unicode standard.
See the documentation for more information.
-->
    <CharacterRegions>
        <CharacterRegion>
            <Start>&#32;</Start>
            <End>&#126;</End>
        </CharacterRegion>
        <CharacterRegion>
            <Start>&#9;</Start>
            <End>&#9;</End>
        </CharacterRegion>
    </CharacterRegions>
</Asset>
</XnaContent>

1
Sorun şu ki, bunlar sadece düz TrueType yazı tipleridir. Tüm dropshadow, ışımalar ve benzeri hala bitmap yazı tiplerine veya benzeri bir şeye ihtiyacım var.
Vaughan Hilts

Düzenleme, yazı tip (ler) i aşağıdaki gibi görün: i.imgur.com/VaBpQ.png
Vaughan

0

Hiç kullanmadığımdan emin değilim ama insanlar Glif Tasarımcısı'nı kullanmamı önerdiler. İşte bir video eğitimi:

http://vimeo.com/32777161

Burada photoshop'tan bahseden bir tartışma var.

Hiero yazı tipi düzenleyicisini kullanan insanlar da var .

Gelen bu web sitesinde size bir göz isteyebilirsiniz diğer yazı editörü listesi vardır.

Hangisinin sizin için en uygun olduğunu bana bildirin :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.