标题: 酷!用51单片机在16×16LED 点阵上玩俄罗斯方块游戏 程序+PCB+电路图 [打印本页]
作者: zerozeroseven 时间: 2009-9-8 20:14
标题: 酷!用51单片机在16×16LED 点阵上玩俄罗斯方块游戏 程序+PCB+电路图
很酷的16×16LED俄罗斯方块游戏制作资料分享给51黑电子论坛的朋友:
pads画的图:
所有程序源码包含工程文件:
源程序.rar
(59.23 KB, 下载次数: 975)
PADS2005画的电路图以及pcb文件下载:
pads2005画的原理图和PCB布线图.7z
(76.44 KB, 下载次数: 1135)
以下是视频效果:
视频:http://v.youku.com/v_show/id_XMTAxNjY4ODY4.html
作者: linyean 时间: 2009-9-9 11:09
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;
- }
-
-
- }
- }
复制代码
作者: 51hei 时间: 2009-9-12 11:59
高手啊!!!!!!!!!
作者: dongyulong 时间: 2009-9-12 21:38
太强大了 牛气
作者: cainiaoa 时间: 2009-9-14 20:18
我看了视频了,真是太厉害了,高人啊
作者: 柳梢儿 时间: 2009-9-17 20:54
东西呢?
作者: xiaoshandong 时间: 2009-9-17 22:17
下来没用的啊!电路图没东西的啊
作者: xiaoshandong 时间: 2009-9-17 22:37
怎么搞的啊
作者: mm520 时间: 2009-9-19 22:38
等我也要学习
作者: 骊威电子 时间: 2009-9-22 21:23
等我也要学习
作者: zerozeroseven 时间: 2009-9-26 15:09
回小山东,原理图和PCB 是PADS2005格式的。用PROTEL打不开的!
作者: mainv 时间: 2009-10-3 10:25
楼主很厉害啊
作者: 扬扬 时间: 2009-10-14 14:10
回帖是一种美德! 楼主好强大
作者: today 时间: 2009-10-16 13:40
好厉害!
作者: sysatom 时间: 2009-10-19 13:08
高手,我几时才有这水平?努力啊!!!
作者: witnessiz 时间: 2009-10-20 15:51
很神奇啊,看得我有点心痒痒,还是有点思路,有空做做看
作者: 幸甚至哉 时间: 2010-3-6 15:57
很好,不错!!!
作者: shichuan 时间: 2010-3-9 16:54
高手也!下载下来学习。
作者: hjwen8680 时间: 2010-3-17 18:41
有点意思啊,值得学习。
作者: 丶苗条的胖子 时间: 2010-3-19 22:19
利害啊,我是新手,大开眼界啊
作者: yuhuashi23 时间: 2010-3-20 19:56
很强大 学习
作者: led001 时间: 2010-4-2 18:13
请问刚开始时候LED是红色的,后来又是绿色的。是同一块板还是不同的板。
作者: jh 时间: 2010-4-3 22:44
我的是8*8的点阵
作者: 东野 时间: 2010-4-4 01:46
真厉害啊
作者: G-ONE 时间: 2010-4-6 10:03
呵呵 抽空也做做玩
作者: lb605751149 时间: 2010-4-6 10:12
不错,学习
作者: mingzhi 时间: 2010-4-18 22:20
很强大,下来学习了,谢谢。
作者: yuanxiang 时间: 2010-4-22 09:28
niu a
!!1
作者: myborntorun 时间: 2010-4-27 17:57
很好。我也在写
作者: skyhie 时间: 2010-5-10 18:30
好厉害哟
作者: cool882 时间: 2010-5-21 12:29
高手啊!!学习一下!!
作者: dianzilk 时间: 2010-5-22 10:35
正在找这方面的资料!谢了!
作者: mrzwx 时间: 2010-6-19 18:58
你的图呢?没图好像看懂呀?
作者: fffzhao 时间: 2010-6-30 01:44
酷,下载来学习下
作者: 桃源客 时间: 2010-6-30 16:34
有意思!就是算法难点。电路应不是很难。
作者: xsx127 时间: 2012-4-22 19:08
牛啊在哪下砸
作者: 宋明强 时间: 2012-4-23 23:53
楼主能指导我做做这个不??
作者: lpq123 时间: 2012-6-8 16:00
这个需要哪些器件啊 可以发清单给我吗 楼主感恩呐
作者: qq177128496 时间: 2012-7-30 20:30
多谢分享
作者: 池中麟 时间: 2012-8-5 12:31
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 池中麟 时间: 2012-8-5 12:32
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 池中麟 时间: 2012-8-5 12:35
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 池中麟 时间: 2012-8-5 12:37
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 池中麟 时间: 2012-8-5 12:37
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 池中麟 时间: 2012-8-5 12:38
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: 池中麟 时间: 2012-8-5 12:38
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: weifengdq 时间: 2014-4-28 15:37
这也可以。。。
作者: skype1027 时间: 2014-9-13 00:05
真可以。。。
作者: wkj3253 时间: 2014-10-23 17:27
试试,谢谢
作者: p18712886438 时间: 2014-11-19 21:43
支持一个
作者: p18712886438 时间: 2014-11-19 21:44
支持一个
作者: 2796277453 时间: 2014-11-20 22:05
谢谢喽。。
作者: p18712886438 时间: 2014-11-21 13:55
支持一个
作者: p18712886438 时间: 2014-11-21 13:55
支持一个
作者: 自自在在 时间: 2014-12-11 18:42
看看。。。
作者: 自自在在 时间: 2014-12-11 18:42
m币不够
作者: 石老A 时间: 2015-9-18 09:22
BANG,BANG,BANG,BANG,BANG,BANG,BANG,BANG,BANG,BANG,BANG,BANG,BANG,
作者: bjgk 时间: 2015-9-20 19:20
厉害,牛人的作品。
作者: 相投欧 时间: 2015-10-16 22:46
求楼主发原理图,为什么用Altium designed看不到
作者: 我是萌妹子 时间: 2015-12-5 15:30
看看,楼主厉害,值得学习
作者: 永远的王同学 时间: 2015-12-25 01:16
唉,等我用电脑再来浏览!
作者: bwzdxl 时间: 2016-5-18 23:41
楼主乃真.高手!!!
作者: 巴斯光年白 时间: 2016-6-6 20:41
哇哦,酷酷
作者: 巴斯光年白 时间: 2016-6-7 20:20
厉害,楼主
作者: Q好人一生平安 时间: 2016-10-16 10:57
PCB没有图,程序学习下
作者: npn 时间: 2016-10-16 22:15
本帖最后由 npn 于 2016-10-16 22:33 编辑
再加上一些带有特殊功能的方块,比如一种会爆炸的方块,掉落后方块放出爆炸特效并且消失部分范围的方块,或者一种特殊方块掉落后让整个竖排的方块全部滑落或消失,通常是1个像素或两个像素竖排的点且旋转不了的一种特殊方块,或者加入更大的难度,一开始中间以及底部就有不规则的固定方块。
作者: zhouqiang 时间: 2016-10-17 09:06
支持支持
作者: 小玄ed 时间: 2016-11-9 22:29
有没有8x8的呀?
作者: ING-sh 时间: 2016-11-10 10:03
大神
,下载学习一下
作者: 773812422 时间: 2016-12-2 17:58
楼主牛逼
这个程序可以在arduino UNO上运行?
作者: 773812422 时间: 2016-12-2 17:58
楼主厉害
作者: huang917500 时间: 2016-12-6 23:07
51黑有你更精彩!
作者: zqy181818 时间: 2017-3-20 16:43
给力。
作者: faridzled 时间: 2017-3-22 00:00
thanks for sharing
作者: ChazLiu 时间: 2017-11-22 22:01
font.h 文件在哪
作者: 一去不返 时间: 2017-11-23 17:00
顶顶顶
作者: wxxl 时间: 2017-11-23 21:27
DXP也打不开,原理图
作者: ゅ前途丶 时间: 2018-1-14 14:58
你打开了没啊
作者: 小吹吹 时间: 2018-7-11 13:14
到移动方块卡住了,来看看大神的操作
作者: 小吹吹 时间: 2018-7-11 13:18
感谢啊
作者: xiaozhong1314 时间: 2018-11-6 13:11
这个需要哪些器件啊 可以发清单给我吗 楼主感恩呐 986212146@qq.com
作者: xiaozhong1314 时间: 2018-11-8 20:22
这个需要哪些器件啊 可以发清单给我吗 楼主感恩呐 986212146@qq.com
作者: hufeihufei110 时间: 2018-11-20 15:17
楼主能不能发我。。没有币了?邮箱联系:282061410@qq.com
作者: sdxrly 时间: 2019-5-5 11:42
学习一下
作者: sunny@1011 时间: 2019-5-5 15:21
为什么有错误?
作者: 15027 时间: 2019-6-7 14:13
来学习学习,楼主牛
作者: 64MIN 时间: 2019-7-1 14:20
牛逼嗷
作者: 一车异世界 时间: 2019-7-8 17:39
总算找到个喜欢写注释的搂住了
,看程序舒服多了。
作者: HYHTYHYT266161 时间: 2021-11-2 23:10
要pads才能打开
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |