リファクタリングもしてない。整理もしてない。とりあえず書いてみただけ。
このコードはひどいので使ってもかまいませんが、どうなってもわたしは知りません。
もし「このコードをコンパイルしてPCが壊れた!」や「パソコンが炎上(物理)した!」など、このプログラムの使用において、わたしはいかなる損害も責任はとりません。ご了承ください。
また、そのままの形で再利用もおやめください。
main.cpp
► スポイラーを表示
#include <DxLib.h>
#include <memory>
#include <string>
#include "StageMgr.h"
#include "FpsControl.h"
auto WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow ) -> int
{
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );
auto pStage = std::make_unique< CStageMgr >();
auto pFps = std::make_unique< CFps >();
while( !ProcessMessage() ) {
ClearDrawScreen(); clsDx();
pStage->Proc();
pFps->Proc();
pStage->Draw();
pFps->Draw();
ScreenFlip();
pFps->Wait();
}
DxLib_End();
return 0;
}
► スポイラーを表示
#pragma once
struct Pos_t
{
int x, y;
Pos_t( int x = 0, int y = 0 ) :
x( x ),
y( y )
{
}
Pos_t& operator += ( const Pos_t& p )
{
this->x += p.x;
this->y += p.y;
return *this;
}
Pos_t operator + ( const Pos_t& p )
{
return { this->x + p.x, this->y + p.y };
}
Pos_t operator - ( const Pos_t& p )
{
return { this->x - p.x, this->y - p.y };
}
};
/**
* 方向
*/
enum class eDir : unsigned
{
eNONE = 0x00000,
eUP = 0x00001,
eLEFT = 0x00002,
eDOWN = 0x00004,
eRIGHT = 0x00008,
};
► スポイラーを表示
#pragma once
#include "Common.h"
#include <memory>
class IStageContext
{
public:
virtual ~IStageContext() {}
/**
* プレイヤーが最初にいる場所
* RPG やったことないから適当
*/
virtual Pos_t GetMapFirstPos() const = 0;
/**
* 現在の座標( nowPos )から方向( dir )に進めるかどうか
* true : 進める
* false : 進めない
*/
virtual bool IsAbleToGo( const Pos_t& nowPos, const eDir& dir ) const = 0;
};
typedef std::shared_ptr< IStageContext > StageContextPtr;
class IGlobalContext
{
public:
virtual ~IGlobalContext() {}
virtual StageContextPtr GetStageContext() const = 0;
};
typedef std::shared_ptr< IGlobalContext > GlobalContextPtr;
► スポイラーを表示
► スポイラーを表示
#include <chrono>
#include <Windows.h>
#include <DxLib.h>
#include "FpsControl.h"
namespace
{
static const int FPS = 60;
static const int CALC_COUNT = 60;
}
CFps::CFps() :
m_Count(),
m_StartTime(),
m_Fps()
{
}
CFps::~CFps()
{
}
void CFps::Proc()
{
if( m_Count == 0 ) {
m_StartTime = std::chrono::system_clock::now();
}
if( m_Count == CALC_COUNT ) {
auto t = std::chrono::system_clock::now();
auto subMsec = std::chrono::duration_cast< std::chrono::milliseconds >( t - m_StartTime ).count();
m_Fps = 1000.0 / ( subMsec / ( double )CALC_COUNT );
m_Count = 0;
m_StartTime = t;
}
m_Count++;
}
void CFps::Draw()
{
DrawFormatString( 0, 2, GetColor( 255, 255, 255 ), "%.3lf", m_Fps );
}
void CFps::Wait()
{
// 実際にかかった時間
auto nowTime = std::chrono::system_clock::now();
auto tookTime = std::chrono::duration_cast< std::chrono::milliseconds >( nowTime - m_StartTime ).count();
// 理想の時間
auto waitTime = m_Count * 1000 / FPS - tookTime;
if( waitTime > 0 ) {
::Sleep( ( DWORD )waitTime );
}
}
► スポイラーを表示
#pragma once
#include "Interface.h"
#include "Common.h"
#include <memory>
class CPlayer
{
IGlobalContext* m_pContext;
Pos_t m_MapPos; // マップ上の座標
Pos_t m_DrawPos; // 描画の時の座標
public:
CPlayer( IGlobalContext* pContext );
~CPlayer();
void Proc();
void Draw();
};
typedef std::shared_ptr< CPlayer > PlayerPtr;
► スポイラーを表示
#include "Player.h"
#include "Common.h"
#include <DxLib.h>
#include "BaseStage.h"
// 書くところが思いつかなかったからここに書く
// 後で直します
// マップ上の座標からスクリーン上の座標に変換する
inline Pos_t ConvPos( const Pos_t& mapPos )
{
int x = CBaseStage::MAP_DRAW_POS_X + CBaseStage::MAP_ONE_BLOCK_SIZE * mapPos.x + CBaseStage::MAP_ONE_BLOCK_SIZE / 2;
int y = CBaseStage::MAP_DRAW_POS_Y + CBaseStage::MAP_ONE_BLOCK_SIZE * mapPos.y + CBaseStage::MAP_ONE_BLOCK_SIZE / 2;
return { x, y };
}
CPlayer::CPlayer( IGlobalContext* pContext ) :
m_pContext( pContext ),
m_DrawPos(),
m_MapPos()
{
auto stg = m_pContext->GetStageContext();
m_MapPos = stg->GetMapFirstPos(); // マップのどこにいるか設定
m_DrawPos = ConvPos( m_MapPos ); // スクリーン上のどこにいるか
}
CPlayer::~CPlayer()
{
}
void CPlayer::Proc()
{
Pos_t next = { 0, 0 };
static int cnt = 0;
if( !cnt && CheckHitKey( KEY_INPUT_UP ) ) { next.y--; cnt++; }
if( !cnt && CheckHitKey( KEY_INPUT_DOWN ) ) { next.y++; cnt++; }
if( !cnt && CheckHitKey( KEY_INPUT_LEFT ) ) { next.x--; cnt++; }
if( !cnt && CheckHitKey( KEY_INPUT_RIGHT ) ) { next.x++; cnt++; }
if( cnt ) {
if( ++cnt == 14 ) {
cnt = 0;
}
}
auto dir = [ & ]
{
// 左右の判定
if( next.x > 0 ) {
return eDir::eRIGHT;
} else if( next.x < 0 ) {
return eDir::eLEFT;
}
// 上下の判定
if( next.y > 0 ) {
return eDir::eDOWN;
} else if( next.y < 0 ) {
return eDir::eUP;
}
// キーの入力が無い
return eDir::eNONE;
}();
// ステージのコンテキストを取得
auto pStageContext = m_pContext->GetStageContext();
// 取得したステージのコンテキストから次の場所に行けるか問う
auto movable = pStageContext->IsAbleToGo( m_MapPos, dir );
if( !movable ) {
next.x = 0;
next.y = 0;
}
m_MapPos += next; // 位置を変える
auto abs_pos = []( Pos_t p )
{
if( p.x < 0 ) p.x = -p.x;
if( p.y < 0 ) p.y = -p.y;
return p;
};
m_DrawPos = ConvPos( m_MapPos ); // 画面上の座標を求める
}
void CPlayer::Draw()
{
DrawCircle( m_DrawPos.x, m_DrawPos.y, 2, GetColor( 128, 128, 0 ) );
}
► スポイラーを表示
#pragma once
#include "Common.h"
#include "Interface.h"
#include <memory>
class CBaseStage : public IStageContext
{
public:
static const auto MAP_ONE_BLOCK_SIZE = 32U;
static const auto MAP_DRAW_POS_X = 200U;
static const auto MAP_DRAW_POS_Y = 2U;
public:
virtual ~CBaseStage() {}
virtual void Proc() = 0;
virtual void Draw() = 0;
virtual bool IsAbleToGo( const Pos_t& nowPos, const eDir& dir ) const override = 0;
};
typedef std::shared_ptr< CBaseStage > BaseStagePtr;
► スポイラーを表示
#pragma once
#include "BaseStage.h"
#include "Common.h"
class CStage1 : public CBaseStage
{
bool m_bShowDebugInfo;
public:
CStage1();
~CStage1();
virtual void Proc() override;
virtual void Draw() override;
virtual Pos_t GetMapFirstPos() const override;
virtual bool IsAbleToGo( const Pos_t& nowPos, const eDir& dir ) const override;
};
► スポイラーを表示
#include <DxLib.h>
#include "Stage1.h"
#include "BaseStage.h"
namespace
{
// マップデータ
static const int STAGE_1_MAP_X_NUM = 5;
static const int STAGE_1_MAP_Y_NUM = 5;
// 1 : 移動できない
// 0 : 移動できる
static unsigned stage1MapData[ STAGE_1_MAP_X_NUM ][ STAGE_1_MAP_Y_NUM ] =
{
/*
0 1 2 3 4 */
{ 0, 0, 1, 1, 1 }, // 0
{ 0, 0, 0, 0, 1 }, // 1
{ 1, 0, 1, 0, 1 }, // 2
{ 1, 0, 0, 0, 1 }, // 3
{ 1, 1, 1, 1, 1 } // 4
};
}
CStage1::CStage1() :
m_bShowDebugInfo( true )
{
}
CStage1::~CStage1()
{
}
// virtual
void CStage1::Proc()
{
static int cnt = 0;
if( !cnt && CheckHitKey( KEY_INPUT_D ) ) {
m_bShowDebugInfo = !m_bShowDebugInfo;
cnt++;
}
if( cnt ) {
if( ++cnt == 30 ) cnt = 0;
}
}
// virtual
void CStage1::Draw()
{
DrawString( 0, 20, "Stage1", GetColor( 255, 255, 255 ) );
for( int i=0 ; i < STAGE_1_MAP_X_NUM ; i++ ) {
for( int j=0 ; j < STAGE_1_MAP_Y_NUM ; j++ ) {
auto x = MAP_DRAW_POS_X + CBaseStage::MAP_ONE_BLOCK_SIZE * i;
auto y = MAP_DRAW_POS_Y + CBaseStage::MAP_ONE_BLOCK_SIZE * j;
DrawBox( x, y,
x + CBaseStage::MAP_ONE_BLOCK_SIZE + 1, y + CBaseStage::MAP_ONE_BLOCK_SIZE + 1,
GetColor( 255, 255, 255 ), ( stage1MapData[ j ][ i ] == 0 ? TRUE : FALSE ) );
if( m_bShowDebugInfo ) {
DrawFormatString( x + CBaseStage::MAP_ONE_BLOCK_SIZE / 2, y + CBaseStage::MAP_ONE_BLOCK_SIZE / 4,
GetColor( 255, 0, 0 ), "%d", stage1MapData[ j ][ i ] );
}
}
}
}
// virtual
Pos_t CStage1::GetMapFirstPos() const
{
int x = 0;
int y = 0;
return { x, y };
}
//virtual
bool CStage1::IsAbleToGo( const Pos_t& nowPos, const eDir& dir ) const
{
Pos_t tmp = nowPos;
// マップの外に出ないように
auto a = ( ( -1 < tmp.y ) && ( tmp.y < STAGE_1_MAP_Y_NUM ) );
auto b = ( ( -1 < tmp.x ) && ( tmp.x < STAGE_1_MAP_X_NUM ) );
if( !a || !b ) {
return false;
}
switch( dir ) {
case eDir::eDOWN: {
tmp.x += 0;
tmp.y += 1;
break;
}
case eDir::eUP: {
tmp.x += 0;
tmp.y += -1;
break;
}
case eDir::eLEFT: {
tmp.x += -1;
tmp.y += 0;
break;
}
case eDir::eRIGHT: {
tmp.x += 1;
tmp.y += 0;
break;
}
case eDir::eNONE: {
tmp.x += 0;
tmp.y += 0;
break;
}
}
// マップ外かどうか
auto after_a = ( ( -1 < tmp.y ) && ( tmp.y < STAGE_1_MAP_Y_NUM ) );
auto after_b = ( ( -1 < tmp.x ) && ( tmp.x < STAGE_1_MAP_X_NUM ) );
if( !after_a || !after_b ) {
return false;
}
return ( stage1MapData[ tmp.y ][ tmp.x ] == 0 );
}
► スポイラーを表示
#pragma once
#include "BaseStage.h"
#include "Common.h"
class CStage2 : public CBaseStage
{
bool m_bShowDebugInfo;
public:
CStage2();
~CStage2();
virtual void Proc() override;
virtual void Draw() override;
virtual Pos_t GetMapFirstPos() const override;
virtual bool IsAbleToGo( const Pos_t& nowPos, const eDir& dir ) const override;
};
► スポイラーを表示
#include <DxLib.h>
#include "Stage2.h"
#include "Common.h"
#include "BaseStage.h"
namespace
{
// マップデータ
// たとえば、ステージ1とマップの大きさを変える
static const int STAGE_2_MAP_X_NUM = 7;
static const int STAGE_2_MAP_Y_NUM = 7;
// 1 : 行けない
// 0 : 移動できる
static const unsigned stage2MapData[ STAGE_2_MAP_X_NUM ][ STAGE_2_MAP_Y_NUM ] =
{
/*
0 1 2 3 4 5 6 */
{ 0, 0, 1, 1, 1, 1, 1 }, // 0
{ 0, 0, 1, 0, 0, 0, 1 }, // 1
{ 1, 0, 0, 0, 0, 0, 1 }, // 2
{ 1, 0, 1, 0, 1, 0, 1 }, // 3
{ 1, 0, 0, 0, 1, 0, 1 }, // 4
{ 1, 0, 1, 1, 1, 0, 1 }, // 5
{ 1, 1, 1, 1, 1, 1, 1 } // 6
};
}
CStage2::CStage2() :
m_bShowDebugInfo( true )
{
}
CStage2::~CStage2()
{
}
// virtual
void CStage2::Proc()
{
static int cnt = 0;
if( !cnt && CheckHitKey( KEY_INPUT_D ) ) {
m_bShowDebugInfo = !m_bShowDebugInfo;
cnt++;
}
if( cnt ) {
if( ++cnt == 30 ) cnt = 0;
}
}
// virtual
void CStage2::Draw()
{
DrawString( 0, 20, "Stage2", GetColor( 255, 255, 255 ) );
for( int i=0 ; i < STAGE_2_MAP_X_NUM ; i++ ) {
for( int j=0 ; j < STAGE_2_MAP_X_NUM ; j++ ) {
auto x = MAP_DRAW_POS_X + CBaseStage::MAP_ONE_BLOCK_SIZE * i;
auto y = MAP_DRAW_POS_Y + CBaseStage::MAP_ONE_BLOCK_SIZE * j;
DrawBox( x, y,
x + CBaseStage::MAP_ONE_BLOCK_SIZE + 1, y + CBaseStage::MAP_ONE_BLOCK_SIZE + 1,
GetColor( 255, 255, 255 ), ( stage2MapData[ j ][ i ] == 0 ? TRUE : FALSE ) );
if( m_bShowDebugInfo ) {
DrawFormatString( x + CBaseStage::MAP_ONE_BLOCK_SIZE / 2, y + CBaseStage::MAP_ONE_BLOCK_SIZE / 4,
GetColor( 255, 0, 0 ), "%d", stage2MapData[ j ][ i ] );
}
}
}
}
// virtual
Pos_t CStage2::GetMapFirstPos() const
{
int x = 0;
int y = 0;
return { x, y };
}
// virtual
bool CStage2::IsAbleToGo( const Pos_t& nowPos, const eDir& dir ) const
{
Pos_t tmp = nowPos;
// マップの外に出ないように
auto a = ( ( -1 < tmp.y ) && ( tmp.y < STAGE_2_MAP_Y_NUM ) );
auto b = ( ( -1 < tmp.x ) && ( tmp.x < STAGE_2_MAP_X_NUM ) );
if( !a || !b ) {
return false;
}
switch( dir ) {
case eDir::eDOWN: {
tmp.x += 0;
tmp.y += 1;
break;
}
case eDir::eUP: {
tmp.x += 0;
tmp.y += -1;
break;
}
case eDir::eLEFT: {
tmp.x += -1;
tmp.y += 0;
break;
}
case eDir::eRIGHT: {
tmp.x += 1;
tmp.y += 0;
break;
}
case eDir::eNONE: {
tmp.x += 0;
tmp.y += 0;
break;
}
}
// マップ外かどうか
auto after_a = ( ( -1 < tmp.y ) && ( tmp.y < STAGE_2_MAP_Y_NUM ) );
auto after_b = ( ( -1 < tmp.x ) && ( tmp.x < STAGE_2_MAP_X_NUM ) );
if( !after_a || !after_b ) {
return false;
}
return ( stage2MapData[ tmp.y ][ tmp.x ] == 0 );
}
► スポイラーを表示
► スポイラーを表示
#include "StageMgr.h"
#include "BaseStage.h"
#include <memory>
#include "Stage1.h"
#include "Stage2.h"
#include "Player.h"
namespace
{
BaseStagePtr CreateStage( unsigned stage )
{
switch( stage ) {
case 1:{
return std::make_shared< CStage1 >();
}
case 2:{
return std::make_shared< CStage2 >();
}
default: {
break;
}
}
return nullptr;
}
}
CStageMgr::CStageMgr() :
m_pStage( CreateStage( 1 ) ),
m_pPlayer( std::make_shared< CPlayer >( this ) )
{
}
CStageMgr::~CStageMgr()
{
}
void CStageMgr::Proc()
{
m_pStage->Proc();
m_pPlayer->Proc();
}
void CStageMgr::Draw()
{
m_pStage->Draw();
m_pPlayer->Draw();
}
// virtual
StageContextPtr CStageMgr::GetStageContext() const
{
return m_pStage;
}