irrlicht/examples/18.SplitScreen/main.cpp
cutealien e50adc3066 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
2022-03-15 19:31:04 +00:00

264 lines
7.4 KiB
C++

/** Example 018 Splitscreen
A tutorial by Max Winkel.
In this tutorial we'll learn how to use split screen (e.g. for racing-games)
with Irrlicht. We'll create a viewport divided into 4 parts, with 3 fixed
cameras and one user-controlled.
OK, let's start with the headers (I think there's
nothing to say about it)
*/
#include <irrlicht.h>
#include "driverChoice.h"
#include "exampleHelper.h"
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
//Namespaces for the engine
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
using namespace gui;
/*
Now we'll define the resolution in a constant for use in
initializing the device and setting up the viewport.
*/
//Resolution
const int ResX=800;
const int ResY=600;
//Use SplitScreen?
bool SplitScreen=true;
// We allow quitting the with the ESC key
bool Quit = false;
/*
We need four pointers to our cameras which are created later:
*/
ICameraSceneNode *Camera[4]={0,0,0,0};
/*
In our event-receiver we switch the SplitScreen-variable,
whenever the user press the S-key.
We also allow quitting the application with ESC.
*/
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
//Key S enables/disables SplitScreen
if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown )
{
if ( event.KeyInput.Key == KEY_KEY_S )
{
SplitScreen = !SplitScreen;
return true;
}
if (event.KeyInput.Key == KEY_ESCAPE )
{
Quit = true;
return true;
}
}
return false;
}
};
/*
The main-function:
First, we initialize the device, get some useful variables,
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.
*/
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
//Instance of the EventReceiver
MyEventReceiver receiver;
//Initialize the engine
const bool fullScreen=false;
IrrlichtDevice *device = createDevice(driverType,
dimension2du(ResX,ResY), 32, fullScreen,
false, false, &receiver);
if (!device)
return 1;
ISceneManager *smgr = device->getSceneManager();
IVideoDriver *driver = device->getVideoDriver();
IGUIEnvironment* guienv = device->getGUIEnvironment();
const io::path mediaPath = getExampleMediaPath();
//Load model
IAnimatedMesh *model = smgr->getMesh(mediaPath + "sydney.md2");
if (!model)
return 1;
IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model);
//Load texture
if (model_node)
{
ITexture *texture = driver->getTexture(mediaPath + "sydney.bmp");
model_node->setMaterialTexture(0,texture);
model_node->setMD2Animation(scene::EMAT_RUN);
//Disable lighting (we've got no light)
model_node->setMaterialFlag(EMF_LIGHTING,false);
}
//Load map
device->getFileSystem()->addFileArchive(mediaPath + "map-20kdm2.pk3");
IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp");
if (map)
{
ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0));
//Set position
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
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.
*/
// Create 3 fixed and one user-controlled cameras
//Front
Camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
//Top
Camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
//Left
Camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));
//User-controlled
Camera[3] = smgr->addCameraSceneNodeFPS();
// don't start at Sydney's position
if (Camera[3])
Camera[3]->setPosition(core::vector3df(-50,0,-50));
/*
Hide the mouse and create a variable for counting the fps:
*/
//Hide mouse
device->getCursorControl()->setVisible(false);
//We want to count the fps
int lastFPS = -1;
/*
There wasn't much new stuff - till now!
The game won't be split the screen just by defining four cameras.
To do this several steps are needed:
- Set the viewport to the whole screen
- Begin a new scene (Clear screen)
- The following 3 steps are repeated for every viewport in the split screen
- Set the viewport to the area you wish
- Activate the camera which should be "linked" with the viewport
- Render all objects
- If you have a GUI:
- Set the viewport the whole screen
- Display the GUI
- End scene
Sounds a little complicated, but you'll see it isn't:
*/
while(!Quit && device->run())
{
// Don't reset mouse cursor when window is not active
Camera[3]->setInputReceiverEnabled(device->isWindowActive());
//Set the viewpoint to the whole screen and begin scene
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100));
//If split screen is used
if (SplitScreen)
{
//Activate camera1
smgr->setActiveCamera(Camera[0]);
//Set viewpoint to the first quarter (left top)
driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));
//Draw scene
smgr->drawAll();
//Activate camera2
smgr->setActiveCamera(Camera[1]);
//Set viewpoint to the second quarter (right top)
driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));
//Draw scene
smgr->drawAll();
//Activate camera3
smgr->setActiveCamera(Camera[2]);
//Set viewpoint to the third quarter (left bottom)
driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));
//Draw scene
smgr->drawAll();
//Set viewport the last quarter (right bottom)
driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));
}
//Activate camera4
smgr->setActiveCamera(Camera[3]);
//Draw scene
smgr->drawAll();
// Back to whole screen for the UI
if (SplitScreen)
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
guienv->drawAll();
driver->endScene();
/*
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:
- X-coordinate of the corner left top
- Y-coordinate of the corner left top
- X-coordinate of the corner right bottom
- Y-coordinate of the corner right bottom
That means, if you want to split the screen into 2 viewports
you would give the following coordinates:
- 1st viewport: 0,0,ResX/2,ResY
- 2nd viewport: ResX/2,0,ResX,ResY
If you didn't fully understand, just play around with the example
to check out what happens.
Last we show the current fps.
*/
if (driver->getFPS() != lastFPS)
{
lastFPS = driver->getFPS();
core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: ";
tmp += lastFPS;
tmp += ")";
device->setWindowCaption(tmp.c_str());
}
}
//Delete device
device->drop();
return 0;
}
/*
That's it! Just compile and play around with the program.
**/