瓦片地图编辑器推进日志#003笔刷选取与地图导出

发布时间:2024年01月16日

?2024年1月15日14:00:00——16:27:30实现笔刷读取,笔刷暂存区,笔刷与笔刷存储区初始化。

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <windows.h>
//#include "pentable.h"
typedef struct setmap
{
	int lx = 0;
	int ly = 0;																	// 游戏地图的左上角坐标
	int rx = 0;
	int ry = 0;																	// 优化计算,确定鼠标是否在网格里
	int row = 0;																// 游戏地图瓦片行个数
	int column = 0;																// 游戏地图瓦片列个数
	int tileSize = 0;															// 正方形瓦片的长宽像素
	int** map = NULL;															// 瓦片地图的二维数组数据,一个一维数组等同于一级指针,一个指针数组是二级指针。
	IMAGE have[10] = { 0 };														// 每个瓦片序号对应的图片
}set;
typedef struct tile
{
	int lx = 0;
	int ly = 0;
	int rx = 0;
	int ry = 0;
	int level=0;
	int tileSize = 0;
	int ismove = 0;
	int isoccupied = 0;
	IMAGE* penimage = NULL;														// 指针,初始化绘制贴图为空
}tile;
typedef struct tilegroup
{
	int lx;
	int ly;
	int rx;
	int ry;
	int row;																	// 行
	int column;																	// 列
	int tileSize;
	tile** pengroup;
}tilegroup;

set* initgamemap()
{
	int row=26, column=27;
	//scanf_s("%d %d", &row, &column);											// 游戏地图瓦片行列个数
	set* gamemap = (set*)malloc(sizeof(set));									// 指针,因为 set 结构体的 map 数组需要修改。学习阶段属性:这是开发着自然而然意识到的问题。
	if (gamemap == NULL)
	{
		printf("地图创建失败,可能是内存不足\n");
		exit(0);
	}
	gamemap->lx = 100;
	gamemap->ly = 100;
	gamemap->row = row;
	gamemap->column = column;
	gamemap->tileSize = 16;
	gamemap->rx = gamemap->lx + gamemap->column * gamemap->tileSize;			// 根据数据计算右下角边缘,右下角行坐标=左上角横坐标+列个数*瓦片像素
	gamemap->ry = gamemap->ly + gamemap->row * gamemap->tileSize;
	gamemap->map = new int* [row];												// 数组动态生成,先生成列,就是一共有多少行,二级指针赋值指针数组
	for (int i = 0; i < row; i++)
	{
		gamemap->map[i] = new int[column];										// 指针数组分别赋值一维数组,每个指针指向一个数组,一行有多少列。主要适配 save()函数部分的打印,一行一行打印
	}
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < column; j++)
		{
			gamemap->map[i][j] = 0;												// 默认0是无障碍
			printf("%d", gamemap->map[i][j]);
		}
		printf("\n");
	}
	initgraph(1280, 800, 1);
	setbkcolor(WHITE);
	cleardevice();
	setlinecolor(BLACK);
	rectangle(gamemap->lx, gamemap->ly, gamemap->rx, gamemap->ry);				// 绘制游戏地图边框
	return gamemap;
}


void draw(ExMessage msg, set* gamemap,tile* pen)
{
	static int isdraw = 0;
	static int oldtilex;
	static int oldtiley;
	if (msg.message == WM_LBUTTONDOWN && msg.x > gamemap->lx && msg.y > gamemap->ly && msg.x < gamemap->rx && msg.y < gamemap->ry)
	{
		int x = msg.x - gamemap->lx;											// 距离游戏地图左上角的行距离
		int y = msg.y - gamemap->ly;
		int tilex = x / gamemap->tileSize;										// 以距离游戏地图左上角的距离再除以瓦片长度,算出在第几个瓦片
		int tiley = y / gamemap->tileSize;
		if (oldtilex != tilex || oldtiley != tiley)								// 性能优化,如果是相同瓦片,就不绘制,这里也有比较是因为打表检测有第一次按下时会不断打印,
		{																		// 所以需要对第一下按住左键也优化
			oldtilex = tilex;													// 记录本次瓦片位置,为下次瓦片是否相同比较,来减少重复绘制
			oldtiley = tiley;
			gamemap->map[tiley][tilex] = pen->level;							// 用 pen 的层级记录修改的地方,而且tiley是确定第几行,tilex是确定第几列
			fillrectangle(gamemap->lx + tilex * gamemap->tileSize, gamemap->ly + tiley * gamemap->tileSize, gamemap->lx + (tilex + 1) * gamemap->tileSize, gamemap->ly + (tiley + 1) * gamemap->tileSize);
			printf("%d %d level = %d\n",tilex ,tiley,pen->level);
		}
		isdraw = 1;																// 实现鼠标长按效果,搭配后面的 if else
	}
	else if (isdraw == 1)
	{
		if (msg.message == WM_LBUTTONUP)
		{
			isdraw = 0;
		}
		else if (isdraw && msg.x > gamemap->lx && msg.y > gamemap->ly && msg.x < gamemap->rx && msg.y < gamemap->ry)
		{
			int x = msg.x - gamemap->lx;										// 距离游戏地图左上角的行距离
			int y = msg.y - gamemap->ly;
			int tilex = x / gamemap->tileSize;									// 以距离游戏地图左上角的距离再除以瓦片长度,算出在第几个瓦片
			int tiley = y / gamemap->tileSize;
			if (oldtilex != tilex || oldtiley != tiley)							// 性能优化,如果是相同瓦片,就不绘制
			{
				oldtilex = tilex;												// 记录本次瓦片位置,为下次瓦片是否相同比较,来减少重复绘制。
				oldtiley = tiley;
				gamemap->map[tiley][tilex] = 1;									// 暂时用1记录修改的地方,而且tiley是确定第几行,tilex是确定第几列
				fillrectangle(gamemap->lx + tilex * gamemap->tileSize, gamemap->ly + tiley * gamemap->tileSize, gamemap->lx + (tilex + 1) * gamemap->tileSize, gamemap->ly + (tiley + 1) * gamemap->tileSize);
				printf("%d %d level = %d\n", tilex, tiley, pen->level);
			}
		}
	}
}

void save(ExMessage msg, set* gamemap)
{
	if (msg.message == WM_KEYDOWN || msg.message == WM_KEYUP)
	{
		if (msg.vkcode == VK_F1)												// 因为peek读取一个按键信息,所以两个按键组合,需要暂存上一个,用来一个标志位,记录ctrl是否按下
		{
			printf("save\n");
			FILE* fp;
			fopen_s(&fp, "gamemap.txt", "w+");
			if (fp == NULL)
			{
				printf("文件创建失败,可能是内存不足\n");
				exit(0);
			}
			for (int i = 0; i < gamemap->row; i++)
			{
				for (int j = 0; j < gamemap->column; j++)
				{
					fprintf(fp, "%d", gamemap->map[i][j]);
				}
				fprintf(fp, "\n");
			}
			fclose(fp);
			printf("save success\n");
			wchar_t s[10];
			InputBox(s, 10, L"不过是提示一下,解决重复保存bug");
		}
	}
}

tilegroup* initpentable()
{
	int row=18;																	// 行个数
	int column=30;																// 列个数
	//scanf_s("%d %d", &row, &column);											// 笔刷瓦片存储区行列个数
	tilegroup* pentable = (tilegroup*)malloc(sizeof(tilegroup));
	if (pentable == NULL) {
		printf("分配笔刷失败,可能是内存不足\n");
		exit(0);
	}
	pentable->lx = 700;															// 初始化瓦片存储区的左上角位置
	pentable->ly = 100;
	pentable->row = row;
	pentable->column = column;
	pentable->tileSize = 16;
	pentable->rx = pentable->lx + pentable->column * pentable->tileSize;		// 根据数据计算右下角边缘,右下角横坐标=左上角横坐标+列个数*瓦片像素
	pentable->ry = pentable->ly + pentable->row * pentable->tileSize;			// 根据数据计算右下角边缘,右下角纵坐标=左上角纵坐标+行个数*瓦片像素
	pentable->pengroup = new tile * [row];										// 数组动态生成,先生成列,就是一共有多少行,二级指针赋值指针数组
	if (pentable->pengroup == NULL)
	{
		printf("笔刷分配失败\n");
		exit(0);
	}
	for (int i = 0; i < row; i++)
	{
		pentable->pengroup[i] = new tile[column];								// 指针数组分别赋值一维数组,每个指针指向一个数组,一行有多少列。主要适配 save()函数部分的打印,一行一行打印
	}
	for (int i = 0; i < row; i++)
	{
		int tiley = pentable->ly + i * pentable->tileSize;
		for (int j = 0; j < column; j++)
		{
			int tilex = pentable->lx + j * pentable->tileSize;
			pentable->pengroup[i][j].lx = tilex;
			pentable->pengroup[i][j].ly = tiley;
			pentable->pengroup[i][j].rx = tilex + pentable->tileSize;
			pentable->pengroup[i][j].ry = tiley + pentable->tileSize;
			pentable->pengroup[i][j].isoccupied = 0;
			pentable->pengroup[i][j].level = i/3;								// 每个层级有3行插槽暂存笔刷
			rectangle(tilex, tiley, tilex + pentable->tileSize, tiley + pentable->tileSize);
		}
		printf("\n");
	}
	setlinecolor(BLACK);
	rectangle(pentable->lx, pentable->ly, pentable->rx, pentable->ry);			// 绘制笔刷存储区的边框
	return pentable;
}
// 选取笔刷
void pickPen(ExMessage msg, tilegroup* have, tile* pen)
{
	if (msg.message == WM_LBUTTONDOWN && msg.x > have->lx && msg.y > have->ly && msg.x < have->rx && msg.y < have->ry)
	{
		for (int i = 0; i < have->row; i++)
		{
			for (int j = 0; j < have->column; j++)
			{
				if (msg.x > have->pengroup[i][j].lx && msg.y > have->pengroup[i][j].ly && msg.x < have->pengroup[i][j].rx && msg.y < have->pengroup[i][j].ry)
				{
					*pen = have->pengroup[i][j];
					printf("pick pen\n");
				}
			}
		}
	}
}

tile* initpen()
{
	tile* pen = (tile*)malloc(sizeof(tile));
	if (pen == NULL)
	{
		printf("分配笔刷失败,可能是内存不足\n");
		exit(0);
	}
	pen->ismove = 0;
	pen->lx = 0;
	pen->ly = 0;
	pen->rx = 0;
	pen->ry = 0;
	pen->tileSize = 0;
	pen->penimage = new IMAGE(100,100);
	return pen;
}
int main()
{
	set* gamemap = initgamemap();
	tilegroup* pentable = initpentable();
	tile* pen = initpen();
	ExMessage msg;
	while (true)
	{
		while (peekmessage(&msg, EX_KEY || EX_MOUSE, true))						// 用 peekmessage()是因为无论有没有消息,都会执行后面的句子,这样可以持续刷新界面。
		{
			draw(msg, gamemap,pen);
			save(msg, gamemap);
			pickPen(msg, pentable, pen);
		}
	}
	closegraph();
	return 0;
}

文章来源:https://blog.csdn.net/a1309602336/article/details/135633614
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。