2014-07-15 6 views
0

나는 C#에서 Visual Studio 2013 Express로 처음부터 게임을 만들었습니다. 이 코드를 실행 때 메모리 부족 오류로 실행까지그리기 사용자 정의 글꼴 스프라이트

모든 것이 순조롭게 진행되었다 :이가 할 의미가 무엇

ExtraGraphics.DrawFont(canvas, new Bitmap(Image.FromFile("Assets\\font.gif")), sliceWidth, sliceHeight, text); 

은 다음과 같습니다

public static class ExtraGraphics 
{ 

    static string[] chars = { " ", "!", "\"", "#", "$", "%", "&", "\'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "¬", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~" }; 
    static List<string> charList = chars.ToList<string>(); 

    public static void DrawFont(this Graphics g, Bitmap image, int width, int height, string str) 
    { 
     for (int i = 0; i < str.Length; i++) 
     { 
      g.DrawImage(image.Clone(new Rectangle(new Point(charList.IndexOf(str.Substring(i)) * width, 0), new Size(width, height)), System.Drawing.Imaging.PixelFormat.DontCare), new Point(i * width, 0)); //Line that errors. 
     } 
    } 
} 

이것은 내가 그것을 호출하는 방법입니다 이미지 (사용자 정의 글꼴)에서 한 줄의 문자를 가져온 다음 분할하여 입력 문자열에 따라 다른 문자를 표시하지만 str 매개 변수에 둘 이상의 문자가있는 경우 해당 오류가 발생합니다.

이것은 here을 사용하는 스프라이트입니다.

+1

당신은'유효한 코드가 아닙니다 ... g. (image.Clone (새 사각형'로 복사 붙여 넣기 오류가 발생했습니다야만 하느니라. 어떤 기능을 사용하면 g'? –

+0

왜 당신은을 사용하고있는'에 요구하고있다 'char's 대신'string'의 묶음이 있습니까? – itsme86

+0

또한이 줄은 문제가 아니지만 낙타를 망가뜨린 짚으로만 쓸 수 있습니다. 객체를 적절하게 처리하지 않으면 부족할 때 OutOfMemoryException이 발생합니다 GDI 핸들 또는 너무 정리되지 않은 관리되지 않는 메모리가 있습니다. –

답변

0

다음은 글꼴 이미지에서 문자 모양을 그리는 코드 조각입니다.

먼저 모든 글리프 비트 맵을 나중에 다시 사용할 수 있도록 유지할 사전을 준비합니다. 키는 각 글리프의 문자입니다.

더 이상 필요하지 않거나 다른 글꼴 이미지 파일을로드하려는 경우 사전을 올바르게 처리하는 방법이 있습니다.

private void Form1_Load(object sender, EventArgs e) 
{ 
    prepareFont(fontImageFileName); 
} 


Dictionary<char, Bitmap> theFont = new Dictionary<char, Bitmap>(); 

string fontImageFileName = @"D:\yourfontimage.png"; 
string fontCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 

int fontCharsPerLine = 7; 
int fontCharsLines = 5; 
int fontCharPixelWidth = 63; 
int fontCharPixelHeight = 87; 



void prepareFont(string fontImageFile) 
{ 
    Rectangle destRect = new Rectangle(0, 0, fontCharPixelWidth, fontCharPixelHeight); 

    using (Bitmap bmp = new Bitmap(fontImageFileName)) 
     for (int y = 0; y < fontCharsLines; y++) 
     for (int x = 0; x < fontCharsPerLine; x++) 
     { 
      if (x + y * fontCharsPerLine < fontCharacters.Length) 
      { 
       char c = fontCharacters[x + y * fontCharsPerLine]; 
       Bitmap glyph = new Bitmap(fontCharPixelWidth, fontCharPixelHeight); 
       using (Graphics G = Graphics.FromImage(glyph)) 
       { 
        G.DrawImage(bmp, destRect, fontCharPixelWidth * x, fontCharPixelHeight * y, 
         fontCharPixelWidth, fontCharPixelHeight, GraphicsUnit.Pixel); 

        theFont.Add(c, glyph); 
       } 
      } 
     } 
} 


void disposeFont() 
{ 
    foreach (char c in theFont.Keys) theFont[c].Dispose(); 
    theFont.Clear(); 
} 

void drawFontString(Graphics G, string text, Point location) 
{ 
    int offset = 0; 
    foreach (char c in text) 
    { 
     if (theFont.Keys.Contains(c)) 
     { 
      G.DrawImage(theFont[c], new Point(location.X + offset, location.Y)); 
      offset += fontCharPixelWidth; 
     } 
    } 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    using (Graphics G = panel1.CreateGraphics()) 
    { drawFontString(G, textBox1.Text, Point.Empty); } 
} 
+0

고마워요.하지만 이미 함수가 하나의 문자 만 그려서 작동하도록 만드는 방법을 찾았습니다. 그런 다음 문자열에있는 문자만큼 많은 시간을 다른 함수가 실행하도록하십시오. 당신의 방법보다 더 효율적인지 모르겠지만 여기에 대한 링크가 있습니다 : http://pastebin.com/aYEw2ge7 – Jack

+0

글쎄, 난 당신의 코드를 시도 할 시간이 없지만 __looks__처럼 당신은 여전히 ​​비트 맵 newImage = image.Clone (..'IMO 당신은'g.DrawImage (newImage..') 뒤에'newImage.Dispose();'를 추가해야합니다. – TaW

+0

좋아, 꽤 개선 된 성능을 가지고있는 것 같습니다! – Jack

2

여기서 문제는 DrawFont 메서드가 호출 될 때마다 번 메모리를 사용한다는 것입니다. 이것은 항상 새로운 메모리를 더 많이 사용하고있는 새로운 Bitmap 객체를 생성하기 때문입니다. 이 문제를 해결하는 가장 쉬운 방법은 그리기 글꼴 루틴을 변경하여 using 문에 새 Bitmap 개체를 만드는 것입니다.

using (var temp = new Bitmap(Image.FromFile("Assets\\font.gif"))) { 
    ExtraGraphics.DrawFont(canvas, temp, sliceWidth, sliceHeight, text); 
} 

메모리 누수를 완전히 수정하려면 복제본을 사용하여 동일한 전략을 수행해야 할 수도 있습니다. 행운을 빌어 요!

메모/편집 : 메모에 언급 된 중요한 항목 중 하나는 가능한 경우 이미지를 한 번로드하려고 시도하는 것입니다. 즉, 양식이로드 될 때 또는 초기화 중에 발생할 수 있습니다. 이것은 두 가지 긍정적 인 효과가 있습니다. 첫 번째는 메모리 누수에 대해 걱정할 필요가 없으며 두 번째는 렌더링 루프의 속도를 크게 높일 수 있다는 것입니다 (디스크에서 이미지를로드하는 속도가 느림).

마지막으로 생각해 볼 점은 그려야 할 픽셀을 복제하려고 시도하는 대신 찾고있는 이미지의 일부분을 그릴 때 Matrix을 사용하는 것입니다. 또한 이로부터 큰 성능 이점을 볼 수 있습니다.

+1

이 솔루션에 완전히 동의하지만이를 해결하는 "더 나은"방법은 비트 맵을 한 번로드 한 다음 어딘가에 메모리에 유지하고 동일한 코드를 계속 참조하는 것입니다. 당신의 코드에서 반복되는 비트 맵. 모든 스크린을 다시 그리기 할 때 영구 저장 장치로부터 읽는 것이 끊임없이 필요합니다. 먹고 게임을 천천히. –

+0

@ScottChamberlain 전적으로 동의합니다.솔루션으로 반드시 제공해야 할 코드가 너무 적습니다. 결코 적게, 나는 이것을 지적하기 위해 답을 수정할 것이다. –

+0

감사합니다. 나는 우리가 말한대로 당신의 제안을 시도하고 있습니다. – Jack