공식 : distance = 루트((x1-x2)제곱 + (y1-y2)제곱)


code :
 
point getDistance(point)
{
    return math.sqrt(point.x * point.x + point.y * point.y);
}

point delta = point(이동좌표.x - 현재좌표.x, 이동좌표.y - 현재좌표.y);
point distance = getDistance(delta); //두 지점간의 거리
int duration = distance / 속도        //이동시간


중심점에서 x,y 좌표

x = cos(각도) * 거리

y = sin(각도) * 거리

Posted by 명혀니
,


참 웃기지 말야....

얼마전 면접 보면서 FSM이 뭔지 아냐고 물어봐서
난 모른다고 했는데....

다 내가 코딩하면서 쓰던 설계방법이라니 말야...ㅋ

팩토리 패턴이나 그외 패턴들도 그렇구....

너무 이론보다 코딩중심으로 공부를 해서 그런가...ㅋ


아무튼 다 집어치우고...


말 그대로 각각의 상태를 정의하는것..ㅋ


내가 쓰던 패턴대로 예제를 작성해 보겟슴ㅋ

enum PLAYER_STATE =
{
  PSTATE_IDLE = 0,
  PSTATE_MOVE,
  PSTATE_WALK,
  PSTATE_JUMP,

  PSTATE_COUNT
}


class CPlayer
{
CPlayer() { m_nState = PSTATE_IDLE; }

PALYER_STATE m_nState;

PLAYER_STATE getState() { return m_nState; }
void setState(PLAYER_STATE nState) { m_nState = nState; }
..........
}


class CGameManager
{
CPlayer* pPlayer;

void onProcessing();

void onProcessIdle();
void onProcessMove();
void onProcessWalk();
void onProcessJump();
}



void OnProcessing()
{
  switch(pPlayer->getState())
{
  case PPLAYER_IDLE:
    onProcessIdle();
    break;

  case PPLAYER_MOVE:
    onProcessMove();
    break;

  case PPLAYER_WALK:
    onProcessWalk();
    break;

  case PPLAYER_JUMP:
    onProcessJump();
    break;
}



대충 요런식? -_-ㅋ
Posted by 명혀니
,
함수 인자로 함수를 넘겨 줄 수 있습니다. (정확히는 함수의 시작주소를 넘겨줌)
http://codepad.org/yawaDRbI


void fooA(void){ printf("함수 A\n"); }
void fooB(void){ printf("함수 B\n"); }
void fooC(void){ printf("함수 C\n"); }

void foo(void (*fp)(void)){ fp(); }

int main(void)
{
        foo(fooA);
        foo(fooB);
        foo(fooC);
        return 0;
}

유의해야 할 점은 리턴타입 / 매개변수 타입을 맞춰주어야 한다는 것이빈다.

이런식으로 사용이 가능하다는 얘기죠.
http://codepad.org/DCWCESFP

int plus(int a,int b){ return a+b; }
int minus(int a,int b){ return a-b; }

int foo(int a,int b,int (*fp)(int,int)){ return fp(a,b); }

int main(void)
{
        printf("%d\n",foo(15, 10, plus));
        printf("%d\n",foo(15, 10, minus));
        return 0;
}


물론 함수포인터도 배열로 생성 가능하니, 배열 인덱스에 따라서 switch 그딴거 없이 상황에 맞게 호출 할 수도 있습니다.
http://codepad.org/EAqooPCT

int plus(int a,int b){ return a+b; }
int minus(int a,int b){ return a-b; }

int foo(int a,int b,int (*fp)(int,int)){ return fp(a,b); }

int main(void)
{
        int i;
        int (*fp[2])(int,int)={plus,minus};
//        fp[0]=plus;        fp[1]=minus;
        for(i=0;i<2;i++)
                printf("%d\n",foo(15, 10, fp[i]));
        
        return 0;
}

아니면 일정 상황이 되었을때 해당 함수를 호출해 주는 형태로도 가능합니다.
http://codepad.org/LG9H0NDU


static int (*g_fp)(int,int);

int plus(int a,int b){ return a+b; }
int minus(int a,int b){ return a-b; }

void SetFp(int (*fp)(int,int)){ g_fp=fp; }

int foo(int a,int b){ return g_fp(a,b); }

int main(void)
{
        SetFp(plus);
        printf("%d\n",foo(15, 10));

        SetFp(minus);
        printf("%d\n",foo(15, 10));

        return 0;
}

출처 - 유리한

Posted by 명혀니
,
콜백 함수를 사용하는 많은 경우에 콜백 함수에 들어갈 인자를 정해줄 수 있다. 그런 예 중에 하나가 CreateThread인데, 쓰레드 몸통이 될 함수에 콜백 인자를 하나 줄 수 있다. 클래스의 멤버를 콜백으로 사용하지 못하는 이유가 바로 this가 없다는 점인데(콜백 함수를 호출하는 쪽에서 무슨 인스턴스의 멤버를 호출할 지 어떻게 알겠는가), 이 콜백 인자로 this를 주고 이 인스턴스에 접근하면 멤버 변수고 함수고 마음대로 쓸 수 있을 것이다.

백 마디 말보다 한 줄 코드가 낫다는 격언에 따라 코드를 풀어보면,

class ThreadObject
{
protected:
      static DWORD WINAPI _ThreadProc(LPVOID lpParam)
      {
             ThreadObject* _this=(ThreadObject*)lpParam;
             return _this->ThreadProc(_this->thread_param);
      }
      HANDLE thread_handle;
      DWORD thread_id;
      LPVOID thread_param;

      // ....
public:
      ThreadObject(LPVOID thread_param=NULL)
      {
            this->thread_param=thread_param;
            thread_handle=CreateThread(NULL,0,&ThreadObject::_ThreadProc,this,0,&thread_id);
      }
      DWORD ThreadProc(LPVOID lpParam)
      {
            //  do something
            return 0;
      }

      // ....
};

대충 이런 모양이 될 것이다.

생성자의 CreateThread에서 ThreadProc을 바로 콜백으로 줄 수 없으므로 _ThreadProc이란 더미 콜백을 주고, 그 콜백의 인자로 현재 객체의 주소(this)를 준다. 더미 콜백에선 인자로 넘어온 값을 캐스팅하여 this 포인터를 구하고 인스턴스의 멤버함수를 호출한다. 이렇게 하면 중간에 더미 콜백이 끼었지만 결과적으론 ThreadProc 멤버함수를 쓰레드 함수로 사용하는 효과를 낼 것이다.

꼭 CreateThread뿐만이 아니더라도 콜백에 인자를 줄 수 있는 경우엔 손쉽게 멤버 함수를 콜백으로 사용하도록 구현할 수 있다.

출처 : 디-
Posted by 명혀니
,

위에 몇개의 함수들 중에
이 함수가 쓰이는 것들이 있는데
깜빡하고 안올렸다 -_-;;

해당 파일이 프로세스 관리자에 올라와 있는지 찾는다 -_-

bool CUtility::getProcessModule(DWORD dwID, CString szProcessName)
 {
  HANDLE hModuleSnap = NULL;
  MODULEENTRY32 me32 = {0};

  hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwID);

  if(hModuleSnap == (HANDLE) - 1)
   return false;

  me32.dwSize = sizeof(MODULEENTRY32);

  if(Module32First(hModuleSnap, &me32))
  {
   do
   {
    if(me32.szModule == szProcessName)
    {
     CloseHandle(hModuleSnap);
     return true;
    }
   } while (Module32Next(hModuleSnap, &me32));
  }

  CloseHandle(hModuleSnap);
  return false;
 }

Posted by 명혀니
,

bool CUtility::isActiveProcess(CString szProcessName)
 {
  HANDLE hProcessSnap = NULL;
  bool bRet = false;
  PROCESSENTRY32 pe32 = {0};
  
  hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if(hProcessSnap == (HANDLE) - 1)
   return false;

  pe32.dwSize = sizeof(PROCESSENTRY32);
  if(Process32First(hProcessSnap, &pe32))
  {
   bool bCurrent = false;
   MODULEENTRY32 me32 = {0};
   do
   {
    bCurrent = getProcessModule(pe32.th32ProcessID, szProcessName);
    if(bCurrent || szProcessName == pe32.szExeFile)
    {
//      HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ProcessID);
//      if(hProcess)
//      {
//       if(TerminateProcess(hProcess, 0))
//       {
//        unsigned long nCode;
//        GetExitCodeProcess(hProcess, &nCode);
//       }
//       CloseHandle(hProcess);
//      }
     CloseHandle(hProcessSnap);
     return true;
    }
   } while (Process32Next(hProcessSnap, &pe32));
  }

  CloseHandle(hProcessSnap);
  return false;
 }

Posted by 명혀니
,

void CUtility::showWindowByProcessID(DWORD dwProcessID, LPTSTR lpszClassName)
 {
  HWND hWnd = ::GetTopWindow(0);
  DWORD dwThreadPID = 0;

  while(hWnd)
  {
   DWORD pID;
   DWORD dwThreadID = ::GetWindowThreadProcessId(hWnd, &pID);
   HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, 0, pID);

   if(dwProcessID == pID)
   {
    dwThreadPID = dwThreadID;
    char szTemp[MAX_PATH] = {0, };
    ::GetClassName(hWnd, szTemp, sizeof(szTemp));

    if(!strcmp(szTemp, lpszClassName))
     ::ShowWindow(hWnd, SW_RESTORE);
   }

   hWnd = ::GetNextWindow(hWnd, GW_HWNDNEXT);
   CloseHandle(hProc);
  }
 }

 void CUtility::showProcess(CString szProcessName, LPTSTR lpszClassName)
 {
  HANDLE hProcessSnap = NULL;
  bool bRet = false;
  PROCESSENTRY32 pe32 = {0};

  hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if(hProcessSnap == (HANDLE) - 1)
   return;

  pe32.dwSize = sizeof(PROCESSENTRY32);
  if(Process32First(hProcessSnap, &pe32))
  {
   bool bCurrent = false;
   MODULEENTRY32 me32 = {0};
   do
   {
    bCurrent = getProcessModule(pe32.th32ProcessID, szProcessName);
    if(bCurrent || szProcessName == pe32.szExeFile)
    {
     HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32.th32ProcessID);
     if(hProcess)
     {
      DWORD dwID = GetProcessId(hProcess);
      showWindowByProcessID(dwID, lpszClassName);
     }     
    }
   } while (Process32Next(hProcessSnap, &pe32));
  }

  CloseHandle(hProcessSnap);
  
 }

Posted by 명혀니
,

int CUtility::deSecretCode(char* pszCode)
 {
  HCRYPTPROV    hProv;
  HCRYPTHASH    hHash;
  HCRYPTKEY    hKey;
  BYTE        pbCode[MAX_PASS];
  DWORD        dwDataLen;

  ZeroMemory(pbCode, MAX_PASS);
  sprintf((char*)pbCode, "%s", pszCode);
  dwDataLen = (DWORD)strlen((char*)pbCode) + 1;

  // CSP(Crystographic Service Provider) 핸들 얻기
  if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
  {
   if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
    return 1;
  }
  
  // 해쉬 만들기
  if(!CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash))
   return 2;

  // 해쉬 값 계산
  if(!CryptHashData(hHash, (BYTE*)SECRET_KEY, (DWORD)strlen(SECRET_KEY), 0))
   return 3;

  // 키 만들기
  if(!CryptDeriveKey(hProv, CALG_RC4, hHash,  0x0080*0x10000, &hKey))
   return 4;

  // 복호화
  if(CryptDecrypt(hKey, 0, TRUE, 0, pbCode, &dwDataLen))
   sprintf(pszCode, "%s", (char*)pbCode);
  else
   return 5;


  // 해쉬 없애기
  CryptDestroyHash(hHash);

  // CSP 핸들 풀어주기
  CryptReleaseContext(hProv, 0);

  return 0;
 }

Posted by 명혀니
,

int CUtility::enSecretCode(char* pszCode)
 {
  HCRYPTPROV    hProv;
  HCRYPTHASH    hHash;
  HCRYPTKEY    hKey;
  BYTE        pbCode[MAX_PASS];
  DWORD        dwDataLen;
  int KeyLen = 7;

  ZeroMemory(pbCode, MAX_PASS);
  sprintf((char*)pbCode, "%s", pszCode);
  dwDataLen = (DWORD)strlen((char*)pbCode) + 1;

  // CSP(Crystographic Service Provider) 핸들 얻기
  if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
  {
   if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
    return 1;  
  }
  // 해쉬 만들기
  if(!CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash))
   return 2;

  // 해쉬 값 계산
  if(!CryptHashData(hHash, (BYTE*)SECRET_KEY, (DWORD)strlen(SECRET_KEY), 0))
   return 3;

  // 키 만들기
  if(!CryptDeriveKey(hProv, CALG_RC4, hHash, 0x0080*0x10000, &hKey))
   return 4;

  // 암호화\tab             
  if(CryptEncrypt(hKey, 0, TRUE, 0, pbCode, &dwDataLen, MAX_PASS))
   sprintf(pszCode, "%s", (char*)pbCode);
  else
   return 5;    // 암호화 에러

  // 해쉬 없애기
  CryptDestroyHash(hHash);

  // CSP 핸들 풀어주기
  CryptReleaseContext(hProv, 0);

  return 0;
 }

Posted by 명혀니
,

bool CUtility::CreateShortcut(const CString szObjPath, const CString szFileName, const CString szDesc, bool bRelevantPlace)
 {
  bool bResult;
  HRESULT hres;
  IShellLink* psl;

  CString strMyPath = szFileName;

  ::CoInitialize(NULL);

  hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) &psl);

  if (SUCCEEDED(hres))
  {
   IPersistFile* ppf;

   psl->SetPath(szObjPath);
   psl->SetDescription(szDesc);

   if(bRelevantPlace)
   {
    CString szWorkDir = szObjPath;
    szWorkDir = szWorkDir.Left(szWorkDir.ReverseFind('\\'));
    psl->SetWorkingDirectory(szWorkDir);
   }

   hres = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf);

   if (SUCCEEDED(hres))
   {
    strMyPath += ".lnk"; // Important !!!

    WCHAR wsz[MAX_PATH];
    ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strMyPath, -1, wsz,MAX_PATH);
    hres = ppf->Save(wsz, TRUE);

    if (hres != S_OK )
    {
     MessageBox(NULL, "IPersistFile->Save() Error", "Error", MB_OK);
     bResult = false;
    }
    else bResult = true;

    ppf->Release();
   }
   psl->Release();
  }

  ::CoUninitialize();

  return bResult;
 }

Posted by 명혀니
,