⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 16x16飞机射击游戏.c

📁 16X16点阵做的射击游戏,类似于俄罗斯方块的点阵游戏,附带proteus仿真原理图.keilC51编译
💻 C
字号:
/*******************************************************
*******16X16点阵飞机射击游戏****************************
********************************************************
**广东技术师范学院天河学院-电气工程系-电气062班*********
***************梁宏阁***********************************
*******************************************************/
////////////////////////////////////////////////////////															  
#include "reg51.h"
#include "absacc.h"
#include "intrins.h"
#include "stdio.h"
 ///////////////////
 #define DENGFANKAISHIJIAN 30
 #define QUDOUDONGSHIJIAN 2
 /////////////
sbit P21 =P2^1 ;
sbit P22 =P2^2 ;
sbit P23 =P2^3 ;
sbit P24 =P2^4 ;
#define P00	P0
////////////////////
sbit A_L =P1^1 ;  //左移动
sbit A_R =P1^2 ;  //右移动
sbit A_F =P1^3 ;  //射击
sbit A_S =P1^4 ;   //开始/暂停
sbit A_T =P1^5 ;   //退出
///////////////////////////////////
#define ZUO(a) P00=a;P24=0;P24=1
#define YOU(a) P00=a;P21=0;P21=1
#define SHANG(a)  P00=a;P22=0;P22=1
#define XIA(a)    P00=a;P23=0;P23=1
//////////////////////////////////////////
//////////////////////////////////////////

typedef struct //"飞机"用结构体统一信息
{
  unsigned char x; //飞机的X坐标,最大为9
  unsigned int t; //飞机头显示内容
  unsigned int w;//飞机尾显示内容
} FEIJI;

FEIJI feiji;//定义飞机变量
///////////////////////////
idata char GoOrStay ;//状态标记-1为未开始,0为正在游戏,1为暂停,2为设置状态
idata char TU_Y;//最接近飞机的Y轴标记自向下数,最上层为1,无层时为0
idata char xuanze;//选择start为0否为1
idata unsigned char Guan;//关数
unsigned char TU[32];//16X16图像数组
idata unsigned char time_a=0;
idata unsigned int time_b=0;//定时器内和关数有关的增量
////////////////////////////////


/*3x5字模*/
unsigned char code S_3X5[10][5]={{0x0e,0x0a,0x0a,0x0a,0x0e}/*0*/,{0x04,0x0c,0x04,0x04,0x04}/*1*/,
{0x0e,0x02,0x0e,0x08,0x0e}/*2*/,{0x0e,0x02,0x0e,0x02,0x0e}/*3*/,{0x0a,0x0a,0x0e,0x02,0x02}/*4*/,
{0x0e,0x08,0x0e,0x02,0x0e}/*5*/,{0x0e,0x08,0x0e,0x0a,0x0e}/*6*/,{0x0e,0x02,0x02,0x02,0x02}/*7*/,
{0x0e,0x0a,0x0e,0x0a,0x0e}/*8*/,{0x0e,0x0a,0x0e,0x02,0x0e}/*9*/,
};
/*start+setup字模*/
unsigned char code start_setup[32]={
0x1c,0x07,0x09,0x02,0x6a,0xb2,0x8a,0xaa,
0xeb,0xb2,0x2a,0xaa,0xca,0xaa,0x00,0x00,
0x03,0x80,0x01,0x06,0x6d,0x55,0x89,0x56,
0xed,0x54,0x29,0x54,0xcd,0x74,0x00,0x00};
unsigned char code start[32]={
0x1c,0x07,0x09,0x02,0x6a,0xb2,0x8a,0xaa,
0xeb,0xb2,0x2a,0xaa,0xca,0xaa,0x00,0x00,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned char code setup[32]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0x03,0x80,0x01,0x06,0x6d,0x55,0x89,0x56,
0xed,0x54,0x29,0x54,0xcd,0x74,0x00,0x00};
 /*STAY字模*/
unsigned char code stay[32]={
0x00,0x00,0x1f,0x00,0x04,0x11,0x04,0x0a,
0x74,0x04,0x84,0xc4,0x85,0x24,0x65,0x24,
0x15,0x24,0x15,0xe4,0xe5,0x20,0x05,0x20,
0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00
};
/*OVER字模*/
unsigned char code over[32]={
0xaa,0xaa,0xff,0xff,0x00,0x00,0x00,0x06,
0x05,0x35,0x65,0x45,0x95,0x46,0x95,0x75,
0x95,0x45,0x65,0x45,0x02,0x35,0x00,0x00,
0xff,0xff,0x55,0x55,0xff,0xff,0x55,0x55
}  ;
/*WIN字模*/
unsigned char code win[32]={
0x55,0x55,0xff,0xff,0x00,0x00,0xa9,0x40,
0x55,0x40,0x55,0x40,0x48,0x80,0x00,0x00,
0x0a,0xa4,0x0a,0xaa,0x05,0x2a,0x00,0x00,
0xff,0xff,0x00,0x00,0xff,0xff,0xaa,0xaa
};
///////////函数声明/////////////////////
extern void feijitu(void);	//根据飞机的x坐标写出它的头尾形状,再给回TU数组
extern void ZHENGJIAYIXING(void);//增加一行
extern void chuqihua(void);//初始化显示
extern void DELAY(unsigned int a);	 //延时子函数a最大为十进制65535
//extern unsigned char zhenli(unsigned char a);//整理调整函数
extern void dian1616(unsigned char ZZ[]);//16X16显示主函数
extern void guanshu(unsigned char n);//将当前关卡加入到数组
extern void QuDouDong(unsigned int a);//去抖动,同时显示
extern void SheJi(void); //射击调整函数
extern void AnNiu_S(void);//判开始暂停按钮
extern void AnNiu_T(void);//判断退出按钮
extern void AnNiu_L(void);//判左移按钮
extern void AnNiu_R(void);//判右移出按钮
extern void AnNiu_F(void);//判射击按钮
extern void AnNiu(void);//按钮合集
extern void SHANstart(void);//闪START 
extern void SHANsetup(void);//闪SETUP
extern void SHAN( char a);//闪0闪start,1闪setup
extern void winORfail(void);//判断胜利还是失败
///////////////////////////////////////


/////////////////////////以下为显示一个16X16/////
 void DELAY(unsigned int a)	 //延时子函数a最大为十进制65535
 {while(a--)
   ;
 }

void dian1616(unsigned char ZZ[])//16X16主函数
{ unsigned char a,b;  //a放行号,b放字在数组的序号
	 if(GoOrStay!=2)
 	 feijitu();	 //加入飞机位置状态
	 guanshu(Guan);	//关数

   b=0;
  XIA(0x00);		 //不送出下半部分
  for(a=0x01;a!=0;a=(a<<1))	  //上半个字
  {	
     DELAY(50) ;//延时一小段时间为看清楚
     ZUO(ZZ[b]) ; //调调整函数,送出左
	 b++ ;
	 YOU(ZZ[b]); //送出右
	 b++ ;

    SHANG(a) ;//送出行号

	DELAY(50) ;//延时一小段时间为了字型显示更清楚

	    ZUO(0) ;  //消影
		YOU(0); 
  }
    SHANG(0x00);		 //不送出上半部分
  for(a=0x01;a!=0;a=(a<<1))	  //下半个字
  {	 DELAY(50) ;//延时一小段时间为看清楚
     

     ZUO(ZZ[b]) ; //调整函数,送出左
	 b++ ;
	 YOU(ZZ[b]); //送出右
	 b++ ;

     XIA(a); //送出行号

	 DELAY(50) ;//延时一小段时间为了字型显示更清楚

		  ZUO(0) ; //消影
		  YOU(0); 
  }   
}
//////////////////以上为显示一个16X16////
 void ZHENGJIAYIXING(void)//增加一行
 {
  char a;
  for(a=15;a>-1;a--)
  {	TU[2*(a+1)]=TU[2*a];
    TU[2*(a+1)+1]=((TU[2*a+1]&0xe0)|(TU[2*(a+1)+1]&0x3f)); //保留信息状态区的内容
  }
   TU[0]=0xff;	//补上第0行显示内容
   TU[1]=(0xe0|(TU[1]&0x3f)); //保留信息状态区的内容


  	   TU_Y=(TU_Y+1); 
 } 
 ////
void feijitu(void) //根据飞机的x坐标,写出它的头尾形态,并再其给回TU数组 
{ 
  unsigned char a;
   feiji.t=0x8000;
  for(a=0;a<feiji.x;a++)
  {
	 feiji.t>>=1;  //右移一位
  }

   feiji.w=(((feiji.t|(feiji.t>>1)&0xffe0)|(feiji.t<<1))&0xffe0);	//尾显示形态

   feiji.t=(feiji.t&0xffe0)|((unsigned int)(0x20|(TU[29]&0x3f))); //保留信息状态区的内容
   feiji.w=(feiji.w&0xffe0)|((unsigned int)(0x20|(TU[31]&0x3f))); //保留信息状态区的内容

   TU[28]=(unsigned char)(feiji.t>>8);
   TU[29]=(unsigned char)feiji.t;
   TU[30]=(unsigned char)(feiji.w>>8);
   TU[31]=(unsigned char)feiji.w;
}
///
void guanshu(unsigned char n) //将当前关卡加入到数组
{
  char a;
  if(n<10)
  {
  for(a=2;a<7;a++)
  {
	 TU[2*a+1]=(TU[2*a+1]&0xe0)|S_3X5[n][a-2];
  }
  }
}
///////////////////////////
void SHANstart(void)   //闪start
{	  char a;
        a=15;
	   while(a--)
	   {
   dian1616(setup); //显示
     AnNiu();
   }
  		a=15;
		while(a--)
	{ dian1616(start_setup); //显示
	  AnNiu();
	}
}
//
void SHANsetup(void)  //闪setup
{	  char a;
        a=15;
	   while(a--)
	   {
   dian1616(start); //显示
   	AnNiu();
   }
  		a=15;
		while(a--)
		{
	 dian1616(start_setup); //显示
	 AnNiu();
	 }
}
//
void SHAN( char a)//a决定0闪start,1闪setup
{
 if(a==0)
 SHANstart();
 else
 SHANsetup();
}
/////////////////////////////////
void QuDouDong(unsigned int a)//去抖动,同时显示
{  
   while(a--)
   {
   if(GoOrStay!=2)
   feijitu();   //加入飞机位置状态
   guanshu(Guan);//加入显示关数
   dian1616(TU); //16x16点阵显示
   }
}
///////
void AnNiu_S(void)//判开始按钮
{  
 	unsigned int n;//超时退出变量
	 A_S=1;
	if(A_S==0)
	{
	 A_S=1;
	 QuDouDong(QUDOUDONGSHIJIAN);//去抖动
	 if(A_S==0)
	 {
	 if(xuanze==0)//如为开始
	 {
	 if(GoOrStay==-1)
	 
		GoOrStay=0;//标记为开始
		else
		{
		if(GoOrStay==0)
		  GoOrStay=1;//如果已开始则暂停
		  else
		 if(GoOrStay==1)
		  {GoOrStay=0;//如果已暂停则开始
		  }
		}
	
	}
	 if(GoOrStay==2)//如为设置
	 {	GoOrStay=-1;//标记为未开始
	    xuanze=0;
	 }
	if(xuanze==1)//如为选择
	 	GoOrStay=2;	 
		
			//等手放开
	n=DENGFANKAISHIJIAN;
	while(A_S==0)
	{
	A_S=1;
	dian1616(TU); //显示
	n--;
	if(n==0)
	break;//按钮超时退出
	}
	}
  } 
}
////
void AnNiu_L(void)//左按钮
{
  unsigned int n;//超时变量
  A_L=1;
 if(A_L==0)
  {
   A_L=1;
   QuDouDong(QUDOUDONGSHIJIAN);	//去抖动
   	if(A_L==0)	//确认进入
	{
	 if(GoOrStay==0)//如果正在游戏则用左右功能
	 {
	 if(feiji.x==0)//如果是最左则去最右
	 {
	   feiji.x=9;
	 }
	 else
	 {
	 feiji.x--;//沿x轴左移
	 }

	}
	if(GoOrStay==-1)//如果未开始则为上下选择功能
	{
	  if(xuanze==0)
	  xuanze=1;
	  else
	  xuanze=0;
	}
	if(GoOrStay==2)//如果为设置则选择关数
	 {
	  if(Guan==9)
	   Guan=0;
	   else
	   Guan++;
	 }
		 	//等手放开
	n=DENGFANKAISHIJIAN;
	while(A_L==0)
	{
	A_L=1;
	dian1616(TU); //显示
	n--;
	if(n==0)
	break;//按钮超时退出
	}
	}//
  }
}
///
  ////
void AnNiu_R(void)//右按钮
{
  unsigned int n;//超时变量
  A_R=1;
 if(A_R==0)
  {
   A_R=1;
   QuDouDong(QUDOUDONGSHIJIAN);	//去抖动
   	if(A_R==0)	//确认进入
	{
	 if(GoOrStay==0)//如果正在游戏则用左右功能
	 {
	 if(feiji.x==9)//如果是最右则去最左
	 {
	   feiji.x=0;
	 }
	 else
	 {
	 feiji.x++;//沿x轴右移
	 }

	}
	if(GoOrStay==-1)//如果未开始则为上下选择功能
	{
	  if(xuanze==0)
	  xuanze=1;
	  else
	  xuanze=0;
	}
	 if(GoOrStay==2)//如果为设置则选择关数
	 {
	  if(Guan==0)
	   Guan=9;
	   else
	   Guan--;
	 }
		 	//等手放开
	n=DENGFANKAISHIJIAN;
	while(A_R==0)
	{
	A_R=1;
	dian1616(TU); //显示
	n--;
	if(n==0)
	break;//按钮超时退出
	}
	}//
  }
}
///
//////
void AnNiu_T(void)//退出
{
 unsigned int n;
 A_T=1;
 if(A_T==0)
 {
   A_T=1;
   if(A_T==0)
   {
	A_T=1;
	QuDouDong(QUDOUDONGSHIJIAN);//去抖动
	if(A_T==0)
	{
      chuqihua();    //初始化


	 //等手放开
	n=DENGFANKAISHIJIAN;
	while(A_T==0)
	{
	A_T=1;
	dian1616(TU); //显示
	n--;
	if(n==0)
	break;//按钮超时退出
	}
	}
   }
 }
}
///
///
void SheJi(void) //射击调整函数
{  idata char y;
   
   y=TU_Y;
  
  if(y!=0)
  {

   if(feiji.x<8)//找出最凹的y坐标
    { 	 //在左半面找
	   for(;((~TU[2*(y-1)])&(0X80>>feiji.x))==((unsigned char)(feiji.t>>8));y--)
	   ;
	}
		 else 
	{	 //在右半面找
	   for(;((~TU[2*(y-1)+1])&(0X80>>(feiji.x-8)))==((unsigned char)(feiji.t&0xc0));y--)
	       ;
	
	 }
   TU[2*(y-1)]=(unsigned char)((~(feiji.t>>8))&TU[2*(y-1)]);
   TU[2*(y-1)+1]=(unsigned char)(~((feiji.t)&0x00c0)&TU[2*(y-1)+1]);
  
  if((TU[2*(TU_Y-1)]==0)&&((TU[2*(TU_Y-1)+1]&0xc0)==0))
   {TU_Y--;
   	 
   }
   }
   	dian1616(TU); //显示
}
void AnNiu_F(void)//判射击按钮
{	unsigned int n;
	A_F=1;
  if(A_F==0)
  {
   A_F=1;
   QuDouDong(QUDOUDONGSHIJIAN);//去抖动
   if(A_F==0)
   {
    if(GoOrStay==0)
    SheJi();//射击调整函数

	   //等手放开
	n=2; //射击键超时少一点
	while(A_F==0)
	{
	A_F=1;
	dian1616(TU); //显示
	n--;
	if(n==0)
	break;//按钮超时退出
	}
   }
  }
}
void AnNiu(void)  //按钮实现
{
   AnNiu_S() ;//判开始暂停
   AnNiu_L() ;//判断左按钮
   AnNiu_R() ;	 //判断右按钮
   AnNiu_F() ;	 //判断射击
   AnNiu_T() ;//判断退出
  
}
////
void FAIL(void)	//失败画面
{
 idata unsigned int n;
 n=300;
 while(n--)
  dian1616(over);
  chuqihua();//初始化
}	
void WINN(void)//胜利
{

 idata unsigned int n;
 n=300;
 while(n--)
 dian1616(win);
 chuqihua(); //初始化
}

void winORfail(void)//判断胜利还是失败
{ 
  if(Guan>9)//10关全过胜利
   WINN();//胜利画面
  else  
  if(TU_Y>14)
   FAIL();
  
}
////
void SheZhi(void)//设置画面
{
  TU[30]=TU[28]=0xff;//去掉飞机图形
  TU[29]|=0XC0;
  TU[31]|=0XC0;
  
 guanshu(Guan);
 while(GoOrStay==2)
 {
 dian1616(TU); //显示
 AnNiu();
 }
}
//////菜单////
void caidan(void)  
{
 	while(GoOrStay==-1|GoOrStay==2)//如果还没开始
	 {
	 if(GoOrStay==-1)
   SHAN(xuanze);//选择画面
     if(GoOrStay==2) 
	    SheZhi();//设置画面   
	 }
}
///////////////////////////////////////////
void TIME1(void) interrupt 3 //定时器1
{ TH1=0X3C;
  TL1=0XB0;//定时器初值
  EA=0;
  P3=0XF0;	
  	
   //定时器处理
   time_a++;
   if(time_a==(40-Guan*2))
	{ 
	ZHENGJIAYIXING();
	time_a=0;}

   time_b++;
   if(time_b==1200)
   {Guan++;
   time_b=0;
   }
   EA=1;
  TR1=1;
   TF1=0;
}
//定时器初始化
void dishiqi(void)
{
  TMOD=0X10;//定时器工作方式1
  TH1=0X3C;
  TL1=0XB0;//定时器初值
  ET1=1;
  EA=1;
  TF1=0;
  TR1=0;//关定时器
}
////////////////////初始化//////////////////
 void chuqihua(void)//初始显示内容为0
 {
 idata char a;
 dishiqi() ;//定时器初始化
 for(a=0;a<32;a++)
 TU[a]=0x0;
 TU_Y=0;
 A_L =1 ;  //左移动
 A_R =1 ;  //右移动
 A_F =1 ;  //射击
 A_S =1 ;   //开始/暂停
 A_T =1 ; //退出
 P21=1;P22=1;P23=1;P24=1;


 for(a=0;a<16;a++)//画上边
 {
 TU[2*a+1]|=0x20;
 }
 ZHENGJIAYIXING(); //加一层

   feiji.x=5;  //初始飞机位置
   GoOrStay=-1; //置状态标记为未开始
   Guan=0;//初始关卡为0
   
   xuanze=0;

 }
/////////////////////////////////
 

	
void main()	   //程序主函数
{
   chuqihua();//初始化
   while(1)
   {
   	if(GoOrStay==-1) 
  	caidan();
    AnNiu(); //按钮	 
	if(GoOrStay==0)
   {dian1616(TU); //显示
   	TR1=1;//游戏时开定时器
   }
   	   winORfail();//判断是否胜利
   if(GoOrStay==1)	//暂停
    {dian1616(stay);
	 TR1=0;//关定时器
	}
   }
}	  



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -