📄 battle.cpp
字号:
Error(reader, "无法读取CG资料");
return false;
}
return true;
}
//
// 把map上的文字改成状态
//
int CBattleAction::FindMapStatus(const char *find)
{
struct {
char str[4];
unsigned type;
} table[] = {
{ "□", NONE },
{ "■", RESTRICTED_AREA },
{ "一", PLAYER | (0 << 8) },
{ "二", PLAYER | (1 << 8) },
{ "三", PLAYER | (2 << 8) },
{ "四", PLAYER | (3 << 8) },
{ "五", PLAYER | (4 << 8) },
{ "六", PLAYER | (5 << 8) },
{ "七", PLAYER | (6 << 8) },
{ "八", PLAYER | (7 << 8) },
{ "九", PLAYER | (8 << 8) },
{ "1", ENEMY | (0 << 8) },
{ "2", ENEMY | (1 << 8) },
{ "3", ENEMY | (2 << 8) },
{ "4", ENEMY | (3 << 8) },
{ "5", ENEMY | (4 << 8) },
{ "6", ENEMY | (5 << 8) },
{ "7", ENEMY | (6 << 8) },
{ "8", ENEMY | (7 << 8) },
{ "9", ENEMY | (8 << 8) },
{ "Ⅰ", OBJECT | (0 << 8) },
{ "Ⅱ", OBJECT | (1 << 8) },
{ "Ⅲ", OBJECT | (2 << 8) },
{ "Ⅳ", OBJECT | (3 << 8) },
{ "Ⅴ", OBJECT | (4 << 8) },
{ "Ⅵ", OBJECT | (5 << 8) },
{ "Ⅶ", OBJECT | (6 << 8) },
{ "Ⅷ", OBJECT | (7 << 8) },
{ "Ⅸ", OBJECT | (8 << 8) },
} ;
for (int i=0; i<(sizeof(table) / sizeof(table[0])); i++) {
if (strcmp(find, table[i].str) == 0)
return table[i].type;
}
return -1;
}
// map
bool CBattleAction::MapCmd(TextReader &reader, Lexer &lexer)
{
if (map_data == 0) { // 此时,已经要决定地图的大小
Error(reader, "请先设定mapsize");
return false;
}
for (int y=0; y<MapSize.cy; y++) {
const char *str = reader.GetString();
if (str == 0) {
Error(reader, "文法错误");
return false;
}
for (int x=0; x<MapSize.cx; x++) {
char chip[3];
chip[0] = str[x * 2 + 0];
chip[1] = str[x * 2 + 1];
chip[2] = 0;
int idx = FindMapStatus(chip);
if (idx < 0) {
Error(reader, "文法错误");
return false;
}
map_data[y][x].type = (unsigned char)idx;
if (idx != RESTRICTED_AREA && idx != NONE) {
map<int, CChip>::iterator p = chip_list.find(idx);
if (p == chip_list.end()) { // 尚未登录
Error(reader, "人物角色尚未登录");
return false;
}
else {
TRACE("[%s] = %d, %d\n", p->second.name.c_str(), x, y);
if ((idx & PLAYER) != 0) {
player_list.push_back(CCharacter(p->second.image, x, y, CCharacter::DEPTH_CHAR));
CCharacter &s = player_list.back();
// 根据人物姓名读入状态
CStatus *status = Parent->GetParam().GetStatus(p->second.name.c_str());
if (status == 0) { // 无的状态
Error(reader, "找不到人物%s的状态信息");
return false;
}
s.status = *status;
sprite.insert(&s);
s.SetDirection(CCharacter::RIGHT);
map_data[y][x].sprite = &s;
StatusCharacter[idx >> 8] = &s; // 显示用人物相关信息
}
else if ((idx & ENEMY) != 0) {
enemy_list.push_back(CCharacter(p->second.image, x, y, CCharacter::DEPTH_CHAR));
CCharacter &s = enemy_list.back();
// 根据人物姓名读入状态
CStatus *status = Parent->GetParam().GetStatus(p->second.name.c_str());
if (status == 0) { // 无的状态
Error(reader, "找不到人物%s的状态信息");
return false;
}
s.status = *status;
sprite.insert(&s);
s.SetDirection(CCharacter::LEFT);
map_data[y][x].sprite = &s;
}
else if ((idx & OBJECT) != 0) {
object_list.push_back(CMapSprite(p->second.image, x, y, CMapSprite::DEPTH_OBJECT));
CMapSprite &s = object_list.back();
sprite.insert(&s);
map_data[y][x].sprite = &s;
}
}
}
}
}
return true;
}
//
// 读入地图定义档
//
bool CBattleAction::LoadMap(const char *name)
{
typedef bool (CBattleAction::*cmd_t)(TextReader &, Lexer &);
typedef pair<const char *, cmd_t> CmdTab;
typedef map<const char *, cmd_t, ic_less> cmdmap;
cmdmap cmd_table;
cmd_table.insert(CmdTab("player", &CBattleAction::PlayerCmd));
cmd_table.insert(CmdTab("enemy", &CBattleAction::EnemyCmd));
cmd_table.insert(CmdTab("object", &CBattleAction::ObjectCmd));
cmd_table.insert(CmdTab("mapsize", &CBattleAction::MapSizeCmd));
cmd_table.insert(CmdTab("mapimage", &CBattleAction::MapImageCmd));
cmd_table.insert(CmdTab("map", &CBattleAction::MapCmd));
char path[_MAX_PATH];
sprintf(path, MAPPATH "%s.txt", name);
TextReader reader(path);
if (!reader) {
Parent->MessageBox("无法读取地图档案。");
return false;
}
const char *str;
while ((str = reader.GetString()) != 0) {
Lexer lexer(str);
if (lexer.NumToken()) {
const char *cmd = lexer.GetString(0);
if (stricmp(cmd, "end") == 0) // 结束
break;
cmdmap::iterator p = cmd_table.find(cmd);
if (p != cmd_table.end()) {
if (!(this->*p->second)(reader, lexer))
return false;
}
else {
Error(reader, "文法错误");
return false;
}
}
}
return true;
}
//
// 读入战斗地图的资料
//
bool CBattleAction::Load(const char *name)
{
// 若仍残留之前的状态,则为error
// 应该不会有这个状态,故设为ASSERT
ASSERT(map_data == 0);
ASSERT(_map_data == 0);
// 读入地图资料
if (!LoadMap(name))
return false;
// 读入CG资料
if (!Cursor.LoadImage("cursor")
|| !Command.LoadImage("command")
|| !TurnEnd.LoadImage("turnend")
|| !StatusBase.LoadImage("status")
|| !PopupImageBase.LoadImage("popup")
|| !PopupParts.LoadImage("popup_parts")
|| !FireBallImage.LoadImage("fireball")
|| !HealImage.LoadImage("heal")
|| !Explosion.LoadImage("explosion"))
return false;
// 产生图像
CClientDC dc(Parent);
if (!PopupImage.Create(dc, PopupImageBase.Width(), PopupImageBase.Height()))
return false;
// 设定sprite
CursorSprite.Set(&Cursor, CPoint(0, 0), CSize(MAPGRID_WIDTH, MAPGRID_HEIGHT), CMapSprite::DEPTH_CURSOR);
{
for (int i=0; i<MAX_COMMAND; i++) {
CommandSprite[i].Set(&Command, CPoint(0, 0), CPoint(0, i * 22), CSize(70, 22), 0);
CommandSprite[i].Show(false);
}
}
TurnEndSprite.Set(&TurnEnd, CPoint(0, 0), CPoint(0, 0), CSize(70, 22), 0);
PopupSprite.Set(&PopupImage, CPoint(0, 0), CPoint(0, 0), PopupImage.Size(), 0);
// 人物的状态
int total_width = StatusBase.Width() * MAX_CHARACTER + 3 * (MAX_CHARACTER - 1);
int x = (WindowWidth - total_width) / 2;
int y = WindowHeight - StatusBase.Height() - 10;
{
for (int i=0; i<MAX_CHARACTER; i++) {
if (!Status[i].Create(dc, StatusBase.Width(), StatusBase.Height()))
return false;
StatusSprite[i].Set(Status + i, CPoint(x, y), CPoint(0, 0), StatusBase.Size(), 0);
x += StatusBase.Width() + 3;
SetPlayerStatus(i);
}
}
CursorPos.x = -1;
CursorPos.y = -1;
SelPos.x = -1;
SelPos.y = -1;
SelChar = 0;
status = STATUS_WAIT_START;
turn = PLAYER_TURN;
NumberView = 0;
StatusChar = 0;
DrawMap(MixedImage);
Parent->WipeIn();
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);
}
// 显示角色的状态
for (int i=0; i<MAX_CHARACTER; i++) {
StatusSprite[i].Draw(image, rect);
}
// 显示光标位置的状态
if (StatusChar != 0) {
PopupSprite.Draw(image, rect);
}
// 照编号显示贴图零件(sprite)
for (int j=0; j<NumberView; j++)
Number[j].Draw(image, rect);
// 显示菜单
switch (status) {
case STATUS_COMMAND:
{
for (int i=0; i<MAX_COMMAND; i++) {
if (CommandSprite[i].IsShow())
CommandSprite[i].Draw(image, rect);
}
}
break;
case STATUS_NEXTTURN:
TurnEndSprite.Draw(image, rect);
break;
}
}
//
// 显示地图(整个地图)
//
void CBattleAction::DrawMap(CImage *image)
{
DrawMap(image, CRect(0, 0, WindowWidth, WindowHeight));
}
//
// 建立人物状态的图像
//
void CBattleAction::SetPlayerStatus(int player)
{
Status[player].Copy(&StatusBase);
if (StatusCharacter[player] != 0) {
CStatus &status = StatusCharacter[player]->status;
CImageDC dc(Status + player);
HFONT oldFont = dc.SelectObject(hFont);
dc.SetTextColor(WhitePixel);
dc.SetBkMode(TRANSPARENT);
char str[256];
dc.ExtTextOut(10, 4, 0, 0, status.name, strlen(status.name), NULL);
dc.ExtTextOut(10, 22, 0, 0, str, sprintf(str, "等级 %7d", status.level), NULL);
dc.ExtTextOut(10, 40, 0, 0, str, sprintf(str, "经验值 %7d", status.experience), NULL);
dc.ExtTextOut(10, 58, 0, 0, str, sprintf(str, "HP值 %3d/%3d", status.hit_point, status.max_hit_point), NULL);
dc.ExtTextOut(10, 76, 0, 0, str, sprintf(str, "MP值 %3d/%3d", status.magic_point, status.max_magic_point), NULL);
dc.SelectObject(oldFont);
}
}
//
// 显示角色的状态
//
void CBattleAction::ChangePlayerStatus(CCharacter *ch)
{
for (int i=0; i<MAX_CHARACTER; i++) {
if (StatusCharacter[i] == ch) {
SetPlayerStatus(i);
RedrawSprite(StatusSprite + i);
}
}
}
//
// 显示突现式状态说明
//
void CBattleAction::ChangeStatus(CPoint point)
{
if (MapRect.PtInRect(point) && map_data[point.y][point.x].type & (PLAYER | ENEMY)) {
if (StatusChar != (CCharacter *)map_data[point.y][point.x].sprite) {
StatusChar = 0;
RedrawSprite(&PopupSprite); // 删除之前的显示
StatusChar = (CCharacter *)map_data[point.y][point.x].sprite;
CStatus &status = StatusChar->status;
// 组合状态显示的零件
PopupImage.Copy(&PopupImageBase); // 复制原始图像
PopupImage.DrawText(hFont, 1, 1, status.name, RGB(0, 0, 0));
PopupImage.DrawText(hFont, 0, 0, status.name);
int hp_len = status.hit_point * 76 / status.max_hit_point;
int mp_len = status.magic_point * 76 / status.max_magic_point;
PopupImage.Copy(&PopupParts, CRect(21, 17, 21 + hp_len, 20), CPoint(0, 20));
PopupImage.Copy(&PopupParts, CRect(21, 32, 21 + mp_len, 35), CPoint(0, 23));
char hp_str[4], mp_str[4], mhp_str[4], mmp_str[4];
sprintf(hp_str, "%03d", status.hit_point);
sprintf(mp_str, "%03d", status.magic_point);
sprintf(mhp_str, "%03d", status.max_hit_point);
sprintf(mmp_str, "%03d", status.max_magic_point);
for (int i=0; i<3; i++) {
PopupImage.Copy(&PopupParts, CRect(42 + i * 8, 21, 50 + i * 8, 31), CPoint((hp_str[i] - '0') * 8, 0));
PopupImage.Copy(&PopupParts, CRect(74 + i * 8, 21, 82 + i * 8, 31), CPoint((mhp_str[i] - '0') * 8, 0));
PopupImage.Copy(&PopupParts, CRect(42 + i * 8, 36, 50 + i * 8, 46), CPoint((mp_str[i] - '0') * 8, 10));
PopupImage.Copy(&PopupParts, CRect(74 + i * 8, 36, 82 + i * 8, 46), CPoint((mmp_str[i] - '0') * 8, 10));
}
point = IndexToPoint(point);
point.x += (MAPGRID_WIDTH - PopupImage.Width()) / 2;
point.y -= 64;
// 若不在范围内,则放在窗口内
if (point.x < 0) {
point.x = 0;
}
else if (point.x >= WindowWidth - PopupImage.Width()) {
point.x = WindowWidth - PopupImage.Width();
}
if (point.y < 0) {
point.y = 0;
}
PopupSprite.SetDrawPos(point);
RedrawSprite(&PopupSprite); // 显示
}
}
else if (StatusChar != 0) { // 有显示状态,但不在人物上
StatusChar = 0;
RedrawSprite(&PopupSprite); // 删除之前的显示
}
}
//
// 移动地图光标
//
void CBattleAction::SetCursor(CPoint point)
{
if (CursorPos != point) { // 若地图位置有更改
ClearCursor(); // 则删除目前显示的光标
CursorPos = point; // 重新设定新的位置
DrawCursor(); // 显示新的光标
ChangeStatus(point); // 变更角色的状态
}
}
//
// 删除地图光标
//
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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -