// 1、TTank.cpp: implementation of the TTank class.坦克类
//
//////////////////////////////////////////////////////////////////////
#include \"stdafx.h\"
#include \"TankWar.h\" #include \"TTank.h\" #include \"TWorld.h\" #include \"TExplode.h\" #include \"TBonus.h\" #include \"TBullet.h\"
////////////////////////////////////////////////////////////////////// // Construction/Destruction
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////// // TEnemyTank
/////////////////////////////////////////////////////////////////// EPG TEnemyTank::m_epg[3];
//////////////////////////////////////////////// //敌军坦克移动
void TEnemyTank::Move() {
if(!IsMyTime()) return ;
//防护小于0,还不死吗 if(m_nShield < 0) { Dead(); //玩家增加经验值 g_world.Player(0)->m_nExper += 10 + m_nType * 10; //加点爆炸效果 g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_TANK)); }
/////////////////////////////////////////////////////
//疯子要行动了,怎么动呢?用随机数来决定吧
//玩家没进入范围,什么也不做
if(ABS(m_nX-g_world.Player(0)->GetX())>500 || ABS(m_nY-g_world.Player(0)->GetY())>500) return ;
//产生0到100之间的随机数状态 int status=Rand(0,100);
//保存现在的位置坐标 int x=m_nX,y=m_nY;
//根据产生的状态行动 if(status<2){ //状态小于2,改变一下方向(概率是... 计算一下好像是: 2/100即0.02) m_dir =(DIRECTION) Rand(0,4); }else if(status <3) { //状态小于3,开火(概率是... 计算一下好像是: (3-2)/100即0.01) switch(m_nType) { case FIRE_TANK: //火弹:射程100,威力20 g_world.BulletLink().Add(NEW TBullet(m_nX,m_nY,m_dir,FIRE,20,100)); break; case DOUBLE_MISSILE_TANK: //火弹:射程250,威力15 g_world.BulletLink().Add(NEW TBullet(m_nX,m_nY,m_dir,DMISSILE,15,250)); break; case SINGLE_MISSILE_TANK: //火弹:射程250,威力10 g_world.BulletLink().Add(NEW TBullet(m_nX,m_nY,m_dir,SMISSILE,10,250)); break; } }else { //其它的状态值就表示运行吧(概率是... 计算一下好像是: 100-3/100即0.97) //生命在于运动嘛:) m_nX+=g_nDirXY[m_dir][0]; m_nY+=g_nDirXY[m_dir][1]; }
///////////////////////////////////////////////////// //计算一下上面的移动是否有效
//先假设移动有效
BOOL canMove=TRUE;
//取得自己的边框 RECT rc; GetRect(rc);
////////////////////////////////////////////////////
//根据方向来计算是否与障碍地图上的障碍物碰撞 if(m_dir==DIR_UP){ //方向向上,只检查左上角及右上角坐标是否碰到障碍
if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; else
if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; }else if(m_dir==DIR_DOWN){ //方向向下,只检查左下角及右下角坐标是否碰到障碍
if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; else
if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; }else if(m_dir==DIR_RIGHT){ //方向向右,只检查右下角及右上角坐标是否碰到障碍
if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; else
if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; }else if(m_dir==DIR_LEFT){ //方向向左,只检查左上角及左上角坐标是否碰到障碍
if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; else
if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT))
canMove = FALSE; }
//总不能移到世界范围以外吧
if(m_nY>g_world.GetHeight()-OBSTACLE_HEIGHT || m_nX>g_world.GetWidth()-OBSTACLE_WIDTH || m_nX<0 || m_nY<0) canMove = FALSE;
//有没有碰到其它的NC坦克?不过要记住排除与自己相撞的情况 //疯子也不会疯到这种程度吧
if(g_world.EnemyTankLink().HitTestAll(this)) //停下来,打个招呼 canMove = FALSE;
//撞到了其它障碍物(木箱、邪恶之源)了吗? if(g_world.ObstacleLink().HitTestAll(this)) canMove = FALSE;
//碰到玩家坦克了吗?
if(g_world.Player(0)->HitTest(this)) //当然不能动了 canMove = FALSE;
//移动无效,恢复原值 if(canMove==FALSE) m_nX = x,m_nY=y;
////////////////////////// //计算当前动画帧
m_nCurrentFrame=m_dir; }
////////////////////////////////////////////////// //画坦克
void TEnemyTank::Draw() {
POINT p; p.x = m_nX; p.y = m_nY;
g_world.LPToDP(p);
WGE_Surface.Blt(m_epg[m_nType], m_nCurrentFrame, p.x,p.y ); }
///////////////////////////////////////// //取边框
void TEnemyTank::GetRect(RECT& rc) {
rc.left = m_nX - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyX; rc.top = m_nY - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyY; rc.bottom = rc.top + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwHeight ; rc.right = rc.left + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwWidth ; }
/////////////////////////////////////////////// //
TEnemyTank::TEnemyTank(int x, int y, int nType)
:TSprite(x,y,100,0,CLASS_TENEMYTANK),m_nType(nType) {
switch(nType) {
case FIRE_TANK: //防护力100,速度1/(50/1000) m_nShield = 100; SetDelayTimer(50); break;
case DOUBLE_MISSILE_TANK: //防护力150,速度1/(70/1000) m_nShield = 150; SetDelayTimer(70); break;
case SINGLE_MISSILE_TANK: //防护力100,速度1/(30/1000) m_nShield = 200; SetDelayTimer(30); break; } }
///////////////////////////////////////////////////////// //碰撞是否有效
BOOL TEnemyTank::HitBy(TObject * pObj) {
//////////////////////////////////////////// //与参数对象碰撞 if(HitTest(pObj)) { ////////////////////////////////////////// //参数对象是一个子弹 if(pObj->ClassType()==CLASS_TBULLET) { //转变为子弹对象 TBullet * pBullet = (TBullet*)pObj;
if(pBullet->m_nType == LIGHT) { //是光弹,防护减去光弹的力量 m_nShield -= pBullet->m_nShield ; return TRUE; } } }
return FALSE; }
///////////////////////////////////////////////////////////////////////
// TPlayerTank玩家
///////////////////////////////////////////////////////////////////
EPG TPlayerTank::m_epg[3];
TPlayerTank::TPlayerTank(int x, int y, int nType)
:TSprite(x,y,100,0,CLASS_TPLAYERTANK),m_nType(nType), m_nExper(0),m_nMoney(0),m_nMaxShield(100) {
SetDelayTimer(1); //参考值40,这里是1 }
///////////////////////////////////////////////// //碰撞是否有效
BOOL TPlayerTank::HitBy(TObject * pObj) {
/////////////////////////////////////////// //是否与参数对象碰撞 if(HitTest(pObj)) { if(pObj->ClassType()==CLASS_TBULLET) { //参数对象炮弹 TBullet * pBullet = (TBullet*)pObj; if(pBullet->m_nType == FIRE||pBullet->m_nType DMISSILE||pBullet->m_nType == SMISSILE) { //被火弹,双导弹,单导弹(都是敌方的炮弹)击中,减防护力 // m_nShield -= pBullet->m_nShield ; m_nShield += pBullet->m_nShield ; return TRUE; } }else if(pObj->ClassType()==CLASS_TBONUS) { //参数对象是奖励 TBonus * pBonus = (TBonus*)pObj;
==
switch(pBonus->m_nBonusType) { case BONUS_RECOVER: //恢复物品 m_nShield += 20; //恢复20点 m_nShield = MIN(m_nShield+20,m_nMaxShield); break; case BONUS_EXPER: //经验物品 //m_nExper += 10; //经验值加10 m_nType = MIN((m_nExper/1000),2); //第1000点升一级 m_nMaxShield = 100 + m_nExper/100; m_dwDelayTimer -= m_dwDelayTimer*10/100; break; case BONUS_MONEY: m_nMoney += 100; //得到100元 } return TRUE; } }
return FALSE; }
///////////////////////////////////////////////////// //玩家坦克移动
void TPlayerTank::Move() {
if(!IsMyTime()) return ; /*
if(m_nShield<0) { Dead(); g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_PLAYER)); return;
} */
/////////////////////////////////////////////////// //响应键盘事件,移动坦克
//保存原坐标
int x=m_nX,y=m_nY;
//处理按键
if(WGE_Input.Key()[DIK_UP]){ if(m_nY>0) m_nY -- ;
//调整最大防护 //速度提高10% m_dir = DIR_UP; }else
if(WGE_Input.Key()[DIK_DOWN]){ if(m_nY if(WGE_Input.Key()[DIK_RIGHT]){ if(m_nX BOOL canMove=TRUE; //假设有效先 RECT rc; GetRect(rc); //是否碰撞地形障碍?方法和敌人坦克一样 if(m_dir==DIR_UP){ if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = TRUE; else if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = TRUE; }else if(m_dir==DIR_DOWN){ if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove =TRUE; else if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = TRUE; }else if(m_dir==DIR_RIGHT){ if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEI GHT)) canMove = TRUE; else if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = TRUE; }else if(m_dir==DIR_LEFT){ if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = TRUE; else if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = TRUE; } //碰到了敌人的坦克没有? if(g_world.EnemyTankLink().HitTestAll(this)) canMove = FALSE; //是否碰到了障碍物(木箱或邪恶源) if(g_world.ObstacleLink().HitTestAll(this)) canMove = FALSE; //移动无效,恢复原坐标 if(canMove==FALSE) m_nX = x,m_nY=y; //计算当前动画帧 m_nCurrentFrame=m_dir; //按左CTRL键开火,不过每100ms才能开一次,加弹总要花点时间吧:) static DWORD dwFireTick=GetTickCount(); if(GetTickCount()-dwFireTick>10) //参考值100ms,这里是10ms { if(WGE_Input.Key()[DIK_LCONTROL]||WGE_Input.Key()[DIK_RCONTROL]){ g_world.BulletLink().Add(NEW TBullet(m_nX,m_nY,m_dir,LIGHT,10+m_nMoney/300,100+m_nType*25)); } dwFireTick=GetTickCount(); } //让玩家坦克处于可视区的中央 g_world.GetViewportRect(rc); int height= rc.bottom - rc.top - OBSTACLE_HEIGHT; int width= rc.right - rc.left - OBSTACLE_WIDTH; g_world.SetViewport(m_nX-width/2,m_nY-height/2); } ////////////////////////////////////////////////////// //画玩家坦克 void TPlayerTank::Draw() { POINT p; p.x = m_nX; p.y = m_nY; g_world.LPToDP(p); WGE_Surface.Blt(m_epg[m_nType], m_nCurrentFrame, p.x,p.y ); } /////////////////////////////////////////////// //返回坦克的边框 void TPlayerTank::GetRect(RECT& rc) { rc.left = m_nX - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyX; rc.top = m_nY - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyY; rc.bottom = rc.top + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwHeight ; rc.right = rc.left + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwWidth ; } //2、TBonus.cpp: implementation of the TBonus class.奖励类 // ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TBonus.h\" #include \"TWorld.h\" EPG TBonus::m_epg_bonus[3]; ESound TBonus::m_sound[1]; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TBonus::~TBonus() { } TBonus::TBonus(int x, int y, BONUS nBonusType) :TObject(x,y,CLASS_TBONUS) { m_nBonusType = nBonusType ; m_nCurrentFrame = 0; m_dwDelayTimer= 100; } void TBonus::Draw() { POINT p; p.x = m_nX; p.y = m_nY; g_world.LPToDP(p); WGE_Surface.Blt(m_epg_bonus[m_nBonusType], m_nCurrentFrame, p.x,p.y ); } void TBonus::GetRect(RECT &rc) { rc.left = m_nX m_epg_bonus[m_nBonusType].GetFrame(m_nCurrentFrame)->m_nKeyX; rc.top = m_nY m_epg_bonus[m_nBonusType].GetFrame(m_nCurrentFrame)->m_nKeyY; rc.bottom = rc.top m_epg_bonus[m_nBonusType].GetFrame(m_nCurrentFrame)->m_dwHeight ; rc.right = rc.left m_epg_bonus[m_nBonusType].GetFrame(m_nCurrentFrame)->m_dwWidth ; } void TBonus::Move() { if(!IsMyTime()) return ; if(g_world.Player(0)->HitBy(this)) { Dead(); - - + + } m_sound[0].Play(); } ++m_nCurrentFrame%=m_epg_bonus[m_nBonusType].GetFrameCount(); //3、TBullet.cpp: implementation of the TBullet class.子弹类 // ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TBullet.h\" #include \"TExplode.h\" #include \"Tworld.h\" ESound TBullet::m_sound[4]; EPG TBullet::m_epg[4]; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TBullet::TBullet(int x,int y,DIRECTION dir,BULLET_TYPE nType,int nShield,int nFireRange) :TSprite(x,y,nShield,0,CLASS_TBULLET),m_nType(nType) { SetDelayTimer(50); m_dir = dir; m_nFireRange = nFireRange; ////////////////////////////////////////// //计算音效的音量及均衡 int valume,pan; //音量和均衡 int w,h; //声源与玩家的距离 w = x - g_world.Player(0)->GetX(); h = y - g_world.Player(0)->GetY(); //计算音效的音量及均衡 valume = MAX(ABS(w),ABS(h)) * (-10000/800); pan = w * (10000/400); ///////////////////////////////////////////////// //跟据类型设置速度 switch(nType) { case LIGHT: //玩家的子弹,总会听到声音的 m_nSpeed = 15; //if(valume>-10000) //小于最小音量,没必要播放 m_sound[2].Play(-1000,pan); break; case FIRE: m_nSpeed = 10; if(valume>-10000) m_sound[1].Play(valume,pan); break; case DMISSILE: m_nSpeed = 0; //导弹开始速度为0,然后利用加速度加速 if(valume>-10000) m_sound[0].Play(valume,pan); break; case SMISSILE: m_nSpeed = 0; if(valume>-10000) m_sound[0].Play(valume,pan); break; } } TBullet::~TBullet() { } void TBullet::Move() { if(!IsMyTime()) return ; TLinkNode * pNode; switch(m_nType) { case FIRE: //火弹,由火坦克发射的炮弹 //计算出当前动画帧 m_nCurrentFrame = m_dir*3+(m_nCurrentFrame+1)%3; //超出射程范围,发出死亡信息 if(m_nFireRange<0) { Dead(); } //击中玩家了吗?(即使死了也不让你好过) if(g_world.Player(0)->HitBy(this)) { //击中目标,任务完成 Dead(); } //已经死亡,来个爆炸效果 if(IsDead()) g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_FIRE)); break; case DMISSILE: //双导弹,敌军的导弹 m_nSpeed +=1; //以加速为1的速度运动 m_nCurrentFrame = m_dir; //计算当前动画的帧 //超出射程范围,发出死亡信息 if(m_nFireRange<0) Dead(); //击中玩家? if(g_world.Player(0)->HitBy(this)) Dead(); //死了 if(IsDead()) { ///////////////////////////////////////////////////// //双导弹当然是两个爆炸效果 if(m_dir==DIR_RIGHT||m_dir==DIR_LEFT) { g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY+6,EXPLODE_MISSILE)); g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY-6,EXPLODE_MISSILE)); }else { g_world.ExplodeLink().Add(NEW TExplode(m_nX+6,m_nY,EXPLODE_MISSILE)); g_world.ExplodeLink().Add(NEW TExplode(m_nX-6,m_nY,EXPLODE_MISSILE)); } } break; case SMISSILE: //单导弹,不用注释了吧 m_nSpeed ++; m_nCurrentFrame = m_dir; if(m_nFireRange<0) Dead(); if(g_world.Player(0)->HitBy(this)) Dead(); if(IsDead()) g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_MISSILE)); break; case LIGHT: //我们的武器:) m_nCurrentFrame = 0; //////////////////////////////////////////////////// //计算是否打中在链表中的敌军坦克 //取得链表中的第一辆坦克 pNode=g_world.EnemyTankLink().m_pHeader; while(pNode) //还不到链尾 { //打中了吗? if(pNode->m_pObject->HitBy(this)) //Ok,Mission completed Dead(); //取得下一辆坦克 pNode = pNode->m_pNext; } //////////////////////////////////////////////////// //计算是否打中障碍物 pNode = g_world.ObstacleLink().m_pHeader ; while(pNode) { if(pNode->m_pObject->HitBy(this)) Dead(); pNode = pNode->m_pNext; } if(m_nFireRange<0) { //太远了,没办法 Dead(); } //???,为什么没有爆炸效果? break; default: TRACE(0,\"Invalid bullet id\"); break; } //填加的代码 //取得自己的边框 RECT rc; GetRect(rc); if(m_nType==LIGHT||m_nType==FIRE||m_nType==SMISSILE||m_nType==DMISSILE) { if(m_dir==DIR_UP){ //方向向上,只检查左上角及右上角坐标是否碰到障碍 if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); //子弹消失 else if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); }else if(m_dir==DIR_DOWN){ //方向向下,只检查左下角及右下角坐标是否碰到障碍 if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) Dead(); else if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) Dead(); }else if(m_dir==DIR_RIGHT){ //方向向右,只检查右下角及右上角坐标是否碰到障碍 if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); else if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) Dead(); }else if(m_dir==DIR_LEFT){ //方向向左,只检查左上角及左上角坐标是否碰到障碍 if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); else if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) Dead(); } } //是不是死了? if(!IsDead()) { //没死,那么继续移动 //速度太快了! if(m_nSpeed>24) m_nSpeed = 24; //向前,向前,向前... m_nX+=g_nDirXY[m_dir][0]*m_nSpeed; m_nY+=g_nDirXY[m_dir][1]*m_nSpeed; //改变射程 m_nFireRange -= m_nSpeed; } } ////////////////////////////////////////////// //画子弹 void TBullet::Draw() { POINT p; p.x = m_nX; p.y = m_nY; g_world.LPToDP(p); //把世界逻辑坐标转换到设备坐标 WGE_Surface.Blt(m_epg[m_nType], m_nCurrentFrame, p.x,p.y ); } /////////////////////////////////////////////// //取得碰撞矩形 void TBullet::GetRect(RECT& rc) { rc.left = m_nX - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyX; rc.top = m_nY - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyY; rc.bottom = rc.top + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwHeight ; rc.right = rc.left + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwWidth ; } // TExplode.cpp: implementation of the TExplode class. // ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TExplode.h\" #include \"TWorld.h\" EPG TExplode::m_epg[4]; ESound TExplode::m_sound[3]; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TExplode::TExplode(int x,int y,EXPLODE nType) :TObject(x,y,CLASS_TEXPLODE),m_nType(nType),m_nCurrentFrame(0) { SetDelayTimer(100); switch(nType) { case EXPLODE_TANK: case EXPLODE_BOX: m_sound[0].Play(); break; case EXPLODE_PLAYER: //玩家爆炸动画慢一点,与声音配合 SetDelayTimer(200); m_sound[0].Play(); break; } } TExplode::~TExplode() { } /////////////////////////////////////////////// //移动 void TExplode::Move() { if(!IsMyTime()) return ; /////////////////////////////////////////// //计算 if(m_nType==EXPLODE_PLAYER) { //玩家爆炸应该壮烈一点 if(m_nCurrentFrame>=m_epg[3].GetFrameCount()-1) { //先来一个小爆炸 m_sound[1].Play(); //然后变成大爆炸 m_nType = EXPLODE_TANK; m_nCurrentFrame = 0; return ; } }else{ //一般爆炸就可以了 if(m_nCurrentFrame>=m_epg[m_nType].GetFrameCount()-1) { //爆炸消失 Dead(); return ; } } m_nCurrentFrame ++; } /////////////////////////////////////////////// //画出爆炸 void TExplode::Draw() { POINT p; p.x = m_nX; p.y = m_nY; g_world.LPToDP(p); if(m_nType==EXPLODE_PLAYER) { WGE_Surface.Blt(m_epg[3],m_nCurrentFrame, p.x,p.y); }else WGE_Surface.Blt(m_epg[m_nType], m_nCurrentFrame, p.x,p.y ); } //////////////////////////////////////////// //取得动画边框 void TExplode::GetRect(RECT& rc) { int i; if(m_nType==EXPLODE_PLAYER) i = 3; else i = m_nType; rc.left = m_nX - m_epg[i].GetFrame(m_nCurrentFrame)->m_nKeyX; rc.top = m_nY - m_epg[i].GetFrame(m_nCurrentFrame)->m_nKeyY; rc.bottom = rc.top + m_epg[i].GetFrame(m_nCurrentFrame)->m_dwHeight ; rc.right = rc.left + m_epg[i].GetFrame(m_nCurrentFrame)->m_dwWidth ; } // 4、TLink.cpp: implementation of the TLink class.连接类 // ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TLink.h\" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TLink::TLink() { m_pHeader = NULL; } TLink::~TLink() { DeleteAll(); } void TLink::AddHeader(TObject * pObject) { ASSERT(pObject); TLinkNode * pAddNode = NEW TLinkNode(pObject); pAddNode->m_pNext = m_pHeader; m_pHeader = pAddNode; } void TLink::AddTail(TObject * pObject) { ASSERT(pObject); TLinkNode * pAddNode = NEW TLinkNode(pObject); if(m_pHeader==NULL) { m_pHeader = pAddNode ; m_pHeader->m_pNext = NULL; }else { TLinkNode * pNode = m_pHeader ; while(pNode->m_pNext) { ASSERT(pObject!=pNode->m_pObject); pNode = pNode->m_pNext ; } pNode->m_pNext = pAddNode ; pAddNode->m_pNext = NULL; } } void TLink::Add(TObject * pObject) { AddHeader(pObject); } void TLink::DeleteAll() { TLinkNode * pNode = m_pHeader; while(pNode) { m_pHeader = pNode->m_pNext ; delete pNode ; pNode = m_pHeader; } } void TLink::Delete(TObject * pObject) { TLinkNode * pPreNode = m_pHeader ; if(m_pHeader->m_pObject == pObject) { m_pHeader = m_pHeader->m_pNext ; delete pPreNode ; return ; } TLinkNode * pNode = pPreNode->m_pNext ; while(pNode) { if(pNode->m_pObject == pObject) { pPreNode->m_pNext = pNode->m_pNext ; delete pNode; return ; } pPreNode = pNode ; pNode = pNode->m_pNext ; } } /////////////////////////////// //画出链表中所有的对象 void TLink::DrawAll() { TLinkNode * pNode = m_pHeader; while(pNode) { pNode->m_pObject->Draw(); pNode = pNode->m_pNext ; } } //////////////////////////////////////////// //移动链表中所有的对象 void TLink::MoveAll() { //取得第一个结点 TLinkNode * pNode = m_pHeader; //循环整个链表 while(pNode) { if(pNode->m_pObject->IsDead()) { //该对象已经被击毁,从链表中删除 TObject * pDeleteObj = pNode->m_pObject; pNode = pNode->m_pNext ; Delete(pDeleteObj); } else { //调用该对象的Move()函数 pNode->m_pObject->Move(); pNode = pNode->m_pNext ; } } } BOOL TLink::HitTestAll(TObject * pObj) { TLinkNode * pNode = m_pHeader; BOOL bHit = FALSE; while(pNode && bHit==FALSE) { if(pNode->m_pObject != pObj) bHit=pNode->m_pObject->HitTest(pObj); pNode = pNode->m_pNext ; } return bHit; } //5、TObject.cpp: implementation of the TObject class.物体类 // ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TObject.h\" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TObject::TObject(int x,int y,CLASS_TYPE nClassType) :m_nX(x),m_nY(y),m_dwLastTickCount(0),m_dwDelayTimer(0), m_nClassType(nClassType),m_bIsDead(FALSE) { } TObject::~TObject() { } ///////////////////////////////////////////// //该对象是否与另它对象碰撞 BOOL TObject::HitTest(TObject* object) { RECT rc1,rc2,temp; GetRect(rc1); object->GetRect(rc2); return IntersectRect(&temp,&rc1,&rc2); } ////////////////////////////////////////////// //是否该我动了? BOOL TObject::IsMyTime() { if(GetTickCount()-m_dwLastTickCount>=m_dwDelayTimer) { m_dwLastTickCount = GetTickCount(); return TRUE; } return FALSE; } //6、TObstacle.cpp: implementation TObstacle class.障碍物类 // ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TObstacle.h\" #include \"TBonus.h\" #include \"TBullet.h\" #include \"TExplode.h\" #include \"TWorld.h\" EPG TObstacle::m_epg[2]; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// of the TObstacle::TObstacle(int x,int y,OBSTACLE nType) :TObject(x,y,CLASS_TOBSTACLE),m_nType(nType),m_nCurrentFrame(0) { SetDelayTimer(100); switch(m_nType) { case OBSTACLE_BOX: //木箱 //硬度100 m_nHardiness = 100; break; case OBSTACLE_END: //邪恶源 //硬度1000! ,非常硬 m_nHardiness = 1000; break; } } TObstacle::~TObstacle() { } void TObstacle::Destroy() { m_epg[0].Destroy(); m_epg[1].Destroy(); } ///////////////////////////////////////////// //击中测试 BOOL TObstacle::HitBy(TObject * pObj) { if(HitTest(pObj)) { ////////////////////////////////////// //只能被光弹击中 if(pObj->ClassType()==CLASS_TBULLET) { TBullet * pBullet = (TBullet*)pObj; if(pBullet->m_nType == LIGHT) { m_nHardiness -= pBullet->m_nShield ; return TRUE; } } } return FALSE; } ////////////////////////////////////////// //移动 void TObstacle::Move() { if(!IsMyTime()) return ; //计算当前帧 ++m_nCurrentFrame%=m_epg[m_nType].GetFrameCount(); if(m_nHardiness<0){ //消失 Dead(); if(m_nType == OBSTACLE_END) { //邪恶源被击毁,过关 //强烈爆炸 g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY, EXPLODE_PLAYER)); //经验值+1000 g_world.Player(0)->m_nExper += 1000; //进入下一关 g_game_status = GAME_STAGECLEAR; }else if(m_nType == OBSTACLE_BOX) { //产生一个随机物品 g_world.BonusLink().Add(NEW TBonus(m_nX,m_nY, (BONUS)Rand(0,3))); //然后爆炸 g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY, EXPLODE_BOX)); } } } /////////////////////////////////////////// //画出来 void TObstacle::Draw() { POINT p; p.x = m_nX; p.y = m_nY; g_world.LPToDP(p); WGE_Surface.Blt(m_epg[m_nType], m_nCurrentFrame, p.x,p.y ); } ///////////////////////////////////////////////////// //碰撞边框 void TObstacle::GetRect(RECT& rc) { rc.left = m_nX - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyX; rc.top = m_nY - m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_nKeyY; rc.bottom = rc.top + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwHeight ; rc.right = rc.left + m_epg[m_nType].GetFrame(m_nCurrentFrame)->m_dwWidth ; } // TSprite.cpp: implementation of the TSprite class. 精灵类// ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TSprite.h\" int g_nDirXY[4][2] = { {1,0} , {0,1},{-1,0},{0,-1} }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// TSprite::TSprite(int x,int y,int nShield,int nStatus,CLASS_TYPE nClassType) :TObject(x,y,nClassType),m_nShield(nShield),m_nStatus(nStatus),m_dir(DIR_LEFT),m_nCurrentFrame(0) { } TSprite::~TSprite() { } // TWorld.cpp: implementation of the TWorld class. 世界类// ////////////////////////////////////////////////////////////////////// #include \"stdafx.h\" #include \"TankWar.h\" #include \"TWorld.h\" #include \"TBonus.h\" #include \"TObstacle.h\" TWorld g_world; //全局唯一的世界对象 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// EGroupPic TWorld::m_grp_terrain; EPG TWorld::m_epg_icon[3]; TWorld::TWorld() :m_pTerrainMap(NULL),m_pObstacleMap(NULL) { } TWorld::~TWorld() { DestroyWorld(); } //////////////////////////////////////////////// //加载地形图像 BOOL TWorld::LoadTerrainPicture(LPCSTR szGrpFile,EDataFile* pDat) { if(m_grp_terrain.Load(szGrpFile,pDat)==FALSE){ MessageBox(NULL,szGrpFile,\"加载错误\ return FALSE; } return TRUE; } //////////////////////////////////////////////////// //加载图标图像 BOOL TWorld::LoadIconPicture(LPCSTR szFile,int nIndex,EDataFile* pDat) { ASSERT(nIndex<3); if(m_epg_icon[nIndex].Load(szFile,pDat)==FALSE) { MessageBox(NULL,szFile,\"加载错误\ TRACE(0,\"Load %s error\ return FALSE; } return TRUE; } /////////////////////////////////////////// //删除世界的资源 void TWorld::DestroyResource() { m_grp_terrain.Destroy(); m_epg_icon[0].Destroy(); m_epg_icon[1].Destroy(); m_epg_icon[2].Destroy(); } /////////////////////////////////////////// //加载新的地图然后开始这一关 BOOL TWorld::LoadStage(int nStage,EDataFile * pDat) { if(nStage == 0) { //已经打完三关,重新开始 m_nStage = 1; } else { m_nStage = nStage; } //删除各对象链表数据 m_EnemyTankLink.DeleteAll(); m_BonusLink.DeleteAll(); m_ObstacleLink.DeleteAll(); m_BulletLink.DeleteAll(); m_ExplodeLink.DeleteAll(); char buf[255]; sprintf(buf,MEDIA(\"第%d关.map\"),m_nStage); EPackFile map; //打开地图文件 if(map.Open(buf,pDat)==FALSE) { MessageBox(NULL,buf,\"加载错误\ TRACE(0,\"加载地图文件错误:%s\ return FALSE; } //读取地图ID DWORD dwID; map.Read(&dwID,sizeof(dwID)); if(dwID!=MAP_ID) { MessageBox(NULL,buf,\"加载错误\ TRACE(0,\"非法的地图文件:%s\ return FALSE; } //读取地图高度和宽度 INT32 nWidth,nHeight; map.Read(&nWidth,sizeof(nWidth)); map.Read(&nHeight,sizeof(nHeight)); //为地形地图分配内存 if(m_pTerrainMap) MemFree(m_pTerrainMap); m_pTerrainMap = (TERRAIN_INDEX*)MemAlloc(nWidth * nHeight sizeof(TERRAIN_INDEX)); if(m_pTerrainMap==NULL) return FALSE; //为障碍地图分配内存 if(m_pObstacleMap) MemFree(m_pObstacleMap); m_pObstacleMap (OBSTACLE_ID*)MemAlloc(4*nWidth*nHeight*sizeof(OBSTACLE_ID)); if(m_pObstacleMap==NULL) return FALSE; //读取地形数据 map.Read(m_pTerrainMap,nWidth * nHeight * sizeof(TERRAIN_INDEX)); m_nMaxVertTerrain = nHeight; m_nMaxHorzTerrain = nWidth; * = //计算出游戏世界的大小 m_nWorldHeight = nHeight * TERRAIN_HEIGHT; m_nWorldWidth = nWidth * TERRAIN_WIDTH; //设置可视区 SetupViewport(0,0,WGE_Surface.m_pBmp->w,WGE_Surface.m_pBmp->h); //读取障碍物数据和物体数据 //障碍地图高度与宽度分别是地形地图的高度与宽度的两倍 nWidth *= 2; nHeight *= 2; for(int h=0;h TBonus(w*OBSTACLE_WIDTH,h*OBSTACLE_HEIGHT, BONUS_MONEY) ); break; case 7: //恢复物品 //加入奖励链表 g_world.BonusLink().Add( NEW TBonus(w*OBSTACLE_WIDTH,h*OBSTACLE_HEIGHT, BONUS_RECOVER) ); break; case 4: //木箱 //加入障碍链表 g_world.ObstacleLink().Add( NEW TObstacle(w*OBSTACLE_WIDTH,h*OBSTACLE_HEIGHT, OBSTACLE_BOX) ); //m_pObstacleMap[w+h*nWidth] = obstacle_id; break; case 9: //邪恶之源 //加入障碍链表,这可是最大的障碍 g_world.ObstacleLink().Add( NEW TObstacle(w*OBSTACLE_WIDTH,h*OBSTACLE_HEIGHT, OBSTACLE_END) ); //m_pObstacleMap[w+h*nWidth] = obstacle_id; break; case 8: //玩家起始位置 m_pPlayer[0]->SetXY(w*OBSTACLE_WIDTH,h*OBSTACLE_HEIGHT); break; case 1: //双弹坦克 //加入NC坦克链表 g_world.EnemyTankLink().Add( NEW TEnemyTank(w*OBSTACLE_WIDTH, h*OBSTACLE_HEIGHT, DOUBLE_MISSILE_TANK) ); break; case 2: //单弹坦克 //加入NC坦克链表 g_world.EnemyTankLink().Add( NEW TEnemyTank(w*OBSTACLE_WIDTH, h*OBSTACLE_HEIGHT, SINGLE_MISSILE_TANK) ); break; case 3: //火坦克 //加入NC坦克链表 g_world.EnemyTankLink().Add( NEW TEnemyTank(w*OBSTACLE_WIDTH, h*OBSTACLE_HEIGHT, FIRE_TANK) ); break; case 0x81: //石头高地障碍 //在障碍地图中设置该位置为障碍 m_pObstacleMap[w+h*nWidth] = obstacle_id; break; default: //无障碍 m_pObstacleMap[w+h*nWidth] = 0; } } } //关闭地图文件 map.Close(); //移动可视区到玩家坦克处 RECT rc; g_world.GetViewportRect(rc); int height= rc.bottom - rc.top - OBSTACLE_HEIGHT; int width= rc.right - rc.left - OBSTACLE_WIDTH; g_world.SetViewport(Player(0)->GetX()-width/2,Player(0)->GetY()-height/2); //画出场景,显示Ready DrawWorld(); sprintf(buf,\"Stage %d Ready\ WGE_Surface.OutTextXY((400-strlen(buf)*8)/2,140,buf); WGE_pScreen->Update(); //加载背景音乐 sprintf(buf,MEDIA(\"stage%d.mid\"),m_nStage); VERIFY(g_back_music.LoadMidi(buf,pDat)); g_back_music.SetRepeats(99999); g_back_music.Play(); //等待3秒 DWORD dwTimer = GetTickCount(); while(GetTickCount()-dwTimer < 3000); //开始游戏 g_game_status = GAME_PLAY; return TRUE; } /////////////////////////////////////////////// //创建一个新世界 BOOL TWorld::CreateWorld(EDataFile *pDat) { //删除旧游戏世界 DestroyWorld(); //创建一个新玩家 m_pPlayer[0] = NEW TPlayerTank(0,0,GREEN_TANK); //加载第1关地图 return LoadStage(1,pDat); } //////////////////////////////////////////////// //删除旧的世界 void TWorld::DestroyWorld() { //删除地形地图 if(m_pTerrainMap){ MemFree(m_pTerrainMap); m_pTerrainMap = NULL; } //删除障碍地图 if(m_pObstacleMap){ MemFree(m_pObstacleMap); m_pObstacleMap = NULL; } m_nViewportHeight = m_nViewportWidth = 0; m_nViewportTop = m_nViewportLeft = 0; //删除当前的玩家 if( m_pPlayer[0]){ delete m_pPlayer[0]; m_pPlayer[0]=NULL; } //删除所有对象 m_EnemyTankLink.DeleteAll(); m_BonusLink.DeleteAll(); m_ObstacleLink.DeleteAll(); m_BulletLink.DeleteAll(); m_ExplodeLink.DeleteAll(); } ////////////////////////////////////////// //设置可视区相对设备坐标的位置及大小 void TWorld::SetupViewport(int origin_x,int origin_y,int width, int height) { m_nViewportOriginX = origin_x; m_nViewportOriginY = origin_y; //调整可视区的高度及宽度不能超过世界的大小和屏幕的大小 int minHeight,minWidth; minWidth = WGE_Surface.m_pBmp->w minHeight = WGE_Surface.m_pBmp->h if(origin_x+width>minWidth) width -= origin_x + width - minWidth; if(origin_y+height>minHeight) height -= origin_y + height - minHeight; m_nViewportHeight = height; m_nViewportWidth = width; } ///////////////////////////////////////////////// //滚动可视区域 void TWorld::ScrollViewport(int dx, int dy) { SetViewport(m_nViewportLeft + dx,m_nViewportTop + dy); } ///////////////////////////////////////////////// //设置可视区在游戏世界中的坐标 void TWorld::SetViewport(int x, int y) { //设置可视区的坐标 m_nViewportTop = y; m_nViewportLeft = x; //调整可视区坐标 if(m_nViewportTop<0) m_nViewportTop = 0; if(m_nViewportTop + m_nViewportHeight >= m_nWorldHeight) m_nViewportTop = m_nWorldHeight - m_nViewportHeight -1; if(m_nViewportLeft < 0) m_nViewportLeft = 0; if(m_nViewportLeft + m_nViewportWidth >= m_nWorldWidth) m_nViewportLeft = m_nWorldWidth - m_nViewportWidth -1; } /////////////////////////////////////////// //画出整个世界 void TWorld::DrawWorld() { //保存屏幕缓冲面的剪载框 1, 1); RECT rcClip; rcClip.left = WGE_Surface.m_pBmp->clip->left; rcClip.right =WGE_Surface.m_pBmp->clip->right; rcClip.top = WGE_Surface.m_pBmp->clip->top; rcClip.bottom =WGE_Surface.m_pBmp->clip->bottom; //取得可视区矩形 RECT rcViewport; GetViewportRect(rcViewport); //然后转换为设备坐标 LPToDP(rcViewport); //把可视区作为屏幕缓冲面的裁剪框 WGE_Surface.SetClip((short)rcViewport.left,(short)rcViewport.top, (short)rcViewport.right,(short)rcViewport.bottom); //计算在可视区中显示的地形坐标范围 int top = m_nViewportTop /TERRAIN_WIDTH; int bottom = (m_nViewportTop + m_nViewportHeight) /TERRAIN_HEIGHT; int left = m_nViewportLeft/TERRAIN_HEIGHT; int right = (m_nViewportLeft + m_nViewportWidth) / TERRAIN_WIDTH; //画地形 for(int h=top;h<=bottom ;h++) for(int w=left;w<=right;w++) { WGE_Surface.Blt(m_grp_terrain, m_pTerrainMap[h*m_nMaxHorzTerrain+w], w*TERRAIN_WIDTH - m_nViewportLeft+m_nViewportOriginX - } h*TERRAIN_HEIGHT- m_nViewportTop+m_nViewportOriginY - //画障碍物 m_ObstacleLink.DrawAll(); //画玩家 if(!m_pPlayer[0]->IsDead()) m_pPlayer[0]->Draw(); //画所有的敌军坦克 m_EnemyTankLink.DrawAll(); //画奖励物品 m_BonusLink.DrawAll(); //画子弹 m_BulletLink.DrawAll(); //画爆炸效果 m_ExplodeLink.DrawAll(); //恢复裁剪框 WGE_Surface.SetClip((short)rcClip.left,(short)rcClip.top, (short)rcClip.right,(short)rcClip.bottom); //======================================================= //画分数条 //------------------------------------------------------- char msg[80]; //设置字符色为绿色 WGE_Surface.SetDrawColor(0,255,0); //计算出分数条的位置 int x,y; x = WGE_Surface.m_pBmp->w-160; y = 2; //准备分数条字符串 sprintf(msg,\" %05d %05d %3d/%3d\ Player(0)->m_nExper, Player(0)->m_nMoney, Player(0)->m_nShield, Player(0)->m_nMaxShield); //画分数条上的图标 WGE_Surface.Blt(m_epg_icon[0],Player(0)->m_nType,x,y); WGE_Surface.Blt(m_epg_icon[1],0,x+46,y); WGE_Surface.Blt(m_epg_icon[2],0,x+94,y); //画分数条字符 WGE_Surface.OutTextXY(x,y,msg); } /////////////////////////////////////////////// //取得可视区在世界坐标中的矩形框 void TWorld::GetViewportRect(RECT& rect) { rect.left = m_nViewportLeft ; rect.top = m_nViewportTop ; rect.right = m_nViewportLeft + m_nViewportWidth ; rect.bottom = m_nViewportTop + m_nViewportHeight ; } ////////////////////////////////////////////////////////// //逻辑坐标转换到设备坐标(即把游戏坐标转换到屏幕坐标) void TWorld::LPToDP(RECT &rc) { rc.top -= m_nViewportTop - m_nViewportOriginY; rc.left -= m_nViewportLeft - m_nViewportOriginX; rc.bottom -= m_nViewportTop - m_nViewportOriginY; rc.right -= m_nViewportLeft - m_nViewportOriginX; } ////////////////////////////////////////////////////////// //逻辑坐标转换到设备坐标(即把游戏坐标转换到屏幕坐标) void TWorld::LPToDP(POINT &pt) { pt.x -= m_nViewportLeft - m_nViewportOriginX; pt.y -= m_nViewportTop - m_nViewportOriginY; } ////////////////////////////////////////////////// //让精灵移动 BOOL TWorld::Move() { if(!m_pPlayer[0]->IsDead()) //没死,Move m_pPlayer[0]->Move(); else { //死了,GAME OVER g_game_status = GAME_OVER; } //处理其它对象的行动 m_BonusLink.MoveAll(); m_ObstacleLink.MoveAll(); m_EnemyTankLink.MoveAll(); m_BulletLink.MoveAll(); m_ExplodeLink.MoveAll(); return TRUE; } 因篇幅问题不能全部显示,请点此查看更多更全内容