Maquettes d'interface utilisateur au code


17

Mon concepteur d'interface utilisateur a fait un joli PSD Photoshop de l'interface utilisateur et tout joli. Le plus gros problème que j'ai est de convertir certaines des polices les plus élégantes utilisées en quelque chose de rendable dans le jeu. Existe-t-il un moyen de convertir ces styles de police dans Photoshop en une police bitmap quelconque?

J'ai besoin de pouvoir rendre du texte comme celui-ci dans mon code:

entrez la description de l'image ici


Avez-vous vérifié des sites comme celui-ci? blogs.msdn.com/b/garykac/archive/2006/08/30/732007.aspx
ssb

Merci beaucoup pour la prime, mais j'ai remarqué que vous ne l'aviez pas marqué comme réponse acceptée. Êtes-vous insatisfait de la réponse? Vous attendiez-vous à un autre type de réponse? J'assemble des interfaces graphiques de jeu dans le cadre de mon travail de jour, je pense donc que je pourrai répondre à vos questions. N'hésitez pas à demander des clarifications ou des explications plus approfondies si vous en avez besoin.
Panda Pyjama

Juste un oubli de ma part. :) J'ai corrigé cela maintenant. Profitez-en et merci!
Vaughan Hilts

Réponses:


18

D'accord, vous devrez me pardonner de ne pas vous avoir donné de code XNA spécifique, car je ne connais pas cette plate-forme, mais ce que je vais vous dire devrait fonctionner sur n'importe quel moteur de jeu qui vous permet de dessiner des sprites.

Les polices ne sont pas votre seul problème, je vais donc vous donner un conseil, puis je vais répondre à votre question. Avec ces deux choses, vous devriez être en mesure de faire une relation amoureuse-colombe avec votre concepteur d'interface graphique, et vous pourrez tous deux créer des jeux très heureux.

La première chose est que vous allez vous asseoir avec votre designer, et vous allez lui demander de vous donner deux ensembles de fichiers. Le premier est un ensemble de fichiers transparents qui composent votre interface graphique (de manière optimale au format PSD ou DXT). Pour chaque bouton, étiquette fixe, arrière-plan, bordure et zone de texte, vous obtiendrez un fichier (vous pouvez également faire un atlas de texture, mais je vous recommande de le faire après avoir assemblé votre interface graphique, puis d'ajuster vos coordonnées source lors du blitting). Le texte non statique doit être omis à ce stade (je reviendrai sur ce point plus tard).

La deuxième chose que vous obtiendrez est la conception graphique réelle, cette fois au format Photoshop. Pour ce fichier, vous allez demander à votre concepteur de réaliser l'intégralité de la conception de l'interface graphique, en utilisant uniquement les fichiers qu'elle vous a précédemment fournis.

Elle va ensuite mettre chaque élément GUI dans une couche distincte, sans aucun effet. Vous allez lui dire de faire ce pixel parfait, car les endroits où elle va tout mettre, c'est où tout sera réellement dans le jeu finalisé.

Une fois que vous obtenez cela, pour chaque couche, vous allez appuyer sur Ctrl-T, et dans le volet Info (F8), vous prendrez note des coordonnées X et Y pour chaque élément. Assurez-vous que vos unités sont définies en pixels (Préférences-> Unités et règles-> Unités). Ce sont les positions que vous allez utiliser pour dessiner vos sprites.

Maintenant, pour les polices, comme vous le savez clairement maintenant, vous ne pourrez pas obtenir que vos polices aient exactement le même aspect que vous les voyez dans Photoshop à l'aide des API de rendu de texte. Vous devrez pré-rendre vos glyphes, puis assembler par programme vos textes. Il existe de nombreuses façons de procéder, et je mentionnerai celle que j'utilise.

La première chose à faire est de rendre tous vos glyphes dans un ou plusieurs fichiers. Si vous ne vous souciez que de l'anglais, une seule texture pour tous les glyphes suffira, mais si vous voulez avoir un jeu de caractères plus étendu, vous pouvez utiliser plusieurs fichiers. Assurez-vous simplement que tous les glyphes que vous voulez sont disponibles sur la police choisie par votre designer.

Ainsi, pour rendre les glyphes, vous pouvez utiliser les fonctionnalités de System.Drawingpour obtenir les mesures de police et dessiner vos glyphes:

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

Avec cela, vous avez dessiné des glyphes blancs sur un fond transparent sur un tas de fichiers PNG et créé un fichier d'index qui vous indique pour chaque point de code, dans quel fichier se trouve le glyphe, son emplacement et ses dimensions. Notez que j'ai également mis deux pixels supplémentaires pour séparer chaque glyphe (pour accueillir d'autres effets)

Maintenant, pour chacun de ces fichiers, vous le mettez dans photoshop et effectuez tous les filtres que vous souhaitez. Vous pouvez définir les couleurs, les bordures, les ombres, les contours et tout ce que vous voulez. Assurez-vous simplement que les effets ne font pas chevaucher les glyphes. Si c'est le cas, ajustez l'espacement, restituez, rincez et répétez. Enregistrez au format PNG ou DXT, et avec le fichier d'index, mettez tout dans votre projet.

Le texte de dessin doit être très simple. Pour chaque caractère que vous souhaitez imprimer, recherchez son emplacement à l'aide de l'index, dessinez-le, avancez la position et répétez. Vous pouvez également ajuster l'espacement, le crénage (délicat), l'espacement vertical et même la coloration. À 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

Et voilà. Répétez l'opération pour toutes les autres polices (et la taille optimale également)

Edit : j'ai changé le code à utiliser Graphics.MeasureStringau lieu de TextRenderer.MeasureText()car ils utilisent tous deux des systèmes de mesure différents, et peut entraîner des incohérences entre le glyphe mesuré et celui dessiné, en particulier avec les glyphes en surplomb trouvés dans certaines polices. Plus d'informations ici .


2
Pourquoi ai-je obtenu un downvote à ce sujet? Si vous allez voter contre, veuillez au moins faire quelques commentaires sur ce que j'ai fait de mal afin que je puisse y remédier la prochaine fois.
Panda Pyjama

Pas moi. Il s'agit d'une excellente réponse approfondie. +1 :-)
Kromster dit soutenir Monica le

6

Eh bien, comme quelqu'un l'a dit, dans XNA, spritefont fait le gros du travail pour vous. sur le site Web du club des créateurs, il existe un exportateur de polices bitmap qui exporte en images de polices de style XNA. ( http://xbox.create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker ) Ensuite, vous pouvez l'ouvrir dans photoshop ou autre et le rendre joli. À partir de là, vous ajoutez la texture à votre projet de contenu et, dans le type de contenu, sélectionnez la texture de la police d'image-objet. Dans votre code, vous le chargez comme une police sprite normale

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


Le problème est que je ne sais pas exactement comment on peut prendre les styles d'une police Photoshop et les appliquer à une texture comme celle-ci.
Vaughan Hilts

Ici, je vais faire une vidéo
CobaltHex


BMFont fait la même chose, mais à mon avis, c'est un meilleur programme. angelcode.com/products/bmfont
Cypher

eh, en exportant un spritefont de base, vous pouvez le personnaliser comme vous le souhaitez dans Photoshop
CobaltHex

4

La solution est assez simple et est utilisée par un grand nombre de jeux. Tout ce que vous avez à faire est de traiter vos polices comme s'il s'agissait de sprites.

Demandez à votre concepteur de dessiner toute la gamme de chiffres et de lettres que vous souhaitez utiliser dans votre jeu. Rendez-les ensuite dans des images statiques de tailles variables (.png, .bmp, quel que soit le format que vous utilisez). Vous aurez quelque chose comme ça:

entrez la description de l'image ici

Maintenant, tout ce que vous avez à faire est de rendre chaque lettre de votre "feuille de police" comme si c'était un sprite à l'écran. Cela aide certainement à construire une classe d'aide pour traduire entre les chaînes et les sprites.

Ma mise en œuvre est plus complexe, mais pratique. La feuille de polices est construite comme l'image ci-dessus avec plusieurs polices dans un seul fichier .png. J'ai un .inifichier qui mappe la lettre de chaque police à une position sur la feuille, ainsi que sa largeur et sa hauteur. Cela permet à mon concepteur (et moi-même) de devenir fou en créant des polices sympas sans avoir à toucher à aucun code. Lorsque je dessine une chaîne à l'écran, j'ai une méthode qui recherche la police et le charfichier .ini pour obtenir la position et les limites de la lettre à partir de la feuille de police, puis je dessine simplement le Texture2Davec en SpriteBatch.Draw()utilisant la source Rectanglede la lettre Dans la question.


2

L'interface utilisateur est un sujet vaste et complexe. Le rendu des polices est une partie difficile. Je vous conseille d'utiliser une bibliothèque déjà existante qui vous permet d'afficher du contenu Flash ou HTML dans le jeu, au lieu de tout refaire vous-même.

Awesomium semble prometteur et devrait fonctionner avec XNA , vous pouvez donc l'essayer. Il est gratuit pour les jeux non commerciaux, ou si vous ne gagnez pas des tonnes d'argent:

Gratuit pour les entreprises indépendantes
    Si votre entreprise a fait moins de 100 000 $ l'an dernier, vous êtes admissible!
Gratuit pour une utilisation non commerciale
Gratuit pour l'évaluation et le développement


C'est une idée assez astucieuse - je suppose que cela résume également une partie du code d'interface utilisateur que je dois écrire. Je vais essayer. Merci!
Vaughan Hilts

Comme c'est un port du moteur Webkit, vous devriez être capable de faire la plupart des styles de texte dont vous avez besoin avec CSS, y compris les contours de traits, les ombres portées et les dégradés.
ChrisC

c'est bien plus complexe que de simplement dessiner des polices
CobaltHex

1
@CobaltHex J'ai vu cette attitude tant de fois et tant d'interfaces utilisateur gâtées dérivées d'une première "oui, créons une interface utilisateur à partir de zéro, cela doit être facile, nous réinventerons la roue pendant que nous y sommes" que j'ai grandi malade. En tant qu'exercice, vérifiez l'image de la maquette OP et imaginez que vous devez rendre une interface utilisateur entière dans le même style sur plusieurs plates-formes, résolutions d'écran et ratios. Maintenant, la nécessité d'une interface utilisateur appropriée devient claire, c'est pourquoi j'ai pris la liberté de poster cette réponse, même si ce n'est pas une solution directe au problème donné.
Laurent Couvidou

Je ne dis pas que vous créez une interface utilisateur à partir de zéro, mais si vous voulez simplement dessiner une police, insérer un moteur de rendu complet est un peu exagéré
CobaltHex

1

Si vous recherchez des effets plus sophistiqués que l'importateur ordinaire .spritefont, vous pouvez essayer de rechercher un "générateur de polices bitmap".

Personnellement, je préfère celui-ci: http://www.ironstarmedia.co.uk/2010/01/free-game-dev-utility-fancy-bitmap-font-generator/

Quelques autres idées:

  • Utilisez un générateur de polices bitmap, puis modifiez le bitmap qu'il produit plus loin dans Photoshop, etc.
  • Mettez autant de texte statique que possible dans les sprites pré-dessinés. Remplissez ensuite des éléments tels que les gamertags et les totaux de score à l'aide de .spritefonts ou de polices générées à partir d'un générateur de polices bitmap.

J'ai certainement vu cela (et c'est très cool, en passant) mais j'espérais transformer directement mes styles de texte Photoshop en polices bitmap utilisables.
Vaughan Hilts

0

XNAfait tout le travail acharné pour vous. Avec, Spritefontvous pouvez facilement convertir un fichier de police sur votre machine en le type de feuille de sprite que vous demandez en définissant un fichier XML.

Une fois que vous avez ajouté le fichier XML à votre projet de contenu, chargez-le avec ContentManager:

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

Voici un exemple de fichier .spritefont de mon projet de contenu:

<?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
Le problème est que ce sont simplement des polices TrueType. J'ai besoin de polices bitmap ou de quelque chose de similaire avec toutes mes ombres portées, des lueurs et autres encore appliquées.
Vaughan Hilts

Voir mon montage, police (s) comme celles-ci: i.imgur.com/VaBpQ.png
Vaughan Hilts

0

Je ne suis pas sûr car je ne l'ai jamais utilisé mais les gens m'ont suggéré d'utiliser Glyph Designer. Voici un tutoriel vidéo:

http://vimeo.com/32777161

Ici, il y a une discussion à ce sujet mentionnant Photoshop.

Il y a des gens qui utilisent également l' éditeur de polices Hiero .

Sur ce site Web, vous trouverez une liste d'autres éditeurs de polices que vous voudrez peut-être consulter.

Faites-moi savoir lequel vous convient le mieux :)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.