瓦片地图编辑器——实现卡马克卷轴的编辑,键盘控制游戏移动和鼠标点击游戏编辑通过同一个视口实现。

 

左边是游戏地图编辑区,右边是地图缓冲区,解决了地图缓冲区拖动bug,成功使得缓冲区可以更新。

AWSD进行移动

鼠标左右键分别是绘制/拖动

按F1健导出为mapv3.txt

F2清空数组

打印的是游戏数组

easyx开发devcpp 5.11 easyx20220922版本

#include <graphics.h>
#include <stdio.h>
#define ROW 150						// 游戏地图行 
#define COLUMN 150					// 游戏地图列 
//#define ROW 20						// 游戏地图行
//#define COLUMN 20					// 游戏地图列
#define PIXNUM 30						// 一个瓦片边长为 30 像素 
#define SHOWSIZE 10						// 一个视口边长为 5 个瓦片 
#define BUFFERSIZE 3					// 地图缓冲区边长 3 个视口 
#define SHOWSPEED 4						// 游戏地图背景移动速度 
#define SHOWX 300						// 游戏显示区域 
#define SHOWY 300
typedef struct area {int lx;								// 左上角坐标int ly;int rx;								// 右上角坐标int ry;int high;							// 高度int wide;
} area;typedef struct checkBackgroundBuffer {	// 用于记录缓冲条件的临界数据int xmin;int ymin;int xmax;int ymax;int adjust;
} bklimit;typedef struct background {				// 游戏地图背景area gamepos;						// 采样区相对于缓冲区的坐标area deskpos;						// 改 bug 整理得到一个新结构体,把窗口坐标封装了int nowpointx;						// 在整个地图数组映射形成的地图上的坐标int nowpointy;IMAGE *gamebk;
} bk;typedef struct backgroundBuffer {							// 游戏背景缓冲区area meshpos;int meshrow;int meshcolumn;bklimit bufferlimit;IMAGE *mapmesh;											// 缓冲区,长宽各为 3*size*a 个像素
} bkbuffer;
int map[ROW][COLUMN]= {0};
//int map[ROW][COLUMN]= {
//	{0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,1,0,0, 0,0,2,0,2, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,0,0,2, 0,0,0,2,0, 0,0,0,0,0},
//	{0,0,0,0,1, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0},
//
//	{0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,1,0,0, 0,0,2,0,2, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,0,0,2, 0,0,0,2,0, 0,0,0,0,0},
//	{0,0,0,0,1, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0},
//
//	{0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,1,0,0, 0,0,2,0,2, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,0,0,2, 0,0,0,2,0, 0,0,0,0,0},
//	{0,0,0,0,1, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0},
//
//	{0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,1,0,0,0, 0,0,0,0,0, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,1,0,0, 0,0,2,0,2, 0,0,0,0,0},
//	{0,0,0,0,0, 0,0,0,0,2, 0,0,0,2,0, 0,0,0,0,0},
//	{0,0,0,0,1, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0},
//};int pixnum=PIXNUM;											// 瓦片的大小正方形像素瓦片的边长
int showsize=SHOWSIZE;
int buffersize = BUFFERSIZE;
bk bkgd;													// background
bkbuffer bkgdbu;											// backgroundbuffer
IMAGE b(3*showsize*pixnum,3*showsize*pixnum);				// mapmesh 缓冲区
IMAGE a(showsize*pixnum,showsize*pixnum);					// 采样区,采样的到的图片就是屏幕上的游戏
// 清除地图
void clearmap();
// 保存编辑完的地图
void savemap();
//读取txt字符表格作为背景数组
void loadmap();
//检测背景是否需要更新
bool buchange() {bool changeflag=0;while(bkgd.gamepos.lx>bkgdbu.bufferlimit.xmax) {		// if else if变 while 解决鼠标拖动,导致的多次平移问题bkgd.gamepos.lx-=bkgdbu.bufferlimit.adjust;bkgdbu.meshpos.lx+=showsize;changeflag=1;printf("死循环\n");}while(bkgd.gamepos.lx<bkgdbu.bufferlimit.xmin) {bkgd.gamepos.lx+=bkgdbu.bufferlimit.adjust;bkgdbu.meshpos.lx-=showsize;changeflag=1;}while(bkgd.gamepos.ly>bkgdbu.bufferlimit.ymax) {bkgd.gamepos.ly-=bkgdbu.bufferlimit.adjust;bkgdbu.meshpos.ly+=showsize;changeflag=1;}while(bkgd.gamepos.ly<bkgdbu.bufferlimit.ymin) {bkgd.gamepos.ly+=bkgdbu.bufferlimit.adjust;bkgdbu.meshpos.ly-=showsize;changeflag=1;}return changeflag;
}
//刷新背景缓冲区
void freshbuffer() {SetWorkingImage(bkgdbu.mapmesh);							// 选择缓冲区为更新对象for(int i=0; i<bkgdbu.meshrow; i++) {for(int j=0; j<bkgdbu.meshcolumn; j++) {switch (map[i+bkgdbu.meshpos.ly][j+bkgdbu.meshpos.lx]) {	// 解决x坐标与数组的对应关系 第二个方括号【】是列数,是横坐标x,控制第几列case 0:setfillcolor(BLACK);						// 二维数组瓦片是 0,则选择黑色瓦片break;case 1:setfillcolor(WHITE);						// 二维数组瓦片是 1,则选择白色瓦片break;case 2:setfillcolor(GREEN);						// 二维数组瓦片是 2,则选择绿色瓦片break;case 3:setfillcolor(BLUE);							// 二维数组瓦片是 3,则选择蓝色瓦片break;}fillrectangle(j*pixnum,i*pixnum,(j+1)*pixnum,(i+1)*pixnum);						// 贴图瓦片}}SetWorkingImage();
}//刷新屏幕
void show() {SetWorkingImage(bkgdbu.mapmesh);														// 从缓冲区采样getimage(bkgd.gamebk,bkgd.gamepos.lx,bkgd.gamepos.ly,showsize*pixnum,showsize*pixnum);SetWorkingImage();putimage(bkgd.deskpos.lx,bkgd.deskpos.ly,bkgd.gamebk);									// 打印采样区,理解连续更新putimage(700,pixnum,bkgdbu.mapmesh);if(bkgd.gamebk==NULL) {printf("图片是空的\n");}if(bkgdbu.mapmesh==NULL) {printf("图片是空的\n");}
}//检测鼠标是否在某一区域
bool checkarea(ExMessage m,area deskpos) {if(m.x>deskpos.lx&&m.y>deskpos.ly&&m.x<deskpos.rx&&m.y<deskpos.ry) {return true;} else {return false;}
}//修改背景数组
void draw(ExMessage msg) {int mapx=0;																// 在采样区的坐标int mapy=0;int mapi=0;																// 当前所在的背景数组瓦片坐标int mapj=0;int allmapi;															// 对应整个数组的坐标int allmapj;static int oldmapi=0;													// 上一次绘制的背景数组坐标瓦片坐标static int oldmapj=0;static int drawflag=0;if(drawflag==1&&checkarea(msg,bkgd.deskpos)) {mapx=msg.x-bkgd.deskpos.lx;											// 相对于游戏窗口左上角的坐标距离mapy=msg.y-bkgd.deskpos.ly;mapi=(mapy+bkgd.gamepos.ly)/pixnum;									// 整除瓦片边长,算出来是在缓冲区的哪个瓦片mapj=(mapx+bkgd.gamepos.lx)/pixnum;allmapi=mapi+bkgdbu.meshpos.ly;										// 计算在相对于整个地图数组左上角 (0,0) 的瓦片位置allmapj=mapj+bkgdbu.meshpos.lx;if(oldmapi!=allmapi||oldmapj!=allmapj) {							// 如果不相同,才进行绘制, 节约运算oldmapi=allmapi;oldmapj=allmapj;map[allmapi][allmapj]=2;										// 缓冲区的那个瓦片坐标实际上是原来完整地图的那个瓦片坐标。printf("游戏采样区网格坐标 x = %d,  y = %d\n",mapj,mapi);freshbuffer();}}if(msg.message ==WM_LBUTTONDOWN&&checkarea(msg,bkgd.deskpos)) {mapx=msg.x-bkgd.deskpos.lx;											// 相对于游戏窗口左上角的坐标距离mapy=msg.y-bkgd.deskpos.ly;mapi=(mapy+bkgd.gamepos.ly)/pixnum;									// 整除瓦片边长,算出来是在缓冲区的哪个瓦片mapj=(mapx+bkgd.gamepos.lx)/pixnum;allmapi=mapi+bkgdbu.meshpos.ly;										// 计算在相对于整个地图左上角 (0,0) 的数组瓦片位置allmapj=mapj+bkgdbu.meshpos.lx;oldmapi=allmapi;oldmapj=allmapj;map[allmapi][allmapj]=2;printf("游戏采样区网格坐标 x = %d,  y = %d\n",mapj,mapi);printf("游戏采样区像素坐标 x = %d,  y = %d\n",bkgd.gamepos.lx,bkgd.gamepos.ly);printf("游戏缓冲区网格坐标 x = %d,  y = %d\n",bkgdbu.meshpos.lx,bkgdbu.meshpos.ly);freshbuffer();drawflag=1;} else if(msg.message==WM_LBUTTONUP) {drawflag=0;}
}
// 右键拖动游戏地图——用坐标变换是无解的,因为鼠标位移detalx detaly的范围持续更新给了数据,
void draft(ExMessage msg) {static int flag=0;static int oldmx=0;														// 鼠标右键时的鼠标像素坐标static int oldmy=0;static int gamex=bkgd.nowpointx;										// 旧的采样区位置,加上鼠标拖动的位移就是新的采样区位置static int gamey=bkgd.nowpointy;SetWorkingImage();if(msg.message == WM_RBUTTONDOWN&&checkarea(msg,bkgd.deskpos)) {flag=1;																// 长按flagoldmx=msg.x;														// 记录拖动的起点oldmy=msg.y;gamex=bkgd.nowpointx;												// 只能使用绝对坐标,相对坐标 bkgd.gamepos.lx 坐标范围是 0-2*showsize*pixnum ,但是相对坐标可以通过记录改写,但是不如绝对坐标直观好写gamey=bkgd.nowpointy;printf("msg.x = %d,msg.y = %d\n",msg.x,msg.y);} else if(flag==1) {bkgd.nowpointx =gamex- (msg.x-oldmx);								// 图片移动的距离等于鼠标移动的距离bkgd.nowpointy =gamey- (msg.y-oldmy);								// 移动方向和鼠标移动方向相反bkgd.gamepos.lx=bkgd.nowpointx-bkgdbu.meshpos.lx*pixnum;			// 绝对坐标和相对坐标的变换,游戏采样区的像素坐标和网格坐标在buchange() 函数里重新分配,保证游戏采样区的像素坐标范围在 0-2*showsize*pixnum 里bkgd.gamepos.ly=bkgd.nowpointy-bkgdbu.meshpos.ly*pixnum;			// nowpointx y 像素坐标改变,然后再修改网格坐标,网格坐标修改完,再到buchange()里增加修改绝对像素坐标
//		printf("msg.x = %d,msg.y = %d\n",msg.x,msg.y);}if(msg.message == WM_RBUTTONUP) {flag=0;}
}//按键移动
void move(ExMessage msg) {static int flag_a=0;static int flag_d=0;static int flag_w=0;static int flag_s=0;static int movespeed=SHOWSPEED;					// 移动速度if(msg.message==WM_KEYDOWN) {		// 开始游戏某个方向移动switch(msg.vkcode) {case 0x41:					// Aflag_a=movespeed;break;case 0x44:					// Dflag_d=movespeed;break;case 0x57:					// Wflag_w=movespeed;break;case 0x53:					// Sflag_s=movespeed;break;}} else if(msg.message==WM_KEYUP) {	// 取消某一方向的持续移动switch(msg.vkcode) {case 0x41:					// Aflag_a=0;break;case 0x44:					// Dflag_d=0;break;case 0x57:					// Wflag_w=0;break;case 0x53:					// Sflag_s=0;break;}}
//	if(>&&<){
//		+=flah_a;
//	}else{
//		+=flag_a;
//	}bkgd.gamepos.lx-=flag_a;			// 左移采样区bkgd.gamepos.lx+=flag_d;			// 右移采样区bkgd.gamepos.ly-=flag_w;			// 上移采样区bkgd.gamepos.ly+=flag_s;			// 下移采样区
}//初始化地图缓冲区
void initbkbuffer() {bkgdbu.mapmesh = &b;													// 挂载地图缓冲区bkgdbu.meshpos.lx=0;bkgdbu.meshpos.ly=0;bkgdbu.meshrow=BUFFERSIZE*showsize;bkgdbu.meshcolumn=BUFFERSIZE*showsize;bkgdbu.bufferlimit.adjust=showsize*pixnum;								// 缓冲区需要更新的临界条件bkgdbu.bufferlimit.xmax=2*showsize*pixnum;								// 超过九宫格就立即更新,采样区默认在九宫格的中心bkgdbu.bufferlimit.xmin=0;bkgdbu.bufferlimit.ymax=2*showsize*pixnum;bkgdbu.bufferlimit.xmin=0;freshbuffer();SetWorkingImage();
//	putimage(700,pixnum,bkgdbu.mapmesh);									// 缓冲区可视化
}
//初始化地图采样区
void initbk() {bkgd.gamebk = &a;														// 如果是在这里声明临时变量 a ,函数执行完毕之后,程序就会销毁变量bkgd.gamepos.lx=showsize*pixnum;										// 采样区默认位置bkgd.gamepos.ly=showsize*pixnum;bkgd.nowpointx=bkgd.gamepos.lx;											// 绝对位置,用于解决gamepos 范围在 0~2*showsize*pixnum 导致的笔刷绘制失败bugbkgd.nowpointy=bkgd.gamepos.ly;											// 打表检测,读表时发现的绘制位置始终在一个区域内,才发现的这个bugbkgd.deskpos.lx=SHOWX;													// 采样之后的粘贴位置bkgd.deskpos.ly=SHOWY;bkgd.deskpos.rx=bkgd.deskpos.lx+showsize*pixnum;						// 粘贴区域的大小,用于检测鼠标指针是否在该区域内绘制bkgd.deskpos.ry=bkgd.deskpos.ly+showsize*pixnum;SetWorkingImage(bkgdbu.mapmesh);getimage(bkgd.gamebk,bkgd.gamepos.lx,bkgd.gamepos.ly,showsize*pixnum,showsize*pixnum);					// 加载屏幕地图,开始采样SetWorkingImage();putimage(bkgd.deskpos.lx,bkgd.deskpos.ly,bkgd.gamebk);					// 粘贴采样结果
}int main() {initgraph(1800,800,1);setbkcolor(GREEN);cleardevice();loadmap();																// 加载地图clearmap();initbkbuffer();initbk();ExMessage msg;while(1) {peekmessage(&msg,EX_KEY|EX_MOUSE,true);move(msg);															// 键盘awsd检查draft(msg);															// 鼠标右键拖动检查draw(msg);															// 鼠标左键绘制if(buchange()) {freshbuffer();													// 刷新九宫格缓冲区printf("九宫格已刷新\n");}if(msg.message==WM_KEYDOWN) {if(msg.vkcode==VK_F1) {savemap();} else if(msg.vkcode== VK_F2) {clearmap();}}show();																// 打印缓冲区,打印新的采样结果,更新游戏背景, 结算完毕统一显示Sleep(2);}return 0;
}
//清楚地图 
void clearmap() {for(int i=0; i<ROW; i++) {for(int j=0; j<COLUMN; j++) {if(i==0||j==0) {map[i][j]=1;} else {map[i][j]=0;}}}printf("freash gammap\n");
}
// 保存地图
void savemap() {FILE* fp;fp=fopen("mapv3.txt","w");for(int i=0; i<ROW; i++) {for(int j=0; j<COLUMN; j++) {fprintf(fp," %d",map[i][j]);}fprintf(fp,"\n");}fclose(fp);printf("save gammap\n");for(int i=0; i<ROW; i++) {for(int j=0; j<COLUMN; j++) {printf(" %d",map[i][j]);}}printf("map 显示已完成\n");
}//加载地图
void loadmap() {FILE* fp;fp=fopen("mapv2.txt","r");for(int i=0; i<ROW; i++) {for(int j=0; j<COLUMN; j++) {fscanf(fp," %d",&map[i][j]);}fscanf(fp,"\n");}fclose(fp);printf("gammap\n");for(int i=0; i<ROW; i++) {for(int j=0; j<COLUMN; j++) {printf(" %d",map[i][j]);}printf("\n");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/427739.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【日志框架】

日志打印 建议用{}占位而不是字符串拼接打日志前先判断日志级别是否可用&#xff1a; 先根据等级过滤规则再决定写不写&#xff1b;先往一个管道写了内容&#xff0c;但再经等级过滤丢弃&#xff0c;徒增开销。 日志框架 Slf4J Slf4J 不是底层日志框架&#xff0c;只是门面…

搭建《幻兽帕鲁》服务器需要怎样配置的云服务器?

随着《幻兽帕鲁》这款游戏的日益流行&#xff0c;越来越多的玩家希望能够在自己的服务器上体验这款游戏。然而&#xff0c;搭建一个稳定、高效的游戏服务器需要仔细的规划和配置。本文将分享搭建《幻兽帕鲁》服务器所需的配置及搭建步骤&#xff0c;助力大家获得更加畅快的游戏…

深入理解MySQL InnoDB线程模型

当我们谈论数据库性能时&#xff0c;存储引擎的线程模型是一个不可忽视的方面。MySQL的InnoDB存储引擎&#xff0c;作为目前最受欢迎的存储引擎之一&#xff0c;其线程模型的设计对于实现高并发、高性能的数据操作至关重要。在本文中&#xff0c;我们将深入探讨MySQL InnoDB线程…

CPMS靶场练习

关键&#xff1a;找到文件上传点&#xff0c;分析对方验证的手段 首先查看前端发现没有任何上传的位置&#xff0c;找到网站的后台&#xff0c;通过弱口令admin 123456可以进入 通过查看网站内容发现只有文章列表可以进行文件上传&#xff1b;有两个图片上传点 图片验证很严格…

Dubbo 3.x源码(16)—Dubbo服务发布导出源码(5)

基于Dubbo 3.1&#xff0c;详细介绍了Dubbo服务的发布与引用的源码。 此前我们学习了Dubbo 3.x源码(15)—Dubbo服务发布导出源码(4)&#xff0c;也就是Dubbo远程服务导出export方法的上半部分&#xff0c;也就是doLocalExport源码&#xff0c;将会得到一个Exporter。 现在我们…

C#使用IsLeapYear方法判断指定年份是否为闰年

目录 一、判断指定年是否为闰年的2个方法 1.使用IsLeapYear方法判断指定年份是否为闰年 2.使用自定义的算法计算指定年份是否为闰年 二、示例 1.方法1的实例 2.方法2的实例 一、判断指定年是否为闰年的2个方法 1.使用IsLeapYear方法判断指定年份是否为闰年 使用IsLeapY…

《Linux高性能服务器编程》笔记06

Linux高性能服务器编程 本文是读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 文章目录 Linux高性能服务器编程第13章 多进程编程13.1 fork 系统调用13…

Spring Boot 整合 Camunda 实现工作流

工作流是我们开发企业应用几乎必备的一项功能&#xff0c;工作流引擎发展至今已经有非常多的产品。最近正好在接触Camunda&#xff0c;所以来做个简单的入门整合介绍。如果您也刚好在调研或者刚开始计划接入&#xff0c;希望本文对您有所帮助。如果您是一名Java开发或Spring框架…

使用强化学习进行神经网络结构搜索的代码以及修改

目录 代码一&#xff08;Using TensorFlow&#xff09;&#xff1a; 代码二&#xff08;Using TensorFlow&#xff09;&#xff1a; 代码三&#xff08;Using PyTorch&#xff09;&#xff1a; 参考&#xff1a; 本人在网上找了三个相关的代码&#xff0c;但是都有问题&…

Web--HTML基础

文章目录 安装环境HTMLhtml框架html基础标签语义标签html特殊符号 安装环境 安装vscode后 安装插件 可以先不写后台直接将前度界面展示出来 自动补全tag&#xff0c;同时修改tag时自动改另一半 在设置里将保存自动格式化的选项勾上 创建一个index.htm文件&#xff0c;这个…

基于sentinel-2 遥感数据的水体提取(水体指数法)

本文框架设置如下&#xff1a; 简单介绍senintel-2数据&#xff1b;如何利用sentinel-2数据获取水体边界/范围 1 Sentinel-2数据介绍及下载方式 有Sentinel-2A/2B两颗卫星&#xff0c;其参数基本一致&#xff0c;因此两颗卫星的数据联合使用很方便。 分辨率有&#xff1a;1…

springboot114基于多维分类的知识管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的基于多维分类的知识管理系统 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章…