코드에 대한 UI 모형 더 우아한

내 UI 디자이너는 UI의 멋진 포토샵 PSD를 만들었습니다. 내가 겪고있는 가장 큰 문제는 더 우아한 글꼴을 게임 내에서 렌더링 가능한 것으로 변환하는 것입니다. Photoshop에서 이러한 글꼴 스타일을 일종의 비트 맵 글꼴로 변환하는 방법이 있습니까?

내 코드 내에서 다음과 같은 텍스트를 렌더링 할 수 있어야합니다.



답변

자, 특정 플랫폼에 대해 잘 모르기 때문에 특정 XNA 코드를 제공하지 않은 것에 대해 저를 용서해야 할 것입니다. 그러나 스프라이트를 그릴 수있는 모든 게임 엔진에서 작업해야한다는 것을 말씀 드리겠습니다.

글꼴이 유일한 문제는 아니기 때문에 몇 가지 조언을 드리겠습니다. 그러면 귀하의 질문에 대답하겠습니다. 이 두 가지를 사용하면 GUI 디자이너와 사랑스런 관계를 맺을 수 있으며 두 사람 모두 행복하게 게임을 만들 수 있습니다.

첫 번째는 디자이너와 함께 앉아 두 세트의 파일을 제공하라는 것입니다. 첫 번째는 GUI를 구성하는 투명한 파일 세트입니다 (최적의 PSD 또는 DXT 형식). 모든 버튼, 고정 레이블, 배경, 테두리 및 텍스트 상자에 대해 하나의 파일을 얻습니다 (텍스처 아틀라스를 수행 할 수도 있지만 GUI를 어셈블 한 다음 블리 팅 할 때 소스 좌표를 조정 한 후에 수행하는 것이 좋습니다). 정적이 아닌 텍스트는이 시점에서 제외해야합니다 (나중에 다시 방문하겠습니다).

두 번째로 얻을 수있는 것은 실제 GUI 디자인입니다. 이번에는 Photoshop 형식입니다. 이 파일의 경우 이전에 제공 한 파일 사용하여 디자이너에게 전체 GUI 디자인을 작성하도록 요청합니다 .

그런 다음 효과를 전혀 사용하지 않고 각 GUI 요소를 별도의 계층에 넣습니다. 그녀가 모든 것을 넣을 위치는 모든 것이 최종 게임에서 실제로있을 것이므로이 픽셀을 완벽하게 수행하도록 지시 할 것입니다.

이를 얻은 후에는 각 레이어에 대해 Ctrl-T를 누르고 정보 창 (F8)에서 각 요소의 X 및 Y 좌표를 기록합니다. 단위가 픽셀로 설정되어 있는지 확인하십시오 (기본 설정-> 단위 및 눈금자-> 단위). 스프라이트를 그릴 때 사용할 위치입니다.

이제 글꼴에 대해 분명히 알 수 있듯이 텍스트 렌더링 API를 사용하여 글꼴을 Photoshop에서 보는 것과 똑같은 모양으로 만들 수 없습니다. 글리프를 미리 렌더링 한 다음 프로그래밍 방식으로 텍스트를 조립해야합니다. 이를 수행하는 방법에는 여러 가지가 있으며, 내가 사용하는 방법을 언급 할 것입니다.

먼저 모든 글리프를 하나 이상의 파일로 렌더링합니다. 영어 만 신경 쓰면 모든 글리프에 대한 하나의 텍스처로 충분하지만 더 확장 된 문자 집합을 원하면 여러 파일을 사용할 수 있습니다. 원하는 모든 글리프가 디자이너가 선택한 글꼴로 제공되는지 확인하십시오.

따라서 글리프를 렌더링하려면 다음 기능을 사용 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 파일에서 투명한 배경 위에 흰색 글리프를 그리고 각 코드 포인트, 글리프가있는 파일, 위치 및 크기를 알려주는 인덱스 파일을 만들었습니다. 각 글리프를 분리하기 위해 두 개의 추가 픽셀을 추가했습니다 (추가 효과를 위해)

이제 각 파일에 대해 Photoshop에 파일을 넣고 원하는 모든 필터를 수행하십시오. 색상, 테두리, 그림자, 윤곽선 및 기타 원하는 것을 설정할 수 있습니다. 효과로 글리프가 겹치지 않도록하십시오. 그렇다면 간격을 조정하고 다시 렌더링하고 헹구고 반복하십시오. 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(), 측정 된 글리프와 그려진 글리프, 특히 일부 글꼴에서 돌출 된 글리프가 일치하지 않을 수 있습니다. 자세한 내용은 여기를 참조 하십시오 .


답변

다른 누군가가 말했듯이, XNA에서 spritefont는 당신을 위해 많은 노력을 기울입니다. 제작자 클럽 웹 사이트에는 XNA 스타일 글꼴 이미지로 내보내는 비트 맵 글꼴 내보내기가 있습니다. ( http://xbox.create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker ) 그런 다음 포토샵이나 다른 곳에서 열어서 예쁘게 보이게 할 수 있습니다. 여기에서 텍스처를 컨텐츠 프로젝트에 추가하고 컨텐츠 유형에서 스프라이트 글꼴 텍스처를 선택하십시오. 코드에서는 일반 스프라이트 글꼴처럼로드합니다

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


답변

이 솔루션은 매우 간단하며 많은 게임에서 사용됩니다. 글꼴이 스프라이트 인 것처럼 처리하기 만하면됩니다.

디자이너가 게임에 사용하려는 숫자와 문자의 전체 범위를 그리도록하십시오. 그런 다음 다양한 크기의 정적 이미지 (.png, .bmp, 사용하는 형식)로 렌더링하십시오. 다음과 같은 것이 있습니다.

이제 “글꼴 시트”의 각 문자를 마치 화면의 스프라이트처럼 렌더링하면됩니다. 문자열과 스프라이트 사이를 변환하는 도우미 클래스를 작성하는 데 확실히 도움이됩니다.

내 구현은 더 복잡하지만 편리합니다. 글꼴 시트는 하나의 .png 파일에 여러 글꼴이있는 위 이미지와 같이 작성됩니다. .ini각 글꼴의 문자를 시트의 위치와 너비 및 높이와 매핑 하는 파일이 있습니다. 이를 통해 디자이너 (나 자신)는 코드를 건드리지 않고도 멋진 글꼴을 만들 수 있습니다. 화면에 문자열을 그릴 때 글꼴과 char.ini 파일에서 글꼴 시트에서 글자의 위치와 경계를 가져 오는 방법을 찾은 다음 글자 의 소스 를 사용하여 Texture2D와 함께 그립니다. 문제의.SpriteBatch.Draw()Rectangle


답변

UI는 방대하고 복잡한 주제입니다. 폰트 렌더링은 어려운 부분입니다. 모든 것을 직접 다시 실행하는 대신 게임 내에서 Flash 또는 HTML 내용을 표시 할 수있는 기존 라이브러리를 사용하는 것이 좋습니다.

Awesomium 은 유망 보이며 XNA와 함께 작동해야 하므로 시도해 볼 수 있습니다. 비상업적 게임이나 돈을 많이 벌지 않는 경우 무료로 사용할 수 있습니다.

인디 회사를 위해 무료
    당신의 회사가 작년에 $ 100K 미만을 만들었다면, 당신은 자격이 있습니다!
비상업적 용도
무료 평가 및 개발 무료


답변

일반 .spritefont 임포터보다 더 멋진 효과를 찾고 있다면 “비트 맵 글꼴 생성기”를 검색해보십시오.

개인적으로 나는 이것을 선호합니다 :
http://www.ironstarmedia.co.uk/2010/01/free-game-dev-utility-fancy-bitmap-font-generator/

다른 아이디어들 :

  • 비트 맵 글꼴 생성기를 사용한 다음 Photoshop 등에서 추가로 생성 된 비트 맵을 편집하십시오.
  • 미리 그려진 스프라이트에 가능한 많은 정적 텍스트를 넣습니다. 그런 다음 게이머 태그와 같은 항목을 채우고 비트 맵 글꼴 생성기에서 생성 된 .spritefonts 또는 글꼴을 사용하여 총점을 계산하십시오.

답변

XNA당신을 위해 모든 노력을 다합니다. 로 Spritefont쉽게 XML 파일을 정의하여 대한 요구하고있다 스프라이트 시트의 종류로 컴퓨터에 글꼴 파일을 변환 할 수 있습니다.

XML 파일을 Content 프로젝트에 추가하면 다음과 같이로드하십시오 ContentManager.

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

내 콘텐츠 프로젝트의 .spritefont 파일의 예는 다음과 같습니다.

<?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>

답변

나는 그것을 결코 사용하지 않았지만 사람들은 나에게 Glyph Designer를 사용하도록 제안했다. 비디오 자습서는 다음과 같습니다.

http://vimeo.com/32777161

여기에 포토샵을 언급 하는 것에 대한 토론 이 있습니다.

Hiero 글꼴 편집기를 사용하는 사람들도 있습니다 .

에서 웹 사이트에 당신이 좀보고 할 수 있습니다 다른 글꼴 편집기의 목록이 있습니다.

어느 것이 당신에게 가장 적합한 지 알려주세요. 🙂