📄 main.c
字号:
/**********************************************************
*名称:推箱子游戏测试版V0.1
*编程:飞扬
*说明:采用YM12864R-3的液晶(ST7920)+62256的RAM+PT6122的遥控
*下一个版本增加音效,地图编辑功能,界面显示美化,撤销上一步!
*主要是学习外扩展RAM才搞这个东东!
**********************************************************/
#include <at89x52.h>
#include "MAIN.H"
/****** 引脚定义 ******/
sbit Beep = P3^3; //音频输出脚
/****** 变量/数组定义 ******/
//定义数组,存放接收到的数据
uchar KeyCoding[4]={0,0,0,0};
//关卡设置
uchar guanka = 0;
//用1024个字节存放动态绘图数据,我叫它显存数据
uchar xdata GamePic[1024];
//十字形(箱子推到圆形位置后变为十字形)
uchar code shizi[8]={0x3c,0x3c,0xff,0xff,0xff,0xff,0x3c,0x3c};
//圆形(箱子要推到的地方)
uchar code yuan[8]={0x3c,0x66,0xc3,0x81,0x81,0xc3,0x66,0x3c};
//箱子(推动的就是他)
uchar code xiangzi[8]={0xff,0x81,0xbd,0xbd,0xbd,0xbd,0x81,0xff};
//娃娃脸(用于推动箱子)
uchar code lian[8]={0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0x7e};
//墙壁
uchar code qiang[8]={0x00,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x00};
//空(用于清空图形移动后的痕迹)
uchar code kong[8]={0,0,0,0,0,0,0,0};
//用于计算图形移动和放置的坐标
//实际存放的是GamePic数组的相应下标
uint code MoveData[64]={
0,1,2,3,4,5,6,7,
128,129,130,131,132,133,134,135,
256,257,258,259,260,261,262,263,
384,385,386,387,388,389,390,391,
512,513,514,515,516,517,518,519,
640,641,642,643,644,645,646,647,
768,769,770,771,772,773,774,775,
896,897,898,899,900,901,902,903
};
/*8X8的游戏地图数据,同时根据图形数据判断娃娃脸是否可以移动,
*箱子是否可以推动,箱子推动的方向是否是墙和箱子,是则不
*能推动!箱子推到的地方是圆形则用十字形替换(将该位置数据换成5),
*推动十字形,则再恢复到箱子的形状(在换成3).
*空(什么都不显示)=0,墙=1,圆=2,箱子=3,脸=4,十字=5 */
uchar code GameMap[10][64]={
//第一关
{1,1,1,1,1,1,1,1,
1,0,0,0,1,2,0,1,
1,2,0,0,3,0,0,1,
1,1,3,1,1,0,0,1,
1,0,0,1,1,3,1,1,
1,0,0,4,0,0,0,1,
1,0,2,1,0,0,0,1,
1,1,1,1,1,1,1,1},
//第二关
{1,1,1,1,1,1,1,1,
1,0,0,0,1,0,0,1,
1,0,2,0,3,2,0,1,
1,1,3,1,1,0,0,1,
1,0,0,1,1,3,1,1,
1,0,0,4,0,2,0,1,
1,0,0,1,0,0,0,1,
1,1,1,1,1,1,1,1},
//第三关
{1,1,1,1,1,1,1,1,
1,0,0,0,1,0,0,1,
1,0,0,0,3,0,0,1,
1,0,3,1,1,0,0,1,
1,0,2,1,1,3,1,1,
1,0,2,4,0,0,0,1,
1,0,2,1,0,0,0,1,
1,1,1,1,1,1,1,1},
//第四关
{1,1,1,1,1,1,1,1,
1,0,0,0,1,0,0,1,
1,0,2,0,3,2,0,1,
1,1,3,1,1,0,0,1,
1,0,0,1,1,3,1,1,
1,0,2,4,0,0,0,1,
1,0,0,1,0,0,0,1,
1,1,1,1,1,1,1,1},
//第五关
{1,1,1,1,1,1,1,1,
1,0,0,0,1,0,0,1,
1,0,0,2,3,0,0,1,
1,1,3,1,1,0,0,1,
1,0,2,1,1,3,1,1,
1,0,0,4,2,0,0,1,
1,0,0,1,0,0,0,1,
1,1,1,1,1,1,1,1},
//6
{1,1,1,1,1,1,1,1,
1,1,0,1,1,0,2,1,
1,0,0,3,0,0,0,1,
1,4,3,3,0,0,0,1,
1,0,1,0,0,1,0,1,
1,0,1,1,1,1,0,1,
1,2,0,0,0,0,2,1,
1,1,1,1,1,1,1,1},
//7
{1,1,1,1,1,1,1,1,
1,0,0,1,0,0,0,1,
1,0,0,1,0,5,0,1,
1,0,0,1,0,2,1,1,
1,1,0,3,0,0,0,1,
1,0,3,0,0,2,0,1,
1,4,0,1,1,0,0,1,
1,1,1,1,1,1,1,1},
//8
{1,1,1,1,1,1,1,1,
1,1,4,0,1,1,1,1,
1,0,0,0,3,2,0,1,
1,0,0,1,0,0,0,1,
1,0,0,0,1,5,0,1,
1,1,0,3,0,0,0,1,
1,1,1,1,0,2,0,1,
1,1,1,1,1,1,1,1},
//9
{1,1,1,1,1,1,1,1,
1,2,0,1,1,1,1,1,
1,2,0,0,0,1,1,1,
1,0,1,3,0,0,0,1,
1,2,0,3,3,1,0,1,
1,1,0,0,0,0,0,1,
1,1,1,1,1,0,4,1,
1,1,1,1,1,1,1,1},
//10
{1,1,1,1,1,1,1,1,
1,1,0,1,1,0,2,1,
1,0,3,0,3,3,0,1,
1,4,0,0,0,0,0,1,
1,0,1,0,0,1,0,1,
1,0,1,1,1,1,0,1,
1,2,0,0,0,0,2,1,
1,1,1,1,1,1,1,1}
};
//因为程序存储器中的的是只读的!
//用于复制程序存储器中的当前地图数据
uchar idata Map[64];
//用于存放圆形的坐标,最多5个圆
//yuanPos[6]存放本关有几个圆
uchar xdata yuanPos[6]=0;
/**********************************************************
*函数名:CopyMap()
*功 能:用于复制程序存储器中的当前地图数据
*输 入:入口参数为当前地图编号
**********************************************************/
void CopyMap(uchar num)
{
uchar i;
for (i=0;i<64;i++)
{
Map[i] = GameMap[num][i];
}
}
/**********************************************************
*函数名:WriteMemorizer()
*功 能:将图形数据写入显存
*pos:要显示图形的位置,*p:指针指向要显示的图形
**********************************************************/
void WriteMemorizer(uchar pos,uchar *p)
{
uchar i;
uint j;
j = MoveData[pos]; //取显存地址(显示坐标)
for (i=0;i<8;i++)
{
GamePic[j] = *p; //要显示的图形写入显存
p++; //下一个数据
j+=16;//显存的下一个地址(每个地址之间的差是16)
} //或者说是间隔是16.
}
/**********************************************************
*函数名:MapCreate()
*功 能:地图生成程序
**********************************************************/
void MapCreate()
{
uchar i;
for (i=0;i<64;i++) //生成8X8的地图
{
switch (Map[i])//获得地图上的图形数据
{
case 0:
WriteMemorizer(i,kong);//空
break;
case 1:
WriteMemorizer(i,qiang);//墙
break;
case 2:
WriteMemorizer(i,yuan);//圆
break;
case 3:
WriteMemorizer(i,xiangzi);//箱子
break;
case 4:
WriteMemorizer(i,lian);//脸
break;
case 5:
WriteMemorizer(i,shizi);//十字
break;
}
}
}
/**********************************************************
*函数名:GameDisplay()
*功 能:游戏图形显示程序(从左到右,从上到下)
**********************************************************/
void GameDisplay()
{
uchar i,j;
uint k=0; //对显存清计数器清0
LCDWriteCommand(0x34);//扩充指令集
LCDWriteCommand(0x36);//绘图显示开
for (i=0;i<32;i++) //写上半屏(32行)
{
LCDWriteCommand(0x80+i);//Y地址寄存器
LCDWriteCommand(0x80); //X地址(LCM自动加1)
for (j=0;j<16;j++)//16x8列
{
LCDWriteData(GamePic[k]);//写入一个字节图形数据
k++; //指向下一个图形字节
}
}
for (i=0;i<32;i++) //写下半屏
{
LCDWriteCommand(0x80+i);//Y地址寄存器
LCDWriteCommand(0x88); //X地址(LCM自动加1)
for (j=0;j<16;j++)//
{
LCDWriteData(GamePic[k]);
k++;
}
}
}
/**********************************************************
*函数名:ReadPosition()
*功 能:读得娃娃脸的当前坐标位置
*返 回:ReadPos
**********************************************************/
uchar ReadPosition()
{
uchar i;
uchar ReadPos; //定义变量存放娃娃脸的位置.
for (i=0;i<64;i++)
{
if(Map[i]==4)
{
ReadPos = i; //记录娃娃脸的坐标
break; //找到位置跳出循环
}
}
return (ReadPos); //返回娃娃脸当前位置
}
/**********************************************************
*函数名:Readyuan()
*功 能:读得圆形的坐标位置(箱子移动目的地)
**********************************************************/
void Readyuan()
{
uchar i,j=0;
for (i=0;i<64;i++)
{
if (Map[i]==2) //找出圆形的位置
{
yuanPos[j] = i; //存放圆的位置
j++;
yuanPos[6] = j;//存放有几个圆
}
}
}
/**********************************************************
*函数名:Refyuan()
*功 能:刷新显示圆形(箱子移动目的地)
**********************************************************/
void Refyuan()
{
uchar i;
for (i=0;i<yuanPos[6];i++)
{
if(Map[yuanPos[i]]==0) Map[yuanPos[i]]=2;
}
if (Map[yuanPos[0]]==5&&Map[yuanPos[1]]==5&&Map[yuanPos[2]]==5)
{//过关
guanka++; //进入下一关
if (guanka==10) guanka=0;
CopyMap(guanka); //复制地图数据
MapCreate(); //地图生成程序
GameDisplay();//游戏界面显示程序
Readyuan();//
}
}
/**********************************************************
*函数名:UpMove()
*功 能:娃娃脸向上移动
*说 明:向上移动是-8 (8X8的数据间隔是8)
*空(什么都不显示)=0,墙=1,圆=2,箱子=3,脸=4,十字=5
**********************************************************/
void UpMove()
{
uchar pos;
pos = ReadPosition(); //获得娃娃脸的位置
if (Map[pos-8]!=1)//判断移动方向前面是否是墙
{
switch (Map[pos-8])
{
case 0: //移动方向前面是空的执行这里
Map[pos-8] = 4;//娃娃脸的新位置
Map[pos] =0; //清空娃娃脸位置
break;
case 2: //是圆形执行这里
Map[pos-8] = 4;//娃娃脸的新位置
Map[pos] =0; //清空娃娃脸位置
break;
case 3: //移动方向前面是箱子执行这里
//箱子的前面不是墙或箱子或十字就可以移动
if (Map[pos-16]==0)
{
Map[pos-16]= 3;//显示箱子
Map[pos-8] = 4;//娃娃脸的新位置
Map[pos] = 0; //清空娃娃脸位置
}
else if (Map[pos-16]==2)
{
Map[pos-16]= 5;//显示十字形
Map[pos-8] = 4;//娃娃脸的新位置
Map[pos] = 0; //清空娃娃脸位置
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -