19-08-2015, 09:00 PM
Tutorial 18: Splitscreen
Un tutorial di Max Winkel.
In questo tutorial impareremo come usare lo splitscreen (e.g. La divisione dello schermo tipica dei racing-games) con Irrlicht. Creeremo un viewport diviso in 4 parti, con 3 camere fisse ed una controllata dall'utente.
Ok, partiamo dagli headers (non credo ci sia nulla da aggiungere).
Ora definiremo la risoluzione con una costante per inizializzare il device all'avvio e impostiamo la variabile globale viewport a true che ci indichi se la vista splitscreen è attiva o no.
Ci servono quattro puntatori alle camere che verranno create dopo:
Nel nostro event-receiver alterneremo la variabile per lo SplitScreen, ogni volta che verrà premuto il tasto 'S'. Il resto degli eventi verranno inviati alla camera FPS dell'utente.
Adesso la funzione main: prima inizializziamo il device, otteniamo i riferimenti allo SourceManager e al VideoDriver, carichiamo una mesh animata da un file .md2 e una mappa da un file .pk3. Essendo cose già viste non spiegherò ogni passo. Interessiamoci solo della posizione iniziale nella mappa.
Creiamo le nostre quattro camere. Una guarda il nostro modello di fronte, una dall'alto ed una di lato. Poi la nostra camera FPS controllata dall'utente.
Pensiamo ad una variabile per tenere conto dei frame per secondo e nascondiamo il puntatore del mouse:
Fino ad ora non c'è niente di nuovo! Solo con la definizione delle quattro camere il gioco non mostrerà mai lo splitscreen. Per farlo servono alcuni passi:
. Impostare il viewport a tutto schermo
. Avviare una scena nuova (un clear screen per ripulire lo schermo)
I seguenti 3 passi vanno ripetuti per ciascun viewport dello splitscreen
. Impostare il viewport sull'area desiderata
. Attivare la camera che volete sia linkata a quel viewport
. Fare il render di tutto
Se avete una GUI:
. Rimettere il viewport a tutto schermo
. Mostrare la GUI
. Fine della scena
Sembra complicato ma vedrete che non lo è:
Come avrete visto, le immagini sono renderizzate per ciascun viewport separatamente. Questo significa che si perderà un po' in performance. OK, se vi state chiedendo “Come faccio ad impostare i viewport in questa o quella parte dello schermo?”, niente panico è veramente semplice: nella funzione rect definite 4 coordinate:
. Coordinata X dell'angolo in alto a sinistra
. Coordinata Y dell'angolo in alto a sinistra
. Coordinata X dell'angolo in basso a destra
. Coordinata Y dell'angolo in basso a sinistra
Questo significa che se volete tagliare lo schermo in 2 parti in 2 viewports dovrete dare le seguenti coordinate:
. 1mo viewport: 0,0,ResX/2,ResY
. 2ndo viewport: ResX/2,0,ResX,ResY
Se non lo capite completamente, provate a cambiare i valori nell'esempio e vedete cosa accade.
Mostriamo il conteggio corrente degli fps e chiudiamo l'engine quando l'utente lo richiederà:
E' tutto! Compiliamo e proviamo il programma. Notare: con il tasto 'S' possiamo passare tra la modalità splitscreen e non.
Versione scaricabile da QUI
Un tutorial di Max Winkel.
In questo tutorial impareremo come usare lo splitscreen (e.g. La divisione dello schermo tipica dei racing-games) con Irrlicht. Creeremo un viewport diviso in 4 parti, con 3 camere fisse ed una controllata dall'utente.
Ok, partiamo dagli headers (non credo ci sia nulla da aggiungere).
Codice PHP:
#include <irrlicht.h>
#include "driverChoice.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;
Codice PHP:
//Resolution
const int ResX=800;
const int ResY=600;
const bool fullScreen=false;
//Use SplitScreen?
bool SplitScreen=true;
Codice PHP:
//cameras
ICameraSceneNode *camera[4]={0,0,0,0};
Codice PHP:
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.Key == KEY_KEY_S && event.KeyInput.PressedDown)
{
SplitScreen = !SplitScreen;
return true;
}
//Send all other events to camera4
if (camera[3])
return camera[3]->OnEvent(event);
return false;
}
};
Codice PHP:
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;
//Initialise the engine
IrrlichtDevice *device = createDevice(driverType,
dimension2du(ResX,ResY), 32, fullScreen,
false, false, &receiver);
if (!device)
return 1;
ISceneManager *smgr = device->getSceneManager();
IVideoDriver *driver = device->getVideoDriver();
//Load model
IAnimatedMesh *model = smgr->getMesh("../../media/sydney.md2");
if (!model)
return 1;
IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model);
//Load texture
if (model_node)
{
ITexture *texture = driver->getTexture("../../media/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("../../media/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));
}
Codice PHP:
// 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));
Codice PHP:
//Hide mouse
device->getCursorControl()->setVisible(false);
//We want to count the fps
int lastFPS = -1;
. Impostare il viewport a tutto schermo
. Avviare una scena nuova (un clear screen per ripulire lo schermo)
I seguenti 3 passi vanno ripetuti per ciascun viewport dello splitscreen
. Impostare il viewport sull'area desiderata
. Attivare la camera che volete sia linkata a quel viewport
. Fare il render di tutto
Se avete una GUI:
. Rimettere il viewport a tutto schermo
. Mostrare la GUI
. Fine della scena
Sembra complicato ma vedrete che non lo è:
Codice PHP:
while(device->run())
{
//Set the viewpoint to the whole screen and begin scene
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
driver->beginScene(true,true,SColor(255,100,100,100));
//If SplitScreen 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();
driver->endScene();
. Coordinata X dell'angolo in alto a sinistra
. Coordinata Y dell'angolo in alto a sinistra
. Coordinata X dell'angolo in basso a destra
. Coordinata Y dell'angolo in basso a sinistra
Questo significa che se volete tagliare lo schermo in 2 parti in 2 viewports dovrete dare le seguenti coordinate:
. 1mo viewport: 0,0,ResX/2,ResY
. 2ndo viewport: ResX/2,0,ResX,ResY
Se non lo capite completamente, provate a cambiare i valori nell'esempio e vedete cosa accade.
Mostriamo il conteggio corrente degli fps e chiudiamo l'engine quando l'utente lo richiederà:
Codice PHP:
//Get and show 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;
}
Versione scaricabile da QUI