my third person camera jka style (not finished)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
noals
Posts: 70
Joined: Sun May 18, 2008 2:59 pm

my third person camera jka style (not finished)

Post by noals »

hi,

well, im receiving some mp with questions about a 3rd person caméra i started in the "beginners help" forum and since the questions are often about things i solved with help of some people or found out, i just share my code and project as it is for now.

its really not finished :
-i dont use external class.
-the zoom is kinda bugued
-there is still the problem about terrain collision i didnt fixed yet (through there is some fix here for exemple)
-no animation yet either (i was working on it when i stopped..)

what does it do :
-load a terrain and spawn a player
-the mouse X axis control the player rotation
-the mouse Y axis control the camera hightness kinda
-the mouse wheel zoom in and out (or is supposed to do so ^^)
-Z,Q,S,D move the player (foward, backward and strafe right and left)
-space for jumping (that help to avoid the terrain bug^when testing..)
-a little black window with FPS.

that's it i think.
i repeat myself but its really not a finished work but maybe that will help people that are bad programmer like me to understand some stuff.
be sure that when all the stuff i want to do are done, i will upload it all for the community but im more into modeling right now or other stuff like mysql so for now i just share that to answer some question i receive in mp.

feel free to use it as you like or to improve it.
dont expect me to answer question about it because if i started it in the 'beginners help" forum, its because im really a beginner...

anyway :
here is my full c::b project so you can take a look (irrlicht 1.4)

update* http://www.fileden.com/files/2006/6/21/80755/Demo3.zip
a little messed up like the first one anyway lol but work with irrlicht 1.7.3

update*2 http://www.fileden.com/files/2006/6/21/ ... _start.zip
it say newton but dont actualy use it, the code is more clean in this version.
beware that in this version i dont use any collision. its actualy my starting point to then use newton as a physic engine if i get it to work someday..


and the full code : (outdated)
(some stuff are in french, sorry for that)

Code: Select all

#include <irrlicht.h>
#include <iostream>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
#pragma comment(lib, "Irrlicht.lib")
 
 
 
//--->  DEFINITION  <---///////////////////////////////////////////////////////////////////////////
bool keys[KEY_KEY_CODES_COUNT];
position2d<f32> cursor;             //position du curseur de la souris
position2d<s32> ScreenCenter;       //centre de l'ecran bien que le curseur soit pas d'accord avec ça lol
f32 RotationSpeed= 1.0;             //determine la vitesse de rotation du joueur.
f32 playerSpeed= 0.8;               //vitesse du joueur
vector3df playerRot;                //rotation du joueur
vector3df playerPos;                //position du joueur
vector3df cameraPos;                //position de la camera
f32 cameraDistance= 100;
 
///////////////////////////////////////////////////////////////////////////////////////////////////
//--->  EVEN RECEIVER  <---////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
 
class MyEventReceiver: public IEventReceiver
{
    public: virtual bool OnEvent(const SEvent& event)
    {
        if (event.EventType == EET_MOUSE_INPUT_EVENT)
        {
            cursor.X = event.MouseInput.X;
            cursor.Y = event.MouseInput.Y;
        }
        if(event.MouseInput.Event == EMIE_MOUSE_WHEEL)
        {
            cameraDistance += -event.MouseInput.Wheel* (cameraDistance / 20) * 3;
            if(cameraDistance < 10) cameraDistance = 10;
        }
 
        if(event.EventType == EET_KEY_INPUT_EVENT)
        {
            keys[event.KeyInput.Key] = event.KeyInput.PressedDown;
            return false;
        }
        return false;
    }
};
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                       //////////////////////////////////////////////////////
//////////////////////////////         MAIN          //////////////////////////////////////////////////////
//////////////////////////////                       //////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
int main()
{
    MyEventReceiver receiver;                  //initialisation du receiver
    IrrlichtDevice* device = createDevice(
        EDT_OPENGL,                            //EDT_SOFTWARE, EDT_NULL, EDT_DIRECT3D8, EDT_DIRECT3D9, EDT_OPENGL
        dimension2d<s32>(800, 600),
        32,
        true,                                  //fullscreen ?
        false, false,                          //?
        &receiver);                            //node receiver
        device->setEventReceiver(&receiver);   // "   "  same
    if (device == 0)return 1;                  //exit if creation failed
 
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
    ICursorControl* myCursor = device->getCursorControl();
 
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                       //////////////////////////////////////////////////////
//////////////////////////////       TERRAIN         //////////////////////////////////////////////////////
//////////////////////////////                       //////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
    ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
        "heightmap/F18.bmp",                                               //heightmap
        0,                                                                 //parent
        -1,                                                                //ID
        vector3df(0.f, 0.f, 0.f),                                          //position
        vector3df(0.f, 0.f, 0.f),                                          //rotaton ?
        vector3df(500,33, 500),                                            //scaling de la heightmap / taille
        SColor(255, 255, 255, 250),                                        //couleur des vertex
        5,                                                                 //detail du node
        ETPS_33,                                                           //patchsize wth ??
        3,                                                                 //smoothfactor
        false);                                                            //add terrain node even with empty heightmap
 
    terrain->setMaterialFlag(EMF_LIGHTING, false);                            //lumière ?
    terrain->setMaterialTexture(0, driver->getTexture("terrain/herbe.jpg"));  //texture
    terrain->setMaterialType(EMT_DETAIL_MAP);
    terrain->scaleTexture(600, 48000);                                        //scaling de la texture
 
//SKYBOX
    driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);              //true ?
    smgr->addSkyBoxSceneNode(
        driver->getTexture("skybox/siege_up.jpg"),                   //up
        driver->getTexture("skybox/siege_dn.jpg"),                   //down
        driver->getTexture("skybox/siege_lf.jpg"),                   //left
        driver->getTexture("skybox/siege_rt.jpg"),                   //right
        driver->getTexture("skybox/siege_bk.jpg"),                   //back
        driver->getTexture("skybox/siege_ft.jpg"));                  //front
        driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);        //?
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                             ////////////////////////////////////////////////
//////////////////////////////       TRIANGLE SELECTOR     ////////////////////////////////////////////////
//////////////////////////////                             ////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
    ISceneNode* terrainNode = 0;
    if(terrain)
    terrainNode = smgr->addMeshSceneNode(terrain->getMesh());
 
    ITriangleSelector* selector = 0;
    if(terrainNode)
    {
        terrainNode->setPosition(vector3df(-1370,-130,-1400));
        selector = smgr->createTerrainTriangleSelector(terrain, 0);
        terrainNode->setTriangleSelector(selector);
        selector->drop();
    }
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
//////////////////////////////          PLAYER         ////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
    for(int x=0; x<irr::KEY_KEY_CODES_COUNT; x++) keys[x] = false;  //key count
 
    ISceneNode* playerNode = smgr->addEmptySceneNode();             //3rd person
    playerNode->setPosition(vector3df(19000, 6000, 37000));
 
    IAnimatedMesh* playerMesh= smgr->getMesh("models/faerie.md2");                                //model
    IAnimatedMeshSceneNode* visualNode= smgr->addAnimatedMeshSceneNode(playerMesh, playerNode);
    if (visualNode)
    {
        visualNode->setMaterialFlag(EMF_LIGHTING, false);
        visualNode->setFrameLoop(0, 159); // 0,310
        visualNode->setAnimationSpeed(35);
        visualNode->setMaterialTexture(0, driver->getTexture("models/faerie.bmp"));               //texture
        visualNode->setRotation(core::vector3df(0,90,0)); //player dos a la caméra
    }
 
//COLLISION PLAYER
    const aabbox3df& box=        playerNode->getBoundingBox();
    const f32 height=            (box.MaxEdge.Y - box.MinEdge.Y)/ 2.f;
    const f32 verticalOffset=    -box.MinEdge.Y - box.MaxEdge.Y;
    const f32 waist=             max_(box.MaxEdge.X - box.MinEdge.X, box.MaxEdge.Z - box.MinEdge.Z)/ 2.f;
 
    ISceneNodeAnimator* anim= smgr->createCollisionResponseAnimator
    (
        selector,                                  //triangle selector
        playerNode,                                //scene node
        vector3df(30,25,30),                       //ellipsoidRadius  //position du perso 30;60;30
        vector3df(0,-3,0),                         //gravity
        vector3df(0,0,0),                          //ellipsoidTranslation
        0.0005f                                    //slidingValue
    );
    playerNode->addAnimator(anim);
    anim->drop();
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
//////////////////////////////         ANIMATION       ////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
bool STAND = false;
if(STAND == true)
{
    visualNode->setFrameLoop(0, 159);
}
 
bool RUN = false;
if(RUN == true)
{
    visualNode->setFrameLoop(160, 183);
}
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
//////////////////////////////          CAMERA         ////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
    ICameraSceneNode* myCamera =
    smgr->addCameraSceneNode(
        playerNode,                                      //parent
        vector3df(0,75,100),                             //angleX, angleH, distance
        playerNode->getPosition(), //vector3df(0,0,0),   //look at...
        -1);                                             //ID
    myCamera->setFarValue(80000);                        //drawing distance
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
//////////////////////////////          CURSOR         ////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
    myCursor->setVisible(false);
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
//////////////////////////////        RENDERING        ////////////////////////////////////////////////////
//////////////////////////////                         ////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
    IGUIEnvironment* guienv = device->getGUIEnvironment();
    IGUIStaticText* debug_panel = guienv->addStaticText(L"",rect<s32>(15, 15, 50, 30),true,true,0,-1,false); //100 : L - h
 
 
    while(device->run())
    {
 
 
    driver->beginScene(true, true, SColor(0,200,200,200));
 
//--------------------------------------------------------------------------------------------------------
    ScreenCenter.X= 400;
    ScreenCenter.Y= 300;
    playerRot.X=0;
    playerRot.Y=playerNode->getRotation().Y+RotationSpeed*(ScreenCenter.X-cursor.X)*-1;
    playerRot.Z=0;
    cameraPos.X=0;
    cameraPos.Y=myCamera->getPosition().Y+/*RotationSpeed*/(ScreenCenter.Y-cursor.Y)*-1;
    cameraPos.Z=cameraDistance;//100;
    playerPos= playerNode->getPosition();
 
 
 
 
    if(keys[KEY_KEY_S]) //moving back
    {
        f32 roty_rad = playerRot.Y * PI / 180; // convert to radians
        playerPos.Z += playerSpeed * cos(roty_rad);
        playerPos.X += playerSpeed * sin(roty_rad);
    }
 
    if(keys[KEY_KEY_Z]) //moving foward
    {
        f32 roty_rad = playerRot.Y * PI / 180; // convert to radians
        playerPos.Z -= playerSpeed * cos(roty_rad);
        playerPos.X -= playerSpeed * sin(roty_rad);
    }
 
    if(keys[KEY_KEY_D]) //strafing right
    {
        f32 roty_rad = playerRot.Y;
        roty_rad -= 90;
        roty_rad *= PI / 180;
        playerPos.Z += playerSpeed * cos(roty_rad);
        playerPos.X += playerSpeed * sin(roty_rad);
    }
 
    if(keys[KEY_KEY_Q]) //strafing left
    {
        f32 roty_rad = playerRot.Y;
        roty_rad += 90;
        roty_rad *= PI / 180;
        playerPos.Z += playerSpeed * cos(roty_rad);
        playerPos.X += playerSpeed * sin(roty_rad);
    }
 
    if(keys[KEY_SPACE])playerPos.Y = playerPos.Y + 3.5f;
 
//--------------------------------------------------------------------------------------------------------
 
        myCamera->setTarget(playerNode->getPosition()); //refresh caméra target
        myCamera->setPosition(cameraPos);
 
        playerNode->setPosition(playerPos);
        playerNode->setRotation(playerRot);
        myCursor->setPosition(ScreenCenter);            //remise a zéro du cursor
 
        smgr->drawAll();
 
 
        stringw framerate = driver->getFPS();
        debug_panel->setText(stringw(framerate).c_str());       //framerate
        debug_panel->setOverrideColor(SColor(255,255,255,255));
        debug_panel->setBackgroundColor(SColor(255,0,0,0));
 
        device->getGUIEnvironment()->drawAll();
        driver->endScene();
    }
    device->drop();
    return 0;
 
}
Last edited by noals on Thu Sep 13, 2012 10:28 pm, edited 4 times in total.
vargero
Posts: 4
Joined: Mon Jun 16, 2008 12:06 pm

Post by vargero »

It helped a lot! I'm testing it, I'll change it to make it look like I need, and I'll post the code here later. Thanks again noals!
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

i'll set up a test program for it later.

thanks for sharing the code.
Image
noals
Posts: 70
Joined: Sun May 18, 2008 2:59 pm

Post by noals »

i think the rotation fonction in this post should help to improve the algo in mine because in the lineage post, the zoom work pretty well.

sorry, i dont take the time to fix it all myself through i still have a lot to do or to learn about programming for a project of mine.
my problem is : i do too much stuffs at the same time so i need to focus on one at a time because its kinda hard to focus on programming, network programming, modeling, 2D graphism, music (im a musician), making my own guitar as well, etc... you get the picture. ^^;

im glad it can already help.
cya
Post Reply