using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Text.RegularExpressions;
R = rgbInputR.Match(colorX); G = rgbInputG.Match(colorX); B = rgbInputB.Match(colorX); //had to flip the R and B ??? b =int.Parse(R.Groups[0].Value); g =int.Parse(G.Groups[0].Value); r =int.Parse(B.Groups[0].Value); } } }
아이폰 앱 개발을 완료 하고 나서, QA 를 위해서 주변 지인 분들이나, 사내 QA 팀에 앱을 배포해야 할 때가 있습니다. 이때 많이 사용하는 방법이 앱을 AdHoc 방법으로 배포를 하는 것입니다. (AdHoc 배포 파일을 만드는 방법은 여러 다른 분들께서 설명을 많이 해 주셨으니, 이번 포스팅에선 넘어갑니다. ) 그런데 이 AdHoc 배포가 여간 불편한게 아닙니다. 저도 그동안 AdHoc 파일을 iPhone 에 설치 하기 위하여 아래 와 같은 절차를 밟았습니다.
AdHoc 파일을 다운로드 받는다.
아이폰과 동기화 되어 있는 iTunes에 설치한다.
아이폰과 동기화 한다.
위 절차가 번거로운 이유는 2번 때문입니다. 꼭 동기화 되어 있는 iTunes 가 필요하기 때문이지요. 하지만, 이번에 소개하는 툴을 사용하면 iTunes 동기화 없이도 AdHoc 파일을 아이폰에 설치 할 수 있습니다.
Ogre로 프로젝트를 하면서 가장 시간을 많이 들였던 충돌 처리 부분 입니다. 처음에는 물리 엔진을 써보고자 Physx , bullet, OgreODE 등 많은 물리엔진을 찾아서 사용 해보려 했지만...;; 결국 Ogre로 구현을 하게 되었습니다. ;; 게임 개발에 필요한 수학적 지식이 부족한 상황에서 검색을 하던중 directx 로 구현한 OBB 충돌 소스를 찾게 되어서 그 소스를 이용하여 Ogre에서 구현을 해봤습니다.
dx 소스는 GpgStudy 에서 참고 하였습니다. Link에 추가 해놓으테니까 참고 하시면 좋을 것 같습니다~~ 그리고 이만희님의 OBB 충돌 논문(Fast Overlap Test for OBB) 을 보시면 그래도 이해더 좀더 되 실 겁니다. 첨부 파일로 올려 놓겠습니다.(올려도 되려나??)
Vector3 obb1_center, obb2_center, T, LL; //box1,box2 의 각각 센터 좌표, Real box_len, a1, a2, a3, b1, b2, b3, TL; Matrix4 obb1_invers_mat, obb2_rotae_mat; Matrix4 R ;
//OBB 박스의 월드 좌표?? obb1_invers_mat = OBB1->getCharMat.inverse(); obb2_rotae_mat = OBB2->getMonMat();
//box1 의 좌표계를 box2의 좌표계로 회전변환 행렬 R = RA-1 * RB(-1은 iverse) R = obb1_invers_mat * obb2_rotae_mat;
//box의 좌표축의 normal vector x, y, z 값 (제가 이해한 내용 - 틀린 내용 일 수도 있음 ㅋ)
//box1 의좌표계에서 box1 중심에서 box2의 중심으로의 이동을 나타내는 vector3 T = Vector3(obb1_center.x - obb2_center.x, obb1_center.y - obb2_center.y, obb1_center.z - obb2_center.z);
구현을 해서 실행을 시켜본 결과 충돌 검출은 잘 하는데 살짝 떨어져 있어도 충돌 체크를 하는 경우가 있는데, 이유는 저도 잘...ㅠㅠ 그래도 이렇게해서 충돌 체크를 한다는거에 감사할 따름입니다. ㅋㅋ 혹시 소스 자체에 수정 할 부분이 있다고 생각되시는 분은 가르침 부탁 드리겠습니다^^ㅋ
인증샷!!!!
Ps. box의 Matrix를 받아 오는 함수를 사용해서 Matrix값을 받아오게 했었는데, 값이 이상 했나 보네여 ;; 충돌 처리가 정확히 되지 않았습니다. 그래서 객체의 Entity 의_getBoneMatrices.transpose()를 사용해서 Matrix값을 받아 와서 충돌처리를 했더니 정확하게 OBB의 충돌 위치에서 멈추는 것을 확인 할 수 있었습니다.
아직 정확한 Ogre의 분석이 되지 않은 상태에서 이것 저것 해보다가 얻어 걸린 것이라서 정확하게 어떻다라는 것을 제가 말씀 드릴 수는 없을 것 같습니다. 이해해 주시길..^^;; ㅋㅋ
(소스에서 이상한점을 발견 하시거나 잘못 된 곳을 발견하시면 저에게도 살포시 알려주세요~ㅋㅋㅋ)
저는 면접을 많이 경험하지 못했습니다. 정확히 면접의 지원자가 되는 경험이 많지 않았습니다. 수많은 면접을 겪어야 했던 사람들에게 이것은 매우 부러운 일일 겁니다.
하지만 면접에 성공한 후 면접으로 사람을 평가해야하는 심사위원이 되면 오히려 이러한 면접 경험의 빈곤을 안타깝게 생각할 겁니다. 무엇보다 지원자들이 밀물처럼 들어와 제발 자신을 뽑아만 달라고 할 거대 게임 회사의 심사위원이 아닌 이름 없는 회사에 작은 프로젝트의 프로듀서로 개발자들을 뽑아야 하는 상황에서는 말입니다.
이런 경우 지원자의 등장 자체가 감사한 일이며 지원자가 제발 능력있는 훌륭한 사람이기를 하는 바람과 그런 지원자가 등장했을 때 부디 다른 회사의 유혹을 뿌리치고 우리 회사로 무사히 출근해 주기만을 바라게 됩니다.
이제 지인들과 회사를 설립한지 5년이 되고 있습니다. 처음 프로듀서로 게임 프로젝트를 시작해 사람들을 뽑아야 할때에는 적극적으로 자신의 역량과 가능성 그리고 합격을 갈망하던 면접자들이 정작 합격하더라도 출근 직전 입사를 포기하는 경우가 많았습니다.
이런 일이 반복되는 것을 느끼며 면접을 바꿔보기로 했습니다. 바로 많지 않은 경험이었지만 지원자로 면접에서 느꼈던 감정을 그리고 바로 그 지원자의 입장에서 어떤 면접을 기대하는지 고민하기 시작했습니다.
제가 피상적으로 판단하고 있던 그동안의 서투른 면접에서 제가 잘못 판단하고 있었던 것은 면접이 단순히 "지원자를 평가하는 자리"라는 것 입니다. 사실 면접은 면접자와 심사위원의 단방향의 관계로만 진행되는 것이 아닙니다. 심사위원은 물론 지원자를 평가하겠지만 반대로 지원자도 심사위원을 통해 회사를 그리고 자신의 미래를 판단한다는 것 입니다.
이러한 점을 깨달은 이후 면접은 많이 달라졌습니다. 지원자를 최대한 정확히 평가하는 것 뿐 아니라 지원자가 최대한 훌륭한 선택을 할 수 있도록 면접을 진행하기 시작했습니다. 그가 가진 능력을 묻는 것 보다 그의 선택의 이유를 묻기 시작했고 무엇이 되고 싶은지 묻기 시작했습니다. 이것은 오히려 지원자를 제대로 평가할 수 있는 질문과 대화들이 되었습니다.
그리고 지원자의 훌륭한 판단을 돕기 위해 그가 선택하고자 하는 이 회사의 본질과 목표를 그리고 함께 했을때 이뤄나갈 수 있는 비전을 제시하기 시작했습니다. 그리고 이러한 과정에서 지원자가 아무리 뛰어난 능력을 가졌다 하더라도 그의 선택이 그에게 좋다고 판단되지 않으면 과감히 돌아가 다시한번 생각해 보라고 하기 시작했습니다. 그리고 만약 합격이 통보되어도 거절 의사를 밝히라고 말하기 시작했습니다. 결국 면접은 심사위원으로써 저의 질문 50% 그리고 지원자의 질문 30% 그리고 토의나 토론이 20%의 비중을 이루기 시작했습니다.
이 용감한 행동은 처음 면접을 준비하며 읽은 몇권의 면접 참고 도서에서도 이야기하지 않은 것 이었습니다. 그리고 모두가 잘 알듯 사람은 자신이 선택한 일에 책임감을 느끼며 그에 걸맞는 행동을 한다는 것 입니다. 이후 합격자들의 입사 취소는 없어지다 시피 했습니다.
그리고 더 좋은 일도 벌어졌습니다. 합격한 멤버들은 여러 난관과 어려움 속에서도 오랜 시간 동안 그리고 지금 까지도 함께 꿈을 향해 뛰어나가고 있습니다. 게임 프로젝트에서 멤버들의 이직은 꽤 비일비재하게 벌어집니다. 하지만 일반적인 면접을 통해 수동적인 합격으로 함께 하게 된 멤버와 달리 스스로 회사를 선택한 면접의 멤버들은 보다 자기자신에게 엄격해 졌습니다. 이탈이 적었으며 보다 능동적으로 일을 하기 시작했습니다.
또하나 좋은 점은 이러한 면접을 통해 심사위원인 제 자신이 지원자들을 통해 많은 것들을 배울 수 있게 되었다는 겁니다. 제가 뽑고자 하는 부분의 일을 해나가는 사람들이 어떤 목표를 가지고 있는지 그리고 어떤 노력을 해오고 있는지 어떤 궁금함이 있는지 말입니다. 이를 통해 제가 뽑고자 하는 업무의 본질을 보다 깊게 파악할 수 있을 뿐 아니라 이후 합격자와 어떤 일들을 어떻게 해나가야 할지를 가늠하고 계획할 수 있는 시간이 되었습니다.
종종 면접이 보여주는 표면적인 관계를 악용해 면접을 통해 자신의 기득권을 과시하는 심사위원을 종종 만나게 됩니다. 또는 면접자의 본질을 파악하기 보다 자신이 요구하는 기능만을 확인하는 경우도 많습니다. 이런 여러가지 방식들은 각 심사위원들의 성향 이라고 하더라도 꼭 잊지 않아야 한다고 생각하는 것이 바로 면접은 심사위원의 선택이 아니라 바로 "면접자의 선택과정"이기도 하다는 것 입니다.
면접의 전문가와 선배 프로듀서들의 생각과 다를지도 모르지만 지금까지 게임 프로젝트를 진행하며 면접과정을 통해 제가 배운 것은 "나는 팀원들 보다 우월한 존재로 면접은 그들을 판별하거나 선별하는 과정이 아니라 파트너를 찾는 과정이며 파트너의 올바른 선택은 나의 올바른 선택만큼 중요하다." 입니다.
Note that for non-relative mouse movement (i.e. if MOUSEEVENTF_ABSOLUTE is not specified as part of dwFlags), negative values for dx and dy are desirable. As such, the "uint" type specification for C# can be safely replaced with Int32.
//Use the values of this enum for the 'dwData' parameter //to specify an X button when using MouseEventFlags.XDOWN or //MouseEventFlags.XUP for the dwFlags parameter. public enum MouseEventDataXButtons : uint { XBUTTON1 = 0x00000001, XBUTTON2 = 0x00000002 }
VB.Net Signature:
This function does indeed return a value, just as the keybd_event API does.
If there is a real error, it will in fact return a value of false, or zero.
The dwExtraInfo appears to be a ULONG_PTR in C++ (IntPtr in VB.NET)
Declare Function apimouse_event Lib "user32.dll" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean
Notes:
FYI, Microsoft tells us for "Windows NT/2000/XP: This function has been superseded. Use SendInput instead."
The C# code below works fine. However you have to keep in mind to add the namespace "System.Runtime.InteropServices" and keep in mind to write the code into a class.
Original contributor tells us:aa
I wanted to emulate the scroll. Searching for this information wasn't easy ... but here is how you do the mouse scroll button
The scroll value can actually be any value larger than 1, if used within a loop.
This allows you to smoothly increment the scrollbar, instead of relying on the inconsistent wheel delta,
which is a variable limited by the user, for mouse wheel. Start-Control Panel-Mouse-Wheel-Scrolling
VB.NET Sample Code:
Const MOUSEEVENTF_WHEEL As Int32 = 2048 Const MOUSEEVENTF_WHEEL_DELTA As Int32 = 120
Private Declare Function apimouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean Private Declare Function apiGetMessageExtraInfo Lib "user32" Alias "GetMessageExtraInfo" () As Int32
Private Sub PlayScroll(ByVal number As Int32, Optional ByVal increment As Int32 = 2) On Error Resume Next For i As Int32 = 1 To number apimouse_event(MOUSEEVENTF_WHEEL, 0, 0, increment, apiGetMessageExtraInfo) Next End Sub
C# Sample Code:
[DllImport("user32.dll")] static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
This code assumes a form called frmMain with a command button called cmdClick a picture box called picClicker and a text box called txtResults
Note Twips are no more. Also, I stripped the FOR loop of delta moves from the command button click to the middle of the picture box.
Option Explicit On
Friend Class frmMain
Inherits System.Windows.Forms.Form
Declare Auto Sub mouse_event Lib "user32" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As IntPtr)
Const MOUSEEVENTF_MOVE As Int32 = &H1 ' mouse move Const MOUSEEVENTF_LEFTDOWN As Int32 = &H2 ' left button down Const MOUSEEVENTF_LEFTUP As Int32 = &H4 ' left button up Const MOUSEEVENTF_RIGHTDOWN As Int32 = &H8 ' right button down Const MOUSEEVENTF_RIGHTUP As Int32 = &H10 ' right button up Const MOUSEEVENTF_MIDDLEDOWN As Int32 = &H20 ' middle button down Const MOUSEEVENTF_MIDDLEUP As Int32 = &H40 ' middle button up Const MOUSEEVENTF_ABSOLUTE As Int32 = &H8000 ' absolute move Const MOUSEEVENTF_WHEEL As Int32 = &H800 ' wheel button rolled
' Simulate moving the mouse to the center of the ' PictureBox and clicking. Private Sub cmdClick_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdClick.Click Dim cur_x As Single Dim cur_y As Single Dim dest_x As Single Dim dest_y As Single
' mouse_event moves in a coordinate system where ' (0, 0) is in the upper left corner and ' (65535,65535) is in the lower right corner.
' Get the current mouse coordinates and convert ' them into this new system. cur_x = System.Windows.Forms.Cursor.Position.X * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width cur_y = System.Windows.Forms.Cursor.Position.Y * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height
' Convert the coordinates of the center of the ' picClicker PictureBox into this new system. Dim pt As Point = picClicker.PointToScreen(New Point(picClicker.ClientRectangle.Width / 2, picClicker.ClientRectangle.Height / 2))
' Move the mouse to its final destination and click it. mouse_event(MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE + MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, dest_x, dest_y, 0, 0) End Sub
Private Sub picClicker_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles picClicker.Click txtResults.Text = txtResults.Text & "MouseClick" & vbCrLf End Sub
Private Sub picClicker_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picClicker.MouseDown txtResults.Text = txtResults.Text & "MouseDown (" & e.X & ", " & e.Y & ")" & vbCrLf End Sub
Private Sub picClicker_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picClicker.MouseUp txtResults.Text = txtResults.Text & "MouseUp (" & e.X & ", " & e.Y & ")" & vbCrLf End Sub
Dim eMouse As New System.Windows.Forms.MouseEventArgs(Windows.Forms.MouseButtons.Left, 1, pt.X, pt.Y, 0)
Me.OnMouseDown(eMouse)
Me.OnMouseMove(eMouse)
Me.OnMouseUp(eMouse)
to work as desired. Although it did trigger mouse events in the form showing the movement and click action desired, it didn't move the mouse pointer on the screen nor did it trigger events in the picture box located at pt.X, pt.Y
Thus I have resigned myself to unmanaged code for now. I will post the SendInput version shortly as mouse_event has been deprecated by Bill in favor ofSendInput.
As the original contributor noted:
You can use the System.Windows.Forms.Cursor.Position property to set the position of the mouse, if you would like.
You will note I have replaced the GetCursorPos calls in the original VB source with this as suggested in the MSDN URL I mention above.