📄 monster.cpp
字号:
/**
* File : Monster.cpp
* Author : Kevin Lynx
* Date : 2007/7/31
*/
#include "stdafx.h"
#include "Monster.h"
#include "Player.h"
#include "World.h"
#include "AnimManager.h"
#include "Bullet.h"
#include "App.h"
#include "Bonus.h"
Monster::Monster( int monsterType ) :
Sprite( monsterType, 3 )
{
}
Monster::~Monster()
{
}
bool Monster::init( ISceneManager *smgr, IAnimatedMesh *mesh, ITexture *texture )
{
if( !Sprite::init( smgr, mesh, texture ) )
{
return false;
}
/// init the animation
if( mType == World::MONSTER_2 )
{
mAnimMgr->addState( AS_NORMAL, 0, 123, 50, true );
mAnimMgr->addState( AS_RUN, 124, 247, 100, true );
}
if( mType == World::MONSTER_3 )
{
mAnimMgr->addState( AS_NORMAL, 0, 123, 50, true );
mAnimMgr->addState( AS_RUN, 124, 247, 100, true );
}
if( mType == World::MONSTER_4 )
{
mAnimMgr->addState( AS_NORMAL, 0, 247, 50, true );
mAnimMgr->addState( AS_RUN, 248, 371, 100, true );
}
mAnimMgr->setCurrentState( AS_RUN );
initDirection();
/// init the status
mStatus = SpriteStatus::NORMAL;
/// hp
mHP = getInitHP( mType );
/// add score
mAddScore = getInitScore( mType );
return true;
}
void Monster::update( float dt )
{
int lastStatus = mStatus;
/// deal with the status
if( mStatus != SpriteStatus::NORMAL )
{
if( SpriteStatus::update( mType ) )
{
mNode->setVisible( true );//normal
}
}
if( lastStatus == SpriteStatus::DEAD &&
mStatus != SpriteStatus::DEAD )
{
/// born, set a new position
float x, y, z;
y = 30;
World::GetSingletonPtr()->getValidPos( x, z );
this->setPosition( vector3df( x, y, z ) );
}
if( mStatus == SpriteStatus::DEAD )
{
return ;
}
if( mStatus == SpriteStatus::BORN_HIDE &&
mNode->isVisible() )
{
mNode->setVisible( false );
}
if( mStatus == SpriteStatus::BORN_SHOW &&
!mNode->isVisible() )
{
mNode->setVisible( true );
}
vector3df lastDir = mDir;
if( mType == World::MONSTER_2 ||
mType == World::MONSTER_4 )
{
ai1();
}
if( mType == World::MONSTER_3 )
{
ai2();
}
/// rotate the monster if the direction is different from the last dir
if( mDir != lastDir )
{
rotate( mDir );
}
Sprite::move( dt );
/// check whether it can fire
if( canFire() )
{
BulletManager::GetSingletonPtr()->createMonsterBullet(
mNode->getPosition(), mDir );
mLastFireTime = App::GetSingletonPtr()->getRealTime();
}
}
void Monster::ai1()
{
if( ( this->getArrayPos() == mLastArrayPos ||
!World::GetSingletonPtr()->isCenterPos( mNode->getPosition() ) ) &&
mDir != vector3df( 0, 0, 0 ) )
{
return ;
}
vector3df lastDir = mDir;
Player *player = Player::GetSingletonPtr();
World *world = World::GetSingletonPtr();
int pax, paz, ax, az;
player->getArrayPos( pax, paz );
this->getArrayPos( ax, az );
int h_dir = pax - ax == 0 ? 0 : ( pax - ax ) / abs( pax - ax );
int v_dir = paz - az == 0 ? 0 : ( paz - az ) / abs( paz - az );
if( h_dir == 0 && v_dir == 0 )
{
/// and now, the monster reached the player's position
/// for further ai, i set the dir to 0, so later,
/// the monster's direction can be calculated again
mDir.set( 0.0f, 0.0f, 0.0f );
return ;
}
//v_dir = -v_dir; //because array +z is different from world +z
if( v_dir == 0 )
{
if( world->canReach( ax + h_dir, az ) )
{
mDir.set( float( h_dir ), 0, 0 );
}
else
{
// donot change the direction at the monment
}
goto goon;
}
else if( h_dir == 0 )
{
if( world->canReach( ax, az + v_dir ) )
{
mDir.set( 0, 0, float( -v_dir ) );
}
else
{
// donot change the direction at the monment
}
goto goon;
}
if( rand() % 100 > 50 )
{
/// choose h_dir
if( ax + h_dir != mLastArrayPos.X && world->canReach( ax + h_dir, az ) )
{
mDir.set( float( h_dir ), 0.0f, 0.0f );
}
else
{
/// choose v_dir
if( az + v_dir != mLastArrayPos.Y && world->canReach( ax, az + v_dir ) )
{
mDir.set( 0.0f, 0.0f, float( -v_dir ) );//because array +z is world -z
}
else if( !world->canReach( ax, az + (int)mDir.Z ) )
{
/// no way can be reached anymore, so just back
mDir = -mDir;
}
}
}
else
{
/// choose v_dir
if( az + v_dir != mLastArrayPos.Y && world->canReach( ax, az + v_dir ) )
{
mDir.set( 0.0f, 0.0f, float( -v_dir ) );//because array +z is world -z
}
else
{
/// choose h_dir
if( ax + h_dir != mLastArrayPos.X && world->canReach( ax + h_dir, az ) )
{
mDir.set( float( h_dir ), 0.0f, 0.0f );
}
else if( !world->canReach( ax + (int)mDir.X, az ) )
{
/// no way can be reached anymore, so just back
mDir = -mDir;
}
}
}
goon:
mLastArrayPos.set( ax, az );
mSpeed = mType == World::MONSTER_2 ? DEFAULT_MONSTER1_SPEED :
DEFAULT_MONSTER3_SPEED ;
if( equals( fabs( mDir.X ), 1.0f ) )
{
if( !world->canReach( ax + (int)mDir.X, az ) )
{
int outZDir;
if( searchNewVDir( ax, az, outZDir ) )
{
mDir.set( 0, 0, -(float)outZDir );
}
else
{
mDir = -mDir;
}
}
}
else if( equals( fabs( mDir.Z ), 1.0f ) )
{
if( !world->canReach( ax, az - (int)mDir.Z ) )
{
//invalid, so search a new direction
int outXDir;
if( searchNewHDir( ax, az, outXDir ) )
{
mDir.set( (float)outXDir, 0, 0 );
}
else
{
//mDir.set( 0, 0, float( v_dir ) );//back
mDir = -mDir;
}
}
}
}
void Monster::ai2()
{
if( this->getArrayPos() == mLastArrayPos ||
!World::GetSingletonPtr()->isCenterPos( mNode->getPosition() ) )
{
World *world = World::GetSingletonPtr();
int ax, az;
this->getArrayPos( ax, az );
cout << ax << " " << az << " dir " << mDir.X << " " << mDir.Z << endl;
return ;
}
World *world = World::GetSingletonPtr();
int ax, az;
this->getArrayPos( ax, az );
int p = 0;
vector3df v[4];
v[p].set( -mDir ); //back direction, the worst solution
if( world->canReach( ax + (int)mDir.X, az - (int)mDir.Z ) )
{
//it's right that you can go on with the current direction
v[++p].set( mDir );
}
if( equals( fabs( mDir.X ), 1.0f ) )// mDir = (1,0,0) or (-1,0,0)
{
if( world->canReach( ax, az + 1 ) )
{
v[++p].set( 0, 0, -1 );
}
if( world->canReach( ax, az - 1 ) )
{
v[++p].set( 0, 0, 1 );
}
}
else if( equals( fabs( mDir.Z ), 1.0f ) )//mDir = (0,0,1) or (0,0,-1)
{
if( world->canReach( ax + 1, az ) )
{
v[++p].set( 1, 0, 0 );
}
if( world->canReach( ax - 1, az ) )
{
v[++p].set( -1, 0, 0 );
}
}
// get a random direction
if( p == 0 )
{
mDir.set( v[0] );
}
else
{
int index = rand() % ( p ) + 1;
mDir.set( v[index] );
}
// set speed
mSpeed = DEFAULT_MONSTER2_SPEED;
mLastArrayPos.set( ax, az );
cout << "AI 2 is RUNNING" << endl;
}
bool Monster::searchNewHDir( int ax, int az, int &outXDir )
{
World *world = World::GetSingletonPtr();
if( world->canReach( ax - 1, az ) )
{
outXDir = -1;
return true;
}
if( world->canReach( ax + 1, az ) )
{
outXDir = 1;
return true;
}
return false;
}
bool Monster::searchNewVDir( int ax, int az, int &outZDir )
{
World *world = World::GetSingletonPtr();
if( world->canReach( ax, az - 1 ) )
{
outZDir = -1;
return true;
}
if( world->canReach( ax, az + 1 ) )
{
outZDir = 1;
return true;
}
return false;
}
bool Monster::canFire()
{
float prob;
if( mType == World::MONSTER_2 )
{
prob = MF_MONSTER2;
}
if( mType == World::MONSTER_3 )
{
prob = MF_MONSTER3;
}
if( mType == World::MONSTER_4 )
{
prob = MF_MONSTER4;
}
if( rand() % 100 >= prob * 100 &&
App::GetSingletonPtr()->getRealTime() - mLastFireTime > mFireDelay )
{
return true;
}
return false;
}
void Monster::initDirection()
{
World *world = World::GetSingletonPtr();
int ax, az;
this->getArrayPos( ax, az );
if( world->canReach( ax - 1, az ) )
{
mDir.set( -1, 0, 0 );
}
else if( world->canReach( ax + 1, az ) )
{
mDir.set( 1, 0, 0 );
}
else if( world->canReach( ax, az - 1 ) )
{
mDir.set( 0, 0, 1 );
}
else if( world->canReach( ax, az + 1 ) )
{
mDir.set( 0, 0, -1 );
}
rotate( mDir );
}
void Monster::hurt( int damage )
{
mHP -= damage;
if( mHP <= 0 )
{
mHP = getInitHP( mType );
changeStatus( SpriteStatus::NORMAL, mType );
mNode->setVisible( false );
/// create some bonus for the player's cool killing .;D
BonusManager::GetSingletonPtr()->createBonus( this->getPosition() );
}
}
bool Monster::isNormalStatus()
{
return mStatus == SpriteStatus::NORMAL;
}
int Monster::getInitHP( int type )
{
int hp;
switch( type )
{
case Sprite::ST_MONSTER_2 :
hp = MONSTER_2_HP ;
break;
case Sprite::ST_MONSTER_3:
hp = MONSTER_3_HP;
break;
case Sprite::ST_MONSTER_4:
hp = MONSTER_4_HP;
break;
}
return hp;
}
int Monster::getInitScore( int type )
{
int score;
switch( type )
{
case Sprite::ST_MONSTER_2 :
score = MONSTER_2_SCORE ;
break;
case Sprite::ST_MONSTER_3:
score = MONSTER_3_SCORE;
break;
case Sprite::ST_MONSTER_4:
score = MONSTER_4_SCORE;
break;
}
return score;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -