Basic Tutorial 5
From PyWiki
WARNING - per discussion on ogre3d.org this tutorial is not up to date and does not illustrate how to do buffered input; however, that discussion does provide some hints on the subject. Tutorial 6 explains (shortly) how to set up Buffered Input and Tutorial 7 uses Buffered Input, too.
Contents |
Basic Tutorial 05: Buffered Input
Prerequisites
This tutorial assumes you have knowledge of Python programming and you have already installed Python-Ogre. This tutorial builds on the material covered in previous tutorials, and it assumes you have read them.
Introduction
In this short tutorial you will be learning to use Ogre's buffered input as opposed to the unbuffered input we used in Tutorial 04. Ogre3D 1.4.0 uses OIS (Object-oriented Input Library). For more details on using OIS with Ogre3d, please refer to Using OIS. The input devices are separated into multiple objects. This tutorial refers to both "Mouse" and "Keyboard" for each respective device we are dealing with.
As you go through the tutorial you should be slowly adding code to your own project and watching the results as we build it. If you are having problems you can view the completed source code example posted at the end of this tutorial.
Getting Started
This tutorial will be building on the Tutorial 04, but we are changing the way that we do input. Since the functionality will be basically the same, we will use the same TutorialApplication class, but we will be starting over on the TutorialFrameListener class. Create a file named basic_5.py:
import ogre.renderer.OGRE as ogre import ogre.io.OIS as OIS import SampleFramework as sf class TutorialFrameListener(sf.FrameListener): """A FrameListener class that handles basic user input.""" def __init__(self, renderWindow, camera, sceneManager): # Subclass any Python-Ogre class and you must call its constructor. sf.FrameListener.__init__(self, renderWindow, camera) # Populate the camera and scene manager containers. self.camNode = camera.parentSceneNode.parentSceneNode self.sceneManager = sceneManager self.eventProcessor = None self.rotate = 0.1 # Rotation speed. self.move = 250 # Movement speed. self.direction = ogre.Vector3(0, 0, 0) # Direction heading. self.keepRendering = True def frameStarted(self, frameEvent): # If the render window has been closed, end the program. if(self.renderWindow.isClosed()): return False return self.keepRendering class TutorialApplication(sf.Application): """The Application class.""" def _createScene(self): # Setup a scene with a low level of ambient light. sceneManager = self.sceneManager sceneManager.ambientLight = 0.25, 0.25, 0.25 # Setup a mesh entity and attach it to a scene node. entity = sceneManager.createEntity('Ninja', 'ninja.mesh') node = sceneManager.rootSceneNode.createChildSceneNode('NinjaNode') node.attachObject(entity) # Setup a White point light. light = sceneManager.createLight('Light1') light.type = ogre.Light.LT_POINT light.position = 250, 150, 250 light.diffuseColour = 1, 1, 1 light.specularColour = 1, 1, 1 # Setup the first camera node and pitch node and aim it. node = sceneManager.rootSceneNode.createChildSceneNode('CamNode1', (-400, 200, 400)) node.yaw(ogre.Degree(-45)) node = node.createChildSceneNode('PitchNode1') node.attachObject(self.camera) # Setup the second camera node and pitch node. node = sceneManager.rootSceneNode.createChildSceneNode('CamNode2', (0, 200, 400)) node.createChildSceneNode('PitchNode2') def _createCamera(self): self.camera = self.sceneManager.createCamera('PlayerCam') self.camera.nearClipDistance = 5 def _createFrameListener(self): self.frameListener = TutorialFrameListener(self.renderWindow, self.camera, self.sceneManager) self.root.addFrameListener(self.frameListener) self.frameListener.showDebugOverlay(True) if __name__ == '__main__': try: ta = TutorialApplication() ta.go() except ogre.OgreException, e: print e
The controls will be the same as used in the Tutorial 04.
Buffered Input in Ogre
Introduction
In the previous tutorial we used unbuffered input, that is, every frame we queried the state of an input device to see what keys and mouse buttons were being held down. Buffered input uses mouse and key listener interfaces to update objects. For example, when a key is pressed, a KeyListener.keyPressed event is fired and when the button is released (no longer being pressed) a KeyListener.keyReleased event is fired to all registered KeyListener classes. This takes care of having to keep track of toggle times or whether the key was pressed or not during the previous frame.
Combining FrameListeners with Input Listeners
Even though in this tutorial our FrameListener is also the key and mouse listener, please don't get stuck in the concept of having to combine the FrameListener with the key and mouse listeners. It's often a very good idea to split the two up, especially in larger applications.
OIS Input Interfaces
There are two interfaces we will be using. The Keyboard interface utilizes a callback listener for key events and the Mouse interface utilizes a listener for mouse button and position events within a MouseState structure.
KeyListener
The Keyboard interface is relatively simple. You have the callback listener, which has two events, keyPressed and keyReleased. You can also check the status of an individual key using the callback methods isKeyDown and isModifierDown instead of worrying about events.
MouseListener
The MouseListener interface defines functions for getting mouse input. With the MouseState structure you can receive the very latest recorded mouse state. In it, you have easy access to the relative X/Y/Z and absolute X/Y/Z values. You can also determine the state of any button by using the buttonDown method to test for button IDs, MB_Left, MB_Right, MB_Middle, MB_Button3, MB_Button4, MB_Button5, MB_Button6, and MB_Button7.
TutorialFrameListener
Complete Source Code Example
#!/usr/bin/env python # This code is Public Domain and was written for Python-Ogre 1.0. """Python-Ogre Beginner Tutorial 05: Buffered Input.""" import ogre.renderer.OGRE as ogre import ogre.io.OIS as OIS import SampleFramework as sf class TutorialFrameListener(sf.FrameListener): """A FrameListener class that handles basic user input.""" def __init__(self, renderWindow, camera, sceneManager): # Subclass any Python-Ogre class and you must call its constructor. sf.FrameListener.__init__(self, renderWindow, camera) # Populate the camera and scene manager containers. self.camNode = camera.parentSceneNode.parentSceneNode self.sceneManager = sceneManager self.eventProcessor = None self.rotate = 0.1 self.move = 250 self.direction = ogre.Vector3(0, 0, 0) self.keepRendering = True def _setupInput(self): # Initialize OIS. windowHnd = self.renderWindow.getCustomAttributeInt("WINDOW") self.InputManager = OIS.createPythonInputSystem([("WINDOW", str(windowHnd))]) # Create all devices, only catch joystick exceptions since most people use Key/Mouse. self.Keyboard = self.InputManager.createInputObjectKeyboard(OIS.OISKeyboard, self.bufferedKeys) self.Mouse = self.InputManager.createInputObjectMouse(OIS.OISMouse, self.bufferedMouse) try: self.Joy = self.InputManager.createInputObjectJoyStick(OIS.OISJoyStick, self.bufferedJoy) except: self.Joy = False #Set initial mouse clipping size. self.windowResized(self.renderWindow) # Register as a Window listener. ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self); def frameStarted(self, frameEvent): if(self.renderWindow.isClosed()): return False # Capture and update each device, this will also trigger any listeners. self.Keyboard.capture() self.Mouse.capture() # Process unbuffered key input. if not self.keyPressed(frameEvent): return False # Translate the camera based on time. self.camNode.translate(self.camNode.orientation * self.direction * frameEvent.timeSinceLastFrame) # Check for Key release to stop moving the camera. self.keyReleased(frameEvent) # Process unbuffered mouse input. self.mousePressed(frameEvent) self.mouseDragged(frameEvent) return self.keepRendering def keyPressed(self, frameEvent): # Stop Rendering if Escape was pressed. if self.Keyboard.isKeyDown(OIS.KC_ESCAPE): return False # Attach the camera to PitchNode1. if self.Keyboard.isKeyDown(OIS.KC_1): self.camera.parentSceneNode.detachObject(self.camera) self.camNode = self.sceneManager.getSceneNode("CamNode1") self.sceneManager.getSceneNode("PitchNode1").attachObject(self.camera) # Attach the camera to PitchNode2. if self.Keyboard.isKeyDown(OIS.KC_2): self.camera.parentSceneNode.detachObject(self.camera) self.camNode = self.sceneManager.getSceneNode("CamNode2") self.sceneManager.getSceneNode("PitchNode2").attachObject(self.camera) # Move Forward. if self.Keyboard.isKeyDown(OIS.KC_UP) or self.Keyboard.isKeyDown(OIS.KC_W): self.direction.z -= self.move # Move Backward. if self.Keyboard.isKeyDown(OIS.KC_DOWN) or self.Keyboard.isKeyDown(OIS.KC_S): self.direction.z += self.move # Strafe Left. if self.Keyboard.isKeyDown(OIS.KC_LEFT) or self.Keyboard.isKeyDown(OIS.KC_A): self.direction.x -= self.move # Strafe Right. if self.Keyboard.isKeyDown(OIS.KC_RIGHT) or self.Keyboard.isKeyDown(OIS.KC_D): self.direction.x += self.move # Move Up. if self.Keyboard.isKeyDown(OIS.KC_PGUP) or self.Keyboard.isKeyDown(OIS.KC_Q): self.direction.y += self.move # Move Down. if self.Keyboard.isKeyDown(OIS.KC_PGDOWN) or self.Keyboard.isKeyDown(OIS.KC_E): self.direction.y -= self.move return True def keyReleased(self, frameEvent): # Undo change to the direction vector when the key is released to stop movement. if self.Keyboard.isKeyDown(OIS.KC_UP) or self.Keyboard.isKeyDown(OIS.KC_W): self.direction.z += self.move # Move Backward. if self.Keyboard.isKeyDown(OIS.KC_DOWN) or self.Keyboard.isKeyDown(OIS.KC_S): self.direction.z -= self.move # Strafe Left. if self.Keyboard.isKeyDown(OIS.KC_LEFT) or self.Keyboard.isKeyDown(OIS.KC_A): self.direction.x += self.move # Strafe Right. if self.Keyboard.isKeyDown(OIS.KC_RIGHT) or self.Keyboard.isKeyDown(OIS.KC_D): self.direction.x -= self.move # Move Up. if self.Keyboard.isKeyDown(OIS.KC_PGUP) or self.Keyboard.isKeyDown(OIS.KC_Q): self.direction.y -= self.move # Move Down. if self.Keyboard.isKeyDown(OIS.KC_PGDOWN) or self.Keyboard.isKeyDown(OIS.KC_E): self.direction.y += self.move def mousePressed(self, frameEvent): ms = self.Mouse.getMouseState() # Toggle the light. if ms.buttonDown(OIS.MB_Left): light = self.sceneManager.getLight('Light1') light.visible = not light.visible def mouseDragged(self, frameEvent): # Rotate the camera. ms = self.Mouse.getMouseState() if ms.buttonDown(OIS.MB_Right): self.camNode.yaw(ogre.Degree(-self.rotate * ms.X.rel).valueRadians()) self.camNode.getChild(0).pitch(ogre.Degree(-self.rotate * ms.Y.rel).valueRadians()) class TutorialApplication(sf.Application): """Application class.""" def _createScene(self): sceneManager = self.sceneManager sceneManager.ambientLight = 0.25, 0.25, 0.25 ent = sceneManager.createEntity("Ninja", "ninja.mesh") node = sceneManager.getRootSceneNode().createChildSceneNode("NinjaNode") node.attachObject(ent) light = sceneManager.createLight("Light1") light.type = ogre.Light.LT_POINT light.position = 250, 150, 250 light.diffuseColour = 1, 1, 1 light.specularColour = 1, 1, 1 # create the first camera node/pitch node node = sceneManager.getRootSceneNode().createChildSceneNode("CamNode1", (-400, 200, 400)) node.yaw(ogre.Degree(-45)) node = node.createChildSceneNode("PitchNode1") node.attachObject(self.camera) # create the second camera node/pitch node node = sceneManager.getRootSceneNode().createChildSceneNode("CamNode2", (0, 200, 400)) node.createChildSceneNode("PitchNode2") def _createCamera(self): self.camera = self.sceneManager.createCamera("PlayerCam") self.camera.nearClipDistance = 5 def _createFrameListener(self): self.frameListener = TutorialFrameListener(self.renderWindow, self.camera, self.sceneManager) self.root.addFrameListener(self.frameListener) self.frameListener.showDebugOverlay(True) if __name__ == '__main__': try: ta = TutorialApplication() ta.go() except ogre.OgreException, e: print e
- Proceed to Basic Tutorial 6 The Ogre Startup Sequence
| Python-Ogre Tutorials |
|---|
|
Python-Ogre Beginner Tutorials: Beginner 1 - Beginner 2 - Beginner 3 - Beginner 4 - Beginner 5 - Beginner 6 - Beginner 7 - Beginner 8 Intermediate Tutorials: Intermediate 1 - Intermediate 2 - Intermediate 3 - Intermediate 4 - Intermediate 5 - Intermediate 6 Advanced Tutorials: Advanced 1 See also: Artist Tutorials - Ogre Articles - Cookbook |