'Programming/C#/Xna/Kinect/WPF'에 14개의 글이 있습니다.

  1. 2013.05.31C# Attempted to read or write protected memory 에러
  2. 2013.05.29RGB 색상표 (16진수) 변환
  3. 2013.05.28XNAExtras로 XBOX360에 폰트를 출력해 보자!! #1
  4. 2013.05.28C# StreamReader 에서의 한글 Encoding 문제
  5. 2013.05.08[XNA] Scrolling background images horizontally across the screen
  6. 2013.05.08[XNA] A Simple 2D Camera
  7. 2013.02.19[C#] String Split (Unity3D)
  8. 2012.12.14[Kinect] 키넥트 1.6 에서 프로그램 종료시 프리즈 되는 현상
  9. 2012.11.20[C#] 컴파일러와 dll파일
  10. 2012.11.15[C#] ListView에서 Tag의 활용

C# Attempted to read or write protected memory 에러

posted-at2013.05.31 17:32 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

Managed Code에서 "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." 와 같은 오류가 발생하는 것은 흔하지 않다이것은 Native Code에서 잘못된 메모리를 참조하는 경우에 발생하는 데아시다시피 Managed환경에서는 포인터를 이용한 직접적인 메모리를 다루는 경우가 거의 없기 때문에 경험할 일이 없을 것이다하지만, PInvoke 와 같은 Interop 를 사용하는 경우라면 달라질 수 있다이는 결국 Native COM Managed 에서 사용하는 것이므로여전히 Native COM에서의 문제가 Managed환경으로 전달되었을 때, Access Violation의 위험성이 있는 것이다결국, Pageheap enable 하거나 해서 Crash Dump를 다시 잡는 것이 필요할 수도 있다일단, Memory Dump를 확인하면 문제가 발생한 Callstack에 아래와 같은 System.AccessViolationException을 볼 수 있다.

 

0:131> !dso

OS Thread Id: 0xacc (131)

RSP/REG          Object           Name

0000000027bda3f0 00000008d0fff488 System.Threading.Thread

0000000027bda438 00000008d0fff488 System.Threading.Thread

0000000027bda588 00000009710807f8 System.String

0000000027bda5a8 00000009710807f8 System.String

0000000027bda5b0 0000000971080908 System.String

0000000027bda668 0000000971080908 System.String

0000000027bda7d0 00000008d100adc8 System.String

0000000027bda7f8 00000008d100ca20 System.String

0000000027bda840 00000008d100b930 System.String

0000000027bda900 00000008d100b930 System.String

0000000027bda9c0 00000008d0fff7c0 System.String

0000000027bda9c8 00000008d0fff7c0 System.String

0000000027bdaaf0 00000008d10095f8 System.String

0000000027bdab08 00000008d100ca20 System.String

0000000027bdab68 00000008d100ca20 System.String

0000000027bdab80 00000008d0fff340 System.AccessViolationException

0000000027bdabe0 00000008d0fff340 System.AccessViolationException

0000000027bdad28 00000008d0fff340 System.AccessViolationException

0000000027bdb0f0 00000008d0ffd308 System.String

0000000027bdb108 00000008d0ffd290 System.String

0000000027bdb110 00000008d0ffd2b0 System.String

0000000027bdb138 00000008d0ffd270 System.String

0000000027bdb140 00000008d0ffd240 System.String

0000000027bdb148 00000008d0ffd208 System.String

0000000027bdb680 00000008d0fff340 System.AccessViolationException

0000000027bdb910 00000008d0fff340 System.AccessViolationException

0000000027bdb938 00000008d0fff340 System.AccessViolationException

. . .

그리고먼저, !verifyheap 을 통해서 Managed Heap Check 하는 것도 필요하다.

 

0:131> !verifyheap

-verify will only produce output if there are errors in the heap

------------------------------

Heap 0

object 0000000880ff00d0: does not have valid MT

curr_object : 0000000880ff00d0

Last good object: 0000000880ff00b0

----------------

total 4 objects

 

출력된 결과는 curr_object가 corruption되었다는 것과 메모리 영역에서 가장 가까운 Object중에 정상적인 Object address를 알려준다그러므로, curr_object 를 살펴보면 invalid 하다는 결과를 얻는다.

 

0:131> !do 0000000880ff00d0

<Note: this object has an invalid CLASS field>

Invalid object

 

0:131> !do 0000000880ff00b0

Name: System.String

MethodTable: 00000642784365a0

EEClass: 000006427803e4f0

Size: 32(0x20) bytes

GC Generation: 0

 (C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String: AES

Fields:

              MT            Field           Offset                 Type VT             Attr            Value Name

0000000000000000  4000096        8         System.Int32  1 instance                4 m_arrayLength

0000000000000000  4000097        c         System.Int32  1 instance                3 m_stringLength

0000000000000000  4000098       10          System.Char  1 instance               41 m_firstChar

0000000000000000  4000099       20        System.String  0   shared           static Empty

                                 >> Domain:Value  00000000d75a2aa0:NotInit Unable to get AppDomain d7900cc0

0000000000000000  400009a       28              SZARRAY  0   shared           static WhitespaceChars

                                 >> Domain:Value  00000000d75a2aa0:NotInit Unable to get AppDomain d7900cc0

 

정상적인 Data를 같이 보여주는 것은 GC에서는 Memory Allocation이 순차적으로 일어난다는 것과 무관하지 않다. low address에서 아래와 같이 Check 하여  Data를 살펴보거나 해당 Object MethodTable 정보를 Check 하는 것은 개발자가 관련있는 Code verify 하는 데 도움이 될 수 있기 때문이다.

 

0:131> dc 0000000880ff00b0

00000008`80ff00b0  784365a0 00000642 00000004 00000003  .eCxB...........  <--- valid Object

00000008`80ff00c0  00450041 00000053 00000000 00000000  A.E.S...........

00000008`80ff00d0  7843e5e0 00000642 0000000d 00000000  ..CxB...........  <--- invalid Object

00000008`80ff00e0  32313338 30323031 .................

 

또한 !gcroot 에 대한 결과로 관련된 Object 등을 Check 할 수 있는 데아래의 경우는 조금 실망스러운 결과이다.

 

0:131> !gcroot 0000000880ff00b0

Note: Roots found on stacks may be false positives. Run "!help gcroot" for

more info.

Scan Thread 52 OSThread 1440

Scan Thread 79 OSThread f4c

Scan Thread 145 OSThread 1f64

Scan Thread 149 OSThread 144c

Scan Thread 99 OSThread 18e4

Scan Thread 148 OSThread 1d38

Scan Thread 93 OSThread 1c0c

Scan Thread 91 OSThread 149c

Scan Thread 146 OSThread 1980

Scan Thread 96 OSThread 1dac

Scan Thread 136 OSThread f84

Scan Thread 98 OSThread 6ac

RSP:33c6cbb8:Root:  0000000880ff00b0(System.String)

RSP:33c6cd88:Root:  0000000880ff00b0(System.String)

RSP:33c6ce28:Root:  0000000880ff00b0(System.String)

RSP:33c6cfc0:Root:  0000000880ff00b0(System.String)

Scan Thread 106 OSThread 1a10

Scan Thread 108 OSThread 1ce4

Scan Thread 122 OSThread 190c

Scan Thread 121 OSThread 1698

Scan Thread 110 OSThread 14a8

Scan Thread 107 OSThread 1c10

Scan Thread 116 OSThread 1b80

Scan Thread 117 OSThread 141c

Scan Thread 131 OSThread acc

Scan Thread 135 OSThread 6e8

Scan Thread 126 OSThread 1d1c

Scan Thread 132 OSThread 1e18

 

해당 Object가 존재하는 98 Thread에서 연관된 Callstack Check 할 수 있다하지만, Native에서도 마찮가지로 Heap Corruption이 발생한 것은 Dumping 시점 이전에 문제가 발생한 것이 이후에 해당 Managed Heap의 사용에 의해 AV가 발생한 경우가 많기 때문에 문제가 정확히 드러나지 않을 수 있다그러므로다소 시간을 걸리더라도 Pageheap enable 하고 여러 차례 Dump를 수집할 필요가 있을 지도 모른다그리고, 1st chance AV 및 기타Exception에 대해서도 Callstack Check 라던가 관련성 여부를 살펴보는 것이 필요할 수 있다.



출처 : http://byung.egloos.com/4987870

RGB 색상표 (16진수) 변환

posted-at2013.05.29 23:05 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

p, td, ul, ol, li { font-size:12px; line-height:140%; margin-top:0; margin-bottom:0; } body { font-size:12px; }

색상표의 16진수 String 값을 Color 구조체로 변환하여 사용

 

string bb = "H808080";

int r = Convert.ToInt32(bb.Substring(1, 2), 16);

int g = Convert.ToInt32(bb.Substring(3, 2), 16);

int b = Convert.ToInt32(bb.Substring(5, 2), 16);

 

Color c = Color.FromArgb(r, g, b);

 

pictureBox1.BackColor = c;

 

 for (KnownColor kc = KnownColor.ActiveBorder; kc <= KnownColor.YellowGreen; ++kc)

 {

         Color c2 = Color.FromKnownColor(kc);

           if ((c.A == c2.A) && (c.R == c2.R) && (c.G == c2.G) && (c.B == c2.B))

          {

                 label1.Text = kc.ToString();

          }

   }


출처 : http://blog.naver.com/kkdcool?Redirect=Log&logNo=110053791437


XNAExtras로 XBOX360에 폰트를 출력해 보자!! #1

posted-at2013.05.28 14:44 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL


* 주의 사항
0. 이글에 대한 모든 권리는 저에게 있습니다. ( 소스에 대한 권리는 개발자 분에게 있습니다. )
1. 이글을 퍼가실때는 아래 댓글로 어디에 퍼가시는지 반드시 알려 주십시요. 
2. 개인블로그등 비상업적인 목적이라면 출처만 밝혀주시면 모두 허용하겠습니다. 단 상업적인 목적이나 상업적인 싸이트에서 게시하실 경우 저에게 연락해 주십시요. 
3. 오탈자나 잘못된 부분들도 모두 아래 댓글에 달아 주십시요 ^^; 부탁드립니다. 
4. 퍼가실때 이 메시지와 퍼온 주소 (http://nomoreid.egloos.com/2910890)를 빠뜨리지 말아주십시요.
5. 아래 소스틑 아직 XBOX360 에서 테스트 해보지 못했습니다. 기술적으로 안될 이유는 없어 보입니다만 혹시나 안될때는 저에게 알려 주십시요. 아는분 엑박360을 빌려서 테스트 해보겠습니다. ^^;




0. 서문.

폰트 출력하는 루틴을 맨땅에 헤딩으로 짤려다 보니 분명히 누군가 만들어놨는데 삽질하는거 같아서 구글링을 통해 XNAExtras를 찾게 되었습니다.

XNAExtras는 xna diaries 라는 전 MS직원(현재 구글 직원-_-;;)인 Gary Kacmarcik씨가 운영했던 블로그에 공개된 툴 + 소스+ 샘플 입니다. 블로그를 통해 틈틈히 공개했던 소스와 툴을 정리해서 모아둔 거라고 보시면 됩니다. 그 안에 우리가 원하던 윈도우 폰트를 텍스쳐로 만들고 화면에 출력하는 부분이 들어 있는것이죠. ^^; 

너무나도 깔끔하고 쉽게 되어 있어서 별로 설명할게 없더군요. 폰트를 기본으로 하는것이므로 유니코드들도 모두 지원 합니다. 또 콘솔게임에서 꼭 필요한 텍스트 파일을 지정해서 해당 폰트만 따로 텍스쳐로 뽑아내는 기능등도 있습니다. (불필요한 폰트 데이터가 들어가는걸 방지하는거죠. 비됴 메모리는 한정되어 있으니.) 간단하게 응용하면 여러 다른 기종에서도 윈도 폰트를 사용하게  할 수 있을거 같습니다.

(xml의 스키마가 공개되어 있으니 해당 xml을 읽어서 font 데이터와 매칭시키는 부분만 따로 만들어주면 texture 데이터를 그대로 이용해서 쓸 수 있을거 같네요. png 포맷이니.)

일단 간단하게 순서를 정리해 보면 다음과 같습니다.

0. 먼저 XNA Game Studio Express 1.0이 깔려 있는 컴퓨터가 있어야  합니다.
1. xnaextras를 다운 -> 압축풀기
2. bmgontgen 유틸리티로 폰트에서 png와 xml을 추출
3. xnaextras의 bitmap font를 포함하는 프로그램을 짠다.
 



1. xnaextras를 다운 -> 압축풀기

12월 1일 최신 버전입니다. 근데 당분간 업데이트는 없을거 같습니다.개발자가 구글로 회사를 옮겼다고 하네요. -_-;;근데 현재 있는것 만으로도 상당히 쓸만합니다. 

URL : http://blogs.msdn.com/garykac/archive/2006/12/01/xnaextras-update.aspx

압축을 풀면 다음과 같은 디렉토리가 생깁니다.








Tools - bmfontgen 유틸리디가 들어있는 디렉토리
XML Schema - 소스에서 사용하는 xml의 스키마가 들어있는 디렉토리 (볼일은 없음)
XNA Samples - 여러가지 응용 샘플이 있는 디렉토리 , XNAExtras에서 사용하는 실제 소스는 samples/common 에 다 들어 있습니다.


2. bmfontgen 유틸리티로 폰트에서 png와 xml을 추출

일단 C:\WINDOWS\Fonts 에 있는 폰트라면 모두 추출할 수 있습니다. 
요즘 유행하는 비스타의 맑은 고딕을 추출해 보았습니다.
단 맑은 고딕에는 한자가 없더라구요. 바탕체에는 한자가 있습니다.
폰트에 없는 글자는 당연히 출력되지 않습니다.

cmd 창에서 tool이 깔린 디렉토리에 가서 다음과 같이 입력하면 폰트를 같은 디렉토리에 bitmap으로 뽑아줍니다.

BMFontGen -name "맑은 고딕" -size 12 -output "malgun12" -range 0000-fffe
BMFontGen - v1.0 beta (build 1119)
Copyright 2006 Microsoft Corp.
WARNING : No character information for 0100-0110
WARNING : No character information for 0112-0125
WARNING : No character information for 0128-0130
.......................


옵션에 대해 설명드리면 

-name 은 윈도우 폰트 이름 입니다.
-size 출력될 폰트 싸이즈
-output 파일명의 앞부분입니다.
-range 출력될 폰트 코드의 범위입니다. 일단 2byte 문자의 모든 범위 (0000 - fffe) 를 출력하게 했습니다. 아래의 WARNING은 폰트가 없는 코드 범위를 알려주는 겁니다. 폰트별로 모든 코드를 다 가지고 있는게 아니라서 적절한 범위를 짤라 사용하면 되겠습니다.

BMFontGen의 모든 기능에 대해서는 여기를 참고해 주십시요.

유용한 옵션중에 -source 라는 옵션이 있습니다. 게임에서 사용하는 대사파일등을 지정해두면 (중복 지정가능) 해당 대사에 사용된 폰트들만 추출해 주는 기능입니다. ^^;

위와 같이 실행하면 같은 디렉토리 안에 output에서 지정된 파일명으로 추출된 폰트 파일들이 다수 있을겁니다.


png 파일을 클릭해 보면 흰색 박스만 나올것입니다. 투명색 + 흰색 글자라 아무것도 보이지 않습니다.
(저도 처음에 안되는줄 알았습니다. -_-;)

 -blackbg 을 붙이면 확인용으로 배경을 검게 할 수 있습니다. 하지만 그대로 쓰면 화면이 이렇게 나온다는거..

그외에 안티알리아싱이라든지 여러가지 유용한 옵션이 많습니다. 참 -bmsize size (256-1024) 이 옵션은 비트맵의 싸이즈를 256-1024까지 바꿔 줍니다. 디폴트는 512구요. 한글처럼 글자가 많은경우는 1024정도로 크게 뽑아주는게 좋겠죠.

아래는 굴림체를 배경을 검게해서 512X512로 추출한겁니다.


3. xnaextras의 bitmap font를 포함하는 프로그램을 짠다.

 실제 프로그램에 적용하는 순서는 다음과 같다.

ㄱ. 빈프로젝트를 하나 만든다.

ㄴ. Content 디렉토리를 하나 만들고 위에서 생성한 png 파일과 xml 파일을 넣는다. XMLExtra 라는 폴더를 만들고 Samples/Common에 있는 BitmapFont.cs 파일을 copy하고 프로젝트에 add 한다.

ㄷ. png와 xml 파일의 properities 창에서 Build Action 을 Embedded Resource 로 수정.

ㄹ. Solution Explorer에 Reference 쪽에 System.xml 추가.

ㅁ. 프로젝트에 멤버변수로 BitmapFont 를 등록 , Initialize()함수에서 BitmapFont를 new 이때 xml과 연결시켜줌 , LoadGraphicsContent 함수에 등록 , Draw 에 등록

ㅂ. 실행.

이게 전부이다. xml을 이용한 데이터 바인딩을 통해 아주 쉽게 쓸 수 있는 형태로 구현해 두었다는것을 알 수 있다.

아래 부분에 프로젝트를 만들고 파일을 추가한 후 수정한 부분만 붉은색으로 바꿔 보겠다.


#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

using XNAExtras;

#endregion

namespace WindowsGame1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        ContentManager content;

        //Bitmap
        BitmapFont m_Malgun;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            content = new ContentManager(Services);
        }


        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            m_Malgun = new BitmapFont("Content/malgun.xml");
            base.Initialize();
        }


        /// <summary>
        /// Load your graphics content.  If loadAllContent is true, you should
        /// load content from both ResourceManagementMode pools.  Otherwise, just
        /// load ResourceManagementMode.Manual content.
        /// </summary>
        /// <param name="loadAllContent">Which type of content to load.</param>
        protected override void LoadGraphicsContent(bool loadAllContent)
        {
            if (loadAllContent)
            {
                // TODO: Load any ResourceManagementMode.Automatic content
            }
            // TODO: Load any ResourceManagementMode.Manual content
            m_Malgun.Reset(graphics.GraphicsDevice);
        }


        /// <summary>
        /// Unload your graphics content.  If unloadAllContent is true, you should
        /// unload content from both ResourceManagementMode pools.  Otherwise, just
        /// unload ResourceManagementMode.Manual content.  Manual content will get
        /// Disposed by the GraphicsDevice during a Reset.
        /// </summary>
        /// <param name="unloadAllContent">Which type of content to unload.</param>
        protected override void UnloadGraphicsContent(bool unloadAllContent)
        {
            if (unloadAllContent == true)
            {
                content.Unload();
            }
        }


        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the default game to exit on Xbox 360 and Windows
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here

            base.Update(gameTime);
        }


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            Color cHilite = Color.DarkBlue;
            Color cWhite = Color.White;

            int nX = 20;
            int nY = -15;

            nY += 20;


            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "안녕하세요 謹賀新年");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "반갑습니다 폰트 테스트 ひびつれづれ 是日");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "あけましておめでとうございます(´ω`)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "1234567890  ♣♬!@#$%^&*() ");
            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㄱ - 느낌표, 물음표 등 부호(!,/...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㄴ - 괄호, 따옴표 등 부호([, 》...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㄷ - 더하기, 빼기 등의 수학적 부호(+, >, ×...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㄹ - 단위($, ℃, ㎖...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅁ - 특수부호(#, ♣, ♬...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅂ - 연결 및 표시선(─, ┐, ╆...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅅ - 한글 원문자 및 괄호문자(㉠, ㈐, ㈃...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅇ - 알파벳과 숫자 원문자 및 괄호문자(ⓑ, ⒀, ⑧...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅈ - 숫자(Ⅷ, 3, ⅱ...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅊ - 분수와 아래첨자, 윗첨자(⅔, ⁴, ₂...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅋ - 한글(ㄱ, ㅞ...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅌ - 이상한 한글 조합(ㅫ, ㆋ...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅍ - 알파벳(x, A, N...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅎ - 그리스 글자(Β, Δ, Σ...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㄲ - 영어 발음기호(æ, ŋ, ð...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㄸ - 일본어 히라가나(あ, け, ず...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅃ - 일본어 가타카나(ア, ヴ, ォ...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅆ - 이상한 글자들(Д, ю, щ...)");

            m_Malgun.DrawString(nX, nY +=( m_Malgun.LineHeight +5), cWhite, "ㅉ - 없음");

 

            base.Draw(gameTime);
        }
    }
}

* 실제 코딩하는 부분은 거의 없습니다.^^; 데이터 바인딩을 xml로 ^^;

* 이외에 리소스를 embeded resource로 해서 실행파일에 넣지 않고 따로 파일로 뽑아서 하는 방법도 있습니다.(samples/BitmapFontDemo)

* Samples 에 여러가지 데모들이 있으니 많이 연구하시고 공개 해주세요. ^^; Sprite를 응용한 TextBox 예제도 있습니다.



출처 : http://nomoreid.egloos.com/2910890

C# StreamReader 에서의 한글 Encoding 문제

posted-at2013.05.28 12:20 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

오늘은 개발자 한 분이... ASP.NET 에서 한글이 포함된 HTML 텍스트를 로딩했는 데, 한글이 깨진다는 문제를 들고 왔습니다.

텍스트 파일의 특성상, 가볍게 다음과 같은 코드로 마무리를 지었던 것입니다.

string fileContent = null;
using ( StreamReader sr = new StreamReader( filePath ) )
{
 fileContent = sr.ReadToEnd();
 sr.Close();
}


저 역시, 위의 코드를 보고 너무 표준적인 코드라 ^^ 문제가 없어 보였지요.

 .NET 에서는 문자열 처리를 명시적으로 지정하지 않는 한, 기본적으로 "System.Text.UTF8Encoding" 으로 처리를 합니다. 문제는 거기서 발생을 하지요.

 해당 HTML 텍스트 한글 파일은 메모장에서 "ASCII" 형식으로 저장된 것이었고, 디코딩을 UTF-8 로 해버리니 당연히 깨질 수 밖에 없습니다.

 한글이 포함된 ASCII 코드를 정상적으로 읽어들이기 위해서는 인코딩을 지정해야 합니다. StreamReader 의 두번째 인자에는 바로 그 인코딩 방식을 지정할 수가 있죠. 우리가 아는 것처럼 "KS_C_5601-1987" 인코딩 방식을 지정해야 합니다. 다음과 같은 코드로.

using ( StreamReader sr = new StreamReader( filePath, Encoding.GetEncoding( "ks_c_5601-1987" ) ) )
{
 fileContent = sr.ReadToEnd();
 sr.Close();
}


 명시적인 Encoding 문자열 지정대신에, Encoding.Default 를 지정해도 됩니다. 시스템 레벨로 설정된 (제어판의 Regional Settings) code page 값이 한글 윈도우즈에서는 기본적으로 "KS_C_5601-1987" 이기 때문입니다.

 하지만, 여기서 끝이 아니죠. ^^
 만약 해당 파일이 utf-8 또는 unicode 로 인코딩된 텍스트 파일이라면? 당연히 위의 코드로 읽어들이게 되면 역시 한글이 깨지게 됩니다.

 Unicode 또는 UTF-8 등의 텍스트 파일은 그 인코딩 방법을 표시하기 위해, 파일의 최초 2~3바이트에 BOM(byte order mark)를 표시해 둡니다. utf-8 로 인코딩된 텍스트 파일을 윈도우즈의 "메모장"으로 열어보면 그러한 표시를 생략하고 순수 텍스트만 보여주지만, 2진 파일 형식으로 볼 수 있는 hexa 에디터등을 통해서 보게 되면, 최초 2~3바이트의 내용이 인코딩에 따라서 달라지는 것을 확인할 수 있습니다.

UTF-8: EF BB BF
Unicode: FF FE

 실제로, BOM 을 통한 디코딩을 지원하지 않는 Editor 로 UTF-8 인코딩된 파일을 열게 되면, 최초 3byte 를 깨진 텍스트로 출력해 주는 것을 볼 수 있습니다.

 아무튼... 그렇다면, 우리도 BOM 을 읽어서 상황에 따라 StreamReader 의 2번째 인자에 각각 해당하는 인코딩을 넣어주면 되겠지요. ^^; 아마도 C++ 이었다면 틀림없이 그렇게 해야 했을 것입니다. 하지만, 우리의 "친절한 .NET 씨"(이 표현은 Loner(
http://simpleisbest.net)에서 빌려옴) 는 그런 작업을 모두 해놓았습니다. 바로 StreamReader 의 3번째 인자에서 그러한 역할을 대신해 줍니다.

public StreamReader(..., bool detectEncodingFromByteOrderMarks);

 매개변수 이름 부터 그런 태생임을 짐작하게 해줍니다. 해당 값을 true 로 전달하면 BOM 마크가 없는 - 예를 들어 ANSI 파일 - 경우에는 2번째 인자에서 지정한 Encoding 방식으로 인식해서 디코딩을 하지만, BOM 이 있으면 거기서 지정된 Encoding 방식으로 되어 있다고 인식해서 디코딩을 하게 됩니다.

그러니... 앞으로 국내에서의 .NET 개발자들은 텍스트 파일을 로딩하기 위한 표준 코드를 다음과 같이 해야 합니다.
using ( StreamReader sr

 = new StreamReader( filePath, Encoding.GetEncoding( "ks_c_5601-1987" ), true ) )
{
 fileContent = sr.ReadToEnd();
 sr.Close();
}


또는

using ( StreamReader sr = new StreamReader( filePath, Encoding.Default, true ) )
{
 fileContent = sr.ReadToEnd();
 sr.Close();
}


 두 가지 모두, 경우에 따라서 논란의 여지가 있지만... 적어도 한글 윈도우즈에서 호스팅 된다는 보장만 된다면, "Encoding.Default" 인자가 가장 좋을 것 같네요. ^^




[XNA] Scrolling background images horizontally across the screen

posted-at2013.05.08 17:24 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

If you're working on 2D games, at some point you're going to want to know how to create a scrolling background. This tutorial will cover setting up a horizontally scrolling background that auto-scrolls behind your character. Let's go ahead and get started.

 

Creating the new game project:

We are going to be using the "Sprite" class we created in the tutorial "Creating a 2D Sprite". Instead of creating a new XNA Game project, you can just download the source for that project and begin working from that game project.

If you would rather create a new game project to start from, but are having trouble remembering how to do that, just follow the steps in this tutorial here and come back to the this tutorial after you've refreshed your memory. Once you have your new game project, you will need to add the "Sprite" class created in this tutorial here to your new project.

Adding the images:

Now, let's add the background images that we are going to be using in this tutorial to the game project. You can download the images used in the project from here. Once you have downloaded the images, add all five background images to the Content folder in your game. If you are having trouble remembering how to add images to an XNA Game project, just follow the steps in this tutorial here and come back to this tutorial after you've refreshed your memory.

Enhancing the Sprite class:

To start out, we are going to make some enhancements to the Sprite class. These enhancements will make the sprite class a bit more flexible and allow us to more easily add in our scrolling background.

Add the following objects to the top of the Sprite class.

        //The size of the Sprite
        public Rectangle Size;
 
        //Used to size the Sprite up or down from the original image
        public float Scale = 1.0f;

The Size object will be used to store the height and width of the scaled sprite and the Scale object will be used to increase or decrease the size of the sprite from the original image. We are defaulting the Scale variable to 1.0 which tells the SpriteBatch to leave the image at its original size. Making Scale a larger number will increase the size of the sprite and a smaller number for scale will being to shrink the sprite.

Next, we will modify the LoadContent method to calculate and initialize the size of our Sprite. Modify the LoadContent method of the Sprite class to look like this.

        //Load the texture for the sprite using the Content Pipeline
        public void LoadContent(ContentManager theContentManager, string theAssetName)
        {
            mSpriteTexture = theContentManager.Load<Texture2D>(theAssetName);
            Size = new Rectangle(0, 0, (int)(mSpriteTexture.Width * Scale), (int)(mSpriteTexture.Height * Scale));
        }

Next, we want to use one of the many overrides of the SpriteBatch object to draw our image with our new Scale applied. Change the Draw method to look like the following.

        //Draw the sprite to the screen
        public void Draw(SpriteBatch theSpriteBatch)
        {
            theSpriteBatch.Draw(mSpriteTexture, Position, 
                new Rectangle(0, 0, mSpriteTexture.Width, mSpriteTexture.Height),Color.White, 
                0.0f, Vector2.Zero, Scale, SpriteEffects.None, 0);
        }

We have added a whole lot of parameters to pass into the Draw method of the SpriteBatch, but the one we are tracking is “Scale”. This will tell the SpriteBatch object to increase or decrease the size of the sprite proportionally.

Do a quick build now to make sure everything compiles. If you’re working off the source code for “Creating a 2D Sprite”, you should see the two sprites drawn to the screen.

Ok, now that we have laid the groundwork in our Sprite class we can now get started on adding the scrolling backgrounds to our game project.

We’ll start by adding some new Sprite objects to the top of the Game1.cs class. Add the following objects to the top of the class.

        Sprite mBackgroundOne;
        Sprite mBackgroundTwo;
        Sprite mBackgroundThree;
        Sprite mBackgroundFour;
        Sprite mBackgroundFive;

These Sprite objects will be used to move our background images across the screen.

Next, let’s Initialize our new Sprite objects and give them there scale value. The original size of the background images is 400 by 300 and the default size for a new Windows game is 800 by 600. So, if we double the size of our images, one will fill the whole screen. We can do that by adjusting the Scale value of our sprites.

Modify the Initialize method to look like this.

        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            mSprite = new Sprite();
            mSpriteTwo = new Sprite();
 
            mBackgroundOne = new Sprite();
            mBackgroundOne.Scale = 2.0f;
 
            mBackgroundTwo = new Sprite();
            mBackgroundTwo.Scale = 2.0f;
 
            mBackgroundThree = new Sprite();
            mBackgroundThree.Scale = 2.0f;
 
            mBackgroundFour = new Sprite();
            mBackgroundFour.Scale = 2.0f;
 
            mBackgroundFive = new Sprite();
            mBackgroundFive.Scale = 2.0f;
 
            base.Initialize();
        }

You can see we have created a new instance of each of our Sprite objects and adjusted the Scale for our background images.

Now that we have initialized our sprites, we need to load the content. Modify the LoadContent method to look like this.

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
 
            // TODO: use this.Content to load your game content here
            mSprite.LoadContent(this.Content, "SquareGuy");
            mSprite.Position = new Vector2(125, 245);
 
            mSpriteTwo.LoadContent(this.Content, "SquareGuy");
            mSpriteTwo.Position.X = 300;
            mSpriteTwo.Position.Y = 300;
 
            mBackgroundOne.LoadContent(this.Content, "Background01");
            mBackgroundOne.Position = new Vector2(0, 0);
 
            mBackgroundTwo.LoadContent(this.Content, "Background02");
            mBackgroundTwo.Position = new Vector2(mBackgroundOne.Position.X + mBackgroundOne.Size.Width, 0);
 
            mBackgroundThree.LoadContent(this.Content, "Background03");
            mBackgroundThree.Position = new Vector2(mBackgroundTwo.Position.X + mBackgroundTwo.Size.Width, 0);
 
            mBackgroundFour.LoadContent(this.Content, "Background04");
            mBackgroundFour.Position = new Vector2(mBackgroundThree.Position.X + mBackgroundThree.Size.Width, 0);
 
            mBackgroundFive.LoadContent(this.Content, "Background05");
            mBackgroundFive.Position = new Vector2(mBackgroundFour.Position.X + mBackgroundFour.Size.Width, 0);
 
        }

You can see that we load the content for each of the Sprite images we added for our backgrounds. We then position each of the images in a trail from left to right. The first image starts at 0,0 which is the top left corner of the screen and then each image is placed in a line after that.

Scrolling backgrounds work by moving the background images across the screen in a snake like fashion. When an image moves all the way off the screen on the left, it is placed at the end of the snake tail so that the images can continually loop in that fashion giving you a seamless horizontally scrolling background.

To create this effect, we need to both move the images and then check to see if the image has moved off the screen and re-position it at the end. We do that by modifying the Update method to look like this.

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
 
            // TODO: Add your update logic here
 
 
            if (mBackgroundOne.Position.X < -mBackgroundOne.Size.Width)
            {
                mBackgroundOne.Position.X = mBackgroundFive.Position.X + mBackgroundFive.Size.Width;
            }
 
            if (mBackgroundTwo.Position.X < -mBackgroundTwo.Size.Width)
            {
                mBackgroundTwo.Position.X = mBackgroundOne.Position.X + mBackgroundOne.Size.Width;
            }
 
            if (mBackgroundThree.Position.X < -mBackgroundThree.Size.Width)
            {
                mBackgroundThree.Position.X = mBackgroundTwo.Position.X + mBackgroundTwo.Size.Width;
            }
 
            if (mBackgroundFour.Position.X < -mBackgroundFour.Size.Width)
            {
                mBackgroundFour.Position.X = mBackgroundThree.Position.X + mBackgroundThree.Size.Width;
            }
 
            if (mBackgroundFive.Position.X < -mBackgroundFive.Size.Width)
            {
                mBackgroundFive.Position.X = mBackgroundFour.Position.X + mBackgroundFour.Size.Width;
            }
            
            Vector2 aDirection = new Vector2(-1, 0);
            Vector2 aSpeed = new Vector2(160, 0);
 
            mBackgroundOne.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundTwo.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundThree.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundFour.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundFive.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;            
 
            base.Update(gameTime);
        }

This code consists of two different sections. We’ll discuss the first section of code below which deals with keeping the "chain" of images going.

            if (mBackgroundOne.Position.X < -mBackgroundOne.Size.Width)
            {
                mBackgroundOne.Position.X = mBackgroundFive.Position.X + mBackgroundFive.Size.Width;
            }
 
            if (mBackgroundTwo.Position.X < -mBackgroundTwo.Size.Width)
            {
                mBackgroundTwo.Position.X = mBackgroundOne.Position.X + mBackgroundOne.Size.Width;
            }
 
            if (mBackgroundThree.Position.X < -mBackgroundThree.Size.Width)
            {
                mBackgroundThree.Position.X = mBackgroundTwo.Position.X + mBackgroundTwo.Size.Width;
            }
 
            if (mBackgroundFour.Position.X < -mBackgroundFour.Size.Width)
            {
                mBackgroundFour.Position.X = mBackgroundThree.Position.X + mBackgroundThree.Size.Width;
            }
 
            if (mBackgroundFive.Position.X < -mBackgroundFive.Size.Width)
            {
                mBackgroundFive.Position.X = mBackgroundFour.Position.X + mBackgroundFour.Size.Width;
            }

You might expect to move the background images first, but this will actually begin to create gaps between the images. Often in game development, you have to be very aware in the order that you are doing things. If we move the images first, then check to see if they’ve moved off the screen, you have to remember that the player has never seen that happen yet because they haven’t been drawn to the screen yet! That doesn’t happen until Draw is called.

So, instead, we first move images that have moved off the screen (and hopefully the player has seen this occur already) to the end of the trail of images. This is done by checking the Sprite’s current position and seeing if it’s moved further then it’s width off the screen. This means that the entire image is now out of the viewable area for the player. If this is true, then we move the image to the one it should be following. The first image follows the fifth, and then the fifth follows the fourth and so on and so on.

Now let’s look at the second part of the code, the movement.

            Vector2 aDirection = new Vector2(-1, 0);
            Vector2 aSpeed = new Vector2(160, 0);
 
            mBackgroundOne.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundTwo.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundThree.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundFour.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            mBackgroundFive.Position += aDirection * aSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;            

Movement is done by increasing the position of a sprite by multiplying Direction, times the speed, times the time that has elapsed.

Direction is just a -1 or 1 in the X and or Y direction. In our case, we want to move the sprites to the left, so we are decreasing in the X direction, so we use a negative one. We are not moving at all in the Y direction, so we leave that 0 for our Direction vector.

Speed is how fast you want the sprite to move. We want the Sprite to move at a decent pace in the X direction and not at all for Y. You can increase or decrease the speed of the scrolling by increasing or decreasing this number.

Finally, you multiply by time elapsed. This is done so that computers that are faster and with faster refresh rates see the same speed of scrolling that slower computers with slower refresh rates see. By default, the XNA framework tries to maintain this internally by keeping everything moving at a fixed time step, but it’s a good habit to get into.

Ok, we’re re-positioning our background sprites as necessary and moving them along at a steady clip in the right direction. The only thing left to do it draw them to the screen.

Modify the Draw method to look like this.

        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
 
            // TODO: Add your drawing code here
            spriteBatch.Begin();
 
            mBackgroundOne.Draw(this.spriteBatch);
            mBackgroundTwo.Draw(this.spriteBatch);
            mBackgroundThree.Draw(this.spriteBatch);
            mBackgroundFour.Draw(this.spriteBatch);
            mBackgroundFive.Draw(this.spriteBatch);
 
            mSprite.Draw(this.spriteBatch);
            mSpriteTwo.Draw(this.spriteBatch);
            spriteBatch.End();
 
            base.Draw(gameTime);
        }

The important thing to note here is that we are drawing the backgrounds BEFORE the two square guy sprites. Sprites are drawn in layers with the first Draw calls drawn first to the screen and the others drawn on top of them. It’s important to remember that when adding your draw code. If we had placed the backgrounds after the sprites, we would have never seen them because the background images would have been drawn on top of the square guys.

That’s it, go ahead and Build CropperCapture2632 the game. You should see the background images begin to scroll horizontally across the screen and the two square guys looking like their floating through the air.

Scrolling Background

Congratulations! You now have successfully learned how to add a horizontally scrolling background to your game. While, this is a good introductory example to scrolling a Horizontal background, but the code wasn’t written in a very object oriented way. I have taken this tutorial a bit further and done some work to make it a little more re-usable project. You can check out the more advanced Horizontal scrolling example.

Can you think of some things you can change? How hard would it be to make this scroll vertically? Do you think you know what you might change?

Play with it, experiment and ask questions. Most of all make sure you’re having fun!


출처 : http://www.xnadevelopment.com/tutorials/scrollinga2dbackground/ScrollingA2DBackground.shtml

[XNA] A Simple 2D Camera

posted-at2013.05.08 17:21 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

What is a camera? Intuitively we know what a camera is:  simply a way to show the action.

A Camera allows us to deal with the display of the action in a detached way from the action.

Implementation

I like to start with what we are trying to achieve. For the purposes of this post, I want to have two cameras showing the same action at different zoom levels, like this:

Capture

In this case we want 2 cameras, with each camera having it’s own ViewPort that we assign when creating like this:

int halfScreenWidth = GraphicsDevice.Viewport.Width/2;
_camera1 = new Camera(new Viewport(0, 0, halfScreenWidth - 3, GraphicsDevice.Viewport.Height));

What we are saying with that is that the Camera class will have a Viewport that occupies the left side of the screen.  The – 3 is there to add a visible gap between the left and right sides of the screen. Lets look at the following portion of the Draw method. Please note you could have all the parameters for _spriteBatch.Begin() null, except for the transform.

 1:             GraphicsDevice.Viewport = _camera1.Viewport;
 2: 
 3:             _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone, null, _camera1.Transform);
 4:             _level.Draw(_spriteBatch);
 5:             _spriteBatch.Draw(_tankTexture, _tankPosition, null, Color.White, _rotation, new Vector2(_tankTexture.Width / 2, _tankTexture.Height / 2), 1, SpriteEffects.None, 0);
 6:             _spriteBatch.End();

Since we have a viewport  per camera, the graphics device needs to know which one to use, and that’s what we are doing in line 1 in the code above. The other important part of the code is the last parameter of the _spriteBatch.Begin call, where we are using the transformation matrix from the camera. This transform is calculated on each update.

So finally lets look at the Camera class:

 1:     public class Camera
 2:     {
 3:         public Matrix Transform { get; private set; }
 4:         public Viewport Viewport { get; private set; }
 5: 
 6:         public Camera(Viewport viewport)
 7:         {
 8:             Transform = Matrix.Identity;
 9:             Viewport = viewport;
 10:         }
 11: 
 12:         public void Update(GameTime gameTime, float rotation, Vector2 position, float zoom)
 13:         {
 14:             Transform = Matrix.CreateTranslation(-position.X, -position.Y, 0) *
 15:                         Matrix.CreateRotationZ(rotation) *
 16:                         Matrix.CreateScale(new Vector3(zoom, zoom, 1)) *
 17:                         Matrix.CreateTranslation(Viewport.Width / 2, Viewport.Height / 2, 0);
 18:         }
 19:     }

The least obvious part of this code lies in the matrix transformation. It is important to understand that we have two coordinate systems in place, the screen and the world. With the transformation matrix we are trying to project the world coordinate system onto the screen system. With that in mind, the first translation matrix (line 14 in the code above) will reposition the world so that point (position.X, position.Y) lines up with the screen’s origin. The result is as follows:

CaptureCapture

What you see at the top left of the pic is a quarter of the tank. If you change the tank’s position then you will see that the tank remains static at the top left (tho rotation applies) and the world moves underneath it.

Capture

The next line, Matrix.CreateRotationZ, creates a matrix representing a rotation around the Z axis. The Z axis points straight out of the screen. In 2D, to perform a rotation, we always rotate around Z.

Capture

Then we need to scale, using the parameters that we sent on update. Don’t forget we set different levels of zoom in each of the two cameras. We use the overload of Matrix.CreateScale() that takes a Vector3 to create a scaling matrix. However we could use the overload that just takes a float and pass the zoom value as a parameter with the same result. Unsurprisingly applying the scale, scales Smile.

Finally we want to center the tank in the middle of each viewport and that’s why you apply the last line (line 17 on the sample above).

Capture

And we are done Smile tho I m sure there are plenty of ways to improve the code, but hopefully it will help as a simple example.

If you want to have a better look at the code, a working sample is available here. If you have any comments, improvements, questions, as always you are very welcome.

UPDATE: I followed up with a post about Spring Camera here.


출처 : http://roundcrisis.com/2012/04/19/xna-a-simple-2d-camera/


[C#] String Split (Unity3D)

posted-at2013.02.19 10:10 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

string a = "文字列A";
string b;

b = a.Substring(「開始位置」,「取り出す文字数」);
開始位置は0から始まる
全角も1文字として数えられます

b = a.Substring(0, 2);	//先頭から2文字→文字
b = a.Substring(1, 2);	//2文字目から3文字→字列
b = a.Substring(1);	//3文字目以降全部→字列A

●特定の文字列で分割

string a = "文字列A\n文字列B";
string[] b;
string c;

b = a.Split("\n"[0]);	//改行コードで分割
c = b[0];	//cには『文字列A』が入る

区切り文字を複数にしたい場合は,配列にすれば可能です
string a = "文字列A\n文字列B";
string[] b;
string c;
string[] KUGIRI = {"\r", "\n"};	//データの区切り文字

b = a.Split(KUGIRI);	//KUGIRI変数内の各文字で分割
c = b[0];	//cには『文字列A』が入る

○空白だけの項目は削除したい場合
Splitには実は第2引数があり,そこに System.StringSplitOptions.RemoveEmptyEntriesを指定すると,分割した後中身の無い変数は削除されます
string a = "文字列A\n\n\n文字列B";	//間に改行が3つある
string[] b;
string c;

b = a.Split("\n"[0], System.StringSplitOptions.RemoveEmptyEntries);	//改行コードで分割。空欄は削除する
//b[0]には『文字列A』
//b[1]には『文字列B』
//が入る

●文字列比較

原則として ==で比較します
string a="文字列A";

if(a == "文字列A"){
	//一致した
}else{
	//一致しなかった
}
・うまく比較できない場合はEqualsメソッドを使う
string a="文字列A";

if(a.Equals("文字列A")){
	//一致した
}else{
	//一致しなかった
}
・宣言をしただけの変数との比較はできません
string a;

if (a == null) {	//x
}
↓こういうエラーが出ます
error CS0165: Use of unassigned local variable `a'

if文を使用する変数は,必ず定義されていなければなりません
されない場合がある。というのもダメです
string a;
int b=1;

if (b == 1) {
	a = "初期化";
}
if (a == null) {
	Debug.Log("true");
}
※bが1でない場合が発生するかも知れないのでエラーになります

・nullの状態
何も入っていない状態が nullなのでは無くて,nullも代入できるという事です
string a=null;

●数値を文字列に代入

・整数
int a = 123;
string b;

b = "" + a;

・少数
float a = 123.45f;
string b;

b = "" + a;

●文字を数値に代入

・整数の場合
string a = "123";
int b;

try{
	b = int.Parse(a);
}catch{
	//エラー時:文字列が整数で無い時(少数の時もエラーになる)
}
変換できない文字列の場合は以下のエラーになります
NullReferenceException: Object reference not set to an instance of an object

・少数の場合
string a = "123.45";
float b;

try{
	b = float.Parse(a);
}catch{
	//エラー時:文字列が少数で無い時
}

○例外を発生させたくない場合はTryParseメソッドを使う
・整数の場合
string a = "123";
int b;

if(int.TryParse(a, out b)){
	//正常の時
	//bに結果の123が入っている
}else{
	//エラー時:文字列が整数で無い時(少数の時もエラーになる)
	//bには常に0が入っている
}

・少数の場合
string a = "123.45";
float b;

if(float.TryParse(a, out b)){
	//正常の時
	//bに結果の123.45が入っている
}else{
	//エラー時:文字列が少数で無い時
	//bには常に0が入っている
}

●文字列検索

string a = "文字列A\n文字列B";
int b;

b = a.IndexOf('\n');

先頭を 0とした,最初に発見した文字数が入ります
この場合は b=4です

文字が発見できなかった場合は,-1が入ります
if (a.IndexOf('\n') == -1) {
	//文字列が無かった
} else {
	//文字列があった
}

●switch~case文

string word="春";

switch(word){
case "春":
case "夏":
case "秋":
case "冬":
    //春夏秋冬のどれかだった場合
    break;
default:
    //それ以外
    break;    //省略不可
}

※最後のbreakは省略できません。書き忘れると以下のエラーが出ます
error CS0163: Control cannot fall through from one case label to another

●デバッグ出力

string debug = "デバッグ文字列";
Debug.Log(debug);
※Consoleウィンドウは,メニューの Window→Consoleで表示されます

[Kinect] 키넥트 1.6 에서 프로그램 종료시 프리즈 되는 현상

posted-at2012.12.14 17:42 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

I have the same problem.

In my debugging i noticed that problem appears only when i use skeleton stream.

Add this line:

sensor.SkeletonStream.Disable();

before:

this.sensor.Stop();
this.sensor = null;

Application hangs on line where Skeleton stream is disabled.

I am using SDK 1.6.

Interesting is that from moment error happens once, it will hang always until i reconnect camera from USB port.


->

Installed 1.5 and this hanging hasn't occurred. 

Josh


키넥트 1.6 버전에서 프로그램을 종료시키면 센서의 Skeleton Stream 부분을 Stop 하는 과정에서 프로세스가 무한루프를 도는 현상이 생김.

짜증나서 구글링해본 결과 같은 문제들이 많이 일어나고 있고, 1.5를 쓰면 아무 문제 없어짐.

아마 최신버전이라 문제가 좀 있는듯

이거땜에 1시간 삽질..


결론 : 1.5로 되돌리니까 문제가 해결됬다. 아직은 일단 1.5 써라.



[C#] 컴파일러와 dll파일

posted-at2012.11.20 18:06 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL


출처 초천재의 블로그 | 초천재
원문 http://idkhs04.blog.me/40108862362

1. 컴파일러

 

프로그래밍 언어를 한답시고 컴파일러를 모른다는것은

영어알파벳 자체를 모르는 사람이 가이드없이 영어권 나라에 가는 경우입니다.

물론.....사람사는것은 워낙 변수가 많아서 바디 랭귀지가 가능하긋지만 그냥 받아들였으면 합니다.

 

a. 컴파일러란 대체 뭔가?

 1. 프로그래밍을 한다는것은 컴퓨터 cpu에게 명령을 하기위해서 인데,

    실제적으로 은밀하게 보자면 우리는 cpu에게 우리가 직접적으로

    명령문을 내리기 위해서가 아닙니다

    그럼 누구에게 알아듣는 코드를 작성한다는것일까요?

    컴파일러입니다. 컴파일러가 없는 프로그래밍 랭귀지는 거의 없을겁니다.

    물론....초저급언어(low level language)인 어셈블리어나 기계어는 작성해서

    바로 넣지만 말이죠. 코드가 16진수나, 0,1로만 이뤄져있지요

    가끔 컴파일에러가 나서 디버깅 창을 열면 볼수가 있습니다. 어셈블리코드;;

    마치....암호같습니다...

 

2. 이 컴파이일러는 워낙 똑똑해서 사람이 치는 코드도 인식하고 이것을 기계어로 바꿔줍니다.

   한국사람이 한국어로 통역관한테 말을 하면, 잘 번역해서 영어로 번역해서 말해줍니다.

 

     결론은 우리는 컴파일코드를 작성한다고 해도 과언이 아니죠

 

b. 닷넷에서의 컴파일러란?

   하지만 C#.NET은 좀다릅니다.

   바로 MicroSoft에서는 통합솔루션이라는 개념으로 닷넷 프레임워크에서 동작하는

   실행파일을 만들기 위한 닷넷언어들만의 컴파일러를 만들었지요

   그것이 CLR입니다. 즉, Common Language Runtime 인데,

   우리가 C#으로 작성한 코드를 IL(중간언어)로 바꿔줍니다.(CIL, MSIL 이라고도 합니다)

 

   그리고 이 IL언어로 실행파일로 저장을 하고

   우리는 닷넷프레임워크상에서 실행을 하는거죠

   여기서 끝이면 좋겠지만 이 IL자체로써 cpu에게 명령을 내릴순 없습니다.

   이 변환된 코드는 다시 JIT(Just In Time) 컴파일러로 변환을 하게 되어 직접적인 기계어로 만들어져

   cpu에게 인식됩니다. 물론 이것도 CLR로 컴파일이 되는거죠

 

  C#코드  -> (CLR컴파일)  -> IL 코드  -> JIT 컴파일(CLR)  ->  기계어(네이티브어)

 

우리가 C#프로그램을 만들려면 C#컴파일러를 사용해야하며,

상대방에 컴파일러 뭐 쓰냐란 질문이 나온다면,,,,

 1. C#컴파일러

 2. CLR컴파일러

 3.  비쥬얼 스튜디오 닷넷  버전

 이 3가지 말은 거의 같다고 생각해도 무방하겠네요

 

 

2. dll 파일 (Dynamic Link Library) : 동적링크라이브러리 파일

 

가끔씩 윈도우의 이상한 폴더(?)ㅋ 폴더를 이리저리 다니거나, 간단한 게임을 받으면

dll 파일이라고 있을겁니다. 이것이 없으면 실행파일이 실행이 되지가 않지요

물론 더블클릭해도 내용을 볼수가 없습니다.

즉...코드가 은닉되어 있기때문에, 어떻게 구현되있는지 알수가 없지요.

이것은 다른관점으로 볼때, 프로그래머의 능력을 은폐시킨것과 같습니다.

나아가 프로그래머의 재산을 보호한것이기도 합니다.

 윈도우 운영체제에만 있는것으로 기능적으로 본다면 참으로 괜찮은것 같습니다.

 

2-1. dll파일의 정의

  소프트웨어를 몇개의 파일로 나누어 따로 저장해서, 필요한것만 메모리에 로드시켜 사용합니다.

  이것은 기능이 특정기능이라면 다른 응용프로그램에서 사용이 가능합니다.

  다른 프로그램인데 똑같은 기능을 쓴다면, 또 다시 코드를 작성해야하는데, 이는 시간과,

  메모리 등을 절약이 가능하고,  경제적인 프로그램 작성이 가능하다는것입니다.

 

1. 프로그래머의 코드 은닉, 재산보호

2. 효율적인 프로그램

    - 코드의 재사용, 메모리/시간 절약


[C#] ListView에서 Tag의 활용

posted-at2012.11.15 18:32 :: posted-inProgramming/C#/Xna/Kinect/WPF :: posted-byNarrL

ListViewItem li;


li = new ListViewItem();


li.Text = each.c_time.ToString() + " " + "L(" + each.c_number + ") " + each.c_scale.ToString();


/* 이런식으로 Tag에 일종의 포인터를 저장해 놓을 수 있다. */

li.Tag = t_add.c_noteList.ElementAt(t_add.c_noteList.Count - 1);


listbox.Items.Add(li);