top of page

​​Chap 6/100: Keyboard and Mouse input / Infinite Terrain Ground

​

What I will Learn here?:

​On this Chapter we will have several new Classes for user input (Keyboard and Mouse) and for camera movement.

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​​​Note:

This is a infinite Ground Terrain, try it! Move with mouse and keybord arrows or also with: a/s/d/w keys

​​

​Let's check our current main source tree, except the LIBs:

​

Added source on White:

​

​│   Applicationclass.cpp
│   Applicationclass.h
│   counter.h
│   main.cpp
│   main.h
│
├───camera
│       cameraClass.cpp
│       cameraClass.h

│       frustumClass.cpp
│       frustumClass.h
│       positionClass.cpp
│       positionClass.h

│

├───game
│       playerClass.cpp
│       playerClass.h
│
├───input
│       inputClass.cpp
│       inputClass.h

│
├───loader
│       objModelV2Class.cpp
│       objModelV2Class.h
│
├───shader
│       shaderClass.cpp
│       shaderClass.h
│
└───system
        dx11Class.cpp
        dx11class.h
        SystemClass.cpp
        SystemClass.h
        xml_loader.cpp
        xml_loader.h

 

​

​

​(main.h) ​

- Set for Chapter 6

​

​​​​​​(inputClass.cpp)​ - This is where we collect the current Keyboard and Mouse State.

If you need a new key use edit the ProcessInput()​

​I will open here a bit for some things that will come in future:

​

    // Process Keyboard STATE:
    // =======================
    //EXIT:

    m_ourPlayer->p_player.IsEscapePressed    = (m_keyboardState[DIK_ESCAPE] & 0x80) ? true:false;
    //BASE MOVEMENT:
    m_ourPlayer->p_player.IsLeftPressed        = (m_keyboardState[DIK_A] & 0x80) || (m_keyboardState[DIK_LEFT] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsRightPressed    = (m_keyboardState[DIK_D] & 0x80) || (m_keyboardState[DIK_RIGHT] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsUpPressed        = (m_keyboardState[DIK_W] & 0x80) || (m_keyboardState[DIK_UP] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsDownPressed        = (m_keyboardState[DIK_S] & 0x80) || (m_keyboardState[DIK_DOWN] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsLeftCtrlPressed = (m_keyboardState[DIK_LCONTROL] & 0x80)? true:false;
    m_ourPlayer->p_player.IsPgUpPressed        = (m_keyboardState[DIK_PGUP] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsPgDownPressed    = (m_keyboardState[DIK_PGDN] & 0x80) ? true:false;

    //COMPOUND DEBUG:
    #if TUTORIAL_CHAP >= 55
    m_ourPlayer->p_player.IsNumPadMinus        = (m_keyboardState[DIK_SUBTRACT] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsNumPadPlus        = (m_keyboardState[DIK_ADD] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsShift            = (m_keyboardState[DIK_LSHIFT] & 0x80) || (m_keyboardState[DIK_RSHIFT] & 0x80) ? true:false;
    #endif

    //MAP:
    #if TUTORIAL_CHAP >= 26
    m_ourPlayer->p_player.IsMapPressed        = (m_keyboardState[DIK_M] & 0x80) ? true:false;
    #endif

    //BAG:
    #if TUTORIAL_CHAP >= 98
    m_ourPlayer->p_player.IsBagPressed        = (m_keyboardState[DIK_B] & 0x80) ? true:false;
    #endif

    //GOD_MODE
    #if TUTORIAL_CHAP >= 11
    m_ourPlayer->p_player.IsGodModePressed    = (m_keyboardState[DIK_F12] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsAPressed        = (m_keyboardState[DIK_1] & 0x80) ? true:false;
    m_ourPlayer->p_player.IsZPressed        = (m_keyboardState[DIK_Q] & 0x80) ? true:false;
    #endif

    // GAME:
    #if TUTORIAL_CHAP >= 81
    m_ourPlayer->p_player.IsRctrlPressed    = (m_keyboardState[DIK_RCONTROL] & 0x80) ? true:false;
    m_ourPlayer->p_player.Is0Pressed        = (m_keyboardState[DIK_0] & 0x80) ? true:false;
    m_ourPlayer->p_player.Is1Pressed        = (m_keyboardState[DIK_F1] & 0x80) ? true:false;
    m_ourPlayer->p_player.Is2Pressed        = (m_keyboardState[DIK_F2] & 0x80) ? true:false;
    m_ourPlayer->p_player.Is3Pressed        = (m_keyboardState[DIK_F3] & 0x80) ? true:false;
    #endif

​

​​(playerClass​.h​)​ - The header of this class is more important than "c" part. I will define the state of a player here

 

///////////////////////////////////////////////////////////////////////////////
// Filename: playerClass.h
///////////////////////////////////////////////////////////////////////////////

#ifndef _PLAYERCLASS_H_
#define _PLAYERCLASS_H_

///////////////////////////////
// PRE-PROCESSING DIRECTIVES //
///////////////////////////////

#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>    //Zero

#if TUTORIAL_CHAP >= 98
#include "../graphics/spriteClass.h"        //[ch7]
struct Item
{
    std::wstring    itemName;
    SpriteClass*    itemImage;
    UINT            itemLvl;
    float            itemSellPrice;
};

struct BagSlot
{
    Item*            slotItem;
    UINT            ItemIdx;
    UINT            numItems;
};
#endif

/////////////
// GLOBALS //
/////////////


#if TUTORIAL_CHAP < 90
#define N_MAX_PLAYERS 1
#else
#define N_MAX_PLAYERS 10    //network support added on CH 90: Align with: network\server\networkmessages.h
#endif//


typedef struct
{    // ids:
    // --------------------------------------------------------------------------------

    bool online;            // Network State
    char playerName[16];    // id key for Server
    UINT hittedByBullet;    // id of player that is shotting on you...
    bool bottleHit;            // Means this player is selected to a detail view...
    bool visibel;            // Visible from on our frustrum?

    // Current Position:
    // --------------------------------------------------------------------------------

    D3DXMATRIX    m_world;    // World Matrix: our position in the 3D world space

    //Network State:
    // --------------------------------------------------------------------------------

    #if TUTORIAL_CHAP >= 90
    bool faction;            // Luso Aliance: true / Vandals Horde: false
    BYTE meshType;            // Race type
    BYTE playerlvl;            // player level
    float health;            // player health
    BYTE ammu[3+1];            // player # ammu on weapon: X
    BYTE currentWeapon;        // Current Weapon Id (0, 1,2,3)
    #endif

    //Private State
    // --------------------------------------------------------------------------------

    #if TUTORIAL_CHAP >= 80
    float    gold;            // Current Gold $$$ on pocket.
    UINT    XP;                // Current eXPerince
    #endif
    #if TUTORIAL_CHAP >= 98
    BagSlot    bag[10];
    #endif

    //Keyboard State:
    // --------------------------------------------------------------------------------


    //EXIT:
    bool IsEscapePressed;   

    //BASE MOVEMENT:
    bool IsLeftPressed;        // <- or a
    bool IsRightPressed;    // -> or d
    bool IsUpPressed;        // ^ or w
    bool IsDownPressed;        // v or s
    bool IsLeftCtrlPressed; // RUN:            left ctrl
    bool IsPgUpPressed;        // LOOK UP:        pg up
    bool IsPgDownPressed;    // LOOK DOWN:    pg down

    //DEBUG / COMPOUND:
    #if TUTORIAL_CHAP >= 55
    bool IsNumPadPlus;        // work also with L CTRL or R CTRL
    bool IsNumPadMinus;        // work also with L CTRL or R CTRL
    bool IsShift;            // Both Shifts
    #endif

    //MAP:

    #if TUTORIAL_CHAP >= 26
    bool IsMapPressed;        // M
    #endif

    //BAG:
    #if TUTORIAL_CHAP >= 98
    bool IsBagPressed;        // B
    #endif

    //GOD_MODE:
    #if TUTORIAL_CHAP >= 11
    bool IsGodModePressed;    // F12
    bool IsAPressed;        // GOD MODE:    1
    bool IsZPressed;        // GOD MODE:    q
    #endif

    // GAME:
    bool IsRctrlPressed;    // RUN

    // WEAPON
    #if TUTORIAL_CHAP >= 81
    bool Is0Pressed;        // NO WEAPON 0
    bool Is1Pressed;        // WEAPON1     F1
    bool Is2Pressed;        // WEAPON2     F2
    bool Is3Pressed;        // WEAPON3     F3
    #endif

} playerType;


///////////////////////////////////////////////////////////////////////////////
// Class name: PlayerClass
///////////////////////////////////////////////////////////////////////////////
class PlayerClass
{
public:
    PlayerClass();
    ~PlayerClass();

public:
    playerType p_player;
    #if TUTORIAL_CHAP >= 96
    std::vector<BagSlot> BagContents; // note: this couse a memory leack...
    #endif
};

#endif

​

​

​(positionClass.cpp)​ - This Class will calculate our position based on movement.

If we press a key like (up arrow) this will cause an aceleration. This aceleration will increase our speed until a defined max speed. Our position will be determinated by the famous newton formula: s = v . t and v = a . t

​

​​//This function calculates the forward speed and movement of the viewer/camera.
void PositionClass::MoveForward(bool keydown, bool ctrl, bool water)
{
    // Update the forward speed movement based on the frame time and whether the user is holding the key down or not.

if(keydown)
    {
        m_forwardSpeed += m_frameTime * (ctrl) ? 0.002f:0.001f;
v = a . t
        float maxSpeed = ctrl ? 0.04f : 0.005f;
        #if TUTORIAL_CHAP >= 40
        if (water)
            maxSpeed/=3;
        #endif//

        if(m_forwardSpeed > (maxSpeed *
m_frameTime))
            m_forwardSpeed =
maxSpeed * m_frameTime;    s = v . t
    }
    else
    {
        m_forwardSpeed -= m_frameTime * 0.0007f;

        if(m_forwardSpeed < 0.0f)
            m_forwardSpeed = 0.0f;
    }

    m_positionX += FAST_sin(m_rotationY) * m_forwardSpeed;
    m_positionZ += FAST_cos(m_rotationY) * m_forwardSpeed;


 

​

​

​(frustumClass.cpp)​ - This class implement a concept called Frustrum on CPU side. Basically this class will implement a filter of objects that are inside of our camera view the other will not be send to the GPU

Later we will check a Frustrum on GPU side.

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​​

 

​​​​​(applicationClass.cpp)​ - CHANGES

​

​Main part of applicationClass

​

​​    //#############################################################################################################
    //      3D    
    //#############################################################################################################

    // 1. 3D RENDERING: SKY
    //----------------------------------------------------------------------------------------------------------------------
    //

    // 2. For demos only:

    //----------------------------------------------------------------------------------------------------------------------
    g_deviceContext->RSSetState(m_DirectX11->m_rasterStateCullFront[FILL_MODE]);
    #define GROUND_PATCH_SIZE 4
    #define N_PATCHEs 6
#if (TUTORIAL_CHAP >= 4)  && defined (SCENE_OBJMODEL) //Note: CH7 become world sand
    for (int z=(int)m_Camera.m_positionZ/GROUND_PATCH_SIZE -N_PATCHEs; z < m_Camera.m_positionZ/GROUND_PATCH_SIZE +N_PATCHEs; z++)
    {
        for (int x=(int)m_Camera.m_positionX/GROUND_PATCH_SIZE -N_PATCHEs; x <= m_Camera.m_positionX/GROUND_PATCH_SIZE +N_PATCHEs; x++)
        {
            objModel.m_world._41 = (float)GROUND_PATCH_SIZE*x;
            objModel.m_world._42 = 0;
            objModel.m_world._43 = (float)GROUND_PATCH_SIZE*z;
            if (m_Frustum->CheckSphere(objModel.m_world._41, 0, objModel.m_world._43, GROUND_PATCH_SIZE) ) //Because its faster than squar
            {
                objModel.render(pContext);
            }
        }
    }
#endif//

    // 3. 3D RENDERING: Terrain
    //----------------------------------------------------------------------------------------------------------------------
    //

    //#############################################################################################################
    //      2D    
    //#############################################################################################################

​

 

​

​

​To navigate on source code:

 

User: public

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​Project Code:

​

​WoMA_Chap6.zip

​​​

​What's next?

We will learn how to render 2D IMAGES (orthogonal projection) Sprites​ / how to render a simple Sky with a Fixed Camera

​

bottom of page