到了最终成果阶段了,虽然中间有一些代码讲起来没有意思,纯靠debug,+1-1解决贴图网格不重合问题,这次是一个分支结束。
想着就是把瓦片贴进大地图里。
延续这几篇帖子,开发时间也从2023年的4月16到了6月2号,80小时基本砸进去才出靠谱效果。
45天平均每天两小时。
DevC++ easyx实现图片拖动,一种悬浮窗实现原理与完整代码-CSDN博客
DevC++ easyx实现悬浮窗放入网格,与在函数分离过程中遇到的BUG下理解 函数的作用时域 以及 初始化与复位的关系。-CSDN博客 DevC++ easyx实现地图拖动,超过屏幕大小的巨大地图的局部显示在屏幕的方法——用悬浮窗的原理来的实现一个视口-CSDN博客
这次迭代过程是,贴图放到视口上,然后视口直接再粘贴到大地图上,然后就导致绘图瓦片重叠,而且也没来及考虑复位问题,就立马意识到还没设置网格。这里走的是网格贴图路线。
然后网格检测贴图位置,属于哪个网格,鼠标松开就被嵌入到哪个网格上。
然后这里设置的是网格长宽80像素,就用了数据图像位置变换:x=x-x%80;这样保留能被80整除的部分,然后px=x/80,得到所属网格的序号,这样就存储了贴图。
至于边界,就是处理鼠标位移和大地图坐标变化的问题。视口和采样区域是1:1,或者说是视口复制粘贴到大地图上成为采样图片,所以视口上鼠标移动多少,就是采样图上移动多少,然后算出来鼠标位置和视口左上角的距离,在大地图里,可以拿采样图左上角的坐标再加上这个数据,就是鼠标实际在大地图里面的坐标。
不多说,上效果
先放一个局部代码,跑不起来,因为适配的代码太庞大,文章后面有两个版本-集成版和cpp .h组合版
extern IMAGE maptile;
void didshow(IMAGE *set,IMAGE maptile,ExMessage m,int show_x,int show_y,int nowlx,int nowly) {
static int flag=0;
static int oldx=-8,oldy=-8;
int putx,puty;
IMAGE olds(80,80);
if(m.message==WM_LBUTTONDOWN) {
SetWorkingImage(set);
putx=nowlx+m.x-show_x;
puty=nowly+m.y-show_y;
putx=putx-putx%80;
puty=puty-puty%80;
putimage(putx,puty,&maptile);
SetWorkingImage();
} else{
if(putx==oldx&&puty==oldy) {
} else {
if(m.message==WM_LBUTTONDOWN) {
}
printf("show %d %d\n",m.x,m.y);
SetWorkingImage(set);
putx=nowlx+m.x-show_x;
puty=nowly+m.y-show_y;
putx=putx-putx%80;
puty=puty-puty%80;
putimage(putx,puty,&maptile);
oldx=putx;
oldy=puty;
SetWorkingImage();
}
}
}
代码比较多,先放一个整合版,.h分类版本看下面其他代码
这里是整合版。
devc++里新建项目,选择Multimedia里的Easyx
然后复制粘贴跑就行。
按键操作说明:
“本程序采用外装easy x拓展库的DEVc++制作而成
是跳一跳游戏配套编辑器
性质与单通道技能不同,是起跳前动画
操作说明
左键长按在网格绘制
右键在网格设置锚点
拖动网格左上角图片到中间的绿色区域暂存
左键点击绿色区域,
在黄色区域的左上角就会出现相同形状,说明已选择
然后在黄色区域左键长按或者单击左键,实现贴图
黄色区域右键移动大地图
按F1 清屏
按F2 导出为 png格式图片,自动命名为“gamemap”
gamemap0,gamemap1,gamemap2....gamemap9为游戏可以读取的有效文件,分别对应关卡1,2,3,4....9
粘贴到游戏目录实现自定义背景”
这是整合版,新建项目,复制粘贴就能跑
#include<stdio.h>
#include<graphics.h>
//INputboX
#include<windows.h>
//Sleep(2000);
//在中断休止
#include <conio.h>
// kbhit(void);检测按键,无也继续下去
#include<string.h>
//保存导入输入
//#include"oripic.h"
//#include"show.h"
//#include"draw.h"
//#include"flowsave.h"
//#include"movecheck.h"
//#include"buttoncheck.h"
//#include"keycheck.h"
int w=3600;
int h=800;
int w2=3,h2=7;
int x2=650,y2=100;
int showx3=101,showy3=100;
extern int w,h;
IMAGE set(w,h);
struct pixlocal {
short x;
short y;
};
struct skline {
int lenth=0;
int setx,sety;
struct pixlocal a[10000];
} nf,ndnf;
struct drawdesksize {
int x;
int y;
int a;
int h;
int sizetile=8;
int smx;
int smy;
} ddm;
IMAGE maptile(ddm.a/ddm.sizetile,ddm.h/ddm.sizetile);
struct pircle {
IMAGE img2;
IMAGE img3;
int orilx,orily;
int nowlx,nowly;
int a,h;
// 原有图片的左上角坐标
int m1x=0,m1y=0;
int putflag=0;
int drawflag=0;
struct skline b;
} save;
struct picsave {
int lx;
int ly;
int wide;
int h;
int useflag;
struct skline b;
} a[28];
void oripicdesk(int a,int h) {
initgraph(a,h,EX_SHOWCONSOLE);
setbkcolor(WHITE);
cleardevice();
// 创制绘图界面,背景色设置,以背景色填充。
setlinecolor(BLACK);
setlinestyle(PS_SOLID,1);
// 不含实线,矩形的面积为8*8;含实线,9*9.
rectangle(0,0,a-2,h-1);
//确定工作界面范围
setfillcolor(WHITE);
}
void oridrawdesksize(struct drawdesksize* ddm,int x,int y) {
ddm->x=x;
ddm->y=y;
ddm->a=640;
ddm->h=640;
ddm->sizetile=8;
ddm->smx=ddm->x-ddm->a/ddm->sizetile;
ddm->smy=ddm->y-ddm->h/ddm->sizetile;
}
void drawdesk(struct drawdesksize ddm) {
int i,j;
int square=ddm.sizetile;
for(i=ddm.x; i<=ddm.x+ddm.a-square; i+=square) {
for(j=ddm.y; j<ddm.y+ddm.h; j+=square) {
fillrectangle(i,j,i+square,j+square);
}
}
rectangle(ddm.smx-1,ddm.smy-1,ddm.x,ddm.y);
}
void oripircle(struct pircle *save,struct drawdesksize *ddm) {
save->orilx=ddm->smx,save->orily=ddm->smy;
save->nowlx=ddm->smx,save->nowly=ddm->smy;
save->a=ddm->a/ddm->sizetile;
save->h=ddm->h/ddm->sizetile;
// 原有图片的左上角坐标
save->m1x=0,save->m1y=0;
save->putflag=0;
save->drawflag=0;
}
void oriset(IMAGE *set,struct drawdesksize ddm,int w,int h) {
SetWorkingImage(set);
setbkcolor(YELLOW);
cleardevice();
setlinecolor(BLACK);
for(int i=0; i<h; i+=ddm.a/ddm.sizetile) {
for(int j=0; j<w; j+=ddm.h/ddm.sizetile)
rectangle(j+1,i+1,j+ddm.a/ddm.sizetile,i+ddm.h/ddm.sizetile);
}
line(0, 0, 800, 1400);
SetWorkingImage();
}
extern struct skline nf,ndnf;
extern IMAGE maptile;
void didshow(IMAGE *set,IMAGE maptile,ExMessage m,int show_x,int show_y,int nowlx,int nowly) {
static int flag=0;
static int oldx=-8,oldy=-8;
int putx,puty;
IMAGE olds(80,80);
if(m.message==WM_LBUTTONDOWN) {
SetWorkingImage(set);
putx=nowlx+m.x-show_x;
puty=nowly+m.y-show_y;
putx=putx-putx%80;
puty=puty-puty%80;
putimage(putx,puty,&maptile);
SetWorkingImage();
} else{
if(putx==oldx&&puty==oldy) {
} else {
if(m.message==WM_LBUTTONDOWN) {
}
printf("show %d %d\n",m.x,m.y);
SetWorkingImage(set);
putx=nowlx+m.x-show_x;
puty=nowly+m.y-show_y;
putx=putx-putx%80;
puty=puty-puty%80;
putimage(putx,puty,&maptile);
oldx=putx;
oldy=puty;
SetWorkingImage();
}
}
}
void show(IMAGE *set,ExMessage m,int show_x,int show_y,int show_wideth,int show_height) {
// 视口的图片大小,视口的大小,在窗口的坐标,视口的大小
static int nowlx,nowly,pic_wide,pic_heigh;
static int m1x,m1y;
static int drawflag,putflag,attachflag;
static IMAGE olds(show_wideth,show_height);
static IMAGE news(show_wideth,show_height);
static int m2x,m2y;
// 加速移动设置,自动移动设置。
static int flag=1;
if(flag==1) {
pic_wide=show_wideth;
pic_heigh=show_height;
m1x=0;
m1y=0;
m2x=0;
m2y=0;
drawflag=0;
putflag=0;
attachflag=0;
flag=0;
setlinecolor(BLACK);
rectangle(show_x,show_y,show_x+show_wideth,show_y+show_height);
BeginBatchDraw();
SetWorkingImage(set);
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
SetWorkingImage();
putimage(show_x,show_y,&olds);
EndBatchDraw();
} else {
if(m.message==WM_LBUTTONDOWN) {
if(m.ctrl&&m.x>show_x&&m.x<show_x+show_wideth&&m.y>show_y&&m.y<show_y+show_height) {
putflag=true;
// 启动批复制粘贴
// printf("%d\n",door.putflag);
SetWorkingImage(set);
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
// 获取视口里的图片
//
m1x=m.x;
m1y=m.y;
m2x=m.x;
m2y=m.y;
// printf("%d %d\n",m1x,m1y);
SetWorkingImage();
} else if (m.x>show_x&&m.x<show_x+show_wideth&&m.y>show_y&&m.y<show_y+show_height) {
// printf("333333\n");
didshow(set,maptile,m,show_x,show_y,nowlx,nowly);
attachflag=true;
}
} else if(attachflag==true&&m.x>show_x&&m.x<show_x+show_wideth&&m.y>show_y&&m.y<show_y+show_height) {
didshow(set,maptile,m,show_x,show_y,nowlx,nowly);
if(m.message==WM_LBUTTONUP) {
attachflag=false;
}
SetWorkingImage(set);
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
SetWorkingImage();
putimage(show_x,show_y,&olds);
} else if(putflag==true) {
BeginBatchDraw();
SetWorkingImage();
SetWorkingImage(set);
nowlx=nowlx-5*(m.x-m1x);
nowly=nowly-5*(m.y-m1y);
// 进行了位移放大。
// 位移同鼠标位移方向相反,大小相同
m1x=m.x;
m1y=m.y;
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
// 获取新地方的底图,为了下次重现,不干扰下次获取临近底图。
// putimage(save->nowlx,save->nowly,&save->img2);
SetWorkingImage();
putimage(show_x,show_y,&olds);
// putimage(500,500,&save->img3);
EndBatchDraw();
// 一次绘图出来,没有屏闪了
if(m.message==WM_LBUTTONUP||m.ctrl==0) {
putflag=0;
}
}
}
}
extern IMAGE maptile;
//用于设置绘图画布大小
//用于记录轨迹
void remem(struct ExMessage m,int *lenth,struct drawdesksize ddm) {
int i=*lenth;
static int oldx=-ddm.sizetile,
oldy=-ddm.sizetile,
a=ddm.sizetile,
h=ddm.sizetile;
if(m.x>oldx&&m.x<oldx+a&&m.y>oldy&&m.y<oldy+h) {
//节约运算,只在绘制时进行坐标变换
} else {
int px=0,py=0,qx=0,qy=0;
int mapqx=0,mapqy=0;
//修正可涂色范围,防止溢出。y<不可等于640+100,x等于640+600-1是边界小方块的最右侧像素
px=m.x-ddm.x;
py=m.y-ddm.y;
//修正600的偏移,601=600+1;0==1%8 ,600=600+(601-600)%8
qx=px-px%a;
qy=py-py%h;
mapqx=qx/a;
mapqy=qy/h;
px=ddm.x+qx;
py=ddm.y+qy;
setfillcolor(BLACK);
fillrectangle(px,py,px+ddm.sizetile,py+ddm.sizetile) ;
nf.a[i].x = mapqx;
nf.a[i].y = mapqy;
i++;
*lenth=i;
nf.lenth=*lenth;
printf("%d %d %d\n",i-1,nf.a[i-1].x,nf.a[i-1].y);
putpixel(ddm.smx+nf.a[i-1].x,ddm.smy+nf.a[i-1].y,BLACK);
oldx=px;
oldy=py;
}
}
void draw(ExMessage m,int *lenth) {
// 绘制的函数
static int flag=0;
if(m.message==WM_LBUTTONDOWN) {
remem(m,lenth,ddm);
// printf("222\n");
flag=1;
} else if(flag==1) {
remem(m,lenth,ddm);
if(m.message==WM_LBUTTONUP) {
flag=0;
}
}
}
void drawmousecheck(ExMessage m,int *lenth,struct drawdesksize * ddm) {
if(m.x>ddm->x&&m.x<ddm->x+ddm->a&&m.y>ddm->y&&m.y<ddm->y+ddm->h) {
draw(m,lenth);
// printf("333\n");
}
}
void oriflowsave(int x,int y,int w,int h){
setfillcolor(GREEN);
int i;
int num=0;
for(int j=0; j<h; j++) {
for(i=1; i<=w; i++) {
a[num].lx=x+1+i*81;
a[num].ly=y+1+j*81;
a[num].wide=80;
a[num].h=80;
a[num].useflag=0;
fillrectangle(a[num].lx,a[num].ly,a[num].lx+a[num].wide,a[num].ly+a[num].h);
num++;
}
}
}
void rehave(ExMessage m,int w,int h) {
int i;
int num=0;
for(int j=0; j<w; j++) {
for(i=1; i<=h;i++) {
if(m.x>a[num].lx&&m.x<a[num].lx+a[num].wide&&m.y>a[num].ly&&m.y<a[num].ly+a[num].h) {
if(a[num].useflag==1) {
ndnf=a[num].b;
break;
}
}
num++;
}
}
}
void pickpen(ExMessage m,int w,int h) {
int i,j;
int num=0;
for(j=0; j<w; j++) {
for(i=1; i<=h; i++) {
if(m.x>a[num].lx&&m.x<a[num].lx+a[num].wide&&m.y>a[num].ly&&m.y<a[num].ly+a[num].h) {
if(a[num].useflag==1) {
getimage(&maptile,a[num].lx,a[num].ly,80,80);
fillrectangle(20,80,100,160);
putimage(20,80,&maptile);
}
}
num++;
}
}
}
void flowsave(ExMessage m,struct pircle *save,int w,int h) {
if(m.message==WM_LBUTTONDOWN) {
pickpen(m,w,h);
} else if(m.message==WM_LBUTTONUP) {
// 单机直接粘贴bug但是可以作为长按的刷新,接入其他地方
int i;
int num=0;
for(int j=0; j<w; j++) {
for(i=1; i<=h; i++) {
if(m.x>a[num].lx&&m.x<a[num].lx+a[num].wide&&m.y>a[num].ly&&m.y<a[num].ly+a[num].h) {
if(a[num].useflag==0) {
a[num].b=nf;
if(save->nowlx!=save->orilx&&save->nowly!=save->orily) {
putimage(save->nowlx,save->nowly,&save->img3);
} else {
getimage(&save->img2,save->orilx,save->orily,save->a,save->h);
}
putimage(a[num].lx,a[num].ly,&save->img2);
save->nowlx=save->orilx;
save->nowly=save->orily;
save->m1x=0;
save->m1y=0;
// printf("%d\n",save->m1x);
save->putflag=false;
a[num].useflag=1;
break;
}
}
num++;
}
}
}
if(m.message==WM_RBUTTONDOWN) {
rehave(m,w,h);
}
}
extern int w2,h2;
void movecheck(struct ExMessage m,struct pircle *save) {
if(save->putflag==0&&m.message==WM_LBUTTONDOWN) {
if(save->m1x==0&&save->m1y==0&&m.x>save->orilx&&m.x<save->orilx+save->a&&m.y>save->orily&&m.y<save->orily+save->h) {
getimage(&save->img2,save->orilx,save->orily,save->a,save->h);
getimage(&save->img3,save->orilx,save->orily,save->a,save->h);
save->m1x=m.x;
save->m1y=m.y;
save->putflag=true;
printf("2222\n");
} else if(m.x>save->nowlx&&m.x<save->nowlx+save->a&&m.y>save->nowly&&m.y<save->nowly+save->h) {
save->putflag=true;
getimage(&save->img2,save->orilx,save->orily,save->a,save->h);
save->m1x=m.x;
save->m1y=m.y;
// printf("11111\n");
}
} else if(save->putflag==true) {
BeginBatchDraw();
putimage(save->nowlx,save->nowly,&save->img3);
save->nowlx=save->nowlx+m.x-save->m1x;
save->nowly=save->nowly+m.y-save->m1y;
save->m1x=m.x;
save->m1y=m.y;
getimage(&save->img3,save->nowlx,save->nowly,save->a,save->h);
putimage(save->nowlx,save->nowly,&save->img2);
EndBatchDraw();
if(m.message==WM_LBUTTONUP) {
save->putflag=0;
}
// 一次绘图出来,没有屏闪了
}
}
void buttonscheck(ExMessage m,struct pircle *save) {
static int flag=0;
if(flag==0) {
rectangle(20,20,60,40);
flowsave(m,save,w2,h2);
flag=1;
}
movecheck(m,save);
flowsave(m,save,w2,h2);
}
extern IMAGE set;
//重置绘图版功能
void ori(struct drawdesksize ddm) {
int i,j;
int square=ddm.sizetile;
setfillcolor(WHITE);
setlinecolor(GREEN);
for(i=ddm.x; i<=ddm.x+ddm.a-square; i+=square) {
for(j=ddm.y; j<ddm.y+ddm.h; j+=square) {
fillrectangle(i,j,i+square,j+square);
}
}
for(i=ddm.smx; i<ddm.smx+ddm.a/ddm.sizetile; i++) {
for(j=ddm.smy; j<ddm.smy+ddm.h/ddm.sizetile; j++) {
putpixel(i,j,WHITE);
}
}
// rectangle(ddm.smx-1,ddm.y-1,ddm.x,ddm.y);
}
void pixnf(int lenth,struct drawdesksize ddm) {
// 小地图打印
int i=0;
for(i=0; i<lenth; i++) {
putpixel(ddm.smx+nf.a[i].x,ddm.smy+nf.a[i].y,WHITE);
if(i%55==0)
Sleep(1);
}
for(i=0; i<lenth; i++) {
putpixel(ddm.smx+nf.a[i].x,ddm.smy+nf.a[i].y,BLACK);
if(i%55==0)
Sleep(1);
}
}
void keycheck(ExMessage m,int *lenth) {
switch(m.vkcode) {
case VK_F1:
ori(ddm);
*lenth=0;
// 优化清屏后叠加在小地图bug'
break;
case VK_F2 :
saveimage(_T("gamemap.png"),&set);
break;
case VK_F5 :
static int limf5=0;
if(limf5==0) {
pixnf(*lenth,ddm);
limf5=1;
break;
} else {
limf5=0;
}
// 限制一次按动,一次调用,因为获取getmessage函数有连续两次探测。
break;
}
}
int main() {
oripicdesk(1800,870);
oridrawdesksize(&ddm,1000,100);
oripircle(&save,&ddm);
oriset(&set,ddm,w,h);
//初始化表格,界面
setlinecolor(BLACK);
oriflowsave(x2,y2,w2,h2);
drawdesk(ddm);
ExMessage m;
int lenth=0;
while (1) {
m = getmessage(EX_MOUSE | EX_KEY);
drawmousecheck(m,&lenth,&ddm);
keycheck(m,&lenth);
buttonscheck(m,&save);
show(&set,m,showx3,showy3,600,700);
}
closegraph();
return 0;
}
上面的整合版本是展示
下面是实际开发.h组合cpp的版本
分类说明
.h版本的功能模块
主函数,可以看出来一次循环执行内容,功能与名称相统一。
main.cpp文件代码
新建项目,复制粘贴,有的保存为cpp,有的保存为.h文件
原始版本:
#include<stdio.h>
#include<graphics.h>
//INputboX
#include<windows.h>
//Sleep(2000);
//在中断休止
#include <conio.h>
// kbhit(void);检测按键,无也继续下去
#include<string.h>
//保存导入输入
#include"oripic.h"
#include"show.h"
#include"draw.h"
#include"flowsave.h"
#include"movecheck.h"
#include"buttoncheck.h"
#include"keycheck.h"
int w=3600;
int h=800;
int w2=3,h2=7;
int x2=650,y2=100;
int showx3=101,showy3=100;
int main() {
oripicdesk(1800,870);
oridrawdesksize(&ddm,1000,100);
oripircle(&save,&ddm);
oriset(&set,ddm,w,h);
//初始化表格,界面
setlinecolor(BLACK);
oriflowsave(x2,y2,w2,h2);
drawdesk(ddm);
ExMessage m;
int lenth=0;
while (1) {
m = getmessage(EX_MOUSE | EX_KEY);
drawmousecheck(m,&lenth,&ddm);
keycheck(m,&lenth);
buttonscheck(m,&save);
show(&set,m,showx3,showy3,600,700);
}
closegraph();
return 0;
}
oripic.h文件代码
初始化,但是这个函数属于最后写的,把一些代码整合,美观一点。其他没啥用
extern int w,h;
IMAGE set(w,h);
struct pixlocal {
short x;
short y;
};
struct skline {
int lenth=0;
int setx,sety;
struct pixlocal a[10000];
} nf,ndnf;
struct drawdesksize {
int x;
int y;
int a;
int h;
int sizetile=8;
int smx;
int smy;
} ddm;
IMAGE maptile(ddm.a/ddm.sizetile,ddm.h/ddm.sizetile);
struct pircle {
IMAGE img2;
IMAGE img3;
int orilx,orily;
int nowlx,nowly;
int a,h;
// 原有图片的左上角坐标
int m1x=0,m1y=0;
int putflag=0;
int drawflag=0;
struct skline b;
} save;
struct picsave {
int lx;
int ly;
int wide;
int h;
int useflag;
struct skline b;
} a[28];
void oripicdesk(int a,int h) {
initgraph(a,h,EX_SHOWCONSOLE);
setbkcolor(WHITE);
cleardevice();
// 创制绘图界面,背景色设置,以背景色填充。
setlinecolor(BLACK);
setlinestyle(PS_SOLID,1);
// 不含实线,矩形的面积为8*8;含实线,9*9.
rectangle(0,0,a-2,h-1);
//确定工作界面范围
setfillcolor(WHITE);
}
void oridrawdesksize(struct drawdesksize* ddm,int x,int y) {
ddm->x=x;
ddm->y=y;
ddm->a=640;
ddm->h=640;
ddm->sizetile=8;
ddm->smx=ddm->x-ddm->a/ddm->sizetile;
ddm->smy=ddm->y-ddm->h/ddm->sizetile;
}
void drawdesk(struct drawdesksize ddm) {
int i,j;
int square=ddm.sizetile;
for(i=ddm.x; i<=ddm.x+ddm.a-square; i+=square) {
for(j=ddm.y; j<ddm.y+ddm.h; j+=square) {
fillrectangle(i,j,i+square,j+square);
}
}
rectangle(ddm.smx-1,ddm.smy-1,ddm.x,ddm.y);
}
void oripircle(struct pircle *save,struct drawdesksize *ddm) {
save->orilx=ddm->smx,save->orily=ddm->smy;
save->nowlx=ddm->smx,save->nowly=ddm->smy;
save->a=ddm->a/ddm->sizetile;
save->h=ddm->h/ddm->sizetile;
// 原有图片的左上角坐标
save->m1x=0,save->m1y=0;
save->putflag=0;
save->drawflag=0;
}
void oriset(IMAGE *set,struct drawdesksize ddm,int w,int h) {
SetWorkingImage(set);
setbkcolor(YELLOW);
cleardevice();
setlinecolor(BLACK);
for(int i=0; i<h; i+=ddm.a/ddm.sizetile) {
for(int j=0; j<w; j+=ddm.h/ddm.sizetile)
rectangle(j+1,i+1,j+ddm.a/ddm.sizetile,i+ddm.h/ddm.sizetile);
}
line(0, 0, 800, 1400);
SetWorkingImage();
}
这就是本篇文案解决的问题后产生的代码,
可以和DevC++ easyx实现悬浮窗放入网格,与在函数分离过程中遇到的BUG下理解 函数的作用时域 以及 初始化与复位的关系。-CSDN博客
与DevC++ easyx实现地图拖动,超过屏幕大小的巨大地图的局部显示在屏幕的方法——用悬浮窗的原理来的实现一个视口-CSDN博客
对比看一看代码,这就是视口编辑代码的族谱。
视口代码。maptile就是粘贴的瓦片,set就是大地图,其他函数参数是视口位置坐标,自己换点数据试试,自然而然。
show.h文件代码
extern struct skline nf,ndnf;
extern IMAGE maptile;
void didshow(IMAGE *set,IMAGE maptile,ExMessage m,int show_x,int show_y,int nowlx,int nowly) {
static int flag=0;
static int oldx=-8,oldy=-8;
int putx,puty;
IMAGE olds(80,80);
if(m.message==WM_LBUTTONDOWN) {
SetWorkingImage(set);
putx=nowlx+m.x-show_x;
puty=nowly+m.y-show_y;
putx=putx-putx%80;
puty=puty-puty%80;
putimage(putx,puty,&maptile);
SetWorkingImage();
} else{
if(putx==oldx&&puty==oldy) {
} else {
if(m.message==WM_LBUTTONDOWN) {
}
printf("show %d %d\n",m.x,m.y);
SetWorkingImage(set);
putx=nowlx+m.x-show_x;
puty=nowly+m.y-show_y;
putx=putx-putx%80;
puty=puty-puty%80;
putimage(putx,puty,&maptile);
oldx=putx;
oldy=puty;
SetWorkingImage();
}
}
}
void show(IMAGE *set,ExMessage m,int show_x,int show_y,int show_wideth,int show_height) {
// 视口的图片大小,视口的大小,在窗口的坐标,视口的大小
static int nowlx,nowly,pic_wide,pic_heigh;
static int m1x,m1y;
static int drawflag,putflag,attachflag;
static IMAGE olds(show_wideth,show_height);
static IMAGE news(show_wideth,show_height);
static int m2x,m2y;
// 加速移动设置,自动移动设置。
static int flag=1;
if(flag==1) {
pic_wide=show_wideth;
pic_heigh=show_height;
m1x=0;
m1y=0;
m2x=0;
m2y=0;
drawflag=0;
putflag=0;
attachflag=0;
flag=0;
setlinecolor(BLACK);
rectangle(show_x,show_y,show_x+show_wideth,show_y+show_height);
BeginBatchDraw();
SetWorkingImage(set);
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
SetWorkingImage();
putimage(show_x,show_y,&olds);
EndBatchDraw();
} else {
if(m.message==WM_LBUTTONDOWN) {
if(m.ctrl&&m.x>show_x&&m.x<show_x+show_wideth&&m.y>show_y&&m.y<show_y+show_height) {
putflag=true;
// 启动批复制粘贴
// printf("%d\n",door.putflag);
SetWorkingImage(set);
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
// 获取视口里的图片
//
m1x=m.x;
m1y=m.y;
m2x=m.x;
m2y=m.y;
// printf("%d %d\n",m1x,m1y);
SetWorkingImage();
} else if (m.x>show_x&&m.x<show_x+show_wideth&&m.y>show_y&&m.y<show_y+show_height) {
// printf("333333\n");
didshow(set,maptile,m,show_x,show_y,nowlx,nowly);
attachflag=true;
}
} else if(attachflag==true&&m.x>show_x&&m.x<show_x+show_wideth&&m.y>show_y&&m.y<show_y+show_height) {
didshow(set,maptile,m,show_x,show_y,nowlx,nowly);
if(m.message==WM_LBUTTONUP) {
attachflag=false;
}
SetWorkingImage(set);
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
SetWorkingImage();
putimage(show_x,show_y,&olds);
} else if(putflag==true) {
BeginBatchDraw();
SetWorkingImage();
SetWorkingImage(set);
nowlx=nowlx-5*(m.x-m1x);
nowly=nowly-5*(m.y-m1y);
// 进行了位移放大。
// 位移同鼠标位移方向相反,大小相同
m1x=m.x;
m1y=m.y;
getimage(&olds,nowlx,nowly,pic_wide,pic_heigh);
// 获取新地方的底图,为了下次重现,不干扰下次获取临近底图。
// putimage(save->nowlx,save->nowly,&save->img2);
SetWorkingImage();
putimage(show_x,show_y,&olds);
// putimage(500,500,&save->img3);
EndBatchDraw();
// 一次绘图出来,没有屏闪了
if(m.message==WM_LBUTTONUP||m.ctrl==0) {
putflag=0;
}
}
}
}
draw.h文件代码
这是绘制瓦片纹理的像素绘图板的绘制矩形像素部分。
做了一点优化,如果还是属于原来的方块,就不执行绘制了。减少重复绘制。
extern IMAGE maptile;
//用于设置绘图画布大小
//用于记录轨迹
void remem(struct ExMessage m,int *lenth,struct drawdesksize ddm) {
int i=*lenth;
static int oldx=-ddm.sizetile,
oldy=-ddm.sizetile,
a=ddm.sizetile,
h=ddm.sizetile;
if(m.x>oldx&&m.x<oldx+a&&m.y>oldy&&m.y<oldy+h) {
//节约运算,只在绘制时进行坐标变换
} else {
int px=0,py=0,qx=0,qy=0;
int mapqx=0,mapqy=0;
//修正可涂色范围,防止溢出。y<不可等于640+100,x等于640+600-1是边界小方块的最右侧像素
px=m.x-ddm.x;
py=m.y-ddm.y;
//修正600的偏移,601=600+1;0==1%8 ,600=600+(601-600)%8
qx=px-px%a;
qy=py-py%h;
mapqx=qx/a;
mapqy=qy/h;
px=ddm.x+qx;
py=ddm.y+qy;
setfillcolor(BLACK);
fillrectangle(px,py,px+ddm.sizetile,py+ddm.sizetile) ;
nf.a[i].x = mapqx;
nf.a[i].y = mapqy;
i++;
*lenth=i;
nf.lenth=*lenth;
printf("%d %d %d\n",i-1,nf.a[i-1].x,nf.a[i-1].y);
putpixel(ddm.smx+nf.a[i-1].x,ddm.smy+nf.a[i-1].y,BLACK);
oldx=px;
oldy=py;
}
}
void draw(ExMessage m,int *lenth) {
// 绘制的函数
static int flag=0;
if(m.message==WM_LBUTTONDOWN) {
remem(m,lenth,ddm);
// printf("222\n");
flag=1;
} else if(flag==1) {
remem(m,lenth,ddm);
if(m.message==WM_LBUTTONUP) {
flag=0;
}
}
}
void drawmousecheck(ExMessage m,int *lenth,struct drawdesksize * ddm) {
if(m.x>ddm->x&&m.x<ddm->x+ddm->a&&m.y>ddm->y&&m.y<ddm->y+ddm->h) {
draw(m,lenth);
// printf("333\n");
}
}
flowsave.h文件
绿色网格检测白色瓦片用于暂存。
void oriflowsave(int x,int y,int w,int h){
setfillcolor(GREEN);
int i;
int num=0;
for(int j=0; j<h; j++) {
for(i=1; i<=w; i++) {
a[num].lx=x+1+i*81;
a[num].ly=y+1+j*81;
a[num].wide=80;
a[num].h=80;
a[num].useflag=0;
fillrectangle(a[num].lx,a[num].ly,a[num].lx+a[num].wide,a[num].ly+a[num].h);
num++;
}
}
}
void rehave(ExMessage m,int w,int h) {
int i;
int num=0;
for(int j=0; j<w; j++) {
for(i=1; i<=h;i++) {
if(m.x>a[num].lx&&m.x<a[num].lx+a[num].wide&&m.y>a[num].ly&&m.y<a[num].ly+a[num].h) {
if(a[num].useflag==1) {
ndnf=a[num].b;
break;
}
}
num++;
}
}
}
void pickpen(ExMessage m,int w,int h) {
int i,j;
int num=0;
for(j=0; j<w; j++) {
for(i=1; i<=h; i++) {
if(m.x>a[num].lx&&m.x<a[num].lx+a[num].wide&&m.y>a[num].ly&&m.y<a[num].ly+a[num].h) {
if(a[num].useflag==1) {
getimage(&maptile,a[num].lx,a[num].ly,80,80);
fillrectangle(20,80,100,160);
putimage(20,80,&maptile);
}
}
num++;
}
}
}
void flowsave(ExMessage m,struct pircle *save,int w,int h) {
if(m.message==WM_LBUTTONDOWN) {
pickpen(m,w,h);
} else if(m.message==WM_LBUTTONUP) {
// 单机直接粘贴bug但是可以作为长按的刷新,接入其他地方
int i;
int num=0;
for(int j=0; j<w; j++) {
for(i=1; i<=h; i++) {
if(m.x>a[num].lx&&m.x<a[num].lx+a[num].wide&&m.y>a[num].ly&&m.y<a[num].ly+a[num].h) {
if(a[num].useflag==0) {
a[num].b=nf;
if(save->nowlx!=save->orilx&&save->nowly!=save->orily) {
putimage(save->nowlx,save->nowly,&save->img3);
} else {
getimage(&save->img2,save->orilx,save->orily,save->a,save->h);
}
putimage(a[num].lx,a[num].ly,&save->img2);
save->nowlx=save->orilx;
save->nowly=save->orily;
save->m1x=0;
save->m1y=0;
// printf("%d\n",save->m1x);
save->putflag=false;
a[num].useflag=1;
break;
}
}
num++;
}
}
}
if(m.message==WM_RBUTTONDOWN) {
rehave(m,w,h);
}
}
movecheck.h文件
就是DevC++ easyx实现图片拖动,一种悬浮窗实现原理与完整代码-CSDN博客
extern int w2,h2;
void movecheck(struct ExMessage m,struct pircle *save) {
if(save->putflag==0&&m.message==WM_LBUTTONDOWN) {
if(save->m1x==0&&save->m1y==0&&m.x>save->orilx&&m.x<save->orilx+save->a&&m.y>save->orily&&m.y<save->orily+save->h) {
getimage(&save->img2,save->orilx,save->orily,save->a,save->h);
getimage(&save->img3,save->orilx,save->orily,save->a,save->h);
save->m1x=m.x;
save->m1y=m.y;
save->putflag=true;
printf("2222\n");
} else if(m.x>save->nowlx&&m.x<save->nowlx+save->a&&m.y>save->nowly&&m.y<save->nowly+save->h) {
save->putflag=true;
getimage(&save->img2,save->orilx,save->orily,save->a,save->h);
save->m1x=m.x;
save->m1y=m.y;
// printf("11111\n");
}
} else if(save->putflag==true) {
BeginBatchDraw();
putimage(save->nowlx,save->nowly,&save->img3);
save->nowlx=save->nowlx+m.x-save->m1x;
save->nowly=save->nowly+m.y-save->m1y;
save->m1x=m.x;
save->m1y=m.y;
getimage(&save->img3,save->nowlx,save->nowly,save->a,save->h);
putimage(save->nowlx,save->nowly,&save->img2);
EndBatchDraw();
if(m.message==WM_LBUTTONUP) {
save->putflag=0;
}
// 一次绘图出来,没有屏闪了
}
}
void buttonscheck(ExMessage m,struct pircle *save) {
static int flag=0;
if(flag==0) {
rectangle(20,20,60,40);
flowsave(m,save,w2,h2);
flag=1;
}
movecheck(m,save);
flowsave(m,save,w2,h2);
}
keycheck.h文件
这个是按键实现保存,清屏处理。
这也是软件快捷键的执行的代码。
extern IMAGE set;
//重置绘图版功能
void ori(struct drawdesksize ddm) {
int i,j;
int square=ddm.sizetile;
setfillcolor(WHITE);
setlinecolor(GREEN);
for(i=ddm.x; i<=ddm.x+ddm.a-square; i+=square) {
for(j=ddm.y; j<ddm.y+ddm.h; j+=square) {
fillrectangle(i,j,i+square,j+square);
}
}
for(i=ddm.smx; i<ddm.smx+ddm.a/ddm.sizetile; i++) {
for(j=ddm.smy; j<ddm.smy+ddm.h/ddm.sizetile; j++) {
putpixel(i,j,WHITE);
}
}
// rectangle(ddm.smx-1,ddm.y-1,ddm.x,ddm.y);
}
void pixnf(int lenth,struct drawdesksize ddm) {
// 小地图打印
int i=0;
for(i=0; i<lenth; i++) {
putpixel(ddm.smx+nf.a[i].x,ddm.smy+nf.a[i].y,WHITE);
if(i%55==0)
Sleep(1);
}
for(i=0; i<lenth; i++) {
putpixel(ddm.smx+nf.a[i].x,ddm.smy+nf.a[i].y,BLACK);
if(i%55==0)
Sleep(1);
}
}
void keycheck(ExMessage m,int *lenth) {
switch(m.vkcode) {
case VK_F1:
ori(ddm);
*lenth=0;
// 优化清屏后叠加在小地图bug'
break;
case VK_F2 :
saveimage(_T("gamemap.png"),&set);
break;
case VK_F5 :
static int limf5=0;
if(limf5==0) {
pixnf(*lenth,ddm);
limf5=1;
break;
} else {
limf5=0;
}
// 限制一次按动,一次调用,因为获取getmessage函数有连续两次探测。
break;
}
}