UI-Modelle zum Code

17

Mein UI-Designer hat eine schöne Photoshop-PSD der Benutzeroberfläche und alles hübsch gemacht. Das größte Problem besteht darin, einige der eleganteren Schriftarten in etwas zu konvertieren, das im Spiel gerendert werden kann. Gibt es eine Möglichkeit, diese Schriftstile in Photoshop in eine Art Bitmap-Schrift umzuwandeln?

Ich muss in der Lage sein, Text in meinem Code so zu rendern:

Bildbeschreibung hier eingeben

Vaughan Hilts
quelle
Haben Sie Websites wie diese überprüft? blogs.msdn.com/b/garykac/archive/2006/08/30/732007.aspx
ssb
Vielen Dank für das Kopfgeld, aber mir ist aufgefallen, dass Sie es nicht als akzeptierte Antwort markiert haben. Sind Sie mit der Antwort unzufrieden? Haben Sie eine andere Art von Antwort erwartet? Ich baue Spiel-GUIs als Teil meiner täglichen Arbeit zusammen, sodass ich möglicherweise in der Lage bin, Ihre Fragen zu beantworten. Fragen Sie bei Bedarf nach Klarstellungen oder ausführlicheren Erklärungen.
Panda Pyjama
Nur ein Versehen von meiner Seite. :) Ich habe das jetzt korrigiert. Viel Spaß und danke!
Vaughan Hilts

Antworten:

18

Okay, Sie werden mir verzeihen müssen, dass ich Ihnen keinen speziellen XNA-Code gegeben habe, da ich mich mit dieser Plattform nicht auskenne, aber was ich Ihnen sagen werde, sollte mit jeder Spiel-Engine funktionieren, mit der Sie Sprites zeichnen können.

Schriftarten sind nicht Ihr einziges Problem. Ich gebe Ihnen daher einen Rat und beantworte dann Ihre Frage. Mit diesen beiden Dingen sollten Sie in der Lage sein, eine Liebesbeziehung zu Ihrem GUI-Designer herzustellen, und Sie werden beide in der Lage sein, sehr glücklich Spiele zu machen.

Das erste ist, dass Sie sich mit Ihrem Designer zusammensetzen und sie bitten, Ihnen zwei Sätze von Dateien zu geben. Das erste ist eine Reihe transparenter Dateien, aus denen sich Ihre Benutzeroberfläche zusammensetzt (optimalerweise im PSD- oder DXT-Format). Für jede Schaltfläche, jedes feste Etikett, jeden Hintergrund, jeden Rahmen und jedes Textfeld erhalten Sie eine Datei (Sie können auch Texturatlas erstellen, ich empfehle dies jedoch, nachdem Sie Ihre GUI zusammengestellt und dann Ihre Quellkoordinaten beim Blitten angepasst haben). Nicht statischer Text sollte an dieser Stelle weggelassen werden (ich werde dies später noch einmal überprüfen).

Als zweites erhalten Sie das eigentliche GUI-Design, diesmal im Photoshop-Format. Für diese Datei werden Sie Ihren Designer bitten, das gesamte GUI-Design zu erstellen , wobei nur die Dateien verwendet werden, die Sie zuvor erhalten haben.

Sie wird dann jedes GUI-Element in eine separate Ebene legen und dabei keinerlei Effekte verwenden. Du wirst ihr sagen, dass sie dieses Pixel perfekt machen soll, denn die Orte, an denen sie alles ablegen wird, sind die Orte, an denen sich alles im endgültigen Spiel befinden wird.

Sobald Sie dies erhalten haben, drücken Sie für jede Ebene die Tastenkombination Strg-T und notieren im Infofenster (F8) die X- und Y-Koordinaten für jedes Element. Stellen Sie sicher, dass Ihre Einheiten auf Pixel eingestellt sind (Einstellungen-> Einheiten & Lineale-> Einheiten). Dies sind die Positionen, die Sie beim Zeichnen Ihrer Sprites verwenden werden.

Wie Sie jetzt sicher wissen, können Sie bei Schriftarten nicht erreichen, dass Ihre Schriftarten genau so aussehen, wie Sie sie in Photoshop mithilfe von Text-Rendering-APIs sehen. Sie müssen Ihre Glyphen vorrendern und dann programmatisch Ihre Texte zusammenstellen. Es gibt viele Möglichkeiten, dies zu tun, und ich werde die erwähnen, die ich benutze.

Als erstes rendern Sie alle Ihre Glyphen in eine oder mehrere Dateien. Wenn Sie sich nur für Englisch interessieren, reicht eine Textur für alle Glyphen aus. Wenn Sie jedoch einen erweiterten Zeichensatz möchten, können Sie mehrere Dateien verwenden. Stellen Sie einfach sicher, dass alle gewünschten Glyphen für die von Ihrem Designer gewählte Schriftart verfügbar sind.

System.DrawingUm die Glyphen zu rendern, können Sie die Funktionen von verwenden , um die Schriftartmetriken abzurufen und Ihre Glyphen zu zeichnen:

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());

Damit haben Sie weiße Glyphen über einen transparenten Hintergrund in einer Reihe von PNG-Dateien gezeichnet und eine Indexdatei erstellt, die für jeden Codepunkt angibt, in welcher Datei sich die Glyphe befindet, wo sie sich befindet und welche Abmessungen sie haben. Beachten Sie, dass ich auch zwei zusätzliche Pixel anbringe, um die einzelnen Glyphen zu trennen (um weitere Effekte zu erzielen).

Nun legen Sie jede dieser Dateien in Photoshop ab und führen alle gewünschten Filter aus. Sie können Farben, Ränder, Schatten, Konturen und alles andere festlegen, was Sie möchten. Stellen Sie einfach sicher, dass sich die Glyphen durch die Effekte nicht überlappen. Passen Sie in diesem Fall den Abstand an, rendern Sie erneut, spülen Sie und wiederholen Sie den Vorgang. Speichern Sie als PNG oder DXT und fügen Sie zusammen mit der Indexdatei alles in Ihr Projekt ein.

Zeichentext sollte sehr einfach sein. Suchen Sie für jedes Zeichen, das Sie drucken möchten, die Position anhand des Index, zeichnen Sie es, verschieben Sie die Position und wiederholen Sie den Vorgang. Sie können auch den Abstand, das Kerning (tricky), den vertikalen Abstand und sogar die Farbe anpassen. In 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

Und los geht's. Wiederholen Sie diesen Vorgang für jede andere Schriftart (und auch für die optimale Größe).

Bearbeiten : Ich änderte den Code zu verwenden , Graphics.MeasureStringstatt , TextRenderer.MeasureText()weil sie beiden unterschiedlichen Messsysteme verwenden, und kann zu Inkonsistenzen zwischen der gemessenen Glyphe führen und der gezogene ein, insbesondere mit überhängenden Glyphen in einigen Schriftart gefunden. Mehr Infos hier .

Panda-Pyjama
quelle
2
Warum habe ich eine Gegenstimme bekommen? Wenn Sie eine Ablehnung vornehmen möchten, geben Sie bitte zumindest einige Kommentare zu dem, was ich falsch gemacht habe, damit ich es beim nächsten Mal beheben kann.
Panda Pyjama
Nicht ich. Dies ist eine hervorragende Antwort auf alle Fragen. +1 :-)
Kromster sagt Unterstützung Monica
6

Nun, wie jemand anderes in XNA sagte, erledigt Spritefont das schwere Heben für Sie. Auf der Creators Club-Website gibt es einen Exporter für Bitmap-Schriftarten, der Schriftbilder im XNA-Stil exportiert. ( http://xbox.create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker ) Dann können Sie es in Photoshop oder was auch immer öffnen und es hübsch aussehen lassen. Von dort aus fügen Sie die Textur Ihrem Inhaltsprojekt hinzu und wählen im Inhaltstyp die Sprite-Schriftart-Textur aus. In Ihrem Code laden Sie es wie eine normale Sprite-Schriftart

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

CobaltHex
quelle
Das Problem ist, dass ich nicht genau weiß, wie man die Stile einer Photoshop-Schriftart auf eine Textur wie diese anwenden kann.
Vaughan Hilts
Hier mache ich ein Video
CobaltHex
BMFont macht dasselbe, aber meiner Meinung nach ist es ein besseres Programm. angelcode.com/products/bmfont
Cypher
Durch Exportieren eines einfachen Spritefonts können Sie ihn in Photoshop
CobaltHex,
4

Die Lösung ist recht einfach und wird von einer Vielzahl von Spielen verwendet. Sie müssen Ihre Schriften nur so behandeln, als wären sie Sprites.

Lassen Sie Ihren Designer die gesamte Reihe von Zahlen und Buchstaben zeichnen, die Sie in Ihrem Spiel verwenden möchten. Rendern Sie sie dann in statische Bilder unterschiedlicher Größe (.png, .bmp, unabhängig vom verwendeten Format). Sie werden so etwas haben:

Bildbeschreibung hier eingeben

Jetzt müssen Sie nur noch jeden Buchstaben von Ihrem "Zeichensatzblatt" rendern, als wäre es ein Sprite auf dem Bildschirm. Es ist sicherlich hilfreich, eine Hilfsklasse für die Übersetzung zwischen Zeichenfolgen und Sprites zu erstellen.

Meine Implementierung ist komplexer, aber praktisch. Das Font Sheet ist wie das obige Bild aufgebaut und enthält mehrere Fonts in einer .png-Datei. Ich habe eine .iniDatei, die die Buchstaben der einzelnen Schriften zusammen mit ihrer Breite und Höhe einer Position auf dem Blatt zuordnet. Dies lässt meinen Designer (und mich) verrückt nach coolen Schriftarten werden, ohne dass er irgendeinen Code anfassen muss. Wenn eine Zeichenfolge auf den Bildschirm zeichnen, habe ich eine Methode , die Blicke auf die Schrift und den charaus der INI - Datei , die Position und die Grenzen des Schreibens des Schriftenblatt zu erhalten, dann das ziehe ich nur Texture2Dmit SpriteBatch.Draw()der Quelle unter Verwendung Rectangledes Buchstabens fraglich.

Chiffre
quelle
2

Die Benutzeroberfläche ist ein umfangreiches und komplexes Thema. Das Rendern von Schriftarten ist ein schwieriger Teil. Ich rate Ihnen, eine bereits vorhandene Bibliothek zu verwenden, mit der Sie Flash- oder HTML-Inhalte im Spiel anzeigen können, anstatt alles selbst zu wiederholen.

Awesomium sieht vielversprechend aus und sollte mit XNA zusammenarbeiten , damit Sie es ausprobieren können. Es ist kostenlos für nichtkommerzielle Spiele oder wenn Sie nicht viel Geld verdienen:

Kostenlos für Indie-Unternehmen
    Wenn Ihr Unternehmen im letzten Jahr weniger als 100.000 US-Dollar verdient hat, sind Sie qualifiziert!
Kostenlos für nichtkommerzielle Zwecke.
Kostenlos für Evaluierung und Entwicklung

Laurent Couvidou
quelle
Das ist eine ziemlich raffinierte Idee - ich denke, sie abstrahiert auch einen Teil des UI-Codes, den ich schreiben muss. Ich werde es versuchen. Vielen Dank!
Vaughan Hilts
Da es sich um einen Port der Webkit-Engine handelt, sollten Sie in der Lage sein, die meisten Textstile, die Sie benötigen, mit CSS zu erstellen, einschließlich Konturen, Schlagschatten und Verläufen.
ChrisC
Das ist weit über die Komplexisierung für das einfache Zeichnen von Schriftarten
CobaltHex
1
@CobaltHex Ich habe diese Einstellung so oft gesehen und so viele verwöhnte Benutzeroberflächen, die von einem anfänglichen "yey let's make a UI from scratch" abgeleitet wurden. Es muss einfach sein, wir werden das Rad neu erfinden, während wir dabei sind. " Schnauze voll. Überprüfen Sie als Übung das OP-Modell und stellen Sie sich vor, Sie müssen eine gesamte Benutzeroberfläche auf mehreren Plattformen, Bildschirmauflösungen und Verhältnissen im gleichen Stil rendern. Jetzt wird die Notwendigkeit einer korrekten Benutzeroberfläche klar. Deshalb habe ich mir erlaubt, diese Antwort zu posten, auch wenn es keine direkte Lösung für das gegebene Problem ist.
Laurent Couvidou
Ich sage nicht, dass Sie eine Benutzeroberfläche von Grund auf neu erstellen, aber wenn Sie nur eine Schriftart zeichnen möchten, ist das Einfügen einer gesamten Rendering-Engine ein bisschen übertrieben
CobaltHex
1

Wenn Sie nach schickeren Effekten als dem normalen .spritefont-Importer suchen, können Sie versuchen, nach einem "Bitmap-Font-Generator" zu suchen.

Persönlich bevorzuge ich dieses: http://www.ironstarmedia.co.uk/2010/01/free-game-dev-utility-fancy-bitmap-font-generator/

Einige andere Ideen:

  • Verwenden Sie einen Bitmap-Font-Generator und bearbeiten Sie die von ihm erzeugte Bitmap anschließend in Photoshop usw.
  • Fügen Sie so viel statischen Text wie möglich in vorgezeichnete Sprites ein. Dann füllen Sie einfach Dinge wie Gamertags und Punktzahlen mit .spritefonts oder Schriftarten aus, die mit einem Bitmap-Font-Generator generiert wurden.
Nick
quelle
Ich habe das definitiv gesehen (und es ist übrigens sehr cool), aber ich hatte gehofft, meine Photoshop-Textstile direkt in brauchbare Bitmap-Schriftarten zu verwandeln.
Vaughan Hilts
0

XNAerledigt die ganze harte Arbeit für Sie. Mit können SpritefontSie auf einfache Weise eine Schriftartdatei auf Ihrem Computer in die Art von Sprite-Sheet konvertieren, nach der Sie fragen, indem Sie eine XML-Datei definieren.

Sobald Sie die XML-Datei zu Ihrem Content-Projekt hinzugefügt haben, laden Sie sie mit den ContentManagerfolgenden Elementen :

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

Hier ist ein Beispiel einer .spritefont-Datei aus meinem Inhaltsprojekt:

<?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>
Jim
quelle
1
Das Problem ist, dass es sich nur um einfache TrueType-Schriftarten handelt. Ich brauche Bitmap-Schriften oder ähnliches, wobei all mein Schlagschatten, Glühen und ähnliches noch angewendet wird.
Vaughan Hilts
Siehe meine Bearbeitung, Schriftart (en) wie diese: i.imgur.com/VaBpQ.png
Vaughan Hilts
0

Ich bin mir nicht sicher, da ich es nie benutzt habe, aber die Leute haben mir vorgeschlagen, Glyph Designer zu verwenden. Hier ist ein Video-Tutorial:

http://vimeo.com/32777161

Hier wird diskutiert , Photoshop zu erwähnen.

Es gibt Leute, die auch den Hiero-Schrifteditor verwenden .

Auf dieser Website finden Sie eine Liste anderer Schrifteditoren, die Sie sich ansehen möchten.

Lass mich wissen, welches für dich am besten funktioniert :)

mm24
quelle