使用ks0108的12864液晶显示的俄罗斯方块

本文介绍了一种使用ks0108液晶显示器实现12864分辨率的俄罗斯方块游戏的方法。通过定义相关变量、绘制函数、初始化和游戏逻辑控制,实现了游戏的显示、移动、旋转等功能。文章提供了详细的代码实现,包括清屏、绘制线条、初始化块、游戏开始和检查游戏结束的函数。
摘要由CSDN通过智能技术生成

先等上来一个文件,还有几个以后登。算法参考了毛建忠的ToyBricks.c,在此表示感谢。

#include "Lcd_ks0108.h"

#define LINE 12//12行
#define ROW  8//8列
volatile unsigned char Block_Old[4][2],Block_Now[4][2];//记录方块原先的位置和现在的位置

,4,代表一个图形由4个方块组成,2代表x,y

volatile unsigned char MapCell[LINE+1][ROW+2];// =

{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,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,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,0,0,0,0,0,0};//方块活动区
volatile unsigned char flag;
volatile unsigned char top;
volatile unsigned char NumNow,NumNext;
volatile unsigned int  Score;
volatile unsigned char IsEnd;
volatile unsigned char IsStart;

//************************************************************************/
//*屏幕使用区域
// |----------x(0-95)------------|
// -         |
// |         |
// |         |   

96*64
// y(0-63)        |  
// |         | 
// |         |
// -         |
// |-----------------------------|
//每个方块8*8,屏幕上总共有12*8个方格,这样安排是由于液晶一页是8位,为了便于计算,取此值。
//可以建立一个12*8的数组,标记此块是否为使用,使用的话,增加新块的时候原先的块不被占用
//                                                                      */
//************************************************************************/
/**********************************************/
//write command
/**********************************************/
void Lcd_Command(unsigned char code)
{
 LOW(E);  //following the timing , first, start E.
 LOW(RS);
 LOW(RW);
 delay_nus(150);
 DATA = code;
 HIGH(E);
 delay_nms(1);
 LOW(E);
 delay_nus(300);
}

/**********************************************/
//write data
/**********************************************/
void Lcd_Data(unsigned char data)
{
 LOW(E);
 HIGH(RS);
 LOW(RW);
 delay_nus(150);
 DATA = data;
 HIGH(E);
 delay_nms(1);
 LOW(E);
 delay_nus(300);

}

/********************************************/
//initial
/********************************************/
void initial_lcd()
{
 Control_DDR = 0xFF;  //as output
 Data_DDR = 0xFF;
 Control_PORT = 0x00;
 Data_PORT = 0x00;

 HIGH(LCD_CS1);
 HIGH(LCD_CS2);
 Lcd_Command(OPEN_DISP); //open display
 //Lcd_Command(DISP_RAM_YROW); //Y position is 0;
}

void ks0108cls (void)       //清屏,光标回到左半屏左上角  
{  
 unsigned char i0,i1;  
 LOW(LCD_CS1);
 LOW(LCD_CS2);
 Lcd_Command(OPEN_DISP);          //打开显示  
 Lcd_Command(DISP_RAM_YROW);          //列地址回到0  
 for(i0=0;i0<8;i0++)     //页地址由0变到7  
 {  
  Lcd_Command(DISP_RAM_PAGE + i0);    
  for(i1=0;i1<64;i1++)//对某一行全写入0  
   Lcd_Data(0);
 }  
}

/********************************************/
//Draw a line
//
//
//           

   
// 0 *****************************************
//  *     *    

 *
//  *  part1  *  part2  *
//  *     *    

 *
//  *  0 - 64  *  0 - 64  * 
//  *     *    

 *
//  *     *    

 *
//  *     *    

 *
// 63 ***************************************** 
//
/********************************************/
void Lcd_DrawLine(unsigned char x,unsigned char y,unsigned char linelength)
{
 Lcd_Command(OPEN_DISP);
 Lcd_Command(DISP_RAM_STARTLINE);
 unsigned char i,temp,data;
 data = 0;
 x = (x>127)? 127:x;
 y = (y>63)? 63:y;
 //judge by the position and length
 switch (x>64)
 {
 case 1://this line is in part2
  HIGH(LCD_CS1);
  LOW(LCD_CS2);
  Lcd_Command(DISP_RAM_PAGE + y/8);//确定在哪一页,8位一页,共8页,取其商

就是页数
  Lcd_Command(DISP_RAM_YROW + x - 64);//确定在哪一列,it has restriction

before,
           

//no less than 64, no more than 127.
  if (x + linelength > 128) linelength = 128 - x;//长度过长,就让他

在最右端结束

  data |= (1<<y%8);//we have confirm the page , now ,we need to know the

exactitude position
  for(i=0;i<linelength;i++)
   Lcd_Data(data);
  break;
 case 0://this line is in part1
  LOW(LCD_CS1);
  HIGH(LCD_CS2);
  Lcd_Command(DISP_RAM_PAGE + y/8);//确定在哪一页,8位一页,共8页,取其商

就是页数
  Lcd_Command(DISP_RAM_YROW + x);//确定在哪一列
  data |= (1<<y%8);
  switch(x + linelength > 64)
  {
  case 1://too long
   temp = 64 - x;
   for(i=0;i<temp;i++)//the part1
    Lcd_Data(data);
   LOW(LCD_CS2);
   HIGH(LCD_CS1);
   Lcd_Command(DISP_RAM_PAGE + y/8);//确定在哪一页,8位一页,共8页

,取其商就是页数
   Lcd_Command(DISP_RAM_YROW);//确定在哪一列

   if (x + linelength < 128) //longer than part1,shorter than

part2
    linelength = linelength + x - 64;
   else
    linelength = 64;

   for(i=0;i<linelength;i++)//the part2
    Lcd_Data(data);

   break;
  case 0://not long
   for(i=0;i<linelength;i++)//the part1
    Lcd_Data(data);
   break;   
  }
  break;
 }


}
/********************************************/
//Draw a vertical line
//
//
//  0     63    

 127  
//  *****************************************
//  *     *    

 *
//  *  part1  *  part2  *
//  *     *    

 *
//  *  0 - 64  *  0 - 64  * 
//  *     *    

 *
//  *     *    

 *
//  *     *    

 *
//  ***************************************** 
//  63
/********************************************/
void Lcd_DrawVerticalLine(unsigned char x,unsigned char y,unsigned char linelength)
{
 unsigned char i,data,fullpagenum;
 Lcd_Command(OPEN_DISP);
 Lcd_Command(DISP_RAM_STARTLINE);
 x = (x>127)? 127:x;
 y = (y>63)? 63:y;
 data = 0;
    //this function is easier than top one,for he no need to judge the part1 or part2.

 fullpagenum = (linelength - 1 - (7 - (y%8)))/8;//how many full pages
 switch (x<64)
 {
 case 1://in part 1
  LOW(LCD_CS1);
  HIGH(LCD_CS2);
  Lcd_Command(DISP_RAM_PAGE + y/8);//确定在哪一页,8位一页,共8页,取其商

就是页数
  Lcd_Command(DISP_RAM_YROW + x);//确定在哪一列
  //接下来这个判断还挺麻烦,用英语更麻烦,还是写汉语吧.需要判断这根线有多高
  //写数据是一次写8位,应该又要和商和余数纠缠了
  

//
  //    --------------------*----------------

-----------------
  //  page1  *  *  * 

 *  *
  //     *  *  

*  *  *
  //    ----*-------*-------*-------*--------

------------------
  //  page2  *  *  *
  //       *  


  //    ------------*-------*----------------

----------------
  //  page3    *  *
  //
  //    -------------------------------------

----------------  //  
  

//
  //起始点不用判断,主要是判断跨越了多少个完整page
  if ((linelength - 1 + y%8) < 8)//只在一个page内
  {
   for (i = 0;i < linelength - y%8 + 1;i++)
   {
    Lcd_Command(DISP_RAM_YROW + x);//确定在哪一列,列地址会

变,所以得改回来
    data |= (1<<(y%8 + i));
   }
   Lcd_Data(data);//把第一个page显示出来
  }
  else//在不只一个page内
  {
   if(fullpagenum > 0)//在不只一个page内,而且至少包含一个完整page
   {
    //在很多个page里,那么就先写第一个page
    for(i = 0;i < 7 - y%8 + 1;i++)
    {
     Lcd_Command(DISP_RAM_YROW + x);//确定在哪一列,

列地址会变,所以得改回来
     data |= (1<<(y%8 + i));
    }
    Lcd_Data(data);//先把第一个page显示出来
    //then we display the leaving pages,注意!,these are

full pages
    for (i = 0;i < fullpagenum;i++)
    {
     Lcd_Command(DISP_RAM_PAGE + y/8 + 1 + i);//确

定在哪一页
     Lcd_Command(DISP_RAM_YROW + x);//确定在哪一列,

列地址会变,所以得改回来
     Lcd_Data(0xFF);
    }
    //last ,we display the last page
    if (((linelength - 1 - (7 - (y%8)))%8)!=0)//表示下面还

突出去一页
    {
     for(i = 0;i < ((linelength - 1 - (7 - (y%

8)))%8);i++)
     {
      Lcd_Command(DISP_RAM_PAGE + y/8 +

fullpagenum + 1);//确定在哪一页
      Lcd_Command(DISP_RAM_YROW + x);//确定

在哪一列,列地址会变,所以得改回来
      data |= (1<<i);
      Lcd_Data(data);
     }
    }
   }
   else//在不只一个page内,but the second one is not full
   {
    for (i = 0;i < (linelength - 1 - (7 - (y%8)));i++)
    {
     Lcd_Command(DISP_RAM_PAGE + y/8 + 1);
     Lcd_Command(DISP_RAM_YROW + x);
     data |= (1<<i);
     Lcd_Data(data);
    }
   }
  }
  break;
 case 0://in part 2  两部分代码完全一样,就是改了改x,这样很傻,但是容易看懂
  LOW(LCD_CS2);
  HIGH(LCD_CS1);
  Lcd_Command(DISP_RAM_PAGE + y/8);//确定在哪一页,8位一页,共8页,取其商

就是页数
  Lcd_Command(DISP_RAM_YROW + x - 64);//确定在哪一列
  if ((linelength - 1 + y%8) < 8)//只在一个page内
  {
   for (i = 0;i < linelength - y%8 + 1;i++)
   {
    Lcd_Command(DISP_RAM_YROW + x - 64);//确定在哪一列,列地

址会变,所以得改回来
    data |= (1<<(y%8 + i));
   }
   Lcd_Data(data);//把第一个page显示出来
  }
  else//在不只一个page内
  {
   if(fullpagenum > 0)//在不只一个page内,而且至少包含一个完整page
   {
    //在很多个page里,那么就先写第一个page
    for(i = 0;i < 7 - y%8 + 1;i++)
    {
     Lcd_Command(DISP_RAM_YROW + x - 64);//确定在哪

一列,列地址会变,所以得改回来
     data |= (1<<(y%8 + i));
    }
    Lcd_Data(data);//先把第一个page显示出来
    //then we display the leaving pages,注意!,these are

full pages
    for (i = 0;i < fullpagenum;i++)
    {
     Lcd_Command(DISP_RAM_PAGE + y/8 + 1 + i);//确

定在哪一页
     Lcd_Command(DISP_RAM_YROW + x - 64);//确定在哪

一列,列地址会变,所以得改回来
     Lcd_Data(0xFF);
    }
    //last ,we display the last page
    if (((linelength - 1 - (7 - (y%8)))%8)!=0)//表示下面还

突出去一页
    {
     for(i = 0;i < ((linelength - 1 - (7 - (y%

8)))%8);i++)
     {
      Lcd_Command(DISP_RAM_PAGE + y/8 +

fullpagenum + 1);//确定在哪一页
      Lcd_Command(DISP_RAM_YROW + x - 64);//

确定在哪一列,列地址会变,所以得改回来
      data |= (1<<i);
      Lcd_Data(data);
     }
    }
   }
   else//在不只一个page内,but the second one is not full
   {
    for (i = 0;i < (linelength - 1 - (7 - (y%8)));i++)
    {
     Lcd_Command(DISP_RAM_PAGE + y/8 + 1);
     Lcd_Command(DISP_RAM_YROW + x - 64);
     data |= (1<<i);
     Lcd_Data(data);
    }
   }
  }
  break;

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值