main.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /** Example 018 Splitscreen
  2. A tutorial by Max Winkel.
  3. In this tutorial we'll learn how to use splitscreen (e.g. for racing-games)
  4. with Irrlicht. We'll create a viewport divided
  5. into 4 parts, with 3 fixed cameras and one user-controlled.
  6. Ok, let's start with the headers (I think there's
  7. nothing to say about it)
  8. */
  9. #include <irrlicht.h>
  10. #include "driverChoice.h"
  11. #include "exampleHelper.h"
  12. #ifdef _MSC_VER
  13. #pragma comment(lib, "Irrlicht.lib")
  14. #endif
  15. //Namespaces for the engine
  16. using namespace irr;
  17. using namespace core;
  18. using namespace video;
  19. using namespace scene;
  20. /*
  21. Now we'll define the resolution in a constant for use in
  22. initializing the device and setting up the viewport. In addition
  23. we set up a global variable saying splitscreen is active or not.
  24. */
  25. //Resolution
  26. const int ResX=800;
  27. const int ResY=600;
  28. const bool fullScreen=false;
  29. //Use SplitScreen?
  30. bool SplitScreen=true;
  31. /*
  32. Now we need four pointers to our cameras which are created later:
  33. */
  34. //cameras
  35. ICameraSceneNode *camera[4]={0,0,0,0};
  36. /*
  37. In our event-receiver we switch the SplitScreen-variable,
  38. whenever the user press the S-key. All other events are sent
  39. to the FPS camera.
  40. */
  41. class MyEventReceiver : public IEventReceiver
  42. {
  43. public:
  44. virtual bool OnEvent(const SEvent& event)
  45. {
  46. //Key S enables/disables SplitScreen
  47. if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
  48. event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown)
  49. {
  50. SplitScreen = !SplitScreen;
  51. return true;
  52. }
  53. //Send all other events to camera4
  54. if (camera[3])
  55. return camera[3]->OnEvent(event);
  56. return false;
  57. }
  58. };
  59. /*
  60. Ok, now the main-function:
  61. First, we initialize the device, get the SourceManager and
  62. VideoDriver, load an animated mesh from .md2 and a map from
  63. .pk3. Because that's old stuff, I won't explain every step.
  64. Just take care of the maps position.
  65. */
  66. int main()
  67. {
  68. // ask user for driver
  69. video::E_DRIVER_TYPE driverType=driverChoiceConsole();
  70. if (driverType==video::EDT_COUNT)
  71. return 1;
  72. //Instance of the EventReceiver
  73. MyEventReceiver receiver;
  74. //Initialise the engine
  75. IrrlichtDevice *device = createDevice(driverType,
  76. dimension2du(ResX,ResY), 32, fullScreen,
  77. false, false, &receiver);
  78. if (!device)
  79. return 1;
  80. ISceneManager *smgr = device->getSceneManager();
  81. IVideoDriver *driver = device->getVideoDriver();
  82. const io::path mediaPath = getExampleMediaPath();
  83. //Load model
  84. IAnimatedMesh *model = smgr->getMesh(mediaPath + "sydney.md2");
  85. if (!model)
  86. return 1;
  87. IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model);
  88. //Load texture
  89. if (model_node)
  90. {
  91. ITexture *texture = driver->getTexture(mediaPath + "sydney.bmp");
  92. model_node->setMaterialTexture(0,texture);
  93. model_node->setMD2Animation(scene::EMAT_RUN);
  94. //Disable lighting (we've got no light)
  95. model_node->setMaterialFlag(EMF_LIGHTING,false);
  96. }
  97. //Load map
  98. device->getFileSystem()->addFileArchive(mediaPath + "map-20kdm2.pk3");
  99. IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp");
  100. if (map)
  101. {
  102. ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0));
  103. //Set position
  104. map_node->setPosition(vector3df(-850,-220,-850));
  105. }
  106. /*
  107. Now we create our four cameras. One is looking at the model
  108. from the front, one from the top and one from the side. In
  109. addition there's a FPS-camera which can be controlled by the
  110. user.
  111. */
  112. // Create 3 fixed and one user-controlled cameras
  113. //Front
  114. camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
  115. //Top
  116. camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
  117. //Left
  118. camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));
  119. //User-controlled
  120. camera[3] = smgr->addCameraSceneNodeFPS();
  121. // don't start at sydney's position
  122. if (camera[3])
  123. camera[3]->setPosition(core::vector3df(-50,0,-50));
  124. /*
  125. Create a variable for counting the fps and hide the mouse:
  126. */
  127. //Hide mouse
  128. device->getCursorControl()->setVisible(false);
  129. //We want to count the fps
  130. int lastFPS = -1;
  131. /*
  132. There wasn't much new stuff - till now!
  133. Only by defining four cameras, the game won't be splitscreen.
  134. To do this you need several steps:
  135. - Set the viewport to the whole screen
  136. - Begin a new scene (Clear screen)
  137. - The following 3 steps are repeated for every viewport in the splitscreen
  138. - Set the viewport to the area you wish
  139. - Activate the camera which should be "linked" with the viewport
  140. - Render all objects
  141. - If you have a GUI:
  142. - Set the viewport the whole screen
  143. - Display the GUI
  144. - End scene
  145. Sounds a little complicated, but you'll see it isn't:
  146. */
  147. while(device->run())
  148. {
  149. //Set the viewpoint to the whole screen and begin scene
  150. driver->setViewPort(rect<s32>(0,0,ResX,ResY));
  151. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100));
  152. //If SplitScreen is used
  153. if (SplitScreen)
  154. {
  155. //Activate camera1
  156. smgr->setActiveCamera(camera[0]);
  157. //Set viewpoint to the first quarter (left top)
  158. driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));
  159. //Draw scene
  160. smgr->drawAll();
  161. //Activate camera2
  162. smgr->setActiveCamera(camera[1]);
  163. //Set viewpoint to the second quarter (right top)
  164. driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));
  165. //Draw scene
  166. smgr->drawAll();
  167. //Activate camera3
  168. smgr->setActiveCamera(camera[2]);
  169. //Set viewpoint to the third quarter (left bottom)
  170. driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));
  171. //Draw scene
  172. smgr->drawAll();
  173. //Set viewport the last quarter (right bottom)
  174. driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));
  175. }
  176. //Activate camera4
  177. smgr->setActiveCamera(camera[3]);
  178. //Draw scene
  179. smgr->drawAll();
  180. driver->endScene();
  181. /*
  182. As you can probably see, the image is rendered for every
  183. viewport separately. That means, that you'll loose much performance.
  184. Ok, if you're asking "How do I have to set the viewport
  185. to get this or that screen?", don't panic. It's really
  186. easy: In the rect-function you define 4 coordinates:
  187. - X-coordinate of the corner left top
  188. - Y-coordinate of the corner left top
  189. - X-coordinate of the corner right bottom
  190. - Y-coordinate of the corner right bottom
  191. That means, if you want to split the screen into 2 viewports
  192. you would give the following coordinates:
  193. - 1st viewport: 0,0,ResX/2,ResY
  194. - 2nd viewport: ResX/2,0,ResX,ResY
  195. If you didn't fully understand, just play around with the example
  196. to check out what happens.
  197. Now we just view the current fps and shut down the engine,
  198. when the user wants to:
  199. */
  200. //Get and show fps
  201. if (driver->getFPS() != lastFPS)
  202. {
  203. lastFPS = driver->getFPS();
  204. core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: ";
  205. tmp += lastFPS;
  206. tmp += ")";
  207. device->setWindowCaption(tmp.c_str());
  208. }
  209. }
  210. //Delete device
  211. device->drop();
  212. return 0;
  213. }
  214. /*
  215. That's it! Just compile and play around with the program.
  216. Note: With the S-Key you can switch between using splitscreen
  217. and not.
  218. **/