www.pudn.com > GameEngine_src.rar > CHero.cpp
// CHero.cpp: implementation of the CHero class. // ////////////////////////////////////////////////////////////////////// #include "CHero.h" #include "normal.h" #include "CMap.h" #include "CEPKFile.h" #include "CEasyAudio.h" #include "CDInput.h" #include "CProgressBar.h" #include "EasyScript.h" #include "CMessageManager.h" #include "CItem.h" #include "CItemFactory.h" #include "CMagic.h" #include "CMagicFactory.h" #include "CGameManager.h" #includeextern CMap theMap; extern PEASYDRAW g_pEasyDraw; extern PEASYAUDIO g_pEasyAudio; extern CDIMouse theMouse; extern CMessageManager theMsgMgr; extern CItemBox theItemBag; extern CItemBox theEquipmentBox; //装备栏 extern CMagicFactory theMagicFactory; extern CItemFactory theItemFactory; extern CGameManager theGameManager; /////////////////////////////////////////////////////////////////////// //英雄数据文件的文件头 /////////////////////////////////////////////////////////////////////// struct HD_FILE_HEADER { union { /******************************************************** *为了保护游戏资源,此处内容省略 ********************************************************/ int data[27]; }; }; char *HERO_EPG_NAME_ARRAY[7] = { "hero%d_wait.epg", "hero%d_idle.epg", "hero%d_walk.epg", "hero%d_hurt.epg", "hero%d_dead.epg", "hero%d_melee.epg", "hero%d_spell.epg" }; ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CHero::CHero() { m_HeroEPGArray = NULL; m_NextDest.row = -1; m_cp_pg = NULL; } CHero::~CHero() { } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// bool CHero::Init() { m_HeroEPGArray = new EPG_DATA[7]; m_pClass = new MONSTER_CLASS; m_HeroSkillArray = new HERO_SKILL[10]; //初始化技能数组 if ( m_HeroEPGArray == NULL || m_pClass == NULL && m_HeroSkillArray == NULL ) return false; ZeroMemory( m_pClass, sizeof(MONSTER_CLASS) ); ZeroMemory( m_HeroSkillArray, 10 * sizeof(HERO_SKILL) ); m_TempSurface = g_pEasyDraw->CreateSurfaceEx( 0, g_pEasyDraw->GetCharWidth() * 8, g_pEasyDraw->GetCharHeight(), true, true, 0 ); if ( m_TempSurface == NULL ) return false; m_NextCell.row = 0; m_NextCell.col = 0; m_pMagic = NULL; m_Distance = 1; m_LastTick = 0; m_pg_frame = 0; m_Direction = 1; m_SpriteType = ST_HERO; return true; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::Free() { SafeDeleteArray( m_HeroEPGArray ); SafeDeleteArray( m_HeroSkillArray ); SafeDelete( m_cp_pg ); SafeDelete( m_pClass ); } //////////////////////////////////////////////////////////////////////// //载入通用资源,包括角色动画,血条,行动指针 //其中血条,行动指针只在游戏初始化载入,游戏结束时自动释放 //////////////////////////////////////////////////////////////////////// bool CHero::LoadHeroRes( HERO_CLASS heroClass ) { CEPKFile epk; int indexClass = (int)heroClass; if ( false == epk.Open( "..\\data\\common.epk", EPK_IN ) ) return false; //载入血条 BYTE *buf = epk.Read( "hp_bk.ecp" ); debug_assert( buf != NULL ); PSURFACE bk_surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); buf = epk.Read( "hp_ft.ecp" ); debug_assert( buf != NULL ); PSURFACE ft_surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); m_HPBar.Init( bk_surf, ft_surf, 28, 5 ); //载入魔条 buf = epk.Read( "mp_bk.ecp" ); debug_assert( buf != NULL ); bk_surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); buf = epk.Read( "mp_ft.ecp" ); debug_assert( buf != NULL ); ft_surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); m_MPBar.Init( bk_surf, ft_surf, 27, 0 ); //载入信息窗口 buf = epk.Read( "info_dlg.ecp" ); debug_assert( buf != NULL ); m_InfoSurface = g_pEasyDraw->CreateSurfaceFromMemory( buf ); //载入控制面板页面 buf = epk.Read( "gui.ecp" ); debug_assert( buf != NULL ); m_GuiSurface = g_pEasyDraw->CreateSurfaceFromMemory( buf ); //载入技能恢复条 buf = epk.Read( "sb_bk.ecp" ); debug_assert( buf != NULL ); bk_surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); buf = epk.Read( "sb_ft.ecp" ); debug_assert( buf != NULL ); ft_surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); m_SkillBar.Init( bk_surf, ft_surf, 0, 0 ); //载入行动指针 buf = epk.Read( "cell_pointer.epg" ); debug_assert( buf != NULL ); m_cp_pg = new CPictureGroup; debug_assert( m_cp_pg != NULL ); m_cp_pg->LoadEPG( (char*)buf, false, 0, 0, 0 ); //载入英雄动画 for ( int i = 0; i < 7; ++i ) { char sz[32]; wsprintf( sz, HERO_EPG_NAME_ARRAY[i], indexClass ); buf = epk.Read( sz ); m_HeroEPGArray[i].LoadEPGFromMemory( (char*)buf ); } //载入声音 for ( i = 1; i <= 3; ++i ) { char sz[16]; wsprintf( sz, "%d.wav", indexClass * 10 + i ); buf = epk.Read( sz ); m_pClass->SoundArray.asSound[i] = g_pEasyAudio->CreateSoundBuffer( (char*)buf, false ); } //载入技能卡页面 int j = indexClass * 10; for ( i = 0; i < 10; ++i ) { char sz[12]; wsprintf( sz, "c%d.ecp", i + j ); buf = epk.Read( sz ); debug_assert( buf != NULL ); m_HeroSkillArray[i].cardSurface = g_pEasyDraw->CreateSurfaceFromMemory(buf); } epk.Close(); //载入英雄魔法 j = indexClass * 10; for ( i = 0; i < 10; ++i ) { theMagicFactory.OnLoadSI( i + j ); } for ( i = 0; i < 7; ++i ) { m_pClass->EPGArray.epg_array[i].pPG = m_HeroEPGArray[i].GetAnimation(); m_pClass->EPGArray.epg_array[i].pSPG= m_HeroEPGArray[i].GetShadow(); } int frame_per_direction = m_pClass->EPGArray.epg_walk.pPG->GetFramePerDirection(); if ( frame_per_direction % 2 == 0 ) m_move_frame = frame_per_direction / 2 - 1; else m_move_frame = frame_per_direction / 2; SetState( SS_WAIT ); return true; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::OnInitLvl() { int j = (int)m_HeroClass * 10; int n = m_pClass->SpriteInfo.m_Agility * 128; for ( int i = 0; i < 10; ++i ) { HERO_SKILL &skill = m_HeroSkillArray[i]; skill.pMagic = theMagicFactory.FindMagic( i + j ); int temp = skill.pMagic->GetInterval() - n; if ( temp < 0 ) temp = 0; skill.interval = temp; } } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// bool CHero::UpdateSprite() { bool re = true; bool bNextFrame = false; //是否更新下一帧 bool bUpdate = false; //是否完成一个动作 bool bMoveMap = false; unsigned int thisTick = timeGetTime(); //更新生命,魔法值,魔法状态与魔法状态动画 if ( thisTick - m_LastTime > 100 ) { m_LastTime = thisTick; m_Life += m_PlusInfo.m_AddLife; if ( m_Life <= 0 && m_State != SS_DEAD ) { SetState( SS_DEAD ); ClearMagicState(); m_move_frame = m_LastTick; } if ( m_Life > m_pClass->SpriteInfo.m_MaxLife ) m_Life = m_pClass->SpriteInfo.m_MaxLife; m_PlusInfo.m_Mana += m_PlusInfo.m_AddMana; if ( m_PlusInfo.m_Mana < 0 ) m_PlusInfo.m_Mana = 0; if ( m_PlusInfo.m_Mana > m_pClass->SpriteInfo.m_MaxMana ) m_PlusInfo.m_Mana = m_pClass->SpriteInfo.m_MaxMana; for ( int i = m_MagicStateArray.GetLength()-1; i >= 0; --i ) //更新魔法状态 { MAGIC_STATE &ms = m_MagicStateArray[i]; if ( thisTick > ms.endTime ) //如果魔法状态已经到结束时间 { AddInfo( ms.effectIndex, -ms.effectValue ); //还原作用值 m_MagicStateArray.Delete(i); //删除状态 } } for ( i = m_MSEArray.GetLength()-1; i >= 0; --i ) //更新魔法状态动画 { MAGIC_STATE_EPG &mse = m_MSEArray[i]; if ( thisTick > mse.endTime ) { m_MSEArray.Delete(i); //如果动画过期,则删除 } else { mse.curFrame++; //否则更新帧 mse.curFrame = mse.curFrame % mse.pEPG->GetNumFrame(); } } } //更新动画帧时间 if ( thisTick - m_LastTick > m_cur_pg->GetDelayTime() - m_PlusInfo.m_Speed ) //speed控制更新速度 { bNextFrame = true; m_LastTick = thisTick; if ( m_Frame == m_pClass->EPGArray.GetLastFrame(m_State) ) bUpdate = true; //如果到了动作的最后一帧 } else goto _exit; //如果不需要更新,则跳转到结束 //判断各个状态,并相应的更新 if ( m_State == SS_WAIT ) //静止状态 { if ( m_Frame == 0 ) { if ( m_HeroState == HS_GOTO_FIGHT ) { goto _goto_fight; } } if ( bUpdate ) { //如果没有攻击目标,则随机的进入空闲状态 m_pEnemy = NULL; if ( m_LastTick % 128 > 100 ) { SetState(SS_IDLE); bNextFrame = false; } } } else if ( m_State == SS_WALK ) //行走状态 { bMoveMap = true; if ( bUpdate ) //如果完成了一步 { if ( m_NextDest.row > -1 ) //如果用户改变了目的地 { GetPath( m_NextDest ); m_NextDest.row = -1; } else if ( m_HeroState == HS_GOTO_FIGHT ) //如果敌人活着,判断与敌人的距离 { _goto_fight: POINT p = m_SpellPoint; if ( m_pEnemy != NULL ) { if ( m_pEnemy->IsAlive() ) p = m_pEnemy->GetBasePoint(); else goto _no_walk; } if ( CalcDistance( m_BasePoint, p ) <= m_Distance ) { GetNextDirection( p ); if ( m_pMagic != NULL ) { Spell( m_pEnemy, p ); } else SetState( SS_MELEE ); m_HeroState = HS_FIGHTING; bNextFrame = false; bMoveMap = false; goto _exit; } else { GetPath( p ); } } if ( m_PathStack.Pop( m_NextCell ) ) //如果还没走完,获取下一步 { if ( theMap.IsCellHold( m_NextCell.row, m_NextCell.col ) ) { goto _no_walk; } POINT p; theMap.CellToPoint( m_NextCell, p ); GetNextDirection( p ); //获取下一步方向 } else { if ( m_HeroState == HS_PICK ) { PickItem( 0 ); m_HeroState = HS_NORMAL; } _no_walk: SetState( SS_WAIT ); //如果已经走完,进入静止状态 bNextFrame = false; bMoveMap = false; goto _exit; } } else if ( m_Frame == m_move_frame ) //到了移位帧,移动精灵到下一个CELL中 { if ( theMap.IsCellHold( m_NextCell.row, m_NextCell.col ) ) { SetState( SS_WAIT ); //如果下一个CELL已被占据,则不继续移动 bNextFrame = false; bMoveMap = false; goto _exit; } //解除原来CELL的占据,并占据下一个CELL theMap.NoHoldCell( m_BasePoint.y / CELL_HEIGHT, m_BasePoint.x / CELL_WIDTH ); theMap.HoldCell( m_NextCell.row, m_NextCell.col ); theMap.CellToPoint( m_NextCell, m_BasePoint ); CalcPriority(); //重新计算优先级 } } else if ( m_State == SS_IDLE || m_State == SS_HURT ) //空闲或受伤状态 { if ( bUpdate ) { SetState( SS_WAIT ); bNextFrame = false; } } else if ( m_State == SS_DEAD ) //死亡状态 { if ( m_SpriteType != ST_BODY ) { m_HeroState = HS_DEAD; m_pEnemy = NULL; theMap.NoHoldCell( m_BasePoint.y / CELL_HEIGHT, m_BasePoint.x / CELL_WIDTH ); m_SpriteType = ST_BODY; CalcPriority(); //重新计算优先级,尸体的优先级要更低 ClearMagicState(); theMsgMgr.AddMessage( "角色死亡" ); theMsgMgr.AddMessage( "五秒后复活" ); } else if ( bUpdate ) { bNextFrame = false; //死亡后,不再更新动作 if ( thisTick - m_move_frame > 15000 ) //死亡后,m_move_frame存储的是死亡时的时间 { GotoRevival(); Cure(); } } } else if ( m_State >= SS_MELEE ) //博斗或施法状态 { if ( m_Frame == m_pClass->EPGArray.GetMiddleFrame( m_State ) ) { if ( m_pMagic != NULL ) { m_pMagic->OnHeroEffect( this, m_pEnemy ); } else { if ( m_pEnemy != NULL && m_pEnemy->IsAlive() ) { if ( CalcDistance( m_BasePoint, m_pEnemy->GetBasePoint() ) <= m_Distance ) { GetNextDirection( m_pEnemy->GetBasePoint() ); m_pEnemy->Hurt( m_PlusInfo.m_Damage, this ); //敌人受到伤害 m_pClass->SoundArray.meleeSound->Play(); } } } } else if ( bUpdate ) { m_HeroState = HS_END_FIGHT; ClearCurMagic(); } } _exit: if ( bMoveMap ) MoveMap(); m_pg_frame = m_cur_pg->UpdateAliveSprite( bNextFrame, m_Frame, m_Direction, m_BasePoint, m_RenderPoint, m_Rect ); return re; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::DrawSprite() { if ( m_PathStack.IsEmpty() == false && m_State == SS_WALK ) { CELL cell = m_PathStack.GetStack()[0]; POINT p; theMap.CellToPoint( cell, p ); m_cp_pg->UpdateFrame( m_cp_frame, m_cp_last_tick ); m_cp_pg->DrawFrame( m_cp_frame, p ); } #ifdef ALPHA_SHADOW m_cur_shadow_pg->DrawShadow( m_pg_frame, m_BasePoint ); #endif m_cur_pg->DrawFrame( m_pg_frame, m_RenderPoint.x, m_RenderPoint.y ); DrawMSE(); } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::DrawBloodBar() { //画血条,魔条: m_HPBar.Draw( 0, 0, m_Life, m_pClass->SpriteInfo.m_MaxLife ); m_MPBar.Draw( 0, 25, m_PlusInfo.m_Mana, m_pClass->SpriteInfo.m_MaxMana ); } const int MOVE_X = 8; const int MOVE_Y = 4; //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::MoveMap() { const RECT &view = theMap.GetViewer(); int half_w = view.left + (view.right-view.left) / 2; int half_h = view.top + (view.bottom-view.top) / 2; switch ( m_Direction ) { case 1: if ( m_BasePoint.x >= half_w-64 ) theMap.MoveMap( MOVE_X, 0 ); break; case 2: if ( m_BasePoint.y >= half_h-32 || m_BasePoint.x >= half_w-64 ) theMap.MoveMap( MOVE_X, MOVE_Y ); break; case 3: if ( m_BasePoint.y >= half_h-32 ) theMap.MoveMap( 0, MOVE_Y); break; case 4: if ( m_BasePoint.x <= half_w+64 || m_BasePoint.y >= half_h-32 ) theMap.MoveMap( -MOVE_X, MOVE_Y ); break; case 5: if ( m_BasePoint.x <= half_w+64 ) theMap.MoveMap( -MOVE_X, 0 ); break; case 6: if ( m_BasePoint.x <= half_w+64 || m_BasePoint.y <= half_h+32 ) theMap.MoveMap( -MOVE_X, -MOVE_Y ); break; case 7: if ( m_BasePoint.y <= half_h+32 ) theMap.MoveMap( 0, -MOVE_Y ); break; case 8: if ( m_BasePoint.x >= half_w-64 || m_BasePoint.y <= half_h+32 ) theMap.MoveMap( MOVE_X, -MOVE_Y ); break; } } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::Cure() { m_Life = m_pClass->SpriteInfo.m_MaxLife; m_PlusInfo.m_Mana = m_pClass->SpriteInfo.m_MaxMana; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// bool CHero::AddLife( int add ) { bool re = false; if ( m_Life < m_pClass->SpriteInfo.m_MaxLife && m_State != SS_DEAD ) { MAGIC_STATE ms; ms.effectIndex = SI_ADDLIFE; ms.effectValue = add; ms.endTime = timeGetTime() + 2000; AddMagicState( ms ); m_PlusInfo.m_AddLife += add; re = true; } return re; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// bool CHero::AddMana( int add ) { bool re = false; if ( m_PlusInfo.m_Mana < m_pClass->SpriteInfo.m_MaxMana && m_State != SS_DEAD ) { MAGIC_STATE ms; ms.effectIndex = SI_ADDMANA; ms.effectValue = add; ms.endTime = timeGetTime() + 2000; AddMagicState( ms ); m_PlusInfo.m_AddMana += add; re = true; } return re; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// bool CHero::ChangeMoney( int value ) { if ( m_Money + value <= 2000000000 && m_Money + value >= 0 ) { m_Money += value; return true; } return false; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::AddHeroXp( int xp ) { int &heroXp = m_pClass->SpriteInfo.m_Xp; short &lvl = m_pClass->SpriteInfo.m_Level; heroXp += xp; if ( heroXp >= m_NextLvlXp ) { heroXp = 0; m_NextLvlXp = lvl * ( 16 * ((lvl/4)+1) * ((lvl/8)+1) * ((lvl/32)+1) * ((lvl/32)+1) );; lvl += 1; m_RestPoint += 3; theEquipmentBox.OnCloseEquipment(); //重新计算各项属性 theMsgMgr.AddMessage( "升级了" ); theMsgMgr.AddMessage( "可以分配剩余点数" ); Cure(); } } //////////////////////////////////////////////////////////////////////// //拾取物品,distance为物品与英雄的距离 //////////////////////////////////////////////////////////////////////// void CHero::PickItem( int distance ) { PTILE tile = theMap.GetTile( m_BasePoint.x, m_BasePoint.y ); debug_assert( tile != NULL ); CPool &pool = tile->m_APool; for ( pool.Begin(); pool.IsNotNull(); pool.MoveNext() ) { CBaseSprite *sprite = *(pool.GetCur()); if ( sprite->GetSpriteType() == ST_ITEM ) { if ( CalcDistance( m_BasePoint, sprite->GetBasePoint() ) <= distance ) { bool b = theItemBag.AddItem( (CItem *)sprite ); } } } } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::ClearItemInfo() { AS_BASE_INFO &baseInfo = m_pClass->SpriteInfo; for ( int i = 0; i < 12; ++i ) baseInfo.baseInfo[i] -= m_ItemBaseInfo.baseInfo[i]; //先把装备的属性减去 memset( &m_ItemBaseInfo, 0, sizeof(AS_BASE_INFO) ); memset( &m_ItemPlusInfo, 0, sizeof(AS_PLUS_INFO) ); } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::AddHeroInfo( int index, int value ) { debug_assert( index >= SI_END && index <= SI_BEGIN ); if ( index >= SI_THUNDER ) { m_ItemBaseInfo.baseInfo[(-index) + SI_BEGIN] += value; } else if ( index <= SI_MP ) { m_ItemPlusInfo.plusInfo[(-index) + SI_MP] += value; } } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::CalcHeroInfo() { AS_BASE_INFO &baseInfo = m_pClass->SpriteInfo; for ( int i = 0; i < 12; ++i ) baseInfo.baseInfo[i] += m_ItemBaseInfo.baseInfo[i]; //先把装备的属性加到基本属性上 int mana = m_PlusInfo.m_Mana; ZeroMemory( &m_PlusInfo, sizeof(m_PlusInfo) ); //计算最大生命值 生命=力量*4 + 敏捷*2 + 智力 + 等级*4 baseInfo.m_MaxLife = baseInfo.m_Strength * 4 + baseInfo.m_Agility * 2 + baseInfo.m_Intelligence + baseInfo.m_Level * 4; baseInfo.m_MaxMana = baseInfo.m_Intelligence * 4 + baseInfo.m_Level; //最大魔法值 = 智力 * 4 + 级别 m_PlusInfo.m_Accuracy = baseInfo.m_Agility + baseInfo.m_Level; //计算命中率 = 敏捷 + 级别 m_PlusInfo.m_Resistance = baseInfo.m_Agility / 2 + baseInfo.m_Level / 4;//计算回避率 = 敏捷 / 2 + 级别 / 4 m_PlusInfo.m_Armor = baseInfo.m_Strength / 4 + baseInfo.m_Level / 4; //计算防御 = 力量 / 4 + 级别/4 if ( m_HeroClass == SC_FENCER ) m_PlusInfo.m_Damage = baseInfo.m_Strength / 2 + baseInfo.m_Level / 2;//伤害 = 力量 / 2 + 级别 / 2; else m_PlusInfo.m_Damage = baseInfo.m_Intelligence/ 2 + baseInfo.m_Level / 2; m_PlusInfo.m_Mana = mana; baseInfo.baseInfo[1] += m_ItemBaseInfo.baseInfo[1]; //最大生命值 baseInfo.baseInfo[2] += m_ItemBaseInfo.baseInfo[2]; for ( i = 0; i < 8; ++i ) m_PlusInfo.plusInfo[i] += m_ItemPlusInfo.plusInfo[i];//附加属性 for ( i = 0; i < m_MagicStateArray.GetLength(); ++i ) { MAGIC_STATE &state = m_MagicStateArray[i]; AddInfo( state.effectIndex, state.effectValue ); //加上魔法状态的属性 } } //信息面版上各个属性显示的位置偏移 //顺序:名字,等级,最大生命,最大魔法,力量,敏捷,知识,毒抗,诅抗,火抗,水抗,电抗,伤害,防御,回避,命中,经验,剩余点 const POINT INFO_OFFSET[19] = { {62, 16}, {220, 15}, {229, 78}, {230, 110}, {62, 79}, {62, 112}, {63, 145}, {230, 143}, {230, 176}, {230, 208}, {230, 241}, {230, 272}, {63, 176}, {63, 206}, {64, 239}, {64, 272}, {221, 46}, {63, 49}, {101, 300}}; //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::ShowHeroInfo() { if ( !m_isInfoDlgOpen ) return; int x = ( g_pEasyDraw->GetDeviceWidth() - m_InfoSurface->GetWidth() ) / 2; int y = ( g_pEasyDraw->GetDeviceHeight()- m_InfoSurface->GetHeight()) / 2; m_InfoSurface->DrawSurface( x, y, 0 ); //绘制信息窗口在屏幕中央 char sz[8]; m_TempSurface->ClearSurface( 0, 0 ); m_TempSurface->WriteText( m_HeroName, strlen(m_HeroName), 0, 0, 0xffffff ); m_TempSurface->DrawSurface( x + INFO_OFFSET[0].x, y + INFO_OFFSET[0].y, 0 ); //绘制英雄名字 for ( int i = 0; i < 11; ++i ) //绘制等级,生,魔,力,敏,智,毒,诅,火,水,电 { wsprintf( sz, "%d", m_pClass->SpriteInfo.baseInfo[i] ); m_TempSurface->ClearSurface( 0, 0 ); m_TempSurface->WriteText( sz, strlen(sz), 0, 0, 0xffffff ); m_TempSurface->DrawSurface( x + INFO_OFFSET[i+1].x, y + INFO_OFFSET[i+1].y, 0 ); } wsprintf( sz, "%d", m_pClass->SpriteInfo.m_Xp ); //经验 m_TempSurface->ClearSurface( 0, 0 ); m_TempSurface->WriteText( sz, strlen(sz), 0, 0, 0xffffff ); m_TempSurface->DrawSurface( x + INFO_OFFSET[16].x, y + INFO_OFFSET[16].y, 0 ); wsprintf( sz, "%d", m_RestPoint ); //剩余点数 m_TempSurface->ClearSurface( 0, 0 ); m_TempSurface->WriteText( sz, strlen(sz), 0, 0, 0xffffff ); m_TempSurface->DrawSurface( x + INFO_OFFSET[17].x, y + INFO_OFFSET[17].y, 0 ); for ( i = 1; i < 5; ++i ) { wsprintf( sz, "%d", m_PlusInfo.plusInfo[i] ); m_TempSurface->ClearSurface( 0, 0 ); m_TempSurface->WriteText( sz, strlen(sz), 0, 0, 0xffffff ); m_TempSurface->DrawSurface( x + INFO_OFFSET[i+11].x, y + INFO_OFFSET[i+11].y, 0 ); } wsprintf( sz, "%d", m_NextLvlXp ); //下一级经验值 m_TempSurface->ClearSurface( 0, 0 ); m_TempSurface->WriteText( sz, strlen(sz), 0, 0, 0xffffff ); m_TempSurface->DrawSurface( x + INFO_OFFSET[18].x, y + INFO_OFFSET[18].y, 0 ); } const RECT INFO_BUTTON[3] = { {127, 74, 150, 97}, {127, 107, 150, 130}, {127, 140, 150, 163}, }; //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// int CHero::UpdateInfoDlg() { if ( !m_isInfoDlgOpen ) return 0; RECT rc; rc.left = ( g_pEasyDraw->GetDeviceWidth() - m_InfoSurface->GetWidth() ) / 2; rc.top = ( g_pEasyDraw->GetDeviceHeight()- m_InfoSurface->GetHeight()) / 2; rc.right = rc.left + m_InfoSurface->GetWidth(); rc.bottom= rc.top + m_InfoSurface->GetHeight(); int mx= theMouse.GetX(); int my= theMouse.GetY(); int re = 0; if ( mx >= rc.left && mx < rc.right ) { if ( my >= rc.top && my < rc.bottom ) { re = 1; if ( theMouse.IsLPress() ) { if ( m_RestPoint > 0 ) { for ( int i = 0; i < 3; ++i ) { if ( mx >= rc.left + INFO_BUTTON[i].left && mx < rc.left + INFO_BUTTON[i].right ) { if ( my >= rc.top + INFO_BUTTON[i].top && my < rc.top + INFO_BUTTON[i].bottom ) { m_pClass->SpriteInfo.baseInfo[i+3]+=1; m_RestPoint--; theEquipmentBox.OnCloseEquipment(); break; } } } } if ( mx >= rc.left + 277 && mx < rc.right + 310 ) { if ( my >= rc.top + 304 && my < rc.top + 337 ) m_isInfoDlgOpen = false; } } } } return re; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::SetCurMagic( int index ) { debug_assert( index >= 1 && index <= 10 ); m_pCurSkill = &m_HeroSkillArray[index-1]; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// bool CHero::Spell( CAliveSprite *pTarget, POINT &p ) { bool re = false; if ( m_pCurSkill != NULL ) { DWORD thisTime = timeGetTime(); if ( thisTime - m_pCurSkill->lastTime > m_pCurSkill->interval ) { m_pMagic = m_pCurSkill->pMagic; m_pEnemy = pTarget; m_Distance = m_pMagic->GetDistance(); POINT dest = p; if ( m_pMagic->IsSelf() ) { pTarget = (CAliveSprite *)this; } else if ( m_pMagic->IsTarget() ) { if ( pTarget == NULL ) { m_pMagic = NULL; return false; } else dest = pTarget->GetBasePoint(); } if ( m_PlusInfo.m_Mana - m_pMagic->GetMana() > 0 ) { re = true; if ( CalcDistance( m_BasePoint, dest ) <= m_Distance ) { GetNextDirection( dest ); m_pMagic->OnHeroSpell( this, pTarget, dest ); m_PlusInfo.m_Mana -= m_pMagic->GetMana(); m_pCurSkill->lastTime = thisTime; m_HeroState = HS_FIGHTING; } else { GetPath( dest ); m_SpellPoint = dest; m_HeroState = HS_GOTO_FIGHT; } } else { theMsgMgr.AddMessage( "精力不足" ); m_pMagic = NULL; } } else theMsgMgr.AddMessage( "魔法尚未恢复" ); } return re; } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::ShowControlPanel() { int x = g_pEasyDraw->GetDeviceWidth() - m_GuiSurface->GetWidth(); int y = g_pEasyDraw->GetDeviceHeight()- m_GuiSurface->GetHeight(); m_GuiSurface->DrawSurface( x, y, 0 ); //绘制技能卡片 if ( m_pCurSkill != NULL ) { m_pCurSkill->cardSurface->DrawSurface( x + 27, y + 8, 0 ); unsigned int curTime = m_pCurSkill->interval - ( timeGetTime() - m_pCurSkill->lastTime ); m_SkillBar.Draw( x + 67, y + 11, curTime, m_pCurSkill->interval ); } } const RECT GUI_BUTTON[6] = { {19,62,41,85}, {47,62,70,85}, {76,62,100,85}, {19,91,41,114,}, {47,91,70,114}, {76,91,100,114} }; //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// int CHero::UpdateControlPanel( int re ) { if ( re == 0 ) { int x = g_pEasyDraw->GetDeviceWidth() - m_GuiSurface->GetWidth(); int y = g_pEasyDraw->GetDeviceHeight()- m_GuiSurface->GetHeight(); int mx = theMouse.GetX(); int my = theMouse.GetY(); if ( mx >= x && mx < g_pEasyDraw->GetDeviceWidth() ) { if ( my >= y && my < g_pEasyDraw->GetDeviceHeight() ) { re = 1; if ( theMouse.IsLPress() ) { if ( mx >= x + GUI_BUTTON[0].left && mx < x + GUI_BUTTON[0].right ) { if ( my >= y + GUI_BUTTON[0].top && my < y + GUI_BUTTON[0].bottom ) theItemBag.ChangeState(); } else if ( mx >= x + GUI_BUTTON[1].left && mx < x + GUI_BUTTON[1].right ) { if ( my >= y + GUI_BUTTON[1].top && my < y + GUI_BUTTON[1].bottom ) theEquipmentBox.ChangeState(); } else if ( mx >= x + GUI_BUTTON[2].left && mx < x + GUI_BUTTON[2].right ) { if ( my >= y + GUI_BUTTON[2].top && my < y + GUI_BUTTON[2].bottom ) ChangeInfoDlg(); } } } } } return re; } const CELL ROUND_CELL[8] = { CELL(0,1), CELL(1,1), CELL(1,0), CELL(1,-1), CELL(0,-1), CELL(-1,-1), CELL(-1,0), CELL(-1,1) }; //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::MoveHeroTo( const POINT &to ) { CELL dest, base; theMap.PointToCell( to, dest ); theMap.PointToCell( m_BasePoint, base ); if ( theMap.IsCellHold( dest.row, dest.col ) ) { bool b = false; int dir = CalcDirection( dest, base )-1; for ( int i = 0; i < 8; ++i ) { dest.row += ROUND_CELL[dir].row; dest.col += ROUND_CELL[dir].col; if ( theMap.IsCellHold( dest.row, dest.col ) == false ) { b = true; break; } ++dir; dir %= 8; } if ( !b ) return; //如果周围CELL无一可走 } theMap.NoHoldCell( base.row, base.col ); theMap.HoldCell( dest.row, dest.col ); theMap.CellToPoint( dest, m_BasePoint ); CalcPriority(); theMap.CalcViewerRect( m_BasePoint.x, m_BasePoint.y ); } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::SetRevival( const char *name ) { ZeroMemory( m_RevivalMapName, 32 ); strcpy( m_RevivalMapName, name ); theMsgMgr.AddMessage( "复活位置指定" ); } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::GotoRevival() { theGameManager.GotoMap( m_RevivalMapName, 1 ); m_SpriteType = ST_HERO; int frame_per_direction = m_pClass->EPGArray.epg_walk.pPG->GetFramePerDirection(); if ( frame_per_direction % 2 == 0 ) m_move_frame = frame_per_direction / 2 - 1; else m_move_frame = frame_per_direction / 2; } //////////////////////////////////////////////////////////////////////// //新建某职业的英雄 //////////////////////////////////////////////////////////////////////// void CHero::NewHero( const char *heroName, HERO_CLASS heroClass ) { strcpy( m_HeroName, heroName ); SetRevival( "zen_en.map" ); m_HeroClass = heroClass; AS_BASE_INFO &baseInfo = m_pClass->SpriteInfo; ZeroMemory( &baseInfo, sizeof(baseInfo) ); ZeroMemory( &m_ItemBaseInfo, sizeof(m_ItemBaseInfo) ); ZeroMemory( &m_ItemPlusInfo, sizeof(m_ItemPlusInfo) ); baseInfo.m_Level = 1; if ( m_HeroClass == SC_FENCER ) { baseInfo.m_Strength = 15; baseInfo.m_Agility = 10; baseInfo.m_Intelligence=5; } else { baseInfo.m_Strength = 5; baseInfo.m_Agility = 10; baseInfo.m_Intelligence=15; } m_NextLvlXp = 16; m_RestPoint = 0; m_Money = 1000; m_HeroState = HS_NORMAL; m_pCurSkill = NULL; CalcHeroInfo(); Cure(); LoadHeroRes( heroClass ); theMap.SetNextMap( "..\\data\\zen_en.map" ); } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::SaveHero() { /******************************************************** *为了保护游戏资源,此函数内容省略 ********************************************************/ } //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// void CHero::LoadHero( const char *heroName ) { /******************************************************** *为了保护游戏资源,此函数内容省略 ********************************************************/ }