www.pudn.com > PG20101.zip > Battle.cpp


// 
// 執行戰鬥 
// 
//		Copyright (c) 2000-2001 Chihiro.SAKAMOTO (HyperWorks) 
// 
#include "stdafx.h" 
#include  
#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::KeyDown(UINT key) 
{ 
	if (status == STATUS_NONE) { 
		CCharacter &s = player_list.back(); 
		CPoint pos = s.GetMapPoint(); 
 
		switch (key) { 
		  case VK_UP: 
			if (pos.y > MapRect.top && map_data[pos.y - 1][pos.x].type == NONE) { 
				map_data[pos.y][pos.x].type = NONE; 
				map_data[pos.y][pos.x].sprite = 0; 
				anime.push_back(MoveAnime(&s, CCharacter::UP)); 
			} 
			break; 
 
		  case VK_DOWN: 
			if (pos.y < MapRect.bottom - 1 && map_data[pos.y + 1][pos.x].type == NONE) { 
				map_data[pos.y][pos.x].type = NONE; 
				map_data[pos.y][pos.x].sprite = 0; 
				anime.push_back(MoveAnime(&s, CCharacter::DOWN)); 
			} 
			break; 
 
		  case VK_LEFT: 
			if (pos.x > MapRect.left && map_data[pos.y][pos.x - 1].type == NONE) { 
				map_data[pos.y][pos.x].type = NONE; 
				map_data[pos.y][pos.x].sprite = 0; 
				anime.push_back(MoveAnime(&s, CCharacter::LEFT)); 
			} 
			break; 
 
		  case VK_RIGHT: 
			if (pos.x < MapRect.right - 1 && map_data[pos.y][pos.x + 1].type == NONE) { 
				map_data[pos.y][pos.x].type = NONE; 
				map_data[pos.y][pos.x].sprite = 0; 
				anime.push_back(MoveAnime(&s, CCharacter::RIGHT)); 
			} 
			break; 
 
		  default: 
			return; 
		} 
		StartAnime(); 
	} 
} 
 
// 
// 計時器的處理 
// 
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; iInvalidateRect(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; 
	} 
}