irrlicht/doc/html/example018.html
2020-05-16 23:31:28 +02:00

317 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 xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>Irrlicht 3D Engine: Tutorial 18: Splitscreen</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
$(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
</head>
<body>
<div id="top"><!-- do not remove this div! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="irrlichtlogo.png"/></td>
<td style="padding-left: 0.5em;">
<div id="projectname">Irrlicht 3D Engine
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Generated by Doxygen 1.7.5.1 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="dynsections.js"></script>
</div>
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
initNavTree('example018.html','');
</script>
<div id="doc-content">
<div class="header">
<div class="headertitle">
<div class="title">Tutorial 18: Splitscreen </div> </div>
</div>
<div class="contents">
<div class="textblock"><div class="image">
<img src="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"><pre class="fragment"><span class="preprocessor">#include &lt;<a class="code" href="irrlicht_8h.html" title="Main header file of the irrlicht, the only file needed to include.">irrlicht.h</a>&gt;</span>
<span class="preprocessor">#include &quot;<a class="code" href="driver_choice_8h.html">driverChoice.h</a>&quot;</span>
<span class="preprocessor">#ifdef _MSC_VER</span>
<span class="preprocessor"></span><span class="preprocessor">#pragma comment(lib, &quot;Irrlicht.lib&quot;)</span>
<span class="preprocessor"></span><span class="preprocessor">#endif</span>
<span class="preprocessor"></span>
<span class="comment">//Namespaces for the engine</span>
<span class="keyword">using namespace </span>irr;
<span class="keyword">using namespace </span>core;
<span class="keyword">using namespace </span>video;
<span class="keyword">using namespace </span>scene;
</pre></div><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"><pre class="fragment"><span class="comment">//Resolution</span>
<span class="keyword">const</span> <span class="keywordtype">int</span> ResX=800;
<span class="keyword">const</span> <span class="keywordtype">int</span> ResY=600;
<span class="keyword">const</span> <span class="keywordtype">bool</span> fullScreen=<span class="keyword">false</span>;
<span class="comment">//Use SplitScreen?</span>
<span class="keywordtype">bool</span> SplitScreen=<span class="keyword">true</span>;
</pre></div><p>Now we need four pointers to our cameras which are created later: </p>
<div class="fragment"><pre class="fragment"><span class="comment">//cameras</span>
ICameraSceneNode *camera[4]={0,0,0,0};
</pre></div><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"><pre class="fragment"><span class="keyword">class </span>MyEventReceiver : <span class="keyword">public</span> IEventReceiver
{
<span class="keyword">public</span>:
<span class="keyword">virtual</span> <span class="keywordtype">bool</span> OnEvent(<span class="keyword">const</span> SEvent&amp; event)
{
<span class="comment">//Key S enables/disables SplitScreen</span>
<span class="keywordflow">if</span> (event.EventType == <a class="code" href="namespaceirr.html#ac9eed96e06e85ce3c86fcbbbe9e48a0ca6f90390f3147a1693e5e2e3422d6ca09" title="A key input event.">irr::EET_KEY_INPUT_EVENT</a> &amp;&amp;
event.KeyInput.Key == <a class="code" href="namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3ae52bafc112fc6c52f6b49cea42fa246e">KEY_KEY_S</a> &amp;&amp; event.KeyInput.PressedDown)
{
SplitScreen = !SplitScreen;
<span class="keywordflow">return</span> <span class="keyword">true</span>;
}
<span class="comment">//Send all other events to camera4</span>
<span class="keywordflow">if</span> (camera[3])
<span class="keywordflow">return</span> camera[3]-&gt;OnEvent(event);
<span class="keywordflow">return</span> <span class="keyword">false</span>;
}
};
</pre></div><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"><pre class="fragment"><span class="keywordtype">int</span> main()
{
<span class="comment">// ask user for driver</span>
<a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0" title="An enum for all types of drivers the Irrlicht Engine supports.">video::E_DRIVER_TYPE</a> driverType=driverChoiceConsole();
<span class="keywordflow">if</span> (driverType==<a class="code" href="namespaceirr_1_1video.html#ae35a6de6d436c76107ad157fe42356d0ae685cada50f8c100403134d932d0414c" title="No driver, just for counting the elements.">video::EDT_COUNT</a>)
<span class="keywordflow">return</span> 1;
<span class="comment">//Instance of the EventReceiver</span>
MyEventReceiver receiver;
<span class="comment">//Initialise the engine</span>
IrrlichtDevice *device = <a class="code" href="namespaceirr.html#abaf4d8719cc26b0d30813abf85e47c76" title="Creates an Irrlicht device. The Irrlicht device is the root object for using the engine.">createDevice</a>(driverType,
<a class="code" href="namespaceirr_1_1core.html#ad2e562e3219072e2f7fc7c2bba0ef0cb" title="Typedef for an unsigned integer dimension.">dimension2du</a>(ResX,ResY), 32, fullScreen,
<span class="keyword">false</span>, <span class="keyword">false</span>, &amp;receiver);
<span class="keywordflow">if</span> (!device)
<span class="keywordflow">return</span> 1;
ISceneManager *smgr = device-&gt;getSceneManager();
IVideoDriver *driver = device-&gt;getVideoDriver();
<span class="comment">//Load model</span>
IAnimatedMesh *model = smgr-&gt;getMesh(<span class="stringliteral">&quot;../../media/sydney.md2&quot;</span>);
<span class="keywordflow">if</span> (!model)
<span class="keywordflow">return</span> 1;
IAnimatedMeshSceneNode *model_node = smgr-&gt;addAnimatedMeshSceneNode(model);
<span class="comment">//Load texture</span>
<span class="keywordflow">if</span> (model_node)
{
ITexture *texture = driver-&gt;getTexture(<span class="stringliteral">&quot;../../media/sydney.bmp&quot;</span>);
model_node-&gt;setMaterialTexture(0,texture);
model_node-&gt;setMD2Animation(<a class="code" href="namespaceirr_1_1scene.html#a08d4a84966e1d2886d0d57e4acbb4f19af240ef944e6e257ec369f87053c756e8">scene::EMAT_RUN</a>);
<span class="comment">//Disable lighting (we&#39;ve got no light)</span>
model_node-&gt;setMaterialFlag(<a class="code" href="namespaceirr_1_1video.html#a8a3bc00ae8137535b9fbc5f40add70d3acea597a2692b8415486a464a7f954d34" title="Will this material be lighted? Default: true.">EMF_LIGHTING</a>,<span class="keyword">false</span>);
}
<span class="comment">//Load map</span>
device-&gt;getFileSystem()-&gt;addFileArchive(<span class="stringliteral">&quot;../../media/map-20kdm2.pk3&quot;</span>);
IAnimatedMesh *map = smgr-&gt;getMesh(<span class="stringliteral">&quot;20kdm2.bsp&quot;</span>);
<span class="keywordflow">if</span> (map)
{
ISceneNode *map_node = smgr-&gt;addOctreeSceneNode(map-&gt;getMesh(0));
<span class="comment">//Set position</span>
map_node-&gt;setPosition(<a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(-850,-220,-850));
}
</pre></div><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"><pre class="fragment"> <span class="comment">// Create 3 fixed and one user-controlled cameras</span>
<span class="comment">//Front</span>
camera[0] = smgr-&gt;addCameraSceneNode(0, <a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(50,0,0), <a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(0,0,0));
<span class="comment">//Top</span>
camera[1] = smgr-&gt;addCameraSceneNode(0, <a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(0,50,0), <a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(0,0,0));
<span class="comment">//Left</span>
camera[2] = smgr-&gt;addCameraSceneNode(0, <a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(0,0,50), <a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">vector3df</a>(0,0,0));
<span class="comment">//User-controlled</span>
camera[3] = smgr-&gt;addCameraSceneNodeFPS();
<span class="comment">// don&#39;t start at sydney&#39;s position</span>
<span class="keywordflow">if</span> (camera[3])
camera[3]-&gt;setPosition(<a class="code" href="namespaceirr_1_1core.html#a06f169d08b5c429f5575acb7edbad811" title="Typedef for a f32 3d vector.">core::vector3df</a>(-50,0,-50));
</pre></div><p>Create a variable for counting the fps and hide the mouse: </p>
<div class="fragment"><pre class="fragment"> <span class="comment">//Hide mouse</span>
device-&gt;getCursorControl()-&gt;setVisible(<span class="keyword">false</span>);
<span class="comment">//We want to count the fps</span>
<span class="keywordtype">int</span> lastFPS = -1;
</pre></div><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>
</ul>
<ul>
<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>
</ul>
<ul>
<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"><pre class="fragment"> <span class="keywordflow">while</span>(device-&gt;run())
{
<span class="comment">//Set the viewpoint to the whole screen and begin scene</span>
driver-&gt;setViewPort(rect&lt;s32&gt;(0,0,ResX,ResY));
driver-&gt;beginScene(<span class="keyword">true</span>,<span class="keyword">true</span>,SColor(255,100,100,100));
<span class="comment">//If SplitScreen is used</span>
<span class="keywordflow">if</span> (SplitScreen)
{
<span class="comment">//Activate camera1</span>
smgr-&gt;setActiveCamera(camera[0]);
<span class="comment">//Set viewpoint to the first quarter (left top)</span>
driver-&gt;setViewPort(rect&lt;s32&gt;(0,0,ResX/2,ResY/2));
<span class="comment">//Draw scene</span>
smgr-&gt;drawAll();
<span class="comment">//Activate camera2</span>
smgr-&gt;setActiveCamera(camera[1]);
<span class="comment">//Set viewpoint to the second quarter (right top)</span>
driver-&gt;setViewPort(rect&lt;s32&gt;(ResX/2,0,ResX,ResY/2));
<span class="comment">//Draw scene</span>
smgr-&gt;drawAll();
<span class="comment">//Activate camera3</span>
smgr-&gt;setActiveCamera(camera[2]);
<span class="comment">//Set viewpoint to the third quarter (left bottom)</span>
driver-&gt;setViewPort(rect&lt;s32&gt;(0,ResY/2,ResX/2,ResY));
<span class="comment">//Draw scene</span>
smgr-&gt;drawAll();
<span class="comment">//Set viewport the last quarter (right bottom)</span>
driver-&gt;setViewPort(rect&lt;s32&gt;(ResX/2,ResY/2,ResX,ResY));
}
<span class="comment">//Activate camera4</span>
smgr-&gt;setActiveCamera(camera[3]);
<span class="comment">//Draw scene</span>
smgr-&gt;drawAll();
driver-&gt;endScene();
</pre></div><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"><pre class="fragment"> <span class="comment">//Get and show fps</span>
<span class="keywordflow">if</span> (driver-&gt;getFPS() != lastFPS)
{
lastFPS = driver-&gt;getFPS();
<a class="code" href="namespaceirr_1_1core.html#aef83fafbb1b36fcce44c07c9be23a7f2" title="Typedef for wide character strings.">core::stringw</a> tmp = L<span class="stringliteral">&quot;Irrlicht SplitScreen-Example (FPS: &quot;</span>;
tmp += lastFPS;
tmp += <span class="stringliteral">&quot;)&quot;</span>;
device-&gt;setWindowCaption(tmp.c_str());
}
}
<span class="comment">//Delete device</span>
device-&gt;drop();
<span class="keywordflow">return</span> 0;
}
</pre></div><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>
</div>
<div id="nav-path" class="navpath">
<ul>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Namespaces</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Friends</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(10)"><span class="SelectionMark">&#160;</span>Defines</a></div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<li class="footer">
<a href="http://irrlicht.sourceforge.net" target="_blank">Irrlicht
Engine</a> Documentation &copy; 2003-2012 by Nikolaus Gebhardt. Generated on Sat Jul 9 2016 18:18:26 for Irrlicht 3D Engine by
<a href="http://www.doxygen.org/index.html" target="_blank">Doxygen</a> 1.7.5.1 </li>
</ul>
</div>
</body>
</html>