俄罗斯方块程序,以前上传过的,这次做了一点点改动和优化,就直接套用进去了。
主要就是修改各种显示:比如方块、颜色、提示等。
主程序很简单,就是每隔一场读取一次按键,然后执行对应的移动、合并、消行、计分等。
老x的俄罗斯方块采用了和别人完全不同的碰撞判断方法哦~ 这点就要看你自己去读程序、发掘它了哦~:)
俄罗斯方块程序部分摘录与下:
/****************************************************************************/
// 源程序大公开 //
// (c) Copyright 2001-2010 xuwenjun //
// All Rights Reserved //
// V1.01 //
/****************************************************************************/
//标 题: 俄罗斯方块程序 //
//文件名: xwj_fk.c //
//版 本: V1.01 //
//修改人: 徐文军 E-mail:xuwenjun@21cn.com //
//日 期: 2010-05-13 //
//描 述: 俄罗斯方块程序 //
// 1、改为VGA输出显示,支持彩色显示 //
// 2、增加方块投影预览、新方块避免碰撞、过关效果等,功能更为完善 //
// 3、程序代码量相当少,包括VGA驱动占用:data=123.1 xdata=764 code=8797 //
// 其中还包括字库占用的1786字节 //
//声 明: //
// 以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处. //
// 如用于商业用途请与作者联系. E-mail:xuwenjun@21cn.com //
// 有问题请mailto xuwenjun@21cn.com 欢迎与我交流! //
/****************************************************************************/
//老版本: V1.00 老版本文件名:xwj_fk.c //
//创建人: 徐文军 E-mail:xuwenjun@21cn.com //
//日 期: 05-05-13 //
//描 述: 老x以前发布过的俄罗斯方块程序哦,5年啦~ //
// 1、功能完整,直接使用 //
// 2、模块独立性强,移植方便,外部仅init和move函数,修改显示和输入即可 //
// 3、对减少内存占用、尽量减少屏幕操作进行适当优化 //
// 4、新方块生成高度随机,绝对无规律 //
// 5、仿真环境为Keil7.5+Proteus6.5,可以联机也可脱机运行 //
/****************************************************************************/
#include <stdlib.h>
#include "xwj_vga_drive.h" //包涵OSD_index头文件
#include "xwj_osd_mini.h" //包涵OSD_IO头文件
#include "keyboard.h" //包涵键盘头文件
#include "change.h" //包涵数制转换头文件
#include "music.h" //包涵音乐头文件
#define __XWJ_FK_C__
#include "xwj_fk.h" //包涵俄罗斯方块头文件
//==============变量定义==============
/****************************************************************************/
...
//==============常量定义==============
/****************************************************************************/
...
/****************************************************************************/
void fk_dot(uchar x,uchar y,uchar type); //显示1个方块点
void fk_cldot(uchar x,uchar y); //清除1个方块点
void fk_refline(yy); //刷新1行背景
void fk_print(uchar x,uchar y,uchar type,uchar num); //显示方块数字0~9,3x5点阵,x=0~7,y=4~19
void fk_print2(uchar x,uchar y,uchar type,uchar num); //显示2位方块数字0~9,3x5点阵,x=0~3,y=4~19
void fk_show(void); //显示分数
bit fk_chk(void); //当前方块冲突检查
bit fk_chknew(void); //新方块冲突检查
void fk_dotnew(uchar x,uchar y); //显示1个预览方块点
void fk_cldotnew(uchar x,uchar y); //清除1个预览方块点
void fk_refnew(void); //刷新预览方块
void fk_del_refnew(void); //清除预览方块
void fk_ref_pause(bit flag); //显示/清除当前方块,暂停时用
void fk_ref_pauseold(bit flag); //显示/清除old方块
void fk_reffk(void); //刷新方块
void fk_new_auto(void); //新方块自动避免碰撞
uchar fk_chk_shadow(void); //查找判断新的方块投影高度
void fk_shadow(void); //显示方块投影
void fk_shadow_flash(void); //方块投影闪烁
void fk_new(void); //产生新方块
void fk_Cls(void); // 方块清屏
void fk_add(void) //方块合并
{
uchar i,j,k;
uchar full=0x00;
uchar fulltemp;
uchar fullline=0x00;
for (i=0;i<4;i++) //方块合并
{
fk_map[ fk_y+i ] |= (fk_mod[ fk_type_r ][ i ])<<fk_x;
full <<= 1;
if ((fk_y+i >= 4) && (fk_map[ fk_y+i ] == 0xffff)) //满行
{
full |= 0x01;
}
}
if (full != 0) //有满行
{
Start_music(Music1); //播放音乐:删除一满行音效
for (j=0;j<5;j++) //消行闪烁3次
{
delay17(12);
fulltemp=full;
for (i=0;i<4;i++) //4行
{
if ((fulltemp&0x08) != 0)
{
fk_map[ fk_y+i ] ^= FULLMAP;
fk_refline(fk_y+i);
}
fulltemp <<= 1;
}
}
for (i=LINEMAX;i<LINEMAX+4;i++) //上面行下移
{
fk_refline(i);
}
fulltemp=full;
for (i=fk_y;i<LINEMAX+4+fullline;i++) //上面行下移
{
...
}
line += fullline; //更新分数、行数
i=(1<<fullline)-1;
score_guan += i; //一关的得分
score += i; //总分
bHz12=0; //bHz12=1:12X12点阵汉字;bHz12=0:16X16点阵汉字
printat(0,69,str_score[ fullline ]); //夸奖
fk_show(); //显示分数
if (((line-fullline)/LINEGUAN) != (line/LINEGUAN))//每20行速度+1
{
speed ++;
Start_music(Music8); //播放音乐:过关音效
bHz12=0; //bHz12=1:12X12点阵汉字;bHz12=0:16X16点阵汉字
printat(0,69,"(^_^)");
bHz12=1; //bHz12=1:12X12点阵汉字;bHz12=0:16X16点阵汉字
if(score_guan>=75) //一关的得分
{printat(20,0,str_win[ 6 ]);} //评价 "神"
else if(score_guan>65)
{printat(20,0,str_win[ 5 ]);} //评价 "牛"
else if(score_guan>52)
{printat(20,0,str_win[ 4 ]);} //评价 "优"
else if(score_guan>40)
{printat(20,0,str_win[ 3 ]);} //评价 "好"
else if(score_guan>30)
{printat(20,0,str_win[ 2 ]);} //评价 "良"
else if(score_guan>22)
{printat(20,0,str_win[ 1 ]);} //评价 "差"
else
{printat(20,0,str_win[ 0 ]);} //评价 "囧"
score_guan=0; //一关的得分
if(speed>=12)
{
//。。。过关特效
}
delay17(10);
}
fk_new(); //产生新方块
}
else
{
bHz12=0; //bHz12=1:12X12点阵汉字;bHz12=0:16X16点阵汉字
if (fk_y > LINEMAX-6) //
{printat(0,69,"糟糕 ");} //糟糕了
else if (fk_y > LINEMAX-10) //
{printat(0,69,"加油 ");} //加油啊
else
{printat(0,69,str_score[ 0 ]);} //空白
if (fk_y==LINEMAX) //在最高位置碰撞且不能消行则游戏结束
{
fk_run=0; //方块初始化
Start_music(Music5); //播放音乐:游戏结束音乐
bHz12=0; //bHz12=1:12X12点阵汉字;bHz12=0:16X16点阵汉字
printat(0,69,":>_<:");
}
else
fk_new(); //产生新方块
}
}
/****************************************************************************/
void fk_init(void) //方块初始化
{
uchar i;
uchar j;
if(Mute) //音乐关闭
Start_music(Music4); //播放音乐:开机音乐
keyinit(); //按键初始化,清空输入缓冲区
moven=0;
if (maxscore<score)
maxscore=score; //保留最高记录
score=0;
if (maxline<line)
maxline=line;
line=0;
fk_show(); //显示分数
fk_del_refnew(); //清除预览方块
for (i=0;i<sizeof(diaplay_buf)%255;i++)
{
j=j+diaplay_buf[ i ];
}
srand(j);
for (i=0;i<sizeof(Dis_Buf);i++)
{
j=j+Dis_Buf[ i ];
j+=rand();
}
srand(j+TL0);
j=rand()&0xfc+1;
for (i=0;i<j;i++)
{
rand();
}
fk_newtype_r = rand()%28;
fk_newx=NEWX;
score_guan=0; //一关的得分
for (i=0;i<4;i++)
{
fk_map[ i ]=0xffff; //背景映象
}
for (i=4;i<LINEMAX+4;i++)
{
fk_map[ i ]=0xffff; //背景映象
fk_refline(i); //刷新1行背景
delay17(6);
}
for (i=LINEMAX+4;i>=4;i--)
{
fk_map[ i ]=~FULLMAP; //背景映象
fk_refline(i); //刷新1行背景
delay17(6);
}
fk_print2(1,6,1,automapn); //显示2位方块数字0~9,3x5点阵,x=0~3,y=4~19
fk_print2(1,13,0,speed+1); //显示2位方块数字0~9,3x5点阵,x=0~3,y=4~19
fk_new(); //产生新方块
while (~fk_run)
{
fk_move(); //等待设置速度关数开始
delay17(1);
}
fk_pause=0; //游戏暂停:关
fk_Cls(); // 清屏
fk_show(); //显示分数
fk_new(); //产生新方块
}
/****************************************************************************/
void fk_move(void) //移动方块
{
unsigned char temp;
unsigned char i;
if(KeyTest()) //检查有无按键
{
putinbuf(KeyGetCode()); //按键码输入接收缓冲区
}
if (checkin())
{
temp=getbyte();
}
else
temp=0xff; //无键设为无效键用于下移方块
switch(temp)
{
default:
if (fk_pause)
break;
if (--moven) //游戏难度
break;
else
{
moven=fk_speed[ speed ];
if (fk_run &&(speed<10)) //游戏中自动下移
Start_music(Music0); //播放音乐:自动下落音效
}
case DownKey: //下移
moven++;
if (fk_run) //游戏中下移
{
if (fk_pause) //游戏暂停
break;
if(fk_y>0)
{
fk_y--;
if(fk_chk())
{
fk_y++; //有冲突取消操作,执行碰撞组合
fk_add(); //方块合并 //产生新方块
}
}
else //方块到底也执行碰撞组合
{
fk_add(); //方块合并
}
}
else //初始化时
{
fk_new(); //产生新方块
}
break;
case UpKey: //上键
if (fk_run) //游戏中右移
{
fk_pause^=1;
if(!fk_pause)
{
fk_ref_pause(1); //恢复暂停时刷新显示方块
}
else
{
fk_shadow_flash(); //清除:方块投影
}
}
else
{
fk_run=1;
}
break;
case EndKey: //下移到底
if (fk_pause) //游戏暂停
break;
fk_y=fk_shadowy;
moven=1;
break;
case RightKey: //右移
if (fk_run) //游戏中右移
{
moven++;
if (fk_pause) //游戏暂停
break;
if(fk_x<=FK_LEN)
{
fk_x++;
if(fk_chk())
fk_x--;//有冲突取消操作
}
}
else //初始化时
{
speed++;
speed %= 16;
fk_print2(1,13,0,speed+1); //显示2位方块数字0~9,3x5点阵,x=0~3,y=4~19
fk_show(); //显示分数
}
break;
case LeftKey: //左移
if (fk_run) //游戏中左移
{
moven++;
if (fk_pause) //游戏暂停
break;
if(fk_x>0)
{
fk_x--;
if(fk_chk())
fk_x++;//有冲突取消操作
}
}
else //初始化时
{
automapn++;
fk_map[ automapn+3 ]=rand()-1|~FULLMAP; //背景映象
fk_refline(automapn+3); //刷新1行背景
if(automapn == 16)
{
automapn = 0;
fk_Cls(); // 清屏
}
fk_print2(1,6,1,automapn); //显示2位方块数字0~9,3x5点阵,x=0~3,y=4~19
fk_print2(1,13,0,speed+1); //显示2位方块数字0~9,3x5点阵,x=0~3,y=4~19
fk_show(); //显示分数
}
break;
case BKey: //右转
if (fk_run) //游戏中右转
{
moven++;
if (fk_pause) //游戏暂停
break;
i=fk_type_r;
fk_type_r++;
if((fk_type_r&0xfc) != (i&0xfc))
fk_type_r = i&0xfc;
if(fk_chk())
{
fk_type_r = i; //有冲突取消操作
if(fk_x ==0)
{
putinbuf(RightKey); //按键码输入接收缓冲区
putinbuf(BKey); //按键码输入接收缓冲区
putinbuf(LeftKey); //按键码输入接收缓冲区
}
else if(fk_x >= FK_LEN-4)
{
need_rounds++;
putinbuf(LeftKey); //按键码输入接收缓冲区
putinbuf(BKey); //按键码输入接收缓冲区
}
}
else
{
while(need_rounds)
{
need_rounds--;
putinbuf(RightKey); //按键码输入接收缓冲区
}
}
}
else //初始化时
{
fk_run = 1;
}
break;
case AKey: //左转
if (fk_run) //游戏中右转
{
moven++;
if (fk_pause) //游戏暂停
break;
i=fk_type_r;
fk_type_r--;
if((fk_type_r&0xfc) != (i&0xfc))
fk_type_r = (i&0xfc)+3;
if(fk_chk())
{
fk_type_r = i; //有冲突取消操作
if(fk_x ==0)
{
putinbuf(RightKey); //按键码输入接收缓冲区
putinbuf(BKey); //按键码输入接收缓冲区
putinbuf(LeftKey); //按键码输入接收缓冲区
}
else if(fk_x >= FK_LEN-4)
{
need_rounds++;
putinbuf(LeftKey); //按键码输入接收缓冲区
putinbuf(AKey); //按键码输入接收缓冲区
}
}
else
{
while(need_rounds)
{
need_rounds--;
putinbuf(RightKey); //按键码输入接收缓冲区
}
}
}
else //初始化时
{
fk_run = 1;
}
break;
}
if(fk_run)
{
if(fk_pause)
{
if(flag_Time0_5s_old^flag_Time0_5s_State) //半秒标志有变化
{
flag_Time0_5s_old=flag_Time0_5s_State;
fk_ref_pause(flag_Time0_5s_State); //暂停时刷新显示方块
}
}
else if((fk_x!=fk_oldx)||(fk_y!=fk_oldy)||(fk_type_r!=fk_oldtype_r))
{
if((fk_x!=fk_oldx)||(fk_type_r!=fk_oldtype_r))
{
fk_shadow(); //显示方块投影
}
fk_reffk(); //刷新显示
}
else
{
fk_shadow_flash(); //方块投影闪烁
}
}
rand();
}
/****************************************************************************/
void main(void)
{
OSD_Cls();
vga_init(); //VGA驱动初始化
delay17(6); //延时0.1秒
Mute=1; //音乐关闭
fk_init(); //方块初始化
while(1)
{
if (~fk_run)
fk_init(); //方块初始化
fk_move(); //移动方块
delay17(1);
}
}
/****************************************************************************/
//本程序由xwj设计的UltraEdit脚本加亮显示,如需要脚本请访问我的Blog:wwww.21ic.com或联系xwjfile@21cn.com |