한국산업기술대학교 제 4 강프레임리스너 (Frame Listener) 이대현교수
학습안내 학습목표 프레임리스너를이용하여게임루프를구현하는방법을이해한다. 오우거엔짂의키입력처리방식을이해한다. 학습내용 프레임리스너의개념프레임리스너를이용한게임캐릭터의이동캐릭터의이동속도조절 OIS 입력시스템을이용한키보드입력의처리
기본게임루프 Initialization Game Logic Drawing N Exit? Y Finish
실제게임루프
오우거엔진의메인렌더링루프 Root::startRendering() 함수에서이루어짐. 메인루프수행내용 프레임리스너 (Frame Listener) 들의 framestarted() 함수호출 모든렌더타겟들이 GPU 에게렌더링요청을완료 프레임리스너 (Frame Listener) 들의 framerenderingqueued() 함수호출 렌더타겟버퍼갱신 (back buffer swap) 루프의중단 프레임리스너 (Frame Listener) 들의 frameended() 함수호출 framestarted(), frameended(), framerenderingqueued() 에서하나라도 false 리턴.
framerenderingqueued() Ogre 1.7 부터 FrameListener 에서사용되기시작함. GPU 에 rendering command 를 issue 한후, 그결과가넘어오기전까지기다리는시간을이용하여, frame 구성로직을 CPU 를이용할수있음. 이에따라, framestarted(), frameended() 만을이용하는것보다성능측면에서유리함.
Ogre::FrameListener 클래스 프레임리스너 (frame listener) 장면이화면에렌더링되기직전및직후에호출되는함수를지니고있는객체 한프레임의렌더링전후에처리해야할일을프레임리스너를통해서구현할수있다. 프레임리스너객체를생성한후, 반드시프레임리스너로등록을시켜야비로소렌더링전후에호출이된다. 여러개의프레임리스너객체가존재할수있다.
실습 Move Professor & Ninja 캐릭터움직이기
main.cpp (1) 실습 class MainListener : public FrameListener public: MainListener(Root* root, OIS::Keyboard *keyboard) : mkeyboard(keyboard), mroot(root) mprofessornode = mroot->getscenemanager("main")->getscenenode("professor"); mninjanode = mroot->getscenemanager("main")->getscenenode("ninja"); } bool framestarted(const FrameEvent &evt) static float professorvelocity = -50.0f; if (mprofessornode->getposition().x < -200.f mprofessornode->getposition().x > 200.f) professorvelocity *= -1; mprofessornode->translate(professorvelocity * evt.timesincelastframe, 0, 0); } }; static float ninjavelocity = 100.0f; if (mninjanode->getposition().x < -400.f mninjanode->getposition().x > 400.0f) ninjavelocity *= -1; mninjanode->translate(ninjavelocity * evt.timesincelastframe, 0, 0); return true;
main.cpp (2) class LectureApp public: void go(void) mscenemgr = mroot->createscenemanager(st_generic, "main"); mcamera = mscenemgr->createcamera("main"); 실습 mesclistener =new ESCListener(mKeyboard); mroot->addframelistener(mesclistener); mmainlistener = new MainListener(mRoot, mkeyboard); mroot->addframelistener(mmainlistener); } };
실행화면
캐릭터를움직이는프레임리스너의구현 (1) class MainListener : public FrameListener FrameListener 클래스로부터상속. public: MainListener(Root* root, OIS::Keyboard *keyboard) : mkeyboard(keyboard), mroot(root) mprofessornode = mroot->getscenemanager("main")->getscenenode("professor"); mninjanode = mroot->getscenemanager("main")->getscenenode("ninja"); } mscenemgr = mroot->createscenemanager(st_generic, "main"); mcamera = mscenemgr->createcamera("main");
FrameListener 멤버함수 Public Member Functions virtual bool framestarted (const FrameEvent &evt) Called when a frame is about to begin rendering. virtual bool framerenderingqueued(const FrameEvent &evt) Called after all render targets have had their rendering commands issued, but before the render windows have been asked to flip their buffers over virtual bool frameended (const FrameEvent &evt) Called just after a frame has been rendered. virtual ~FrameListener () struct FrameEvent Real timesincelastevent; Real timesincelastframe; };
캐릭터를움직이는프레임리스너의구현 (2) bool framestarted(const FrameEvent &evt) static float professorvelocity = -50.0f; if (mprofessornode->getposition().x < -200.f mprofessornode->getposition().x > 200.f) professorvelocity *= -1; mprofessornode->translate(professorvelocity * evt.timesincelastframe, 0, 0); static float ninjavelocity = 100.0f; if (mninjanode->getposition().x < -400.f mninjanode->getposition().x > 400.0f) ninjavelocity *= -1; mninjanode->translate(ninjavelocity * evt.timesincelastframe, 0, 0); } return true;
프레임리스너의생성및등록 class LectureApp void go(void) mesclistener = new ESCListener(mKeyboard); mroot->addframelistener(mesclistener); 프레임리스너를생성. mmainlistener = new MainListener(mRoot, mkeyboard); mroot->addframelistener(mmainlistener); mroot->startrendering(); }; 프레임리스너를등록. 렌더링루프에서프레임리스너를계속호출하게됨.
실습 Move with Key 방향키로캐릭터움직이기
main.cpp professornode 처리부변경 class MainListener : public FrameListener 실습 bool framestarted(const FrameEvent &evt) static float professorvelocity = 50.0f; if (mkeyboard->iskeydown(ois::kc_left)) mprofessornode->translate(-professorvelocity * evt.timesincelastframe, 0, 0); else if (mkeyboard->iskeydown(ois::kc_right)) mprofessornode->translate(professorvelocity * evt.timesincelastframe, 0, 0); } };
실행화면 좌우키이로앞의캐릭터를좌우이동할수있음.
OIS InputManager 의생성및키보드입력장치등록 class LectureApp void go(void) 윈도우핸들러획득 size_t hwnd = 0; mwindow->getcustomattribute("window", &hwnd); InputManager 생성 minputmanager = OIS::InputManager::createInputSystem(hWnd); mkeyboard = static_cast<ois::keyboard*> (minputmanager->createinputobject(ois::oiskeyboard, false)); } }; 키보드입력장치의생성 무버퍼입력
ESC 처리프레임리스너의구현 class ESCListener : public FrameListener OIS::Keyboard *mkeyboard; public: ESCListener(OIS::Keyboard *keyboard) : mkeyboard(keyboard) } bool framestarted(const FrameEvent &evt) mkeyboard->capture(); } }; return!mkeyboard->iskeydown(ois::kc_escape);
방향키입력에따른이동속도방향조정 bool framestarted(const FrameEvent &evt) static float professorvelocity = 50.0f; if (mkeyboard->iskeydown(ois::kc_left)) mprofessornode->translate(-professorvelocity * evt.timesincelastframe, 0, 0); else if (mkeyboard->iskeydown(ois::kc_right)) mprofessornode->translate(professorvelocity * evt.timesincelastframe, 0, 0); }
학습정리 게임루프의구성 초기화, 게임로직, 렌더링, 종료프로세스로구성. 게임로직과렌더링이무한반복. 프레임리스너 오우거엔짂의렌더링프로세스전후에실행됨. 게임로직을구현해넣을수있는곳. 일정한속도의캐릭터이동 프레임타임을이용하여, 캐릭터의이동속도를설정함. OIS 입력시스템 키보드및마우스입력처리가능. 프레임리스너내에서입력처리함으로써사용자의입력을게임로직과연결시킬수있음.