?
左邊是游戲地圖編輯區(qū),右邊是地圖緩沖區(qū),解決了地圖緩沖區(qū)拖動(dòng)bug,成功使得緩沖區(qū)可以更新。
AWSD進(jìn)行移動(dòng)
鼠標(biāo)左右鍵分別是繪制/拖動(dòng)
按F1健導(dǎo)出為mapv3.txt
F2清空數(shù)組
打印的是游戲數(shù)組文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-823127.html
easyx開(kāi)發(fā)devcpp 5.11 easyx20220922版本文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-823127.html
#include <graphics.h>
#include <stdio.h>
#define ROW 150 // 游戲地圖行
#define COLUMN 150 // 游戲地圖列
//#define ROW 20 // 游戲地圖行
//#define COLUMN 20 // 游戲地圖列
#define PIXNUM 30 // 一個(gè)瓦片邊長(zhǎng)為 30 像素
#define SHOWSIZE 10 // 一個(gè)視口邊長(zhǎng)為 5 個(gè)瓦片
#define BUFFERSIZE 3 // 地圖緩沖區(qū)邊長(zhǎng) 3 個(gè)視口
#define SHOWSPEED 4 // 游戲地圖背景移動(dòng)速度
#define SHOWX 300 // 游戲顯示區(qū)域
#define SHOWY 300
typedef struct area {
int lx; // 左上角坐標(biāo)
int ly;
int rx; // 右上角坐標(biāo)
int ry;
int high; // 高度
int wide;
} area;
typedef struct checkBackgroundBuffer { // 用于記錄緩沖條件的臨界數(shù)據(jù)
int xmin;
int ymin;
int xmax;
int ymax;
int adjust;
} bklimit;
typedef struct background { // 游戲地圖背景
area gamepos; // 采樣區(qū)相對(duì)于緩沖區(qū)的坐標(biāo)
area deskpos; // 改 bug 整理得到一個(gè)新結(jié)構(gòu)體,把窗口坐標(biāo)封裝了
int nowpointx; // 在整個(gè)地圖數(shù)組映射形成的地圖上的坐標(biāo)
int nowpointy;
IMAGE *gamebk;
} bk;
typedef struct backgroundBuffer { // 游戲背景緩沖區(qū)
area meshpos;
int meshrow;
int meshcolumn;
bklimit bufferlimit;
IMAGE *mapmesh; // 緩沖區(qū),長(zhǎng)寬各為 3*size*a 個(gè)像素
} 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; // 瓦片的大小正方形像素瓦片的邊長(zhǎng)
int showsize=SHOWSIZE;
int buffersize = BUFFERSIZE;
bk bkgd; // background
bkbuffer bkgdbu; // backgroundbuffer
IMAGE b(3*showsize*pixnum,3*showsize*pixnum); // mapmesh 緩沖區(qū)
IMAGE a(showsize*pixnum,showsize*pixnum); // 采樣區(qū),采樣的到的圖片就是屏幕上的游戲
// 清除地圖
void clearmap();
// 保存編輯完的地圖
void savemap();
//讀取txt字符表格作為背景數(shù)組
void loadmap();
//檢測(cè)背景是否需要更新
bool buchange() {
bool changeflag=0;
while(bkgd.gamepos.lx>bkgdbu.bufferlimit.xmax) { // if else if變 while 解決鼠標(biāo)拖動(dòng),導(dǎo)致的多次平移問(wèn)題
bkgd.gamepos.lx-=bkgdbu.bufferlimit.adjust;
bkgdbu.meshpos.lx+=showsize;
changeflag=1;
printf("死循環(huán)\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;
}
//刷新背景緩沖區(qū)
void freshbuffer() {
SetWorkingImage(bkgdbu.mapmesh); // 選擇緩沖區(qū)為更新對(duì)象
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坐標(biāo)與數(shù)組的對(duì)應(yīng)關(guān)系 第二個(gè)方括號(hào)【】是列數(shù),是橫坐標(biāo)x,控制第幾列
case 0:
setfillcolor(BLACK); // 二維數(shù)組瓦片是 0,則選擇黑色瓦片
break;
case 1:
setfillcolor(WHITE); // 二維數(shù)組瓦片是 1,則選擇白色瓦片
break;
case 2:
setfillcolor(GREEN); // 二維數(shù)組瓦片是 2,則選擇綠色瓦片
break;
case 3:
setfillcolor(BLUE); // 二維數(shù)組瓦片是 3,則選擇藍(lán)色瓦片
break;
}
fillrectangle(j*pixnum,i*pixnum,(j+1)*pixnum,(i+1)*pixnum); // 貼圖瓦片
}
}
SetWorkingImage();
}
//刷新屏幕
void show() {
SetWorkingImage(bkgdbu.mapmesh); // 從緩沖區(qū)采樣
getimage(bkgd.gamebk,bkgd.gamepos.lx,bkgd.gamepos.ly,showsize*pixnum,showsize*pixnum);
SetWorkingImage();
putimage(bkgd.deskpos.lx,bkgd.deskpos.ly,bkgd.gamebk); // 打印采樣區(qū),理解連續(xù)更新
putimage(700,pixnum,bkgdbu.mapmesh);
if(bkgd.gamebk==NULL) {
printf("圖片是空的\n");
}
if(bkgdbu.mapmesh==NULL) {
printf("圖片是空的\n");
}
}
//檢測(cè)鼠標(biāo)是否在某一區(qū)域
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;
}
}
//修改背景數(shù)組
void draw(ExMessage msg) {
int mapx=0; // 在采樣區(qū)的坐標(biāo)
int mapy=0;
int mapi=0; // 當(dāng)前所在的背景數(shù)組瓦片坐標(biāo)
int mapj=0;
int allmapi; // 對(duì)應(yīng)整個(gè)數(shù)組的坐標(biāo)
int allmapj;
static int oldmapi=0; // 上一次繪制的背景數(shù)組坐標(biāo)瓦片坐標(biāo)
static int oldmapj=0;
static int drawflag=0;
if(drawflag==1&&checkarea(msg,bkgd.deskpos)) {
mapx=msg.x-bkgd.deskpos.lx; // 相對(duì)于游戲窗口左上角的坐標(biāo)距離
mapy=msg.y-bkgd.deskpos.ly;
mapi=(mapy+bkgd.gamepos.ly)/pixnum; // 整除瓦片邊長(zhǎng),算出來(lái)是在緩沖區(qū)的哪個(gè)瓦片
mapj=(mapx+bkgd.gamepos.lx)/pixnum;
allmapi=mapi+bkgdbu.meshpos.ly; // 計(jì)算在相對(duì)于整個(gè)地圖數(shù)組左上角 (0,0) 的瓦片位置
allmapj=mapj+bkgdbu.meshpos.lx;
if(oldmapi!=allmapi||oldmapj!=allmapj) { // 如果不相同,才進(jìn)行繪制, 節(jié)約運(yùn)算
oldmapi=allmapi;
oldmapj=allmapj;
map[allmapi][allmapj]=2; // 緩沖區(qū)的那個(gè)瓦片坐標(biāo)實(shí)際上是原來(lái)完整地圖的那個(gè)瓦片坐標(biāo)。
printf("游戲采樣區(qū)網(wǎng)格坐標(biāo) x = %d, y = %d\n",mapj,mapi);
freshbuffer();
}
}
if(msg.message ==WM_LBUTTONDOWN&&checkarea(msg,bkgd.deskpos)) {
mapx=msg.x-bkgd.deskpos.lx; // 相對(duì)于游戲窗口左上角的坐標(biāo)距離
mapy=msg.y-bkgd.deskpos.ly;
mapi=(mapy+bkgd.gamepos.ly)/pixnum; // 整除瓦片邊長(zhǎng),算出來(lái)是在緩沖區(qū)的哪個(gè)瓦片
mapj=(mapx+bkgd.gamepos.lx)/pixnum;
allmapi=mapi+bkgdbu.meshpos.ly; // 計(jì)算在相對(duì)于整個(gè)地圖左上角 (0,0) 的數(shù)組瓦片位置
allmapj=mapj+bkgdbu.meshpos.lx;
oldmapi=allmapi;
oldmapj=allmapj;
map[allmapi][allmapj]=2;
printf("游戲采樣區(qū)網(wǎng)格坐標(biāo) x = %d, y = %d\n",mapj,mapi);
printf("游戲采樣區(qū)像素坐標(biāo) x = %d, y = %d\n",bkgd.gamepos.lx,bkgd.gamepos.ly);
printf("游戲緩沖區(qū)網(wǎng)格坐標(biāo) x = %d, y = %d\n",bkgdbu.meshpos.lx,bkgdbu.meshpos.ly);
freshbuffer();
drawflag=1;
} else if(msg.message==WM_LBUTTONUP) {
drawflag=0;
}
}
// 右鍵拖動(dòng)游戲地圖——用坐標(biāo)變換是無(wú)解的,因?yàn)槭髽?biāo)位移detalx detaly的范圍持續(xù)更新給了數(shù)據(jù),
void draft(ExMessage msg) {
static int flag=0;
static int oldmx=0; // 鼠標(biāo)右鍵時(shí)的鼠標(biāo)像素坐標(biāo)
static int oldmy=0;
static int gamex=bkgd.nowpointx; // 舊的采樣區(qū)位置,加上鼠標(biāo)拖動(dòng)的位移就是新的采樣區(qū)位置
static int gamey=bkgd.nowpointy;
SetWorkingImage();
if(msg.message == WM_RBUTTONDOWN&&checkarea(msg,bkgd.deskpos)) {
flag=1; // 長(zhǎng)按flag
oldmx=msg.x; // 記錄拖動(dòng)的起點(diǎn)
oldmy=msg.y;
gamex=bkgd.nowpointx; // 只能使用絕對(duì)坐標(biāo),相對(duì)坐標(biāo) bkgd.gamepos.lx 坐標(biāo)范圍是 0-2*showsize*pixnum ,但是相對(duì)坐標(biāo)可以通過(guò)記錄改寫(xiě),但是不如絕對(duì)坐標(biāo)直觀好寫(xiě)
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); // 圖片移動(dòng)的距離等于鼠標(biāo)移動(dòng)的距離
bkgd.nowpointy =gamey- (msg.y-oldmy); // 移動(dòng)方向和鼠標(biāo)移動(dòng)方向相反
bkgd.gamepos.lx=bkgd.nowpointx-bkgdbu.meshpos.lx*pixnum; // 絕對(duì)坐標(biāo)和相對(duì)坐標(biāo)的變換,游戲采樣區(qū)的像素坐標(biāo)和網(wǎng)格坐標(biāo)在buchange() 函數(shù)里重新分配,保證游戲采樣區(qū)的像素坐標(biāo)范圍在 0-2*showsize*pixnum 里
bkgd.gamepos.ly=bkgd.nowpointy-bkgdbu.meshpos.ly*pixnum; // nowpointx y 像素坐標(biāo)改變,然后再修改網(wǎng)格坐標(biāo),網(wǎng)格坐標(biāo)修改完,再到buchange()里增加修改絕對(duì)像素坐標(biāo)
// printf("msg.x = %d,msg.y = %d\n",msg.x,msg.y);
}
if(msg.message == WM_RBUTTONUP) {
flag=0;
}
}
//按鍵移動(dòng)
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; // 移動(dòng)速度
if(msg.message==WM_KEYDOWN) { // 開(kāi)始游戲某個(gè)方向移動(dòng)
switch(msg.vkcode) {
case 0x41: // A
flag_a=movespeed;
break;
case 0x44: // D
flag_d=movespeed;
break;
case 0x57: // W
flag_w=movespeed;
break;
case 0x53: // S
flag_s=movespeed;
break;
}
} else if(msg.message==WM_KEYUP) { // 取消某一方向的持續(xù)移動(dòng)
switch(msg.vkcode) {
case 0x41: // A
flag_a=0;
break;
case 0x44: // D
flag_d=0;
break;
case 0x57: // W
flag_w=0;
break;
case 0x53: // S
flag_s=0;
break;
}
}
// if(>&&<){
// +=flah_a;
// }else{
// +=flag_a;
// }
bkgd.gamepos.lx-=flag_a; // 左移采樣區(qū)
bkgd.gamepos.lx+=flag_d; // 右移采樣區(qū)
bkgd.gamepos.ly-=flag_w; // 上移采樣區(qū)
bkgd.gamepos.ly+=flag_s; // 下移采樣區(qū)
}
//初始化地圖緩沖區(qū)
void initbkbuffer() {
bkgdbu.mapmesh = &b; // 掛載地圖緩沖區(qū)
bkgdbu.meshpos.lx=0;
bkgdbu.meshpos.ly=0;
bkgdbu.meshrow=BUFFERSIZE*showsize;
bkgdbu.meshcolumn=BUFFERSIZE*showsize;
bkgdbu.bufferlimit.adjust=showsize*pixnum; // 緩沖區(qū)需要更新的臨界條件
bkgdbu.bufferlimit.xmax=2*showsize*pixnum; // 超過(guò)九宮格就立即更新,采樣區(qū)默認(rèn)在九宮格的中心
bkgdbu.bufferlimit.xmin=0;
bkgdbu.bufferlimit.ymax=2*showsize*pixnum;
bkgdbu.bufferlimit.xmin=0;
freshbuffer();
SetWorkingImage();
// putimage(700,pixnum,bkgdbu.mapmesh); // 緩沖區(qū)可視化
}
//初始化地圖采樣區(qū)
void initbk() {
bkgd.gamebk = &a; // 如果是在這里聲明臨時(shí)變量 a ,函數(shù)執(zhí)行完畢之后,程序就會(huì)銷(xiāo)毀變量
bkgd.gamepos.lx=showsize*pixnum; // 采樣區(qū)默認(rèn)位置
bkgd.gamepos.ly=showsize*pixnum;
bkgd.nowpointx=bkgd.gamepos.lx; // 絕對(duì)位置,用于解決gamepos 范圍在 0~2*showsize*pixnum 導(dǎo)致的筆刷繪制失敗bug
bkgd.nowpointy=bkgd.gamepos.ly; // 打表檢測(cè),讀表時(shí)發(fā)現(xiàn)的繪制位置始終在一個(gè)區(qū)域內(nèi),才發(fā)現(xiàn)的這個(gè)bug
bkgd.deskpos.lx=SHOWX; // 采樣之后的粘貼位置
bkgd.deskpos.ly=SHOWY;
bkgd.deskpos.rx=bkgd.deskpos.lx+showsize*pixnum; // 粘貼區(qū)域的大小,用于檢測(cè)鼠標(biāo)指針是否在該區(qū)域內(nèi)繪制
bkgd.deskpos.ry=bkgd.deskpos.ly+showsize*pixnum;
SetWorkingImage(bkgdbu.mapmesh);
getimage(bkgd.gamebk,bkgd.gamepos.lx,bkgd.gamepos.ly,showsize*pixnum,showsize*pixnum); // 加載屏幕地圖,開(kāi)始采樣
SetWorkingImage();
putimage(bkgd.deskpos.lx,bkgd.deskpos.ly,bkgd.gamebk); // 粘貼采樣結(jié)果
}
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); // 鍵盤(pán)awsd檢查
draft(msg); // 鼠標(biāo)右鍵拖動(dòng)檢查
draw(msg); // 鼠標(biāo)左鍵繪制
if(buchange()) {
freshbuffer(); // 刷新九宮格緩沖區(qū)
printf("九宮格已刷新\n");
}
if(msg.message==WM_KEYDOWN) {
if(msg.vkcode==VK_F1) {
savemap();
} else if(msg.vkcode== VK_F2) {
clearmap();
}
}
show(); // 打印緩沖區(qū),打印新的采樣結(jié)果,更新游戲背景, 結(jié)算完畢統(tǒng)一顯示
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");
}
}
到了這里,關(guān)于瓦片地圖編輯器——實(shí)現(xiàn)卡馬克卷軸的編輯,鍵盤(pán)控制游戲移動(dòng)和鼠標(biāo)點(diǎn)擊游戲編輯通過(guò)同一個(gè)視口實(shí)現(xiàn)。的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!