📄 ttank.cpp
字号:
// 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(40);
}
/////////////////////////////////////////////////
//碰撞是否有效
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 ;
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; //速度提高10%
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 -- ;
m_dir = DIR_UP;
}else
if(WGE_Input.Key()[DIK_DOWN]){
if(m_nY<g_world.GetHeight()-OBSTACLE_HEIGHT)
m_nY += 1;
m_dir = DIR_DOWN;
}else
if(WGE_Input.Key()[DIK_LEFT]){
if(m_nX>0) m_nX -= 1;
m_dir = DIR_LEFT;
}else
if(WGE_Input.Key()[DIK_RIGHT]){
if(m_nX<g_world.GetWidth()-OBSTACLE_WIDTH)
m_nX += 1;
m_dir = DIR_RIGHT;
}
/////////////////////////////////////////////////////////
//计算上面的移动是否有效
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(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>100)
{
if(WGE_Input.Key()[DIK_LCONTROL]){
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 ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -