伴随角色的移动,地图自动扩大的实现
2023-2-24 ~ 2023-2-27
(1)
操作方法
方向键控制红点移动,移动过的地方成为地图,回车键退出。
简单说明
GetImageHDC 可以获取设备 HDC(Handle Device Context 设备上下文句柄),StretchBlt 可以把一个 HDC 的内容缩放后输出到另一个 HDC 上,GetImageBuffer 可以获取 IMAGE 类的缓冲区,操作这个缓冲区可以改变 IMAGE 也就是图像的内容。这三个函数十分简便地实现了地图缩放。
程序截图
代码实现
////////////////////////////////////////////
// 程序:伴随角色的移动,地图自动扩大的实现
// 作者:我想做三国志
// 编译环境:Visual Studio 2019,EasyX_20220901
// 编写日期:2023-2-25
#include <graphics.h>
const int WIDTH = 640; // 屏幕宽度
const int HEIGHT = 480; // 屏幕高度
const int UP = 0; // 上方向
const int DOWN = 2; // 下方向
const int LEFT = 1; // 左方向
const int RIGHT = 3; // 右方向
const int NONE = 4; // 空方向
const int COLNUM = 3; // 颜色数量
const int NODEWIDTH = 4; // 节点宽度
const int NODEHEIGHT = 4; // 节点高度
const int PATHWIDTH = 2; // 路径宽度
const int PATHLEN = 1; // 路径长度
COLORREF ColArr[COLNUM] = { BLACK, WHITE, RED }; // 颜色数组
// 画节点
void DrawNode(DWORD* buf, int LeftEst, int RightEst, int UpEst, int DownEst, int x, int y, char element)
{
setfillcolor(ColArr[element]);
solidrectangle(x * (NODEWIDTH + PATHLEN), y * (NODEHEIGHT + PATHLEN), x * (NODEWIDTH + PATHLEN) + NODEWIDTH - 1, y * (NODEHEIGHT + PATHLEN) + NODEHEIGHT - 1);
if (element == COLNUM + 1)
{
int radius = min(NODEHEIGHT, NODEWIDTH) / 2;
setfillcolor(RED);
solidcircle(x * (NODEWIDTH + PATHLEN) + radius, y * (NODEHEIGHT + PATHLEN) + radius, radius);
}
}
// 画路径
void DrawPath(DWORD* buf, int LeftEst, int RightEst, int UpEst, int DownEst, int x, int y, char Dir)
{
int beginPX = x * (PATHLEN + NODEWIDTH), beginPY = y * (NODEHEIGHT + PATHLEN);
int height = PATHWIDTH, width = PATHWIDTH;
switch (Dir)
{
case UP: beginPX += (NODEWIDTH - PATHWIDTH) / 2; beginPY -= PATHLEN; height = PATHLEN; break;
case DOWN: beginPX += (NODEWIDTH - PATHWIDTH) / 2; beginPY += NODEHEIGHT; height = PATHLEN; break;
case LEFT: beginPY += (NODEHEIGHT - PATHWIDTH) / 2; beginPX -= PATHLEN; width = PATHLEN; break;
case RIGHT: beginPY += (NODEHEIGHT - PATHWIDTH) / 2; beginPX += NODEWIDTH; width = PATHLEN; break;
}
setfillcolor(WHITE);
solidrectangle(beginPX, beginPY, beginPX + width - 1, beginPY + height - 1);
}
// 画地图
void DrawMap(DWORD* buf, int LeftEst, int RightEst, int UpEst, int DownEst, char* AuxiliaryMap, char* PathHoriMap, char* PathVertMap)
{
// 画节点
for (int i = 0; i < DownEst - UpEst + 1; i++)
for (int j = 0; j < RightEst - LeftEst + 1; j++)
DrawNode(buf, LeftEst, RightEst, UpEst, DownEst, j, i, AuxiliaryMap[i * (RightEst - LeftEst + 1) + j]);
// 画横向道路
for (int i = 0; i < DownEst - UpEst + 1; i++)
for (int j = 0; j < RightEst - LeftEst; j++)
if (PathHoriMap[i * (RightEst - LeftEst) + j] == 1)
DrawPath(buf, LeftEst, RightEst, UpEst, DownEst, j, i, RIGHT);
// 画竖向道路
for (int i = 0; i < DownEst - UpEst; i++)
for (int j = 0; j < RightEst - LeftEst + 1; j++)
if (PathVertMap[i * (RightEst - LeftEst + 1) + j] == 1)
DrawPath(buf, LeftEst, RightEst, UpEst, DownEst, j, i, DOWN);
}
// 主函数
int main()
{
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
HDC mainDC = GetImageHDC(NULL); // 主窗口的 DC
SetStretchBltMode(mainDC, HALFTONE); // 设置拉伸贴图模式
int beginX = 0, beginY = 0;
int LeftEst = -3, RightEst = 3, UpEst = -3, DownEst = 3;
int showWidth = WIDTH - 50, showHeight = HEIGHT - 50;
char* AuxiliaryMap = new char[(RightEst - LeftEst + 1) * (DownEst - UpEst + 1)];
char* PathHoriMap = new char[(RightEst - LeftEst) * (DownEst - UpEst + 1)];
char* PathVertMap = new char[(DownEst - UpEst) * (RightEst - LeftEst + 1)];
memset(AuxiliaryMap, 0, sizeof(char) * (RightEst - LeftEst + 1) * (DownEst - UpEst + 1));
memset(PathHoriMap, 0, sizeof(char) * (RightEst - LeftEst) * (DownEst - UpEst + 1));
memset(PathVertMap, 0, sizeof(char) * (DownEst - UpEst) * (RightEst - LeftEst + 1));
AuxiliaryMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)] = COLNUM - 1;
// 建立 img 对象
IMAGE img((NODEWIDTH + PATHLEN) * (RightEst - LeftEst + 1) - PATHLEN, (NODEHEIGHT + PATHLEN) * (DownEst - UpEst + 1) - PATHLEN);
HDC imgDC = GetImageHDC(&img);
DWORD* pBuf = GetImageBuffer(&img);
memset(pBuf, 0, sizeof(DWORD) * img.getwidth() * img.getheight());
SetWorkingImage(&img);
DrawMap(pBuf, LeftEst, RightEst, UpEst, DownEst, AuxiliaryMap, PathHoriMap, PathVertMap);
// 贴图到主窗口
double times = min(showHeight / (double)img.getheight(), showWidth / (double)img.getwidth());
int BeginShowPX = (WIDTH - showWidth) / 2 + (showWidth - img.getwidth() * times) / 2;
int BeginShowPY = (HEIGHT - showHeight) / 2 + (showHeight - img.getheight() * times) / 2;
SetWorkingImage(NULL);
StretchBlt(mainDC, BeginShowPX, BeginShowPY, (int)(img.getwidth() * times + 0.5), (int)(img.getheight() * times + 0.5),
imgDC, 0, 0, img.getwidth(), img.getheight(), SRCCOPY);
FlushBatchDraw();
bool isExit = false;
ExMessage msg;
while (!isExit)
{
msg = getmessage(EX_KEY);
if (msg.message == WM_KEYDOWN)
{
int newX = beginX, newY = beginY;
char Dir = NONE;
switch (msg.vkcode)
{
case VK_UP: newY--; Dir = UP; break;
case VK_DOWN: newY++; Dir = DOWN; break;
case VK_LEFT: newX--; Dir = LEFT; break;
case VK_RIGHT: newX++; Dir = RIGHT; break;
case VK_RETURN: isExit = true; break;
}
if (isExit) break;
int oriX = abs(LeftEst), oriY = abs(UpEst), oriH = DownEst - UpEst + 1, oriW = RightEst - LeftEst + 1;
bool isRefresh = false;
if (newX < LeftEst)
{
LeftEst--;
isRefresh = true;
}
else if (newX > RightEst)
{
RightEst++;
isRefresh = true;
}
if (newY < UpEst)
{
UpEst--;
isRefresh = true;
}
else if (newY > DownEst)
{
DownEst++;
isRefresh = true;
}
SetWorkingImage(&img);
if (isRefresh)
{
char* tempAuxiliaryMap = new char[(RightEst - LeftEst + 1) * (DownEst - UpEst + 1)];
char* tempPathHoriMap = new char[(RightEst - LeftEst) * (DownEst - UpEst + 1)];
char* tempPathVertMap = new char[(DownEst - UpEst) * (RightEst - LeftEst + 1)];
memset(tempAuxiliaryMap, 0, sizeof(char) * ((RightEst - LeftEst + 1) * (DownEst - UpEst + 1)));
memset(tempPathHoriMap, 0, sizeof(char) * (RightEst - LeftEst) * (DownEst - UpEst + 1));
memset(tempPathVertMap, 0, sizeof(char) * (DownEst - UpEst) * (RightEst - LeftEst + 1));
int beginXX = abs(LeftEst) - oriX, beginYY = abs(UpEst) - oriY;
for (int i = 0; i < oriH; i++)
for (int j = 0; j < oriW; j++)
tempAuxiliaryMap[(beginYY + i) * (RightEst - LeftEst + 1) + beginXX + j] = AuxiliaryMap[i * oriW + j];
for (int i = 0; i < oriH; i++)
for (int j = 0; j < oriW - 1; j++)
tempPathHoriMap[(beginYY + i) * (RightEst - LeftEst) + beginXX + j] = PathHoriMap[i * (oriW - 1) + j];
for (int i = 0; i < oriH - 1; i++)
for (int j = 0; j < oriW; j++)
tempPathVertMap[(beginYY + i) * (RightEst - LeftEst + 1) + beginXX + j] = PathVertMap[i * oriW + j];
delete[] AuxiliaryMap;
delete[] PathHoriMap;
delete[] PathVertMap;
AuxiliaryMap = tempAuxiliaryMap;
PathHoriMap = tempPathHoriMap;
PathVertMap = tempPathVertMap;
img.Resize((NODEWIDTH + PATHLEN) * (RightEst - LeftEst + 1) - PATHLEN, (NODEHEIGHT + PATHLEN) * (DownEst - UpEst + 1) - PATHLEN);
imgDC = GetImageHDC(&img);
pBuf = GetImageBuffer(&img);
memset(pBuf, 0, sizeof(DWORD) * img.getwidth() * img.getheight());
DrawMap(pBuf, LeftEst, RightEst, UpEst, DownEst, AuxiliaryMap, PathHoriMap, PathVertMap);
times = min(showHeight / (double)img.getheight(), showWidth / (double)img.getwidth());
BeginShowPX = (WIDTH - showWidth) / 2 + (showWidth - img.getwidth() * times) / 2;
BeginShowPY = (HEIGHT - showHeight) / 2 + (showHeight - img.getheight() * times) / 2;
}
AuxiliaryMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)] = 1;
AuxiliaryMap[(newY + abs(UpEst)) * (RightEst - LeftEst + 1) + newX + abs(LeftEst)] = 2;
DrawNode(pBuf, LeftEst, RightEst, UpEst, DownEst, beginX + abs(LeftEst), beginY + abs(UpEst),
AuxiliaryMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)]);
DrawNode(pBuf, LeftEst, RightEst, UpEst, DownEst, newX + abs(LeftEst), newY + abs(UpEst),
AuxiliaryMap[(newY + abs(UpEst)) * (RightEst - LeftEst + 1) + newX + abs(LeftEst)]);
DrawPath(pBuf, LeftEst, RightEst, UpEst, DownEst, beginX + abs(LeftEst), beginY + abs(UpEst), Dir);
switch (Dir)
{
case UP: PathVertMap[(newY + abs(UpEst)) * (RightEst - LeftEst + 1) + newX + abs(LeftEst)] = 1; break;
case DOWN: PathVertMap[(beginY + abs(UpEst)) * (RightEst - LeftEst + 1) + beginX + abs(LeftEst)] = 1; break;
case LEFT: PathHoriMap[(newY + abs(UpEst)) * (RightEst - LeftEst) + newX + abs(LeftEst)] = 1; break;
case RIGHT: PathHoriMap[(beginY + abs(UpEst)) * (RightEst - LeftEst) + beginX + abs(LeftEst)] = 1; break;
}
beginX = newX;
beginY = newY;
}
SetWorkingImage(NULL);
cleardevice();
StretchBlt(mainDC, BeginShowPX, BeginShowPY, img.getwidth() * times, img.getheight() * times,
imgDC, 0, 0, img.getwidth(), img.getheight(), SRCCOPY);
FlushBatchDraw();
}
delete[] AuxiliaryMap;
delete[] PathHoriMap;
delete[] PathVertMap;
closegraph();
return 0;
}