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;
- }
-
-
- }
- }
复制代码 |