forked from Mirrorlandia_minetest/irrlicht
Add tiny UI to SplitScreen example and some minor cleanup.
Just to show that GUI can be used print usable keys on screen. Also ESC can be used now to quit. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6307 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
parent
d31b7aa261
commit
e50adc3066
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
A tutorial by Max Winkel.
|
A tutorial by Max Winkel.
|
||||||
|
|
||||||
In this tutorial we'll learn how to use splitscreen (e.g. for racing-games)
|
In this tutorial we'll learn how to use split screen (e.g. for racing-games)
|
||||||
with Irrlicht. We'll create a viewport divided
|
with Irrlicht. We'll create a viewport divided into 4 parts, with 3 fixed
|
||||||
into 4 parts, with 3 fixed cameras and one user-controlled.
|
cameras and one user-controlled.
|
||||||
|
|
||||||
Ok, let's start with the headers (I think there's
|
OK, let's start with the headers (I think there's
|
||||||
nothing to say about it)
|
nothing to say about it)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -23,55 +23,62 @@ using namespace irr;
|
|||||||
using namespace core;
|
using namespace core;
|
||||||
using namespace video;
|
using namespace video;
|
||||||
using namespace scene;
|
using namespace scene;
|
||||||
|
using namespace gui;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we'll define the resolution in a constant for use in
|
Now we'll define the resolution in a constant for use in
|
||||||
initializing the device and setting up the viewport. In addition
|
initializing the device and setting up the viewport.
|
||||||
we set up a global variable saying splitscreen is active or not.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Resolution
|
//Resolution
|
||||||
const int ResX=800;
|
const int ResX=800;
|
||||||
const int ResY=600;
|
const int ResY=600;
|
||||||
const bool fullScreen=false;
|
|
||||||
|
|
||||||
//Use SplitScreen?
|
//Use SplitScreen?
|
||||||
bool SplitScreen=true;
|
bool SplitScreen=true;
|
||||||
|
|
||||||
|
// We allow quitting the with the ESC key
|
||||||
|
bool Quit = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we need four pointers to our cameras which are created later:
|
We need four pointers to our cameras which are created later:
|
||||||
*/
|
*/
|
||||||
//cameras
|
ICameraSceneNode *Camera[4]={0,0,0,0};
|
||||||
ICameraSceneNode *camera[4]={0,0,0,0};
|
|
||||||
/*
|
/*
|
||||||
In our event-receiver we switch the SplitScreen-variable,
|
In our event-receiver we switch the SplitScreen-variable,
|
||||||
whenever the user press the S-key. All other events are sent
|
whenever the user press the S-key.
|
||||||
to the FPS camera.
|
We also allow quitting the application with ESC.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MyEventReceiver : public IEventReceiver
|
class MyEventReceiver : public IEventReceiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool OnEvent(const SEvent& event)
|
virtual bool OnEvent(const SEvent& event)
|
||||||
{
|
{
|
||||||
//Key S enables/disables SplitScreen
|
//Key S enables/disables SplitScreen
|
||||||
if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
|
if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown )
|
||||||
event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown)
|
|
||||||
{
|
{
|
||||||
SplitScreen = !SplitScreen;
|
if ( event.KeyInput.Key == KEY_KEY_S )
|
||||||
return true;
|
{
|
||||||
|
SplitScreen = !SplitScreen;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event.KeyInput.Key == KEY_ESCAPE )
|
||||||
|
{
|
||||||
|
Quit = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Send all other events to camera4
|
|
||||||
if (camera[3])
|
|
||||||
return camera[3]->OnEvent(event);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ok, now the main-function:
|
The main-function:
|
||||||
First, we initialize the device, get the SourceManager and
|
First, we initialize the device, get some useful variables,
|
||||||
VideoDriver, load an animated mesh from .md2 and a map from
|
load an animated mesh from .md2 and a map from .pk3.
|
||||||
.pk3. Because that's old stuff, I won't explain every step.
|
Because that's old stuff, I won't explain every step.
|
||||||
Just take care of the maps position.
|
Just take care of the maps position.
|
||||||
*/
|
*/
|
||||||
int main()
|
int main()
|
||||||
@ -84,7 +91,8 @@ int main()
|
|||||||
//Instance of the EventReceiver
|
//Instance of the EventReceiver
|
||||||
MyEventReceiver receiver;
|
MyEventReceiver receiver;
|
||||||
|
|
||||||
//Initialise the engine
|
//Initialize the engine
|
||||||
|
const bool fullScreen=false;
|
||||||
IrrlichtDevice *device = createDevice(driverType,
|
IrrlichtDevice *device = createDevice(driverType,
|
||||||
dimension2du(ResX,ResY), 32, fullScreen,
|
dimension2du(ResX,ResY), 32, fullScreen,
|
||||||
false, false, &receiver);
|
false, false, &receiver);
|
||||||
@ -93,6 +101,7 @@ int main()
|
|||||||
|
|
||||||
ISceneManager *smgr = device->getSceneManager();
|
ISceneManager *smgr = device->getSceneManager();
|
||||||
IVideoDriver *driver = device->getVideoDriver();
|
IVideoDriver *driver = device->getVideoDriver();
|
||||||
|
IGUIEnvironment* guienv = device->getGUIEnvironment();
|
||||||
|
|
||||||
const io::path mediaPath = getExampleMediaPath();
|
const io::path mediaPath = getExampleMediaPath();
|
||||||
|
|
||||||
@ -121,6 +130,9 @@ int main()
|
|||||||
map_node->setPosition(vector3df(-850,-220,-850));
|
map_node->setPosition(vector3df(-850,-220,-850));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add some static text gui element, to give users information and how to show how using the UI works.
|
||||||
|
guienv->addStaticText(L"<S> to switch split screen.\n<ESC> to quit", recti(5,5, 100, 30), false, true, 0, -1, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we create our four cameras. One is looking at the model
|
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
|
from the front, one from the top and one from the side. In
|
||||||
@ -129,19 +141,19 @@ user.
|
|||||||
*/
|
*/
|
||||||
// Create 3 fixed and one user-controlled cameras
|
// Create 3 fixed and one user-controlled cameras
|
||||||
//Front
|
//Front
|
||||||
camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
|
Camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
|
||||||
//Top
|
//Top
|
||||||
camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
|
Camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
|
||||||
//Left
|
//Left
|
||||||
camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));
|
Camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));
|
||||||
//User-controlled
|
//User-controlled
|
||||||
camera[3] = smgr->addCameraSceneNodeFPS();
|
Camera[3] = smgr->addCameraSceneNodeFPS();
|
||||||
// don't start at sydney's position
|
// don't start at Sydney's position
|
||||||
if (camera[3])
|
if (Camera[3])
|
||||||
camera[3]->setPosition(core::vector3df(-50,0,-50));
|
Camera[3]->setPosition(core::vector3df(-50,0,-50));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a variable for counting the fps and hide the mouse:
|
Hide the mouse and create a variable for counting the fps:
|
||||||
*/
|
*/
|
||||||
//Hide mouse
|
//Hide mouse
|
||||||
device->getCursorControl()->setVisible(false);
|
device->getCursorControl()->setVisible(false);
|
||||||
@ -150,12 +162,12 @@ Create a variable for counting the fps and hide the mouse:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
There wasn't much new stuff - till now!
|
There wasn't much new stuff - till now!
|
||||||
Only by defining four cameras, the game won't be splitscreen.
|
The game won't be split the screen just by defining four cameras.
|
||||||
To do this you need several steps:
|
To do this several steps are needed:
|
||||||
- Set the viewport to the whole screen
|
- Set the viewport to the whole screen
|
||||||
- Begin a new scene (Clear screen)
|
- Begin a new scene (Clear screen)
|
||||||
|
|
||||||
- The following 3 steps are repeated for every viewport in the splitscreen
|
- The following 3 steps are repeated for every viewport in the split screen
|
||||||
- Set the viewport to the area you wish
|
- Set the viewport to the area you wish
|
||||||
- Activate the camera which should be "linked" with the viewport
|
- Activate the camera which should be "linked" with the viewport
|
||||||
- Render all objects
|
- Render all objects
|
||||||
@ -168,31 +180,31 @@ To do this you need several steps:
|
|||||||
Sounds a little complicated, but you'll see it isn't:
|
Sounds a little complicated, but you'll see it isn't:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while(device->run())
|
while(!Quit && device->run())
|
||||||
{
|
{
|
||||||
// Don't reset mouse cursor when window is not active
|
// Don't reset mouse cursor when window is not active
|
||||||
camera[3]->setInputReceiverEnabled(device->isWindowActive());
|
Camera[3]->setInputReceiverEnabled(device->isWindowActive());
|
||||||
|
|
||||||
//Set the viewpoint to the whole screen and begin scene
|
//Set the viewpoint to the whole screen and begin scene
|
||||||
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
|
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
|
||||||
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100));
|
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100));
|
||||||
//If SplitScreen is used
|
//If split screen is used
|
||||||
if (SplitScreen)
|
if (SplitScreen)
|
||||||
{
|
{
|
||||||
//Activate camera1
|
//Activate camera1
|
||||||
smgr->setActiveCamera(camera[0]);
|
smgr->setActiveCamera(Camera[0]);
|
||||||
//Set viewpoint to the first quarter (left top)
|
//Set viewpoint to the first quarter (left top)
|
||||||
driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));
|
driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));
|
||||||
//Draw scene
|
//Draw scene
|
||||||
smgr->drawAll();
|
smgr->drawAll();
|
||||||
//Activate camera2
|
//Activate camera2
|
||||||
smgr->setActiveCamera(camera[1]);
|
smgr->setActiveCamera(Camera[1]);
|
||||||
//Set viewpoint to the second quarter (right top)
|
//Set viewpoint to the second quarter (right top)
|
||||||
driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));
|
driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));
|
||||||
//Draw scene
|
//Draw scene
|
||||||
smgr->drawAll();
|
smgr->drawAll();
|
||||||
//Activate camera3
|
//Activate camera3
|
||||||
smgr->setActiveCamera(camera[2]);
|
smgr->setActiveCamera(Camera[2]);
|
||||||
//Set viewpoint to the third quarter (left bottom)
|
//Set viewpoint to the third quarter (left bottom)
|
||||||
driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));
|
driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));
|
||||||
//Draw scene
|
//Draw scene
|
||||||
@ -201,15 +213,21 @@ Sounds a little complicated, but you'll see it isn't:
|
|||||||
driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));
|
driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));
|
||||||
}
|
}
|
||||||
//Activate camera4
|
//Activate camera4
|
||||||
smgr->setActiveCamera(camera[3]);
|
smgr->setActiveCamera(Camera[3]);
|
||||||
//Draw scene
|
//Draw scene
|
||||||
smgr->drawAll();
|
smgr->drawAll();
|
||||||
|
|
||||||
|
// Back to whole screen for the UI
|
||||||
|
if (SplitScreen)
|
||||||
|
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
|
||||||
|
guienv->drawAll();
|
||||||
|
|
||||||
driver->endScene();
|
driver->endScene();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
As you can probably see, the image is rendered for every
|
As you can probably see, the image is rendered for every
|
||||||
viewport separately. That means, that you'll loose much performance.
|
viewport separately. That means, that you'll loose much performance.
|
||||||
Ok, if you're asking "How do I have to set the viewport
|
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
|
to get this or that screen?", don't panic. It's really
|
||||||
easy: In the rect-function you define 4 coordinates:
|
easy: In the rect-function you define 4 coordinates:
|
||||||
- X-coordinate of the corner left top
|
- X-coordinate of the corner left top
|
||||||
@ -225,10 +243,8 @@ Sounds a little complicated, but you'll see it isn't:
|
|||||||
If you didn't fully understand, just play around with the example
|
If you didn't fully understand, just play around with the example
|
||||||
to check out what happens.
|
to check out what happens.
|
||||||
|
|
||||||
Now we just view the current fps and shut down the engine,
|
Last we show the current fps.
|
||||||
when the user wants to:
|
|
||||||
*/
|
*/
|
||||||
//Get and show fps
|
|
||||||
if (driver->getFPS() != lastFPS)
|
if (driver->getFPS() != lastFPS)
|
||||||
{
|
{
|
||||||
lastFPS = driver->getFPS();
|
lastFPS = driver->getFPS();
|
||||||
@ -244,7 +260,4 @@ Sounds a little complicated, but you'll see it isn't:
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
That's it! Just compile and play around with the program.
|
That's it! Just compile and play around with the program.
|
||||||
Note: With the S-Key you can switch between using splitscreen
|
|
||||||
and not.
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user