전에 Windows SharePoint Service 3.0 으로 협업을 해보자라는 글을 올린 적이 있다. 그 때 SharePoint 개발 회사에서 그만 두고 난 뒤 더 이상 쓰질 못했다. 물론 직접 돌려보면서 이런 저런 사용방법을 적을 수도 있지만, 너무 게으른 성품 때문에 결국 다 쓰지 못한 채 연재를 더 이상하지 못했다.

그 즈음 SharePoint 2010 이 나오고 있었고, 지금은 공식 판매 한지 벌써 1년 정도 지났다. 지금은 다시 회사를 옮기게 되었고, 어찌 어찌 하다 보니, 다시 SharePoint를 만지게 되었다. 오랜만에 SharePoint를 만지다 보니까, 예전 2007 시절에서 사용하던 방법은 더 이상 활용하기가 무리가 있다고 생각된다. 그래서 지금은 완전히 처음부터 다시 만진다는 느낌으로 하나씩 손 대보려고 한다.

그런데 지금 주 거래처가 미쿡이다 보니, 지금 사용하는 SharePoint는 영문판이다.
그래서 캡쳐되는 화면도 영문판으로 진행될 것 같다.

image

728x90

예전 Windows App을 API 기반의 C 로 만들거나, MFC로 만들 때, 각종 Event 처리를 위해, 독자적인 ID를 만들었다. 그런데, 미처 인식을 못한 것이, 어떤 ID를 사용해서 운영을 해야 겹치는 경우 없이 제대로 되는지 정하지 않고 임의대로 했다.

그 중 WM_USER 값이다.
WM_USER는 사용자가 정의해서 쓸 수 있는 ID 정도로만 인식하고 있었다. 이 값으로 시작해서 최대 0x7c00 까지 정의해서 쓸 수 있다. 10진수로 한다면, 1024 ~ 31744 까지 정의해서 쓸 수 있다. 그래서 예전에는 사용할 ID 값을 아래와 같이 정의하곤 했다.

#define WM_CUSTOMUPDATE WM_USER + 100

즉 1024 + 100 = 1124 를 WM_CUSTOMUPDATE 라는 이벤트 ID로 사용한다는 의미.
하지만, 내가 안 쓰더라도, 별도로 사용되는 컨트롤이나, 3th-Party의 컨트롤의 경우 저 이벤트를 사용하는 경우가 종종 있어 자칫 종종 겹치는 경우가 있었다. 그래서 위 처럼 + 100 정도가 아닌, 5000 정도로 팍팍 띄워서 정의하기도 했다.

그런데, 알고 보니, WM_APP 라는 값이 있었다. 이 값은 최소한 컨트롤 같은 곳에서 사용하지 않는 완전 App 개발자 용으로 남겨놓은 영역이라고 한다. 이 값은 0x8000 ~ 0xBFFF 값이다. 10진수로 한다면 32768 ~ 49151 으로 볼 수 있다.

이번에 C#으로 이것저것 만들다가, 결국 unmanaged code들을 짜게 되었는데, 이 때 Windows Message를 주로 핸들링 하게 되었는데, 이벤트 ID를 대충 대충 정해서 구현한 것 같았다. 가급적 저 ID 정의 Rule에 맞추어서 정의해야 할 것 같다.

이 내용은 아래 링크에서 참고해  정리했다.(EUC-KR 이여서, 일부 Web Browser에서 종종 깨져 보인다.)

http://winapi.co.kr/reference/Message/WM_USER.htm

728x90

로그 파일을 읽는 경우가 종종 있는데, 로그 중에 계속 쌓이는 로그를 연속으로 볼 때가 있다.
이 경우 tail viewer 혹은 log tail viewer 들이 있는데, 그 툴을 활용하면, 계속 쌓이는 로그를 실시간으로 볼 수 있다.
과거 떠돌이 프로젝트 수행 중에 받았던 파일이 있다. WinTail 이라는 프로그램 인데, 그 프로그램이 그런 역할을 수행해줬다. 속도도 빠르고 좋았던 기억.

문제는 한글이 깨져서 나온다. 한글로 적힌 로그가 나오면 그대로 깨져서 나온다는..
아마도 C++로 만든거 같은데, 과거 인코딩과 거리가 멀던 그 시절에 만들어진 프로그램 같다.
이번에 작성 중인 프로그램도 로그 파일을 쌓고 있는데, 문제는 로그 내용을 한글로 적었다는 것. 
결국 무슨 말인지 알 길이 없어서, 직접 만들어야 겠다는 생각이 들었다.

image_2

 

.NET Framework 2.0을 기반으로 하며, C#으로 짰다. 모든 Visual Studio 2010 에서 작업했다.

처음에는 ListBox를 사용하여 로그 파일을 열었다. 
최소한 내가 만드는 로그 보는데는 문제가 없었다.
그래서 자신만만(?)하게 지인인 호박양에게 전달했는데,
왠걸...IIS 로그를 넣어 봤는데, All Stop 이라고 Report 해줬다.

즉, NET 기본 컨트롤로는 로그 Viewer로 쓰기에는 너무나 부적합했다는 것이다. 결국 이렇게 저렇게 검색을 하다가 우연히 발견한 오픈소스 기반의 Text Viewer인 Scintilla 를 찾았다. 이 Viewer는 C++로 되어 있으며, Win32와 GTK+ 기반으로 되어 있다. 소스 코드 에디터 처럼 특정 문자에 색을 입히거나, 코드를 묶어서 접고 펼치기 등, 다양한 소스코드 관련 Editor Viewer로 활용되는 유명한 솔루션. (현재 2.27 버전이며, 2011년 6월 20일이 최종 수정)

그것을 .NET으로 포팅한 프로젝트가 있었으니, 그것이 ScintillaNET 이였다.
일단 ScinitillaNET의 코드를 특별히 수정할 필요는 없었고, Binary 파일( http://scintillanet.codeplex.com/releases/view/34393#DownloadId=88753 )을 직접 받았다. 이 구성요소를 가지고 프로그래밍을 하려면, 최소한 SciLexer.dll 파일이 System32 에 위치해야 한다. 그리고 ScintillaNet.dll 파일을 프로젝트에 Reference를 걸어주면 된다. 물론 배포 할 때는 저 두 개의 파일이 실행되는 파일과 같은 경로에만 있으면 된다.

그래서 한번 돌려봤더니..

image_4

특정 경로의 파일을 열고, Start 하면 된다. 중간에 화면 Clear가 필요하면 Clear 로그를, Log 파일 내용을 완전히 지우고 싶으면 Trunc 로그를 하면 된다.

사용법은 그렇게 어려운편은 아니니 Pass.

소스 파일과 실행파일 묶음은 첨부로 올린다.
아, 이거 돌릴려면 최소한 .NET Framework 2.0 이상이 설치되어 있어야 한다.

728x90

.NET에서 Debug 관련해서 할 때, Visual Studo 를 사용하다 보면, 현재 실행 위치를 기반으로 실행 순서를 확인할 수 있습니다. Call Stack 이라는 이름의 창으로 그 안으로 보면, 어느 부분에서 어떻게 실행되었는지, 해당 코드는 어떤 파일이며, 몇번째 라인에서 실행했는지 등을 확인 할 수 있습니다.

그림에 있는 Call Stack 까지는 아니지만, 최소한 어떤 함수에서 어떤 함수로 불렸는지 확인하는 방법이 있습니다.이 때 사용하는 것이, System.Diagnostics.StackTrace 라는 클래스 입니다.

이 클래스를 생성한 뒤, GetFrames() 라는 함수를 부르면, 그 메소드를 호출한 위치의 Thread를 기준으로 Call Stack 내용을 끄집어 낼 수 있습니다. 이 때 가져오는 형태를 StackFrame이라고 하는데, 이것을 Array 형태로 가져옵니다.

이 Array를 열어 GetMethed() 한 뒤, Name을 끄집어 내면 해당 실행 모듈의 이름을 꺼낼 수 있습니다.
위의 Flow를 이용하여 간단한 소스를 나타내면 다음과 같습니다.


System.Diagnostics.StackTrace stacks = new System.Diagnostics.StackTrace(); 
System.Diagnostics.StackFrame[] frames = stacks.GetFrames(); 
foreach (System.Diagnostics.StackFrame frame in frames) 
{ 
      System.Diagnostics.Debug.Write(frame.GetMethod().Name); 
      System.Diagnostics.Debug.Write(" <- " ); 
} 
System.Diagnostics.Debug.WriteLine(" ");

그러면 현재 호출된 메소드를 기준으로 표시됩니다.
필요하면 Method에 개체를 이용해서 Assembly를 빼거나, 기타 소스 코드들을 따라 들어가면, 원하는 정보들을 쉽게 뽑아낼 수 있을 것입니다.

728x90

정확히는 버튼이 사라지는 문제는 아니고, 단지, Focus가 된 부분만 버튼이 보이는 문제를 의미한다.

VGridControl 에 ButtonEdit를 가져다 붙인 것인데, 이상하게 Focus 가 된 줄만 버튼이 보이고, 나머지는 보이지 않는다. 다른 줄에 Focus를 보내면 그제서야 나온다는…

이 속성 값이 어디서 설정하는 것인지 한 참을 찾다가, DevExpress의 Support 페이지에서 찾았다.
(http://www.devexpress.com/Support/Center/p/Q96026.aspx)
Foucs가 안가더라도 모두 보이게하는 방법을 찾고 있었다.

간단했다. Grid 개체에 ShowButtonMode 라는 Property에 ShowAlways로 설정하면 되었다.
코드로 표기하면 아래와 같다.

gridCtrl.ShowButtonMode = DevExpress.XtraVerticalGrid.ShowButtonModeEnum.ShowAlways;

그러면 원하는 형태인 모든 Row에 해당 컨트롤들이 보인다.

728x90

출처 : 이선우 과장님.

.NET 응용 프로그램에 app.config 라는 설정을 넣는 부분이 있다.(ASP.NET의 web.config과 유사). 응용 프로그램이 최초 실행될때 기본적으로 설정할 때 사용되는 값들인데, 이 부분을 직접 Text로 열어 편집하곤 했다.

appsettings_view
이 부분을 직접 편집하는 것도 방법이겠지만, Resource 편집하듯 설정하는 방법이 있다.
솔루션 목록에서 윈도우 응용 프로그램 프로젝트 위에서 속성을 클릭하면 응용 프로그램 속성창이 뜨는데,
그 중 Settings 탭에 위치한 항목이 바로 그것이다.

property_settings

그런데 저 Type을 보면 알겠지만, .NET에서 제공되는 형만 존재한다.
만일 enum 형태로 사용자가 만든 별도의 형이 있다면? 그것을 사용하는 방법이 있다면?

바로 그것이다.예를 들어보자.만일 다음과 같은 enum이 존재한다면..

enums_example

TestType 이라는 형태로 저 Settings에 표현하려면??

물론 위와 같은 TestType을 먼저 선언한다.
그리고 난 뒤, 아까 Settings 에 들어가도록 한다. 그리고 Type 부분의 콤보 박스를 클릭한다.

settings_types

클릭하게 되면 여기서 사용가능한 Type들이 나열된다. 그러나 우리가 원하는 Type은 없다.
이제 맨 아래쪽에 있는 Browse... 를 선택하도록 한다.
이제 Select a Type 이라는 항목을 볼 수 있다. 여기서 아까 선언했던 enum을 찾도록 한다.
selectappsettingtype
찾았으면 선택한 뒤 OK를 클릭한다.

그리고 원하는 값을 선택한 뒤, 저장한다.
selectsettingsvalues

 

자! 그런데 여기서 문제 그 하나.

먼저 위에서 처럼 enum을 선언했는데, browse를 해도 그 enum을 찾을 수 없는 경우.
이 부분 때문에 이선우 과장님이 이리저리 헤매다가 그 차이점을 밝혔다.
즉 저 enum 선언은 반드시 app.config에 걸리는 응용 프로그램 외에 설정해야 된다는 것이다.
다시 말해 만일 app.config가 TestApp 라는 응용 프로그램에 존재한다면, Class Library 프로젝트를 별도로 만들어
그 안에서 선언해야 된다는 것이다.

correcteddefine

지금 필자가 구현한 코드 부분을 예로 든다면, 실제 실행되는 응용 프로그램이 TwainGui. 즉 app.config는 저 안에 있다. 하지만, enum은 별도의 Class Library 프로젝트인 TwainLib 라는 위치에 있다. 그것을 선언한 것.

저렇게 만들어 컴파일이 정상적으로 된다면, TwainGui에서 참조를 걸어 놓으면 위의 예제처럼 Browse 할 때 저 enum을 볼 수 있다.

 

이걸로 땡일까? 부부~ 이제 그 문제 2.

사용자 정의된 이 특수한 Type에 대한 안의 값을 선택하는 콤보 부분을 주목하자.
correcteddefine2 
아주 자연스럽게 나타나는데, 실제로 그럴까?

10이면 10, 100이면 100 대부분 아래와 같이 Type 목록으로 나오지 않고, 달랑 한개의 값만 표시된다.

correcteddefine3

실제로 그 안의 값을 열어보면, 마치 빈 TextBox 마냥 직접 사람이 입력하게 만든다.
말이 쉽지 실제로 그 값들이 기묘한 문자열이라면 찾기 무리.
처리 방법은 매우 간단하다. 일단 위의 값을 그대로 저장한 상태로 컴파일을 완료한다.
그리고 Visual Studio을 껏다가 다시켠다. 그리고 프로젝트 Reload.

즉 프로젝트를 Reload 함으로써 Reset이 되어야 올바른 값 목록이 나온다는 것이다.

일단 여기까지!

728x90

사실 전역변수 처럼 쓰이는 각종 응용 프로그램 설정 내역들이 있다.

보통은 app.config 혹은 web.config 를 통해 값을 읽어오게 되는데,

그 로직 아무리 짧아야, 2~3줄씩 되고,

설정이 필요할 때 마다 app.config 혹은 web.config에서 일일히 읽어오는 것도 나름대로 곤욕이다.

그러기 위해 Sigleton 패턴을 사용하는게 제일인듯.

 

그런데, 이런 Singleton 패턴은 Windows 응용 프로그램 같은 경우야,

하나의 인스턴스니 상관 없지만, 웹 응용 프로그램같은 경우에는 조금 난감한 것도 사실.

 

이에 현재 나름대로 고민해서 짜본 방법이 아래와 같다.

 

public static class ConfigManager()

{

        public static string TempFileLocation

        {

                get

                {

                          string sResult = string.empty;

                          try

                          {

                                 sResult = ConfigurationManager.AppSettings["tempfolder"];

                          }

                          catch

                          {

                           }

                           return sResult;

                 }

 

         }

}

 

저렇게 만들면 ConfigManager를 일일히 new 할 필요가 없다. Heap이 아닌 응용 프로그램 저장 위치에 단 한개의 인스턴스만 존재하므로, 최소한 이 부분을 띄워주는데에서는 무조건 저 한개의 로직에서 처리가 된다.

저 방법의 핵심은 static 인데, static으로 정의되는 내용은 어쨌던 별도의 Instance 생성이 필요없다는 훌륭한 강점을 가지게 된다.

 

그런데, 설정 구성이 많아지게 되면 그 만큼 코드도 무척 길어지게 된다. 처음 설정 내역이 4~5개 까지는 그럭저럭 봐주는데, 설정 내용이 20여개를 넘자, 매번 저렇게 구성하는것도 환장하겠고, 더욱이 appsetting의 Key 값이 변경될때도 나름 고역. 
더욱이  매번 appsetting 에서 값을 읽어오는게 영 마음에 꺼림찍했다.(NET 프레임워크 개발한 분들도 나름 천재들이니, 옵티마이징 하면, 저 로직도 나름 정리가 잘 되리라 생각은 하지만)

그럼 데이터를 1회만 읽어오고, 모두 한자리에 때려 박는 방법을 다시 생각했다.

public static class ConfigManager()

{

       static ConfigManager()

       {

                try

                {

                        ConfigManager.tempFolderLocation =
                                     ConfigurationManager.AppSettings["tempfolder"];

                }

                catch

                {

                }

         }

 

        static string tempFolderLocation;

        public static string TempFileLocation

        {

                get

                {

                          return ConfigManager.tempFolderLocation;

                 }

 

         }

}

 

즉 static 클래스 안에 Constructor를 만들어서 그 안에서 1회 읽어오게 하고,

실제 일반 사용자가 사용하는 부분에서는 static으로 저장된 변수 값만 읽어가게 되는 것이다.

직접 XML이나, INI 파일 파서를 만든 상태라면, 그 로직을 Constructor에 만들고

구성하면 되는 것이다.

즉 핵심은 static 클래스에서 static 생성자를 만드는 것!. 이게 핵심.

728x90
삼각함수를 이용하여 좌표계를 계산하는 로직을 정리했다.
리펙토링 건덕지가 무척 많아 솔직히 손을 많이 대야 겠지만,
그래도 나름대로 작성한 부분이 있어 정리한다.

만든 내용을 정리하자면, 사각형 두개를 그린 뒤, 해당 사각형의 중심좌표를 구한다.
그리고 그 중심좌표들을 양끝으로 하는 선을 긋는다.
이 때, 선과 사각형이 만나는 좌표를 구하는 공식을 만들어봤다.


이 작업의 시작은 시작점과 끝점으로 연결된 직선을 빗변으로한 삼각형이라고 생각한 뒤,
각도를 구해야 한다. 삼각형의 특정 부위의 값만 구하면 각도 구하는 방법이 무척많다.
이 때 바로 등장하는게 삼각함수 였던 것이다.

맨 먼저 가정 부터 시작한다.
2개의 사각형이 있고, 좌표계에서 위치와 크기를 정확히 알고 있다는 데서 시작한다.
사각형은 총 4개의 점에서 출발하는데, 반드시 직각사각형이며,
각 좌표 값은 직관적 계산을 통해 얻어 올 수 있어야 한다. (한 점과 너비, 높이만 알면 사각형이 만들어진다.)
아래의 그림의 사각형은 특정좌표 값을 이미 가지고 있다는 가정에서 출발한다.
(컴퓨터로 그래픽 객체를 다루어보았다면 쉽게 알 수 있다.)

각 좌표나 값들이 정의되었으면, 이제 해야 하는 것은 각도를 구하는 것이다.
구해야 되는 각도는 radian 이라고 하는 삼각함수 계산용 각도다.
(일반 각도랑 틀림 : 참고 -> 위키피아 라디안 )



이 라디안을 구하기 위해서는 아크 탄젠트라고 불리는 삼각함수를 써야 한다.
보통 탄젠트 = 높이 / 밑변 으로 계산된다. 이 때 탄젠트에 걸친 각도 값을 구하기 위해서는 그의 역함수인
아크 탄젠트를 써야 한다. 즉 arctan(높이/밑변) 하면 radian 값이 나오게 된다.


자 이제 각도를 구했으니, 실제 목적인 사각형과 직선과 만나는 위치에 대한 좌표를 구해야 한다.
최소한 좌표 중 X 좌표는 구할 수 있다. 사각형의 중심점에서 사각형 너비/2 를 빼면 된다.
그러면 X 좌표가 나온다. 그러나, Y 좌표는 그냥 찍으면 모를까, 정확한 값은 나오지 않는다.
이 때 실제적인 삼각함수를 적용한다.

여기서 우리가 아는 값은 알고 싶은 좌표의 X 좌표. 그리고 각도(Radian 값이다.)이다.
이 두개의 값을 이용해서 뽑는 방법을 찾아보자.


먼저 알고 싶어하는 Y 좌표를 길이로 생각하자. 중심점을 기준으로 일정 양만큼 올라가면,
Y 좌표가 나오게 된다. 이 때 일정 양을 b' 라고 한다. 즉 좌표 값이 아닌 길이로 생각하는 것이다.

마찬가지로 중심점을 기준으로 X 좌표간의 차이를 a' 라고 한다.

잘 보면, 삼각형이 다시 만들어진다. a'가 밑변, b'가 높이인 형태의 삼각형인 것이다.
이를 tangent를 이용해서 값을 구하는 것이다.

tangent의 공식을 보면 이렇다.
tan(radian) = 높이 / 밑변.

이 중 우리가 구해야 할 값이 높이라고 할 때, 그 값을 b' 라고 하면,

tan(radian) = b' / 밑변.

이 값들을 우리가 알고 있는 값들로 치환하면,

tan(R < -이건 앞의 아크 탄젠트로 구했다.) = b' / a'

이걸 양변에 a'를 곱하면,

a' * tan(R) = b'

끝.

그래서 구한 b' 값을 중심점 좌표의 Y에서 b' 만큼 빼거나 더하면 된다.


앗.. 여기서 중요한 점.
b' 값을 더하거나 빼야 한다고 했는데, 그 기준이 무척 중요하다.
언제 빼고 언제 더해야 할까?

사각형을 수평으로 반으로 나눈 다음, 직선이 위를 바라보면 뺀다.
역으로 아래를 바라보면 더하면 되는 것이다.
(이 부분은 수학적으로 판단하기 보다, 컴퓨터 그래픽 좌표계로 판단하면 쉽다.)

아래의 그림은 위의 공식을 이용해 계산된 결과 값이다.
까만색 상자에서 출발해서 흰색 상자에서 끝난다.
직선은 각 상자의 중심점을 연결했다.
위의 계산식의 결과로 나온 점을 찍어보면,
직선과 검은색 상자가 만나는 부분이 빨강색 점처럼 나타나게 된다.






protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    Graphics gc = e.Graphics;

    Pen pen = new Pen(Color.Green, 1.5f);

    int nDirection = -1;

    float nWidth = 150f;
    float nHeight = 80f;

    PointF posBox1 = new PointF(30f, 40f);
    PointF posBox2 = new PointF(330f, 110f);

    gc.DrawRectangle(Pens.Black, posBox1.X, posBox1.Y, nWidth, nHeight);
    gc.DrawRectangle(Pens.Ivory, posBox2.X, posBox2.Y, nWidth, nHeight);

    PointF centerBox1 = GetCenter(posBox1.X, posBox1.Y, nWidth, nHeight);
    PointF centerBox2 = GetCenter(posBox2.X, posBox2.Y, nWidth, nHeight);

    nDirection = GetDirection(centerBox1, centerBox2);

    PointF newPos = GetSourcePos(centerBox1, centerBox2, nWidth, nHeight, nDirection);

    gc.DrawRectangle(Pens.Red, newPos.X - 2, newPos.Y - 2, 4, 4);

    gc.DrawLine(Pens.Salmon, centerBox1, centerBox2);


    pen.Dispose();

}

PointF GetCenter(float X, float Y, float Width, float Height)
{
    PointF point = new PointF(X + Width / 2, Y + Height / 2);
    return point;
}

int GetDirection(PointF pos1, PointF pos2)
{
    // Direction Number.
    //
    //            0
    //         7     1
    //       6         2
    //         5     3
    //            4
    //
    // Direction을 판단 할 수 없는 경우 ( 같은 좌표위에 있는 경우 ) -1을 돌림.


    if (pos1.X == pos2.X)
    {
        if (pos1.Y > pos2.Y)
            return 0;   // North
        if (pos1.Y < pos2.Y)
            return 4;   // South
    }
    if (pos1.Y == pos2.Y)
    {
        if (pos1.X < pos2.X)
            return 2;   // East
        if (pos1.X > pos2.X)
            return 6;   // West
    }
    if (pos1.X < pos2.X)
    {
        if (pos1.Y > pos2.Y)   
            return 1;   // North-East
        if (pos1.Y < pos2.Y)
            return 3;   // South-East
    }
    if (pos1.X > pos2.X)
    {
        if (pos1.Y < pos2.Y)
            return 5;   // North-West
        if (pos1.Y > pos2.Y)
            return 7;   // South-West
    }
    return -1;
}

float GetDeltaY(float a, float b, float nWidth)
{
    double rad = Math.Atan((double)(b / a));
    float result = (float)((nWidth / 2) * Math.Tan(rad));
    return result;
}

PointF GetSourcePos(PointF srcCenter, PointF tgtCenter, float Width, float Height, int nDirection)
{
    PointF pos = new PointF(srcCenter.X, srcCenter.Y);
    float a = Math.Abs(tgtCenter.X - srcCenter.X);
    float b = Math.Abs(srcCenter.Y - tgtCenter.Y);
   
    switch (nDirection)
    {
        case 0:
            pos.Y -= Height / 2;
            break;
        case 1:
            pos.X += Width /2;
            pos.Y -= GetDeltaY(a,b, Width);
            break;
        case 2:
            pos.X += Width / 2;
            break;
        case 3:
            pos.X += Width / 2;
            pos.Y += GetDeltaY(a, b, Width);
            break;
        case 4:
            pos.Y += Height / 2;
            break;
        case 5:
            pos.X -= Width / 2;
            pos.Y += GetDeltaY(a, b, Width);
            break;
        case 6:
            pos.X -= Width / 2;
            break;
        case 7:
            pos.X -= Width / 2;
            pos.Y -= GetDeltaY(a, b, Width);
            break;
        default:
            break;
    }
    return pos;
}
PS. 예전에 삼각함수 따위는 어디다 써~ 하면서 내팽겨 쳤는데, 아주 곤혹스러운 상태다.
(특히 그래픽 할때.). 결국 삼각함수 책을 하나 사서 봤는데 은근 도움이 많이 되었다.
그래도 한 때 배운 가락이 있어 기억 되살리면서 하나씩 조립해보고 있다.
(삼각함수에 대한 값은 컴퓨터가 알아서 계산 해주니깐 공식만 잘 알면 된다. )

나중에 그래픽 관련(게임을 만들든 뭘 하든) 프로그래밍을 할 생각이면 삼각함수 기초 부터 한번 다시 살펴봐야 할 것 같다.
728x90

+ Recent posts

728x90