Tutorial 18 - Splitscreen - Chip - 19-08-2015
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).
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;
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.
Codice PHP: //Resolution const int ResX=800; const int ResY=600; const bool fullScreen=false;
//Use SplitScreen? bool SplitScreen=true;
Ci servono quattro puntatori alle camere che verranno create dopo:
Codice PHP: //cameras ICameraSceneNode *camera[4]={0,0,0,0};
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.
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; } };
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.
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)); }
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.
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));
Pensiamo ad una variabile per tenere conto dei frame per secondo e nascondiamo il puntatore del mouse:
Codice PHP: //Hide mouse device->getCursorControl()->setVisible(false); //We want to count the fps int lastFPS = -1;
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 è:
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();
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à:
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; }
E' tutto! Compiliamo e proviamo il programma. Notare: con il tasto 'S' possiamo passare tra la modalità splitscreen e non.
Versione scaricabile da QUI
|