Giao diện người dùng mô phỏng mã


17

Nhà thiết kế UI của tôi đã tạo ra một PSD photoshop đáng yêu của UI và mọi thứ đều đẹp. Vấn đề lớn nhất mà tôi gặp phải là chuyển đổi một số phông chữ thanh lịch hơn được sử dụng thành thứ gì đó có thể kết xuất trong trò chơi. Có cách nào để chuyển đổi các kiểu phông chữ này trong Photoshop sang một phông chữ bitmap nào đó không?

Tôi cần có thể hiển thị văn bản như thế này trong mã của mình:

nhập mô tả hình ảnh ở đây


Bạn đã kiểm tra các trang web như thế này? blog.msdn.com/b/ÿkac/archive/2006/08/30/732007.aspx
ssb

Cảm ơn bạn rất nhiều vì tiền thưởng, nhưng tôi nhận thấy bạn đã không đánh dấu nó là câu trả lời được chấp nhận. Bạn không hài lòng với câu trả lời? Bạn có mong đợi một loại câu trả lời khác nhau không? Tôi lắp ráp GUI trò chơi như một phần công việc hàng ngày của mình, vì vậy tôi nghĩ rằng tôi có thể trả lời câu hỏi của bạn. Hãy yêu cầu làm rõ hoặc giải thích kỹ lưỡng hơn nếu bạn cần.
Panda Pyjama

Chỉ là một giám sát về phía tôi. :) Tôi đã sửa nó ngay bây giờ. Thưởng thức và cảm ơn bạn!
Vaughan Hilts

Câu trả lời:


18

Được rồi, bạn sẽ phải tha thứ cho tôi vì đã không cung cấp cho bạn mã XNA cụ thể, bởi vì tôi không am hiểu về nền tảng đó, nhưng những gì tôi sẽ nói với bạn là nên làm việc trên bất kỳ công cụ trò chơi nào cho phép bạn vẽ các họa tiết.

Phông chữ không phải là vấn đề duy nhất của bạn, vì vậy tôi sẽ cho bạn một lời khuyên, và sau đó tôi sẽ trả lời câu hỏi của bạn. Với hai điều này, bạn sẽ có thể tạo mối quan hệ yêu đương với nhà thiết kế GUI của mình và cả hai bạn sẽ có thể rất vui vẻ làm trò chơi.

Điều đầu tiên là bạn sẽ ngồi lại với nhà thiết kế của mình và bạn sẽ yêu cầu cô ấy đưa cho bạn hai bộ hồ sơ. Đầu tiên là một tập hợp các tệp trong suốt tạo nên GUI của bạn (tối ưu ở định dạng PSD hoặc DXT). Đối với mỗi nút, nhãn cố định, nền, đường viền và hộp văn bản, bạn sẽ nhận được một tệp (bạn cũng có thể thực hiện kết cấu, nhưng tôi khuyên bạn nên làm điều đó sau khi lắp ráp GUI và sau đó điều chỉnh tọa độ nguồn khi tắt). Văn bản không tĩnh nên được bỏ qua tại thời điểm này (Tôi sẽ xem lại điều này sau).

Điều thứ hai bạn sẽ nhận được là thiết kế GUI thực tế, lần này là ở định dạng Photoshop. Đối với tệp này, bạn sẽ yêu cầu nhà thiết kế của bạn thực hiện toàn bộ thiết kế GUI, chỉ sử dụng các tệp mà trước đây cô ấy đã cung cấp cho bạn.

Sau đó, cô ấy sẽ đặt từng thành phần GUI vào một lớp riêng biệt, không sử dụng bất kỳ hiệu ứng nào. Bạn sẽ bảo cô ấy làm pixel này thật hoàn hảo, bởi vì những vị trí mà cô ấy sẽ đặt mọi thứ, là nơi mọi thứ sẽ thực sự có trong trò chơi hoàn thiện.

Khi bạn nhận được điều đó, với mỗi lớp, bạn sẽ nhấn Ctrl-T và trên ngăn Thông tin (F8), bạn sẽ lưu ý đến tọa độ X và Y cho từng thành phần. Đảm bảo các đơn vị của bạn được đặt thành pixel (Tùy chọn-> Đơn vị & Thước đo-> Đơn vị). Đây là những vị trí bạn sẽ sử dụng khi vẽ các họa tiết của mình.

Bây giờ, đối với các phông chữ, như bạn có thể biết rõ bây giờ, bạn sẽ không thể có được các phông chữ của mình trông giống hệt như cách bạn nhìn thấy chúng trong Photoshop bằng API kết xuất văn bản. Bạn sẽ phải kết xuất trước glyphs của mình và sau đó lập trình các văn bản của bạn theo chương trình. Có nhiều cách để làm điều này, và tôi sẽ đề cập đến cách tôi sử dụng.

Điều đầu tiên là kết xuất tất cả các glyph của bạn thành một hoặc nhiều tệp. Nếu bạn chỉ quan tâm đến tiếng Anh, một kết cấu cho tất cả các glyph sẽ đủ, nhưng nếu bạn muốn có một bộ ký tự mở rộng hơn, bạn có thể sử dụng một số tệp. Chỉ cần đảm bảo rằng tất cả các glyphs bạn muốn có sẵn trên phông chữ mà nhà thiết kế của bạn đã chọn.

Vì vậy, để hiển thị glyphs, bạn có thể sử dụng các phương tiện System.Drawingđể lấy số liệu phông chữ và vẽ glyphs của mình:

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

Với điều này, bạn đã vẽ các glyph trắng trên nền trong suốt trên một loạt các tệp PNG và tạo một tệp chỉ mục cho bạn biết từng loại tiền mã hóa, trong đó tệp glyph được đặt, vị trí và kích thước của nó. Lưu ý rằng tôi cũng đặt hai pixel bổ sung để tách từng glyph (để đệm cho các hiệu ứng tiếp theo)

Bây giờ, đối với mỗi tệp đó, bạn đặt nó vào photoshop và thực hiện tất cả các bộ lọc bạn muốn. Bạn có thể đặt màu sắc, đường viền, bóng, đường viền và bất cứ thứ gì bạn muốn. Chỉ cần đảm bảo rằng các hiệu ứng không làm cho glyphs trùng nhau. Nếu vậy, điều chỉnh khoảng cách, kết xuất lại, rửa và lặp lại. Lưu dưới dạng PNG hoặc DXT và cùng với tệp chỉ mục, đặt mọi thứ vào dự án của bạn.

Vẽ văn bản nên rất đơn giản. Đối với mỗi char bạn muốn in, tìm vị trí của nó bằng chỉ mục, vẽ nó, tiến vị trí và lặp lại. Bạn cũng có thể điều chỉnh khoảng cách, k sâu (khéo léo), khoảng cách dọc và thậm chí tô màu. Trong 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

Và ở đó bạn đi. Lặp lại cho mọi phông chữ khác (và kích thước tối ưu là tốt)

Chỉnh sửa : Tôi đã thay đổi mã để sử dụng Graphics.MeasureStringthay TextRenderer.MeasureText()vì cả hai đều sử dụng các hệ thống đo lường khác nhau và có thể dẫn đến sự không thống nhất giữa glyph đo được và mã được vẽ, đặc biệt là với glyphs nhô ra trong một số phông chữ. Thêm thông tin ở đây .


2
Tại sao tôi nhận được một downvote về điều này? Nếu bạn đang downvote, ít nhất xin vui lòng cho một số ý kiến ​​về những gì tôi đã làm sai để tôi có thể sửa chữa nó lần sau.
Panda Pajama

Không phải tôi. Đây là một câu trả lời sâu sắc tuyệt vời. +1 :-)
Kromster nói hỗ trợ Monica

6

Vâng, như người khác đã nói, trong XNA, spritefont thực hiện công việc nặng nhọc cho bạn. trên trang web câu lạc bộ người sáng tạo có một nhà xuất khẩu phông chữ bitmap xuất khẩu trong các hình ảnh phông chữ kiểu XNA. ( http://xbox.create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker ) Sau đó, bạn có thể mở nó bằng photoshop hoặc bất cứ thứ gì và làm cho nó trông đẹp. Từ đó, bạn thêm kết cấu vào dự án nội dung của bạn và trong loại nội dung, chọn kết cấu phông chữ sprite. Trong mã của bạn, bạn tải nó như một phông chữ sprite bình thường

(Ví dụ: http://www.youtube.com/watch?v=SynGWrWYUQI )


Vấn đề là tôi không chắc chắn chính xác làm thế nào người ta có thể lấy các kiểu từ phông chữ Photoshop và áp dụng chúng vào một kết cấu như thế này.
Vaughan Hilts

Ở đây, tôi sẽ làm một video
CobaltHex


BMFont làm điều tương tự, nhưng theo tôi là một chương trình tốt hơn. angelcode.com/products/bmfont
Cypher

eh, bằng cách xuất một spritefont cơ bản, bạn có thể tùy chỉnh nó theo cách bạn muốn trong photoshop
CobaltHex

4

Giải pháp khá đơn giản và được sử dụng bởi rất nhiều trò chơi. Tất cả bạn phải làm là đối xử với phông chữ của bạn như thể chúng là các họa tiết.

Yêu cầu nhà thiết kế của bạn rút ra toàn bộ phạm vi số và chữ cái mà bạn muốn sử dụng trong trò chơi của mình. Sau đó kết xuất chúng thành các hình ảnh tĩnh có kích thước khác nhau (.png, .bmp, bất kỳ định dạng nào bạn sử dụng). Bạn sẽ có một cái gì đó như thế này:

nhập mô tả hình ảnh ở đây

Bây giờ, tất cả những gì bạn phải làm là hiển thị từng chữ cái từ "bảng phông chữ" của bạn như thể nó là một hình vẽ trên màn hình. Nó chắc chắn giúp xây dựng một lớp trợ giúp để dịch giữa các chuỗi và các họa tiết.

Việc thực hiện của tôi phức tạp hơn, nhưng tiện dụng. Bảng phông chữ được xây dựng giống như hình ảnh trên với nhiều phông chữ trong một tệp .png. Tôi có một .initệp ánh xạ chữ cái của mỗi phông chữ đến một vị trí trên trang tính, cùng với chiều rộng và chiều cao của nó. Điều này cho phép nhà thiết kế của tôi (và bản thân tôi) thực hiện các thao tác tạo phông chữ thú vị mà không cần phải chạm vào bất kỳ mã nào. Khi vẽ một chuỗi lên màn hình, tôi có một phương pháp tra cứu phông chữ và chartừ tệp .ini để lấy vị trí và ranh giới của chữ cái từ bảng phông chữ, sau đó tôi chỉ cần vẽ Texture2Dbằng SpriteBatch.Draw()cách sử dụng nguồn Rectanglecủa chữ cái trong câu hỏi.


2

UI là một chủ đề rộng lớn và phức tạp. Hiển thị phông chữ là một phần khó khăn. Tôi khuyên bạn nên sử dụng thư viện đã có sẵn cho phép bạn hiển thị nội dung Flash hoặc HTML trong trò chơi, thay vì tự mình làm lại mọi thứ.

Awesomium có vẻ đầy hứa hẹn và sẽ hoạt động với XNA , vì vậy bạn có thể dùng thử. Nó miễn phí để sử dụng cho các trò chơi phi thương mại hoặc nếu bạn không kiếm được nhiều tiền:

Miễn phí cho các công ty Indie
    Nếu công ty của bạn kiếm được ít hơn $ 100K vào năm ngoái, bạn đủ điều kiện!
Miễn phí cho sử dụng phi thương mại
Miễn phí cho Đánh giá & Phát triển


Đó là một ý tưởng khá tiện lợi - tôi đoán nó cũng trừu tượng hóa một số mã UI tôi phải viết. Tôi sẽ thử. Cảm ơn!
Vaughan Hilts

Vì đây là một cổng của công cụ Webkit, bạn sẽ có thể thực hiện hầu hết các kiểu văn bản bạn cần với CSS, bao gồm các đường viền nét, thả bóng và độ dốc.
ChrisC

đó là cách phức tạp hóa chỉ đơn giản là vẽ phông chữ
CobaltHex

1
@CobaltHex Tôi đã thấy thái độ này rất nhiều lần và rất nhiều giao diện người dùng hư hỏng xuất phát từ một "ban đầu, hãy tạo ra một giao diện người dùng từ đầu, nó sẽ dễ dàng phát ốm vì nó Như một bài tập, hãy kiểm tra hình ảnh mô phỏng OP và tưởng tượng bạn phải kết xuất toàn bộ giao diện người dùng theo cùng một kiểu trên một số nền tảng, độ phân giải màn hình và tỷ lệ. Bây giờ nhu cầu về một giao diện người dùng phù hợp trở nên rõ ràng, đó là lý do tại sao tôi đã tự do đăng câu trả lời này, ngay cả khi đó không phải là giải pháp trực tiếp cho vấn đề đã cho.
Laurent Couvidou

Tôi không nói rằng bạn tạo UI từ đầu, nhưng nếu bạn chỉ muốn vẽ một phông chữ, việc chèn toàn bộ công cụ kết xuất là hơi quá mức
CobaltHex

1

Nếu bạn đang tìm kiếm các hiệu ứng fancier hơn trình nhập .spritefont đơn giản, bạn có thể thử tìm kiếm "trình tạo phông chữ bitmap".

Cá nhân tôi thích cái này: http://www.ironstarmedia.co.uk/2010/01/free-game-dev-utility-fancy-bitmap-font-generator/

Một số ý tưởng khác:

  • Sử dụng trình tạo phông chữ bitmap và sau đó chỉnh sửa bitmap mà nó tạo ra thêm trong photoshop, v.v.
  • Đặt càng nhiều văn bản tĩnh càng tốt vào các họa tiết được vẽ sẵn. Sau đó điền vào những thứ như gamertags và tổng số điểm bằng cách sử dụng .spritefonts hoặc phông chữ được tạo từ trình tạo phông chữ bitmap.

Tôi chắc chắn đã thấy điều đó (và nó rất tuyệt, nhân tiện) nhưng tôi đã hy vọng trực tiếp biến các kiểu văn bản Photoshop của mình thành các phông chữ bitmap có thể sử dụng được.
Vaughan Hilts

0

XNAlàm tất cả các công việc khó khăn cho bạn. Với Spritefontbạn có thể dễ dàng chuyển đổi một tệp phông chữ trên máy của mình thành loại bảng sprite mà bạn đang hỏi bằng cách xác định tệp XML.

Khi bạn thêm tệp XML vào dự án Nội dung, hãy tải nó bằng ContentManager:

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

Đây là một ví dụ về tệp .spritefont từ dự án nội dung của tô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
Vấn đề là đây chỉ là các phông chữ TrueType đơn giản. Tôi cần phông chữ bitmap hoặc một cái gì đó tương tự với tất cả các hình mờ, phát sáng và tương tự vẫn được áp dụng.
Vaughan Hilts

Xem chỉnh sửa của tôi, phông chữ như thế này: i.imgur.com/VaBpQ.png
Vaughan Hilts

0

Tôi không chắc vì tôi chưa bao giờ sử dụng nó nhưng mọi người đề nghị tôi sử dụng Glyph Designer. Đây là một video hướng dẫn:

http://vimeo.com/32777161

Ở đây có một cuộc thảo luận về nó đề cập đến photoshop.

Có những người sử dụng trình soạn thảo phông chữ Hiero .

Trong trang web này có một danh sách các trình soạn thảo phông chữ khác mà bạn có thể muốn xem qua.

Hãy cho tôi biết cái nào phù hợp nhất với bạn :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.