(微控制器原理與應用)大液晶屏的遊戲設計(推箱子)
阿新 • • 發佈:2019-01-09
圖十二 遊戲程式介面
系統的優點與不足
優點:遊戲容易上手,而且可以鍛鍊大腦思維
不足:有些關卡設計簡單
參考文獻
[1] 陳海宴. 51微控制器原理及應用--基於Keil C與Proteus. 北京航空航天大學出版,2010-07-01,第1版.
[2] 彭偉. 微控制器C語言程式設計實訓100例——基於8051+PROTEUS模擬. 電子工業出版社,2009-06-01 .
[3] 浦濱. C遊戲程式設計從入門到精通. 北京希望電子出版社,2002-5-1
[4] 李巨集 張家田,等. 液晶顯示器件應用技術 機械工業出版社, 2004-7-1
[5]AT89c52資料手冊
附錄程式碼
Variable.h #define uchar unsigned char #define uint unsigned int //**********T6963c命令巨集定義*********************// //地址指標設定 #define cur_pos 0x21 //游標位置設定 #define CGR_pos 0x22 //CGRAM偏置地址設定 #define add_pos 0x24 //地址指標位置 //顯示區域設定 #define txt_stp 0x40 //文字區首地址 #define txt_wid 0x41 //文字區寬度 #define grh_stp 0x42 //圖形區首地址 #define grh_wid 0x43 //圖形區寬度 //顯示方式設定 #define mod_or 0x80 //顯示方式:邏輯或 #define mod_xor 0x81 //顯示方式:邏輯異或 #define mod_and 0x82 //顯示方式:邏輯與 #define mod_tch 0x83 //顯示方式:文字特徵 //顯示狀態設定 #define dis_sw 0x90 //顯示開關 //D0=1/0:游標閃爍啟用/禁用 //D1=1/0:游標顯示啟用/禁用 //D2=1/0:文字顯示啟用/禁用 //D3=1/0:圖形顯示啟用/禁用 //游標形狀設定 #define cur_shp 0xa0 //游標形狀選擇:0xa0~0xa7光標占的行數:1行~8行 //資料自動讀寫設定 #define aut_wr 0xb0 //自動寫 #define aut_rd 0xb1 //自動讀 #define aut_ovr 0xb2 //自動讀寫結束 //資料一次讀寫設定 #define inc_wr 0xc0 //資料寫,地址+1 #define inc_rd 0xc1 //資料讀,地址+1 #define dec_wr 0xc2 //資料寫,地址-1 #define dec_rd 0xc3 //資料讀,地址-1 #define noc_wr 0xc4 //資料寫,地址不變 #define noc_rd 0xc5 //資料讀,地址不變 uchar tcount; //中斷計數 uint Timtcount; //計時變數(秒) uchar playing,startflag;//遊戲標誌,開始標誌 uchar levelg; //記錄當前關卡 uchar man_x,man_y; //紀錄當前小人所在位置 //**********lcd12864引腳位定義*********************// sbit wr =P2^0; sbit rd =P2^1; sbit cd =P2^2; sbit rst=P2^3; uchar code Number[][16]= //數字0-9 { 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00, //0 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, //1 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x04,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00, //2 0x00,0x00,0x00,0x3C,0x42,0x42,0x04,0x18,0x04,0x02,0x02,0x42,0x44,0x38,0x00,0x00, //3 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x24,0x44,0x44,0x7E,0x04,0x04,0x1E,0x00,0x00, //4 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00, //5 0x00,0x00,0x00,0x1C,0x24,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x24,0x18,0x00,0x00, //6 0x00,0x00,0x00,0x7E,0x44,0x44,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, //7 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00, //8 0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x26,0x1A,0x02,0x02,0x24,0x38,0x00,0x00, //9 }; //開機畫面 uchar code start_box[]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xE0,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFC,0x7C,0xC0,0x06,0x30,0xC6,0x00,0x1F,0xFF,0xFF,0x00,0x00,0x00, 0x00,0x00,0x01,0x86,0xC7,0xF0,0x06,0x1F,0xC7,0xF8,0x30,0x00,0x01,0xC0,0x00,0x00, 0x00,0x00,0x01,0x87,0x86,0x18,0x0C,0x01,0x80,0x0C,0x30,0x00,0x00,0xC0,0x00,0x00, 0x00,0x00,0x01,0x87,0x82,0x18,0x1C,0x01,0x80,0x0E,0x30,0x00,0x00,0x40,0x00,0x00, 0x00,0x00,0x01,0x87,0x06,0x0C,0x18,0x01,0x00,0x06,0x30,0x00,0x00,0x40,0x00,0x00, 0x00,0x00,0x0F,0x87,0x07,0x0F,0x10,0x03,0x00,0x0C,0x30,0x00,0x00,0xC0,0x00,0x00, 0x00,0x00,0x0C,0x06,0x00,0x01,0x90,0x43,0x00,0x0C,0x1F,0xFF,0x01,0x80,0x00,0x00, 0x00,0x00,0x0C,0x06,0x00,0x01,0x98,0xC3,0x08,0x38,0x00,0x3E,0x03,0x00,0x00,0x00, 0x00,0x00,0x0C,0x0C,0x00,0x01,0x8F,0xC3,0x1C,0x38,0x00,0x3C,0x06,0x00,0x00,0x00, 0x00,0x00,0x0C,0x0C,0x00,0x03,0x1F,0xC7,0xFC,0x7C,0x7F,0xF6,0x0F,0xE0,0x00,0x00, 0x00,0x00,0x0F,0x88,0x1E,0x1F,0x1C,0x7F,0x67,0xDC,0xC0,0x03,0x18,0x30,0x00,0x00, 0x00,0x00,0x01,0x8C,0x00,0x03,0x18,0x01,0x80,0x0C,0xC0,0x01,0xF0,0x30,0x00,0x00, 0x00,0x00,0x03,0x87,0x80,0x03,0x10,0x00,0x80,0x0C,0xC0,0x00,0x00,0x30,0x00,0x00, 0x00,0x00,0x0E,0x01,0x80,0x03,0x10,0x00,0x9F,0x0C,0xC0,0x00,0x00,0x30,0x00,0x00, 0x00,0x00,0x0C,0x01,0x80,0x03,0x18,0x0F,0x80,0x0C,0xC0,0x00,0x00,0x30,0x00,0x00, 0x00,0x00,0x0C,0x01,0x9E,0x1F,0x0E,0x1B,0x80,0x0C,0xC0,0x00,0x00,0x30,0x00,0x00, 0x00,0x00,0x0C,0x03,0x00,0x03,0x0E,0x31,0x00,0x0C,0x7F,0xF0,0x7F,0xE0,0x00,0x00, 0x00,0x00,0x0C,0x06,0x00,0x03,0x1C,0x30,0x9F,0x0C,0x00,0x30,0x60,0x00,0x00,0x00, 0x00,0x00,0x07,0x86,0x00,0x03,0x38,0x30,0xC0,0x0C,0x00,0x30,0x60,0x00,0x00,0x00, 0x00,0x00,0x01,0x86,0x1E,0x1F,0x30,0x18,0xC0,0x0C,0x01,0xF0,0x60,0x00,0x00,0x00, 0x00,0x00,0x07,0x86,0x00,0x01,0xB0,0x0F,0x80,0x0C,0x03,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x0C,0x06,0x00,0x01,0x98,0x07,0x1F,0x0C,0x03,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x0C,0x06,0x00,0x01,0x8C,0x06,0x00,0x0C,0x03,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x0C,0x06,0x00,0x03,0x07,0x06,0x00,0x0C,0x03,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x0C,0x06,0x0F,0xFF,0x03,0x06,0x00,0x0C,0x03,0x00,0x60,0x00,0x00,0x00, 0x00,0x00,0x0C,0x0F,0x18,0x00,0x03,0x07,0x00,0x18,0x03,0x00,0xC0,0x00,0x00,0x00, 0x00,0x00,0x07,0xF9,0xF0,0x00,0x01,0xFD,0xFF,0xF0,0x01,0xFF,0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,0xFE,0x18,0x7F,0x3F,0xC0,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x8D,0xB6,0x18,0x31,0xB6,0xC0,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x8C,0x30,0x1C,0x31,0x86,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x30,0x3C,0x31,0x86,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,0x3C,0x3F,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x30,0x36,0x36,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x30,0x3E,0x36,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x30,0x66,0x33,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x8C,0x30,0x63,0x33,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x8C,0x30,0x63,0x31,0x86,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x78,0xF7,0xF9,0xCF,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; /********************************************* 遊戲關卡 一共9關 數字符號表示:人物1 磚頭2 箱子3 目的4 成功5 **********************************************/ uchar code level[][8][8]={ /*第1關*/ 0,0,2,2,2,2,2,0, 2,2,2,0,0,0,2,0, 2,0,3,0,2,0,2,2, 2,0,2,0,0,4,0,2, 2,0,0,0,0,2,0,2, 2,2,0,2,0,0,0,2, 0,2,1,0,0,2,2,2, 0,2,2,2,2,2,0,0, /*第2關*/ 2,2,2,2,2,2,2,2, 2,0,0,0,0,0,1,2, 2,0,0,0,5,0,0,2, 2,0,0,2,2,2,2,2, 2,2,0,0,2,0,0,0, 2,0,3,0,2,0,0,0, 2,0,0,4,2,0,0,0, 2,2,2,2,2,0,0,0, /*第3關*/ 0,0,2,2,2,2,0,0, 0,0,2,4,4,2,0,0, 0,2,2,0,4,2,2,0, 0,2,0,0,3,4,2,0, 2,2,0,3,0,0,2,2, 2,0,0,2,3,3,0,2, 2,0,0,1,0,0,0,2, 2,2,2,2,2,2,2,2, /*第4關*/ 0,0,0,2,2,2,2,0, 0,2,2,2,0,1,2,0, 0,2,0,0,3,0,2,0, 2,2,0,2,0,2,2,2, 2,0,0,2,0,2,4,2, 2,0,2,0,0,3,4,2, 2,0,0,0,0,0,0,2, 2,2,2,2,2,2,2,2, /*第5關*/ 0,0,0,2,2,2,2,0, 0,2,2,2,0,1,2,0, 0,2,0,0,3,0,2,0, 2,2,0,2,0,2,2,2, 2,0,0,2,0,2,4,2, 2,0,2,0,0,0,0,2, 2,0,0,0,0,0,0,2, 2,2,2,2,2,2,2,2, /*第6關*/ 0,0,0,2,2,2,2,0, 0,2,2,2,0,1,2,0, 0,2,0,0,3,0,2,0, 2,2,0,2,0,2,2,2, 2,0,0,2,0,2,4,2, 2,0,2,0,0,3,4,2, 2,0,3,0,0,0,4,2, 2,2,2,2,2,2,2,2, /*第7關*/ 0,0,2,2,2,2,2,0, 2,2,2,0,0,0,2,0, 2,0,3,0,2,0,2,2, 2,0,2,0,0,4,0,2, 2,0,0,0,0,2,0,2, 2,2,3,2,4,0,0,2, 0,2,1,0,0,2,2,2, 0,2,2,2,2,2,0,0, /*第8關*/ 0,2,2,2,2,0,0,0, 2,2,0,0,2,0,0,0, 2,1,3,0,2,0,0,0, 2,2,3,0,2,2,0,0, 2,2,0,3,0,2,0,0, 2,4,3,0,0,2,0,0, 2,4,4,5,4,2,0,0, 2,2,2,2,2,2,0,0, /*第9關*/ 0,0,0,2,2,2,2,0, 0,2,2,2,0,0,2,0, 2,2,0,1,3,0,2,0, 2,0,4,3,0,0,2,0, 2,0,4,5,0,2,2,0, 2,0,4,3,0,2,0,0, 2,2,0,0,2,2,0,0, 0,2,2,2,2,0,0,0, }; uchar level_temp[8][8]= //記錄當前的遊戲介面的變化 { 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, }; uchar code elements[][8]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //0空白 0x3C,0x7E,0x66,0x3C,0x7E,0x99,0x3C,0x66, //1人物 0x7F,0x7F,0x7F,0x00,0xEF,0xEF,0xEF,0x00, //2磚頭 0xFF,0xC3,0xA5,0x99,0x99,0xA5,0xC3,0xFF, //3箱子 0x00,0x18,0x24,0x4A,0x52,0x24,0x18,0x00, //4目標 0xFF,0xBD,0xDB,0xE7,0xE7,0xDB,0xBD,0xFF, //5箱子到達目標 }; unsigned char code Di[]= //"第"字 //第 { 0x20,0x40,0x3F,0x7E,0x48,0x90,0x85,0x08,0x3F,0xF8,0x01,0x08,0x01,0x08,0x3F,0xF8, 0x21,0x00,0x21,0x00,0x3F,0xFC,0x03,0x04,0x05,0x04,0x19,0x28,0xE1,0x10,0x01,0x00, }; unsigned char code Guan[]= //“關”字 //關 { 0x10,0x10,0x08,0x10,0x08,0x20,0x00,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00, 0xFF,0xFE,0x01,0x00,0x02,0x80,0x02,0x80,0x04,0x40,0x08,0x20,0x30,0x18,0xC0,0x06, }; unsigned char code Yong[]= //“用”字 //用 { 0x00,0x00,0x3F,0xF8,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,0x21,0x08,0x21,0x08, 0x21,0x08,0x3F,0xF8,0x21,0x08,0x21,0x08,0x21,0x08,0x41,0x08,0x41,0x28,0x80,0x10, }; unsigned char code Shi[]= //“時”字 //時 { 0x00,0x08,0x00,0x08,0x7C,0x08,0x44,0x08,0x45,0xFE,0x44,0x08,0x44,0x08,0x7C,0x08, 0x44,0x88,0x44,0x48,0x44,0x48,0x44,0x08,0x7C,0x08,0x44,0x08,0x00,0x28,0x00,0x10, }; unsigned char code Miao[]= //“秒”字 //秒 { 0x08,0x20,0x1C,0x20,0xF0,0x20,0x10,0xA8,0x10,0xA4,0xFC,0xA2,0x11,0x22,0x31,0x20, 0x3A,0x24,0x54,0x24,0x54,0x28,0x90,0x08,0x10,0x10,0x10,0x20,0x10,0xC0,0x00,0x00, }; main.c #include<reg51.h> #include"Variable.h" /************************************************** 函式名:status_bit_01() 功能:狀態位sta1(讀/寫指令),sta0(讀/寫資料)判斷 入口引數: 返回值:狀態值i ***************************************************/ uchar status_bit_01() { uchar i; P0=0xff; cd=1; rd=0; for(i=10;i>0;i--) { if((P1&0x03)==0x03) break; } rd=1; return i; } /********************************************* 函式名:write_data(uchar dat) 功能:寫資料 入口引數:8位資料dat 返回值: *********************************************/ void write_data(uchar dat) { while(status_bit_01()==0); rd=1;cd=0;wr=0; P0=dat; wr=1;cd=1; //一定要有這一句,補完後面的時序! } /********************************************* 函式名:write_cmd1(uchar cmd) 功能:寫命令,無引數 入口引數:8位命令cmd 返回值: *********************************************/ void write_cmd1(uchar cmd) { while(status_bit_01()==0); rd=1;cd=1;wr=0; P0=cmd; wr=1;cd=0; //一定要有這一句,補完後面的時序! } /************************************************ 函式名:write_cmd3(uchar cmd) 功能:寫雙引數命令 入口引數:8位資料data1,8位資料data2,8位命令cmd 返回值: *************************************************/ void write_cmd3(uchar data1,uchar data2,uchar cmd) { write_data(data1); write_data(data2); write_cmd1(cmd); } /************************************************ 函式名:setc_xy() 功能:定位 入口引數:列字元地址x,行位地址y 返回值: *************************************************/ void setc_xy(uchar x, uchar y) { int temp; temp = y * 0x10 + x; write_cmd3(temp&0xff,temp/0xff,add_pos); } /********************************************* 函式名:write_cmd2(uchar cmd) 功能:寫單引數命令 入口引數:8位資料dat,8位命令cmd 返回值: *********************************************/ void write_cmd2(uchar dat,uchar cmd) { write_data(dat); write_cmd1(cmd); } /********************************* 功能:分解計時值的各位,並顯示在響應的位置上 函式名: time_change(unsigned int ttime) 入口引數:計時值 返回值: ***********************************/ void time_change(uint ttime) { uchar a1,a2,a3,a4,a5; uchar i,j; a1=ttime/10000; a2=ttime/1000%10; a3=ttime/100%10; a4=ttime/10%10; a5=ttime%10; for(j=0;j<16;j++) //a1 { for(i=0;i<1;i++) { setc_xy(9+i,32+j); write_cmd2(Number[a1][j],inc_wr); } } for(j=0;j<16;j++) //a2 { for(i=0;i<1;i++) { setc_xy(10+i,32+j); write_cmd2(Number[a2][j],inc_wr); } } for(j=0;j<16;j++) //a3 { for(i=0;i<1;i++) { setc_xy(11+i,32+j); write_cmd2(Number[a3][j],inc_wr); } } for(j=0;j<16;j++) //a4 { for(i=0;i<1;i++) { setc_xy(12+i,32+j); write_cmd2(Number[a4][j],inc_wr); } } for(j=0;j<16;j++) //a5 { for(i=0;i<1;i++) { setc_xy(13+i,32+j); write_cmd2(Number[a5][j],inc_wr); } } } /********************************* 功能:初始化51 函式名: int51_timec() 入口引數: 返回值: ***********************************/ void int51_timec() { EA=1; TMOD=0x11; ET0=1; TR0=0; TH0=(65536-50000)/256; TL0=(65536-50000)%256; } /********************************* 功能:定時器0中斷 函式名: t0_tt() 入口引數: 返回值: ***********************************/ void t0_tt() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; tcount++; if(tcount==20) { tcount=0; Timtcount++; time_change(Timtcount); } } /************************************************ 函式名:init_12864() 功能:初始化lcd12864 入口引數: 返回值: *************************************************/ void init_12864() { wr=1;rd=1;cd=1;rst=1;//初始化 write_cmd3(0x01,0x00,0x21);//游標指標設定 write_cmd3(0x00,0x00,0x42);//圖形區首地址 write_cmd3(16,0x00,0x43);//圖形區寬度 write_cmd1(0x88);//顯示方式設定,正常顯示 write_cmd1(0x98);//圖形方式顯示,不顯示字母,只打點 write_cmd1(0xa0);//游標形狀設定1 0 1 0 0 N2 N1 N0 } /************************************************ 函式名:start_ui() 功能:開機畫面 入口引數: 返回值: *************************************************/ void start_ui() { uint i; setc_xy(0,0); for(i=0;i<1024;i++) { write_cmd2(start_box[i],inc_wr); } } /******************************** 函式名:delayms(x) 功能:按鍵掃描延時 入口引數:x=延遲時間 返回值: *********************************/ void delayms(uint x) { uchar i; while(x--); for(i=0;i<100;i++); } /******************************** 函式名:keys_scan() 功能:按鍵掃描 入口引數: 返回值:按鍵號keyno *********************************/ uchar keys_scan() { uchar tmp; //高4位置1,放入4行 uchar keyno=16; if(P1 != 0x0f) { P1 = 0x0f; delayms(1); //按鍵後00001111將程式設計0000××××,×中有一個為0.其餘為1 //下面的異或操作會把3個1變成0,唯一的0變成1 tmp = P1 ^ 0x0f; //判斷按鍵發生於0-3列中哪一列 switch(tmp) { case 1: keyno = 0;break; case 2: keyno = 1;break; case 4: keyno = 2;break; case 8: keyno = 3;break; default:keyno = 16;//無鍵按下 } //低4位置0,放入4列 P1 = 0xf0; delayms(1); //按鍵後11110000將變成××××0000,×中有1個為0,3個仍為1 tmp = (P1 >> 4)^ 0x0f; //對0-3行分別附加起始值0,4,8,12 switch(tmp) { case 1:keyno += 0;break; case 2:keyno += 4;break; case 4:keyno += 8;break; case 8:keyno += 12;break; } P1=0x0f; return keyno; } return keyno; } /************************************************ 函式名:clc() 功能:清屏 入口引數: 返回值: *************************************************/ void clc() { int i; write_cmd3(0,0,add_pos); for(i = 0; i < 1024; i++) write_cmd2(0x00,inc_wr); } /************************************************ 函式名:printelement() 功能:指定字元位置,顯示元素 入口引數:列字元地址xh,行字元地址yh,元素程式碼elnum 返回值: *************************************************/ void printelement(uchar xh, uchar yh,uchar elnum) { uchar i; int temp; for(i=0;i<8;i++) //行地址加+1 { temp = yh* 0x80+i*0x10 + xh; write_cmd3(temp&0xff,temp/0xff,add_pos); write_cmd2(elements[elnum][i],noc_wr); } } void display_time() { unsigned i,j; for(j=0;j<16;j++)//顯示“第”字 { for(i=0;i<2;i++) { setc_xy(9+i,j); write_cmd2(Di[j*2+i],inc_wr);//陣列的地址不要亂! } } for(j=0;j<16;j++)//關數 { for(i=0;i<1;i++) { setc_xy(11+i,j); write_cmd2(Number[levelg+1][j],inc_wr); //陣列的地址不要亂! } } for(j=0;j<16;j++) { for(i=0;i<2;i++) { setc_xy(12+i,j); write_cmd2(Guan[j*2+i],inc_wr);//“關”字 } } for(j=0;j<16;j++) { for(i=0;i<2;i++) //列式按字元定址的,行是按位定址的 { setc_xy(9+i,16+j); write_cmd2(Yong[j*2+i],inc_wr); //“用”字 } } for(j=0;j<16;j++) { for(i=0;i<2;i++) { setc_xy(12+i,16+j); write_cmd2(Shi[j*2+i],inc_wr); //“時”字 } } for(j=0;j<16;j++) { for(i=0;i<2;i++) { setc_xy(14+i,32+j); write_cmd2(Miao[j*2+i],inc_wr); //“秒”字 } } } /************************************************ 函式名:gamebg() 功能:顯示遊戲本關卡遊戲介面 入口引數:關卡代號g 返回值: *************************************************/ void gamebg(uchar g) { unsigned i,j; for(i=0;i<8;i++) //行 { for(j=0;j<8;j++) //列 { if(level[g][i][j]==1) { man_x=j; man_y=i; } level_temp[i][j]=level[g][i][j]; //當前關卡存入遊戲緩衝 printelement(j,i,level_temp[i][j]); //顯示當前關卡 } } display_time(); time_change(Timtcount); } /************************************************ 函式名:level_suc() 功能:判斷是否通過本關卡 入口引數: 返回值: *************************************************/ void level_suc() { uchar i,j,k=1; for(i = 0; i < 8; i++) //行 { if(k==0) break; for(j = 0; j < 8; j++) //列 { if(level[levelg][i][j]==4||level[levelg][i][j]==5) //迴圈掃描目標位置都有箱子在,此關卡就通過 { if(level_temp[i][j]==5) k=1; //此位置箱子在目標位置上 else { k=0; //有目標位置沒有箱子 break; } } } } if(k==1) //所有目標位置都有箱子 { if(levelg<8) levelg+=1; else levelg=0; //通關後重新從第一關開始 Timtcount=0; //計時清零 TH0=(65536-50000)/256; TL0=(65536-50000)%256; tcount=0; gamebg(levelg); } } /************************************************ 函式名:key_up() 功能:按向上鍵的操作 入口引數: 返回值: 註釋含義: ?=:是否等與 上:本位置的上一個位置 目: 箱子的目標位置 成:箱子在目標位置上 源:位置最開始的元素 本:本位置 空:空白位置 再上:本位置的再上一個位置 箱:箱子 *************************************************/ void key_up() { if(level_temp[man_y-1][man_x]==0||level_temp[man_y-1][man_x]==4) //上?=目/成 { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) //本,源?=目/成 { level_temp[man_y][man_x]=4; //本=目 printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; //本=空 printelement(man_x,man_y,0); } man_y=man_y-1; //上=人//完成一次移動 level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); } else if(level_temp[man_y-1][man_x]==3) //上?=箱 { if(level_temp[man_y-2][man_x]==0) //再上?=空白 { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) //本,源?=目/成 { level_temp[man_y][man_x]=4; //本=目 printelement(man_x,man_y,4); } else //本=空 { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y-1; //上=人 level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y-1][man_x]=3; //再上=箱//完成一次移動 printelement(man_x,man_y-1,3); } else if(level_temp[man_y-2][man_x]==4) //再上?=目 { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) //本,源?=目/成 { level_temp[man_y][man_x]=4; //本=目 printelement(man_x,man_y,4); } else //本=空 { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y-1; level_temp[man_y][man_x]=1; //上=人 printelement(man_x,man_y,1); level_temp[man_y-1][man_x]=5; //再上=成 printelement(man_x,man_y-1,5); } } else if(level_temp[man_y-1][man_x]==5) //上?=成 { if(level_temp[man_y-2][man_x]==0) //再上?=空 { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) //本,源?=目/成 { level_temp[man_y][man_x]=4; //本=目 printelement(man_x,man_y,4); } else { //本=空 level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y-1; //上=人 level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y-1][man_x]=3; //再上=箱 printelement(man_x,man_y-1,3); } else if(level_temp[man_y-2][man_x]==4) //再上?=目 { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) //本,源?=目/成 { level_temp[man_y][man_x]=4; //本=目 printelement(man_x,man_y,4); } else //本=空 { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y-1; //上=人 level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y-1][man_x]=5; //再上=成 printelement(man_x,man_y-1,5); } } level_suc(); //判斷是否完成本關 } /************************************************ 函式名:key_down() 功能:按向下鍵的操作 入口引數: 返回值: *************************************************/ void key_down() { if(level_temp[man_y+1][man_x]==0||level_temp[man_y+1][man_x]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); } else if(level_temp[man_y+1][man_x]==3) { if(level_temp[man_y+2][man_x]==0) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y+1][man_x]=3; printelement(man_x,man_y+1,3); } else if(level_temp[man_y+2][man_x]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y+1][man_x]=5; printelement(man_x,man_y+1,5); } } else if(level_temp[man_y+1][man_x]==5) { if(level_temp[man_y+2][man_x]==0) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y+1][man_x]=3; printelement(man_x,man_y+1,3); } else if(level_temp[man_y+2][man_x]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_y=man_y+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y+1][man_x]=5; printelement(man_x,man_y+1,5); } } level_suc(); } /************************************************ 函式名:key_left() 功能:按向左鍵的操作 入口引數: 返回值: *************************************************/ void key_left() { if(level_temp[man_y][man_x-1]==0||level_temp[man_y][man_x-1]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x-1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); } else if(level_temp[man_y][man_x-1]==3) { if(level_temp[man_y][man_x-2]==0) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x-1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x-1]=3; printelement(man_x-1,man_y,3); } else if(level_temp[man_y][man_x-2]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x-1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x-1]=5; printelement(man_x-1,man_y,5); } } else if(level_temp[man_y][man_x-1]==5) { if(level_temp[man_y][man_x-2]==0) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x-1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x-1]=3; printelement(man_x-1,man_y,3); } else if(level_temp[man_y][man_x-2]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x-1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x-1]=5; printelement(man_x-1,man_y,5); } } level_suc(); } /************************************************ 函式名:key_right() 功能:按向右鍵的操作 入口引數: 返回值: *************************************************/ void key_right() { if(level_temp[man_y][man_x+1]==0||level_temp[man_y][man_x+1]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); } else if(level_temp[man_y][man_x+1]==3) { if(level_temp[man_y][man_x+2]==0) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x+1]=3; printelement(man_x+1,man_y,3); } else if(level_temp[man_y][man_x+2]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x+1]=5; printelement(man_x+1,man_y,5); } } else if(level_temp[man_y][man_x+1]==5) { if(level_temp[man_y][man_x+2]==0) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x+1]=3; printelement(man_x+1,man_y,3); } else if(level_temp[man_y][man_x+2]==4) { if(level[levelg][man_y][man_x]==4||level[levelg][man_y][man_x]==5) { level_temp[man_y][man_x]=4; printelement(man_x,man_y,4); } else { level_temp[man_y][man_x]=0; printelement(man_x,man_y,0); } man_x=man_x+1; level_temp[man_y][man_x]=1; printelement(man_x,man_y,1); level_temp[man_y][man_x+1]=5; printelement(man_x+1,man_y,5); } } level_suc(); } /************************************************ 函式名:void put_box() 功能:推箱子游戲規則 入口引數: 返回值: *************************************************/ void put_box() { uint keyupdate; keyupdate=16; if(P1!=0x0f)//若沒有這句,有可能在按鍵掃描後執行while(P1!=0x0f),就得不到按鍵值,使按鍵失效 { keyupdate=keys_scan(); while(P1!=0x0f); } switch(keyupdate) { case 0: key_up();break; case 1:key_down();break; case 2:key_left();break; case 3:key_right();break; case 4: playing=0; startflag=1; Timtcount=0; TR0=0; clc(); start_ui(); break; //退出遊戲 case 5: if(levelg!=8) levelg++; gamebg(levelg); //顯示第一關 Timtcount=0; TH0=(65536-50000)/256; TL0=(65536-50000)%256; tcount=0; break; //下一關 case 6: if(levelg!=0) levelg--; gamebg(levelg); //顯示第一關 Timtcount=0; TH0=(65536-50000)/256; TL0=(65536-50000)%256; tcount=0; break; //上一關 } } void main() { uchar kupdate; uchar startflag; int51_timec(); //初始化51 init_12864(); //初始化12864 startflag=1; playing=0; start_ui(); while(1) { while(startflag) //等待確定鍵按下 { kupdate=16; if(P1!=0x0f) //若沒有這句,有可能在按鍵掃描後執行while(P1!=0x0f),就得不到按鍵值,使按鍵失效 { kupdate=keys_scan(); while(P1!=0x0f); } switch(kupdate) { case 4: startflag=0; playing=1; break; } } clc();//清屏 levelg=0; gamebg(levelg); //顯示第一關 Timtcount=0; TR0=1; while(playing) //遊戲中... { put_box(); } startflag=1; } }