디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

적분시리즈: 리듬게임을 만들수 있을까? 9. 키보드/마우스 처리

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.07.20 22:55:32
조회 147 추천 0 댓글 3




한동안 코딩에 열중하느라 강좌가 늦어졌다. 그 사이에 많은 부분을 뜯어고쳤으니, 어디 어디가 바뀌었는지부터 설명하겠다.

class MState
{
protected:
    GGame* const m_pGame;
public:
    MState(GGame* pGame) : m_pGame(pGame){}
    virtual ~MState(){};
    virtual void OnProc()=0;
    virtual void OnPostProc()=0;
    virtual void OnDraw()=0;
    virtual void OnLost()=0;
    virtual void ()=0;
    virtual void (int KeyCode)=0;
    virtual void (int KeyCode)=0;
    virtual void OnDrawSkip()=0;
};

가장 큰 변화라고 할 수 있는 것은 MState가 이벤트호출시 매번 받던 Game* pGame인자를 받지 않게했다. 그 대신아예 멤버변수로 Game* const m_pGame을 선언했다. 그리고 생성자에서 Game* pGame을 받아서 m_pGame에저장한다.
이에 따라서 MState를 상속받는 MPlayGame클래스에서도 마찬가지의 변화가 일어났다.

또한 위 코드에서 볼 수 있듯이 전체적인 이벤트처리가 다양해졌다.
키보드이벤트 과 이 추가되었고
그리기가 생략될 경우에 OnDraw대신에 OnDrawSkip이 호출된다.

GGame클래스에서도 변화가 일어났다.

class GGame
{
    friend class MState;
protected:
    ......
    bool m_activated;
    BYTE m_keystate[256];
    bool m_drawskip;
    void _getkeystate();
    void _getcursorpos();
    void OnDraw();
    void (int keycode);
    void (int keycode);
    void OnDrawSkip();
public:
    enum{
        KS_Pressed=1,
        KS_Down=2,
        KS_Up=4,
    };/*
      GetKeyState함수의 리턴값으로 사용된다.
      */
    POINT m_cursorpos;
    ......
    GRET SetDrawSkip(bool skip);
    bool GetDrawSkip();
    int GetKeyState(BYTE keycode);
};

바뀐 부분만 살펴보자면 먼저 MState클래스가 friend클래스로 선언되어서 MState클래스에서 GGame의 protected,private에도 접근할수 있게 하였다.
그리고 OnRender를 OnDraw로 이름을 바꿔서 통일시켰다. 또 ,,OnDrawSkip이추가되었고, ,을 처리할수 있게 m_keystate[256]변수가 추가되고, 열거형KS_Pressed, KS_Down, KS_Up이 추가되었다.
OnDrawSkip을 처리할 수 있게 m_drawskip변수도 추가되었다.
현재 키보드의 상태를 알아오는 _getkeystate함수와 마우스좌표를 알아오는 _getcursorpos함수가 추가되었다.
마지막으로 현재 키상태를 조사하는 GetKeyState함수가 추가되었다.

GGame::GGame() : ...... m_drawskip(false)
{
    ......
    memset(m_keystate, 0, sizeof(m_keystate));
}

생성자에서 m_drawskip를 false초기화하고, m_keystate를 0으로 초기화했다.

void GGame::_getkeystate()
{
    for(int i=0;i<256;i++)
    {
        if(m_keystate[i] & KS_Pressed)
        {
            if(GetAsyncKeyState(i))
            {
                m_keystate[i]=KS_Pressed;
            }
            else
            {
                m_keystate[i]=KS_Up;
            }
        }
        else
        {
            if(GetAsyncKeyState(i))
            {
                m_keystate[i]=KS_Down | KS_Pressed;
            }
            else
            {
                m_keystate[i]=0;
            }
        }
    }
}

현재 키보드상태를 조사해오는 함수이다. 함수 설명에 앞서서 WinApi 중 GetAsyncKeyState함수와 GetKeyState함수에 대해서 간략히 설명하겠다.
둘 다 키보드 상태를 조사해오는 함수지만, GetKeyState는 큐에 쌓여있는 키보드상태를 가져오고, GetAsyncKeyState는 큐는 무시하고, 현재 키보드 상태를 가져온다.
보통 때에는 큰 차이가 없을지 몰라도, 컴퓨터가 버벅거리거나해서 키가 제때에 처리되지 않고 큐에 쌓이게 되면, GetKeyState함수는 이전의 키 상태를 가져와버리는 문제가 있다.
따라서 키보드처리가 중요한 게임에서는 GetAsyncKeyState함수를 쓰는게 바람직하다.

처음에 m_keystate를 256개의 배열로 선언한 이유는 키코드 0~255번 사이에 키보드의 모든 키가 할당되기 때문이다.즉, 그 256개만 검사하면 모든 키를 검사한것이라는 얘기이다. m_keystate에 현재 키의 상태, 눌려졌는가, 떼어졌는가의모든 정보를 담기 위해서 KS_Pressed=1, KS_Down=2, KS_Up=4라고 정의했다.
KS_Pressed는 현재 키가 눌려있을때 셋되고, KS_Down은 막 키가 눌러졌을때, KS_Up은 막 키가 떼어졌을때 셋된다.

(m_keystate[i] & KS_Pressed)를 하여 1이 나오면 키가 눌려있는 것이고, 0이 나오면 키가 눌리지 않은 것이다.
GetAsyncKeyState가 0이 아닌값을 리턴하면 키가 놀려져있는 것이고, 0을 리턴하면 키가 눌려지지 않은것이다.
각각의 경우를 따져 4가지로 분기하여 KS_Pressed, KS_Down, KS_Up을 설정했다.

void GGame::_getcursorpos()
{
    GetCursorPos(&m_cursorpos);
    if(!m_dev.fullscreen)
    {
        ScreenToClient(m_dev.hwnd, &m_cursorpos);
    }
}

이 함수는 현재 마우스커서의 위치를 알아온다. 그러기 위해서 WinApi함수인 GetCursorPos를 호출하는데, 이 함수는 모니터 좌상단을 (0,0)으로 보고 화면상의 커서의 위치를 알아낸다.
따라서 전체화면 모드가 아닌 경우에는 화면상의 위치가 아닌 작업영역상의 위치를 알아와야 하므로,
ScreenToClient함수를 사용하여 화면상의 좌표를 현재 윈도우의 작업영역상의 좌표로 변환해준다.

GRET GGame::SetDrawSkip(bool skip)
{
    m_drawskip=skip;
    return 0;
}

bool GGame::GetDrawSkip()
{
    return m_drawskip;
}

그리기 생략여부를 설정하고 알아오는 함수이다. 설명할게 없을 정도로 간단하다.

void GGame::OnCreate()
{
    GStrings strs;
    strs.Load(&DataInFile(L"textures.str"));
    for(size_t i=0;i<strs.size();i++)
    {
        LoadTexture(strs[i].c_str());
    }
    LoadSprites(&DataInFile(L"sprites.dat"));
    SetState(new MPlayGame(this));
}

void GGame::OnProc()
{
    if(m_pstate)m_pstate->OnProc();
}


void GGame::OnDraw()
{
    if(m_pstate)m_pstate->OnDraw();
}


void GGame::OnPostProc()
{
    if(m_pstate)m_pstate->OnPostProc();
}

void GGame::OnLost()
{
    if(m_pstate)m_pstate->OnLost();
}


void GGame::()
{
    if(m_pstate)m_pstate->();
}


void GGame::(int keycode)
{
    if(m_pstate)m_pstate->(keycode);
}


void GGame::(int keycode)
{
    if(m_pstate)m_pstate->(keycode);
}


void GGame::OnDrawSkip()
{
    if(m_pstate)m_pstate->OnDrawSkip();
}

이벤트 처리부분이다. 특별한거는 없고, 주목해야할 부분은 OnCreate에서 new MPlayGame을 할때 MPlayGame의생성자가 GGame*pGame을 필요하게 바뀌었으므로 (MState의 생성자가 바뀐것을 기억하라.) this포인터를 넘겨주었다.

GRET GGame::MessageLoop()
{
    bool islost=false;
    MSG msg;
    if(m_pd3dd)OnCreate();
    while(1)
    {
        if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        {
            if(msg.message==WM_QUIT)return 0;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            if(m_pnewstate)
            {
                if(m_pstate)delete m_pstate;
                m_pstate=m_pnewstate;
                m_pnewstate=NULL;
            }
            _getkeystate();
            _getcursorpos();
            OnProc();
            for(int i=0;i<256;i++)
            {
                if(m_keystate[i] & KS_Down) (i);
                if(m_keystate[i] & KS_Up) (i);
            }
            if(islost)
            {
                if((!m_dev.fullscreen || m_activated) && Reset3DDevice()==0)
                {
                    islost=false;
                    m_pspr->Device();
                    ();
                }
            }
            else if(m_drawskip)
            {
                OnDrawSkip();
            }
            else
            {
                m_pd3dd->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(64,128,192), 1.f, 0);
                if( SUCCEEDED(m_pd3dd->BeginScene()) )
                {
                    m_pspr->Begin(D3DXSPRITE_ALPHABLEND);
                    OnDraw();
                    m_pspr->End();
                    m_pd3dd->EndScene();
                    if(m_pd3dd->Present(NULL, NULL, NULL, NULL)==D3DERR_DEVICELOST)
                    {
                        islost=true;
                        m_pspr->OnLostDevice();
                        OnLost();
                    }
                }
            }
            OnPostProc();
            m_drawskip=false;
        }
    }
    return 0;
}

메시지루프부분이 좀 바뀌었다. OnProc을 호출하기 바로전에 _getkeystate, _getcursorpos를 호출하여키보드상태, 커서좌표를 얻어온다. 그리고 OnProc이 호출된 후에 m_keystate에서 KS_Down이 셋된 것은이벤트를 호출해주고, KS_Up이 셋된 것은 이벤트를 호출해준다.
그리고 m_drawskip이 참일 경우에는 그리기부분에 돌입하지 않고 OnDrawSkip을 호출하고 m_drawskip이 거짓일때 그리기부분에 돌입한다. 그리고 m_drawskip은 매 프레임 마지막부분에서 거짓으로 다시 설정한다.
        

추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 끝까지 다 본 걸 후회하게 만든 용두사미 드라마는? 운영자 25/07/07 - -
AD 디지털 액세서리 기간한정 세일! 운영자 25/07/11 - -
공지 프로그래밍 갤러리 이용 안내 [88] 운영자 20.09.28 45419 65
2871262 나는 암만 생각해도 SVN이 더 편한거 같은데 ㅆㅇㅆ(124.216) 05:13 5 0
2871261 svn에서 깃 전환하고 느낀것인데 [7] ㅆㅇㅆ(124.216) 05:10 20 0
2871260 환자가 천천히 나을수록 의사는 돈을 더 번다는 역설 [1] 발명도둑잡기(118.235) 05:06 10 0
2871258 근데 삼촌 빡고수라던데 왜 프갤 탈퇴한거냐 [4] ㅆㅇㅆ(124.216) 04:49 20 0
2871256 computer란 사라진 직업 [1] 발명도둑잡기(118.235) 04:40 14 0
2871254 문화계 만난 이 대통령 “예술인 기본소득 필요” 발명도둑잡기(118.235) 04:21 10 0
2871252 방금 전 뜬 9GAG 릴스 혼자 하는 테니스 릴스 영상 보니 발명도둑잡기(118.235) 04:02 13 0
2871251 삼촌이 100% 자동화 백엔드 도구 만들었던데 [1] 프갤러(183.101) 03:59 25 0
2871250 동양철학:남에게 받은건 바위에 새기고, 도운것은 모래에 새겨라 ㅇㅇ(183.101) 03:57 9 0
2871249 오늘의 소설, 영화 실마리: 일제와 나치의 동맹과 몰락 이야기 발명도둑잡기(118.235) 03:45 15 0
2871247 '노동존중' 이재명 정부와 최저임금법 제1조[노동TALK] 발명도둑잡기(118.216) 03:29 11 0
2871246 히틀러에게 훈장을 받은 일본 해군장교 발명도둑잡기(118.216) 03:27 11 0
2871243 오늘의 영상 기획 실마리: 컴퓨터 팬으로 드론 발명도둑잡기(118.235) 02:51 16 0
2871242 탑골공원은 일제의 압제를 뚫고 기미독립선언을 했던 장소임 발명도둑잡기(118.235) 02:28 17 0
2871240 냥덩이 똥구멍 찢길 예정 발명도둑잡기(118.235) 02:22 18 0
2871239 세상에 대한 원망과 슬픔이 느껴지는 글이 있다 발명도둑잡기(118.235) 02:14 14 0
2871238 전광훈 자유마을 업드려뻗쳐와 에스파-더티 워크 풍자 발명도둑잡기(118.235) 02:11 13 0
2871237 반공 국가보안법으로 키운 가짜뉴스 생산 공장 목록 발명도둑잡기(118.235) 02:04 14 0
2871233 나는 변태야 여자아이 생식기 사냥꾼이야 ㅇㅅㅇ [6] 류류(118.235) 01:28 60 1
2871232 야한게 최고임 변태 저질이 최고임 ㅇㅅㅇ 류류(118.235) 01:26 30 1
2871231 결혼정보회사 대표가 솔직하게 말하는 며느리 조건 발명도둑잡기(118.216) 01:22 14 0
2871230 편부모가정에 하명뿐인 부모님은 공무원인데 [2] 프갤러(58.72) 01:12 27 0
2871229 세븐틴 떠리 에이~ 루도그담당(58.239) 01:03 25 0
2871228 발도잡행님 도배 보면서 느끼는데 국가 장학금 받아먹었는데 배급견 욕하는건 [3] ㅆㅇㅆ(124.216) 01:00 36 0
2871227 오늘의 소설, 영화 실마리: 집단 따돌림 피해자 동맹 발명도둑잡기(118.235) 00:57 13 0
2871225 요즘 mz사이에서 유행중이라는 콘텐츠 발명도둑잡기(118.216) 00:09 21 0
2871224 요즘 인기라는 日 할머니 대여 서비스 발명도둑잡기(118.216) 07.12 24 0
2871223 학생넷이랑 알찬 여름 함께하지 않을래? 발명도둑잡기(118.235) 07.12 13 0
2871222 오늘의 소설, 영화 실마리: 계좌 비공개 은행이 고객 살인청부해 돈 갈취 발명도둑잡기(118.235) 07.12 13 0
2871221 오늘의 게임, 소설, 영화 실마리: 인간과 귀신의 대결 작품 발명도둑잡기(118.235) 07.12 15 0
2871219 이재명 대통령 쭈꾸미삼겹살집 회동 보니 드는 생각 [1] 발명도둑잡기(118.216) 07.12 34 0
2871218 "네 여자친구 10분이면 꼬셔"..지인 폭행한 20대 징역형 발명도둑잡기(118.216) 07.12 19 0
2871216 이중 갈취로 '홀로캐시'(holocash) 뜯어낸 유대인 파워의 민낯 발명도둑잡기(118.216) 07.12 13 0
2871215 국내에만 29억개…무방비 IoT 기기, 사생활 유출 부른다 발명도둑잡기(118.216) 07.12 16 0
2871214 청혼 도중 폭포 아래로 추락…영상 확산에 누리꾼 '충격' 발명도둑잡기(118.216) 07.12 18 0
2871213 대동아냥덩권⭐ [1] ♥로스트미디어냥덩이♥갤로그로 이동합니다. 07.12 25 0
2871212 역대급 1위 터졌다…‘충격’에 휩싸인 일본 발명도둑잡기(118.216) 07.12 26 0
2871211 나도 코딩 개고수가 되고 싶어 [5] 아스카영원히사랑해갤로그로 이동합니다. 07.12 73 0
2871210 내일 칼럼 하나 쓸깡? 쓸 주제가 뭐 있을까낭? [1] ♥로스트미디어냥덩이♥갤로그로 이동합니다. 07.12 26 0
2871208 주 1회 칼럼 써야하는댕,, ♥로스트미디어냥덩이♥갤로그로 이동합니다. 07.12 16 0
2871207 살 엄청 찌는 백종원피자 알바한 오해원 발명도둑잡기(118.216) 07.12 12 0
2871206 실존하는게 놀라운 지구상의 신비한 생물들 발명도둑잡기(118.216) 07.12 14 0
2871204 월 600 정도만 되어도 만족하겠다 [6] 아스카영원히사랑해갤로그로 이동합니다. 07.12 57 0
2871203 이효리, 달라진 예능 환경 언급 "10년 전 방송선 女 가슴 사이즈로 놀 발명도둑잡기(118.216) 07.12 22 0
2871202 친중좌파 2재명 탄핵운동행진⭐+ 가즈아앙 ♥로스트미디어냥덩이♥갤로그로 이동합니다. 07.12 18 0
2871201 [단독] “의리의 한소희”, 뒤늦게 알려진 미담…5천만원 상당 깜짝 선물 발명도둑잡기(118.216) 07.12 26 0
2871200 김충현의 죽음, 그날 그때 무슨 일이... "김충현은 어느 회사 직원이었 발명도둑잡기(118.216) 07.12 11 0
2871199 안녕하세요 선생님들 외주에 대해서 질문이 있습니다. [1] 프갤러(119.192) 07.12 16 0
2871197 불과 한달만에 대한민국을 처참하게 망가뜨리고 잇는 2찢명 ♥로스트미디어냥덩이♥갤로그로 이동합니다. 07.12 22 1
뉴스 [집 나가면 개호강] “보조견은 다 대형견인 줄” 강소라도 몰랐다…청각장애인 돕는 ‘보청견’ 등장에 시선 집중! 디시트렌드 07.11
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2