good,給大家省點黑幣 樓主的源碼如下:
- /*********************************************************************************************************
- ** 俄羅斯方塊
- ** 基于8位51系列MCU(SST89E516)
- **
- ** All Rights Reserved
- **
- ** V0.00
- **
- **
- **--------------文件信息--------------------------------------------------------------------------------
- **文 件 名: ELS.c
- **最后修改日期: 2009年5月20日
- **描 述: 基于51單片機的俄羅斯方塊游戲 顯示屏幕為16*16 雙色高亮點陣模塊
- **
- **--------------歷史版本信息----------------------------------------------------------------------------
- ** 修改人: 趙同陽
- ** 版 本: V0.00
- ** 日 期:
- ** 描 述: 原始版本
- **------------------------------------------------------------------------------------------------------
- **--------------當前版本修訂------------------------------------------------------------------------------
- ** 修改人:
- ** 日 期:
- ** 描 述:
- **
- **------------------------------------------------------------------------------------------------------
- ********************************************************************************************************/
- #include"reg52.h" //包含51 特殊功能寄存器資源變量聲明文件
- #include <intrins.h> //KEILC51 自帶的左右移庫函數
- #include <stdlib.h> //包含 KEILC51 的隨機數產生函數
- #include"font.h"
- #define uchar unsigned char // 將常用的數據類型 縮寫
- #define uint unsigned int // 將常用的數據類型 縮寫
- #define H_H P2 // 定義顯示屏的高8行選擇位
- #define H_L P0 // 定義顯示屏的低8行選擇位
- sbit SUOCUN = P3^3; // 定義移位寄存器74HC595的鎖存端口
- sbit CLOCK = P3^2; // 定義移位寄存器74HC595的時鐘端口
- sbit DI = P3^5; // 定義移位寄存器74HC595的數據端口
- sbit OE = P3^4; // 定義移位寄存器74HC595的使能端口
- uchar idata disp_buff[32]; // 定義顯示直接送往74HC595 的顯示緩存
- uchar idata disp_buff1[32]; // 定義顯示直接送往74HC595 的顯示緩存備份 因為處理顯示緩存在中斷中完成,而緩存中數據的處理
- // 在前臺,這樣顯示會有點錯亂,所以做了備份.這樣在加工顯存中數據的時候,送備份中的數據到顯示屏
- uchar rec_line[16]; // 記錄堆滿一行的行編號數組
- uchar cur_mod=0; // 當前形狀編號
- uchar color=0;
- uchar cur_mod_sty=0; // 當前形狀變化的四種狀態編號
- uchar time_down=0; // 設置自動下降標志,由定時器觸發
- uint time_count=0; // 記錄中斷次數,為了得到更長的定時時間
- uchar need_redraw_temp=0; // 是否需要刷新顯存中的數據,太頻繁刷新會降低系統性能,如在程序中需刷新,請置此標志
- uchar need_save2_loc=0; // 當前方塊因為無法下降,而停下來.這時候需將 "顯示陣列"數字的數據dis_pos[20][16] 保存 (顯示窗內所有方塊的位置)到"記錄數組陣列"LOC_pos[20][16]
- uchar done_line_num=0; // 記錄本次方塊下降結束,成就多少行滿
- char els_cur_x=1; // 記錄當前方塊的X位置
- char els_cur_y=3; // 記錄當前方塊的Y位置
- uchar cur_key=0; // 記錄本次按鍵掃描得到的按鍵號
- uchar old_key=0; // 記錄上次按鍵掃描得到的按鍵號
- uchar key_time=0; // 記錄按鍵按下去多長時間
- uchar char_move_time=0; //
- #define game 1
- #define logo 2
- uchar sys_st =logo;
- #define max_long_pre 50 // 定義按鍵按下去多少個循環監測周期才算"常按",根據實際測量一次按鍵掃描15MS執行一次,那這里就50*15MS 執行第二
- // 功能比如 下降按鍵 短按為下降一格 如果常按 就觸發迅速下降功能
- uchar data temp_els[16]= // 方塊的固定形狀是保存到ROM區域的(els_sty[6][4][4][4]),但是為了加工的方便,將固定ROM 內的基本形狀取出放到本數組
- {
- 0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,
- };
- uchar data temp_test[16]= //在當前形狀變形(旋轉)前要先判斷當前方塊如果變成下一個形狀能否造成碰觸
- {
- 0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,
- };
- uchar xdata font_1[32]=
- {0x00,0x01};
- uchar xdata font_2[32]=
- {0x00,0x01};
- uchar code temp_els_empty[16]= //定義個4*4 的空方塊,主要是為了清除上次方塊動作留下的痕跡
- {
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,
- };
- uchar data_led[4]={0xff,0xff,0xff,0xff}; //顯示在定時器中斷中調用,每次只顯示一行,一行中是16位(2個字節)本屏幕時雙色所以定義四個字節
- uchar xdata loc_pos[20][16]= //定義記錄每個已經固定點的位置 為了簡化計算,每個點用一個字節代替,可以減少運算時間和復雜性
- {
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- };
- uchar xdata dis_pos[20][16]=
- //顯示屏幕要刷新的數據 所對應的陣列,為了簡化計算,每個點用一個字節代替,可以減少運算時間和復雜性
- //但是送到屏幕上的數據是由這些數據轉過來的,最終轉成每個點對應一位.由數組disp_buff[32]接收
- {
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- };
- uchar code dis_ini[20][16]= //初始化固定點的記錄情況,每次游戲開始前調用
- {
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- };
- //種 形 行 列
- //類 狀 號 號
- uchar code els_sty[6][4][4][4]= //定義游戲中用到的方塊形狀種類 本種類的四種角度 每種方塊由4*4點組成
- { //可以輕易加新形狀,如果自己加新的形狀,要靠X軸和Y軸!!
- {
- {
- {0xff,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0xff,0xff},
- },
- {
- {0xff,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
-
- {0xff,0x00,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0xff,0xff},
- },
- },
- //////////////////////////////////////////////////////////以上為形狀1所對應的四種狀態///////////////////////////////////////
- {
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0xff,0x00,0x00},
- {0x00,0xff,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- {0xff,0x00,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- {0x00,0xff,0x00,0x00},
- {0x00,0xff,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0xff,0x00},
- {0xff,0xff,0xff,0x00},
- {0x00,0x00,0xff,0x00},
- },
- },
- //////////////////////////////////////////////////////////以上為形狀2所對應的四種狀態///////////////////////////////////////
- {
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- },
- },
- //////////////////////////////////////////////////////////以上為形狀3所對應的四種狀態///////////////////////////////////////
- {
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0x00,0xff,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- {0x00,0xff,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- {0x00,0xff,0x00,0x00},
- },
- },
- //////////////////////////////////////////////////////////以上為形狀4所對應的四種狀態///////////////////////////////////////
- {
- {
- {0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- {0x00,0x00,0xff,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0xff,0xff,0x00},
- {0x00,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00},
- {0xff,0xff,0xff,0x00},
- {0x00,0x00,0xff,0x00},
- },
- {
- {0x00,0x00,0x00,0x00},
- {0x00,0xff,0xff,0x00},
- {0x00,0xff,0x00,0x00},
- {0xff,0xff,0x00,0x00},
- },
- },
- //////////////////////////////////////////////////////////以上為形狀5所對應的四種狀態///////////////////////////////////////
- };
- //自己做的漢子庫
- uchar code zhi[] = // 數據表
- {
- 0x01,0x00,0x01,0x00,0x01,0x04,0xFF,0xFE,
- 0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xFC,
- 0x00,0x00,0x02,0x00,0x11,0x80,0x50,0x84,
- 0x50,0x12,0x90,0x12,0x0F,0xF0,0x00,0x00,
- };
- uchar code bo[] = // 數據表
- {
- 0x10,0x50,0x10,0x48,0x17,0xFC,0x10,0x40,
- 0xFB,0xF8,0x12,0x48,0x13,0xF8,0x1A,0x48,
- 0x33,0xF8,0xD2,0x48,0x10,0x10,0x1F,0xFE,
- 0x12,0x10,0x11,0x10,0x51,0x50,0x20,0x20,
- };
- uchar code dian[] = // 數據表
- {
- 0x1F,0xF0,0x41,0x04,0x7F,0xFE,0x81,0x02,
- 0x3D,0x74,0x01,0x00,0x3D,0x70,0x01,0x00,
- 0x3F,0xF8,0x21,0x08,0x3F,0xF8,0x21,0x08,
- 0x3F,0xF8,0x01,0x02,0x01,0x02,0x01,0xFE,
- };
- uchar code zi[] = // 數據表
- {
- 0x00,0x10,0x3F,0xF8,0x00,0x10,0x00,0x20,
- 0x00,0x40,0x01,0x80,0x01,0x04,0xFF,0xFE,
- 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00
- };
- void font_round()
- {
- uchar a=0,b=0;
- for(a=0;a<16;a++)
- {
- font_1[a*2]<<=1;
- if(font_1[a*2+1]&0x80)
- font_1[a*2]+=1;
- font_1[a*2+1]<<=1;
- if(font_2[a*2]&0x80)
- font_1[a*2+1]+=1;
- font_2[a*2]<<=1;
- if(font_2[a*2+1]&0x80)
- font_2[a*2]+=1;
-
- font_2[a*2+1]<<=1;
- }
- for(a=0;a<32;a++)
- {
- disp_buff[a]=font_1[a];
- }
- }
- void send_595(uchar dat) //向595發一個字節數據
- {
- uchar a=0;
- for(a=0;a<8;a++) //將一個字節數據分8次依次移入595
- {
- CLOCK=0;
- if(dat&0x01)
- DI=1;
- else
- DI=0;
- dat=dat>>1;
- CLOCK=1;
- }
- }
- void ini_int(void) //初始化中斷和定時系統,本程序只用到了定時器1
- {
- // D7 D6 D5 D4 D3 D2 D1 D0
- TMOD=0X11;//GATA C/T M1 M0 ------- GATA C/T M1 M0 定時器工作模式設置為 GATA=0關閉門控使能 C/T=0 M1=0 M0=1,選擇時鐘源來自外部晶體12分頻.
- ET0=0; //打開外部中斷0的使能開關
- ET1=1; //打開外部中斷1的使能開關
- PT0=0; //設置外部中斷0的中斷優先等級為0
- PT1=0; //設置外部中斷1的中斷優先等級為0
- TH0=63; //設置定時器0的高8位初始化值
- TL0=0xcd; //設置定時器0的低8位初始化值 精確10毫秒溢出
- TH1=0XE0; //設置定時器1的高8位初始化值
- TL1=0X00; //設置定時器1的低8位初始化值 大約3MS 左右溢出
- TR0=0; //讓定時器0開始工作
- TR1=1; //讓定時器1開始工作
- EA =1; //打開中斷允許總開關
- }
- void send_data_led(uchar *p) //將一行的數據送出到595 包括綠色和紅色
- {
- uchar a=0;
- send_595(*(p+3));
- send_595(*(p+2));
- send_595(*(p+1));
- send_595(*p);
- }
- uint rond_k=0x8000; //因為采用動態掃描,每次只能讓一行亮,這里控制行的是P2 口和P0 口,兩個字節.聲明個兩字節的變量,依次循環在每位上
- void dis_pos2dis_buff() //將顯示陣列的數據(每點對應一個字節對應每點對應一位)
- {
- uchar a=0;
- uchar b=0;
- uchar c=0;
- uchar *t=dis_pos;
- t+=64;
- for(c=0;c<32;c++)
- {
- for(a=0;a<8;a++)
- {
- if(*t) //將dis_pos的數據(每個點對應一字節)轉成(每點一個位)disp_buff
- disp_buff1[b]=(disp_buff1[b]<<1)+1;
- else
- disp_buff1[b]=(disp_buff1[b]<<1);
- t++;
- }
- b++;
- } //對臨時緩沖操作
- for(c=0;c<32;c++)
- {
- disp_buff[c]=disp_buff1[c] ; //將臨時緩沖加到32字節的刷新緩沖
- }
- }
- void add_els_temp2dis_pos(uchar *p,char x_start,char y_start) //將當前俄羅斯顯示到窗口的指定位置
- {
- uchar aa=0,bb=0;
- for(;(y_start>=0)&&(aa<4);aa++,y_start--)
- {
- for(bb=0;bb<4;bb++)
- {
- if(p[(3-aa)*4+bb])
- dis_pos[y_start][x_start+bb]=0xff;
- }
- }
- }
- void save_dis2loc() //將顯示陣列保存 到記錄陣列
- {
- uchar a,b;
- for(a=0;a<20;a++)
- for(b=0;b<16;b++)
- loc_pos[a][b]=dis_pos[a][b];
- }
- uchar test_down(uchar *p) //測試是否有下降的可能
- {
- uchar a=0,b=0;
- for(a=0;a<4;a++)
- for(b=0;b<4;b++)
- if(p[a*4+b])
- if(loc_pos[els_cur_y+1-(3-a)][els_cur_x+b])
- return 0xff;
- return 0;
- }
- uchar test_left(uchar *p) //測試是否有左移的可能
- {
- uchar a=0,b=0;
- for(a=0;a<4;a++)
- for(b=0;b<4;b++)
- if(p[a*4+b])
- if(loc_pos[els_cur_y-(3-a)][els_cur_x+b-1])
- return 0xff;
- return 0;
- }
- uchar test_right(uchar *p) //測試是否能右移可能
- {
- uchar a=0,b=0;
- for(a=0;a<4;a++)
- for(b=0;b<4;b++)
- if(p[a*4+b])
- if(loc_pos[els_cur_y-(3-a)][els_cur_x+b+1])
- return 0xff;
- return 0;
- }
- uchar find_line(uchar *p) //每次下降結束就監測是否湊夠一行,是否滿,以及記錄湊成了幾行,和湊滿一行的行號
- {
- uchar a=0,b=0,c=0;
- for(a=0;a<19;a++)
- {
- c=0;
- for(b=0;b<16;b++)
- if(loc_pos[a][b])
- c++;
- if(c==16)
- {
- *p=a;
- p++;
- done_line_num++;
- }
- if((a==4)&&(c>2))
- return 1;
- }
- return 0;
- }
- void copy_s_d() //將當前方塊的下個形狀4*4 裝到測試方塊存儲中,以便測試當前是否能變形
- {
- uchar a=0,b=0,c=0;
- if(cur_mod_sty<4)
- c=cur_mod_sty+1;
- else
- c=0;
- for(a=0;a<4;a++)
- for(b=0;b<4;b++)
- {
- temp_test[a*4+b]=els_sty[cur_mod][c][a][b];
- }
- }
- void copy_d_s() //將下一個方塊的形狀調出放到 當前方塊裝載
- {
- uchar a=0,b=0,c=0;
- if(cur_mod_sty<3)
- c=cur_mod_sty+1;
- else
- c=0;
- for(a=0;a<4;a++)
- for(b=0;b<4;b++)
- {
- temp_els[a*4+b]=els_sty[cur_mod][c][a][b];
- }
- }
- void copy_d_s1() //和上面一樣用途一樣,只是一個在中斷中調用,一個在后臺調用
- {
- uchar a=0,b=0,c=0;
- if(cur_mod_sty<3)
- c=cur_mod_sty+1;
- else
- c=0;
- for(a=0;a<4;a++)
- for(b=0;b<4;b++)
- {
- temp_els[a*4+b]=els_sty[cur_mod][c][a][b];
- }
- }
- unsigned char get_key()//得到當前按鍵數據在1-16之間,無按下,返回0
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned char c=0;
- unsigned char key=0;
- for(a=0;a<4;a++)
- {
- P1=~(0X80>>a);
- c=(P1&0XFF);
- if((P1&0x0f)!=0x0f)
- {
- for(b=0;b<4;b++)
- {
- P1=~(0X08>>b);
- if((P1>>4)!=0X0F)
- {
- key=a*4+b+1;
- break;
- }
- }
- }
- }
- return key;
- }
- void ex1_int(void) interrupt 3 /*外部中斷1的服務函數 即外部中斷1發生后單片機自動調轉到本函數處執行*/
- {
- static unsigned char index_disp=0; //定義一個靜態變量來記錄現在顯示哪一位
- static unsigned char move_count=0;
- static unsigned char font_count=0;
- uchar h=0,l=0;
- TH1=0xfa; //溢出后重新給定時器付初值 1MS 溢出一次
- TL1=0X00;
- ///////////////////////////////////////////////////刷新一行點陣開始/////////////////////////////////////
- if(color)
- {
- data_led[2]=~disp_buff[index_disp*2]; //將當前行的顯存送到指定區域準備一次性發送
- data_led[3]=~disp_buff[index_disp*2+1];
- data_led[0]=0xff; //紅色不顯示
- data_led[1]=0xff; //紅色不顯示
- }
- else
- {
- data_led[0]=~disp_buff[index_disp*2]; //將當前行的顯存送到指定區域準備一次性發送
- data_led[1]=~disp_buff[index_disp*2+1];
- data_led[2]=0xff; //紅色不顯示
- data_led[3]=0xff;
- }
- SUOCUN=0;
- if(index_disp<16) //一畫面分16次送完,每次中斷只送一行
- {
- OE=1;
- send_data_led(data_led);
- H_H=~(rond_k/0XFF);
- H_L=~(rond_k&0XFF);
- SUOCUN=1;
- OE=0;
- rond_k=_iror_(rond_k,1);
- index_disp++;
- }
- /////////////////////////////////////////////////刷新一行點陣結束////////////////////////////////////
- else //16次送完,第17次用來處理其他要在中斷處理的動作,比如按鍵掃描
- {
- rond_k=0x8000;
- index_disp=0; //否則掃描一次結束繼續重頭再來
- if(sys_st==logo)
- {
- if(char_move_time<20)
- char_move_time++;
- else
- {
- char_move_time=0;
- if(move_count<16)
- {
- font_round();
- move_count++;
- }
- else
- {
- move_count=0;
- for(h=0;h<32;h++)
- font_2[h]=GB_16[font_count].Msk[h];
- if(font_count<25)
- font_count++;
- else
- {
- color=!color;
- font_count=0;
- }
- font_round();
- move_count++;
- }
- }
- if(get_key())
- sys_st=game;
- }
- if(time_count<100) //自動下降時間大概1秒
- {
- time_count++;
- }
- else
- {
- if(test_down(temp_els)) //判斷是否還能下降
- {
- need_save2_loc=1; //下降不了,要保存 顯存數據到固定陣列
- }
- else
- {
- if(need_redraw_temp==0) //看現在是否后臺在刷新,不是則允許刷新
- {
- time_down=1; //時間造成的自動下降標志
- els_cur_y++; //當前方塊可以下降
- need_redraw_temp=1; //要重新刷新所有
- }
- }
- time_count=0;
- } //時間引起的下降判斷結束
- cur_key=get_key(); //掃描現在按鍵
- if(cur_key) //有按鍵按下
- {
- if(cur_key==old_key) //判段是連續按下
- {
- if(key_time<max_long_pre) //連續按下的時間小于常按時間
- {
- key_time++; //按下的時間自動加1
- }
- else
- { //常按處理
- if(cur_key==14) //下降按鍵常按,快速下降
- {
- cur_key=0;
- if(test_down(temp_els)) //每次快速下降后判斷是否降到底
- {
- need_save2_loc=1;
- }
- else
- {
- time_down=1;
- els_cur_y++;
- need_redraw_temp=1;
-
- }
- }
- }
- }
- else //否則記錄下現在的按鍵到OLD_KEY
- {
- old_key=cur_key;
- cur_key=0; //
- }
- }
- else //手松開
- { //清常按標志
- key_time=0;
- if(old_key) //假如按鍵不是0,執行記錄下的按鍵功能 HAVE BUG
- {
- switch (old_key)
- { //變形處理
- case 10:
- copy_s_d(); //將下個形狀裝到temp_test中,
-
- if((!test_left(temp_test))&&(!test_right(temp_test))) //測試是否能變形
- {
- if(cur_mod_sty<3) //變形為下個狀態
- cur_mod_sty++;
- else
- cur_mod_sty=0;
- copy_d_s(); //能變形,則調下個方塊到現在的方塊中
- need_redraw_temp=1; //設需要重新刷新標志
- }
- break;
- case 13:
- if(!test_left(temp_els)) //左鍵被按下
- {
- els_cur_x--;
- need_redraw_temp=1;
- }
- break;
- case 14: //下降按鍵被按下,并松開后執行 下降一格命令
- if(!time_down)
- {
- if(test_down(temp_els))
- {
- need_save2_loc=1;
- }
- else
- {
- if(need_redraw_temp==0)
- {
- els_cur_y++;
- need_redraw_temp=1;
- }
- }
- }
- else
- time_down=0;
- need_redraw_temp=1;
- break;
- case 15:
- if(!test_right(temp_els))
- {
- els_cur_x++;
- need_redraw_temp=1;
- }
- break;
- };
- }
- key_time=0;
- old_key=0;
- }
- }
-
- }
- void ini_gui() //重新初始化游戲界面
- {
- uchar a=0,b=0;
- for(a=0;a<20;a++)
- for(b=0;b<16;b++)
- loc_pos[a][b]=dis_ini[a][b];
- }
- main()
- {
- uint a=0;
- uchar h=0,l=0;
- uint i;
-
- uchar s_h=0,s_l=0;
- uchar d_h=0,d_l=0;
- i = (TH1<<8)|TL1;
- srand(i); //利用隨機函數得到下一個方快形狀
-
- ini_gui(); //初始化游戲界面
- for(h=0;h<4;h++)
- for(l=0;l<4;l++)
- temp_els[h*4+l]=els_sty[cur_mod][cur_mod_sty][h][l]; //換新的形狀到臨時方塊區域
- ini_int();
- while(1)
- {
- switch(sys_st)
- {
- case game:
- if(need_redraw_temp)
- {
- need_redraw_temp=0;
- for(h=0;h<20;h++)
- for(l=0;l<20;l++)
- dis_pos[h][l]= loc_pos[h][l]; //按照已分布方塊內容 重新刷新顯存區域
- add_els_temp2dis_pos(temp_els,els_cur_x,els_cur_y); //在顯存中重新畫臨時方塊
- dis_pos2dis_buff(); //
- }
- if(!need_redraw_temp) //因為每次方塊坐標動作都引起重畫 ,并且坐標值會變動,如果坐標值變動了,但沒來的及重畫,這個時候顯存的值
- //如果被保留到方塊位置記錄陣列中,顯然是錯誤的.
- if(need_save2_loc) //假如觸底
- {
- key_time=0; //釋放常按功能,例如常按引起迅速下降,這個結果是本次方塊下降到碰觸, 那么將引起下一個方塊的重新開始,
- //因為下個方塊重新開始的時候,我們顯然不希望它也迅速下降到底.因此要釋放和常按關系的變量key_time
- save_dis2loc(); //保存顯存內容到紀錄數組
- els_cur_y=3; //重設方塊位置 X 坐標
- els_cur_x=6; //重設方塊位置 Y 坐標
- cur_mod = TL1%5; //調用隨機函數得到下一個將要出現的方塊形狀編號
- copy_d_s1(); //將下一個形狀,從固定ROM 調 到RAM 中
- if(find_line(rec_line))//每次下降都檢查是否本次下降結束引起堆滿!!也就是:是否游戲結束
- {
- sys_st=logo;
- els_cur_y=3; //游戲結束后你可以設置任意你要的動作,在這里只是重新開始游戲
- ini_gui(); //重新初始化界面
- }
- else
- {
- if(done_line_num) //如果本次下落引起湊滿一行或多行
- {
- d_h=19;
- for(s_h=19;s_h>0;s_h--) //將目前 位置陣列數組中(排除已湊滿一行)外的所有行,從最后一行往上拷
- {
- if((s_h!=rec_line[0])&&(s_h!=rec_line[1])&&(s_h!=rec_line[2])&&(s_h!=rec_line[3]))//湊滿行后,從倒數第一行開始拷貝(排除已經堆滿的行)
- {
- for(s_l=0;s_l<16;s_l++)
- {
- dis_pos[d_h][s_l]=loc_pos[s_h][s_l]; //重新建立各方快坐標 到顯示內存暫存
- }
- d_h--;
- }
- }
- for(h=0;h<20;h++) //將暫存的數據 拷貝到方快位置關系數組中
- for(l=0;l<16;l++)
- {
- loc_pos[h][l]=dis_pos[h][l];
- }
- for(h=0;h<5;h++) //本次處理湊成N行結束 清除一些中間變量
- rec_line[h]=0x00;
- done_line_num=0;
- need_redraw_temp=1;
- }
- }
- need_save2_loc=0; //需要刷新
- }
- break;
- //游戲結束顯示滾動LOGO
- case logo:
- break;
- }
-
-
- }
- }
復制代碼 |