こちらの龍神録C++版をDLしてソースコードを見て、自分のやりたい操作が書いていったのですが、わからないところもありましたので質問させてください、DLするのは大変だとおもうのでDLしたソースコードの中から載せます。
key
#ifndef DEF_KEY_H
#define DEF_KEY_H
#define KEY_CODE_NUM 256
#include "Singleton.h"
class CKey : public CSingleton<CKey>{
int m_nKey[ KEY_CODE_NUM ];
public:
CKey();
void Update();
int Get( int sKeyCode );
};
#endif
//--------------------------------------------------------------------------------------------------
#include <DxLib.h>
#include "Macro.h"
#include "Key.h"
/*
@brief コンストラクタ
*/
CKey::CKey(){
memset( m_nKey, 0, sizeof( m_nKey ) );
}
/*
@brief キーが押されているフレーム数の更新
*/
void CKey::Update(){
char tmpKey[KEY_CODE_NUM]; //現在のキーの入力状態を格納する
GetHitKeyStateAll( tmpKey ); //全てのキーの入力状態を得る
for( int i=0; i<KEY_CODE_NUM; i++ ){
if( tmpKey[i] != 0 ){ //i番のキーコードに対応するキーが押されていたら
if( m_nKey[i] < 0 ){//前フレームで離されていたら
m_nKey[i] = 1; //入力して1フレーム目にする
} else { //前フレームで押されていたら
m_nKey[i]++; //入力フレーム数を加算
}
} else { //押されていなければ
if( m_nKey[i] > 0 ){//前フレームで押されていたら
m_nKey[i] = -1; //離されて1フレーム目にする
} else { //前フレームで離されていたら
m_nKey[i]--; //離されているフレーム数を加算(減算)
}
}
}
}
/*
@brief KeyCodeのキーが押されてるフレーム数を返す
@param[in] sKeyCode キーコード(KEY_INPUT_Zとか)
*/
int CKey::Get( int sKeyCode ){
if( !( 0<= sKeyCode && sKeyCode < KEY_CODE_NUM ) ){
eprintfDx("KeyCodeが範囲外です。 %d", sKeyCode );
return -1;
}
return m_nKey[ sKeyCode ];
}
#ifndef DEF_PLAYER_H
#define DEF_PLAYER_H
#include "BaseChara.h"
#include "PlyrShot.h"
namespace nsPlayer{
static const int sBodySize = 50;
static const float fHitRange = 2.1f;
};
class CPlayer : public CBaseChara{
unsigned int m_uPow;
CPlyrShot *m_pPlyrShot;
bool Process_Hit();
public:
CPlayer(ScrPrm_t* Prm);
~CPlayer();
bool Initialize() override;
bool Process() override;
void Draw() override;
bool Hit( int nPow ) override;
void StartBossBattle() override;
bool Process_Ctrl();
void LoadModel();
void SetType(){ m_eType = nsChara::ePlyr; }
void SetBodySize(){ m_fBodyH = 17.f; m_fBodyD = -5.f; m_nBodySize = 0; }
void SetHitRange(){ m_fHitRange = nsPlayer::fHitRange; }
void DeleteAllShot(){ m_pPlyrShot->Delete(); }
std::list<CBullet*>* GetBulList(){ return m_pPlyrShot->GetBulList(); }
const VECTOR GetTalkPrevPos();
const VECTOR GetTalkNextPos();
};
#endif
//--------------------------------------------------------------------------------------------------------------
#include <math.h>
#include "Player.h"
#include "Key.h"
#include "GameDefine.h"
#include "CommonDefine.h"
#include "Model.h"
#include "Facade.h"
#include "Util.h"
#include "EffMgr.h"
#include "Eff_HitBom.h"
#include "SndGame.h"
using namespace std;
static const float csMoveSpd = 3.0f;
static const int csHitBomTime = 10;
static const int csReturningTime = 10;
const static VECTOR vNextPos={ FWO/2, FHO*4/5, 0 };
CPlayer::CPlayer(ScrPrm_t* Prm):CBaseChara(Prm){
m_uPow = 0;
m_vPos.x = FWO / 2;
m_vPos.y = FWO * 3 / 4;
m_pPlyrShot = new CPlyrShot( &m_vPos, &m_uPow );
m_bReady = true;
}
CPlayer::~CPlayer(){
delete m_pPlyrShot; m_pPlyrShot = nullptr;
}
void CPlayer::LoadModel(){
m_nMdl = CModel::Inst()->Get( eMDL_Reimu );
}
bool CPlayer::Initialize(){
CBaseChara::Initialize();
MV1SetRotationXYZ( m_nMdl, VGet( DEF_MDLROTA_X, PI, 0.0f ) ) ;
return true;
}
// キー入力による自機の移動計算
bool CPlayer::Process_Ctrl(){
float x=0, y=0;
//-----------------------------------------------------------------------------------------※このような書き方をしたい!
if( CKey::Inst()->Get( KEY_INPUT_LEFT ) > 0 ){ x = -csMoveSpd; }
if( CKey::Inst()->Get( KEY_INPUT_RIGHT ) > 0 ){ x = +csMoveSpd; }
if( CKey::Inst()->Get( KEY_INPUT_UP ) > 0 ){ y = -csMoveSpd; }
if( CKey::Inst()->Get( KEY_INPUT_DOWN ) > 0 ){ y = +csMoveSpd; }
//------------------------------------------------------------------------------------------------------------------------
if( x && y ){ //斜めに移動中なら
x /= sqrt(2.0f); //√2で割る
y /= sqrt(2.0f);
}
if( CKey::Inst()->Get( KEY_INPUT_LSHIFT ) > 0 ){ //低速移動中なら
x /= 3.0f; //速度を1/3にする
y /= 3.0f;
}
m_vPos.x += x; m_vPos.y += y;
if( m_vPos.x < FX ){ m_vPos.x = FX; } //画面外にはみ出すなら、再端に設定
if( FX+FW < m_vPos.x ){ m_vPos.x = FX+FW; }
if( m_vPos.y < FY ){ m_vPos.y = FY; }
if( FY+FH < m_vPos.y ){ m_vPos.y = FY+FH; }
return true;
}
bool CPlayer::Process(){
if( m_bNowTalking ){
return true;
}
switch( m_eState ){
case eRETURNING: //浮上中
m_vPos.y-=2;
if( m_nCnt == 60 ){
m_nCnt=0;
m_eState = eNORMAL;
}
break;
case eNORMAL: //通常
Process_Ctrl();
break;
case eHITTING: //喰らいボム受付中
if( m_nCnt == csHitBomTime ){
m_eState = eRETURNING;
m_nCnt = 0;
m_vPos.x = FWO/2;
m_vPos.y = FHO + nsPlayer::sBodySize;
// CEff_Base *p = CEffMgr::Inst()->Get( eEFFTYPE_HITBOM, 0 );
// if( p ){
// p->SetDelFlag();
// }
}
break;
default:
break;
}
Process_Hit();
m_pPlyrShot->Process();
return CBaseChara::Process();
}
void CPlayer::Draw(){
m_pPlyrShot->Draw();
CBaseChara::Draw();
}
void CPlayer::StartBossBattle(){
m_vPos = vNextPos;
m_pMotion->Attach( eMdlAnim_Normal );
}
//被弾時処理
bool CPlayer::Hit( int nPow ){
m_eState = eHITTING;
m_nCnt = 0;
CEffMgr::Inst()->Register( new CEff_HitBom(csHitBomTime) );
CSndGame::Inst()->SetPlay( eSNDGM_PlyrHit );
return false; //死亡するならfalseを返す。自機にはHPが無いので必ずfalse
}
bool CPlayer::Process_Hit(){
// 敵が持つ弾リストのリストを取得
list< list<CBullet* >* > ListOfBulList;
// 敵が持つレーザーリストのリストを取得
list< list<CLaser * >* > ListOfLasList;
CFacade::Inst()->GetListOfBulList( ListOfBulList, ListOfLasList );
//弾リストのリスト分ループ
for(list< list<CBullet* >* >::iterator it=ListOfBulList.begin();it!=ListOfBulList.end();it++){
//弾リスト分ループ
for(list< CBullet* >::iterator bl=(*it)->begin();bl!=(*it)->end();bl++){
if( Util_IsHit( (*bl)->GetPos(), (*bl)->GetSpd(), (*bl)->GetAng(), (*bl)->GetHitR(),
m_vPos, m_fHitRange ) ){
if( m_eState == eNORMAL ){
Hit( 0 ); //自機の場合、ダメージ量を表す引数0に意味は無い
}
(*bl)->SetDelFlag();
return true;
}
}
}
return false;
}
const VECTOR CPlayer::GetTalkPrevPos(){
return Get3DPos();
}
const VECTOR CPlayer::GetTalkNextPos(){
return Util_Get3DPos( vNextPos, m_fBodyD, m_fBodyH, DEF_MDLROTA_X );
}
順を追って説明します。Key関係は、幸いコードに説明(コメント)もついていましたし、理解できました。
(Getの返り値が0以上ということは、update(押下されるとGetの返り値と同じ値が加算される)であるように押下状態を示し、player.cppにあるif( CKey::Inst()->Get( KEY_INPUT_LEFT ) > 0 )は左が押されている時・・・というのは理解できました。また、ループでkeyのupdateを呼べばいいことも分かります)
しかし、if( CKey::Inst()->Get( KEY_INPUT_LEFT ) > 0 )にある「Inst()」の意味がイマイチわかりません。シングルトンと調べたのですが例が少なくて理解に苦しんでいるのが現状です。(テンプレートに関しては、少ししか勉強していません・・・)
Inst()の存在理由がわからないので、もしif( CKey::Inst()->Get( KEY_INPUT_LEFT ) > 0 )からInstを取るとどうなってしまうのかなどわかりません。(コメント(説明がなかったため理解できませんでした・・・))
自分なりにまとめた結果、Key.hにもSingleton.hがインクルードされていますし、Singleton.hさえ理解すればこの問題は解決されると思っているので、どうか仕組みとソースの意味を教えてください。(Singleton.hは下に貼っておきます。)
Singleton.h
#ifndef DEF_SINGLETON_H
#define DEF_SINGLETON_H
template <typename _T>
class CSingleton {
protected:
CSingleton() {
}
virtual ~CSingleton() {
// m_pInst = nullptr;
}
// static _T* m_pInst;
public:
static _T* Inst() {
static _T inst;
return &inst;
// if ( m_pInst == nullptr ){
// m_pInst = new _T;
// }
// return m_pInst;
};
};
//template<typename _T>
//_T* CSingleton<_T>::m_pInst = nullptr;
#endif