/////////////////////////////////////////////////////////
// 界面声明类
// 只针对控制界面不涉及主程序
// 建立面板容器 和 按钮 等类
// 这些按钮都是在容器上所以绑定在容器上配置文件包含按钮内容
////////////////////////////////////////////////////
#pragma once
#include <vector>
#include <ddraw.h>
#include "DirectFunction.h"
/// CBUTTON 的声明
class CButton;
class DXMouse;
/*
//简易显示面
class CSimpleInterface
{
public:
bool iniInterface(LPDIRECTDRAW7 _lpdd,LPDIRECTDRAWSURFACE7 _animDest,DXMouse* _DMouse,char *_filename );//界面的初始
化
void run() ; //运行接受消息 鼠标键盘对界面控制区的访问 返回按键内容
void runGraphic(); //运行图像
protected:
std::vector<CButton*> m_vecControl; //控件集合
int m_interfaceID; //界面ID
DXMouse* m_DMouse ; //鼠标的缓存
bool isInterfaceIni; //是否被初始化
BOB * m_InterfaceBOB; // 单位格的对应图元属性
DX::CBOB* m_InterfaceCBOB; //显示对应单元的函数
};
*/
class CInterface
{
public:
CInterface():isInterfaceIni(false){ }
CInterface(LPDIRECTDRAW7 _lpdd,LPDIRECTDRAWSURFACE7 _animDest,DXMouse* _DMouse,char *_filename )
{ iniInterface(_lpdd,_animDest,_DMouse,_filename);}
~CInterface(){ release(); }
bool iniInterface(LPDIRECTDRAW7 _lpdd,LPDIRECTDRAWSURFACE7 _animDest,DXMouse* _DMouse,char *_filename );//界面的初始
化
void run() ; //运行接受消息 鼠标键盘对界面控制区的访问 返回按键内容
virtual void runGraphic(); //运行图像
bool release(); //释放资源内存
int getControlCommand()
{
return m_ControlCommand;
} //获取游戏状态命令
private:
void processControl(); //处理按钮等控件
int m_ControlCommand; //控制命令
DXMouse* m_DMouse ; //鼠标的缓存
bool isInterfaceIni; //是否被初始化
BOB * m_InterfaceBOB; // 单位格的对应图元属性
DX::CBOB* m_InterfaceCBOB; //显示对应单元的函数
int m_interfaceID; //界面ID
std::vector<CButton*> m_vecControl; //控件集合
};
/////////////////////////////////////////////////
// Content: 逻辑角色类函数 定义
/////////////////////////////////////////////////
#pragma once
#include "enum.h"
#include "exception.h"
#include "CLogicActor.h"
#include "CModel.h"
#include "CMessageManager.h"
#include "CBombManager.h"
#include "CProperty.h"
#include "CMap.h"
#include "o_time.h"
//构造函数
CLogicActor::CLogicActor(CModel* _model,CMessageManager* _MsManager,int& _id,const Pos& _pos,int& _camp)
:m_pModel(_model),m_pMsManager(_MsManager),m_ID(_id),m_Pos(_pos),
m_Camp(_camp),m_UpdateVelocity(CParam::UpdateVelocity)
{
m_pBombKind = new CBombKind( *(m_pModel->m_pBombManager->getBombKind(0) ) ); //取得炸弹类型
}
//析构函数
CLogicActor::~CLogicActor()
{
if(m_pBombKind==0)
throw Exception("~CLogicActor(),m_pBombKind==0");
delete m_pBombKind;
}
//接收消息
void CLogicActor::receiveMessage(MS::CMessage* _ms)
{
if(_ms==0)
throw Exception("CLogicActor::receiveMessage, ms==0");
m_MessageCon.push_back(_ms); //放入消息容器
}
//更改炸弹类型
void CLogicActor::setBombKind(int kind)
{
m_pBombKind = m_pModel->m_pBombManager->getBombKind(kind);
}
//处理吃物品
void CLogicActor::dealProperty(const CProperty* pProperty)
{
switch(pProperty->m_Type)
{
case ENUM::IncreaseBombNum: //增加炸弹数量
{
const CIncreaseBombNum* p = dynamic_cast<const CIncreaseBombNum*>(pProperty);
}
break;
case ENUM::IncreaseBombPower: //增加炸弹威力
{
const CIncreaseBombPower* p = dynamic_cast<const CIncreaseBombPower*>(pProperty);
if( m_pBombKind->m_Power < m_pModel->m_pMap->rowNum() )
m_pBombKind->m_Power += p->m_Power;
}
break;
case ENUM::ChangeBlastTime: //改变炸弹爆炸时间
{
const CChangeBlastTime* p = dynamic_cast<const CChangeBlastTime*>(pProperty);
m_pBombKind->m_BlastTime = p->m_BlastTime;
}
break;
default:
break;
}
}
//上移
void CLogicActor::moveUp()
{
m_pMsManager->registerMessage(ENUM::MapMessage,
new MS::CMessage_Move(m_ID,ENUM::UP,m_Pos,Pos(m_Pos.x,m_Pos.y-1)) );
}
//下移
void CLogicActor::moveDown()
{
m_pMsManager->registerMessage(ENUM::MapMessage,
new MS::CMessage_Move(m_ID,ENUM::DOWN,m_Pos,Pos(m_Pos.x,m_Pos.y+1)) );
}
//左移
void CLogicActor::moveLeft()
{
m_pMsManager->registerMessage(ENUM::MapMessage,
new MS::CMessage_Move(m_ID,ENUM::LEFT,m_Pos,Pos(m_Pos.x-1,m_Pos.y)) );
}
//右移
void CLogicActor::moveRight()
{
m_pMsManager->registerMessage(ENUM::MapMessage,
new MS::CMessage_Move(m_ID,ENUM::RIGHT,m_Pos,Pos(m_Pos.x+1,m_Pos.y)) );
}
//放炸弹
void CLogicActor::setBomb()
{
m_pMsManager->registerMessage(ENUM::MapMessage,
new MS::CMessage_SetBomb(m_ID,m_Pos,m_pBombKind) );
}
/////////////////////////////////////////////////
// Content: 逻辑角色类 定义
/////////////////////////////////////////////////
#pragma once
#include <vector>
#include "CMessage.h"
#include "utils.h"
class CModel;
class CMessageManager;
class CProperty;
//逻辑角色类
class CLogicActor
{
public:
CLogicActor(CModel* _model,CMessageManager* _MsManager,int& _id,const Pos& _pos,int& _camp);
~CLogicActor();
int getID() {return m_ID;} //取得ID
Pos getPos() {return m_Pos;} //取得Pos
void receiveMessage(MS::CMessage* _ms); //接收消息
virtual void run() = 0; //执行函数
virtual void initial()=0; //初始化函数
void setBombKind(int kind); //更改炸弹类型
CBombKind* getBombKind() { return m_pBombKind; } //取得炸弹类型
int getUpdateVelocity()const {return m_UpdateVelocity;} //取得更新速度
std::vector<MS::CMessage*>& getMsgCon(){return m_MessageCon;}//取得消息容器
void dealProperty(const CProperty* pProperty); //处理吃物品
void moveUp(); //上移
void moveDown(); //下移
void moveLeft(); //左移
void moveRight(); //右移
void setBomb(); //放炸弹
protected:
int& m_ID; //Actor ID
const Pos& m_Pos; //坐标(Actor坐标引用)
int& m_Camp; //所属阵营
int m_UpdateVelocity; //更新速度(单位:祯)
int m_BombNum; //现有炸弹数
CModel* m_pModel; //模型
CBombKind* m_pBombKind; //炸弹类型
std::vector<MS::CMessage*> m_MessageCon; //消息容器
CMessageManager* m_pMsManager; //消息管理器
};
/////////////////////////////////////////////////
// Content: 地图类 函数定义
/////////////////////////////////////////////////
#pragma once
#include "CParam.h"
#include "CMap.h"
#include "exception.h"
#include "windowsUtils.h"
//构造函数
CMap::CMap():m_Width(0),m_Height(0)
{
loadMap(); //载入地图
}
//析构函数
CMap::~CMap()
{
if(m_Map==0)
throw Exception("~CMap(),指针为空");
for(int i=0;i<m_Height;i++)
delete[] m_Map[i]; //释放空间
delete[] m_Map;
}
//初始化
void CMap::init(CModel* _model,CMessageManager* _MsManager)
{
m_pMsManager = _MsManager;
m_pModel = _model;
}
//载入地图
void CMap::loadMap()
{
//打开地图文件
char temp[50];
std::ifstream mapfile(CParam::loadMapName.c_str());
if(!mapfile)
throw Exception("CMap::loadMap(), 无法打开地图文件");
mapfile>>m_Width>>m_Height; //读入地图宽,高
mapfile>>temp>> m_BOBDisplayHeight; //读入位图精灵显示的高
mapfile>>temp>>m_BOBDisplayWidth; //读入位图精灵显示的宽
if( m_Width*m_BOBDisplayWidth > SCREEN_WIDTH )
{
m_BOBDisplayWidth = SCREEN_WIDTH/ m_Width;
MessageBox(NULL,"位图显示的宽大于显示面积","发生异常!",MB_OK);
}
if( m_Height*m_BOBDisplayHeight > SCREEN_HEIGHT )
{
m_BOBDisplayHeight = SCREEN_HEIGHT / m_Height ;
MessageBox(NULL,"位图显示的高大于显示面积","发生异常!",MB_OK);
}
//建立2维数组
m_Map = new int*[m_Height];
for(int i=0;i<m_Height;i++)
{
m_Map[i] = new int[m_Height];
}
//读入原始地图信息
char tmp[30];
for(int i=0;i<m_Height;i++)
{
mapfile>>tmp;
for(int j=0;j <m_Width;j++)
{
m_Map[i][j] = 0; //地图归0
switch(tmp[j])
{
case '0':
addElem(Pos(j,i),ENUM::Block); //永久障碍物
break;
case '1':
addElem(Pos(j,i),ENUM::Space); //空地
addElem(Pos(j,i),ENUM::Access);
break;
case '2':
addElem(Pos(j,i),ENUM::Brick); //砖块
break;
}
}
}
//打开角色文件
std::ifstream actorfile(CParam::ActorFileName.c_str());
if(!actorfile)
{ throw Exception("CMap::loadMap(), 无法打开角色文件"); }
char BOBBMPFile[50]; //BMP文件名
int actorNum; //角色数
int x,y; //坐标
//添加角色到地图
actorfile>>actorNum;
for(int i=0;i<actorNum;i++)
{
actorfile>>tmp>>x>>y;
actorfile>>BOBBMPFile;
addElem( Pos(x,y),ENUM::Actor );
delElem( Pos(x,y),ENUM::Access );
}
}
//判断该处是否有指定地图元素
bool CMap::judgeElem(int _x,int _y , ENUM::ElemType _elem) const
{
return ( m_Map[_y & _elem ][_x & _elem] == _elem );
}
//判断该处是否有指定地图元素
bool CMap::judgeElem(const Pos& _pos, ENUM::ElemType _elem)const
{
return ( (m_Map[_pos.y][_pos.x] & _elem)== _elem );
}
//返回指定处地图元素
int CMap::getElem(const Pos& _pos)const
{
return m_Map[_pos.y][_pos.x];
}
//返回指定处地图元素
int CMap::getElem(int _x,int _y)const
{
return m_Map[_y][_x];
}
//添加指定地图元素
void CMap::addElem(const Pos& _pos, const ENUM::ElemType _elem)
{
m_Map[_pos.y][_pos.x] |= _elem;
}
//删除指定地图元素
void CMap::delElem(const Pos& _pos, const ENUM::ElemType _elem)
{
m_Map[_pos.y][_pos.x] ^= _elem;
}
//检测坐标是否合法
bool CMap::checkPos(const Pos& _pos)const
{
if(_pos.x < 0 || _pos.x >= m_Width || _pos.y < 0 || _pos.y >= m_Height)
return false;
return true;
}
//检测坐标是否合法
bool CMap::checkPos(int _x,int _y )const
{
if(_x< 0 || _x >= m_Width || _y < 0 || _y >= m_Height)
return false;
return true;
}
//处理消息
void CMap::dealMessage()
{
std::vector<MS::CMessage*>& msCon = m_pMsManager->getMessageCon(ENUM::MapMessage);
std::vector<MS::CMessage*>::iterator iter = msCon.begin();
for(;iter != msCon.end();++iter)
{
//根据消息类型分派给处理函数
switch( (*iter)->m_MsType)
{
case ENUM::Move:
dealMove(*iter);
break;
case ENUM::SetBomb:
dealSetBomb(*iter);
break;
case ENUM::Die:
dealDie(*iter);
break;
default:
break;
}
}
msCon.clear(); //清空消息容器
}
//处理移动消息
void CMap::dealMove(MS::CMessage* _ms)
{
MS::CMessage_Move* ms = dynamic_cast<MS::CMessage_Move*>(_ms);
//检查是否为被困人员
if( judgeElem(ms->m_To,ENUM::BesiegeActor)==true)
{
//发送处理被困消息
m_pMsManager->registerMessage(ENUM::ActorMessage,new MS::CMessage_DealBesiege(ms->m_From,ms->m_To) );
delete ms;
return;
}
//检查是否可以移动
if( judgeElem(ms->m_To,ENUM::Access)==true )
{
//修改地图
addElem(ms->m_To,ENUM::Actor);
delElem(ms->m_To,ENUM::Access);
delElem(ms->m_From,ENUM::Actor);
if( judgeElem(ms->m_From, ENUM::Bomb) == false ) //出发处无炸弹就修改地图为通路
addElem(ms->m_From,ENUM::Access);
m_pMsManager->registerMessage(ENUM::ActorMessage,_ms); //通知Actor模块处理
//如果处于爆炸区
if(judgeElem(ms->m_To,ENUM::BlastArea)==true)
{
//通知被炸消息
m_pMsManager->registerMessage( ENUM::ActorMessage,new MS::CMessage_BeBomb(ms->m_To) );
}
return;
}
//不能移动则不改变坐标
MS::CMessage_Move* message = new MS::CMessage_Move(ms->m_ActorID,ms->m_ActionType,ms->m_From,ms->m_From);
m_pMsManager->registerMessage(ENUM::ActorMessage,message);
delete ms;
}
//处理放置炸弹消息
void CMap::dealSetBomb(MS::CMessage* _ms)
{
MS::CMessage_SetBomb* ms = dynamic_cast<MS::CMessage_SetBomb*>(_ms);
if( judgeElem(ms->m_Pos,ENUM::Bomb)==false)
{
addElem(ms->m_Pos,ENUM::Bomb); //修改地图
//通知炸弹管理器处理
m_pMsManager->registerMessage(ENUM::BombMessage,ms);
//发给角色处理
MS::CMessage_SetBomb* message = new MS::CMessage_SetBomb();
*message = *ms;
m_pMsManager->registerMessage(ENUM::ActorMessage,message);
return;
}
delete ms; //删除已处理消息
}
//处理死亡消息
void CMap::dealDie(MS::CMessage* _ms)
{
MS::CMessage_Die* ms = dynamic_cast<MS::CMessage_Die*>(_ms);
delElem(ms->m_Pos,ENUM::Actor); //修改地图
addElem(ms->m_Pos,ENUM::Access);
delete ms; //删除已处理消息
}
/////////////////////////////////////////////////
// Content: 地图类 定义
/////////////////////////////////////////////////
#pragma once
#include <vector>
#include <fstream>
#include <windows.h>
#include <windowsx.h>
#include "utils.h"
#include "enum.h"
#include "CMessageManager.h"
class CModel;
class CMessageManager;
//地图类
class CMap
{
public:
CMap();
~CMap(); //析构函数
void init(CModel* _model,CMessageManager* _MsManager); //初始化
void dealMessage(); //处理消息
void loadMap(); //载入地图
void saveMap(); //保存地图
int getBOBDisplayWidth() { return m_BOBDisplayWidth; }
int getBOBDisplayHeight() { return m_BOBDisplayHeight; }
int rowNum() const {return m_Height;} //返回地图宽有多少行
int lineNum()const {return m_Width;} //返回地图高有多少列
//判断该处是否有指定地图元素
bool judgeElem(const Pos& _pos, const ENUM::ElemType _elem)const;
bool judgeElem(int _x,int _y ,const ENUM::ElemType _elem)const;
int getElem(const Pos& _pos)const; //返回指定处地图元素
int getElem(int _x,int _y)const; //返回指定处地图元素
void addElem(const Pos& _pos, const ENUM::ElemType _elem); //添加指定地图元素
void delElem(const Pos& _pos, const ENUM::ElemType _elem); //删除指定地图元素
//检查坐标是否合法
bool checkPos(const Pos& _pos)const;
bool checkPos(int _x,int _y )const;
private:
int** m_Map; //地图信息
int m_Width; //地图宽度
int m_Height; //地图高度
int m_BOBDisplayWidth; //位图精灵显示的高
int m_BOBDisplayHeight; //位图精灵显示的宽
CModel* m_pModel; //模型
CMessageManager* m_pMsManager; //消息管理器
std::vector<MS::CMessage*> m_MessageCon; //消息容器
void dealMove(MS::CMessage* _ms); //处理移动消息
void dealSetBomb(MS::CMessage* _ms); //处理放置炸弹消息
void dealDie(MS::CMessage* _ms); //处理死亡消息
};
/////////////////////////////////////////////////
// Content: 消息类定义
/////////////////////////////////////////////////
#pragma once
#include <vector>
#include "enum.h"
#include "utils.h"
class CBombKind;
class CProperty;
class CActor;
namespace MS
{
//消息虚基类
class CMessage
{
public:
CMessage(ENUM::MessageType _MsType):m_MsType(_MsType) {}
virtual ~CMessage() {}
ENUM::MessageType m_MsType; //消息类型
};
//移动
class CMessage_Move:public CMessage
{
public:
CMessage_Move():CMessage(ENUM::Move) {}
CMessage_Move(int _id,ENUM::ActionType _move,const Pos& _from, const Pos& _to)
:CMessage(ENUM::Move),m_ActorID(_id),m_ActionType(_move),m_From(_from),m_To(_to){}
int m_ActorID; //角色ID
ENUM::ActionType m_ActionType; //移动类型
Pos m_From; //原坐标
Pos m_To; //目的地坐标
};
//放置炸弹
class CMessage_SetBomb:public CMessage
{
public:
CMessage_SetBomb():CMessage(ENUM::SetBomb) {}
CMessage_SetBomb(int _id,const Pos& _pos,const CBombKind* _kind)
:CMessage(ENUM::SetBomb),m_ActorID(_id),m_Pos(_pos),m_pBombKind(_kind) {}
int m_ActorID; //角色ID
Pos m_Pos; //炸弹坐标
const CBombKind* m_pBombKind; //炸弹类型
};
//被炸
class CMessage_BeBomb:public CMessage
{
public:
CMessage_BeBomb():CMessage(ENUM::BeBomb) {}
CMessage_BeBomb(const Pos& _pos)
:CMessage(ENUM::BeBomb),m_Pos(_pos){}
Pos m_Pos; //被炸者坐标
};
//死亡
class CMessage_Die:public CMessage
{
public:
CMessage_Die():CMessage(ENUM::BeBomb) {}
CMessage_Die(int _id,const Pos& _pos)
:CMessage(ENUM::Die),m_ID(_id),m_Pos(_pos){}
int m_ID; //死亡者ID
Pos m_Pos; //死亡者坐标
};
//出现道具
class CMessage_AppearProperty:public CMessage
{
public:
CMessage_AppearProperty(CProperty* pProperty)
:CMessage(ENUM::AppearProperty),m_pProperty(pProperty) {}
CProperty* m_pProperty; //道具
};
//某人被困
class CMessage_Besiege:public CMessage
{
public:
CMessage_Besiege(CActor* actor)
:CMessage(ENUM::msBesiege),m_pActor(actor) {}
CActor* m_pActor; //被困人员
};
//处理被困
class CMessage_DealBesiege:public CMessage
{
public:
CMessage_DealBesiege(const Pos& dealPos,const Pos& besiegePos)
:CMessage(ENUM::DealBesiege),m_DealActorPos(dealPos),m_BesiegeActorPos(besiegePos) {}
Pos m_DealActorPos; //处理人员坐标
Pos m_BesiegeActorPos; //被困人员坐标
};
}
/////////////////////////////////////////////////
// Content: 消息管理类 函数定义
/////////////////////////////////////////////////
#include "o_assert.h"
#include "exception.h"
#include "CMessageManager.h"
//构造函数
CMessageManager::CMessageManager()
{
}
//析构函数
CMessageManager::~CMessageManager()
{
//释放内存
std::vector<MsConType>::iterator iter1 = m_AllMessageCon.begin();
for(;iter1 != m_AllMessageCon.end();++iter1 )
{
MsConType::iterator iter2 = iter1->begin();
for(;iter2 != iter1->end();++iter2)
{
delete *iter2;
}
}
}
//创建消息容器
void CMessageManager::createMessageCon(int _num)
{
if(_num < 0)
throw Exception("createMessageCon(_num <= 0) ") ;
m_AllMessageCon.resize(_num);
}
//注册消息
void CMessageManager::registerMessage(ENUM::ModelType _id,MS::CMessage* _ms)
{
m_AllMessageCon[_id].push_back(_ms);
}
//取得消息容器
CMessageManager::MsConType& CMessageManager::getMessageCon(ENUM::ModelType _id)
{
return m_AllMessageCon[_id];
}
//清空消息容器
void CMessageManager::clearMessageCon(ENUM::ModelType _id)
{
m_AllMessageCon[_id].clear();
}
///////////////////////////////////////////////
//Content: 消息管理类定义
///////////////////////////////////////////////
#pragma once
#include <vector>
#include "CMessage.h"
//消息管理类
class CMessageManager
{
public:
CMessageManager();
~CMessageManager();
typedef std::vector<MS::CMessage*> MsConType; //重命名消息容器类型
void createMessageCon(int _num); //创建消息容器
void registerMessage(ENUM::ModelType _id,MS::CMessage* _ms); //注册消息
MsConType& getMessageCon(ENUM::ModelType _id); //取得消息容器
void clearMessageCon(ENUM::ModelType _id); //清空消息容器
private:
std::vector<MsConType> m_AllMessageCon; //所有消息容器
};
//提示:管理类并不真正删除消息,由相关模块处理完后释放/////////////////////////////////////////
//Content: 模型类 函数定义
/////////////////////////////////////////
#include "exception.h"
#include "CModel.h"
#include "CActorManager.h"
#include "CBombManager.h"
#include "CPropertyManager.h"
#include "CMap.h"
#include "CMessageManager.h"
#include "CControl.h"
#include "CVirtualMap.h"
//构造函数
CModel::CModel(LPDIRECTDRAW7& _lpdd,LPDIRECTDRAWSURFACE7& _animDest)
{
m_pMap = new CMap();
m_pActorManager = new CActorManager(_lpdd , _animDest);
m_pBombManager = new CBombManager(_lpdd , _animDest);
m_pPropertyManager = new CPropertyManager(this,_lpdd,_animDest);
m_pControl = new CControl();
m_pVirtualMap = new CVirtualMap(this);
}
//析构函数
CModel::~CModel()
{
if( !m_pActorManager || !m_pBombManager || !m_pPropertyManager || !m_pMap )
throw Exception("~CModel(), 指针为空");
delete m_pActorManager;
delete m_pBombManager;
delete m_pPropertyManager;
delete m_pMap;
delete m_pVirtualMap;
}
//初始化
void CModel::init(CMessageManager* _pMsManager)
{
m_pMap->init(this,_pMsManager);
m_pActorManager->init(this,_pMsManager);
m_pBombManager->init(this,_pMsManager);
m_pPropertyManager->init(this);
refreshVtMap();
}
//更新VtMap
void CModel::refreshVtMap(void)
{
delete m_pVirtualMap;
m_pVirtualMap = new CVirtualMap(this);
}
/////////////////////////////////////////
//Content: 模型类 定义
/////////////////////////////////////////
#pragma once
#include <ddraw.h>
class CActorManager;
class CBombManager;
class CPropertyManager;
class CMap;
class CMessageManager;
class CControl;
class CVirtualMap;
//模型类
class CModel
{
public:
CModel(LPDIRECTDRAW7& _lpdd,LPDIRECTDRAWSURFACE7& _animDest);
~CModel();
void init(CMessageManager* _pMsManager); //初始化
void refreshVtMap(void); //更新VtMap
CActorManager* m_pActorManager; //角色管理器
CBombManager* m_pBombManager; //炸弹管理器
CPropertyManager* m_pPropertyManager;//道具管理器
CMap* m_pMap; //地图
CVirtualMap* m_pVirtualMap; //虚拟地图
CControl* m_pControl; //控制类
};
/////////////////////////////////////////////////
// Content: 参数类 函数及静态成员定义
/////////////////////////////////////////////////
#include <fstream>
#include "CParam.h"
#include "exception.h"
//静态成员定义
bool CParam::isFullSrceen;
std::string CParam::DXMouseResouce;
std::string CParam::BackgroudResouce;
std::string CParam::InterfaceResouce;
std::string CParam::DXSoundResouce;
std::string CParam::loadMapName;
std::string CParam::ActorFileName;
std::string CParam::BombFileName;
std::string CParam::PropertyFileName;
int CParam::iAccessCost;
int CParam::iBrickCost;
int CParam::iBlastTime;
int CParam::iMaxClosed;
int CParam::iInfinite;
int CParam::iCautionDist;
int CParam::iAttackPriority;
int CParam::iEscapePriority;
int CParam::iFeachPriority;
int CParam::iGoToBesiege;
int CParam::iToBlastArea;
int CParam::CycleTime;
int CParam::DeltaActionTime;
int CParam::UpdateVelocity;
//构造函数
CParam::CParam()
{
//从配置文件中读入参数
std::ifstream file("File\\Param.ini");
if(!file)
throw Exception("CParam(), 无法打开配置文件");
char tmp[50];
file>>tmp>>isFullSrceen;
file>>tmp>>BackgroudResouce;
file>>tmp>>InterfaceResouce;
file>>tmp>>DXMouseResouce;
file>>tmp>>DXSoundResouce;
file>>tmp>>loadMapName;
file>>tmp>>ActorFileName;
file>>tmp>>BombFileName;
file>>tmp>>PropertyFileName;
file>>tmp>>iAccessCost;
file>>tmp>>iBrickCost;
file>>tmp>>iBlastTime;
file>>tmp>>iMaxClosed;
file>>tmp>>iInfinite;
file>>tmp>>iCautionDist;
file>>tmp>>iAttackPriority;
file>>tmp>>iEscapePriority;
file>>tmp>>iFeachPriority;
file>>tmp>>iGoToBesiege;
file>>tmp>>iToBlastArea;
file>>tmp>>CycleTime;
file>>tmp>>DeltaActionTime;
file>>tmp>>UpdateVelocity;
}
/////////////////////////////////////////////////
// Content: 参数类 定义
/////////////////////////////////////////////////
#pragma once
#include <string>
//参数类,用于载入配置信息
class CParam
{
public:
CParam(); //构造函数
static bool isFullSrceen; //是否为全屏
static std::string BackgroudResouce; //背景资源描述文件
static std::string InterfaceResouce; //界面资源描述文件
static std::string DXMouseResouce; //鼠标资源描述文件
static std::string DXSoundResouce; //声音资源描述文件
static std::string loadMapName; //地图文件名
static std::string ActorFileName; //Actor文件名
static std::string BombFileName; //Bomb文件名
static std::string PropertyFileName; //道具文件名
static int iAccessCost; //通路的代价
static int iBrickCost; //通过砖块的代价
static int iBlastTime; //爆炸持续的时间
static int iMaxClosed; //Astar的close表的上限
static int iInfinite; //极大数
static int iCautionDist; //警戒距离
static int iAttackPriority; //攻击任务的优先级上线
static int iEscapePriority; //逃跑任务的优先级上线
static int iFeachPriority; //捡消息的优先级
static int iGoToBesiege; //到被困Actor的优先级
static int iToBlastArea; //进入爆炸区域的最低安全值
static int CycleTime; //周期执行时间(ms)
static int DeltaActionTime; //动作间隔时间
static int UpdateVelocity; //Actor初始更新时间
};
/////////////////////////////////////////////////
// Content: 玩家控制角色类 函数定义
/////////////////////////////////////////////////
#include "CPlayerActor.h"
#include "CModel.h"
#include "CMessageManager.h"
#include "CControl.h"
#include "CActorManager.h"
#include "CActor.h"
//构造函数
CPlayerActor::CPlayerActor(CModel* _model, CMessageManager* _MsManager,int& _id,const Pos& _pos,int& _camp)
:CLogicActor(_model,_MsManager,_id,_pos,_camp)
{
int i = _id;
}
//析构函数
CPlayerActor::~CPlayerActor()
{
}
//执行函数
void CPlayerActor::run()
{
//如果自身处于被困状态则不执行 以后的
if ( m_pModel->m_pActorManager->getActor(m_Pos)->m_State== ENUM::Besiege)
return;
dealAction();
}
void CPlayerActor::initial()
{}
//处理动作消息
void CPlayerActor::dealAction()
{
if(m_pModel->m_pControl->getIsSetBomb()==true)
setBomb(); //放炸弹
ENUM::ActionType action = m_pModel->m_pControl->getAction();
switch(action)
{
case ENUM::UP: //上移
moveUp();
break;
case ENUM::DOWN: //下移
moveDown();
break;
case ENUM::LEFT: //左移
moveLeft();
break;
case ENUM::RIGHT: //右移
moveRight();
break;
default:
break;
}
m_pModel->m_pControl->resetAction(); //复原
}
/////////////////////////////////////////////////
// Content: 玩家控制角色类 定义
/////////////////////////////////////////////////
#pragma once
#include "CLogicActor.h"
class CModel;
class CMessageManager;
//玩家控制角色
class CPlayerActor:public CLogicActor
{
public:
CPlayerActor(CModel* _model, CMessageManager* _MsManager,int& _id,const Pos& _pos,int& _camp);
~CPlayerActor();
void run(); //执行函数
void initial();
private:
void dealAction(); //处理动作消息
};/////////////////////////////////////////////////
// Content: 道具类 函数定义
/////////////////////////////////////////////////
#pragma once
#include "CModel.h"
#include "CMap.h"
#include "CProperty.h"
#include "CGraphicProperty.h"
#include "exception.h"
//构造函数
CProperty::CProperty(ENUM::PropertyType type,const Pos& pos,CModel* _model,
LPDIRECTDRAW7 _lpdd,LPDIRECTDRAWSURFACE7 _animDest,int _style,char* filename)
:m_Type(type),m_Pos(pos)
{
m_graphicProperty = new CGraphicProperty( m_Pos ); //对图像BOB进行初始化
m_graphicProperty->BOBSurInition(_lpdd,_animDest,0,filename,
_model->m_pMap->getBOBDisplayWidth(),_model->m_pMap->getBOBDisplayHeight());
strcpy(m_Filename,filename);
}
//析构函数
CProperty::~CProperty()
{
if(m_graphicProperty == 0 )
throw Exception("~CProperty(), m_graphicProperty ==0");
delete m_graphicProperty;
}
//执行图像
void CProperty::runGraphic()
{
m_graphicProperty->run();
}
/////////////////////////////////////////////////
// Content: 道具类 定义
/////////////////////////////////////////////////
#pragma once
#include "utils.h"
#include "enum.h"
class CGraphicProperty;
class CModel;
//道具虚基类
class CProperty
{
public:
CProperty(ENUM::PropertyType type,const Pos& pos,CModel* _model,LPDIRECTDRAW7 _lpdd,
LPDIRECTDRAWSURFACE7 _animDest,int _style,char* filename);
virtual ~CProperty();
void runGraphic(); //执行图像
ENUM::PropertyType m_Type; //类型
Pos m_Pos; //坐标
char m_Filename[50]; //图像文件名
CGraphicProperty* m_graphicProperty; //道具绘制类
};
//增加炸弹数量
class CIncreaseBombNum:public CProperty
{
public:
CIncreaseBombNum(const Pos& pos,int num,CModel* _model,LPDIRECTDRAW7 _lpdd,
LPDIRECTDRAWSURFACE7 _animDest,int _style,char *filename)
:CProperty(ENUM::IncreaseBombNum,pos,_model,_lpdd,_animDest,_style,filename),m_Num(num) {}
CIncreaseBombNum();
int m_Num; //增加炸弹数
};
//增加炸弹威力
class CIncreaseBombPower:public CProperty
{
public:
CIncreaseBombPower(const Pos& pos,int power,CModel* _model,LPDIRECTDRAW7 _lpdd,
LPDIRECTDRAWSURFACE7 _animDest,int _style,char *filename)
:CProperty(ENUM::IncreaseBombPower,pos,_model,_lpdd,_animDest,_style,filename),m_Power(power) {}
int m_Power; //增加威力
};
//改变炸弹爆炸时间
class CChangeBlastTime:public CProperty
{
public:
CChangeBlastTime(const Pos& pos,int blastTime,CModel* _model,LPDIRECTDRAW7 _lpdd,
LPDIRECTDRAWSURFACE7 _animDest,int _style,char* filename)
:CProperty(ENUM::ChangeBlastTime,pos,_model,_lpdd,_animDest,_style,filename),m_BlastTime(blastTime) {}
int m_BlastTime; //爆炸时间
};
/////////////////////////////////////////////////
// Content: 道具管理器类 函数定义
/////////////////////////////////////////////////
#include <fstream>
#include <ddraw.h>
#include <time.h>
#include "CParam.h"
#include "exception.h"
#include "CProperty.h"
#include "CPropertyManager.h"
#include "CModel.h"
#include "CMap.h"
//构造函数
CPropertyManager::CPropertyManager(CModel* _pModel,LPDIRECTDRAW7& _lpdd,LPDIRECTDRAWSURFACE7& _animDest)
:m_pModel(_pModel),m_animDest( _animDest),m_lpdd( _lpdd)
{
//读道具文件
std::ifstream file(CParam::PropertyFileName.c_str());
if(!file)
throw Exception("CPropertyManager(),道具文件无法打开");
int num;
int type;
float probability;
char BOBfileName[50];
Pos pos(0,0);
file>>num;
for(int i=0;i< num;i++)
{
file>>type>>BOBfileName>>probability;
m_ProbabilityCon.push_back(probability);
switch(type)
{
case 0: //增加炸弹数量
{
int bombNum;
file>>bombNum;
m_PropertyTypeCon.push_back( new CIncreaseBombNum
(pos,bombNum,m_pModel,_lpdd,_animDest,0,BOBfileName));
}
break;
case 1: //增加炸弹威力
{
int power;
file>>power;
m_PropertyTypeCon.push_back( new CIncreaseBombPower
(pos,power,m_pModel,_lpdd,_animDest,0,BOBfileName));
}
break;
case 2: //改变炸弹爆炸时间
{
int blastTime;
file>>blastTime;
m_PropertyTypeCon.push_back( new CChangeBlastTime
(pos,blastTime,m_pModel,_lpdd,_animDest,0,BOBfileName));
}
break;
default:
break;
}
}
}
//析构函数
CPropertyManager::~CPropertyManager()
{
//析构道具类型容器
PropertyConType::iterator iter = m_PropertyTypeCon.begin();
for(;iter!=m_PropertyTypeCon.end();++iter)
{
delete *iter;
}
//析构道具容器
iter = m_PropertyCon.begin();
for(;iter!=m_PropertyCon.end();++iter)
{
delete *iter;
}
}
//初始化
void CPropertyManager::init(CModel* _model)
{
//修改地图
PropertyConType::iterator iter = m_PropertyCon.begin();
for(;iter!=m_PropertyCon.end();++iter)
{
m_pModel->m_pMap->addElem((*iter)->m_Pos,ENUM::Property);
}
srand( (unsigned)time( NULL ) );
}
//图像执行
void CPropertyManager::RunGraphic()
{
PropertyConType::iterator iter = m_PropertyCon.begin();
for(;iter!=m_PropertyCon.end();++iter)
{
(*iter)->runGraphic();
}
}
//取得道具
const CProperty* CPropertyManager::GetProperty(const Pos& pos)const
{
PropertyConType::const_iterator iter = m_PropertyCon.begin();
for(;iter!=m_PropertyCon.end();++iter)
{
if((*iter)->m_Pos==pos)
{
return *iter;
}
}
throw Exception("CPropertyManager::GetProperty(),无此道具");
}
//添加道具
CProperty* CPropertyManager::AddProperty(const Pos& pos)
{
float rate = float(rand()%100) /100;
float total = 0;
size_t idx = 0;
PropertyConType::iterator iter = m_PropertyTypeCon.begin();
//根据概率决定出现什么道具
for(;iter!=m_PropertyTypeCon.end();++iter)
{
total += m_ProbabilityCon[idx];
if(rate <= total)
{
switch( (*iter)->m_Type)
{
case ENUM::IncreaseBombNum:
{
CIncreaseBombNum* pType = dynamic_cast<CIncreaseBombNum*>(*iter);
CIncreaseBombNum* p = new CIncreaseBombNum(pos,pType->m_Num,m_pModel,
m_lpdd,m_animDest,0,pType->m_Filename);
m_PropertyCon.push_back(p);
m_pModel->m_pMap->addElem(pos,ENUM::Property); //修改地图
return p;
}
break;
case ENUM::IncreaseBombPower:
{
CIncreaseBombPower* pType = dynamic_cast<CIncreaseBombPower*>(*iter);
CIncreaseBombPower* p = new CIncreaseBombPower(pos,pType->m_Power,m_pModel,
m_lpdd,m_animDest,0,pType->m_Filename);
m_PropertyCon.push_back(p);
m_pModel->m_pMap->addElem(pos,ENUM::Property); //修改地图
return p;
}
break;
case ENUM::ChangeBlastTime:
{
CChangeBlastTime* pType = dynamic_cast<CChangeBlastTime*>(*iter);
CChangeBlastTime* p = new CChangeBlastTime(pos,pType->m_BlastTime,m_pModel,
m_lpdd,m_animDest,0,pType->m_Filename);
m_PropertyCon.push_back(p);
m_pModel->m_pMap->addElem(pos,ENUM::Property); //修改地图
return p;
}
break;
default:
break;
}
}
idx++;
}
return 0; //不出现物品
}
//删除道具
void CPropertyManager::DelProperty(const Pos& pos)
{
PropertyConType::iterator iter = m_PropertyCon.begin();
for(;iter!=m_PropertyCon.end();++iter)
{
if((*iter)->m_Pos==pos)
{
m_pModel->m_pMap->delElem(pos,ENUM::Property); //修改地图
delete *iter;
m_PropertyCon.erase(iter);
return;
}
}
throw Exception("CPropertyManager::DelProperty(),无此道具");
}
/////////////////////////////////////////////////
// Content: 道具管理器类 定义
/////////////////////////////////////////////////
#pragma once
#include <vector>
class CProperty;
class CModel;
//道具管理器类
class CPropertyManager
{
public:
typedef std::vector<CProperty*> PropertyConType;
CPropertyManager(CModel* _pModel,LPDIRECTDRAW7& _lpdd,LPDIRECTDRAWSURFACE7& _animDest);
~CPropertyManager();
void init(CModel* _model); //初始化
void RunGraphic(); //图像执行
const CProperty* GetProperty(const Pos& pos)const; //取得道具
CProperty* AddProperty(const Pos& pos); //添加道具
void DelProperty(const Pos& pos); //删除道具
private:
std::vector<float> m_ProbabilityCon; //道具出现概率
PropertyConType m_PropertyTypeCon; //道具类型容器
PropertyConType m_PropertyCon; //道具容器
CModel* m_pModel; //模型
LPDIRECTDRAW7 m_lpdd; //建立初始化一次的备份
LPDIRECTDRAWSURFACE7 m_animDest; //建立初始化一次的备份
char m_BOBfileName[50]; //建立初始化一次的备份
};
/////////////////////////////////////////////////
// Content: 响应曲线
/////////////////////////////////////////////////
#pragma once
#include ".\CResponseLine.h"
CResponseLine::CResponseLine (std::vector<int>& vSamples)
{
Init(vSamples);
}
void CResponseLine::Init (std::vector<int>& vSamples)
{
m_iUperBound = vSamples.size();
m_vSamples = vSamples;
}
int CResponseLine::GetValue(size_t iInput)
{
if (iInput > m_iUperBound)
{
return m_vSamples[m_iUperBound];
}
else
{
return m_vSamples[iInput];
}
}
/////////////////////////////////////////////////
// Content: 响应曲线类定义
/////////////////////////////////////////////////
#pragma once
#include <vector>
class CResponseLine
{
public:
CResponseLine (std::vector<int>& vSamples); //构造函数,参数为采样点向量,后面int表示量化值
~CResponseLine(void){}
void Init(std::vector<int>& vSamples); //响应曲线的初始化
int GetValue(size_t iInput); //取得响应值
private:
size_t m_iUperBound; //上界,下界为0
std::vector<int> m_vSamples; //采样点
};
#include ".\CTask.h"
#include "CAIActor.h"
#include "CModel.h"
#include "CMap.h"
#include "CActorManager.h"
#include "CActor.h"
#include "CParam.h"
#include "CBomb.h"
//测试用
//*****************************************
#ifndef NDEBUG
#include <fstream>
#endif
//*****************************************
CTask::CTask(const int iPriority, CAIActor* actor, CModel* pModel):m_ToBlastArea(false)
{
//除了保存actor的指针外还需要保留一份actor的ID的副本
//因为如果actorCon添加或者删除一个人那么actor的位置会动态改变,
//那么指针所指向的actor则可能不是以前那个
m_ActorID = actor->getID();
m_iPriority = iPriority;
m_actor = actor;
m_pModel = pModel;
//为astar类提供场景
m_astar.init(pModel);
}
//安置炸弹
void CTask::placeBomb(void)
{
bGetActor();
m_actor->setBomb();
}
bool CTask::bHaveBrick(void)
{
bGetActor();
return m_pModel->m_pMap->judgeElem(m_actor->getPos(), ENUM::Brick);
}
void CTask::setPriority(int& iPriority)
{
m_iPriority = iPriority;
}
bool CTask::bGetActor(void)
{
m_pModel->m_pActorManager->getActor(m_ActorID);
return true;
}
int CTask::bCouldEscape(Pos& pos)
{
CVirtualMap& vtMap = *(m_pModel->m_pVirtualMap);
//搜索的圈数
int iMaxLeftTime = 2+vtMap.maxLeftTime();
bGetActor();
Pos actPos = m_actor->getPos();
//首先标记actor所在的位置
virtualPos vtPos;
vtPos = vtMap.GetNode(actPos);
vtPos.bSearch = true;
vtPos.iCost = 0;
vtMap.SetNode(actPos, vtPos);
//安全点的队列.,将安全点放入这里面,并选取最优
std::multimap<int, Pos, std::greater<int> > qSafePos;
//然后进行深度优先搜索
std::queue<Pos> que;
que.push(actPos);
Pos nowPos;
while(!que.empty() && iMaxLeftTime-- >= 0)
{
Pos PrePos = que.front();
que.pop();
virtualPos PreVtPos = vtMap.GetNode(PrePos);
Pos NowPos;
//向上扩展
NowPos.x = PrePos.x;
NowPos.y = PrePos.y-1;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
//向下扩展
NowPos.x = PrePos.x;
NowPos.y = PrePos.y+1;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
//向左扩展
NowPos.x = PrePos.x - 1;
NowPos.y = PrePos.y;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
//向右扩展
NowPos.x = PrePos.x + 1;
NowPos.y = PrePos.y;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
}
/*
//**********************************************************
#ifndef NDEBUG
std::ofstream file;
file.open("CTaskcpp.txt");
//file << "(" <<j << ","<< i<< "):";
for (std::multimap<int, Pos, std::greater<int> >::iterator iter = qSafePos.begin(); iter != qSafePos.end(); ++iter)
{
file << "cost"<< iter->first
<< "\tx:" <<iter->second.x
<< "\ty:" << iter ->second.y << std::endl;
}
#endif
//**********************************************************
*/
//表示没有找到安全点
if (qSafePos.empty())
{
//清除Virtual上的标记
vtMap.clearTag();
return 0;
}
else
{
pos = getNextPos(qSafePos, vtMap);
//清除Virtual上的标记
vtMap.clearTag();
return qSafePos.begin()->first;
}
}
bool CTask::bExpandNode(Pos& PrePos, Pos& NowPos,
virtualPos& PreVtPos,
CVirtualMap& vtMap,
std::multimap<int, Pos, std::greater<int> >& qSafePos
)
{
//没有越界
if (NowPos.y >= 0 && NowPos.x >=0 && NowPos.x < vtMap.width() && NowPos.y < vtMap.height() )
{
//检测是否被扩展过,并且要满足为通路
virtualPos NowVtPos = vtMap.GetNode(NowPos);
if (!NowVtPos.bSearch && PreVtPos.iCost + 2 < NowVtPos.iTimeLeft
&& NowVtPos.checkNode(Access) && !NowVtPos.checkNode(BeingBlast))
{
NowVtPos.bSearch = true;
NowVtPos.iCost = PreVtPos.iCost + 1;
vtMap.SetNode(NowPos, NowVtPos);
//如果不为BlastArea则表明此处安全
if (!NowVtPos.checkNode( BlastArea))
{
qSafePos.insert(std::pair<int,Pos>(1000-NowVtPos.iCost,NowPos));
}
//如果两个爆炸区域的剩余时间大于1+爆炸持续时间,则timeleft大的地方为安全区
else if ( abs(PreVtPos.iTimeLeft - NowVtPos.iTimeLeft) >= 1 + CParam::iBlastTime
&& !m_pModel->m_pMap->judgeElem(PrePos,ENUM::Bomb)
&& PreVtPos.checkNode(BlastArea) && NowVtPos.checkNode(BlastArea))
{
NowVtPos.bSearch = true;
NowVtPos.iCost = PreVtPos.iCost + 1;
vtMap.SetNode(NowPos, NowVtPos);
if (PreVtPos.iTimeLeft > NowVtPos.iTimeLeft )
{
qSafePos.insert(std::pair<int,Pos>(500-PreVtPos.iCost+abs(PreVtPos.iTimeLeft -
NowVtPos.iTimeLeft)-CParam::iBlastTime,PrePos));
}
else
{
qSafePos.insert(std::pair<int,Pos>(500-NowVtPos.iCost+abs(PreVtPos.iTimeLeft -
NowVtPos.iTimeLeft)-CParam::iBlastTime,NowPos));
}
}
return true;
}
}//end if (nowPos.y >= 0)
return false;
}
Pos CTask::getNextPos(std::multimap<int, Pos, std::greater<int> >& qSafePos, CVirtualMap& vtMap)
{
//取得一个权值最大的安全点,然后搜索一条路径,返回一个坐标
//std::vector<Pos> vecPath;
Pos bestPos = qSafePos.begin()->second;
//从bestPos开始扩展到起点
virtualPos NowVtPos = vtMap.GetNode(bestPos);
int iNowCost = NowVtPos.iCost;
Pos nowPos = bestPos;
while (--iNowCost > 0)
{
//检查上方
nowPos.x = bestPos.x;
nowPos.y = bestPos.y-1;
if (nowPos.y >= 0)
{
NowVtPos = vtMap.GetNode(nowPos);
if ( NowVtPos.checkNode(Access) && NowVtPos.bSearch && NowVtPos.iCost == iNowCost)
{
bestPos = nowPos;
continue;
}
}
//检测下方
nowPos.x = bestPos.x;
nowPos.y = bestPos.y+1;
if (nowPos.y < vtMap.height())
{
NowVtPos = vtMap.GetNode(nowPos);
if (NowVtPos.checkNode(Access) && NowVtPos.bSearch && NowVtPos.iCost == iNowCost)
{
bestPos = nowPos;
continue;
}
}
//检测左边
nowPos.x = bestPos.x-1;
nowPos.y = bestPos.y;
if (nowPos.x >= 0)
{
NowVtPos = vtMap.GetNode(nowPos);
if (NowVtPos.checkNode(Access) && NowVtPos.bSearch && NowVtPos.iCost == iNowCost)
{
bestPos = nowPos;
continue;
}
}
//检查右方
nowPos.x = bestPos.x+1;
nowPos.y = bestPos.y;
if (nowPos.y < vtMap.width())
{
NowVtPos = vtMap.GetNode(nowPos);
if (NowVtPos.checkNode(Access) && NowVtPos.bSearch && NowVtPos.iCost == iNowCost)
{
bestPos = nowPos;
continue;
}
}
}//end while (--iNowPriority != 0)
return bestPos;
}
//检查是否能安装炸弹后逃跑
int CTask::bCouldPlaceAndEscape(Pos& pos)
{
//检测能否安置炸弹
CVirtualMap vtMap(*m_pModel->m_pVirtualMap);
vtMap.subOne(); //所有爆炸时间-1
bGetActor();
Pos actPos = m_actor->getPos();
//首先标记actor所在的位置
virtualPos vtPos;
//在虚拟地图中安置炸弹
vtMap.setBomb(actPos,m_actor->getBombKind());
vtPos = vtMap.GetNode(actPos);
vtPos.bSearch = true;
vtPos.iCost = 0;
vtMap.SetNode(actPos, vtPos);
//安全点的队列.,将安全点放入这里面,并选取最优
std::multimap<int, Pos, std::greater<int> > qSafePos;
//然后进行深度优先搜索
std::queue<Pos> que;
que.push(actPos);
int iMaxLeftTime = 2+vtMap.maxLeftTime();
Pos nowPos;
while(!que.empty() && iMaxLeftTime-- >= 0)
{
Pos PrePos = que.front();
que.pop();
virtualPos PreVtPos = vtMap.GetNode(PrePos);
Pos NowPos;
//向上扩展
NowPos.x = PrePos.x;
NowPos.y = PrePos.y-1;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
//向下扩展
NowPos.x = PrePos.x;
NowPos.y = PrePos.y+1;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
//向左扩展
NowPos.x = PrePos.x - 1;
NowPos.y = PrePos.y;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
//向右扩展
NowPos.x = PrePos.x + 1;
NowPos.y = PrePos.y;
if ( bExpandNode(PrePos, NowPos,PreVtPos,vtMap,qSafePos) )
{
que.push(NowPos);
}
}
//表示没有找到安全点
if (qSafePos.empty())
{
return 0;
}
else
{
pos = getNextPos(qSafePos, vtMap);
int pri = qSafePos.begin()->first;
Pos ipos=qSafePos.begin()->second;
return qSafePos.begin()->first;
}
return 0;
}
int CTask::bInPower(int ID)
{
//取得敌人位置
Pos ePos = m_pModel->m_pActorManager->getActor(ID)->getPos();
//取得自己的位置以及火力属性;
bGetActor();
Pos myPos = m_actor->getPos();
int iPower =m_actor->getBombKind()->m_Power;
int i;
//首先检查敌人是否在火力十字范围内
if ((myPos.x == ePos.x || myPos.y == ePos.y)
&& abs(myPos.x - ePos.x) <= iPower && abs(myPos.y - ePos.y) <= iPower )
{
//检查自己与敌人之间是否存在障碍物
if (myPos.x == ePos.x)
{
if (myPos.y-1 >= 0 && m_pModel->m_pMap->judgeElem(Pos(myPos.x, myPos.y-1),ENUM::Actor)
&&m_pModel->m_pActorManager->getActor(ID)->getPos() == Pos(myPos.x, myPos.y-1))
{
return 1;
}
if ( myPos.y+1 < m_pModel->m_pMap->rowNum() && m_pModel->m_pMap->judgeElem(Pos(myPos.x,
myPos.y+1),ENUM::Actor))
{
return 1;
}
if (myPos.y > ePos.y)
{
for (i = 1; i < abs(myPos.y - ePos.y); ++i)
{
if (!m_pModel->m_pMap->judgeElem(Pos(myPos.x, myPos.y-i),ENUM::Access))
{
return 0;
}
}
}
else
{
for (i = 1; i < abs(myPos.y - ePos.y); ++i)
{
if (!m_pModel->m_pMap->judgeElem(Pos(myPos.x, myPos.y+i),ENUM::Access))
{
return 0;
}
}
}
return abs(myPos.y - ePos.y);
}
else if ( myPos.y == ePos.y)
{
if (myPos.x-1 >= 0 && m_pModel->m_pMap->judgeElem(Pos(myPos.x-1, myPos.y),ENUM::Actor))
{
return 1;
}
if (myPos.x+1 < m_pModel->m_pMap->lineNum() && m_pModel->m_pMap->judgeElem(Pos(myPos.x+1,
myPos.y),ENUM::Actor))
{
return 1;
}
if (myPos.x > ePos.x)
{
for (i = 1; i < abs(myPos.x - ePos.x); ++i)
{
if (!m_pModel->m_pMap->judgeElem(Pos(myPos.x-i, myPos.y),ENUM::Access))
{
return 0;
}
}
}
else
{
for (i = 1; i < abs(myPos.y - ePos.y); ++i)
{
if (!m_pModel->m_pMap->judgeElem(Pos(myPos.x+i, myPos.y),ENUM::Access))
{
return 0;
}
}
}
return abs(myPos.x - ePos.x);
}
}
else
{
return 0;
}//end if ((myPos.x = ePos.x || myPos.y = ePos.y) && abs(myPos.x - ePos.x) <= iPower && abs(myPos.y - ePos.y) <=
iPower )
return 0;
}
//检查某点是否为爆炸区域
bool CTask::bIsBlastArea(const Pos& pos)
{
CVirtualMap* vtMap = (m_pModel->m_pVirtualMap);
if (vtMap->checkNode(pos, BlastArea) || m_pModel->m_pMap->judgeElem(pos, ENUM::BlastArea))
{
return true;
}
else
{
return false;
}
}
//该点是否能去
bool CTask::bCanTo(const Pos& pos)
{
CVirtualMap* vtMap = (m_pModel->m_pVirtualMap);
return vtMap->bCanTo(pos);
}
//执行移动操作
void CTask::move(const Pos& targetPos,const Pos& nowPos)
{
//判断移动方向
if (targetPos.y == nowPos.y )
{
if (targetPos.x < nowPos.x)
{
//左移
m_actor->moveLeft();
}
else if (targetPos.x > nowPos.x)
{
//右移
m_actor->moveRight();
}
}
else if (targetPos.x == nowPos.x)
{
if (targetPos.y < nowPos.y)
{
//上移
m_actor->moveUp();
}
else if (targetPos.y > nowPos.y)
{
//下移
m_actor->moveDown();
}
}
}
//////////////////////////////////////////////////
//攻击任务
CAttackTask::CAttackTask(const int iPriority, CAIActor* actor, CModel* pModel,int enemyID)
:CTask(iPriority, actor, pModel)
{
//TODO:这里填入构造代码
m_ID = enemyID;
}
CAttackTask::~CAttackTask(void)
{
//TODO:这里填入析构代码
}
void CAttackTask::execute()
{
bGetActor();
//取得敌人的位置
Pos enemyPos;
enemyPos = m_pModel->m_pActorManager->getActor(m_ID)->getPos();
Pos actPos = m_actor->getPos();
deque<Pos> path;
m_ToBlastArea = false;
//检测敌人是否在火力范围内
Pos excapePos;
if (bInPower(m_ID))
{
//能够安装炸弹并全身而退
if (bCouldPlaceAndEscape(excapePos) > 505+CParam::iBlastTime)
{
m_actor->setBomb();
}
}
else
{
Pos nextPos;
Pos actPos = m_actor->getPos();
//if( !m_Path.empty())
//{
// nextPos = m_Path.front(); //下一步
//}
//不能过则另寻一路
//if( m_pModel->m_pMap->judgeElem(nextPos, ENUM::Access)==false )
//{
//执行astar,取得下一步的目的
path = m_astar.astar(m_actor->getPos(),enemyPos, CParam::iMaxClosed);
if (path.empty())
{
return;
}
nextPos = path.front();
//}
//如果可以通过
if (m_pModel->m_pMap->judgeElem(nextPos, ENUM::Access))
{
//如果前方是爆炸区域则不执行
if (bCanTo(nextPos)==false)
{
return;
}
move(nextPos, actPos);
//path.pop_front();
m_ToBlastArea = true;
}
//如果不能通过则炸掉
else
{
if (bCouldPlaceAndEscape(excapePos)> 515+CParam::iBlastTime)
{
m_actor->setBomb();
return;
}
else
{
//TODO:如果不能安置炸弹的处理,这里暂时不写先
}
}
}
return;
}
bool CAttackTask::updatePriority(void)
{
bGetActor();
//取得敌人与自己的位置
CActor* enemy = m_pModel->m_pActorManager->getActor(m_ID);
//监测 敌人如果死亡 返回false
if (enemy->m_State == ENUM::HaveDie)
{
return false;
}
//如果敌人 处于锁定状态
else if (enemy->m_State==ENUM::Besiege)
{
m_iPriority = 0;
return true;
}
Pos enemyPos = enemy->getPos();
Pos myPos = m_actor->getPos();
//判定攻击任务的优先级
if(m_ToBlastArea ==true)
m_iPriority = 100 - (abs(enemyPos.x - myPos.x)+abs(enemyPos.y - myPos.y));
else
m_iPriority = CParam::iAttackPriority - (abs(enemyPos.x - myPos.x)+abs(enemyPos.y - myPos.y));
return true;
}
/////////////////////////////////////////////////////
//goto任务
CGotoTask::CGotoTask(const int iPriority, CAIActor* actor, CModel* pModel,const Pos& pos):CTask(iPriority, actor, pModel)
{
//TODO:这里填入构造代码
m_targetPos = pos;
//设置物品ID
}
CGotoTask::~CGotoTask(void)
{
//TODO:这里填入析构代码
}
void CGotoTask::execute()
{
bGetActor();
Pos nextPos;
Pos actPos = m_actor->getPos();
Pos excapePos;
deque<Pos> path;
m_ToBlastArea = false;
//if( !m_Path.empty())
//{
// nextPos = m_Path.front(); //下一步
//}
//不能过则另寻一路
//if( m_Path.empty() || m_pModel->m_pMap->judgeElem(nextPos, ENUM::Access)==false )
//{
//执行astar,取得下一步的目的
path = m_astar.astar(m_actor->getPos(),m_targetPos, CParam::iMaxClosed);
if (path.empty())
{
return;
}
nextPos = path.front();
//}
//如果可以通过
if (m_pModel->m_pMap->judgeElem(nextPos, ENUM::Access))
{
//如果前方是爆炸区域则不执行
if (bCanTo(nextPos)==false)
{
return;
}
move(nextPos, actPos);
m_ToBlastArea = true;
//m_Path.pop_front();
}
//如果不能通过则炸掉
else
{
if (bCouldPlaceAndEscape(excapePos))
{
m_actor->setBomb();
return;
}
else
{
//TODO:如果不能安置炸弹的处理,这里暂时不写先
}
}
}
//设置目的地
void CGotoTask::setTargetPos(const Pos& pos)
{
m_targetPos = pos;
}
//更新优先级,如果任务失效则返回false,如果更新成功则返回true
bool CGotoTask::updatePriority(void)
{
return true;
}
//////////////////////////////////////////////////////
//逃跑任务
CEscapeTask::CEscapeTask(const int iPriority, CAIActor* actor, CModel* pModel):CTask(iPriority, actor, pModel)
{
//TODO:这里填入构造代码
}
CEscapeTask::~CEscapeTask(void)
{
//TODO:这里填入析构代码
}
void CEscapeTask::execute(void)
{
//如果处于爆炸区则ret
bGetActor();
if (m_pModel->m_pMap->judgeElem(m_actor->getPos(), ENUM::BlastArea))
{
return;
}
//找到一个安全地点
Pos aim;
if (bCouldEscape(aim))
{
if (m_pModel->m_pMap->judgeElem(aim, ENUM::BlastArea))
{
return;
}
if (m_actor->state() == ENUM::Caution)
{
Pos newAim;
if (m_pModel->m_pMap->judgeElem(m_actor->getPos(),ENUM::Access)
&&bCouldPlaceAndEscape(newAim)>520)
{
m_actor->setBomb();
}
else
{
move(aim,m_actor->getPos());
}
}
else
{
move(aim,m_actor->getPos());
}
}
else
{
//如果处在警戒状态
if (m_actor->state() == ENUM::Caution)
{
//如果能够安置炸弹
if (m_pModel->m_pMap->judgeElem(m_actor->getPos(), ENUM::Access))
{
m_actor->setBomb();
}
else
{
//向敌人方向移动
Pos targetPos = m_pModel->m_pActorManager->getNearestEnemy(m_actor->getPos())->getPos();
std::deque<Pos> path = m_astar.astar(m_actor->getPos(), targetPos, CParam::iMaxClosed, true);
if (path.empty())
{
return;
}
Pos nextPos = path.front();
Pos actPos = m_actor->getPos();
move(nextPos, actPos);
}
}
}//end if (bCouldEscape(aim))
}
//更新优先级,如果任务失效则返回false,如果更新成功则返回true
bool CEscapeTask::updatePriority(void)
{
bGetActor();
Pos nowPos = m_actor->getPos();
if (bIsBlastArea(nowPos))
{
m_iPriority = CParam::iEscapePriority;
return true;
}
else
{
m_iPriority = 1;
}
return true;
}
/////////////////////////////////////////////////////
CFeachTask::CFeachTask(const int iPriority, CAIActor* actor, CModel* pModel, const Pos& _pos):CGotoTask(iPriority, actor,
pModel, Pos(0,0))
{
//TODO:取得道具的pos
m_targetPos = _pos;
}
CFeachTask::~CFeachTask(void)
{
}
bool CFeachTask::updatePriority(void)
{
bGetActor();
Pos myPos = m_actor->getPos();
//检测物品是否存在
if (m_pModel->m_pMap->judgeElem(m_targetPos, ENUM::Property))
{
if(m_ToBlastArea==true)
m_iPriority = 90 - (abs(m_targetPos.x - myPos.x)+abs(m_targetPos.y - myPos.y));
else
m_iPriority = CParam::iFeachPriority - (abs(m_targetPos.x - myPos.x)+abs(m_targetPos.y - myPos.y));
return true;
}
else
{
return false;
}
}
/////////////////////////////////////////////////////
CGoToBesiegeTask::CGoToBesiegeTask(const int iPriority, CAIActor* actor, CModel* pModel, const Pos& _pos):CGotoTask
(iPriority, actor, pModel, Pos(0,0))
{
//TODO:取得被困Actor的pos
m_targetPos = _pos;
}
CGoToBesiegeTask::~CGoToBesiegeTask(void)
{
}
bool CGoToBesiegeTask::updatePriority(void)
{
bGetActor();
Pos myPos = m_actor->getPos();
//检测该Actor是否还被困
if (m_pModel->m_pMap->judgeElem(m_targetPos, ENUM::BesiegeActor))
{
m_iPriority = CParam::iGoToBesiege - (abs(m_targetPos.x - myPos.x)+abs(m_targetPos.y - myPos.y));
return true;
}
else
{
return false;
}
}
/////////////////////////////////////////////////
// Content: 任务类 函数及静态成员定义
/////////////////////////////////////////////////
#pragma once
#include <map>
#include <vector>
#include <queue>
#include "enum.h"
#include "CAstar.h"
#include "CVirtualMap.h"
class CModel;
class CAIActor;
//任务的基类
class CTask
{
public:
CTask(const int iPriority, CAIActor* actor, CModel* pModel);
virtual ~CTask(void) {}
virtual void execute(void)=0; //执行
virtual bool updatePriority(void)=0;//更新优先级,如果任务失效则返回false,如果更新成功则返回true
int m_taskID; //任务id
int m_iPriority; //优先度
int m_ID; //任务目标ID
int m_ActorID; //所属actor的ID
//*****************************************************
//测试用代码
//bool testbCouldEscape(Pos& pos){return bCouldPlaceAndEscape(pos);}
bool testbIsBlastArea(const Pos& pos){return bIsBlastArea(pos);}
//*****************************************************/
protected:
void placeBomb(void); //安置炸弹
void setPriority(int& iPriority); //设置自身优先级
bool bGetActor(void); //取得actor的指针
int bCouldEscape(Pos& pos); //检测是否能逃跑,如果!=0则返回躲避点
bool bIsBlastArea(const Pos& pos); //检测pos处是否为爆炸区域
int bCouldPlaceAndEscape(Pos& pos);//检测能否安置炸弹后并顺利逃跑,如果!=0则返回躲避点
bool bHaveBrick(void); //检查前方是否有砖头
int bInPower(int ID); //检测敌人是否在火力范围,如果不在则返回0,在则返回距离
bool bCanTo(const Pos& pos); //该点是否能去
bool bExpandNode(Pos& PrePos, Pos& NowPos,
virtualPos& PreVtPos,
CVirtualMap& vtMap,
std::multimap<int, Pos, std::greater<int> >& qSafePos);
//扩展节点
Pos getNextPos(std::multimap<int, Pos, std::greater<int> >& qSafePos,CVirtualMap& vtMap); //取得下一步移动的目
的地
void move(const Pos& targetPos,const Pos& nowPos); //执行移动操作
CAstar m_astar; //Astar组件
CAIActor* m_actor; //所属actor的指针
CModel* m_pModel; //场景指针
std::deque<Pos> m_Path; //Astar生成的路径
bool m_ToBlastArea; //是否通过爆炸区域
};
//攻击任务
class CAttackTask:public CTask
{
public:
CAttackTask(const int iPriority, CAIActor* actor, CModel* pModel,int enemyID);
~CAttackTask(void);
void execute(void); //执行
bool updatePriority(void);//更新优先级,如果任务失效则返回false,如果更新成功则返回true
};
//goto任务
class CGotoTask:public CTask
{
public:
CGotoTask(const int iPriority, CAIActor* actor, CModel* pModel, const Pos& pos);
~CGotoTask(void);
virtual void execute(void);
void setTargetPos(const Pos& pos); //设置目的地
bool updatePriority(void);//更新优先级,如果任务失效则返回false,如果更新成功则返回true
protected:
Pos m_targetPos; //目标位置
};
//逃跑任务
class CEscapeTask:public CTask
{
public:
CEscapeTask(const int iPriority, CAIActor* actor, CModel* pModel);
~CEscapeTask(void);
bool updatePriority(void);//更新优先级,如果任务失效则返回false,如果更新成功则返回true
void execute(void);
};
//Get任务用于取得物品
class CFeachTask:public CGotoTask
{
public:
CFeachTask(const int iPriority, CAIActor* actor, CModel* pModel, const Pos& _pos);
~CFeachTask(void);
bool updatePriority(void);//更新优先级,如果任务失效则返回false,如果更新成功则返回true
};
//营救或杀死被困Actor
class CGoToBesiegeTask:public CGotoTask
{
public:
CGoToBesiegeTask(const int iPriority, CAIActor* actor, CModel* pModel, const Pos& _pos);
~CGoToBesiegeTask(void);
bool updatePriority(void);//更新优先级,如果任务失效则返回false,如果更新成功则返回true
};
cost999 x:18 y:17
cost998 x:18 y:16
cost997 x:18 y:15
cost996 x:18 y:14
cost995 x:18 y:13
cost995 x:17 y:14
cost995 x:16 y:15
cost994 x:18 y:12
cost994 x:17 y:13
cost993 x:18 y:11
cost993 x:17 y:12
cost993 x:16 y:13
cost992 x:17 y:11
cost992 x:16 y:12
cost991 x:17 y:10
cost991 x:16 y:11
cost990 x:17 y:9
cost990 x:16 y:10
cost989 x:17 y:8
cost989 x:16 y:9
cost499 x:18 y:17
cost498 x:18 y:16
cost497 x:18 y:15
/////////////////////////////////////////////////
// Content: 虚拟地图类 成员函数的定义
// 用来做逃跑点的搜索
/////////////////////////////////////////////////
#include "./CVirtualMap.h"
#include "CParam.h"
CVirtualMap::CVirtualMap(CVirtualMap& vtMap)
{
m_iWidth = vtMap.width();
m_iHeight= vtMap.height();
m_Map = new virtualPos [m_iWidth*m_iHeight];
unsigned int size = m_iWidth*m_iHeight;
for (unsigned int i = 0; i < size; ++i)
{
m_Map[i] = vtMap.m_Map[i];
}
}
CVirtualMap::CVirtualMap(CModel* model)
{
/*
//**************************************
#ifndef NDEBUG
#include <fstream>
std::ofstream file;
file.open("testCVirtualMapcpp.txt");
#endif
//**************************************
*/
m_iWidth = model->m_pMap->lineNum();
m_iHeight= model->m_pMap->rowNum();
m_Map = new virtualPos [m_iWidth*m_iHeight];
int i,j;
for (i = 0; i < model->m_pMap->rowNum(); ++i)
{
for (j = 0; j < model->m_pMap->lineNum(); ++j)
{
SetNode(Pos(j,i), virtualPos(0, CParam::iInfinite, 0, false));
//假设不为通路
if (model->m_pMap->judgeElem(Pos(j,i), ENUM::Access))
{
addElem(Pos(j,i),Access);
}
else if (model->m_pMap->judgeElem(Pos(j,i), ENUM::BlastArea))
{
addElem(Pos(j,i),BeingBlast);
}
else
{
delElem(Pos(j,i), Access);
//假设有Actor则标记
if (model->m_pMap->judgeElem(Pos(j,i), ENUM::Actor))
{
addElem(Pos(j,i),Actor);
}
}//end if (pMap->judgeElem(Pos(j,i), ENUM::Access))
}//end for j
}//end for i
//开始迭代bomb容器,来标记爆炸区域及其时间
CBombManager::BombConType::iterator iter;
CBombManager::BombConType& BombCon = refreshBombCon(model);
for(iter = BombCon.begin(); iter != BombCon.end(); ++iter)
{
Pos pos = (*iter)->m_Pos;
//首先标记炸弹位置的cost
SetNode(pos,virtualPos(unAccess|BlastArea, (*iter)->m_TimeLeft, 0,true));
//向上扩展,直到遇到障碍物
int k;
for (k = 1; k <= (*iter)->m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x,pos.y-k), *(*iter)) )
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
//向下扩展,直到遇到障碍物
for (k = 1; k <= (*iter)->m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x,pos.y+k), *(*iter)) )
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
//向左扩展,直到遇到障碍物
for (k = 1; k <= (*iter)->m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x-k,pos.y), *(*iter)) )
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
//向右扩展,直到遇到障碍物
for (k = 1; k <= (*iter)->m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x+k,pos.y), *(*iter)) )
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
}//end for(; iter != model->m_pBombManager->m_BombCon.end(); ++iter)
//清除炸弹容器
for (iter = m_BombConType.begin(); iter != m_BombConType.end(); ++iter)
{
delete *iter;
}
/*
//测试用代码
//***************************************************************
#ifndef NDEBUG
for (i = 0; i < model->m_pMap->rowNum(); ++i)
{
for (j = 0; j < model->m_pMap->lineNum(); ++j)
{
virtualPos testvtPos;
testvtPos = GetNode(Pos(j,i));
file << "(" <<j << ","<< i<< "):";
file << "eType:" << testvtPos.eType <<"\tbSearch" <<testvtPos.bSearch << "\tiCost" <<testvtPos.iCost
<< "\tiTimeLeft" <<testvtPos.iTimeLeft << std::endl;
}//end for j
}//end for i
#endif
//***************************************************************
*/
}
CVirtualMap::~CVirtualMap()
{
delete[] m_Map;
}
void CVirtualMap::SetNode(Pos& pos, virtualPos& posValue)
{
m_Map[m_iWidth*pos.x + pos.y] = posValue;
}
virtualPos& CVirtualMap::GetNode(const Pos& pos)
{
return m_Map[m_iWidth*pos.x + pos.y];
}
int CVirtualMap::maxLeftTime(void)
{
//返回一个最大的爆炸时间
int i,j;
int iMaxLeftTime = 0;
for (i = 0; i < this->m_iWidth; ++i)
{
for (j = 0; j < this->m_iHeight; ++j)
{
virtualPos vtPos = GetNode(Pos(i,j));
if (vtPos.checkNode(BlastArea) && iMaxLeftTime < vtPos.iTimeLeft )
{
iMaxLeftTime = vtPos.iTimeLeft;
}
}
}
return iMaxLeftTime;
}
void CVirtualMap::subOne(void)
{
int i,j;
for (i = 0; i < this->m_iWidth; ++i)
{
for (j = 0; j < this->m_iHeight; ++j)
{
virtualPos vtPos = GetNode(Pos(i,j));
if (vtPos.checkNode(BlastArea) && vtPos.iTimeLeft != 0 )
{
--vtPos.iTimeLeft;
SetNode(Pos(i,j),vtPos);
}
}
}
}
void CVirtualMap::setBomb(const Pos& pos, CBombKind* pBombKind)
{
Pos NowPos = pos;
int iTimeLeft = pBombKind->m_BlastTime;
//首先确定TimeLeft
virtualPos NowVtPos = GetNode(NowPos);
if ( NowVtPos.checkNode(BlastArea) )
{
if (iTimeLeft > NowVtPos.iTimeLeft)
{
iTimeLeft = NowVtPos.iTimeLeft;
}
}
CBomb bomb(NowPos,pBombKind);
;
bomb.m_TimeLeft = iTimeLeft;
//标记自身
SetBlastArea(pos, bomb);
delElem(pos,Access);
//向上扩展,直到遇到障碍物
int k;
for (k = 1; k <= bomb.m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x,pos.y-k),bomb))
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
//向下扩展,直到遇到障碍物
for (k = 1; k <= bomb.m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x,pos.y+k),bomb))
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
//向左扩展,直到遇到障碍物
for (k = 1; k <= bomb.m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x-k,pos.y),bomb))
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
//向右扩展,直到遇到障碍物
for (k = 1; k <= bomb.m_pKind->m_Power; ++k)
{
if (!SetBlastArea(Pos(pos.x+k,pos.y), bomb))
{
break;
}
}//end for (k = 0; k < iter->m_Power; ++k)
}
bool CVirtualMap::SetBlastArea(const Pos& pos,CBomb& bomb)
{
virtualPos vtPos = GetNode(pos);
//确定不会越界
if (pos.x >= 0 && pos.x < m_iWidth && pos.y >= 0 && pos.y < m_iHeight)
{
//如果是通路或者玩家则标记
if ( checkNode(pos, Access) || checkNode(pos, Actor))
{
//如果pos点已经是爆炸范围了
//则判断爆炸范围的剩余爆炸时间如果比当前炸弹的剩余时间大则替换之,否则不做修改
if ( !checkNode(pos, BlastArea) ||bomb.m_TimeLeft < vtPos.iTimeLeft )
{
//标记BlastArea
vtPos.eType |= BlastArea;
vtPos.iTimeLeft = bomb.m_TimeLeft;
vtPos.iCost = 0;
vtPos.bSearch = false;
SetNode(Pos(pos.x, pos.y), vtPos);
}//end if ( !checkNode(pos, BlastArea) || vtPos.iTimeLeft > bomb.m_pKind->m_BlastTime )
//否则不做任何修改
return true;
}
else
{
//如果遇上障碍物则停止扩展
return false;
}//end if (model->m_pMap->judgeElem(pos, ENUM::Access))
}
else
{
return false;
}
}
//检查某点是否含有某元素,如:是否为通路
bool CVirtualMap::checkNode(const Pos& pos, posType eType)
{
if ((GetNode(pos).eType & eType) !=0)
{
return true;
}
else
{
return false;
}
}
bool CVirtualMap::bCanTo(const Pos& pos) //改点是否能到
{
return GetNode(pos).bCanTo();
}
//添加某元素
void CVirtualMap::addElem(const Pos& _pos, posType _elem)
{
GetNode(_pos).eType |= _elem;
}
//删除某元素
void CVirtualMap::delElem(const Pos& _pos, posType _elem)
{
GetNode(_pos).eType &= ~_elem;
}
//判断某个位置是否有_elem
bool CVirtualMap::judgeElem(const Pos& _pos, posType _elem)
{
return (GetNode(_pos).eType & _elem) != 0;
}
//计算炸弹的剩余爆炸时间
CBombManager::BombConType CVirtualMap::refreshBombCon(CModel* model)
{
CBombManager::BombConType& oriCon = model->m_pBombManager->getBombCon();
CBombManager::BombConType::iterator iterOriginal;
for (iterOriginal = oriCon.begin(); iterOriginal != oriCon.end(); ++iterOriginal )
{
CBomb* pBomb= new CBomb((*iterOriginal)->m_Pos, (*iterOriginal)->m_pKind);
pBomb->m_TimeLeft = (*iterOriginal)->m_TimeLeft;
m_BombConType.push_back(pBomb);
}
//m_BombConType = model->m_pBombManager->getBombCon();
CBombManager::BombConType::iterator iter;
bool bContinue = true;
while (bContinue)
{
bContinue = false;
//迭代的修改timeleft
for (iter = m_BombConType.begin(); iter != m_BombConType.end(); ++iter )
{
//取得炸弹的坐标
Pos bombPos = (*iter)->m_Pos;
int iPower = (*iter)->m_pKind->m_Power;
int iTimeLeft = (*iter)->m_TimeLeft;
Pos NowPos;
//向上扩展
NowPos.x = bombPos.x;
for (int i = 1; i <= iPower; i++)
{
NowPos.y = bombPos.y - i;
if (!expandBomb( NowPos, m_BombConType, iter, iTimeLeft, model, bContinue))
{
break;
}
}
//向下扩展
NowPos.x = bombPos.x;
for (int i = 1; i <= iPower; i++)
{
NowPos.y = bombPos.y + i;
if (!expandBomb( NowPos, m_BombConType, iter, iTimeLeft, model, bContinue))
{
break;
}
}
//向右扩展
NowPos.y = bombPos.y;
for (int i = 1; i <= iPower; i++)
{
NowPos.x = bombPos.x + i;
if (!expandBomb( NowPos, m_BombConType, iter, iTimeLeft, model, bContinue))
{
break;
}
}
//向左扩展
NowPos.y = bombPos.y;
for (int i = 1; i <= iPower; i++)
{
NowPos.x = bombPos.x - i;
if (!expandBomb( NowPos, m_BombConType, iter, iTimeLeft, model, bContinue))
{
break;
}
}
}//end for (iter = bombCon.begin(); iter != bombCon.end(); ++iter )
}
return m_BombConType;
}
std::pair<bool,CBomb*> CVirtualMap::searchBomb(const Pos& _pos,const CBombManager::BombConType bombCon)
{
CBombManager::BombConType::const_iterator iter = bombCon.begin();
for(;iter != bombCon.end();++iter)
{
if( (*iter)->m_Pos == _pos )
{
return std::pair<bool,CBomb*>(true, *iter);
}
}
return std::pair<bool,CBomb*>(true, *(bombCon.begin()));
}
//清除VtMap上的标记
void CVirtualMap::clearTag(void)
{
virtualPos vtPos;
int i,j;
for (i = 0; i < m_iHeight; ++i)
{
for (j = 0; j < m_iWidth; ++j)
{
vtPos = GetNode(Pos(j,i));
vtPos.bSearch = false;
vtPos.iCost = 0;
}
}
}
bool CVirtualMap::expandBomb(Pos& _pos, CBombManager::BombConType bombCon,
CBombManager::BombConType::iterator iter, int iTimeLeft, CModel* model, bool& bContinue)
{
//检查是否越界
if (_pos.x >= 0 && _pos.y >= 0 && _pos.x < m_iWidth && _pos.y < m_iHeight)
{
if ( model->m_pMap->judgeElem(_pos, ENUM::Access))
{
return true;
}
//如果pos处是炸弹,那么返回炸弹信息,并修改
else if (model->m_pMap->judgeElem(_pos, ENUM::Bomb))
{
std::pair<bool, CBomb*> pairObject = searchBomb(_pos, bombCon);
if (pairObject.first && pairObject.second->m_TimeLeft > (*iter)->m_TimeLeft)
{
pairObject.second->m_TimeLeft = (*iter)->m_TimeLeft;
bContinue = true;
}
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
/////////////////////////////////////////////////
// Content: 虚拟地图类 定义
// 用来做逃跑点的搜索
/////////////////////////////////////////////////
#pragma once
#include <list>
#include "utils.h"
#include "CMap.h"
#include "CBomb.h"
#include "CModel.h"
#include "CBombManager.h"
#include "CParam.h"
enum posType {unAccess = 0, Access = 1, BlastArea = 2, Actor = 4, BeingBlast = 8 };
struct virtualPos
{
//安全的节点有两种可能,1)某个节点不再爆炸区域内 2)两个爆炸区域的剩余爆炸时间相差(1+爆炸持续时间)
public:
int eType;
int iTimeLeft;
int iCost; //从起点到这里所经历的时间,bSearch=true有效
bool bSearch; //是否被搜索过
virtualPos(){bSearch = false; eType = 0;}
virtualPos(int type){ eType=type; bSearch = false;}
virtualPos(int type,int time,int cost,bool search)
{eType = type; iTimeLeft = time; iCost = cost; bSearch = search;}
//检查某点是否含有某元素,如:是否为通路
bool checkNode(posType type)
{
if ((eType & type) !=0)
{
return true;
}
else
{
return false;
}
}
bool bCanTo()
{
if ((eType & BlastArea)!=0 && iTimeLeft < CParam::iToBlastArea)
return false;
return true;
}
};
class CMap;
class CModel;
class CBomb;
class CBombKind;
#include "CBomb.h"
//虚拟地图的定义
class CVirtualMap
{
public:
CVirtualMap(CVirtualMap& vtMap);
CVirtualMap(CModel* model);
~CVirtualMap();
void SetNode(Pos& pos, virtualPos& posValue); //设置某个节点的值
virtualPos& GetNode(const Pos& pos); //取得某个节点的值
int width(void){return m_iWidth;} //返回宽度
int height(void){return m_iHeight;} //返回高度
int maxLeftTime(void); //返回最大的爆炸时间
void subOne(void); //所有爆炸区域的剩余爆炸时间
-1
void setBomb(const Pos& pos, CBombKind* pBombKind); //安置炸弹
bool checkNode(const Pos& pos, posType eType); //检查某点是否含有某元素,如:是否为通路
bool bCanTo(const Pos& pos); //改点是否能到
void addElem(const Pos& _pos, posType _elem); //添加某元素
void delElem(const Pos& _pos, posType _elem); //删除某元素
bool judgeElem(const Pos& _pos, posType _elem); //判断某个位置是否有_elem
void clearTag(void); //清除VtMap上的标记
CBombManager::BombConType refreshBombCon(CModel* model); //计算炸弹的剩余爆炸时间
virtualPos* m_Map; //地图
private:
//bool SetBlastArea(Pos& pos,CModel* pModel,std::list<CBomb>::iterator iter);
bool expandBomb(Pos& _pos, CBombManager::BombConType bombCon, CBombManager::BombConType::iterator iter,
int iTimeLeft, CModel* model, bool& bContinue);
//在炸弹容器中查找炸弹
std::pair<bool,CBomb*> searchBomb(const Pos& _pos,const CBombManager::BombConType bombCon);
bool SetBlastArea(const Pos& pos,CBomb& bomb);
int m_iWidth; //宽度
int m_iHeight; //高度
CBombManager::BombConType m_BombConType;//备份的炸弹容器
};
/////////////////////////////////////////////////
// cxf 修改过
// 2006.1.13 BOB
// 2006.1.15 BOB
// 2006.2.15 BOB
///////////////////////////////////////////////////////
#include "DirectFunction.h"
//显示文字
int DX::Draw_Text_GDI( LPDIRECTDRAWSURFACE7 lpdds,char *text, int x,int y, COLORREF color)
{
HDC hdc;
if (FAILED(lpdds->GetDC(&hdc) ) )
{ return false; }
SetTextColor(hdc,color);
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc,x,y,text,static_cast<int>(strlen(text)) );
if(lpdds) //释放dc
{ lpdds->ReleaseDC(hdc); }
return true;
}
//画直线
void DX::Draw_Line ( LPDIRECTDRAWSURFACE7 lpdds,int Ax,int Ay, int Bx,int By, int penWidth ,int penStyle ,COLORREF color )
{
HDC hdc;
if (FAILED(lpdds->GetDC(&hdc) ) )
{ return ; }
HPEN hpen=CreatePen( penStyle,penWidth,color );
SelectObject(hdc, hpen);
MoveToEx(hdc,Ax,Ay,NULL);
LineTo(hdc,Bx,By);
DeleteObject( hpen);
if(lpdds) //释放dc
{ lpdds->ReleaseDC(hdc); }
}
//填充Rect 区域为 color 或者叫画矩形
void DX::Draw_Rect (LPDIRECTDRAWSURFACE7 lpdds,int Ax,int Ay, int Bx,int By,COLORREF color)
{
RECT rect;
rect.left = Ax;
rect.right = Bx;
rect.top = Ay;
rect.bottom= By;
Draw_Rect(lpdds, rect,color);
}
//填充Rect 区域为 color 或者叫画矩形
void DX::Draw_Rect (LPDIRECTDRAWSURFACE7 lpdds,RECT _rect,COLORREF color)
{
DDBLTFX _ddbltfx;
DDRAW_INIT_STRUCT(_ddbltfx) ;
_ddbltfx.dwFillColor=color;
lpdds->Blt( &_rect,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL ,& _ddbltfx) ;
}
//载入位图
bool DX::Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
int file_handle=0, // 文件句柄
index=0; //文件数据信息
UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
OFSTRUCT file_data; // the file data information
if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
{
MessageBox(NULL, filename ,"打开位图文件发生异常!",MB_OK);
return false;
}
_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
{
_lclose(file_handle);
return false;
}
//下一段代码读取位图信息
// 载入文件位图文件头
_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
if (bitmap->bitmapinfoheader.biBitCount == 8)
{
MessageBox(NULL, filename ,"BOB位图不是24位!",MB_OK); exit(0) ;
}
_lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 ||
bitmap->bitmapinfoheader.biBitCount==24)
{
if (!(bitmap->buffer = new UCHAR[bitmap->bitmapinfoheader.biSizeImage] ))
{
_lclose(file_handle);
return false;
}
_lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
}
else
{ return false; }
_lclose(file_handle);
DX::Flip_Bitmap(bitmap->buffer,
bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8),
bitmap->bitmapinfoheader.biHeight);
return true;
}
//卸载图像///////////////////////////////////////////////////////////
bool DX::UnLoad_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
if (bitmap->buffer)
{
delete [](bitmap->buffer);
bitmap->buffer = NULL;
}
return true;
}
//获取位图信息///////////////////////////////////////////////////////////
bool DX::Flip_Bitmap( UCHAR *image, int bytes_per_line, int height)
{
UCHAR *buffer;
int index;
buffer = new UCHAR[bytes_per_line*height] ;
memcpy(buffer,image,bytes_per_line*height);
for (index=0; index < height; index++)
{
memcpy(&image[((height-1) - index)*bytes_per_line],&buffer[index*bytes_per_line], bytes_per_line);
}
delete []buffer;
return true;
}
//载入图像 从 BITMAP_FILE_PTR 到 页面 ///////////////////////////////////////
bool DX::Bitmap_To_LPDIRECTDRAWSURFACE(LPDIRECTDRAWSURFACE7& lpdds,const BITMAP_FILE& bitmap ,int width,int height)
{
DDSURFACEDESC2 ddsd ;
DDRAW_INIT_STRUCT(ddsd) ; //如果不去清空ddsd ^_^ 永远不要相信它里面是干净的
lpdds->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
DWORD *primary_buffer = (DWORD *)ddsd.lpSurface;
for (int index_y = 0; index_y < height; index_y++)
{
for (int index_x = 0; index_x < width; index_x++)
{
UCHAR blue = (bitmap.buffer[index_y*width*3 + index_x*3 + 0]),
green = (bitmap.buffer[index_y*width*3 + index_x*3 + 1]),
red = (bitmap.buffer[index_y*width*3 + index_x*3 + 2]);
DWORD pixel = _RGB32BIT(0,red,green,blue);
primary_buffer[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;
}
}
if (FAILED(lpdds->Unlock(NULL)))
{ return false;}
return true;
}
//裁减函数 //////////////////////////////////////////////////////
LPDIRECTDRAWCLIPPER DX::DDraw_Attach_Clipper(LPDIRECTDRAW7 lpdd,LPDIRECTDRAWSURFACE7 lpdds, int num_rects, LPRECT clip_list)
{
int index=0; // 循环变量
LPDIRECTDRAWCLIPPER lpddclipper;
LPRGNDATA region_data;
if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
return(NULL);
region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));
// 拷贝参数到LPRGNDATA region_data
memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);
// set up fields of header
region_data->rdh.dwSize = sizeof(RGNDATAHEADER);
region_data->rdh.iType = RDH_RECTANGLES;
region_data->rdh.nCount = num_rects;
region_data->rdh.nRgnSize = num_rects*sizeof(RECT);
region_data->rdh.rcBound.left = 64000;
region_data->rdh.rcBound.top = 64000;
region_data->rdh.rcBound.right = -64000;
region_data->rdh.rcBound.bottom = -64000;
// find bounds of all clipping regions
for (index=0; index<num_rects; index++)
{
// test if the next rectangle unioned with the current bound is larger
if (clip_list[index].left < region_data->rdh.rcBound.left)
region_data->rdh.rcBound.left = clip_list[index].left;
if (clip_list[index].right > region_data->rdh.rcBound.right)
region_data->rdh.rcBound.right = clip_list[index].right;
if (clip_list[index].top < region_data->rdh.rcBound.top)
region_data->rdh.rcBound.top = clip_list[index].top;
if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
region_data->rdh.rcBound.bottom = clip_list[index].bottom;
} // end for index
// now we have computed the bounding rectangle region and set up the data
// now let's set the clipping list
if (FAILED(lpddclipper->SetClipList(region_data, 0)))
{
free(region_data);
return(NULL);
}
if (FAILED(lpdds->SetClipper(lpddclipper)))
{
free(region_data);
return(NULL);
}
free(region_data);
return(lpddclipper);
}
////////////////////////////////////////////////////////////////////////////////////
//
// 位图精灵(BOB)图像格式
//
////////////////////////////////////////////////////////////////////////////////////
void BOB_TYPE::iniSingleBOB(int _Displaywide,int _Displayheight,int _x,int _y,int _vx ,int _vy,int _frequent,int _appendvx
,int _appendvy )
{
m_BOBDisplayWidth = _Displaywide; //重要的初始化,表示图元实际显示的大小可能放大或缩小
m_BOBDisplayHeight = _Displayheight; //重要的初始化,表示图元实际显示的大小可能放大或缩小
m_vx = _vx ; //重要的初始化 表示速度
m_vy = _vy ; //重要的初始化 表示速度
m_frequent=_frequent; //重要的初始化 表示绘制频率
m_x=_x; //重要的初始化 2006.3.29
m_y=_y; //重要的初始化 2006.3.29
m_appendvx=_appendvx; //次要的初始化 2006.3.27
m_appendvy=_appendvy; //次要的初始化 2006.3.27
anim_index=0; //不重要的初始化 2006.3.10
state=0; //不重要的初始化 2006.3.10
}
///////////////////////////////////////////////////////////////////////////////////
//
// BOB类的实现部分
// 图元精灵的实现
///////////////////////////////////////////////////////////////////////////////////
//为什么不构造函数初始是为了需要该类型出现时才进行初始化,例如如果没有造出A兵种就不会再入相关的资源
// _Displaywide,int _Displayheight显示大小,与BMP大小有区别
bool DX::CBOB::initializtion( LPDIRECTDRAW7 _lpdd,LPDIRECTDRAWSURFACE7 _animDestlpdd,
int _style, char *filename )
{
if( isInitializtion) //已初始化掉一次
{ return false; }
m_lpdd = _lpdd;
m_animDest = _animDestlpdd ;
m_style =_style;
m_bob = NULL;
if( !readDataFile( filename ) ) //载入BOB相关数据必须先栽入BOB数据
{ MessageBox(NULL, filename ,"BOB位图打开异常!",MB_OK); exit(0) ;}
if( !creatBackSurface( filename ) ) //载入图像创建位图的缓冲
{ MessageBox(NULL, filename ,"BOB位图缓冲打开异常!",MB_OK);exit(0) ;}
isInitializtion = 1; //非常重要的改变
return true;
}
//释放BOB
bool DX::CBOB::CBOBRelease( )
{
if( ! isInitializtion) //未初始化 未分配显存
{ return false; }
if ( m_animSource) // 释放主显示表面
{
isInitializtion=0;
m_animSource->Release();
m_animSource = NULL;
return true;
}
return false;
}
//创建位图的缓冲
bool DX::CBOB::creatBackSurface( char *filename )
{
BITMAP_FILE BOBbitmap ; // 位图
string tempName1=filename;
tempName1+=".bmp";
const char* tempName2 = tempName1.c_str();
DDSURFACEDESC2 ddsd ; // Direct信息结构
if ( !Load_Bitmap_File( & BOBbitmap ,(char *) tempName2) )
{ MessageBox(NULL, filename ,"BOB位图缓冲载入异常!",MB_OK); exit(0) ;}
DDRAW_INIT_STRUCT(ddsd) ;
ddsd.dwFlags = DDSD_CAPS |DDSD_WIDTH | DDSD_HEIGHT |DDSD_CKSRCBLT ;
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY ; //显存
ddsd.dwHeight = BOBbitmap.bitmapinfoheader.biHeight;
ddsd.dwWidth = BOBbitmap.bitmapinfoheader.biWidth;
ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = m_color_key_value ;
ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = m_color_key_value ;
if (FAILED(m_lpdd->CreateSurface(&ddsd, &m_animSource, NULL)))
{ return false;}
if ( !Bitmap_To_LPDIRECTDRAWSURFACE(m_animSource, BOBbitmap, ddsd.dwWidth ,ddsd.dwHeight ) )
{ return false;}
if( !UnLoad_Bitmap_File( & BOBbitmap ))
{ return false;}
return true;
}
//读取关于BOB数据如BOB的宽和高等
bool DX::CBOB::readDataFile(char *filename)
{
string tempName=filename ;
tempName+=".txt";
const char* name=tempName.c_str();
char tmp[30];
int temp1=0, temp2=0;
int colorKey1=0 ,colorKey2=0,colorKey3=0;
ifstream file(name);
if(!file)
{ MessageBox(NULL, name ,"位图初始化文件打开异常!",MB_OK);exit(1);}
file>>tmp>>colorKey1>>colorKey2>>colorKey3 ; //读取掩码
m_color_key_value = _RGB24BIT( colorKey1 ,colorKey2 ,colorKey3 ) ;
file>>tmp>>m_BOBBMPWidth;
file>>tmp>>m_BOBBMPHeight;
file>>tmp>>m_commonfrequent;
file>>tmp>>temp1;
while(temp1--)
{
file>>temp2;
m_vecState.push_back(temp2);
}
return true;
}
//返回某状态的张数限制 不成功返回-1
int DX::CBOB::getAnimIndex(int _state)
{
if(_state>static_cast<int>(m_vecState.size()) || _state<0)
{ return -1;}
return m_vecState[_state];
}
//接口防止位初始化BOB也在绘图
void DX::CBOB::CBOBRun(BOB* _bob,int x,int y,int& row,int& line)
{
m_bob = _bob; //不能修改_bob
copyAnimSourceToAnimDest( x, y, row, line);
}
//拷贝源表面BOB到页面缓存 默认都是相同大小的区域
bool DX::CBOB::copyAnimSourceToAnimDest(int x,int y,int& row,int& line)
{
//进行row line 检查
if(row>static_cast<int>(m_vecState.size())-1)
{
row=0;
//*********************************************************
#ifndef NDEBUG
MessageBox(NULL,"索引超过ROW","发生异常!",MB_OK);
#endif
//***********************************************************
return false;
}
if( m_vecState[row]==line)
{ line=0;}
dest_rect.left = x; //进行初始化 ,必须初始化不然会错
dest_rect.top = y;
dest_rect.right = dest_rect.left + m_bob->m_BOBDisplayWidth ;
dest_rect.bottom = dest_rect.top + m_bob->m_BOBDisplayHeight ;
source_rect.left = line * m_BOBBMPWidth ;
source_rect.top = row * m_BOBBMPHeight ;
source_rect.right = source_rect.left + m_BOBBMPWidth ;
source_rect.bottom = source_rect.top + m_BOBBMPHeight ;
DDRAW_INIT_STRUCT(m_ddbltfx) ; //设置颜色掩码
if (FAILED( m_animDest->Blt(&dest_rect, m_animSource , &source_rect, DDBLT_WAIT | DDBLT_KEYSRC , &m_ddbltfx) ))
{ return false ; }
return true;
}
///////////////////////////////////////////////////////////////////////////
// 图像引擎子类
//
//////////////////////////////////////////////////////////////////////////////////
//初始化静态成员变量
bool DX::CDrawEngine::isInition=0; //是否被初始化,整个DX只能在为空或释放后才可以重新建立
//构造函数
bool DX::CDrawEngine::inition(HWND hwnd ,RECT clipperRect ,bool fullWindow)
{
if(isInition ) //表示已经被初始化
{ return false; }
m_WindowHandle = hwnd ;
m_clipperRect = clipperRect; //裁减区域
DDSURFACEDESC2 ddsd ; // Direct信息结构
DDRAW_INIT_STRUCT(ddsd) ;
if (FAILED(DirectDrawCreateEx(NULL, (void **)&m_lpdd, IID_IDirectDraw7, NULL)))
{ exit(0) ;}
if( !fullWindow )
{
if (FAILED(m_lpdd->SetCooperativeLevel(m_WindowHandle,DDSCL_NORMAL))) //全屏
{ exit(0) ; }
}
else
{
//设置全屏显示模式
if (FAILED(m_lpdd->SetCooperativeLevel(m_WindowHandle,
DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT )))//| DDSCL_MULTITHREADED
{ exit(0) ; }
if (FAILED(m_lpdd->SetDisplayMode( m_clipperRect.right-m_clipperRect.left ,m_clipperRect.bottom-
m_clipperRect.top,32,0,0)))
{ exit(0) ; }
}
// 创建主显示表面
DDRAW_INIT_STRUCT(ddsd) ; //清空内存
ddsd.dwFlags = DDSD_CAPS ; // 初始有效区域
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE ; // 申请主显示表面
m_lpdd->CreateSurface(&ddsd,&m_lpddsprimary,NULL);
DDRAW_INIT_STRUCT(ddsd) ;
ddsd.dwFlags = DDSD_CAPS |DDSD_WIDTH | DDSD_HEIGHT ;
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY ; //显存DDSCAPS_SYSTEMMEMORY 内存
ddsd.dwHeight = m_clipperRect.bottom - m_clipperRect.top ;
ddsd.dwWidth = m_clipperRect.right - m_clipperRect.left ;
if (FAILED( m_lpdd->CreateSurface(&ddsd, &m_lpddsback, NULL)))
{ exit(0) ;}
DDBLTFX ddbltfx; //将后备区域先全部归0 不然屏幕的
DDRAW_INIT_STRUCT(ddbltfx);
ddbltfx.dwSize =sizeof(ddbltfx);
ddbltfx.dwFillColor = 0;
if (FAILED(m_lpddsback->Blt(NULL, NULL, NULL, DDBLT_COLORFILL , &ddbltfx)))
{ exit(0) ; }
if (fullWindow)
{ m_lpddclipper = DX::DDraw_Attach_Clipper(m_lpdd,m_lpddsback,1,&m_clipperRect); }
else
{
// 设置窗口的裁剪
if (FAILED(m_lpdd->CreateClipper(0,&m_lpddclipper,NULL)))
{ exit(0) ;}
if (FAILED(m_lpddclipper->SetHWnd(0, m_WindowHandle)))
{ exit(0) ; }
if (FAILED(m_lpddsprimary->SetClipper(m_lpddclipper)))
{ exit(0) ; }
}
isInition = 1; //必须将其变为一表示已经初始化
return true;
}
//释放DX
bool DX::CDrawEngine::DrawEngineRelease()
{
if (m_lpddclipper)
{ m_lpddclipper->Release(); }
if (m_lpddsback)
{ m_lpddsback->Release(); }
if (m_lpddsprimary)
{ m_lpddsprimary->Release(); }
if (m_lpdd)
{ m_lpdd->Release(); }
isInition = 0; //必须归为0
return true;
}
//显示到屏幕上
void DX::CDrawEngine::displayOnScreen()
{
if (FAILED(m_lpddsprimary->Blt(&m_clipperRect, m_lpddsback, NULL, DDBLT_WAIT,NULL)))
{ return ;}
}
////////////////////////////////////////////////////////////////////////
// 要用到的宏和结构常量
// 以及基本的图像处理类
// 2006.3.24
/////////////////////////////////////////////////////////////////////////
#define INITGUID // make sure directX guids are included
#pragma once
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <windows.h>
#include <windowsx.h>
#include <string>
#include <io.h>
#include <ddraw.h>
using namespace std;
//---------------定义类型别名
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
//--------------------常量定义
const int BITMAP_ID = 0x4D42 ; //位图格式标志
//inline bool KEYDOWN(int vk){ return ( ( GetAsyncKeyState(vk) & 0x8000) ? 1 : 0 );}
//inline bool KEYUP(int vk) { return ( ( GetAsyncKeyState(vk) & 0x6000) ? 0 : 1 );}
// 初始化内存为0 ,必须是引用
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
//图像颜色编码方式
inline int _RGB16BIT555(int r,int g,int b) { return ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10)) ;}// 16色位图 5. 5 .5 1
位a
inline int _RGB16BIT565(int r,int g,int b) { return ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11));} // 16色位图 5.6.5 绿
色多一位
inline int _RGB24BIT(int r,int g,int b) { return( (b) + ((g) << 8) + ((r) << 16) ) ;} // 32色位图 8.8.8 8位
a
inline int _RGB32BIT(int a,int r,int g,int b){ return((b) + ((g) << 8) + ((r) << 16) + ((a) << 24));} // 32色位图 8.8.8 8位
a
//位图结构
typedef struct BITMAP_FILE_TAG
{
public:
BITMAPFILEHEADER bitmapfileheader; //位图文件头信息
BITMAPINFOHEADER bitmapinfoheader; // 调色板信息
PALETTEENTRY palette[256]; // 储存调色板v
UCHAR *buffer; // 指向位图数据指针
} BITMAP_FILE, *BITMAP_FILE_PTR;
//位图精灵(BOB)图像格式
typedef struct BOB_TYPE
{
public:
BOB_TYPE(){ }
BOB_TYPE( int _x,int _y,bool _isDraw=1,int _state=0 ,int _anim_index=0):
m_x(_x),m_y(_y),isDraw(_isDraw),state( _state),anim_index(_anim_index)
{ } //构造函数
void iniSingleBOB(int _Displaywide,int _Displayheight,int _x,int _y,int _vx ,int _vy,int _frequent,int _appendvx ,int
_appendvy ); //设置BOB实际显示大小在屏幕上
public:
//int ID ; //BOB ID号
int m_frequent; //显示频率
bool isDraw; //是否要被显示
int state; //状态 处于跑还是跳
int anim_index; //当前处于该动画的几张(跑的2张)
int m_x,m_y; //BOB 位置在图像上
int m_BOBDisplayWidth, m_BOBDisplayHeight; //显示时的大小
int m_vx,m_vy; //BOB 在X,Y方向上的速度
int m_appendvx,m_appendvy; //附加值处理对于例如在帧频率*步长如3*3=39而每格为40就要在最后补上
} BOB ,*BOB_PTR;
////////////////////////////////////////////////////////////////////////////////
// 要用到的函数和类
//
//////////////////////////////////////////////////////////////////////////////////
namespace DX
{
//显示文字
int Draw_Text_GDI( LPDIRECTDRAWSURFACE7 lpdds,char *text, int x,int y, COLORREF color);
//画直线
void Draw_Line ( LPDIRECTDRAWSURFACE7 lpdds,int Ax,int Ay, int Bx,int By, int penWidth=1,int
penStyle=PS_SOLID,COLORREF color=_RGB32BIT(0,0, 0, 0));
//填充Rect 区域为 color 或者叫画矩形
void Draw_Rect (LPDIRECTDRAWSURFACE7 lpdds,int Ax,int Ay, int Bx,int By,COLORREF color);
void Draw_Rect (LPDIRECTDRAWSURFACE7 lpdds,RECT _rect,COLORREF color);
//切换图像
bool Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
//载入图像 从磁盘到BITMAP_FILE_PTR
bool Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
//卸载图像
bool UnLoad_Bitmap_File(BITMAP_FILE_PTR bitmap);
//载入图像 从 BITMAP_FILE_PTR 到 页面
bool Bitmap_To_LPDIRECTDRAWSURFACE ( LPDIRECTDRAWSURFACE7& lpdds,const BITMAP_FILE& bitmap ,int width,int height);
//裁减函数
LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAW7 lpdd,LPDIRECTDRAWSURFACE7 lpdds, int num_rects, LPRECT
clip_list);
//进行关于BOB的相关所有操作
class CBOB
{
public:
CBOB():isInitializtion (0) { } ;
~CBOB( ) { CBOBRelease();};
//为什么不构造函数初始是为了需要该类型出现时才进行初始化,例如如果没有造出A兵种就不会再入相关的资源
// _Displaywide,int _Displayheight显示大小,与BMP大小有区别
bool initializtion( LPDIRECTDRAW7 _lpdd,LPDIRECTDRAWSURFACE7 _animDest, int _style, char *filename );
bool isBOBInitializtion(){ return isInitializtion; } //是否BOB被初始化
bool CBOBRelease( ); //释放BOB
void CBOBRun(BOB* _bob,int x,int y,int& row,int& line); //接口防止位初始化BOB也在绘图
int getCommonFrequent(){ return m_commonfrequent; } //获取通用显示频率
int getSizeOfvecState(){ return static_cast<int> (m_vecState.size()); } //返回状态的数目
int getAnimIndex(int _state); //返回某状态的张数限制 不成功返回-1
protected:
bool copyAnimSourceToAnimDest(int x,int y,int& row,int& line) ; //拷贝源表面BOB到页面缓存具有自动处理索引rowline溢
出
bool readDataFile(char *filename); //读取关于BOB数据如BOB的宽和高登
bool creatBackSurface(char *filename); //创建位图的缓冲
protected:
BOB* m_bob ; //图元精灵
bool isInitializtion ; //是否被初始化
int m_style ; //BOB类型
LPDIRECTDRAW7 m_lpdd ; //Direct对象
vector<int> m_vecState; //每种状态对应的支持张数 如 1表示跳, 跳有4张图像 0
表示不动一般1张
DWORD m_color_key_value; //色彩健值 (掩码值)
DDBLTFX m_ddbltfx; // 填充结构
RECT dest_rect ; // 目的矩形
RECT source_rect ; // 源矩形
int m_commonfrequent ; //绘制通用频率
int m_BOBBMPWidth, m_BOBBMPHeight; // BMP上BOB的宽和高 这就表明所有同类型的BOB图像的一样的
大小
LPDIRECTDRAWCLIPPER m_lpddclipper; // 裁剪器
LPDIRECTDRAWSURFACE7 m_animSource; //此处是指动画的原表面 (额外开辟的专门放BOB的显
存)
LPDIRECTDRAWSURFACE7 m_animDest; //此处是指动画的目的表面 (可能是住表面,但更常见是
后备表面的显缓存)
};
////////////////////////////////////////////////////////
// 进行图形控制的接口类
//
/////////////////////////////////////////////////////////
class CDrawEngine
{
public:
CDrawEngine (){ }; //构造函数
~CDrawEngine(){ DrawEngineRelease();}; //析构函数
bool inition(HWND hwnd ,RECT clipperRect ,bool fullWindow); //建立DX
bool DrawEngineRelease(); //释放DX
virtual void run()=0; //执行函数
bool isBeInition(){ return isInition;} //是否被初始化了
protected:
static bool isInition; //是否被初始化,整个DX只能在为空或释放后才可以重新建立
void displayOnScreen(); //显示到屏幕上
HWND m_WindowHandle ; //全局函数句柄
RECT m_clipperRect ; // 绘制区域(裁减区域)
LPDIRECTDRAWCLIPPER m_lpddclipper ; // 裁剪器
LPDIRECTDRAW7 m_lpdd ; // Direct对象
LPDIRECTDRAWSURFACE7 m_lpddsprimary ; // 主显示表面
LPDIRECTDRAWSURFACE7 m_lpddsback ; // 后备
};
}
#include <fstream>
#include "DirectInput.h"
//静态变量的定义
bool DXInput::CDirectInput::IsDInputInitonal;
LPDIRECTINPUT8 DXInput::CDirectInput::m_lpdi;
/////////////////////////////////////////////////////////////
// DirectInput接口的释放
////////////////////////////////////////////////////////
//构造函数
DXInput::CDirectInput::CDirectInput()
{
IsDInputInitonal=false;
}
//接口构建 构造函数
DXInput::CDirectInput::CDirectInput(HINSTANCE _hinstance)
{
IsDInputInitonal=true;
inition(_hinstance);
}
//释放接口
DXInput::CDirectInput::~CDirectInput()
{
if(IsDInputInitonal==true)
{
if(m_lpdi==NULL)
{ MessageBox(NULL,"m_lpdi==NULL","发生异常!",MB_OK); }
else
{ m_lpdi->Release(); }
}
}
//真正创建接口
void DXInput::CDirectInput::inition(HINSTANCE _hinstance)
{
if(IsDInputInitonal==true)
{ return ; }
IsDInputInitonal = true; //标志已经初始化
if (FAILED(DirectInput8Create(_hinstance ,DIRECTINPUT_VERSION , IID_IDirectInput8, (void **)&m_lpdi,NULL)))
{
MessageBox(NULL,"DirectInput8Create","发生异常!",MB_OK);
exit(1);
}
}
///////////////////////////////////////////////////////
// 鼠标接口的定义
//
///////////////////////////////////////////////////////
//构造函数
DXInput::CDirectMouse::CDirectMouse( )
:Isinitonal(false)
{
}
//构造函数申请资源
DXInput::CDirectMouse::CDirectMouse(HWND _hwnd,HINSTANCE _hinstance,int _MouseRangeW,int _MouseRangeH)
: Isinitonal(true)
{
initializtion(_hwnd,_hinstance, _MouseRangeW, _MouseRangeH);
}
//析构函数释放资源
DXInput::CDirectMouse::~ CDirectMouse( )
{
release( );
}
//初始化
bool DXInput::CDirectMouse::initializtion(HWND _hwnd,HINSTANCE _hinstance,int _MouseRangeW,int _MouseRangeH)
{
//如果LPDIRECTINPUT8没有建立必须先建立 LPDIRECTINPUT8
if(IsDInputInitonal==true)
{ }
else
{ inition( _hinstance);}
//开始初始化DirectMouse
if( Isinitonal==true)
{ return false; }
else
{
m_MouseX=0;
m_MouseY=0;
m_MouseRangeW = _MouseRangeW;
m_MouseRangeH = _MouseRangeH;
//SetCursorPos(0,0); //将光标定位于0,0这样计数才正确
Isinitonal = true; //必须归为true
}
if (m_lpdi->CreateDevice(GUID_SysMouse, &m_lpdimouse, NULL)!=DI_OK)
{
MessageBox(NULL,"m_lpdi->CreateDevice","发生异常!",MB_OK);
exit(1);
}
if (m_lpdimouse->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
{
MessageBox(NULL,"m_lpdimouse->SetCooperativeLevel","发生异常!",MB_OK);
exit(1);
}
if (m_lpdimouse->SetDataFormat(&c_dfDIMouse)!=DI_OK)
{
MessageBox(NULL,"m_lpdimouse->SetDataFormat","发生异常!",MB_OK);
exit(1);
}
if (m_lpdimouse->Acquire()!=DI_OK)
{
MessageBox(NULL,"m_lpdimouse->Acquire()","发生异常!",MB_OK);
exit(1);
}
return true;
}
//释放接口
bool DXInput::CDirectMouse::release( )
{
if( Isinitonal==false )
{ return false;}
else
{ Isinitonal = false ; }
if(m_lpdimouse==NULL)
{ MessageBox(NULL,"m_lpdimouse->Unacquire()","发生异常!",MB_OK); }
m_lpdimouse->Unacquire();
return true;
}
//获取鼠标位置同时和当前那个键被按下,那个键使用返回值 左键0右键1没有鼠标键按下为-1
int DXInput::CDirectMouse::getMousesAndButton(int& MouseX,int& MouseY)
{
//*********************************************************
#ifndef NDEBUG
if( Isinitonal==false )
{ MessageBox(NULL,"还未初始化getMousesAndButton就要调用","发生异常!",MB_OK);exit(1);}
#endif
//***********************************************************
if(FAILED(m_lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID*)(&m_mousesState))))
{
MessageBox(NULL,"m_lpdimouse->GetDeviceState","发生异常!",MB_OK);
exit(1);
}
m_MouseX += m_mousesState.lX;
m_MouseY += m_mousesState.lY;
if( m_MouseX<0 )
{
m_MouseX=0;
}else
{}
if(m_MouseX>= m_MouseRangeW)
{
m_MouseX= m_MouseRangeW;
}else
{}
if( m_MouseY<0 )
{
m_MouseY=0;
}else
{}
if(m_MouseY>= m_MouseRangeH)
{
m_MouseY= m_MouseRangeH;
}else
{}
MouseX=m_MouseX;
MouseY=m_MouseY;
//以下这句话是针对真正的鼠标 而不是针对贴图的鼠标
//SetCursorPos(MouseX,MouseY); //纠正鼠标当前位置
/*
//*********************************************************
#ifndef NDEBUG
std::ofstream file;
file.open("cxf.txt",std::ios::app);
file<<MouseX<<" "<<MouseY<<" "<<std::endl;
#endif
//***********************************************************
*/
if(m_mousesState.rgbButtons[0] & 0x80) //鼠标左键按下
{
/*
//*********************************************************
#ifndef NDEBUG
std::ofstream file;
file.open("cxf.txt",std::ios::app);
file<<MouseX<<" "<<MouseY<<" "<<std::endl;
#endif
//***********************************************************
*/
return 0;
}
if(m_mousesState.rgbButtons[1] & 0x80) //鼠标右键按下
{ return 1;}
return -1; //没有鼠标键按下
}
//设置鼠标的当前位置
bool DXInput::CDirectMouse::setCursorPos(int _x,int _y)
{
if(_x<0 || _y <0 || _x>m_MouseRangeW || _y>m_MouseRangeW)
{ return false;}
m_MouseX = _x;
m_MouseY = _y;
return true;
}
////////////////////////////////////////////////////////////
//
// directInput类库
//
//////////////////////////////////////////////////////////
#pragma once
#define INITGUID
#include <objbase.h>
#include <dinput.h>
#include <ddraw.h>
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
namespace DXInput
{
/////////////////////////////
// 输入类的接口 基类
// 保证LPDIRECTINPUT8 唯一性
//////////////////////////////
class CDirectInput
{
public:
CDirectInput( );
CDirectInput(HINSTANCE _hinstance);
~CDirectInput();
LPDIRECTINPUT8 getLPDIRECTINPUT8(){ return m_lpdi;}
protected:
void inition(HINSTANCE _hinstance);
static bool IsDInputInitonal; //是否被初始化
static LPDIRECTINPUT8 m_lpdi ; // 输入对象
};
/////////////////////////////////
// 处理鼠标
/////////////////////////////////
class CDirectMouse:public CDirectInput
{
public:
CDirectMouse() ;
CDirectMouse(HWND _hwnd,HINSTANCE _hinstance,int m_MouseRangeW=800,int m_MouseRangeH=600) ; //构造函数申请
资源
~ CDirectMouse( ) ; //析构函数释放资源
bool initializtion(HWND _hwnd,HINSTANCE _hinstance,int m_MouseRangeW=800,int m_MouseRangeH=600); //初始化
bool release( ); //释放接口
//bool getLeftButtonDown(int& MouseX,int& MouseY); //鼠标左键点下时的位置
//bool getRightButtonDown(int& MouseX,int& MouseY); //鼠标右键点下时的位置
//bool getMousesPos(int& MouseX,int& MouseY); //鼠标当前位置
bool setCursorPos(int _x,int _y) ; //设置鼠标的当前位置
int getMousesAndButton(int& MouseX,int& MouseY); //获取鼠标位置同时和当前那个键被按下,那个键使用返回值
//左键0右键1没有鼠标键按下为-1
private:
int m_MouseRangeW,m_MouseRangeH; //鼠标可以移动的范围
int m_MouseX,m_MouseY; //鼠标的位置
bool Isinitonal; //是否被初始化
DIMOUSESTATE m_mousesState; //鼠标当前状态
LPDIRECTINPUTDEVICE8 m_lpdimouse; // 输入鼠标对象
};
/////////////////////////////////
// 处理键盘
/////////////////////////////////
class CDirectKeyBoard:public CDirectInput
{
private:
};
}
#include "DirectSound.h"
//本函数载入wav格式音乐 建立directsound缓存 以及载入数据到内存中 返回声音的ID
bool DXSound::CDirectSound::LoadWAV(char *filename,int soundID, int control_flags )
{
HMMIO hwav; // wave文件句柄
MMCKINFO parent,child; //父块和子块
WAVEFORMATEX wfmtx; // wave 格式
UCHAR *snd_buffer, // 临时声音数据指针
*audio_ptr_1=NULL, // 指向第一个的声音缓存的数据指针
*audio_ptr_2=NULL; // 指向第二个的声音缓存的数据指针
DWORD audio_length_1=0, // 第一个写缓存长度
audio_length_2=0; // 第二个写缓存长度
//是否有空闲的音乐ID 如果没有返回-1;
if (soundID==-1)
{ return false;}
//第一步 是否这儿有已打开的ID
if (m_sound_fx[soundID].state != SOUND_NULL) // 确信声音没有被使用
{ return false; }
//建立块信息结构
parent.ckid = (FOURCC)0;
parent.cksize = 0;
parent.fccType = (FOURCC)0;
parent.dwDataOffset = 0;
parent.dwFlags = 0;
// 拷贝数据
child = parent;
//打开WAV文件
if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
{ MessageBox(NULL,"mmioOpen","发生异常!",MB_OK); exit(1); }
// 分解到parent.fccType; //descend into the RIFF
parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
{
mmioClose(hwav, 0); //关闭文件
MessageBox(NULL,"mmioDescend","发生异常!",MB_OK);
exit(1);
}
//分解到child.ckid; descend to the WAVEfmt
child.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioDescend(hwav, &child, &parent, 0))
{
mmioClose(hwav, 0); //关闭文件
MessageBox(NULL,"mmioDescend","发生异常!",MB_OK);
exit(1);
}
// 从文件中读入WAV格式文件格式信息
if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
{
mmioClose(hwav, 0); //关闭文件
MessageBox(NULL,"mmioDescend","发生异常!",MB_OK);
exit(1);
}
// 确信数据格式是PCM
if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
{
mmioClose(hwav, 0); //关闭文件
MessageBox(NULL,"mmioDescend","发生异常!",MB_OK);
exit(1);
}
// 现在提升一级以便能存取数据
if (mmioAscend(hwav, &child, 0))
{
mmioClose(hwav, 0);
MessageBox(NULL,"mmioAscend","发生异常!",MB_OK);
exit(1);
}
// 降解到数据块
child.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
{
mmioClose(hwav, 0);
MessageBox(NULL,"mmioAscend","发生异常!",MB_OK);
exit(1);
}
//最后读取数据建立DXSound数据缓存
snd_buffer = (UCHAR *)malloc(child.cksize); // 分配内存给数据
mmioRead(hwav, (char *)snd_buffer, child.cksize);// 读取WAV数据
mmioClose(hwav, 0); // 关闭文件
// 在数据接构中设置速率和大小set rate and size in data structure
m_sound_fx[soundID].rate = wfmtx.nSamplesPerSec;
m_sound_fx[soundID].size = child.cksize;
m_sound_fx[soundID].state = SOUND_LOADED;
m_sound_fx[soundID].soundName=filename;
// 建立数据格式
memset(&m_pcmwf, 0, sizeof(WAVEFORMATEX));
m_pcmwf.wFormatTag = WAVE_FORMAT_PCM; // 脉冲编码调制
m_pcmwf.nChannels = 1;
m_pcmwf.nSamplesPerSec = 11025; // 一般都是这种速率
m_pcmwf.nBlockAlign = 1;
m_pcmwf.nAvgBytesPerSec = m_pcmwf.nSamplesPerSec * m_pcmwf.nBlockAlign;
m_pcmwf.wBitsPerSample = 8;
m_pcmwf.cbSize = 0;
//准备建立声音缓存
memset(&m_dsbd,0,sizeof(DSBUFFERDESC));
m_dsbd.dwSize = sizeof(DSBUFFERDESC);
m_dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
m_dsbd.dwBufferBytes = child.cksize;
m_dsbd.lpwfxFormat = &m_pcmwf;
// 创建声音缓存
if (FAILED(m_lpds->CreateSoundBuffer(&m_dsbd,&m_sound_fx[soundID].dsbuffer,NULL)))
{
free(snd_buffer); //失败后释放内存
MessageBox(NULL,"CreateSoundBuffer","发生异常!",MB_OK);
exit(1);
}
//拷贝声音到缓存
if (FAILED(m_sound_fx[soundID].dsbuffer->Lock(0,
child.cksize,
(void **) &audio_ptr_1,
&audio_length_1,
(void **)&audio_ptr_2,
&audio_length_2,
DSBLOCK_FROMWRITECURSOR)))
{
free(snd_buffer); //失败后释放内存
MessageBox(NULL,"m_sound_fx","发生异常!",MB_OK);
exit(1);
}
// 拷贝循环缓存的前部分
memcpy(audio_ptr_1, snd_buffer, audio_length_1);
// 拷贝循环缓存的后部分
memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);
// 缓存解所锁
if (FAILED(m_sound_fx[soundID].dsbuffer->Unlock(audio_ptr_1,
audio_length_1,
audio_ptr_2,
audio_length_2)))
{
free(snd_buffer); //失败后释放内存
MessageBox(NULL,"m_sound_fx","发生异常!",MB_OK);
exit(1);
}
//释放临时内存
free(snd_buffer);
// 返回声音ID
return true;;
}
bool DXSound::CDirectSound::initionCDirectSound(HWND _hwnd,char * fileName)
{
if(m_isIniDirectSound==true)
{ return false;}
if( DirectSoundCreate(NULL,&m_lpds,NULL)!=DS_OK)
{ MessageBox(NULL,"DirectSoundCreate","发生异常!",MB_OK); exit(1); }
if (m_lpds->SetCooperativeLevel(_hwnd,DSSCL_NORMAL)!=DS_OK)
{ MessageBox(NULL,"SetCooperativeLevel","发生异常!",MB_OK); exit(1); }
memset(m_sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS) ;
//初始化声音数组
for (int index=0;index<MAX_SOUNDS; index++)
{
memset(&m_sound_fx[index],0,sizeof(pcm_sound));
m_sound_fx[index].state = SOUND_NULL;
m_sound_fx[index].id = -1; //应该都初始化为-1表示没有声音被载入
}
if( readSoundIniFile(fileName) == false )
{
MessageBox(NULL,"initionCDirectSound","发生异常!",MB_OK);
exit(1);
}
m_currentSoundID =-1; //当前没有声音
m_isIniDirectSound=true;
return true;
}
bool DXSound::CDirectSound::releaseCDirectSound()
{
if(m_isIniDirectSound == false)
{ return false;}
for (int index=0; index<MAX_SOUNDS; index++) // 释放
{
if (m_sound_fx[index].state !=SOUND_NULL )
{
m_sound_fx[index].dsbuffer->Stop();
m_sound_fx[index].dsbuffer->Release();
}
}
if (m_lpds!=NULL)
{ m_lpds->Release(); }
m_isIniDirectSound=false;
return true;
}
//读取声音初始化文件
bool DXSound::CDirectSound::readSoundIniFile(char *_filename)
{
char temp[30];
int soundWavNum=0;
int tempID;
char fileName[50];
std::ifstream file( _filename );
if(!file)
{ MessageBox(NULL,"readSoundIniFile","发生异常!",MB_OK);exit(1);}
file>>temp>>soundWavNum;
for(int n=0;n<soundWavNum;n++)
{
file>>fileName>>tempID;
if( LoadWAV(fileName,tempID)==true)
{
m_sound_fx[tempID].id=tempID;
}
}
return true;
}
//设置当前声音ID
bool DXSound::CDirectSound::setCurrentSound(int _id )
{
if(_id>MAX_SOUNDS || m_sound_fx[_id].state==SOUND_NULL)
{ return false; }
m_currentSoundID=0;
return true;
}
//播放声音
bool DXSound::CDirectSound::runSound()
{
if(m_currentSoundID == -1)
{ return false;}
if (FAILED(m_sound_fx[m_currentSoundID].dsbuffer->SetCurrentPosition(0)))
{ return false;}
if ( FAILED( m_sound_fx[m_currentSoundID].dsbuffer->Play(0,0,DSBPLAY_LOOPING) ))
{ return false;}
return true;
}
//播放声音
bool DXSound::CDirectSound::PlayAll( )
{
for (int index=0; index<MAX_SOUNDS; index++)
{
if (m_sound_fx[index].dsbuffer)
{
if (FAILED(m_sound_fx[index].dsbuffer->SetCurrentPosition(0)))
{ return false;}
if (m_sound_fx[index].dsbuffer->Play(0,0,DSBPLAY_LOOPING)==DSERR_BUFFERLOST)
{ return false;}
}
}
}
//设置声音大小
bool DXSound::CDirectSound::SetVolume(int id,int vol)
{
if (m_sound_fx[id].dsbuffer->SetVolume( DSVOLUME_TO_DB(vol) )!=DS_OK)
{ return false; }
return true;
}
//设置声音的频率
bool DXSound::CDirectSound::SetFreq(int id,int freq)
{
if (m_sound_fx[id].dsbuffer->SetFrequency(freq)!=DS_OK)
{ return false; }
return true;
}
//设置声音的声道
bool DXSound::CDirectSound::SetPan(int id,int pan)
{
if (m_sound_fx[id].dsbuffer->SetPan(pan)!=DS_OK)
{ return false;}
return true;
}
//停止特定声音
bool DXSound::CDirectSound::StopSound(int id)
{
if (m_sound_fx[id].state != SOUND_NULL)
{
m_sound_fx[id].dsbuffer->Stop();
m_sound_fx[id].dsbuffer->SetCurrentPosition(0);
return true;
}
return false;
}
//停止所有声音
void DXSound::CDirectSound::StopAllSounds()
{
for (int index=0; index < MAX_SOUNDS; index++)
{ StopSound(index); }
}
//删除特定声音 释放接口
bool DXSound::CDirectSound::DeleteSound(int id)
{
if(! StopSound(id))
{ return false;}
if (m_sound_fx[id].dsbuffer)
{
m_sound_fx[id].dsbuffer->Release();
m_sound_fx[id].dsbuffer = NULL;
}
return true;
}
//删除所有声音 释放接口
void DXSound::CDirectSound::DeleteAllSounds()
{
for (int index=0; index < MAX_SOUNDS; index++)
{ DeleteSound(index); }
}
//返回声音的指针 LPDWORD pdwStatus
int DXSound::CDirectSound::StatusSound(int id)
{
if (m_sound_fx[id].dsbuffer)
{
ULONG status;
m_sound_fx[id].dsbuffer->GetStatus(&status); //设置情形
return(status);
}
else
{
return -1; //表示错误
}
}
//设置重复声音但是不用再一次载入
int DXSound::CDirectSound::ReplicateSound(int source_id)
{
if (source_id!=-1)
{
for (int id=0; id < MAX_SOUNDS; id++)
{
if (m_sound_fx[id].state==SOUND_NULL)
{
m_sound_fx[id] = m_sound_fx[source_id];
if (FAILED(m_lpds->DuplicateSoundBuffer(m_sound_fx[source_id].dsbuffer,
& m_sound_fx[id].dsbuffer)))
{
m_sound_fx[id].dsbuffer = NULL;
m_sound_fx[id].state = SOUND_NULL;
return -1;
}
m_sound_fx[id].id = id;
return( id);
}
}
}
else
{ return(-1); }
return(-1);
}
/////////////////////////////////////////
// directSound库
//
//////////////////////////////////////////////////
#pragma once
#define INITGUID
#include <windows.h>
#include <windowsx.h>
#include <string.h>
#include <malloc.h>
#include <memory.h>
#include <dsound.h>
#include <dmksctrl.h>
#include <dmusici.h>
#include <dmusicc.h>
#include <dmusicf.h>
#include <fstream>
#include "DirectSoundUtility.h"
namespace DXSound
{
//声音类 同时可以播放WAV格式音乐
class CDirectSound
{
public:
CDirectSound():m_isIniDirectSound(false) { }
CDirectSound(HWND hwnd,char * fileName) { initionCDirectSound(hwnd,fileName);}
~CDirectSound() { releaseCDirectSound(); }
bool initionCDirectSound(HWND hwnd,char * fileName) ; //初始化函数
bool releaseCDirectSound(); //释放接口
bool getIsIniDirectSound() { return m_isIniDirectSound;}
LPDIRECTSOUND getLPDIRECTSOUND(){ return m_lpds;} //获取LPDIRECTSOUND为DXMusic
bool setCurrentSound(int _id) ; //设置当前声音ID
bool runSound(); //播放声音
bool PlayAll( ); //播放声音
bool SetVolume(int id,int vol); //设置声音大小 0-100 0为禁音
bool SetFreq(int id,int freq); //设置声音的频率100,000以下
bool SetPan(int id,int pan); //设置声音的声道-10,000 to 10,0000 0表示在中间
bool StopSound(int id); //停止特定声音
void StopAllSounds( ); //停止所有声音
private:
bool readSoundIniFile(char *filename); //读取声音初始化文件
bool LoadWAV(char *filename,int soundID, int control_flags = DSBCAPS_CTRLDEFAULT);//载入WAV格式音乐
int ReplicateSound(int source_id); //设置重复声音但是不用再一次载入
int StatusSound(int id); //获取声音指针 也许有危险所以不提供出来
bool DeleteSound(int id); //删除特定声音
void DeleteAllSounds( ); //删除所有声音
private:
int m_currentSoundID; //当前播放声音
bool m_isIniDirectSound; //是否已经初始化
LPDIRECTSOUND m_lpds; // directsound 接口指针
DSBUFFERDESC m_dsbd; // directsound 描述
DSCAPS m_dscaps; // directsound caps
HRESULT m_vdsresult; // directsound 结果
DSBCAPS m_dsbcaps; // directsound 缓冲 caps
//LPDIRECTSOUNDBUFFER m_lpdsbprimary; // 主混淆缓冲区
pcm_sound m_sound_fx[MAX_SOUNDS]; // 第二级声音缓冲数组
WAVEFORMATEX m_pcmwf; // 通用WAV声音格式
};
}
////////////////////////////////////////////////
// 声音库中需要的宏和定义
// 基本上只是对 其汉化
///////////////////////////////////////////////
#include <string>
#define WIN32_LEAN_AND_MEAN
//-------------------------------------------------------------
// 常量定义
//-------------------------------------------------------------
const int DM_NUM_SEGMENTS=64 ;// midi数据段在内存中缓存的数量
// midi 对象状态定义
const int MIDI_NULL = 0 ; // midi 对象未定义
const int MIDI_LOADED = 1 ; // midi 对象被载入
const int MIDI_PLAYING = 2 ; // midi 被载入和播放
const int MIDI_STOPPED = 3 ; // midi 被载入停止播放
// 系统中声音最大数量
const int MAX_SOUNDS = 256;
//数字音乐状态定义
const int SOUND_NULL = 0 ; // SOUND 对象未定义
const int SOUND_LOADED = 1 ; // SOUND 对象被载入
const int SOUND_PLAYING = 2 ; // SOUNDS 被载入和播放
const int SOUND_STOPPED = 3 ; // SOUND 被载入停止播放
//--------------------------------------------------------------
// 常用函数和宏的定义
//-------------------------------------------------------------
inline int DSVOLUME_TO_DB(int volume) { return (DWORD)(-30*(100 - volume)); } //通过分贝调节音量
#define MULTI_TO_WIDE( x,y ) MultiByteToWideChar( CP_ACP,MB_PRECOMPOSED, y,-1,x,_MAX_PATH) //将多字节形式转换为
Unicode
#ifndef DSBCAPS_CTRLDEFAULT
#define DSBCAPS_CTRLDEFAULT (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME )
#endif
//-----------------------------------------------------------------------------------
// 常用的结构体
//-----------------------------------------------------------------------------------
//单独的声音类
typedef struct pcm_sound_typ
{
LPDIRECTSOUNDBUFFER dsbuffer; // 声音缓冲器
std::string soundName ; //声音名字
int state; // 声音状态
int rate; // 回放速度频率
int size; // 声音大小
int id; // 声音ID
} pcm_sound, *pcm_sound_ptr;
// directmusic MIDI 段
typedef struct DMUSIC_MIDI_TYP
{
IDirectMusicSegment *dm_segment; // IDirectMusicSegment
IDirectMusicSegmentState *dm_segstate; // 状态
int id; // 段的ID
int state; // midi 歌曲状态
} DMUSIC_MIDI, *DMUSIC_MIDI_PTR;
/////////////////////////////////////////////////
// Content: 放置常用枚举类型
/////////////////////////////////////////////////
#pragma once
namespace ENUM
{
//消息接收模块类型(角色,炸弹,地图)
enum ModelType {ActorMessage = 0,BombMessage = 1,MapMessage = 2};
//消息类型(移动,放置炸弹,炸弹爆炸,被炸,死亡,出现道具,某人被困,处理被困)
enum MessageType { Move = 0,SetBomb = 1,Blast = 2,BeBomb = 3,Die = 4,AppearProperty = 5,
msBesiege = 6,DealBesiege = 7};
//动作类型(无动作,上,下,左,右,放炸弹)
enum ActionType { NoAction = 0,UP = 1,DOWN = 2,LEFT = 3,RIGHT = 4,SetBombAction = 5};
//游戏元素类型(通路,永久障碍物,空地,砖块,炸弹,角色,爆炸,被困人员)
enum ElemType { Access = 1, Block = 2, Space = 4, Brick = 8,
Bomb = 16,Actor = 32,BlastArea = 64,Property = 128,BesiegeActor = 256};
//角色类型(玩家,AI)
enum ActorType {PlayerActor = 0,AIActor = 1};
//任务类型
enum TaskType {Attack = 0, Goto = 1, Escape = 3};
//角色的状态(存活,被困,死亡,放松警戒, 警戒)
enum ActorState {Alive = 0,Besiege = 1,HaveDie = 2,Relax = 3, Caution = 4};
//道具类型(变速,增加炸弹数,增加炸弹威力,改变炸弹爆炸时间)
enum PropertyType {ChangeSpeed = 0,IncreaseBombNum = 1,IncreaseBombPower = 2,
ChangeBlastTime = 3};
enum GameState { GameBegin =1000 , GameOver=1001 ,GamePause=1002 ,GameMenu=1003 ,GameAuthor=1004,GameIsOn=1005};
}
/////////////////////////////////////////////////
// Content: 放置异常类型
/////////////////////////////////////////////////
#pragma once
//异常类
class Exception
{
public:
Exception(char* _str):str(_str) {}
char* str;
};
/////////////////////////////////////////////////
// Content: 程序main函数
/////////////////////////////////////////////////
#pragma once
#include "exception.h"
#include "windowsUtils.h"
#include "CGameEngine.h"
#include "CParam.h"
#include "resource.h"
///////////////////////////////////////////////////////
// 全局变量
/////////////////////////////////////////////////////////
HWND g_hwnd;
HINSTANCE g_hinstance;
//windows消息处理函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(msg)
{
case WM_CREATE:
{
return(0);
} break;
case WM_PAINT:
{
hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
return(0);
} break;
case WM_DESTROY:
{
PostQuitMessage(0);
return(0);
} break;
default:break;
}
return (DefWindowProc(hwnd, msg, wparam, lparam));
}
//main执行函数
void Run(MSG& msg)
{
CParam param; //读入配置文件
CGameEngine gameEngine;
gameEngine.init(g_hwnd , g_hinstance); //初始化
while(TRUE)
{
if (PeekMessage(&msg,0,0,0,PM_NOREMOVE))
{
if(!GetMessage(&msg, 0, 0, 0 )) return;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
gameEngine.run(); //引擎执行
}
}
// 主函数////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)
{
WNDCLASSEX winclass; // this will hold the class we create
MSG msg; // generic message
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(hinstance, "CICON" );
winclass.hCursor = LoadCursor(hinstance,"CURSOR_HAND");
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = 0;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(0, IDI_APPLICATION);
if (!RegisterClassEx(&winclass))
return(0);
if (!(g_hwnd = CreateWindowEx(0,
WINDOW_CLASS_NAME,
"AI泡泡",
WS_POPUP | WS_VISIBLE,
// WS_OVERLAPPED |WS_VISIBLE| WS_SYSMENU ,
0,0,
SCREEN_WIDTH,SCREEN_HEIGHT,
0,
0,
hinstance,
0)))
{
return(0);
}
g_hinstance = hinstance;
try
{
Run(msg);
}
catch(Exception e)
{
MessageBox(NULL,e.str,"发生异常!",MB_OK);
}
return int(msg.wParam);
}
/////////////////////////////////////////////////////
//Content: 用于设置断言
/////////////////////////////////////////////////////
#ifndef O_ASSERTH
#define O_ASSERTH
#include <fstream>
//assert的实现函数
template<class E>
inline void _assert(const char* exp,const char* file,int line)
{
std::ofstream os("debug Error.txt" , std::ios_base::app); //打开错误记录文件
os<<file<<" Line:"<<line<<" Exp:"<<exp<<"\n";
throw E(); //抛出异常E
}
//ASSERT宏为用户使用
#ifdef NDEBUG
#define ASSERT(exp,E) (void)0 //非调试模式
#else
#define ASSERT(exp,E) ( exp? (void)0 : (_assert<E>(#exp, __FILE__, __LINE__)) ) //调试模式
#endif
#endif
/*
计时类,用于测量运行时间
作者:sf.tk
最后修改时间:2005.7.2
*/
/////////////////////////////////////////////////
// cxf 修改过
// 2006.1.11
///////////////////////////////////////////////////////
#pragma once
#include <windows.h>
namespace our
{
class Time
{
public:
Time();
Time(int f); //设置帧速
~Time();
void start(); //开始计时
void end(); //停止计时
bool setFrequent(int f); //设置帧速
bool setAlterTime(int time); //设置间隔时间 以毫秒计算
bool isTime() ; //是否是到时间了
void clear() ; //时间重新开始
private:
int frequent; //频率间隔时间
int _start,_end; //起止时间(毫秒)
bool flag; //标志计时状态
};
inline Time::Time(int _f):_start(0),_end(0),flag(false) //设置帧速
{
frequent=300;
if(_f<=0)
{ MessageBox(NULL, "频率为负" ,"时间频率设置异常!",MB_OK);}
frequent=_f;
}
inline Time::Time():_start(0),_end(0),flag(false) ,frequent(300)
{ }
inline Time::~Time()
{ }
inline void Time::start()
{
_start=GetTickCount();
flag=false;
}
inline void Time::end()
{
_end=GetTickCount();
flag=true;
}
inline bool Time::setFrequent(int f) //设置帧速
{
if(f<=0)
{ MessageBox(NULL, "频率为负" ,"时间频率设置异常!",MB_OK);}
frequent=1000/f;
return true;
}
inline bool Time::setAlterTime(int time) //设置间隔时间 以毫秒计算
{
if(time<=0)
{ MessageBox(NULL, "时间间隔为负" ,"时间间隔设置异常!",MB_OK);}
frequent=time;
return true;
}
inline bool Time::isTime() //是否是到时间了
{
if( static_cast<int>(GetTickCount()) -_end >frequent)
{ _end=GetTickCount(); return true;}
else
{ return false;}
}
inline void Time::clear()
{
_start=0;
_end=0;
flag=true;
}
}
/////////////////////////////////////////////////
// Content: 放置常用结构
/////////////////////////////////////////////////
#pragma once
//坐标结构
struct Pos
{
public:
int x;
int y;
public:
Pos():x(0),y(0){}
Pos(int _x,int _y):x(_x),y(_y) {}
void operator=(const Pos& rhs)
{ x = rhs.x; y = rhs.y; }
friend bool operator==(const Pos& lhs,const Pos& rhs) //相等判断
{
return (lhs.x==rhs.x && lhs.y==rhs.y);
}
friend bool operator!=(const Pos& lhs,const Pos& rhs) //相等判断
{
return (lhs.x != rhs.x || lhs.y != rhs.y);
}
//bool operator==(const Pos& rhs) //相等判断
//{ return (x==rhs.x && y==rhs.y); }
friend bool operator <(const Pos& pos1,const Pos& pos2)
{
if(pos2.y > pos1.y) return true;
if(pos1.y > pos2.y) return false;
if(pos2.x > pos1.x) return true;
return false;
}
};
#pragma once
#include <windows.h>
//----------------全局常量
const int SCREEN_WIDTH=800 ;
const int SCREEN_HEIGHT=600;
const int FULLSRCEEN =1;
const int WINDOWSSREEN =0;
//---------------定义类型别名
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
//--------------------宏定义
#define WINDOW_CLASS_NAME "WINCLASS1"
inline bool KEYDOWN(int vk){ return ( ( GetAsyncKeyState(vk) & 0x8000) ? 1 : 0 );}
inline bool KEYUP(int vk) { return ( ( GetAsyncKeyState(vk) & 0x6000) ? 0 : 1 );}
////////// 测试时用的全局宏 /////////////////////////////////