​​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:
​
​​​
​What's next?
We will learn how to render 2D IMAGES (orthogonal projection) Sprites​ / how to render a simple Sky with a Fixed Camera
​