Game Programming 04 The Game Loop and Real-time Simulation 2010 년 2 학기 디지털콘텐츠전공.

Slides:



Advertisements
Similar presentations
Introduction to Macromedia Director 8.5 – Lingo
Advertisements

Game Programming Patterns Game Loop
Robotics Simulator Intelligent Systems Lab. What is it ? Software framework - Simulating Robotics Algorithms.
Essentials of Interactive Computer Graphics: Concepts and Implementation K. Sung, P. Shirley, S. Baer Intro and Chapter 1 Goals Give student some idea.
Ch 1 Intro to Graphics page 1CS 367 First Day Agenda Best course you have ever had (survey) Info Cards Name, , Nickname C / C++ experience, EOS experience.
Computer-Based Animation. ● To animate something – to bring it to life ● Animation covers all changes that have visual effects – Positon (motion dynamic)
Operating Systems Concepts 1. A Computer Model An operating system has to deal with the fact that a computer is made up of a CPU, random access memory.
AGD: 5. Game Arch.1 Objective o to discuss some of the main game architecture elements, rendering, and the game loop Animation and Games Development.
User Interface Programming in C#: Direct Manipulation Chris North CS 3724: HCI.
Week 1 - Friday.  What did we talk about last time?  C#  SharpDX.
Software design and development Marcus Hunt. Application and limits of procedural programming Procedural programming is a powerful language, typically.
PacMan by Midway, released 1980 CSE 380 – Computer Game Programming Real-Time Game Architecture.
Chapter 3.1:Operating Systems Concepts 1. A Computer Model An operating system has to deal with the fact that a computer is made up of a CPU, random access.
1 Perception, Illusion and VR HNRS 299, Spring 2008 Lecture 19 Other Graphics Considerations Review.
MrsBillinghurst. net A2 Computing A2 Computing Projects Game Animation in Pascal.
CSE 380 – Computer Game Programming Render Threading Portal, by Valve,
MOMA Display Screens K u r t R a l s k e.
Welcome to CIS 083 ! Events CIS 068.
SE Team 9 3D Flyer Cole Hoosier Ryan Hannebaum Leanne Gray Alex Stampbach Matt Cook.
1 Lecture 2 Animation References: [1] Gregory Junker, Pro OGRE 3D Programming, Apress, 2006 [2] Ogre Tutorials – Ogre Wiki
Game Engine Programming. Game Engine Game Engine Rendering Engine (OGRE) Rendering Engine (OGRE) Physics Engine (Bullet) Physics Engine (Bullet) Input/Output.
Introduction to Arrays. definitions and things to consider… This presentation is designed to give a simple demonstration of array and object visualizations.
Game Programming 05 3D math for Games 2010 년 2 학기 디지털콘텐츠전공.
Liang, Introduction to Java Programming, Eighth Edition, (c) 2011 Pearson Education, Inc. All rights reserved Event Driven Programming, The.
Game Programming 02 - OGRE3D 엔진 소개 2010 년 2 학기 디지털콘텐츠전공.
Addison Wesley is an imprint of © 2010 Pearson Addison-Wesley. All rights reserved. Chapter 7 The Game Loop and Animation Starting Out with Games & Graphics.
Dr. Ken Hoganson, Kennesaw State University Introduction to the Torque Game Development System.
Motion Planning in Games Mark Overmars Utrecht University.
Learning Unity. Getting Unity
User Interface Programming in C#: Direct Manipulation Chris North CS 3724: HCI.
111 Introduction to OGRE3D Programming: Main Loop.
1 Perception and VR MONT 104S, Fall 2008 Lecture 21 More Graphics for VR.
Control flow for interactive applications CSE 3541 Matt Boggus.
Reference: The Game Loop Animation / Game loop 1. Update variables 2. [Get input from the user] (GameLoop only) 3. Draw (using variables)
11 General Game Programming Approach. The program is event-driven The program is event-driven –Messages = events –So as all windows system (for example.
CS324e - Elements of Graphics and Visualization Timing Framework.
Game Programming Patterns Game Loop From the book by Robert Nystrom
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 4: Events Programming with Alice and Java First Edition by John Lewis.
SCRIPT PROGRAMMING WITH FLASH Introductory Level 1.
UW EXTENSION CERTIFICATE PROGRAM IN GAME DEVELOPMENT 2 ND QUARTER: ADVANCED GRAPHICS Game program main loop.
T HE G AME L OOP. A simple model How simply could we model a computer game? By separating the game in two parts: – the data inside the computer, and –
Processor Memory Processor-memory bus I/O Device Bus Adapter I/O Device I/O Device Bus Adapter I/O Device I/O Device Expansion bus I/O Bus.
Visualization Recreate the ping pong scene in 3D using ball and racket coordinates.
Time Management.  Time management is concerned with OS facilities and services which measure real time.  These services include:  Keeping track of.
SE Team 9 GlobalFlyer Cole Hoosier Ryan Hannebaum Leanne Gray Alex Stampbach.
Unbuffered Input Games generally use unbuffered Input Ogre provides FrameListeners – Ogre's main infinite loop → startRendering – Also called the render.
12-Jun-16 Event loops. 2 Programming in prehistoric times Earliest programs were all “batch” processing There was no interaction with the user Input Output.
(More) Event handling. Input and Windowed-OS’s Windowed OS’s (Windows, OSX, GUI-linux’s) send messages (events) when the user does something “on” the.
Game Development with Unity3D
Game and animation control flow
Layers in Adobe After Effect
MOM! Phineas and Ferb are … Aims:
Week 2 - Monday CS361.
Clocks, I/O devices, Thin Clients, and Power Management
Game Loops + Part II Reference:
Goals Give student some idea what this class is about
Frame Update, Level Representation & Graphics
Ogre Overview Lecture 3.
Ogre Overview.
Game Engine Architecture
Introduction to Events
Game and animation control flow
EE 422C Java FX.
Event loops.
3D Game Development Time and game loop Jernej Vičič.
Event loops 17-Jan-19.
Event loops 17-Jan-19.
Week 6: Time and triggers!
Event loops.
Games Development 2 Entity / Architecture Review
Presentation transcript:

Game Programming 04 The Game Loop and Real-time Simulation 2010 년 2 학기 디지털콘텐츠전공

Time in Game Games: –Real-time, dynamic, interactive computer simulation –Time plays an important role! –Different types of time in a game Real time Game time local timeline of an animation

Rendering Loop Real-time 3D Graphics is different from OS’s GUI –Redraw in Windows PC/Mac OS: Mostly static Small portion of the screen is changing Rectangle invalidation –Redraw in a Game: Entire contents of the screen is changing Like a movie with a series of still images in rapid succession Succession requires a LOOP – the rendering loop

Rendering Loop Typical structure for a rendering loop: while(!quit) { // Update camera transform based on // user input, or predefined scenario updateCamera(); // Update positions, orientations and // other visual states of the elements updateSceneElements(); // Render a still frame into the “back buffer” renderScene(); // Swap the back buffer with the front buffer swapBuffers(); } while(!quit) { // Update camera transform based on // user input, or predefined scenario updateCamera(); // Update positions, orientations and // other visual states of the elements updateSceneElements(); // Render a still frame into the “back buffer” renderScene(); // Swap the back buffer with the front buffer swapBuffers(); }

Game Loop Game consists of many subsystems: –Device I/O –Rendering –Animation –Collision detection and resolution –Rigid body dynamic simulation (optional) –Multiplayer networking –Audio Need to be update periodically – Game Loop –Update rates can be different Rendering/animation: 30~60 Hz Dynamic simulation: 120 Hz AI: 2 Hz (twice per second)

Game Loop – A Simple Example Pong (Atari arcade game) –A Legendary Game: story.com/arcade.htmhttp:// story.com/arcade.htm –Simple but exciting!

Pong Game Loop void main()// pong { initGame(); while(true)// Game Loop { readInterfaceDevices(); if(quitButtonPressed()) break; movePaddles(); moveBall(); collideAndBounceBall(); if(ballImpactedSide(LEFT_PLAYER) { incrementScore(RIGHT_PLAYER); resetBall(); } if(ballImpactedSide(RIGHT_PLAYER) { incrementScore(LEFT_PLAYER); resetBall(); } renderPlayfield(); } void main()// pong { initGame(); while(true)// Game Loop { readInterfaceDevices(); if(quitButtonPressed()) break; movePaddles(); moveBall(); collideAndBounceBall(); if(ballImpactedSide(LEFT_PLAYER) { incrementScore(RIGHT_PLAYER); resetBall(); } if(ballImpactedSide(RIGHT_PLAYER) { incrementScore(LEFT_PLAYER); resetBall(); } renderPlayfield(); }

Game loop architectural styles 1.Windows Message Pumps 2.Callback-Driven Frameworks 3.Even-based Updating

Windows Message Pumps Message Pump: –A routine for handling windows messages Games in a Windows OS must obey windows’ rule Many messages from the OS cannot be ignored // Message Pump – Typical Windows Routine while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // Message Pump – Typical Windows Routine while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }

Windows Message Pumps Message Pump for a game: –Modify the windows message pump with the game loop // Message Pump for a game while (true) { // Service all pending windows messages while (PeekMessage(&msg, NULL, 0, 0)>0) { TranslateMessage(&msg); DispatchMessage(&msg); } // If no more windows messages, // run one iteration of the game loop RunOneIterationOfGameLoop(); } // Message Pump for a game while (true) { // Service all pending windows messages while (PeekMessage(&msg, NULL, 0, 0)>0) { TranslateMessage(&msg); DispatchMessage(&msg); } // If no more windows messages, // run one iteration of the game loop RunOneIterationOfGameLoop(); }

Call-back Driven Framework Framework: –A partially-constructed application Encapsulating knowledge of how to use the low-level libraries Providing functions for the game flow But functions are mostly empty –Need to be completed by a programmer Fill-in the missing details Overide call-back functions

Call-back Driven Framework Example from Ogre3D’s game loop while (true) { for (each frameListener) { frameListener.frameStarted(); } renderCurrentScene(); for (each frameListener) { frameListener.frameEnded(); } while (true) { for (each frameListener) { frameListener.frameStarted(); } renderCurrentScene(); for (each frameListener) { frameListener.frameEnded(); }

Call-back Driven Framework Using Ogre’s FrameListener Class GameFrameListener : public Ogre::FrameListener { public: virtual void frameStarted(const FrameEvent &event) { // Do things happening before rendering pollJoypad(event); updatePlayerControls(events); updateDynamicSimulation(events); resolveCollisions(events); updateCamera(events); // etc. } virtual void frameEnded(const FrameEvent &event) { // Do things after rendering drawHud(events); } Class GameFrameListener : public Ogre::FrameListener { public: virtual void frameStarted(const FrameEvent &event) { // Do things happening before rendering pollJoypad(event); updatePlayerControls(events); updateDynamicSimulation(events); resolveCollisions(events); updateCamera(events); // etc. } virtual void frameEnded(const FrameEvent &event) { // Do things after rendering drawHud(events); }

Event-Driven Updating Event: –Any interesting change in the state of the game –Examples: The player pressing a keyboard The explosion going off An enemy character spotting the player

Event-Driven Updating Event System –Similar to windows GUI –A subsystem of a game engine Register events of interests Respond to the events when they occur –Periodic services can be implemented by an event Example: Posting a event for every 1/30 sec. Using the event que for posting a event for the future

MEASURING AND DEALING WITH TIME

Timelines Real Time –Actual time measured directly via the CPU clock Game Time –Times measured or used in the game –Does not need to be coincide with the real time Slow/fast motion in the game Temporarily pausing the game When debugging, slow-down helps to figure out.

Timelines Local and Global timelines –Each animation clip or audio clip may have a different timeline Origin (t=0) defined to the start of the clip Easy to speed up/down when playback Easy to play backward Playing a clip Speed up Play backward

Frame Rate and Time Deltas Frame Rate: f –How rapidly the sequence of still images changes –Hertz (Hz) : number of cycles for second –Frames per Second (FPS) : Used in games and film. Same with Hz 30/60 in North America or Japan (NTSC) 50 in Europe (PAL) –Can be varying time to time! Time Delta: Δt –The amount of time between frames: Also known as Frame time, delta time Inverse of the frame rate: 1/f 30 FPS = 1/30 sec = 33.3 ms

From Frame Rate to Speed Speed: v –Meters per second (or pixels per second) Make a spaceship move: –Change in position: Δx = v Δt –With a current position x 1, at next frame: x 2 = x 1 + v Δt –Since the movement depends on Δt, how to determine it?

Old-days CPU-dependent Games CPU-Dependent: –Do not use any Δt ! –Instead, specify the speed by the meters per frame –With a good PC, will runs fast –With a bad PC, will runs slow –Provide a “Turbo” button to speed up in old-days

Updating based on Elapsed Time –To be CPU-independent: Measuring Δt Read CPU time twice: Once at the beginning and once at the end of the frame Most game do this! –Is it accurate? We are measuring the past Δt as an upcomming Δt “Past performance is not a guarantee of future results” Sudden drop in the frame rate: Frame-rate spike

Using a Running Average Averaging the frame-time over a few frames –Reduce the influence of a sudden change in frame rate –Can adapt smoothly with a varying framerate

Governing the Frame Rate Frame Rate Governing: –Guarantee every frame’s duration to be 33.3 ms or 16.6 ms –Sleep if ends earlier otherwise “takes our lumps”

Measuring Real Time Querying system time: –The number of seconds since midnight, Jan 1, 1970 –Not enough resolution High-Resolution Timer: –Count the number of CPU cycles since the last power on/reset –For example: 3GHz processor increments 3 billion times per second Resolution: 1/3 billion = 3.33 x second =0.333 ns Stored with 64 bit integer: 195 years of duration to record time(); QueryPerformanceCounter();// read the counter (64bit integer) QueryPerformanceFrequency(); // cycles per second QueryPerformanceCounter();// read the counter (64bit integer) QueryPerformanceFrequency(); // cycles per second

Time to Back to OGRE3D

Basic of OGRE Scene Manager: –Managing everything appearing in the scene –Cameras, Objects, Planes, billboards, lights...and so on 3 kinds of Scene Managers –Octree(8 진 트리 ) Scene Manager 기본 장면 관리자 대부분의 장면에 사용 가능 –BSP(Binary Surface Partition) Scene Manager 건물 내부와 같이 벽과 복도 등으로 구성된 장면에 최적화된 성능. –Terrain Scene Manager 정적 지형을 가지는 비교적 소규모의 장면에 적합 고해상도의 지형에 적합 mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);

Basic of OGRE Entity: –Objects to be rendered on the scene –3D meshes: Character, robot, fish, terrain and so on. –Cameras, lights, billboards are not entities. 3D Mesh

Basic of OGRE Scene Node: –Representing translation, rotation and scale (transformation) –Not an actual object –An(or multiple) entity can be attached to. Node Entity1 Entity2

Scene Manager, node and entity root Node1 Node2 Entity1 Entity2 Entity3 Node3 Entity4 Entity5 Node4 Entity6

Hierarchical Modeling A hierarchical model is created by nesting the descriptions of subparts into one another to form a tree organization

Revisiting the code void TutorialApplication::createScene(void) { // create your scene here :) Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh"); Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); headNode->attachObject(ogreHead); // Set ambient light mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5)); // Create a light Ogre::Light* l = mSceneMgr->createLight("MainLight"); l->setPosition(20,80,50); } void TutorialApplication::createScene(void) { // create your scene here :) Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh"); Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); headNode->attachObject(ogreHead); // Set ambient light mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5)); // Create a light Ogre::Light* l = mSceneMgr->createLight("MainLight"); l->setPosition(20,80,50); }

Adding One More Node void TutorialApplication::createScene(void) { // create your scene here :) Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh"); Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); headNode->attachObject(ogreHead); Ogre::Entity* ogreHead2 = mSceneMgr->createEntity( "Head2", "ogrehead.mesh" ); Ogre::SceneNode* headNode2 = mSceneMgr->getRootSceneNode()->createChildSceneNode ( "HeadNode2", Ogre::Vector3( 100, 0, 0 ) ); headNode2->attachObject( ogreHead2 ); // Set ambient light mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5)); // Create a light Ogre::Light* l = mSceneMgr->createLight("MainLight"); l->setPosition(20,80,50); } void TutorialApplication::createScene(void) { // create your scene here :) Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh"); Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); headNode->attachObject(ogreHead); Ogre::Entity* ogreHead2 = mSceneMgr->createEntity( "Head2", "ogrehead.mesh" ); Ogre::SceneNode* headNode2 = mSceneMgr->getRootSceneNode()->createChildSceneNode ( "HeadNode2", Ogre::Vector3( 100, 0, 0 ) ); headNode2->attachObject( ogreHead2 ); // Set ambient light mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5)); // Create a light Ogre::Light* l = mSceneMgr->createLight("MainLight"); l->setPosition(20,80,50); }

Node Transformation Translate: –SceneNode::translate ( Ogre::Vector3(..) ); Rotate: –SceneNode::yaw(Degree(..)); –SceneNode::pitch ( ); –SceneNode::roll ( ); Scale –SceneNode::scale ( x, y, z );

Cool ninja without hassle Replace the CreateScene function with the one in our homepage!

정리 OGRE 3D 의 rendering process: – 시스템 초기화 Root 개체 생성 Configuration 설정 Render Window 생성 Resource 위치 설정 Frame Listener 생성 – 씬 생성 Scene Manager 생성 Camera 및 viewport 생성 Light 생성 Entity 생성 Scene node 생성 – 렌더링

Frame Listener 한 장면이 화면에 렌더링되기 직전 / 직후에 해야 할 일을 정의하고 있는 객체 추가 작업을 위해서는 frame listener 를 추가 생성 하고, 이를 root 에 등록시켜 사용 여러 개의 frame listener 가 존재할 수 있다.

Frame Listener 의 맴버함수 frameStarted Called just before a frame is rendered. frameRenderingQueued Called after all render targets have had their r endering commands issued, but before the render windows have been asked to flip th eir buffers over frameEnded Called just after a frame has been rendered. virtual bool frameStarted(const FrameEvent& evt); virtual bool frameRenderingQueued(const FrameEvent& evt); virtual bool frameEnded(const FrameEvent& evt) virtual bool frameStarted(const FrameEvent& evt); virtual bool frameRenderingQueued(const FrameEvent& evt); virtual bool frameEnded(const FrameEvent& evt) FrameEvent structure: Real timeSinceLastEvent, Real timeSinceLastFrame 값을 기억하는 구조체

Frame Listener 의 호출 Root 객체의 rendering loop 내에서 호출 bool Root::renderOneFrame(void) { if(!_fireFrameStarted()) return false; if (!_updateAllRenderTargets()) return false; return _fireFrameEnded(); } bool Root::renderOneFrame(void) { if(!_fireFrameStarted()) return false; if (!_updateAllRenderTargets()) return false; return _fireFrameEnded(); }

Ogre Engine 의 Rendering Loop Root::startRendering() 함수에서 이뤄짐 Redering Loop 실행 – 매 프레임 마다 renderOneFrame 실행 : Loop 의 중단 –FrameStarted, frameRenderingQueued, FrameEnded 에서 하나라도 false 를 return 할 경우 1. Frame Listener 들의 FrameStarted() 함수 호출 3. Frame Listener 들의 FrameEnded() 함수 호출 Frame Listener 들의 frameRenderingQueued() 함수 호출 2. 한 프레임 렌더링

Input Handling Types of input handling –Unbuffered Input Testing states of Mouse/Keyboard every frame Do action if necessary –Buffered Input Event(message)-driven Event is queued into a buffer Call message pump routines per frame

Ninja 움직이기 Add two functions in Application class: class OgreApp : public BaseApplication { public: BasicTutorial4(void); virtual ~BasicTutorial4(void); protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); private: bool processUnbufferedInput(const Ogre::FrameEvent& evt); } class OgreApp : public BaseApplication { public: BasicTutorial4(void); virtual ~BasicTutorial4(void); protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); private: bool processUnbufferedInput(const Ogre::FrameEvent& evt); }

Ninja 움직이기 Add two functions in Application class: class OgreApp : public BaseApplication { public: BasicTutorial4(void); virtual ~BasicTutorial4(void); protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); private: bool processUnbufferedInput(const Ogre::FrameEvent& evt); } class OgreApp : public BaseApplication { public: BasicTutorial4(void); virtual ~BasicTutorial4(void); protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); private: bool processUnbufferedInput(const Ogre::FrameEvent& evt); }

CreateScene 수정 Ninja 를 포함하고 light 를 세팅 mSceneMgr->setAmbientLight(Ogre::ColourValue(0.25, 0.25, 0.25)); Ogre::Entity* ninjaEntity = mSceneMgr->createEntity("Ninja", "ninja.mesh"); Ogre::SceneNode *node = mSceneMgr->getRootSceneNode() ->createChildSceneNode("NinjaNode"); node->attachObject(ninjaEntity); Ogre::Light* pointLight = mSceneMgr->createLight("pointLight"); pointLight->setType(Ogre::Light::LT_POINT); pointLight->setPosition(Ogre::Vector3(250, 150, 250)); pointLight->setDiffuseColour(Ogre::ColourValue::White); pointLight->setSpecularColour(Ogre::ColourValue::White); mSceneMgr->setAmbientLight(Ogre::ColourValue(0.25, 0.25, 0.25)); Ogre::Entity* ninjaEntity = mSceneMgr->createEntity("Ninja", "ninja.mesh"); Ogre::SceneNode *node = mSceneMgr->getRootSceneNode() ->createChildSceneNode("NinjaNode"); node->attachObject(ninjaEntity); Ogre::Light* pointLight = mSceneMgr->createLight("pointLight"); pointLight->setType(Ogre::Light::LT_POINT); pointLight->setPosition(Ogre::Vector3(250, 150, 250)); pointLight->setDiffuseColour(Ogre::ColourValue::White); pointLight->setSpecularColour(Ogre::ColourValue::White);

Frame Listner 수정 frameRenderingQueued 함수 override bool OgreApp::frameRenderingQueued(const Ogre::FrameEvent& evt) { bool ret = BaseApplication::frameRenderingQueued(evt); if(!processUnbufferedInput(evt)) return false; return ret; } bool OgreApp::frameRenderingQueued(const Ogre::FrameEvent& evt) { bool ret = BaseApplication::frameRenderingQueued(evt); if(!processUnbufferedInput(evt)) return false; return ret; }

Processing Input bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt) { static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt) { static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant

Processing Input UnbufferedInput 구현 –Mouse 와 keyboard 의 현재 상태를 얻어옴 (BaseApplication::frameRenderingQueued 에서 수행 ) 다음과 같이 사용할 준비를 한다. bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt) { static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt) { static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant mMouse->capture(); mKeyboard->capture(); mMouse->capture(); mKeyboard->capture();

Toggle 기능 구현 현재 mouse 와 마지막 mouse 상태의 비교를 통 해 구현 bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left); if (currMouse && ! mMouseDown) { Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible()); } mMouseDown = currMouse; bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left); if (currMouse && ! mMouseDown) { Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible()); } mMouseDown = currMouse;

Delayed Toggle 구현 눌린 시간을 기억하여 어느 일정시간이상 눌렸으 면 실행 mToggle -= evt.timeSinceLastFrame; if ((mToggle isKeyDown(OIS::KC_1)) { mToggle = 0.5; Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible()); } mToggle -= evt.timeSinceLastFrame; if ((mToggle isKeyDown(OIS::KC_1)) { mToggle = 0.5; Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible()); }

Keyboard 입력 구현 키보드의 상태를 찾아내어 구현 Ogre::Vector3 transVector = Ogre::Vector3::ZERO; if (mKeyboard->isKeyDown(OIS::KC_I)) // Forward transVector.z -= mMove; if (mKeyboard->isKeyDown(OIS::KC_K)) // Backward transVector.z += mMove; if (mKeyboard->isKeyDown(OIS::KC_U)) // Up transVector.y += mMove; if (mKeyboard->isKeyDown(OIS::KC_O)) // Down transVector.y -= mMove; mSceneMgr->getSceneNode("NinjaNode") ->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL); Ogre::Vector3 transVector = Ogre::Vector3::ZERO; if (mKeyboard->isKeyDown(OIS::KC_I)) // Forward transVector.z -= mMove; if (mKeyboard->isKeyDown(OIS::KC_K)) // Backward transVector.z += mMove; if (mKeyboard->isKeyDown(OIS::KC_U)) // Up transVector.y += mMove; if (mKeyboard->isKeyDown(OIS::KC_O)) // Down transVector.y -= mMove; mSceneMgr->getSceneNode("NinjaNode") ->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);

Rotate 구현 SHIFT 키와 조합하여 구현 if (mKeyboard->isKeyDown(OIS::KC_J)) // Left - yaw or strafe { if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw left mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(mRotate * 5)); } else { transVector.x -= mMove; // Strafe left } if (mKeyboard->isKeyDown(OIS::KC_L)) // Right - yaw or strafe { if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw right mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(-mRotate * 5)); } else { transVector.x += mMove; // Strafe right } if (mKeyboard->isKeyDown(OIS::KC_J)) // Left - yaw or strafe { if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw left mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(mRotate * 5)); } else { transVector.x -= mMove; // Strafe left } if (mKeyboard->isKeyDown(OIS::KC_L)) // Right - yaw or strafe { if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw right mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(-mRotate * 5)); } else { transVector.x += mMove; // Strafe right }