Creare Videogiochi - Game Developer
Tutorial 21a - Quake3 Explorer - Versione stampabile

+- Creare Videogiochi - Game Developer (https://www.making-videogames.net/giochi)
+-- Forum: Altri Programmi per la Creazione di Videogames (https://www.making-videogames.net/giochi/Forum-Altri-Programmi-per-la-Creazione-di-Videogames)
+--- Forum: Irrlicht Engine (https://www.making-videogames.net/giochi/Forum-Irrlicht-Engine)
+--- Discussione: Tutorial 21a - Quake3 Explorer (/thread-Tutorial-21a-Quake3-Explorer)



Tutorial 21a - Quake3 Explorer - Chip - 23-08-2015

Tutorial 21: Quake3 Explorer

[Immagine: 021shot.jpg]

In questo tutorial mostreremo come caricare più mappe Quake 3.
Specifiche:
. Carico Load archivio BSP a Runtime dal menù
. Carico di una mappa dal menù. Mostriamo uno Screenshot
. Impsotazione del VideoDriver a runtime dal menù
. Variazione del GammaLevel a runtime
. Creazione SceneNodes per gli Shaders
. Carico della EntityList e creazione delle Entity come SceneNodes
. Creazione giocatori con armi e rispettive collisioni
. Musica
E' possibile scaricare Quake III Arena demo ( copyright id software ) al seguente path ftp://ftp.idsoftware.com/idstuff/quake3/win32/q3ademo.exe
Copyright 2006-2011 Burningwater, Thomas Alten
Codice PHP:
#include "driverChoice.h"
#include <irrlicht.h>
#include "q3factory.h"
#include "sound.h" 
La struttura Game Data è usata per mantenere i dati del gioco e gestirne il funzionamento
Codice PHP:
struct GameData
{
    
GameData ( const path &startupDir) :
        
retVal(0), StartupDir(startupDir), createExDevice(0), Device(0)
    {
        
setDefault ();
    }

    
void setDefault ();
    
s32 save ( const path &filename );
    
s32 load ( const path &filename );

    
s32 debugState;
    
s32 gravityState;
    
s32 flyTroughState;
    
s32 wireFrame;
    
s32 guiActive;
    
s32 guiInputActive;
    
f32 GammaValue;
    
s32 retVal;
    
s32 sound;

    
path StartupDir;
    
stringw CurrentMapName;
    array<
pathCurrentArchiveList;

    
vector3df PlayerPosition;
    
vector3df PlayerRotation;

    
tQ3EntityList Variable;

    
Q3LevelLoadParameter loadParam;
    
SIrrlichtCreationParameters deviceParam;
    
funcptr_createDeviceEx createExDevice;
    
IrrlichtDevice *Device;
}; 
Impostazione dei valori di default
Codice PHP:
void GameData::setDefault ()
{
    
debugState EDS_OFF;
    
gravityState 1;
    
flyTroughState 0;
    
wireFrame 0;
    
guiActive 1;
    
guiInputActive 0;
    
GammaValue 1.f;

    
// default deviceParam;
#if defined ( _IRR_WINDOWS_ )
    
deviceParam.DriverType EDT_DIRECT3D9;
#else
    
deviceParam.DriverType EDT_OPENGL;
#endif
    
deviceParam.WindowSize.Width 800;
    
deviceParam.WindowSize.Height 600;
    
deviceParam.Fullscreen false;
    
deviceParam.Bits 24;
    
deviceParam.ZBufferBits 16;
    
deviceParam.Vsync false;
    
deviceParam.AntiAlias false;

    
// default Quake3 loadParam
    
loadParam.defaultLightMapMaterial EMT_LIGHTMAP;
    
loadParam.defaultModulate EMFN_MODULATE_1X;
    
loadParam.defaultFilter EMF_ANISOTROPIC_FILTER;
    
loadParam.verbose 2;
    
loadParam.mergeShaderBuffer 1;        // merge meshbuffers with same material
    
loadParam.cleanUnResolvedMeshes 1;    // should unresolved meshes be cleaned. otherwise blue texture
    
loadParam.loadAllShaders 1;           // load all scripts in the script directory
    
loadParam.loadSkyShader 0;            // load sky Shader
    
loadParam.alpharef 1;

    
sound 0;

    
CurrentMapName "";
    
CurrentArchiveList.clear ();

    
// Explorer Media directory
    
CurrentArchiveList.push_back StartupDir "../../media/" );

    
// Add the original quake3 files before you load your custom map
    // Most mods are using the original shaders, models&items&weapons
    
CurrentArchiveList.push_back("/q/baseq3/");

    
CurrentArchiveList.push_back(StartupDir "../../media/map-20kdm2.pk3");

Carica lo stato attuale del gioco da un tipico file di configurazione quake3 cfg
Codice PHP:
s32 GameData::load ( const path &filename )
{
    if (!
Device)
        return 
0;

    
// the quake3 mesh loader can also handle *.shader and *.cfg file
    
IQ3LevelMeshmesh = (IQ3LevelMesh*) Device->getSceneManager()->getMesh filename );
    if (!
mesh)
        return 
0;

    
tQ3EntityList &entityList mesh->getEntityList ();

    
stringc s;
    
u32 pos;

    for ( 
u32 e 0!= entityList.size (); ++)
    {
        
//dumpShader ( s, &entityList[e], false );
        //printf ( s.c_str () );

        
for ( u32 g 0!= entityList[e].getGroupSize (); ++)
        {
            const 
SVarGroup *group entityList[e].getGroup );

            for ( 
u32 index 0index group->Variable.size (); ++index )
            {
                const 
SVariable &group->Variable[index];
                
pos 0;
                if ( 
v.name == "playerposition" )
                {
                    
PlayerPosition getAsVector3df v.contentpos );
                }
                else
                if ( 
v.name == "playerrotation" )
                {
                    
PlayerRotation getAsVector3df v.contentpos );
                }
            }
        }
    }

    return 
1;

Salva lo stato del gioco nel file di configurazione quake3
Codice PHP:
s32 GameData::save ( const path &filename )
{
    return 
0;
    if (!
Device)
        return 
0;

    
c8 buf[128];
    
u32 i;

    
// Store current Archive for restart
    
CurrentArchiveList.clear();
    
IFileSystem *fs Device->getFileSystem();
    for ( 
0!= fs->getFileArchiveCount(); ++)
    {
        
CurrentArchiveList.push_back fs->getFileArchive(i)->getFileList()->getPath() );
    }

    
// Store Player Position and Rotation
    
ICameraSceneNode camera Device->getSceneManager()->getActiveCamera ();
    if ( 
camera )
    {
        
PlayerPosition camera->getPosition ();
        
PlayerRotation camera->getRotation ();
    }

    
IWriteFile *file fs->createAndWriteFile filename );
    if (!
file)
        return 
0;

    
snprintf buf128"playerposition %.f %.f %.f\nplayerrotation %.f %.f %.f\n",
            
PlayerPosition.XPlayerPosition.ZPlayerPosition.Y,
            
PlayerRotation.XPlayerRotation.ZPlayerRotation.Y);
    
file->write buf, (s32strlen buf ) );
    for ( 
0!= fs->getFileArchiveCount(); ++)
    {
        
snprintf buf128"archive %s\n",stringc fs->getFileArchive(i)->getFileList()->getPath() ).c_str () );
        
file->write buf, (s32strlen buf ) );
    }

    
file->drop ();
    return 
1;

La struttura per rappresentare il giocatre
Codice PHP:
struct Q3Player : public IAnimationEndCallBack
{
    
Q3Player ()
    : 
Device(0), MapParent(0), Mesh(0), WeaponNode(0), StartPositionCurrent(0)
    {
        
animation[0] = 0;
        
memset(Anim0sizeof(TimeFire)*4);
    }

    
virtual void OnAnimationEnd(IAnimatedMeshSceneNodenode);

    
void create (   IrrlichtDevice *device,
                    
IQ3LevelMeshmesh,
                    
ISceneNode *mapNode,
                    
IMetaTriangleSelector *meta
                
);
    
void shutdown ();
    
void setAnim ( const c8 *name );
    
void respawn ();
    
void setpos ( const vector3df &pos, const vector3dfrotation );

    
ISceneNodeAnimatorCollisionResponse cam() { return camCollisionResponse Device ); }

    
IrrlichtDevice *Device;
    
ISceneNodeMapParent;
    
IQ3LevelMeshMesh;
    
IAnimatedMeshSceneNodeWeaponNode;
    
s32 StartPositionCurrent;
    
TimeFire Anim[4];
    
c8 animation[64];
    
c8 buf[64];
}; 
Fine struttura per il giocatore
Codice PHP:
void Q3Player::shutdown ()
{
    
setAnim );

    
dropElement (WeaponNode);

    if ( 
Device )
    {
        
ICameraSceneNodecamera Device->getSceneManager()->getActiveCamera();
        
dropElement camera );
        
Device 0;
    }

    
MapParent 0;
    
Mesh 0;

Creazione di un nuovo giocatore
Codice PHP:
void Q3Player::create IrrlichtDevice *deviceIQ3LevelMeshmeshISceneNode *mapNodeIMetaTriangleSelector *meta )
{
    
setTimeFire Anim 0200FIRED );
    
setTimeFire Anim 15000 );

    if (!
device)
        return;
    
// load FPS weapon to Camera
    
Device device;
    
Mesh mesh;
    
MapParent mapNode;

    
ISceneManager *smgr device->getSceneManager ();
    
IVideoDriver driver device->getVideoDriver();

    
ICameraSceneNodecamera 0;

    
SKeyMap keyMap[10];
    
keyMap[0].Action EKA_MOVE_FORWARD;
    
keyMap[0].KeyCode KEY_UP;
    
keyMap[1].Action EKA_MOVE_FORWARD;
    
keyMap[1].KeyCode KEY_KEY_W;

    
keyMap[2].Action EKA_MOVE_BACKWARD;
    
keyMap[2].KeyCode KEY_DOWN;
    
keyMap[3].Action EKA_MOVE_BACKWARD;
    
keyMap[3].KeyCode KEY_KEY_S;

    
keyMap[4].Action EKA_STRAFE_LEFT;
    
keyMap[4].KeyCode KEY_LEFT;
    
keyMap[5].Action EKA_STRAFE_LEFT;
    
keyMap[5].KeyCode KEY_KEY_A;

    
keyMap[6].Action EKA_STRAFE_RIGHT;
    
keyMap[6].KeyCode KEY_RIGHT;
    
keyMap[7].Action EKA_STRAFE_RIGHT;
    
keyMap[7].KeyCode KEY_KEY_D;

    
keyMap[8].Action EKA_JUMP_UP;
    
keyMap[8].KeyCode KEY_KEY_J;

    
keyMap[9].Action EKA_CROUCH;
    
keyMap[9].KeyCode KEY_KEY_C;

    
camera smgr->addCameraSceneNodeFPS(0100.0f0.6f, -1keyMap10false0.6f);
    
camera->setName "First Person Camera" );
    
//camera->setFOV ( 100.f * core::DEGTORAD );
    
camera->setFarValue20000.f );

    
IAnimatedMeshMD2weaponMesh = (IAnimatedMeshMD2*) smgr->getMesh("gun.md2");
    if ( 
== weaponMesh )
        return;

    if ( 
weaponMesh->getMeshType() == EAMT_MD2 )
    {
        
s32 count weaponMesh->getAnimationCount();
        for ( 
s32 i 0!= count; ++)
        {
            
snprintf buf64"Animation: %s"weaponMesh->getAnimationName(i) );
            
device->getLogger()->log(bufELL_INFORMATION);
        }
    }

    
WeaponNode smgr->addAnimatedMeshSceneNode(
                        
weaponMesh,
                        
smgr->getActiveCamera(),
                        
10,
                        
vector3df000),
                        
vector3df(-90,-90,90)
                        );
    
WeaponNode->setMaterialFlag(EMF_LIGHTINGfalse);
    
WeaponNode->setMaterialTexture(0driver->getTexture"gun.jpg"));
    
WeaponNode->setLoopMode false );
    
WeaponNode->setName "tommi the gun man" );

    
//create a collision auto response animator
    
ISceneNodeAnimatoranim =
        
smgr->createCollisionResponseAnimatormetacamera,
            
vector3df(30,45,30),
            
getGravity "earth" ),
            
vector3df(0,40,0),
            
0.0005f
        
);

    
camera->addAnimatoranim );
    
anim->drop();

    if ( 
meta )
    {
        
meta->drop ();
    }

    
respawn ();
    
setAnim "idle" );

Ci serve un buon punto di partenza dentro il livello. Possiamo chiedere al Quake3 Loader tutte le entità che appartengono alla classe "info_player_deathmatch"
Codice PHP:
void Q3Player::respawn ()
{
    if (!
Device)
        return;
    
ICameraSceneNodecamera Device->getSceneManager()->getActiveCamera();

    
Device->getLogger()->log"respawn" );

    if ( 
StartPositionCurrent >= Q3StartPosition (
            
Meshcamera,StartPositionCurrent++,
            
cam ()->getEllipsoidTranslation() )
        )
    {
        
StartPositionCurrent 0;
    }

Impostiamo la posizione del giocatore prendendo quelle salvate
Codice PHP:
void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation )
{
    if (!
Device)
        return;
    
Device->getLogger()->log"setpos" );

    
ICameraSceneNodecamera Device->getSceneManager()->getActiveCamera();
    if ( 
camera )
    {
        
camera->setPosition pos );
        
camera->setRotation rotation );
        
camera->OnAnimate );
    }

Impostiamo l'animazione e l'arma del giocatore
Codice PHP:
void Q3Player::setAnim ( const c8 *name )
{
    if ( 
name )
    {
        
snprintf animation64"%s"name );
        if ( 
WeaponNode )
        {
            
WeaponNode->setAnimationEndCallback this );
            
WeaponNode->setMD2Animation animation );
        }
    }
    else
    {
        
animation[0] = 0;
        if ( 
WeaponNode )
        {
            
WeaponNode->setAnimationEndCallback );
        }
    }
}

// Callback
void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNodenode)
{
    
setAnim );

Gli elementi della GUI
Codice PHP:
struct GUI
{
    
GUI ()
    {
        
memset this0sizeof ( *this ) );
    }

    
void drop()
    {
        
dropElement Window );
        
dropElement Logo );
    }

    
IGUIComboBoxVideoDriver;
    
IGUIComboBoxVideoMode;
    
IGUICheckBoxFullScreen;
    
IGUICheckBoxBit32;
    
IGUIScrollBarMultiSample;
    
IGUIButtonSetVideoMode;

    
IGUIScrollBarTesselation;
    
IGUIScrollBarGamma;
    
IGUICheckBoxCollision;
    
IGUICheckBoxVisible_Map;
    
IGUICheckBoxVisible_Shader;
    
IGUICheckBoxVisible_Fog;
    
IGUICheckBoxVisible_Unresolved;
    
IGUICheckBoxVisible_Skydome;
    
IGUIButtonRespawn;

    
IGUITableArchiveList;
    
IGUIButtonArchiveAdd;
    
IGUIButtonArchiveRemove;
    
IGUIFileOpenDialogArchiveFileOpen;
    
IGUIButtonArchiveUp;
    
IGUIButtonArchiveDown;

    
IGUIListBoxMapList;
    
IGUITreeViewSceneTree;
    
IGUIStaticTextStatusLine;
    
IGUIImageLogo;
    
IGUIWindowWindow;
};
Classe CQuake3EventHandler per il controllo del gioco
class CQuake3EventHandler : public IEventReceiver
{
public:

    
CQuake3EventHandlerGameData *gameData );
    
virtual ~CQuake3EventHandler ();

    
void Animate();
    
void Render();

    
void AddArchive ( const patharchiveName );
    
void LoadMap ( const stringwmapNames32 collision );
    
void CreatePlayers();
    
void AddSkyu32 dome, const c8 *texture );
    
Q3Player *GetPlayer u32 index ) { return &Player[index]; }

    
void CreateGUI();
    
void SetGUIActives32 command);

    
bool OnEvent(const SEventeve);

private:

    
GameData *Game;

    
IQ3LevelMeshMesh;
    
ISceneNodeMapParent;
    
ISceneNodeShaderParent;
    
ISceneNodeItemParent;
    
ISceneNodeUnresolvedParent;
    
ISceneNodeBulletParent;
    
ISceneNodeFogParent;
    
ISceneNode SkyNode;
    
IMetaTriangleSelector *Meta;

    
c8 buf[256];

    
Q3Player Player[2];

    
struct SParticleImpact
    
{
        
u32 when;
        
vector3df pos;
        
vector3df outVector;
    };
    array<
SParticleImpactImpacts;
    
void useItemQ3Player player);
    
void createParticleImpactsu32 now );

    
void createTextures ();
    
void addSceneTreeItemISceneNode parentIGUITreeViewNodenodeParent);

    
GUI gui;
    
void dropMap ();
}; 
Costruttore della CQuake3EventHandler
Codice PHP:
CQuake3EventHandler::CQuake3EventHandlerGameData *game )
Game(game), Mesh(0), MapParent(0), ShaderParent(0), ItemParent(0), UnresolvedParent(0),
    
BulletParent(0), FogParent(0), SkyNode(0), Meta(0)
{
    
buf[0]=0;
    
// Also use 16 Bit Textures for 16 Bit RenderDevice
    
if ( Game->deviceParam.Bits == 16 )
    {
        
game->Device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BITtrue);
    }

    
// Quake3 Shader controls Z-Writing
    
game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENTtrue);

    
// create internal textures
    
createTextures ();

    
sound_init game->Device );

    
Game->Device->setEventReceiver this );
}

// destructor
CQuake3EventHandler::~CQuake3EventHandler ()
{
    
Player[0].shutdown ();
    
sound_shutdown ();

    
Game->save"explorer.cfg" );

    
Game->Device->drop();
}


// create runtime textures smog, fog
void CQuake3EventHandler::createTextures()
{
    
IVideoDriver driver Game->Device->getVideoDriver();

    
dimension2du dim(6464);

    
video::IImageimage;
    
u32 i;
    
u32 x;
    
u32 y;
    
u32 data;
    for ( 
0!= 8; ++)
    {
        
image driver->createImage video::ECF_A8R8G8B8dim);
        
data = (u32*) image->lock ();
        for ( 
0!= dim.Height; ++)
        {
            for ( 
0!= dim.Width; ++)
            {
                
data [x] = 0xFFFFFFFF;
            }
            
data = (u32*) ( (u8*) data image->getPitch() );
        }
        
image->unlock();
        
snprintf buf64"smoke_%02d");
        
driver->addTexturebufimage );
        
image->drop ();
    }

    
// fog
    
for ( 0!= 1; ++)
    {
        
image driver->createImage video::ECF_A8R8G8B8dim);
        
data = (u32*) image->lock ();
        for ( 
0!= dim.Height; ++)
        {
            for ( 
0!= dim.Width; ++)
            {
                
data [x] = 0xFFFFFFFF;
            }
            
data = (u32*) ( (u8*) data image->getPitch() );
        }
        
image->unlock();
        
snprintf buf64"fog_%02d");
        
driver->addTexturebufimage );
        
image->drop ();
    }

Creazione della GUI
Codice PHP:
void CQuake3EventHandler::CreateGUI()
{

    
IGUIEnvironment *env Game->Device->getGUIEnvironment();
    
IVideoDriver driver Game->Device->getVideoDriver();

    
gui.drop();

    
// set skin font
    
IGUIFontfont env->getFont("fontlucida.png");
    if (
font)
        
env->getSkin()->setFont(font);
    
env->getSkin()->setColor EGDC_BUTTON_TEXTvideo::SColor(240,0xAA,0xAA,0xAA) );
    
env->getSkin()->setColor EGDC_3D_HIGH_LIGHTvideo::SColor(240,0x22,0x22,0x22) );
    
env->getSkin()->setColor EGDC_3D_FACEvideo::SColor(240,0x44,0x44,0x44) );
    
env->getSkin()->setColor EGDC_EDITABLEvideo::SColor(240,0x44,0x44,0x44) );
    
env->getSkin()->setColor EGDC_FOCUSED_EDITABLEvideo::SColor(240,0x54,0x54,0x54) );
    
env->getSkin()->setColor EGDC_WINDOWvideo::SColor(240,0x66,0x66,0x66) );

    
// minimal gui size 800x600
    
dimension2d<u32dim 800600 );
    
dimension2d<u32vdim Game->Device->getVideoDriver()->getScreenSize() );

    if ( 
vdim.Height >= dim.Height && vdim.Width >= dim.Width )
    {
        
//dim = vdim;
    
}
    else
    {
    }

    
gui.Window env->addWindow rect<s32> ( 00dim.Widthdim.Height ), falseL"Quake3 Explorer" );
    
gui.Window->setToolTipText L"Quake3Explorer. Loads and show various BSP File Format and Shaders." );
    
gui.Window->getCloseButton()->setToolTipText L"Quit Quake3 Explorer" );

    
// add a status line help text
    
gui.StatusLine env->addStaticText0rect<s32>( 5,dim.Height 30,dim.Width 5,dim.Height 10),
                                
falsefalsegui.Window, -1true
                            
);


    
env->addStaticText L"VideoDriver:"rect<s32>( dim.Width 40024dim.Width 31040 ),falsefalsegui.Window, -1false );
    
gui.VideoDriver env->addComboBox(rect<s32>( dim.Width 30024dim.Width 1040 ),gui.Window);
    
gui.VideoDriver->addItem(L"Direct3D 9.0c"EDT_DIRECT3D9 );
    
gui.VideoDriver->addItem(L"Direct3D 8.1"EDT_DIRECT3D8 );
    
gui.VideoDriver->addItem(L"OpenGL 1.5"EDT_OPENGL);
    
gui.VideoDriver->addItem(L"Software Renderer"EDT_SOFTWARE);
    
gui.VideoDriver->addItem(L"Burning's Video (TM) Thomas Alten"EDT_BURNINGSVIDEO);
    
gui.VideoDriver->setSelected gui.VideoDriver->getIndexForItemData Game->deviceParam.DriverType ) );
    
gui.VideoDriver->setToolTipText L"Use a VideoDriver" );

    
env->addStaticText L"VideoMode:"rect<s32>( dim.Width 40044dim.Width 31060 ),falsefalsegui.Window, -1false );
    
gui.VideoMode env->addComboBox(rect<s32>( dim.Width 30044dim.Width 1060 ),gui.Window);
    
gui.VideoMode->setToolTipText L"Supported Screenmodes" );
    
IVideoModeList *modeList Game->Device->getVideoModeList();
    if ( 
modeList )
    {
        
s32 i;
        for ( 
0!= modeList->getVideoModeCount (); ++)
        {
            
u16 d modeList->getVideoModeDepth );
            if ( 
16 )
                continue;

            
u16 w modeList->getVideoModeResolution ).Width;
            
u16 h modeList->getVideoModeResolution ).Height;
            
u32 val << 16 h;

            if ( 
gui.VideoMode->getIndexForItemData val ) >= )
                continue;

            
f32 aspect = (f32/ (f32h;
            const 
c8 *"";
            if ( 
core::equals aspect1.3333333333f ) ) "4:3";
            else if ( 
core::equals aspect1.6666666f ) ) "15:9 widescreen";
            else if ( 
core::equals aspect1.7777777f ) ) "16:9 widescreen";
            else if ( 
core::equals aspect1.6f ) ) "16:10 widescreen";
            else if ( 
core::equals aspect2.133333f ) ) "20:9 widescreen";

            
snprintf bufsizeof buf ), "%d x %d, %s",wh);
            
gui.VideoMode->addItem stringw buf ).c_str(), val );
        }
    }
    
gui.VideoMode->setSelected gui.VideoMode->getIndexForItemData (
                                    
Game->deviceParam.WindowSize.Width << 16 |
                                    
Game->deviceParam.WindowSize.Height ) );

    
gui.FullScreen env->addCheckBox Game->deviceParam.Fullscreenrect<s32>( dim.Width 40064dim.Width 30080 ), gui.Window,-1L"Fullscreen" );
    
gui.FullScreen->setToolTipText L"Set Fullscreen or Window Mode" );

    
gui.Bit32 env->addCheckBox Game->deviceParam.Bits == 32rect<s32>( dim.Width 30064dim.Width 24080 ), gui.Window,-1L"32Bit" );
    
gui.Bit32->setToolTipText L"Use 16 or 32 Bit" );

    
env->addStaticText L"MultiSample:"rect<s32>( dim.Width 23564dim.Width 15080 ),falsefalsegui.Window, -1false );
    
gui.MultiSample env->addScrollBartruerect<s32>( dim.Width 15064dim.Width 7080 ), gui.Window,-);
    
gui.MultiSample->setMin );
    
gui.MultiSample->setMax );
    
gui.MultiSample->setSmallStep );
    
gui.MultiSample->setLargeStep );
    
gui.MultiSample->setPos Game->deviceParam.AntiAlias );
    
gui.MultiSample->setToolTipText L"Set the MultiSample (disable, 1x, 2x, 4x, 8x )" );

    
gui.SetVideoMode env->addButton (rect<s32>( dim.Width 6064dim.Width 1080 ), gui.Window, -1,L"set" );
    
gui.SetVideoMode->setToolTipText L"Set Video Mode with current values" );

    
env->addStaticText L"Gamma:"rect<s32>( dim.Width 400104dim.Width 310120 ),falsefalsegui.Window, -1false );
    
gui.Gamma env->addScrollBartruerect<s32>( dim.Width 300104dim.Width 10120 ), gui.Window,-);
    
gui.Gamma->setMin 50 );
    
gui.Gamma->setMax 350 );
    
gui.Gamma->setSmallStep );
    
gui.Gamma->setLargeStep 10 );
    
gui.Gamma->setPos core::floor32 Game->GammaValue 100.f ) );
    
gui.Gamma->setToolTipText L"Adjust Gamma Ramp ( 0.5 - 3.5)" );
    
Game->Device->setGammaRamp Game->GammaValueGame->GammaValueGame->GammaValue0.f0.f );


    
env->addStaticText L"Tesselation:"rect<s32>( dim.Width 400124dim.Width 310140 ),falsefalsegui.Window, -1false );
    
gui.Tesselation env->addScrollBartruerect<s32>( dim.Width 300124dim.Width 10140 ), gui.Window,-);
    
gui.Tesselation->setMin );
    
gui.Tesselation->setMax 12 );
    
gui.Tesselation->setSmallStep );
    
gui.Tesselation->setLargeStep );
    
gui.Tesselation->setPos Game->loadParam.patchTesselation );
    
gui.Tesselation->setToolTipText L"How smooth should curved surfaces be rendered" );

    
gui.Collision env->addCheckBox truerect<s32>( dim.Width 400150dim.Width 300166 ), gui.Window,-1L"Collision" );
    
gui.Collision->setToolTipText L"Set collision on or off ( flythrough ). \nPress F7 on your Keyboard" );
    
gui.Visible_Map env->addCheckBox truerect<s32>( dim.Width 300150dim.Width 240166 ), gui.Window,-1L"Map" );
    
gui.Visible_Map->setToolTipText L"Show or not show the static part the Level. \nPress F3 on your Keyboard" );
    
gui.Visible_Shader env->addCheckBox truerect<s32>( dim.Width 240150dim.Width 170166 ), gui.Window,-1L"Shader" );
    
gui.Visible_Shader->setToolTipText L"Show or not show the Shader Nodes. \nPress F4 on your Keyboard" );
    
gui.Visible_Fog env->addCheckBox truerect<s32>( dim.Width 170150dim.Width 110166 ), gui.Window,-1L"Fog" );
    
gui.Visible_Fog->setToolTipText L"Show or not show the Fog Nodes. \nPress F5 on your Keyboard" );
    
gui.Visible_Unresolved env->addCheckBox truerect<s32>( dim.Width 110150dim.Width 10166 ), gui.Window,-1L"Unresolved" );
    
gui.Visible_Unresolved->setToolTipText L"Show the or not show the Nodes the Engine can't handle. \nPress F6 on your Keyboard" );
    
gui.Visible_Skydome env->addCheckBox truerect<s32>( dim.Width 110180dim.Width 10196 ), gui.Window,-1L"Skydome" );
    
gui.Visible_Skydome->setToolTipText L"Show the or not show the Skydome." );

    
//Respawn = env->addButton ( rect<s32>( dim.Width - 260, 90, dim.Width - 10, 106 ), 0,-1, L"Respawn" );

    
env->addStaticText L"Archives:"rect<s32>( 5dim.Height 530dim.Width 600,dim.Height 514 ),falsefalsegui.Window, -1false );

    
gui.ArchiveAdd env->addButton rect<s32>( dim.Width 725dim.Height 530dim.Width 665dim.Height 514 ), gui.Window,-1L"add" );
    
gui.ArchiveAdd->setToolTipText L"Add an archive, usually packed zip-archives (*.pk3) to the Filesystem" );
    
gui.ArchiveRemove env->addButton rect<s32>( dim.Width 660dim.Height 530dim.Width 600dim.Height 514 ), gui.Window,-1L"del" );
    
gui.ArchiveRemove->setToolTipText L"Remove the selected archive from the FileSystem." );
    
gui.ArchiveUp env->addButton rect<s32>( dim.Width 575dim.Height 530dim.Width 515dim.Height 514 ), gui.Window,-1L"up" );
    
gui.ArchiveUp->setToolTipText L"Arrange Archive Look-up Hirachy. Move the selected Archive up" );
    
gui.ArchiveDown env->addButton rect<s32>( dim.Width 510dim.Height 530dim.Width 440dim.Height 514 ), gui.Window,-1L"down" );
    
gui.ArchiveDown->setToolTipText L"Arrange Archive Look-up Hirachy. Move the selected Archive down" );


    
gui.ArchiveList env->addTable rect<s32>( 5,dim.Height 510dim.Width 450,dim.Height 410 ), gui.Window  );
    
gui.ArchiveList->addColumn L"Type");
    
gui.ArchiveList->addColumn L"Real File Path");
    
gui.ArchiveList->setColumnWidth 060 );
    
gui.ArchiveList->setColumnWidth 1284 );
    
gui.ArchiveList->setToolTipText L"Show the attached Archives" );


    
env->addStaticText L"Maps:"rect<s32>( 5dim.Height 400dim.Width 450,dim.Height 380 ),falsefalsegui.Window, -1false );
    
gui.MapList env->addListBox rect<s32>( 5,dim.Height 380dim.Width 450,dim.Height 40  ), gui.Window, -1true  );
    
gui.MapList->setToolTipText L"Show the current Maps in all Archives.\n Double-Click the Map to start the level" );


    
// create a visible Scene Tree
    
env->addStaticText L"Scenegraph:"rect<s32>( dim.Width 400dim.Height 400dim.Width 5,dim.Height 380 ),falsefalsegui.Window, -1false );
    
gui.SceneTree env->addTreeView(   rect<s32>( dim.Width 400dim.Height 380dim.Width 5dim.Height 40 ),
                                    
gui.Window, -1truetruefalse );
    
gui.SceneTree->setToolTipText L"Show the current Scenegraph" );
    
gui.SceneTree->getRoot()->clearChildren();
    
addSceneTreeItem Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() );


    
IGUIImageListimageList env->createImageList(    driver->getTexture "iconlist.png" ),
                                        
dimension2di3232 ), true );

    if ( 
imageList )
    {
        
gui.SceneTree->setImageListimageList );
        
imageList->drop ();
    }


    
// load the engine logo
    
gui.Logo env->addImagedriver->getTexture("irrlichtlogo3.png"), position2d<s32>(516 ), true);
    
gui.Logo->setToolTipText L"The great Irrlicht Engine" );

    
AddArchive "" );

Aggiunta di un archivio Archive al FileSystems e aggiornamento della GUI
Codice PHP:
void CQuake3EventHandler::AddArchive ( const patharchiveName )
{
    
IFileSystem *fs Game->Device->getFileSystem();
    
u32 i;

    if ( 
archiveName.size () )
    {
        
bool exists false;
        for ( 
0!= fs->getFileArchiveCount(); ++)
        {
            if ( 
fs->getFileArchive(i)->getFileList()->getPath() == archiveName )
            {
                
exists true;
                break;
            }
        }

        if (!
exists)
        {
            
fs->addFileArchive(archiveNametruefalse);
        }
    }

    
// store the current archives in game data
    // show the attached Archive in proper order
    
if ( gui.ArchiveList )
    {
        
gui.ArchiveList->clearRows();

        for ( 
0!= fs->getFileArchiveCount(); ++)
        {
            
IFileArchive archive fs->getFileArchive );

            
u32 index gui.ArchiveList->addRow(i);

            
core::stringw typeName;
            switch(
archive->getType())
            {
            case 
io::EFAT_ZIP:
                
typeName "ZIP";
                break;
            case 
io::EFAT_GZIP:
                
typeName "gzip";
                break;
            case 
io::EFAT_FOLDER:
                
typeName "Mount";
                break;
            case 
io::EFAT_PAK:
                
typeName "PAK";
                break;
            case 
io::EFAT_TAR:
                
typeName "TAR";
                break;
            default:
                
typeName "archive";
            }

            
gui.ArchiveList->setCellText index0typeName );
            
gui.ArchiveList->setCellText index1archive->getFileList()->getPath() );
        }
    }


    
// browse the archives for maps
    
if ( gui.MapList )
    {
        
gui.MapList->clear();

        
IGUISpriteBank *bank Game->Device->getGUIEnvironment()->getSpriteBank("sprite_q3map");
        if ( 
== bank )
            
bank Game->Device->getGUIEnvironment()->addEmptySpriteBank("sprite_q3map");

        
SGUISprite sprite;
        
SGUISpriteFrame frame;
        
core::rect<s32r;

        
bank->getSprites().clear();
        
bank->getPositions().clear ();
        
gui.MapList->setSpriteBank bank );

        
u32 g 0;
        
core::stringw s;

        
// browse the attached file system
        
fs->setFileListSystem FILESYSTEM_VIRTUAL );
        
fs->changeWorkingDirectoryTo "/maps/" );
        
IFileList *fileList fs->createFileList ();
        
fs->setFileListSystem FILESYSTEM_NATIVE );

        for ( 
i=0ifileList->getFileCount(); ++i)
        {
            
fileList->getFullFileName(i);
            if ( 
s.find ".bsp" ) >= )
            {
                
// get level screenshot. reformat texture to 128x128
                
path c );
                
deletePathFromFilename );
                
cutFilenameExtension c);
                
path "levelshots/" ) + c;

                
dimension2du dim 128128 );
                
IVideoDriver driver Game->Device->getVideoDriver();
                
IImageimage 0;
                
ITexture *tex 0;
                
path filename;

                
filename ".jpg";
                if ( 
fs->existFile filename ) )
                    
image driver->createImageFromFilefilename );
                if ( 
== image )
                {
                    
filename ".tga";
                    if ( 
fs->existFile filename ) )
                        
image driver->createImageFromFilefilename );
                }

                if ( 
image )
                {
                    
IImagefilter driver->createImage video::ECF_R8G8B8dim );
                    
image->copyToScalingBoxFilter filter);
                    
image->drop ();
                    
image filter;
                }

                if ( 
image )
                {
                    
tex driver->addTexture filenameimage );
                    
image->drop ();
                }


                
bank->setTexture gtex );

                
r.LowerRightCorner.dim.Width;
                
r.LowerRightCorner.dim.Height;
                
gui.MapList->setItemHeight r.LowerRightCorner.);
                
frame.rectNumber bank->getPositions().size();
                
frame.textureNumber g;

                
bank->getPositions().push_back(r);

                
sprite.Frames.set_used );
                
sprite.Frames.push_back(frame);
                
sprite.frameTime 0;
                
bank->getSprites().push_back(sprite);

                
gui.MapList->addItem s.c_str (), );
                
+= 1;
            }
        }
        
fileList->drop ();

        
gui.MapList->setSelected ( -);
        
IGUIScrollBar bar = (IGUIScrollBar*)gui.MapList->getElementFromId);
        if ( 
bar )
            
bar->setPos );

    }


Pulisce e rilascia la mappa in memoria
Codice PHP:
void CQuake3EventHandler::dropMap ()
{
    
IVideoDriver driver Game->Device->getVideoDriver();

    
driver->removeAllHardwareBuffers ();
    
driver->removeAllTextures ();

    
Player[0].shutdown ();


    
dropElement ItemParent );
    
dropElement ShaderParent );
    
dropElement UnresolvedParent );
    
dropElement FogParent );
    
dropElement BulletParent );


    
Impacts.clear();

    if ( 
Meta )
    {
        
Meta 0;
    }

    
dropElement MapParent );
    
dropElement SkyNode );

    
// clean out meshes, because textures are invalid
    // TODO: better texture handling;-)
    
IMeshCache *cache Game->Device->getSceneManager ()->getMeshCache();
    
cache->clear ();
    
Mesh 0;

Caricamento di una nuova mappa
Codice PHP:
void CQuake3EventHandler::LoadMap ( const stringw &mapNames32 collision )
{
    if ( 
== mapName.size() )
        return;

    
dropMap ();

    
IFileSystem *fs Game->Device->getFileSystem();
    
ISceneManager *smgr Game->Device->getSceneManager ();

    
IReadFilefile fs->createMemoryReadFile(&Game->loadParam,
                
sizeof(Game->loadParam), L"levelparameter.cfg"false);

    
// load cfg file
    
smgr->getMeshfile );
    
file->drop ();

    
// load the actual map
    
Mesh = (IQ3LevelMesh*) smgr->getMesh(mapName);
    if ( 
== Mesh )
        return; 
Aggiunta delle mesh presenti nella nostra Scene ( polygon & patches ) la geometria delle mesh è ottimizzata per un disegno più veloce (alberi Octree)
Codice PHP:
IMesh *geometry Mesh->getMesh(E_Q3_MESH_GEOMETRY);
    if ( 
== geometry || geometry->getMeshBufferCount() == 0)
        return;

    
Game->CurrentMapName mapName;

    
//create a collision list
    
Meta 0;

    
ITriangleSelector selector 0;
    if (
collision)
        
Meta smgr->createMetaTriangleSelector();

    
//IMeshBuffer *b0 = geometry->getMeshBuffer(0);
    //s32 minimalNodes = b0 ? core::s32_max ( 2048, b0->getVertexCount() / 32 ) : 2048;
    
s32 minimalNodes 2048;

    
MapParent smgr->addOctreeSceneNode(geometry0, -1minimalNodes);
    
MapParent->setName mapName );
    if ( 
Meta )
    {
        
selector smgr->createOctreeTriangleSelectorgeometry,MapParentminimalNodes);
        
//selector = smgr->createTriangleSelector ( geometry, MapParent );
        
Meta->addTriangleSelectorselector);
        
selector->drop ();
    }

    
// logical parent for the items
    
ItemParent smgr->addEmptySceneNode();
    if ( 
ItemParent )
        
ItemParent->setName "Item Container" );

    
ShaderParent smgr->addEmptySceneNode();
    if ( 
ShaderParent )
        
ShaderParent->setName "Shader Container" );

    
UnresolvedParent smgr->addEmptySceneNode();
    if ( 
UnresolvedParent )
        
UnresolvedParent->setName "Unresolved Container" );

    
FogParent smgr->addEmptySceneNode();
    if ( 
FogParent )
        
FogParent->setName "Fog Container" );

    
// logical parent for the bullets
    
BulletParent smgr->addEmptySceneNode();
    if ( 
BulletParent )
        
BulletParent->setName "Bullet Container" ); 
Ora costruiamo uno SceneNodes per ogni Shader presente gli oggetti sono registrati nella quake mesh E_Q3_MESH_ITEMS e gli Shader ID sono registrati nel MaterialParameters come i teschi scuri, la lava animata e.. tubi verdi lampeggianti?
Codice PHP:
Q3ShaderFactory Game->loadParamGame->DeviceMeshE_Q3_MESH_ITEMS,ShaderParentMetafalse );
    
Q3ShaderFactory Game->loadParamGame->DeviceMeshE_Q3_MESH_FOG,FogParent0false );
    
Q3ShaderFactory Game->loadParamGame->DeviceMeshE_Q3_MESH_UNRESOLVED,UnresolvedParentMetatrue ); 
Ora costruiamo i modelli dalla Entity List
Codice PHP:
Q3ModelFactory Game->loadParamGame->DeviceMeshItemParentfalse );

Aggiungo un SceneNode con un'icona all'albero della scena
Codice PHP:
void CQuake3EventHandler::addSceneTreeItemISceneNode parentIGUITreeViewNodenodeParent)
{
    
IGUITreeViewNodenode;
    
wchar_t msg[128];

    
s32 imageIndex;
    list<
ISceneNode*>::ConstIterator it parent->getChildren().begin();
    for (; 
it != parent->getChildren().end(); ++it)
    {
        switch ( (*
it)->getType () )
        {
            case 
ESNT_Q3SHADER_SCENE_NODEimageIndex 0; break;
            case 
ESNT_CAMERAimageIndex 1; break;
            case 
ESNT_EMPTYimageIndex 2; break;
            case 
ESNT_MESHimageIndex 3; break;
            case 
ESNT_OCTREEimageIndex 3; break;
            case 
ESNT_ANIMATED_MESHimageIndex 4; break;
            case 
ESNT_SKY_BOXimageIndex 5; break;
            case 
ESNT_BILLBOARDimageIndex 6; break;
            case 
ESNT_PARTICLE_SYSTEMimageIndex 7; break;
            case 
ESNT_TEXTimageIndex 8; break;
            default:
imageIndex = -1; break;
        }

        if ( 
imageIndex )
        {
            
swprintf msg128L"%hs,%hs",
                
Game->Device->getSceneManager ()->getSceneNodeTypeName ( (*it)->getType () ),
                (*
it)->getName()
                );
        }
        else
        {
            
swprintf msg128L"%hs",(*it)->getName() );
        }

        
node nodeParent->addChildBackmsg0imageIndex );

        
// Add all Animators
        
list<ISceneNodeAnimator*>::ConstIterator ait = (*it)->getAnimators().begin();
        for (; 
ait != (*it)->getAnimators().end(); ++ait)
        {
            
imageIndex = -1;
            
swprintf msg128L"%hs",
                
Game->Device->getSceneManager ()->getAnimatorTypeName ( (*ait)->getType () )
                );

            switch ( (*
ait)->getType () )
            {
                case 
ESNAT_FLY_CIRCLE:
                case 
ESNAT_FLY_STRAIGHT:
                case 
ESNAT_FOLLOW_SPLINE:
                case 
ESNAT_ROTATION:
                case 
ESNAT_TEXTURE:
                case 
ESNAT_DELETION:
                case 
ESNAT_COLLISION_RESPONSE:
                case 
ESNAT_CAMERA_FPS:
                case 
ESNAT_CAMERA_MAYA:
                default:
                    break;
            }
            
node->addChildBackmsg0imageIndex );
        }

        
addSceneTreeItem ( *itnode );
    }
}


// Adds life!
void CQuake3EventHandler::CreatePlayers()
{
    
Player[0].create Game->DeviceMeshMapParentMeta );
}


// Adds a skydome to the scene
void CQuake3EventHandler::AddSkyu32 dome, const c8 *texture)
{
    
ISceneManager *smgr Game->Device->getSceneManager ();
    
IVideoDriver driver Game->Device->getVideoDriver();

    
bool oldMipMapState driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
    
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPSfalse);

    if ( 
== dome )
    {
        
// irrlicht order
        //static const c8*p[] = { "ft", "lf", "bk", "rt", "up", "dn" };
        // quake3 order
        
static const c8*p[] = { "ft""rt""bk""lf""up""dn" };

        
u32 i 0;
        
snprintf buf64"%s_%s.jpg"texturep[i] );
        
SkyNode smgr->addSkyBoxSceneNodedriver->getTexture buf ), 0000);

        if (
SkyNode)
        {
            for ( 
06; ++)
            {
                
snprintf buf64"%s_%s.jpg"texturep[i] );
                
SkyNode->getMaterial(i).setTexture 0driver->getTexture buf ) );
            }
        }
    }
    else
    if ( 
== dome )
    {
        
snprintf buf64"%s.jpg"texture );
        
SkyNode smgr->addSkyDomeSceneNode(
                
driver->getTexturebuf ), 32,32,
                
1.f1.f1000.f011);
    }
    else
    if ( 
== dome )
    {
        
snprintf buf64"%s.jpg"texture );
        
SkyNode smgr->addSkyDomeSceneNode(
                
driver->getTexturebuf ), 16,8,
                
0.95f2.f1000.f011);
    }

    if (
SkyNode)
        
SkyNode->setName("Skydome");
    
//SkyNode->getMaterial(0).ZBuffer = video::EMDF_DEPTH_LESS_EQUAL;

    
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPSoldMipMapState);
}


// enable GUI elements
void CQuake3EventHandler::SetGUIActives32 command)
{
    
bool inputState false;

    
ICameraSceneNode camera Game->Device->getSceneManager()->getActiveCamera ();

    switch ( 
command )
    {
        case 
0Game->guiActive 0inputState = !Game->guiActive; break;
        case 
1Game->guiActive 1inputState = !Game->guiActive;;break;
        case 
2Game->guiActive ^= 1inputState = !Game->guiActive;break;
        case 
3:
            if ( 
camera )
                
inputState = !camera->isInputReceiverEnabled();
            break;
    }

    if ( 
camera )
    {
        
camera->setInputReceiverEnabled inputState );
        
Game->Device->getCursorControl()->setVisible( !inputState );
    }

    if ( 
gui.Window )
    {
        
gui.Window->setVisible Game->guiActive != );
    }

    if ( 
Game->guiActive &&
            
gui.SceneTree && Game->Device->getGUIEnvironment()->getFocus() != gui.SceneTree
        
)
    {
        
gui.SceneTree->getRoot()->clearChildren();
        
addSceneTreeItem Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() );
    }

    
Game->Device->getGUIEnvironment()->setFocus Game->guiActive gui.Window);

Gestione dell'input nel gioco
Codice PHP:
bool CQuake3EventHandler::OnEvent(const SEventeve)
{
    if ( 
eve.EventType == EET_LOG_TEXT_EVENT )
    {
        return 
false;
    }

    if ( 
Game->guiActive && eve.EventType == EET_GUI_EVENT )
    {
        if ( 
eve.GUIEvent.Caller == gui.MapList && eve.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN )
        {
            
s32 selected gui.MapList->getSelected();
            if ( 
selected >= )
            {
                
stringw loadMap gui.MapList->getListItem selected );
                if ( 
== MapParent || loadMap != Game->CurrentMapName )
                {
                    
printf "Loading map %ls\n"loadMap.c_str() );
                    
LoadMap loadMap );
                    if ( 
== Game->loadParam.loadSkyShader )
                    {
                        
AddSky 1"skydome2" );
                    }
                    
CreatePlayers ();
                    
CreateGUI ();
                    
SetGUIActive );
                    return 
true;
                }
            }
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.ArchiveRemove && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
        {
            
Game->Device->getFileSystem()->removeFileArchivegui.ArchiveList->getSelected() );
            
Game->CurrentMapName "";
            
AddArchive "" );
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.ArchiveAdd && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
        {
            if ( 
== gui.ArchiveFileOpen )
            {
                
Game->Device->getFileSystem()->setFileListSystem FILESYSTEM_NATIVE );
                
gui.ArchiveFileOpen Game->Device->getGUIEnvironment()->addFileOpenDialog L"Add Game Archive" false,gui.Window  );
            }
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_SELECTED )
        {
            
AddArchive gui.ArchiveFileOpen->getFileName() );
            
gui.ArchiveFileOpen 0;
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_DIRECTORY_SELECTED )
        {
            
AddArchive gui.ArchiveFileOpen->getDirectoryName() );
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_CHOOSE_DIALOG_CANCELLED )
        {
            
gui.ArchiveFileOpen 0;
        }
        else
        if ( ( 
eve.GUIEvent.Caller == gui.ArchiveUp || eve.GUIEvent.Caller == gui.ArchiveDown ) &&
            
eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
        {
            
s32 rel eve.GUIEvent.Caller == gui.ArchiveUp ? -1;
            if ( 
Game->Device->getFileSystem()->moveFileArchive gui.ArchiveList->getSelected (), rel ) )
            {
                
s32 newIndex core::s32_clamp gui.ArchiveList->getSelected() + rel0gui.ArchiveList->getRowCount() - );
                
AddArchive "" );
                
gui.ArchiveList->setSelected newIndex );
                
Game->CurrentMapName "";
            }
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.VideoDriver && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
        {
            
Game->deviceParam.DriverType = (E_DRIVER_TYPEgui.VideoDriver->getItemData gui.VideoDriver->getSelected() );
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.VideoMode && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
        {
            
u32 val gui.VideoMode->getItemData gui.VideoMode->getSelected() );
            
Game->deviceParam.WindowSize.Width val >> 16;
            
Game->deviceParam.WindowSize.Height val 0xFFFF;
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.FullScreen && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
        {
            
Game->deviceParam.Fullscreen gui.FullScreen->isChecked();
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Bit32 && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
        {
            
Game->deviceParam.Bits gui.Bit32->isChecked() ? 32 16;
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.MultiSample && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED )
        {
            
Game->deviceParam.AntiAlias gui.MultiSample->getPos();
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Tesselation && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED )
        {
            
Game->loadParam.patchTesselation gui.Tesselation->getPos ();
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Gamma && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED )
        {
            
Game->GammaValue gui.Gamma->getPos () * 0.01f;
            
Game->Device->setGammaRamp Game->GammaValueGame->GammaValueGame->GammaValue0.f0.f );
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.SetVideoMode && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
        {
            
Game->retVal 2;
            
Game->Device->closeDevice();
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Window && eve.GUIEvent.EventType == gui::EGET_ELEMENT_CLOSED )
        {
            
Game->Device->closeDevice();
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Collision && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
        {
            
// set fly through active
            
Game->flyTroughState ^= 1;
            
Player[0].cam()->setAnimateTarget Game->flyTroughState == );

            
printf "collision %d\n"Game->flyTroughState == );
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Visible_Map && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
        {
            
bool v gui.Visible_Map->isChecked();

            if ( 
MapParent )
            {
                
printf "static node set visible %d\n",);
                
MapParent->setVisible );
            }
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Visible_Shader && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
        {
            
bool v gui.Visible_Shader->isChecked();

            if ( 
ShaderParent )
            {
                
printf "shader node set visible %d\n",);
                
ShaderParent->setVisible );
            }
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Visible_Skydome && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED )
        {
            if ( 
SkyNode )
            {
                
bool v = !SkyNode->isVisible();
                
printf "skynode set visible %d\n",);
                
SkyNode->setVisible );
            }
        }
        else
        if ( 
eve.GUIEvent.Caller == gui.Respawn && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
        {
            
Player[0].respawn ();
        }

        return 
false;
    }

    
// fire
    
if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_SPACE &&
        
eve.KeyInput.PressedDown == false) ||
        (
eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
        )
    {
        
ICameraSceneNode camera Game->Device->getSceneManager()->getActiveCamera ();
        if ( 
camera && camera->isInputReceiverEnabled () )
        {
            
useItemPlayer );
        }
    }

    
// gui active
    
if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_F1 &&
        
eve.KeyInput.PressedDown == false) ||
        (
eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_RMOUSE_LEFT_UP)
        )
    {
        
SetGUIActive );
    }

    
// check if user presses the key
    
if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.PressedDown == false)
    {
        
// Escape toggles camera Input
        
if ( eve.KeyInput.Key == irr::KEY_ESCAPE )
        {
            
SetGUIActive );
        }
        else
        if (
eve.KeyInput.Key == KEY_F11)
        {
            
// screenshot are taken without gamma!
            
IImageimage Game->Device->getVideoDriver()->createScreenShot();
            if (
image)
            {
                
core::vector3df pos;
                
core::vector3df rot;
                
ICameraSceneNode cam Game->Device->getSceneManager()->getActiveCamera ();
                if ( 
cam )
                {
                    
pos cam->getPosition ();
                    
rot cam->getRotation ();
                }

                static const 
c8 *dName[] = { "null""software""burning",
                    
"d3d8""d3d9""opengl" };

                
snprintf(buf256"%s_%ls_%.0f_%.0f_%.0f_%.0f_%.0f_%.0f.jpg",
                        
dName[Game->Device->getVideoDriver()->getDriverType()],
                        
Game->CurrentMapName.c_str(),
                        
pos.Xpos.Ypos.Z,
                        
rot.Xrot.Yrot.Z
                        
);
                
path filename buf );
                
filename.replace '/''_' );
                
printf "screenshot : %s\n"filename.c_str() );
                
Game->Device->getVideoDriver()->writeImageToFile(imagefilename100 );
                
image->drop();
            }
        }
        else
        if (
eve.KeyInput.Key == KEY_F9)
        {
            
s32 value EDS_OFF;

            
Game->debugState = ( Game->debugState ) & 3;

            switch ( 
Game->debugState )
            {
                case 
1value EDS_NORMALS EDS_MESH_WIRE_OVERLAY EDS_BBOX_ALL; break;
                case 
2value EDS_NORMALS EDS_MESH_WIRE_OVERLAY EDS_SKELETON; break;
            } 
Imposta il debug della mappa on/off
Codice PHP:
debugState debugState ==  EDS_OFF EDS_NORMALS EDS_MESH_WIRE_OVERLAY EDS_BBOX_ALLEDS_OFF;
            if ( 
ItemParent )

            {
                list<
ISceneNode*>::ConstIterator it ItemParent->getChildren().begin();
                for (; 
it != ItemParent->getChildren().end(); ++it)
                {
                    (*
it)->setDebugDataVisible value );
                }
            }

            if ( 
ShaderParent )
            {
                list<
ISceneNode*>::ConstIterator it ShaderParent->getChildren().begin();
                for (; 
it != ShaderParent->getChildren().end(); ++it)
                {
                    (*
it)->setDebugDataVisible value );
                }
            }

            if ( 
UnresolvedParent )
            {
                list<
ISceneNode*>::ConstIterator it UnresolvedParent->getChildren().begin();
                for (; 
it != UnresolvedParent->getChildren().end(); ++it)
                {
                    (*
it)->setDebugDataVisible value );
                }
            }

            if ( 
FogParent )
            {
                list<
ISceneNode*>::ConstIterator it FogParent->getChildren().begin();
                for (; 
it != FogParent->getChildren().end(); ++it)
                {
                    (*
it)->setDebugDataVisible value );
                }
            }

            if ( 
SkyNode )
            {
                
SkyNode->setDebugDataVisible value );
            }

        }
        else
        if (
eve.KeyInput.Key == KEY_F8)
        {
            
// set gravity on/off
            
Game->gravityState ^= 1;
            
Player[0].cam()->setGravity getGravity Game->gravityState "earth" "none" ) );
            
printf "gravity %s\n"Game->gravityState "earth" "none" );
        }
        else
        if (
eve.KeyInput.Key == KEY_F7)
        {
            
// set fly through active
            
Game->flyTroughState ^= 1;
            
Player[0].cam()->setAnimateTarget Game->flyTroughState == );
            if ( 
gui.Collision )
                
gui.Collision->setChecked Game->flyTroughState == );

            
printf "collision %d\n"Game->flyTroughState == );
        }
        else
        if (
eve.KeyInput.Key == KEY_F2)
        {
            
Player[0].respawn ();
        }
        else
        if (
eve.KeyInput.Key == KEY_F3)
        {
            if ( 
MapParent )
            {
                
bool v = !MapParent->isVisible ();
                
printf "static node set visible %d\n",);
                
MapParent->setVisible );
                if ( 
gui.Visible_Map )
                    
gui.Visible_Map->setChecked );
            }
        }
        else
        if (
eve.KeyInput.Key == KEY_F4)
        {
            if ( 
ShaderParent )
            {
                
bool v = !ShaderParent->isVisible ();
                
printf "shader node set visible %d\n",);
                
ShaderParent->setVisible );
                if ( 
gui.Visible_Shader )
                    
gui.Visible_Shader->setChecked );
            }
        }
        else
        if (
eve.KeyInput.Key == KEY_F5)
        {
            if ( 
FogParent )
            {
                
bool v = !FogParent->isVisible ();
                
printf "fog node set visible %d\n",);
                
FogParent->setVisible );
                if ( 
gui.Visible_Fog )
                    
gui.Visible_Fog->setChecked );
            }

        }
        else
        if (
eve.KeyInput.Key == KEY_F6)
        {
            if ( 
UnresolvedParent )
            {
                
bool v = !UnresolvedParent->isVisible ();
                
printf "unresolved node set visible %d\n",);
                
UnresolvedParent->setVisible );
                if ( 
gui.Visible_Unresolved )
                    
gui.Visible_Unresolved->setChecked );
            }
        }
    }

    
// check if user presses the key C ( for crouch)
    
if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_KEY_C )
    {
        
// crouch
        
ISceneNodeAnimatorCollisionResponse *anim Player[0].cam ();
        if ( 
anim && == Game->flyTroughState )
        {
            if ( 
false == eve.KeyInput.PressedDown )
            {
                
// stand up
                
anim->setEllipsoidRadius (  vector3df(30,45,30) );
                
anim->setEllipsoidTranslation vector3df(0,40,0));

            }
            else
            {
                
// on your knees
                
anim->setEllipsoidRadius (  vector3df(30,20,30) );
                
anim->setEllipsoidTranslation vector3df(0,20,0));
            }
            return 
true;
        }
    }
    return 
false;

metodo useItem
Codice PHP:
void CQuake3EventHandler::useItemQ3Player player)
{
    
ISceneManagersmgr Game->Device->getSceneManager();
    
ICameraSceneNodecamera smgr->getActiveCamera();

    if (!
camera)
        return;

    
SParticleImpact imp;
    
imp.when 0;

    
// get line of camera

    
vector3df start camera->getPosition();

    if ( 
player->WeaponNode )
    {
        
start.+= 0.f;
        
start.+= 0.f;
        
start.+= 0.f;
    }

    
vector3df end = (camera->getTarget() - start);
    
end.normalize();
    
start += end*20.0f;

    
end start + (end camera->getFarValue());

    
triangle3df triangle;
    
line3d<f32line(startend);

    
// get intersection point with map
    
scene::ISceneNodehitNode;
    if (
smgr->getSceneCollisionManager()->getCollisionPoint(
        
lineMetaendtriangle,hitNode))
    {
        
// collides with wall
        
vector3df out triangle.getNormal();
        
out.setLength(0.03f);

        
imp.when 1;
        
imp.outVector out;
        
imp.pos end;

        
player->setAnim "pow" );
        
player->Anim[1].next += player->Anim[1].delta;
    }
    else
    {
        
// doesnt collide with wall
        
vector3df start camera->getPosition();
        if ( 
player->WeaponNode )
        {
            
//start.X += 10.f;
            //start.Y += -5.f;
            //start.Z += 1.f;
        
}

        
vector3df end = (camera->getTarget() - start);
        
end.normalize();
        
start += end*20.0f;
        
end start + (end camera->getFarValue());
    }

    
// create fire ball
    
ISceneNodenode 0;
    
node smgr->addBillboardSceneNodeBulletParent,dimension2d<f32>(10,10), start);

    
node->setMaterialFlag(EMF_LIGHTINGfalse);
    
node->setMaterialTexture(0Game->Device->getVideoDriver()->getTexture("fireball.bmp"));
    
node->setMaterialFlag(video::EMF_ZWRITE_ENABLEfalse);
    
node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);

    
f32 length = (f32)(end start).getLength();
    const 
f32 speed 5.8f;
    
u32 time = (u32)(length speed);

    
ISceneNodeAnimatoranim 0;

    
// set flight line

    
anim smgr->createFlyStraightAnimator(startendtime);
    
node->addAnimator(anim);
    
anim->drop();

    
snprintf buf64"bullet: %s on %.1f,%1.f,%1.f",
                
imp.when "hit" "nohit"end.Xend.Yend.);
    
node->setName buf );


    
anim smgr->createDeleteAnimator(time);
    
node->addAnimator(anim);
    
anim->drop();

    if (
imp.when)
    {
        
// create impact note
        
imp.when Game->Device->getTimer()->getTime() +
            (
time + (s32) ( ( 1.f Noiser::get() ) * 250.f ));
        
Impacts.push_back(imp);
    }

    
// play sound
}

// rendered when bullets hit something
void CQuake3EventHandler::createParticleImpactsu32 now )
{
    
ISceneManagersm Game->Device->getSceneManager();

    
struct smokeLayer
    
{
        const 
c8 texture;
        
f32 scale;
        
f32 minparticleSize;
        
f32 maxparticleSize;
        
f32 boxSize;
        
u32 minParticle;
        
u32 maxParticle;
        
u32 fadeout;
        
u32 lifetime;
    };

    
smokeLayer smoke[] =
    {
        { 
"smoke2.jpg"0.4f1.5f18.f20.f2050200010000 },
        { 
"smoke3.jpg"0.2f1.2f15.f20.f1030100012000 }
    };


    
u32 i;
    
u32 g;
    
s32 factor 1;
    for ( 
0!= 2; ++)
    {
        
smoke[g].minParticle *= factor;
        
smoke[g].maxParticle *= factor;
        
smoke[g].lifetime *= factor;
        
smoke[g].boxSize *= Noiser::get() * 0.5f;
    }

    for ( 
i=0Impacts.size(); ++i)
    {
        if (
now Impacts[i].when)
            continue;

        
// create smoke particle system
        
IParticleSystemSceneNodepas 0;

        for ( 
0!= 2; ++)
        {
            
pas sm->addParticleSystemSceneNode(falseBulletParent, -1Impacts[i].pos);

            
snprintf buf64"bullet impact smoke at %.1f,%.1f,%1.f",
                
Impacts[i].pos.X,Impacts[i].pos.Y,Impacts[i].pos.Z);
            
pas->setName buf );

            
// create a flat smoke
            
vector3df direction Impacts[i].outVector;
            
direction *= smoke[g].scale;
            
IParticleEmitterem pas->createBoxEmitter(
                
aabbox3d<f32>(-4.f,0.f,-4.f,20.f,smoke[g].minparticleSize,20.f),
                
direction,smoke[g].minParticlesmoke[g].maxParticle,
                
video::SColor(0,0,0,0),video::SColor(0,128,128,128),
                
250,400060);

            
em->setMinStartSize (dimension2d<f32>( smoke[g].minparticleSizesmoke[g].minparticleSize));
            
em->setMaxStartSize (dimension2d<f32>( smoke[g].maxparticleSizesmoke[g].maxparticleSize));

            
pas->setEmitter(em);
            
em->drop();

            
// particles get invisible
            
IParticleAffectorpaf pas->createFadeOutParticleAffector(
                
video::SColor 000), smoke[g].fadeout);
            
pas->addAffector(paf);
            
paf->drop();

            
// particle system life time
            
ISceneNodeAnimatoranim sm->createDeleteAnimatorsmoke[g].lifetime);
            
pas->addAnimator(anim);
            
anim->drop();

            
pas->setMaterialFlag(video::EMF_LIGHTINGfalse);
            
pas->setMaterialFlag(video::EMF_ZWRITE_ENABLEfalse);
            
pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
            
pas->setMaterialTexture(0Game->Device->getVideoDriver()->getTexturesmoke[g].texture ));
        }

        
// play impact sound
        #ifdef USE_IRRKLANG
         
if (irrKlang
         { 
            
audio::ISoundsound irrKlang->play3D(impactSoundImpacts[i].posfalsefalsetrue);
            if (
sound
            {
         
// adjust max value a bit to make to sound of an impact louder
               
sound->setMinDistance(400);
               
sound->drop(); 
            }
         }
        
#endif
        // delete entry
        
Impacts.erase(i);
        
i--;
    }


..continua nel Tutorial 21b