Player.cpp
上传用户:lian_0917
上传日期:2013-03-24
资源大小:1151k
文件大小:17k
源码类别:

其他游戏

开发平台:

MultiPlatform

  1. /********************************************************************
  2. created: 2004/05/25
  3. created: 25:5:2004   15:07
  4. filename:  d:WorksGamelibPlayer.cpp
  5. file path: d:WorksGamelib
  6. file base: Player
  7. file ext: cpp
  8. author: lazybug
  9. purpose: CPlayer类得实现部分
  10. *********************************************************************/
  11. #include "stdafx.h"
  12. #include "GameObj.h"
  13. #include "callback_functions.h"
  14. #include "Gamelogic.h"
  15. #include <cmath>
  16. #include <mmsystem.h>
  17. #define PI 3.1415926
  18. using namespace std ;
  19. CPlayer::CPlayer(const string& name)
  20. {
  21. // 打开相应人物的profile读取执行
  22. fstream in ;
  23. string filename = ".\Actor\" ;
  24. SPropertyItem item ;
  25. GameRes* res_info ;
  26. string script ;
  27. string small_res_name ;
  28. string middle_res_name ;
  29. string big_res_name ;
  30. string face_res_name ;
  31. // 人物属性还没有图片
  32. item.icon_id = -1 ;
  33. filename += name ;
  34. filename += ".profile" ;
  35. in.open(filename.c_str(), ios::in) ;
  36. if ( in.is_open() )
  37. {
  38. // 人物说明,可以带有tag标记
  39. in >> self_description ;
  40. // 读人物的四个图片资源名:小,中,大,头像
  41. in >> small_res_name >> middle_res_name >> big_res_name >> face_res_name ;
  42. // 读入人物属性
  43. in >> item.name >> item.val ;
  44. while ( item.name != "END" )
  45. {
  46. m_property.push_back( item ) ;
  47. in >> item.name >> item.val ;
  48. }
  49. // 读入人物技能
  50. in >> item.name >> item.description >> item.val ;
  51. while ( item.name != "END" )
  52. {
  53. m_skills.push_back( item ) ;
  54. in >> item.name >> item.description >> item.val ;
  55. }
  56. // 读入人物说话列表
  57. in >> script ;
  58. while ( script != "END" )
  59. {
  60. this->push_script( script ) ;
  61. in >> script ;
  62. }
  63. // 读入人物说话方式
  64. in >> script ;
  65. if ( script == "RANDOM" )
  66. {
  67. SetTalkState( CPlayer::RANDOM ) ;
  68. }
  69. else if ( script == "CONDITIONAL" )
  70. {
  71. SetTalkState( CPlayer::CONDITIONAL ) ;
  72. }
  73. else if ( script == "LOOP" )
  74. {
  75. SetTalkState( CPlayer::LOOP ) ;
  76. }
  77. else if ( script == "CONTINUAL" )
  78. {
  79. SetTalkState( CPlayer::CONTINUAL ) ;
  80. }
  81. else
  82. {
  83. string reason = "Unexpected npc talk style '" ;
  84. reason += script ;
  85. reason += "' when reading profile :";
  86. reason += filename ;
  87. throw logic_error( reason.c_str() ) ;
  88. }
  89. }
  90. /*
  91.  * 根据人物profile提供的信息向Unicough引擎申请图片资源
  92.  */
  93. if ( small_res_name != "NULL" )
  94. {
  95. res_info = context->GetRes(small_res_name) ;
  96. (*LoadActor)( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &Small_Res_id ) ;
  97. this->ResID = Small_Res_id ;
  98. }
  99. if ( middle_res_name != "NULL" )
  100. {
  101. res_info = context->GetRes(middle_res_name) ;
  102. LoadActor( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &Middle_Res_id ) ;
  103. this->ResID = Middle_Res_id ;
  104. }
  105. if ( big_res_name != "NULL" )
  106. {
  107. res_info = context->GetRes(big_res_name) ;
  108. LoadActor( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &Big_Res_id ) ;
  109. this->ResID = Big_Res_id ;
  110. }
  111. if ( face_res_name != "NULL")
  112. {
  113. res_info = context->GetRes(face_res_name) ;
  114. LoadActor( res_info->filename.c_str(), res_info->h_frame, res_info->v_frame, res_info->color_key, &face_Res_id ) ;
  115. }
  116. this->name = name ;
  117. this->x = 0 ;
  118. this->y = 0 ;
  119. this->facing = 0 ;
  120. this->attack_str = NULL ;
  121. this->active_in_scene = false ;
  122. this->is_doing_task = false ;
  123. this->is_loop = false ;
  124. this->waiting_mode = false ;
  125. this->is_dead = false ;
  126. this->is_auto_attack = false ;
  127. this->state = CGameLogic::STOP ;
  128. this->m_current_words = 0 ;
  129. }
  130. CPlayer::~CPlayer()
  131. {
  132. }
  133. SPropertyItem* CPlayer::Property(const std::string& name)
  134. {
  135. vector<SPropertyItem>::iterator pos = m_property.begin() ;
  136. for ( ; pos != m_property.end(); pos++ )
  137. {
  138. if ( pos->name == name )
  139. {
  140. return &(*pos) ;
  141. }
  142. }
  143. throw exception("try to get nonexsisted player property!") ;
  144. }
  145. SPropertyItem* CPlayer::Skill(const std::string& name)
  146. {
  147. vector<SPropertyItem>::iterator pos = m_skills.begin() ;
  148. for ( ; pos != m_skills.end(); pos++ )
  149. {
  150. if ( pos->description == name )
  151. {
  152. return &(*pos) ;
  153. }
  154. }
  155. string what = "try to get nonexsisted player skill: " ;
  156. what += name ;
  157. throw exception( what.c_str() ) ;
  158. }
  159. SPropertyItem* CPlayer::FindTools(const std::string& description)
  160. {
  161. vector<SPropertyItem>::iterator pos = m_tools.begin() ;
  162. for ( ; pos != m_tools.end(); pos++ )
  163. {
  164. if ( pos->description == description )
  165. {
  166. return &(*pos) ;
  167. }
  168. }
  169. return NULL ;
  170. }
  171. void CPlayer::DelTools(const std::string& description)
  172. {
  173. vector<SPropertyItem>::iterator pos = m_tools.begin() ;
  174. for ( ; pos != m_tools.end(); pos++ )
  175. {
  176. if ( pos->description == description )
  177. {
  178. m_tools.erase( pos ) ;
  179. return ;
  180. }
  181. }
  182. }
  183. void CPlayer::AddTool(SPropertyItem& tool )
  184. {
  185. m_tools.push_back(tool) ;
  186. }
  187. void CPlayer::SetActiveRes(RanderState s )
  188. {
  189. switch (s) 
  190. {
  191. case BIG :
  192. this->ResID = Big_Res_id ;
  193. break;
  194. case SMALL :
  195. this->ResID = Small_Res_id ;
  196. break;
  197. case MID:
  198. this->ResID = Middle_Res_id ;
  199. break ;
  200. default:
  201. throw logic_error("Unexpected rander state when CPlayer::SetActiveRes()") ;
  202. }
  203. }
  204. /*
  205.  * 清空所有任务路点
  206.  */
  207. void CPlayer::flush_all_way_point()
  208. {
  209. m_way_points.clear() ;
  210. is_doing_task = false ;
  211. }
  212. /*
  213.  * 在队列末尾加入新的路点
  214.  */
  215. void CPlayer::push_way_point(int dest_x, int dest_y)
  216. {
  217. if ( m_way_points.empty() )
  218. {
  219. m_way_points.push_front( make_pair(dest_x, dest_y) ) ;
  220. is_doing_task = true ;
  221. }
  222. else
  223. {
  224. m_way_points.push_front( make_pair(dest_x, dest_y) ) ;
  225. }
  226. }
  227. /*
  228.  * 在队列头插入一个节点,改变当前路线
  229.  */
  230. void CPlayer::insert_way_point(int x, int y)
  231. {
  232. m_way_points.push_back( make_pair(x, y) ) ;
  233. is_doing_task = true ;
  234. }
  235. double CPlayer::compute_dxy()
  236. {
  237. int dest_x ;
  238. int dest_y ;
  239. double min_length = 800 * 800 + 600 * 600 ;
  240. double temp ;
  241. int dx1 = (int)( context->GetWalkingSpeed() * cos(22.0 / 180 * PI) ) ;
  242. int dy1 = (int)( context->GetWalkingSpeed() * sin(22.0 / 180 * PI) ) ;
  243. int dx2 = (int)( context->GetWalkingSpeed() * cos(31.0 / 180 * PI) ) ;
  244. int dy2 = (int)( context->GetWalkingSpeed() * sin(31.0 / 180 * PI) ) ;
  245. dest_x = m_way_points.back().first ;
  246. dest_y = m_way_points.back().second ;
  247. // 在第一个方向try: 向上
  248. if ( ( temp = ActiveLength( x+dx2, y-dy2, dest_x, dest_y ) ) < min_length )
  249. {
  250. way_point_dx = dx2 ;
  251. way_point_dy = -dy2 ;
  252. min_length = temp ;
  253. this->facing = 2 ;
  254. }
  255. // 在第二个方向上try :向下
  256. if ( ( temp = ActiveLength( x-dx2, y+dy2, dest_x, dest_y ) ) < min_length  )
  257. {
  258. way_point_dx = -dx2 ;
  259. way_point_dy = dy2 ;
  260. min_length = temp ;
  261. this->facing = 0 ;
  262. }
  263. // 在第三个方向try:向左
  264. if ( ( temp = ActiveLength( x-dx1, y-dy1, dest_x, dest_y ) ) < min_length )
  265. {
  266. way_point_dx = -dx1 ;
  267. way_point_dy = -dy1 ;
  268. min_length = temp ;
  269. this->facing = 3 ;
  270. }
  271. // 在第四个方向try:向右
  272. if ( ( temp = ActiveLength( x+dx1, y+dy1, dest_x, dest_y ) ) < min_length )
  273. {
  274. way_point_dx = dx1 ;
  275. way_point_dy = dy1 ;
  276. min_length = temp ;
  277. this->facing = 1 ;
  278. }
  279. // 如果都不能移动,停在原地
  280. if ( min_length > sqrt(800.0 * 800.0 + 600.0 * 600.0) )
  281. {
  282. way_point_dx = 0 ;
  283. way_point_dy = 0 ;
  284. }
  285. else
  286. {
  287. consist_way_time = rand() % 4 + 4 ;
  288. this->state = CGameLogic::WALKING ;
  289. }
  290. return min_length ;
  291. }
  292. bool CPlayer::AutoUpdate()
  293. {
  294. // 检查动画是否播放完毕
  295. CheckMovFrameEnd() ;
  296. if ( is_dead )
  297. {
  298. return false;
  299. }
  300. if ( this == &(context->m_ActorManager->GetActiveActor()) )
  301. {
  302. // 如果是用户控制的人物,仅刷新用户关注的npc
  303. this->context->m_ActorManager->RefreshUserAttention() ;
  304. return false ;
  305. }
  306. // 如果是自动攻击模式,那么检测和ActiveActor的距离
  307. if ( is_auto_attack && active_in_scene && !is_dead && !this->context->is_fighting() )
  308. {
  309. CPlayer& actor = context->m_ActorManager->GetActiveActor() ;
  310. if ( !actor.is_dead )
  311. {
  312. vector<string> Argu ;
  313. Argu.push_back(actor.name);
  314. Argu.push_back(this->name);
  315. if ( ActiveLength( actor.x, actor.y, this->x, this->y ) < context->GetSensitiveLength() * 1.2 )
  316. {
  317. this->context->m_EventManager->Call_Event( "fight", &Argu ) ;
  318. this->context->m_EventManager->Continue_Doing() ;
  319. }
  320. }
  321. }
  322. // 是不是在等待模式,如果间隔时间不到就不继续执行
  323. if ( waiting_mode )
  324. {
  325. if (timeGetTime() - start_time > waiting_time )
  326. {
  327. waiting_mode = false ;
  328. }
  329. else
  330. {
  331. return true ;
  332. }
  333. }
  334. if ( is_doing_task && active_in_scene && !context->is_fighting() )
  335. {
  336. int dest_x = m_way_points.back().first ;
  337. int dest_y = m_way_points.back().second ;
  338. if ( test_goal() || ( abs(x - dest_x) < context->GetWalkingSpeed() && abs( y - dest_y ) < context->GetWalkingSpeed() ) )
  339. {
  340. // 到达一个目的地,弹出队列
  341. m_way_points.pop_back() ;
  342. if ( is_loop )
  343. {
  344. m_backup_way_points.push_front( make_pair(dest_x, dest_y) ) ;
  345. }
  346. if ( !m_way_points.empty() )
  347. {
  348. // 还有目标点在队列中,继续移动
  349. compute_dxy() ;
  350. x += way_point_dx ;
  351. y += way_point_dy ;
  352. consist_way_time-- ;
  353. this->EnterWaitingMode( 1000 ) ;
  354. }
  355. else
  356. {
  357. if ( is_loop )
  358. {
  359. m_way_points = m_backup_way_points ;
  360. m_backup_way_points.clear() ;
  361. compute_dxy() ;
  362. x += way_point_dx ;
  363. y += way_point_dy ;
  364. consist_way_time-- ;
  365. this->EnterWaitingMode( 1000 ) ;
  366. }
  367. else
  368. {
  369. // 没有目标点,结束移动
  370. is_doing_task = false ;
  371. this->state = CGameLogic::STOP ;
  372. }
  373. }
  374. }
  375. else
  376. {
  377. if (consist_way_time < 0)
  378. {
  379. compute_dxy() ;
  380. }
  381. consist_way_time -- ;
  382. // 按原路线不能走通就选择新路线
  383. if ( context->GetLogicalMapInfo( x + way_point_dx, y + way_point_dy ) == 0 )
  384. {
  385. compute_dxy() ;
  386. }
  387. if ( !this->DetectOtherActor(2 * way_point_dx, 2 * way_point_dy) )
  388. {
  389. x += way_point_dx ;
  390. y += way_point_dy ;
  391. }
  392. else
  393. {
  394. this->EnterWaitingMode( 5000 ) ;
  395. }
  396. }
  397. }
  398. return is_doing_task ;
  399. }
  400. /*
  401.  * 动态计算地图两点间举例
  402.  */
  403. double CPlayer::ActiveLength(int x1, int y1, int x2, int y2)
  404. {
  405. if ( context->GetLogicalMapInfo(x1, y1) != 0 )
  406. {
  407. return sqrt( (double)( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ) ;
  408. }
  409. else
  410. {
  411. return 3e10 ;
  412. }
  413. }
  414. bool CPlayer::test_goal()
  415. {
  416. int dest_x = m_way_points.back().first ;
  417. int dest_y = m_way_points.back().second ;
  418. int old_way_point_dx = way_point_dx ;
  419. int old_way_point_dy = way_point_dy ;
  420. int old_consist_way_time = consist_way_time ;
  421. double length = compute_dxy() ;
  422. if ( length <= context->GetWalkingSpeed() )
  423. {
  424. return true ;
  425. }
  426. else
  427. {
  428. way_point_dx = old_way_point_dx ;
  429. way_point_dy = old_way_point_dy ;
  430. consist_way_time = old_consist_way_time ;
  431. return false ;
  432. }
  433. }
  434. void CPlayer::set_task_loop(bool is_loop)
  435. {
  436. this->is_loop = is_loop ;
  437. }
  438. void CPlayer::EnterWaitingMode(unsigned int time )
  439. {
  440. this->state = CGameLogic::STOP ;
  441. way_point_dx = 0 ;
  442. way_point_dy = 0 ;
  443. waiting_time = time ;
  444. waiting_mode = true ;
  445. start_time = timeGetTime() ;
  446. }
  447. bool CPlayer::DetectOtherActor(int dx, int dy)
  448. {
  449. // 枚举压栈
  450. context->m_ActorManager->push_enum_state() ;
  451. CPlayer* other = context->m_ActorManager->enumActor() ;
  452. bool flag = false ;
  453. while ( other != NULL ) 
  454. {
  455. if ( other != this && other->active_in_scene && ActiveLength( other->x, other->y, this->x + dx, this->y + dy ) <= context->GetSensitiveLength() )
  456. {
  457. flag = true ;
  458. }
  459. other = context->m_ActorManager->enumActor() ;
  460. }
  461. // 枚举出栈
  462. context->m_ActorManager->pop_enum_state() ;
  463. return flag ;
  464. }
  465. void CPlayer::push_script(std::string& ProcName )
  466. {
  467. m_talking_script.push_back(ProcName) ;
  468. }
  469. string& CPlayer::TalkScript()
  470. {
  471. size_t i ;
  472. switch( m_talk_state ) 
  473. {
  474. // 随机的时候,就随机取脚本执行
  475. case RANDOM :
  476. i = rand() % m_talking_script.size() ;
  477. return m_talking_script[i] ;
  478. break;
  479. case CONTINUAL:
  480. if ( m_current_words < m_talking_script.size() )
  481. {
  482. return m_talking_script[ m_current_words++ ] ;
  483. }
  484. else
  485. {
  486. return m_talking_script[ m_current_words-1 ] ;
  487. }
  488. break ;
  489. case CONDITIONAL :
  490. return m_talking_script[ m_current_words ] ;
  491. break;
  492. case LOOP :
  493. if ( m_current_words < m_talking_script.size() )
  494. {
  495. return m_talking_script[ m_current_words++ ] ;
  496. }
  497. else
  498. {
  499. m_current_words = 0 ;
  500. return m_talking_script[ m_current_words++ ] ;
  501. }
  502. break;
  503. default:
  504. throw runtime_error("Incredible error in CPlayer::TalkScript()") ;
  505. break;
  506. }
  507. }
  508. void CPlayer::SetTalkState(TalkState state)
  509. {
  510. m_talk_state = state ;
  511. }
  512. void CPlayer::NextTalking(string& ProcName )
  513. {
  514. vector<string>::iterator pos = find( m_talking_script.begin(), m_talking_script.end(), ProcName ) ;
  515. if ( pos != m_talking_script.end() )
  516. {
  517. m_current_words = pos - m_talking_script.begin() ;
  518. }
  519. else
  520. {
  521. throw logic_error("Required procedure is not in actor's list!") ;
  522. }
  523. }
  524. void CPlayer::SetInfoText(const std::string& info )
  525. {
  526. m_attack_str_buf = info ;
  527. this->attack_str = m_attack_str_buf.c_str() ;
  528. GetFrameCount(&m_frame_count_for_info) ;
  529. }
  530. void CPlayer::CheckMovFrameEnd()
  531. {
  532. size_t now_frame ;
  533. GetFrameCount( &now_frame ) ;
  534. // 检查停止播放信息字符
  535. if ( now_frame - m_frame_count_for_info > FRAMENUMFORTEXT && this->attack_str != NULL )
  536. {
  537. this->attack_str = NULL ;
  538. }
  539. // 检查停止播放人物动画
  540. if ( now_frame - m_frame_count_for_movie > FRAMENUMFORMOV && this->state == CGameLogic::FIGHTING )
  541. {
  542. this->state = CGameLogic::STOP ;
  543. }
  544. }
  545. void CPlayer::NpcFight(std::string& fighter_name )
  546. {
  547. // Random选择攻击招数
  548. size_t selector = rand() % m_skills.size() ;
  549. Attack( m_skills.begin()->description, fighter_name ) ;
  550. }
  551. void CPlayer::PlayFightMovie()
  552. {
  553. // 开始播放动画
  554. this->state = CGameLogic::FIGHTING ;
  555. GetFrameCount(&m_frame_count_for_movie) ;
  556. }
  557. void CPlayer::Attack(std::string& skill, std::string& name )
  558. {
  559. SPropertyItem* attack_skill = this->Skill(skill) ;
  560. CPlayer& actor = this->context->m_ActorManager->GetActor( name ) ;
  561. stringstream info ;
  562. if ( attack_skill->name == "内定" )
  563. {
  564. if ( attack_skill->description == "法术:如沐春风" )
  565. {
  566. if ( Property("魔法力")->val + attack_skill->val > 0 )
  567. {
  568. this->ChangeProperty( "魔法力", attack_skill->val ) ;
  569. this->ChangeProperty( "生命力", this->Property("生命力上限")->val * 2 / 3 );
  570. info << "<size=8><color=65535>生命力恢复到66%!" ;
  571. SetInfoText( info.str() ) ;
  572. Speak("如沐春风") ;
  573. }
  574. else
  575. {
  576. // 法术失败
  577. info << "<size=8><color=255>法术失败!" ;
  578. SetInfoText( info.str() ) ;
  579. Speak("法术失败");
  580. }
  581. }
  582. }
  583. else
  584. {
  585. // 对对方造成伤害
  586. int val = - ( rand() % this->Property("攻击力")->val ) ;
  587. val += attack_skill->val ;
  588. actor.ChangeProperty(attack_skill->name, val) ;
  589. info << "<size=8><color=255>受到攻击: " << val ;
  590. // 对方播放信息字符
  591. actor.SetInfoText( info.str() ) ;
  592. // 自己播放攻击动画
  593. PlayFightMovie() ;
  594. // 播放声音
  595. Speak( "挥剑" ) ;
  596. }
  597. context->m_EventManager->Wait( FRAMENUMFORTEXT + 5 ) ;
  598. }
  599. void CPlayer::TryEscape(const std::string& name )
  600. {
  601. vector<string> Argu ;
  602. // 根据速度来判断是否能够逃脱
  603. int npc_speed = context->m_ActorManager->GetActor(name).Property("速度")->val ;
  604. int my_speed = Property("速度")->val ;
  605. Argu.push_back(this->name) ;
  606. Argu.push_back(name) ;
  607. if ( rand() % ( npc_speed + my_speed ) <= my_speed )
  608. {
  609. context->m_EventManager->Do_Event("escape_success", &Argu) ;
  610. }
  611. else
  612. {
  613. context->m_EventManager->Call_Event("escape_fail", &Argu) ;
  614. }
  615. }
  616. void CPlayer::ChangeProperty(const string& property, int val )
  617. {
  618. SPropertyItem* item = this->Property( property ) ;
  619. SPropertyItem* topval = this->Property( property+"上限" ) ;
  620. item->val += val ;
  621. if ( item->val > topval->val )
  622. {
  623. item->val = topval->val ;
  624. }
  625. // 处理升级问题
  626. int upgrade_line = 100 * ( 1 << (this->Property("等级")->val - 1) ) ;
  627. if ( property == "经验" )
  628. {
  629. while ( item->val >= upgrade_line )
  630. {
  631. // 提升一个等级
  632. this->Property("等级")->val++ ;
  633. // 各项属性上限分别提升
  634. this->Property("生命力上限")->val += this->Property("+生命力")->val ;
  635. this->Property("魔法力上限")->val += this->Property("+魔法力")->val ;
  636. this->Property("速度上限")->val += this->Property("+速度")->val ;
  637. this->Property("攻击力上限")->val += this->Property("+攻击力")->val ;
  638. this->Property("速度")->val = this->Property("速度上限")->val ;
  639. this->Property("生命力")->val = this->Property("生命力上限")->val ;
  640. this->Property("魔法力")->val = this->Property("魔法力上限")->val ;
  641. upgrade_line = 100 * ( 1 << (this->Property("等级")->val - 1) ) ;
  642. // 播放音效
  643. Speak("升级") ;
  644. // 播放字幕
  645. this->SetInfoText("<size=10>等级 +1") ;
  646. }
  647. }
  648. }
  649. void CPlayer::Die()
  650. {
  651. this->active_in_scene = false ;
  652. this->is_dead = true ;
  653. if ( this == &( context->m_ActorManager->GetActiveActor() ) )
  654. {
  655. context->m_is_dead = true ;
  656. }
  657. }
  658. void CPlayer::AutoAttack(bool val)
  659. {
  660. this->is_auto_attack = val ;
  661. }
  662. void CPlayer::LearnSkill(const SPropertyItem& skill )
  663. {
  664. m_skills.push_back( skill ) ;
  665. }