Player.cpp
上传用户:lian_0917
上传日期:2013-03-24
资源大小:1151k
文件大小:17k
- /********************************************************************
- created: 2004/05/25
- created: 25:5:2004 15:07
- filename: d:WorksGamelibPlayer.cpp
- file path: d:WorksGamelib
- file base: Player
- file ext: cpp
- author: lazybug
- purpose: CPlayer类得实现部分
- *********************************************************************/
- #include "stdafx.h"
- #include "GameObj.h"
- #include "callback_functions.h"
- #include "Gamelogic.h"
- #include <cmath>
- #include <mmsystem.h>
- #define PI 3.1415926
- using namespace std ;
- CPlayer::CPlayer(const string& name)
- {
- // 打开相应人物的profile读取执行
- fstream in ;
- string filename = ".\Actor\" ;
- SPropertyItem item ;
- GameRes* res_info ;
- string script ;
- string small_res_name ;
- string middle_res_name ;
- string big_res_name ;
- string face_res_name ;
- // 人物属性还没有图片
- item.icon_id = -1 ;
- filename += name ;
- filename += ".profile" ;
- in.open(filename.c_str(), ios::in) ;
- if ( in.is_open() )
- {
- // 人物说明,可以带有tag标记
- in >> self_description ;
- // 读人物的四个图片资源名:小,中,大,头像
- in >> small_res_name >> middle_res_name >> big_res_name >> face_res_name ;
- // 读入人物属性
- in >> item.name >> item.val ;
- while ( item.name != "END" )
- {
- m_property.push_back( item ) ;
- in >> item.name >> item.val ;
- }
- // 读入人物技能
- in >> item.name >> item.description >> item.val ;
- while ( item.name != "END" )
- {
- m_skills.push_back( item ) ;
- in >> item.name >> item.description >> item.val ;
- }
- // 读入人物说话列表
- in >> script ;
- while ( script != "END" )
- {
- this->push_script( script ) ;
- in >> script ;
- }
- // 读入人物说话方式
- in >> script ;
- if ( script == "RANDOM" )
- {
- SetTalkState( CPlayer::RANDOM ) ;
- }
- else if ( script == "CONDITIONAL" )
- {
- SetTalkState( CPlayer::CONDITIONAL ) ;
- }
- else if ( script == "LOOP" )
- {
- SetTalkState( CPlayer::LOOP ) ;
- }
- else if ( script == "CONTINUAL" )
- {
- SetTalkState( CPlayer::CONTINUAL ) ;
- }
- else
- {
- string reason = "Unexpected npc talk style '" ;
- reason += script ;
- reason += "' when reading profile :";
- reason += filename ;
- throw logic_error( reason.c_str() ) ;
- }
- }
- /*
- * 根据人物profile提供的信息向Unicough引擎申请图片资源
- */
- if ( small_res_name != "NULL" )
- {
- res_info = context->GetRes(small_res_name) ;
- (*LoadActor)( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &Small_Res_id ) ;
- this->ResID = Small_Res_id ;
- }
-
- if ( middle_res_name != "NULL" )
- {
- res_info = context->GetRes(middle_res_name) ;
- LoadActor( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &Middle_Res_id ) ;
- this->ResID = Middle_Res_id ;
- }
- if ( big_res_name != "NULL" )
- {
- res_info = context->GetRes(big_res_name) ;
- LoadActor( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &Big_Res_id ) ;
- this->ResID = Big_Res_id ;
- }
- if ( face_res_name != "NULL")
- {
- res_info = context->GetRes(face_res_name) ;
- LoadActor( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &face_Res_id ) ;
- }
- this->name = name ;
- this->x = 0 ;
- this->y = 0 ;
- this->facing = 0 ;
- this->attack_str = NULL ;
- this->active_in_scene = false ;
- this->is_doing_task = false ;
- this->is_loop = false ;
- this->waiting_mode = false ;
- this->is_dead = false ;
- this->is_auto_attack = false ;
- this->state = CGameLogic::STOP ;
- this->m_current_words = 0 ;
- }
- CPlayer::~CPlayer()
- {
- }
- SPropertyItem* CPlayer::Property(const std::string& name)
- {
- vector<SPropertyItem>::iterator pos = m_property.begin() ;
- for ( ; pos != m_property.end(); pos++ )
- {
- if ( pos->name == name )
- {
- return &(*pos) ;
- }
- }
- throw exception("try to get nonexsisted player property!") ;
- }
- SPropertyItem* CPlayer::Skill(const std::string& name)
- {
- vector<SPropertyItem>::iterator pos = m_skills.begin() ;
- for ( ; pos != m_skills.end(); pos++ )
- {
- if ( pos->description == name )
- {
- return &(*pos) ;
- }
- }
- string what = "try to get nonexsisted player skill: " ;
- what += name ;
- throw exception( what.c_str() ) ;
- }
- SPropertyItem* CPlayer::FindTools(const std::string& description)
- {
- vector<SPropertyItem>::iterator pos = m_tools.begin() ;
- for ( ; pos != m_tools.end(); pos++ )
- {
- if ( pos->description == description )
- {
- return &(*pos) ;
- }
- }
- return NULL ;
- }
- void CPlayer::DelTools(const std::string& description)
- {
- vector<SPropertyItem>::iterator pos = m_tools.begin() ;
- for ( ; pos != m_tools.end(); pos++ )
- {
- if ( pos->description == description )
- {
- m_tools.erase( pos ) ;
- return ;
- }
- }
- }
- void CPlayer::AddTool(SPropertyItem& tool )
- {
- m_tools.push_back(tool) ;
- }
- void CPlayer::SetActiveRes(RanderState s )
- {
- switch (s)
- {
- case BIG :
- this->ResID = Big_Res_id ;
- break;
- case SMALL :
- this->ResID = Small_Res_id ;
- break;
- case MID:
- this->ResID = Middle_Res_id ;
- break ;
- default:
- throw logic_error("Unexpected rander state when CPlayer::SetActiveRes()") ;
- }
- }
- /*
- * 清空所有任务路点
- */
- void CPlayer::flush_all_way_point()
- {
- m_way_points.clear() ;
- is_doing_task = false ;
- }
- /*
- * 在队列末尾加入新的路点
- */
- void CPlayer::push_way_point(int dest_x, int dest_y)
- {
- if ( m_way_points.empty() )
- {
- m_way_points.push_front( make_pair(dest_x, dest_y) ) ;
- is_doing_task = true ;
- }
- else
- {
- m_way_points.push_front( make_pair(dest_x, dest_y) ) ;
- }
- }
- /*
- * 在队列头插入一个节点,改变当前路线
- */
- void CPlayer::insert_way_point(int x, int y)
- {
- m_way_points.push_back( make_pair(x, y) ) ;
- is_doing_task = true ;
- }
- double CPlayer::compute_dxy()
- {
- int dest_x ;
- int dest_y ;
- double min_length = 800 * 800 + 600 * 600 ;
- double temp ;
- int dx1 = (int)( context->GetWalkingSpeed() * cos(22.0 / 180 * PI) ) ;
- int dy1 = (int)( context->GetWalkingSpeed() * sin(22.0 / 180 * PI) ) ;
- int dx2 = (int)( context->GetWalkingSpeed() * cos(31.0 / 180 * PI) ) ;
- int dy2 = (int)( context->GetWalkingSpeed() * sin(31.0 / 180 * PI) ) ;
- dest_x = m_way_points.back().first ;
- dest_y = m_way_points.back().second ;
- // 在第一个方向try: 向上
- if ( ( temp = ActiveLength( x+dx2, y-dy2, dest_x, dest_y ) ) < min_length )
- {
- way_point_dx = dx2 ;
- way_point_dy = -dy2 ;
- min_length = temp ;
- this->facing = 2 ;
- }
- // 在第二个方向上try :向下
- if ( ( temp = ActiveLength( x-dx2, y+dy2, dest_x, dest_y ) ) < min_length )
- {
- way_point_dx = -dx2 ;
- way_point_dy = dy2 ;
- min_length = temp ;
- this->facing = 0 ;
- }
- // 在第三个方向try:向左
- if ( ( temp = ActiveLength( x-dx1, y-dy1, dest_x, dest_y ) ) < min_length )
- {
- way_point_dx = -dx1 ;
- way_point_dy = -dy1 ;
- min_length = temp ;
- this->facing = 3 ;
- }
- // 在第四个方向try:向右
- if ( ( temp = ActiveLength( x+dx1, y+dy1, dest_x, dest_y ) ) < min_length )
- {
- way_point_dx = dx1 ;
- way_point_dy = dy1 ;
- min_length = temp ;
- this->facing = 1 ;
- }
- // 如果都不能移动,停在原地
- if ( min_length > sqrt(800.0 * 800.0 + 600.0 * 600.0) )
- {
- way_point_dx = 0 ;
- way_point_dy = 0 ;
- }
- else
- {
- consist_way_time = rand() % 4 + 4 ;
- this->state = CGameLogic::WALKING ;
- }
- return min_length ;
- }
- bool CPlayer::AutoUpdate()
- {
- // 检查动画是否播放完毕
- CheckMovFrameEnd() ;
- if ( is_dead )
- {
- return false;
- }
- if ( this == &(context->m_ActorManager->GetActiveActor()) )
- {
- // 如果是用户控制的人物,仅刷新用户关注的npc
- this->context->m_ActorManager->RefreshUserAttention() ;
- return false ;
- }
- // 如果是自动攻击模式,那么检测和ActiveActor的距离
- if ( is_auto_attack && active_in_scene && !is_dead && !this->context->is_fighting() )
- {
- CPlayer& actor = context->m_ActorManager->GetActiveActor() ;
- if ( !actor.is_dead )
- {
- vector<string> Argu ;
- Argu.push_back(actor.name);
- Argu.push_back(this->name);
- if ( ActiveLength( actor.x, actor.y, this->x, this->y ) < context->GetSensitiveLength() * 1.2 )
- {
- this->context->m_EventManager->Call_Event( "fight", &Argu ) ;
- this->context->m_EventManager->Continue_Doing() ;
- }
- }
- }
- // 是不是在等待模式,如果间隔时间不到就不继续执行
- if ( waiting_mode )
- {
- if (timeGetTime() - start_time > waiting_time )
- {
- waiting_mode = false ;
- }
- else
- {
- return true ;
- }
- }
- if ( is_doing_task && active_in_scene && !context->is_fighting() )
- {
- int dest_x = m_way_points.back().first ;
- int dest_y = m_way_points.back().second ;
- if ( test_goal() || ( abs(x - dest_x) < context->GetWalkingSpeed() && abs( y - dest_y ) < context->GetWalkingSpeed() ) )
- {
- // 到达一个目的地,弹出队列
- m_way_points.pop_back() ;
- if ( is_loop )
- {
- m_backup_way_points.push_front( make_pair(dest_x, dest_y) ) ;
- }
- if ( !m_way_points.empty() )
- {
- // 还有目标点在队列中,继续移动
- compute_dxy() ;
- x += way_point_dx ;
- y += way_point_dy ;
- consist_way_time-- ;
- this->EnterWaitingMode( 1000 ) ;
- }
- else
- {
- if ( is_loop )
- {
- m_way_points = m_backup_way_points ;
- m_backup_way_points.clear() ;
- compute_dxy() ;
- x += way_point_dx ;
- y += way_point_dy ;
- consist_way_time-- ;
- this->EnterWaitingMode( 1000 ) ;
- }
- else
- {
- // 没有目标点,结束移动
- is_doing_task = false ;
- this->state = CGameLogic::STOP ;
- }
- }
- }
- else
- {
- if (consist_way_time < 0)
- {
- compute_dxy() ;
- }
- consist_way_time -- ;
- // 按原路线不能走通就选择新路线
- if ( context->GetLogicalMapInfo( x + way_point_dx, y + way_point_dy ) == 0 )
- {
- compute_dxy() ;
- }
- if ( !this->DetectOtherActor(2 * way_point_dx, 2 * way_point_dy) )
- {
- x += way_point_dx ;
- y += way_point_dy ;
- }
- else
- {
- this->EnterWaitingMode( 5000 ) ;
- }
- }
- }
- return is_doing_task ;
- }
- /*
- * 动态计算地图两点间举例
- */
- double CPlayer::ActiveLength(int x1, int y1, int x2, int y2)
- {
- if ( context->GetLogicalMapInfo(x1, y1) != 0 )
- {
- return sqrt( (double)( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) ;
- }
- else
- {
- return 3e10 ;
- }
- }
- bool CPlayer::test_goal()
- {
- int dest_x = m_way_points.back().first ;
- int dest_y = m_way_points.back().second ;
- int old_way_point_dx = way_point_dx ;
- int old_way_point_dy = way_point_dy ;
- int old_consist_way_time = consist_way_time ;
- double length = compute_dxy() ;
- if ( length <= context->GetWalkingSpeed() )
- {
- return true ;
- }
- else
- {
- way_point_dx = old_way_point_dx ;
- way_point_dy = old_way_point_dy ;
- consist_way_time = old_consist_way_time ;
- return false ;
- }
- }
- void CPlayer::set_task_loop(bool is_loop)
- {
- this->is_loop = is_loop ;
- }
- void CPlayer::EnterWaitingMode(unsigned int time )
- {
- this->state = CGameLogic::STOP ;
- way_point_dx = 0 ;
- way_point_dy = 0 ;
- waiting_time = time ;
- waiting_mode = true ;
- start_time = timeGetTime() ;
- }
- bool CPlayer::DetectOtherActor(int dx, int dy)
- {
- // 枚举压栈
- context->m_ActorManager->push_enum_state() ;
- CPlayer* other = context->m_ActorManager->enumActor() ;
- bool flag = false ;
- while ( other != NULL )
- {
- if ( other != this && other->active_in_scene && ActiveLength( other->x, other->y, this->x + dx, this->y + dy ) <= context->GetSensitiveLength() )
- {
- flag = true ;
- }
- other = context->m_ActorManager->enumActor() ;
- }
- // 枚举出栈
- context->m_ActorManager->pop_enum_state() ;
- return flag ;
- }
- void CPlayer::push_script(std::string& ProcName )
- {
- m_talking_script.push_back(ProcName) ;
- }
- string& CPlayer::TalkScript()
- {
- size_t i ;
- switch( m_talk_state )
- {
- // 随机的时候,就随机取脚本执行
- case RANDOM :
- i = rand() % m_talking_script.size() ;
- return m_talking_script[i] ;
- break;
- case CONTINUAL:
- if ( m_current_words < m_talking_script.size() )
- {
- return m_talking_script[ m_current_words++ ] ;
- }
- else
- {
- return m_talking_script[ m_current_words-1 ] ;
- }
- break ;
- case CONDITIONAL :
- return m_talking_script[ m_current_words ] ;
- break;
- case LOOP :
- if ( m_current_words < m_talking_script.size() )
- {
- return m_talking_script[ m_current_words++ ] ;
- }
- else
- {
- m_current_words = 0 ;
- return m_talking_script[ m_current_words++ ] ;
- }
- break;
- default:
- throw runtime_error("Incredible error in CPlayer::TalkScript()") ;
- break;
- }
- }
- void CPlayer::SetTalkState(TalkState state)
- {
- m_talk_state = state ;
- }
- void CPlayer::NextTalking(string& ProcName )
- {
- vector<string>::iterator pos = find( m_talking_script.begin(), m_talking_script.end(), ProcName ) ;
- if ( pos != m_talking_script.end() )
- {
- m_current_words = pos - m_talking_script.begin() ;
- }
- else
- {
- throw logic_error("Required procedure is not in actor's list!") ;
- }
- }
- void CPlayer::SetInfoText(const std::string& info )
- {
- m_attack_str_buf = info ;
- this->attack_str = m_attack_str_buf.c_str() ;
- GetFrameCount(&m_frame_count_for_info) ;
- }
- void CPlayer::CheckMovFrameEnd()
- {
- size_t now_frame ;
-
- GetFrameCount( &now_frame ) ;
- // 检查停止播放信息字符
- if ( now_frame - m_frame_count_for_info > FRAMENUMFORTEXT && this->attack_str != NULL )
- {
- this->attack_str = NULL ;
- }
- // 检查停止播放人物动画
- if ( now_frame - m_frame_count_for_movie > FRAMENUMFORMOV && this->state == CGameLogic::FIGHTING )
- {
- this->state = CGameLogic::STOP ;
- }
- }
- void CPlayer::NpcFight(std::string& fighter_name )
- {
- // Random选择攻击招数
- size_t selector = rand() % m_skills.size() ;
- Attack( m_skills.begin()->description, fighter_name ) ;
- }
- void CPlayer::PlayFightMovie()
- {
- // 开始播放动画
- this->state = CGameLogic::FIGHTING ;
- GetFrameCount(&m_frame_count_for_movie) ;
- }
- void CPlayer::Attack(std::string& skill, std::string& name )
- {
- SPropertyItem* attack_skill = this->Skill(skill) ;
- CPlayer& actor = this->context->m_ActorManager->GetActor( name ) ;
- stringstream info ;
- if ( attack_skill->name == "内定" )
- {
- if ( attack_skill->description == "法术:如沐春风" )
- {
- if ( Property("魔法力")->val + attack_skill->val > 0 )
- {
- this->ChangeProperty( "魔法力", attack_skill->val ) ;
- this->ChangeProperty( "生命力", this->Property("生命力上限")->val * 2 / 3 );
- info << "<size=8><color=65535>生命力恢复到66%!" ;
- SetInfoText( info.str() ) ;
- Speak("如沐春风") ;
- }
- else
- {
- // 法术失败
- info << "<size=8><color=255>法术失败!" ;
- SetInfoText( info.str() ) ;
- Speak("法术失败");
- }
- }
- }
- else
- {
- // 对对方造成伤害
- int val = - ( rand() % this->Property("攻击力")->val ) ;
- val += attack_skill->val ;
- actor.ChangeProperty(attack_skill->name, val) ;
- info << "<size=8><color=255>受到攻击: " << val ;
- // 对方播放信息字符
- actor.SetInfoText( info.str() ) ;
- // 自己播放攻击动画
- PlayFightMovie() ;
- // 播放声音
- Speak( "挥剑" ) ;
- }
- context->m_EventManager->Wait( FRAMENUMFORTEXT + 5 ) ;
- }
- void CPlayer::TryEscape(const std::string& name )
- {
- vector<string> Argu ;
- // 根据速度来判断是否能够逃脱
- int npc_speed = context->m_ActorManager->GetActor(name).Property("速度")->val ;
- int my_speed = Property("速度")->val ;
- Argu.push_back(this->name) ;
- Argu.push_back(name) ;
- if ( rand() % ( npc_speed + my_speed ) <= my_speed )
- {
- context->m_EventManager->Do_Event("escape_success", &Argu) ;
- }
- else
- {
- context->m_EventManager->Call_Event("escape_fail", &Argu) ;
- }
- }
- void CPlayer::ChangeProperty(const string& property, int val )
- {
- SPropertyItem* item = this->Property( property ) ;
- SPropertyItem* topval = this->Property( property+"上限" ) ;
- item->val += val ;
- if ( item->val > topval->val )
- {
- item->val = topval->val ;
- }
- // 处理升级问题
- int upgrade_line = 100 * ( 1 << (this->Property("等级")->val - 1) ) ;
- if ( property == "经验" )
- {
- while ( item->val >= upgrade_line )
- {
- // 提升一个等级
- this->Property("等级")->val++ ;
- // 各项属性上限分别提升
- this->Property("生命力上限")->val += this->Property("+生命力")->val ;
- this->Property("魔法力上限")->val += this->Property("+魔法力")->val ;
- this->Property("速度上限")->val += this->Property("+速度")->val ;
- this->Property("攻击力上限")->val += this->Property("+攻击力")->val ;
- this->Property("速度")->val = this->Property("速度上限")->val ;
- this->Property("生命力")->val = this->Property("生命力上限")->val ;
- this->Property("魔法力")->val = this->Property("魔法力上限")->val ;
- upgrade_line = 100 * ( 1 << (this->Property("等级")->val - 1) ) ;
- // 播放音效
- Speak("升级") ;
- // 播放字幕
- this->SetInfoText("<size=10>等级 +1") ;
- }
- }
- }
- void CPlayer::Die()
- {
- this->active_in_scene = false ;
- this->is_dead = true ;
- if ( this == &( context->m_ActorManager->GetActiveActor() ) )
- {
- context->m_is_dead = true ;
- }
- }
- void CPlayer::AutoAttack(bool val)
- {
- this->is_auto_attack = val ;
- }
- void CPlayer::LearnSkill(const SPropertyItem& skill )
- {
- m_skills.push_back( skill ) ;
- }