Add some for newer examples which didn't have those so far. Only updating this once now as some were broken. Next time on release. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6204 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			237 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 | |
| <html>
 | |
| <head>
 | |
| <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
 | |
| <meta http-equiv="X-UA-Compatible" content="IE=9"/>
 | |
| <meta name="generator" content="Doxygen 1.8.13"/>
 | |
| <meta name="viewport" content="width=device-width, initial-scale=1"/>
 | |
| <title>Tutorial 18: Splitscreen</title>
 | |
| <html xmlns="http://www.w3.org/1999/xhtml">
 | |
| <!-- Wanted to avoid copying .css to each folder, so copied default .css from doxyen in here, kicked out most stuff we don't need for examples and modified some a little bit. 
 | |
|      Target was having a single html in each example folder which is created from the main.cpp files and needs no files besides some images below media folder.
 | |
|      Feel free to improve :)
 | |
| 	 -->
 | |
| <style>
 | |
| body, table, div, p, dl {
 | |
| 	font: 400 14px/22px;
 | |
| }
 | |
| body {
 | |
| 	background-color: #F0F0F0;
 | |
| 	color: black;
 | |
| 	margin-left: 5%;
 | |
| 	margin-right: 5%;
 | |
| }
 | |
| p.reference, p.definition {
 | |
| 	font: 400 14px/22px;
 | |
| }
 | |
| .title {
 | |
| 	font: 400 14px/28px;
 | |
| 	font-size: 150%;
 | |
| 	font-weight: bold;
 | |
| 	margin: 10px 2px;
 | |
| }
 | |
| h1, h2, h3, h4, h5, h6 {
 | |
| 	-webkit-transition: text-shadow 0.5s linear;
 | |
| 	-moz-transition: text-shadow 0.5s linear;
 | |
| 	-ms-transition: text-shadow 0.5s linear;
 | |
| 	-o-transition: text-shadow 0.5s linear;
 | |
| 	transition: text-shadow 0.5s linear;
 | |
| 	margin-right: 15px;
 | |
| }
 | |
| caption {
 | |
| 	font-weight: bold;
 | |
| }
 | |
| h3.version {
 | |
| 	font-size: 90%;
 | |
| 	text-align: center;
 | |
| }
 | |
| a {
 | |
| 	color: #3D578C;
 | |
| 	font-weight: normal;
 | |
| 	text-decoration: none;
 | |
| }
 | |
| .contents a:visited {
 | |
| 	color: #4665A2;
 | |
| }
 | |
| a:hover {
 | |
| 	text-decoration: underline;
 | |
| }
 | |
| a.el {
 | |
| 	font-weight: bold;
 | |
| }
 | |
| a.code, a.code:visited, a.line, a.line:visited {
 | |
| 	color: #4665A2; 
 | |
| }
 | |
| a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
 | |
| 	color: #4665A2; 
 | |
| }
 | |
| pre.fragment {
 | |
| 	border: 1px solid #C4CFE5;
 | |
| 	background-color: #FBFCFD;
 | |
| 	padding: 4px 6px;
 | |
| 	margin: 4px 8px 4px 2px;
 | |
| 	overflow: auto;
 | |
| 	word-wrap: break-word;
 | |
| 	font-size:  9pt;
 | |
| 	line-height: 125%;
 | |
| 	font-family: monospace, fixed;
 | |
| 	font-size: 105%;
 | |
| }
 | |
| div.fragment {
 | |
| 	padding: 0px;
 | |
| 	margin: 4px 8px 4px 2px;
 | |
| 	background-color: #FBFCFD;
 | |
| 	border: 1px solid #C4CFE5;
 | |
| }
 | |
| div.line {
 | |
| 	font-family: monospace, fixed;
 | |
| 	font-size: 13px;
 | |
| 	min-height: 13px;
 | |
| 	line-height: 1.0;
 | |
| 	text-wrap: unrestricted;
 | |
| 	white-space: -moz-pre-wrap; /* Moz */
 | |
| 	white-space: -pre-wrap;     /* Opera 4-6 */
 | |
| 	white-space: -o-pre-wrap;   /* Opera 7 */
 | |
| 	white-space: pre-wrap;      /* CSS3  */
 | |
| 	word-wrap: break-word;      /* IE 5.5+ */
 | |
| 	text-indent: -53px;
 | |
| 	padding-left: 53px;
 | |
| 	padding-bottom: 0px;
 | |
| 	margin: 0px;
 | |
| 	-webkit-transition-property: background-color, box-shadow;
 | |
| 	-webkit-transition-duration: 0.5s;
 | |
| 	-moz-transition-property: background-color, box-shadow;
 | |
| 	-moz-transition-duration: 0.5s;
 | |
| 	-ms-transition-property: background-color, box-shadow;
 | |
| 	-ms-transition-duration: 0.5s;
 | |
| 	-o-transition-property: background-color, box-shadow;
 | |
| 	-o-transition-duration: 0.5s;
 | |
| 	transition-property: background-color, box-shadow;
 | |
| 	transition-duration: 0.5s;
 | |
| }
 | |
| div.contents {
 | |
| 	margin-top: 10px;
 | |
| 	margin-left: 12px;
 | |
| 	margin-right: 8px;
 | |
| }
 | |
| div.center {
 | |
| 	text-align: center;
 | |
| 	margin-top: 0px;
 | |
| 	margin-bottom: 0px;
 | |
| 	padding: 0px;
 | |
| }
 | |
| div.center img {
 | |
| 	border: 0px;
 | |
| }
 | |
| span.keyword {
 | |
| 	color: #008000
 | |
| }
 | |
| span.keywordtype {
 | |
| 	color: #604020
 | |
| }
 | |
| span.keywordflow {
 | |
| 	color: #e08000
 | |
| }
 | |
| span.comment {
 | |
| 	color: #800000
 | |
| }
 | |
| span.preprocessor {
 | |
| 	color: #806020
 | |
| }
 | |
| span.stringliteral {
 | |
| 	color: #002080
 | |
| }
 | |
| span.charliteral {
 | |
| 	color: #008080
 | |
| }
 | |
| blockquote {
 | |
| 	background-color: #F7F8FB;
 | |
| 	border-left: 2px solid #9CAFD4;
 | |
| 	margin: 0 24px 0 4px;
 | |
| 	padding: 0 12px 0 16px;
 | |
| }
 | |
| hr {
 | |
| 	height: 0px;
 | |
| 	border: none;
 | |
| 	border-top: 1px solid #4A6AAA;
 | |
| }
 | |
| address {
 | |
| 	font-style: normal;
 | |
| 	color: #2A3D61;
 | |
| }
 | |
| div.header {
 | |
| 	background-image:url('nav_h.png');
 | |
| 	background-repeat:repeat-x;
 | |
| 	background-color: #F9FAFC;
 | |
| 	margin:  0px;
 | |
| 	border-bottom: 1px solid #C4CFE5;
 | |
| }
 | |
| div.headertitle {
 | |
| 	padding: 5px 5px 5px 10px;
 | |
| }
 | |
| .image {
 | |
| 	text-align: center;
 | |
| }
 | |
| .caption {
 | |
| 	font-weight: bold;
 | |
| }
 | |
| div.zoom {
 | |
| 	border: 1px solid #90A5CE;
 | |
| }
 | |
| tr.heading h2 {
 | |
| 	margin-top: 12px;
 | |
| 	margin-bottom: 4px;
 | |
| }
 | |
| </style>
 | |
| </head>
 | |
| <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
 | |
| <!--END TITLEAREA-->
 | |
| <!-- end header part -->
 | |
| <!-- Generated by Doxygen 1.8.13 -->
 | |
| </div><!-- top -->
 | |
| <div class="header">
 | |
|   <div class="headertitle">
 | |
| <div class="title">Tutorial 18: Splitscreen </div>  </div>
 | |
| </div><!--header-->
 | |
| <div class="contents">
 | |
| <div class="textblock"><div class="image">
 | |
| <img src="../../media/example_screenshots/018shot.jpg" alt="018shot.jpg"/>
 | |
| </div>
 | |
|  <p>A tutorial by Max Winkel.</p>
 | |
| <p>In this tutorial we'll learn how to use splitscreen (e.g. for racing-games) with Irrlicht. We'll create a viewport divided into 4 parts, with 3 fixed cameras and one user-controlled.</p>
 | |
| <p>Ok, let's start with the headers (I think there's nothing to say about it) </p><div class="fragment"><div class="line"><span class="preprocessor">#include <irrlicht.h></span></div><div class="line"><span class="preprocessor">#include "driverChoice.h"</span></div><div class="line"><span class="preprocessor">#include "exampleHelper.h"</span></div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef _MSC_VER</span></div><div class="line"><span class="preprocessor">#pragma comment(lib, "Irrlicht.lib")</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="comment">//Namespaces for the engine</span></div><div class="line"><span class="keyword">using namespace </span>irr;</div><div class="line"><span class="keyword">using namespace </span>core;</div><div class="line"><span class="keyword">using namespace </span>video;</div><div class="line"><span class="keyword">using namespace </span>scene;</div></div><!-- fragment --><p> Now we'll define the resolution in a constant for use in initializing the device and setting up the viewport. In addition we set up a global variable saying splitscreen is active or not. </p><div class="fragment"><div class="line"><span class="comment">//Resolution</span></div><div class="line"><span class="keyword">const</span> <span class="keywordtype">int</span> ResX=800;</div><div class="line"><span class="keyword">const</span> <span class="keywordtype">int</span> ResY=600;</div><div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> fullScreen=<span class="keyword">false</span>;</div><div class="line"></div><div class="line"><span class="comment">//Use SplitScreen?</span></div><div class="line"><span class="keywordtype">bool</span> SplitScreen=<span class="keyword">true</span>;</div></div><!-- fragment --><p> Now we need four pointers to our cameras which are created later: </p><div class="fragment"><div class="line"><span class="comment">//cameras</span></div><div class="line">ICameraSceneNode *camera[4]={0,0,0,0};</div></div><!-- fragment --><p> In our event-receiver we switch the SplitScreen-variable, whenever the user press the S-key. All other events are sent to the FPS camera. </p><div class="fragment"><div class="line"><span class="keyword">class </span>MyEventReceiver : <span class="keyword">public</span> IEventReceiver</div><div class="line">{</div><div class="line">    <span class="keyword">public</span>:</div><div class="line">        <span class="keyword">virtual</span> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent& event)</div><div class="line">        {</div><div class="line">            <span class="comment">//Key S enables/disables SplitScreen</span></div><div class="line">            <span class="keywordflow">if</span> (event.EventType == irr::EET_KEY_INPUT_EVENT &&</div><div class="line">                event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown)</div><div class="line">            {</div><div class="line">                SplitScreen = !SplitScreen;</div><div class="line">                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line">            }</div><div class="line">            <span class="comment">//Send all other events to camera4</span></div><div class="line">            <span class="keywordflow">if</span> (camera[3])</div><div class="line">                <span class="keywordflow">return</span> camera[3]->OnEvent(event);</div><div class="line">            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">        }</div><div class="line">};</div></div><!-- fragment --><p> Ok, now the main-function: First, we initialize the device, get the SourceManager and VideoDriver, load an animated mesh from .md2 and a map from .pk3. Because that's old stuff, I won't explain every step. Just take care of the maps position. </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> main()</div><div class="line">{</div><div class="line">    <span class="comment">// ask user for driver</span></div><div class="line">    video::E_DRIVER_TYPE driverType=driverChoiceConsole();</div><div class="line">    <span class="keywordflow">if</span> (driverType==video::EDT_COUNT)</div><div class="line">        <span class="keywordflow">return</span> 1;</div><div class="line"></div><div class="line">    <span class="comment">//Instance of the EventReceiver</span></div><div class="line">    MyEventReceiver receiver;</div><div class="line"></div><div class="line">    <span class="comment">//Initialise the engine</span></div><div class="line">    IrrlichtDevice *device = createDevice(driverType,</div><div class="line">            dimension2du(ResX,ResY), 32, fullScreen,</div><div class="line">            <span class="keyword">false</span>, <span class="keyword">false</span>, &receiver);</div><div class="line">    <span class="keywordflow">if</span> (!device)</div><div class="line">        <span class="keywordflow">return</span> 1;</div><div class="line"></div><div class="line">    ISceneManager *smgr = device->getSceneManager();</div><div class="line">    IVideoDriver *driver = device->getVideoDriver();</div><div class="line"></div><div class="line">    <span class="keyword">const</span> io::path mediaPath = getExampleMediaPath();</div><div class="line"></div><div class="line">    <span class="comment">//Load model</span></div><div class="line">    IAnimatedMesh *model = smgr->getMesh(mediaPath + <span class="stringliteral">"sydney.md2"</span>);</div><div class="line">    <span class="keywordflow">if</span> (!model)</div><div class="line">        <span class="keywordflow">return</span> 1;</div><div class="line">    IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model);</div><div class="line">    <span class="comment">//Load texture</span></div><div class="line">    <span class="keywordflow">if</span> (model_node)</div><div class="line">    {</div><div class="line">        ITexture *texture = driver->getTexture(mediaPath + <span class="stringliteral">"sydney.bmp"</span>);</div><div class="line">        model_node->setMaterialTexture(0,texture);</div><div class="line">        model_node->setMD2Animation(scene::EMAT_RUN);</div><div class="line">        <span class="comment">//Disable lighting (we've got no light)</span></div><div class="line">        model_node->setMaterialFlag(EMF_LIGHTING,<span class="keyword">false</span>);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">//Load map</span></div><div class="line">    device->getFileSystem()->addFileArchive(mediaPath + <span class="stringliteral">"map-20kdm2.pk3"</span>);</div><div class="line">    IAnimatedMesh *map = smgr->getMesh(<span class="stringliteral">"20kdm2.bsp"</span>);</div><div class="line">    <span class="keywordflow">if</span> (map)</div><div class="line">    {</div><div class="line">        ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0));</div><div class="line">        <span class="comment">//Set position</span></div><div class="line">        map_node->setPosition(vector3df(-850,-220,-850));</div><div class="line">    }</div></div><!-- fragment --><p> Now we create our four cameras. One is looking at the model from the front, one from the top and one from the side. In addition there's a FPS-camera which can be controlled by the user. </p><div class="fragment"><div class="line"><span class="comment">// Create 3 fixed and one user-controlled cameras</span></div><div class="line"><span class="comment">//Front</span></div><div class="line">camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));</div><div class="line"><span class="comment">//Top</span></div><div class="line">camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));</div><div class="line"><span class="comment">//Left</span></div><div class="line">camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));</div><div class="line"><span class="comment">//User-controlled</span></div><div class="line">camera[3] = smgr->addCameraSceneNodeFPS();</div><div class="line"><span class="comment">// don't start at sydney's position</span></div><div class="line"><span class="keywordflow">if</span> (camera[3])</div><div class="line">    camera[3]->setPosition(core::vector3df(-50,0,-50));</div></div><!-- fragment --><p> Create a variable for counting the fps and hide the mouse: </p><div class="fragment"><div class="line"><span class="comment">//Hide mouse</span></div><div class="line">device->getCursorControl()->setVisible(<span class="keyword">false</span>);</div><div class="line"><span class="comment">//We want to count the fps</span></div><div class="line"><span class="keywordtype">int</span> lastFPS = -1;</div></div><!-- fragment --><p> There wasn't much new stuff - till now! Only by defining four cameras, the game won't be splitscreen. To do this you need several steps:</p><ul>
 | |
| <li>Set the viewport to the whole screen</li>
 | |
| <li>Begin a new scene (Clear screen)</li>
 | |
| <li>The following 3 steps are repeated for every viewport in the splitscreen<ul>
 | |
| <li>Set the viewport to the area you wish</li>
 | |
| <li>Activate the camera which should be "linked" with the viewport</li>
 | |
| <li>Render all objects</li>
 | |
| </ul>
 | |
| </li>
 | |
| <li>If you have a GUI:<ul>
 | |
| <li>Set the viewport the whole screen</li>
 | |
| <li>Display the GUI</li>
 | |
| </ul>
 | |
| </li>
 | |
| <li>End scene</li>
 | |
| </ul>
 | |
| <p>Sounds a little complicated, but you'll see it isn't: </p><div class="fragment"><div class="line"><span class="keywordflow">while</span>(device->run())</div><div class="line">{</div><div class="line">    <span class="comment">//Set the viewpoint to the whole screen and begin scene</span></div><div class="line">    driver->setViewPort(rect<s32>(0,0,ResX,ResY));</div><div class="line">    driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100));</div><div class="line">    <span class="comment">//If SplitScreen is used</span></div><div class="line">    <span class="keywordflow">if</span> (SplitScreen)</div><div class="line">    {</div><div class="line">        <span class="comment">//Activate camera1</span></div><div class="line">        smgr->setActiveCamera(camera[0]);</div><div class="line">        <span class="comment">//Set viewpoint to the first quarter (left top)</span></div><div class="line">        driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));</div><div class="line">        <span class="comment">//Draw scene</span></div><div class="line">        smgr->drawAll();</div><div class="line">        <span class="comment">//Activate camera2</span></div><div class="line">        smgr->setActiveCamera(camera[1]);</div><div class="line">        <span class="comment">//Set viewpoint to the second quarter (right top)</span></div><div class="line">        driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));</div><div class="line">        <span class="comment">//Draw scene</span></div><div class="line">        smgr->drawAll();</div><div class="line">        <span class="comment">//Activate camera3</span></div><div class="line">        smgr->setActiveCamera(camera[2]);</div><div class="line">        <span class="comment">//Set viewpoint to the third quarter (left bottom)</span></div><div class="line">        driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));</div><div class="line">        <span class="comment">//Draw scene</span></div><div class="line">        smgr->drawAll();</div><div class="line">        <span class="comment">//Set viewport the last quarter (right bottom)</span></div><div class="line">        driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));</div><div class="line">    }</div><div class="line">    <span class="comment">//Activate camera4</span></div><div class="line">    smgr->setActiveCamera(camera[3]);</div><div class="line">    <span class="comment">//Draw scene</span></div><div class="line">    smgr->drawAll();</div><div class="line">    driver->endScene();</div></div><!-- fragment --><p> As you can probably see, the image is rendered for every viewport separately. That means, that you'll loose much performance. Ok, if you're asking "How do I have to set the viewport
 | |
|         to get this or that screen?", don't panic. It's really easy: In the rect-function you define 4 coordinates:</p><ul>
 | |
| <li>X-coordinate of the corner left top</li>
 | |
| <li>Y-coordinate of the corner left top</li>
 | |
| <li>X-coordinate of the corner right bottom</li>
 | |
| <li>Y-coordinate of the corner right bottom</li>
 | |
| </ul>
 | |
| <p>That means, if you want to split the screen into 2 viewports you would give the following coordinates:</p><ul>
 | |
| <li>1st viewport: 0,0,ResX/2,ResY</li>
 | |
| <li>2nd viewport: ResX/2,0,ResX,ResY</li>
 | |
| </ul>
 | |
| <p>If you didn't fully understand, just play around with the example to check out what happens.</p>
 | |
| <p>Now we just view the current fps and shut down the engine, when the user wants to: </p><div class="fragment"><div class="line">        <span class="comment">//Get and show fps</span></div><div class="line">        <span class="keywordflow">if</span> (driver->getFPS() != lastFPS)</div><div class="line">        {</div><div class="line">            lastFPS = driver->getFPS();</div><div class="line">            core::stringw tmp = L<span class="stringliteral">"Irrlicht SplitScreen-Example (FPS: "</span>;</div><div class="line">            tmp += lastFPS;</div><div class="line">            tmp += <span class="stringliteral">")"</span>;</div><div class="line">            device->setWindowCaption(tmp.c_str());</div><div class="line">        }</div><div class="line">    }</div><div class="line">    <span class="comment">//Delete device</span></div><div class="line">    device->drop();</div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><p> That's it! Just compile and play around with the program. Note: With the S-Key you can switch between using splitscreen and not. </p>
 | |
| </div></div><!-- contents -->
 | |
| <!-- HTML footer for doxygen 1.8.13-->
 | |
| <!-- start footer part -->
 | |
| <p> </p>
 | |
| </body>
 | |
| </html>
 |