?核心在于 changewait()函数对采样区越界检测,以及对采样区的刷新,就是九宫格绘制到采样区域里。
?
#include <graphics.h>
#include <stdio.h>
// 默认游戏地图
int map[20][20]= {
{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 a=30; // 瓦片的大小正方形像素瓦片的边长
int xc=3*a; // 采样区左上角坐标
int yc=3*a; // 采样区左上角坐标
IMAGE c(3*a,3*a); // 采样图片,就是屏幕上看到的游戏的大小
int see = 9; // 缓冲区的大小
int seex =0; // 缓冲区对应的数组左上角坐标
int seey=0; // 缓冲区对应的数组左上角坐标
IMAGE n(see*a,see*a); // 缓冲区,长宽各为 see*a 个像素
void loadmap();
void changewait() {
int changeflag=0;
if(xc>2*(3*a)) { // 如果采样区移动超过自身一倍
xc=xc-(3*a); // 采样区减少一份长度,
seex+=3; // 缓冲区增加一份长度
changeflag=1; // 如果有重置,就更新缓冲区,重新采样打印
}
if(xc<0) {
xc=xc+3*a;
seex-=3; // 采样区增减和屏幕移动增减同号
changeflag=1;
}
if(yc>2*(3*a)) {
yc=yc-(3*a);
seey+=3;
changeflag=1;
}
if(yc<0) {
yc=yc+(3*a);
seey-=3;
changeflag=1;
}
if(changeflag) {
SetWorkingImage(&n); // 选择缓冲区为更新对象
for(int i=0; i<9; i++) {
for(int j=0; j<9; j++) {
switch (map[i+seey][j+seex]) { // 解决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*a,i*a,(j+1)*a,(i+1)*a); // 贴图瓦片
}
}
changeflag=0;
}
SetWorkingImage(&n); // 从缓冲区采样
getimage(&c,xc,yc,3*a,3*a);
SetWorkingImage();
putimage(800,a,&n); // 打印缓冲区,理解间断更新
putimage(1300,a,&c); // 打印缓冲区,理解连续更新
printf("cx = %d, yc = %d\n",xc,yc);
printf("seex = %d, seey = %d\n",seex,seey);
}
void changev2(ExMessage msg) {
static int flag=0;
static int oldx;
static int oldy;
static int orx=xc;
static int ory=xc;
if(msg.message == WM_RBUTTONDOWN) {
flag=1; // 长按flag
oldx=msg.x; // 记录拖动的起点
oldy=msg.y;
printf("msg.x = %d,msg.y = %d\n",msg.x,msg.y);
} else if(flag==1) { // 长按时不变参考点
xc = orx-(msg.x-oldx); // 图片移动的距离等于鼠标移动的距离
yc= ory-(msg.y-oldy); // 移动方向和鼠标移动方向相反
changewait();
}
if(msg.message == WM_RBUTTONUP) {
flag=0;
orx=xc;
ory=yc;
}
}
void change(ExMessage msg) {
if(msg.message==WM_KEYDOWN) { // 游戏移动
switch(msg.vkcode) {
case 0x41: // A
xc--; // 左移采样区
break;
case 0x44: // D
xc++; // 右移采样区
break;
case 0x57: // W
yc--; // 上移采样区
break;
case 0x53: // S
yc++; // 下移采样区
break;
}
}
changewait();
}
int main() {
loadmap(); // 加载地图
getimage(&n,1*a,1*a,see*a,see*a); // 加载缓冲区
putimage(800,a,&n); // 显示缓冲区
ExMessage msg;
while(1) {
peekmessage(&msg,EX_KEY|EX_MOUSE,true);
change(msg);
changev2(msg);
Sleep(1);
}
closegraph();
return 0;
}
void loadmap() {
// FILE* fp;
// fp=fopen("map.txt","r");
// for(int i=0; i<20; i++) {
// for(int j=0; j<20; j++) {
// fscanf(fp," %d",&map[i][j]);
// }
// fscanf(fp,"\n");
// }
//
// printf("gammap\n");
// for(int i=0; i<20; i++) {
// for(int j=0; j<20; j++) {
// printf(" %d",map[i][j]);
// }
// printf("\n");
// }
// fclose(fp);
initgraph(1800,800,1);
setbkcolor(GREEN);
cleardevice();
for(int i=0; i<20; i++) {
for(int j=0; j<20; j++) {
rectangle(i*a,j*a,(i+1)*a,(j+1)*a);
}
}
setfillcolor(WHITE);
for(int i=0; i<20; i++) {
for(int j=0; j<20; j++) {
switch (map[i][j]) {
case 0:
setfillcolor(BLACK);
break;
case 1:
setfillcolor(WHITE);
break;
case 2:
setfillcolor(GREEN);
break;
case 3:
setfillcolor(BLUE);
break;
}
fillrectangle(j*a,i*a,(j+1)*a,(i+1)*a);
}
}
}