www.gusucode.com > 基于VC++的PRG游戏角色走动模块示例-源码程序 > 基于VC++的PRG游戏角色走动模块示例-源码程序\code\Battle.cpp
// // 执行战斗 //Download by http://www.NewXing.com // Copyright (c) 2000-2001 Chihiro.SAKAMOTO (HyperWorks) // #include "stdafx.h" #include <stdlib.h> #include "MainWin.h" #include "File.h" #include "Misc.h" #include "Battle.h" // // 构造函数 // CBattleAction::CBattleAction(CMainWin *win, CAction *oldAction): CAction(win, oldAction), _map_data(0), map_data(0), ViewImage(win->GetViewImage()) { status = STATUS_NONE; } // // 析构函数 // CBattleAction::~CBattleAction() { delete _map_data; delete map_data; } // // 按下鼠标左键时执行的处理 // void CBattleAction::LButtonDown(UINT modKeys, CPoint point) { CPoint pos = PointToIndex(point); // 需要地图座标 switch (status) { case STATUS_NONE: // 选取游戏的角色 if (MapRect.PtInRect(pos) && map_data[pos.y][pos.x].type & PLAYER) { SelPos = pos; SelChar = (CCharacter *)map_data[SelPos.y][SelPos.x].sprite; FindDist(pos.x, pos.y, 4); // 暂时固定在4步 status = STATUS_MOVE; } break; case STATUS_MOVE: // 点选时的移动范围 if (MapRect.PtInRect(pos) && map_data[pos.y][pos.x].type & MOVEDIST) { MovePlayer(SelChar, pos); } break; case STATUS_ANIME: break; } } // // 移动鼠标时的处理 // void CBattleAction::MouseMove(UINT modKeys, CPoint point) { switch (status) { case STATUS_NONE: // 初始状态 case STATUS_MOVE: // 显示移动范围 SetCursor(PointToIndex(point)); break; } } // // 计时器的处理 // bool CBattleAction::TimedOut(int timerId) { switch (timerId) { case TIMER_MOVE_ID: // 移动动画 { ASSERT(status == STATUS_ANIME); MoveAnime &ar = anime.front(); CCharacter *character = ar.character; RemoveSprite(character); character->MoveAnime(ar.action, ar.count); AddSprite(character); if (ar.count++ == 3) { // 4个模式后前进到下一格 anime.pop_front(); // 若不再登录,则结束动画 if (anime.size() == 0) { CPoint pos = character->GetMapPoint(); map_data[pos.y][pos.x].type |= PLAYER; map_data[pos.y][pos.x].sprite = character; status = STATUS_NONE; return true; } } } break; } return false; } // // 初始化 // bool CBattleAction::Init() { // 读入CG资料 if (!Cursor.LoadImage("cursor") || !MapImage.LoadImage("map1") || !Player.LoadImage("fighter") || !Enemy.LoadImage("puyo")) return false; // 设定sprite CursorSprite.Set(&Cursor, CPoint(0, 0), CSize(MAPGRID_WIDTH, MAPGRID_HEIGHT), CMapSprite::DEPTH_CURSOR); CursorPos.x = -1; CursorPos.y = -1; SelPos.x = -1; SelPos.y = -1; SelChar = 0; status = STATUS_NONE; MapSize.cx = MapSize.cy = 10; // 地图的尺寸大小 MapRect.SetRect(0, 0, MapSize.cx, MapSize.cy); // 确认map-data的可用空间 _map_data = new MapData[MapSize.cx * MapSize.cy]; map_data = new MapData *[MapSize.cy]; for (int i=0; i<MapSize.cy; i++) { map_data[i] = _map_data + i * MapSize.cx; } // 把游戏者的人物新增到座标5, 5 { map_data[5][5].type = PLAYER; player_list.push_back(CCharacter(&Player, 5, 5, CCharacter::DEPTH_CHAR)); CCharacter &s = player_list.back(); sprite.insert(&s); s.SetDirection(CCharacter::RIGHT); map_data[5][5].sprite = &s; } // 把敌人的人物新增到座标6, 3 { map_data[3][6].type = ENEMY; enemy_list.push_back(CCharacter(&Enemy, 6, 3, CCharacter::DEPTH_CHAR)); CCharacter &s = enemy_list.back(); sprite.insert(&s); s.SetDirection(CCharacter::RIGHT); map_data[3][6].sprite = &s; } DrawMap(ViewImage); Parent->InvalidateRect(NULL); return true; } // // 产生地图画面 // void CBattleAction::DrawMap(CImage *image, const CRect &rect) { // 若地图有背景,则显示之 if (MapImage.IsOK()) { image->Copy(&MapImage, rect); } // 显示sprite for (mapset::iterator p = sprite.begin(); p != sprite.end(); p++) { (*p)->Draw(image, rect); } } // // 显示地图(整个地图) // void CBattleAction::DrawMap(CImage *image) { DrawMap(image, CRect(0, 0, WindowWidth, WindowHeight)); } // // 移动地图光标 // void CBattleAction::SetCursor(CPoint point) { if (CursorPos != point) { // 若地图位置有更改 ClearCursor(); // 则删除目前显示的光标 CursorPos = point; // 重新设定新的位置 DrawCursor(); // 显示新的光标 } } // // 删除地图光标 // void CBattleAction::ClearCursor() { if (MapRect.PtInRect(CursorPos)) { RemoveSprite(&CursorSprite); } CursorPos.x = CursorPos.y = -1; } // // 显示地图光标 // void CBattleAction::DrawCursor() { if (MapRect.PtInRect(CursorPos)) { CursorSprite.SetMapPoint(CursorPos); AddSprite(&CursorSprite); } } // 重新绘制sprite void CBattleAction::RedrawSprite(CSprite *s) { CRect rect; s->GetRect(&rect); UpdateRect(rect); } // 新增sprite void CBattleAction::AddSprite(CSprite *s) { sprite.insert(s); RedrawSprite(s); } // 删除sprite void CBattleAction::RemoveSprite(CSprite *s) { if (sprite.erase(s)) { RedrawSprite(s); } } // 寻找移动范围 void CBattleAction::FindDist(int x, int y, int dist, bool first) { if (!first) { AddDistCursor(x, y, dist, 0); map_data[y][x].type |= MOVEDIST; } map_data[y][x].dist = dist; if (dist == 0) return; if (y > MapRect.top && map_data[y - 1][x].ChkMove(dist)) FindDist(x, y - 1, dist - 1, false); if (y < MapRect.bottom - 1 && map_data[y + 1][x].ChkMove(dist)) FindDist(x, y + 1, dist - 1, false); if (x > MapRect.left && map_data[y][x - 1].ChkMove(dist)) FindDist(x - 1, y, dist - 1, false); if (x < MapRect.right - 1 && map_data[y][x + 1].ChkMove(dist)) FindDist(x + 1, y, dist - 1, false); } // 显示范围 void CBattleAction::AddDistCursor(int x, int y, int dist, int type) { // 已登录的部分 if ((map_data[y][x].type & (MOVEDIST | ATTACKDIST)) != 0) return; cursor_list.push_back(CMapSprite(&Cursor, x, y, CSize(MAPGRID_WIDTH, MAPGRID_HEIGHT), CMapSprite::DEPTH_AREA)); CMapSprite &s = cursor_list.back(); s.SetSrcPos(0, 32 + type * 32); AddSprite(&s); } // 删除显示范围 void CBattleAction::ClearDistCursor() { while (cursor_list.size()) { CMapSprite &cr = cursor_list.front(); CPoint pos = cr.GetMapPoint(); RemoveSprite(&cr); map_data[pos.y][pos.x].type &= ~(MOVEDIST | ATTACKDIST); map_data[pos.y][pos.x].dist = 0; cursor_list.pop_front(); } } // 人物移动 void CBattleAction::MovePlayer(CCharacter *character, CPoint point) { MoveCharacter(point.x, point.y, map_data[point.y][point.x].dist, character); CPoint pos = character->GetMapPoint(); map_data[pos.y][pos.x].type = NONE; map_data[pos.y][pos.x].sprite = 0; map_data[pos.y][pos.x].dist = 0; SetCursor(CPoint(-1, -1)); ClearDistCursor(); StartAnime(); } // 登录人物的移动动画 void CBattleAction::MoveCharacter(int x, int y, int dist, CCharacter *character) { if (map_data[y][x].sprite != character) { dist++; if (y > MapRect.top && map_data[y - 1][x].dist == dist) { MoveCharacter(x, y - 1, dist, character); anime.push_back(MoveAnime(character, CCharacter::DOWN)); } else if (y < MapRect.bottom - 1 && map_data[y + 1][x].dist == dist) { MoveCharacter(x, y + 1, dist, character); anime.push_back(MoveAnime(character, CCharacter::UP)); } else if (x > MapRect.left && map_data[y][x - 1].dist == dist) { MoveCharacter(x - 1, y, dist, character); anime.push_back(MoveAnime(character, CCharacter::RIGHT)); } else if (x < MapRect.right - 1 && map_data[y][x + 1].dist == dist) { MoveCharacter(x + 1, y, dist, character); anime.push_back(MoveAnime(character, CCharacter::LEFT)); } } } // 执行移动动画 void CBattleAction::StartAnime() { if (anime.size()) { Parent->SetTimer(TIMER_MOVE_ID, TIMER_MOVE_TIME); status = STATUS_ANIME; } else { status = STATUS_NONE; } }