这段时间学习了一些C++的内容,跟着教程使用C++粗略还原了俄罗斯方块的一些基本内容,本文主要针对方块下落的环节找到一些可以选择的方案。
俄罗斯方块实现简述
工具介绍
编译软件采用VC++2010,图形库是EasyX,这算是比较初级的软件了,简单的功能往往只需要使用简单的工具[狗头]。
程序结构
俄罗斯方块的粗略实现只需要根据功能建立一些结构体,暂时还可以不使用到C++的类功能,下面对程序结构进行简要说明。
主函数部分void main(void)
1.显示欢迎界面
设计一个Hello界面
2.显示游戏界面
设计一个游戏界面。分为游戏区、下一个方块区、右侧积分和等级区、操作说明区。其中游戏区和NEXT区的外框、积分区的SCORE和LEVEL、操作区是固定好的。
3.在右上角产生新的方块
4.开始游戏部分(下面拆分)
5.结束
游戏部分
1.在游戏区产生一个新块,执行下落等功能(下面拆分)
2.判断这个块下落结束后是否需要消除行,是则消除行、加分、加等级,不是则跳过
下落等功能
1.使NEXT区显示的方块对应地在游戏区出现
2.在右上角绘制一个新的方块
3.向下移动(讨论部分)
实现原理
俄罗斯方块的实现原理是
将游戏区设计成二维数组(例如30×15大小),预先将各种块也设计成二位数组写好并存入一个.cpp文件中(例如5×5大小);随机生成一个存在NEXT区域,再将此块在游戏区生成并使其按时间下落,同时新随机生成一个块存在NEXT区域;在当前块下落后判断是否需要消除行,若是则执行消除,并且该行的所有上方数据向下移动一行。循环实现即可。
讨论部分:当前块下落过程
我按照教程写的第一版下落函数的流程为:
1.首先检查游戏是否结束,即GAME OVER!
2.做一个循环
(1)检查当前是否有按键按下,如果该键为SPACE,则暂停。
(2)将当前方块清除
(3)如果有按键按下,并且该键为“上”,则先判断该方块是否可以转换,如果可以则转换形状;如果该键为“下”,则将方块下落速度调整至最快;如果该键为“左(右)”,则判断该方块是否可以向左(右)移动,如果可以则把方块坐标向左(右)移动一格。
(4)将当前方块坐标向下移一格并绘制当前方块
(5)等待一段时间(这段时间可以被“下”键调整至极低)
(5)判断方块是否可以继续向下移动,若可以则继续循环,若不可则在地图二维数组中标记固化位置。
3.“等待”方法中,将等待时间分为若干个10ms的时间块,如果检测到按键输入,则跳出该模块,进入下一个循环中。
在该方法完成后发现,如果不按按键,是按照规定时间逐步下落,但是每按一次按键,方块都会迅速下落一格,即如果按了“左”,方块会瞬移到他的左下方,这与实际玩法不符,所以进行了改动,流程如下:
1.检查游戏是否结束,即GAME OVER!
2.循环开始
(1)清除当前方块,下落一格,生成新方块
(2)直接生成一个每10ms一周期的循环,每个周期内检查是否有按键按下,如果有并且是“上”、“左”、“右”,则判断是否能够到达新的位置,如果是则直接生成新的位置。如果是“下”则降低持续时间,缩短该10ms一周期的总周期数。
(3)方块的固化处理不变。
上代码
改动前:
//向下移动
void move(void) {
//初始位置
int x = START_X;
int y = START_Y;
int k = 0; //y偏移量
block_dir_t blockDir = BLOCK_UP;//当前朝向
int curSpeed = speed;//当前速度
//检测游戏是否结束
failCheck();
//持续向下
while(1) {
if(kbhit()) { //检查是否有按键
int key = getch();
if(key == KEY_SPACE) {
getch();
}
}
//清除当前方块
clearBlock(x, k, blockDir);
if(kbhit()) { //检查是否有按键
int key = getch();
if(key == KEY_UP) {
block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);
if(rotateable(x, y+k, nextDir)) {
blockDir = nextDir;
}
}
else if(key == KEY_DOWN) {
curSpeed = 50;
}
else if(key == KEY_LEFT){
if(moveable(x, y+k, MOVE_LEFT, blockDir))
x -= 20;
}
else if(key == KEY_RIGHT) {
if(moveable(x, y+k, MOVE_RIGHT, blockDir))
x += 20;
}
}
k += 20;//偏移量加一格
//绘制当前方块
drawBlock(x, y+k, blockDir);
//等待
wait(curSpeed);
//方块的"固化"处理,能否向下移动
if(!moveable(x, y+k, MOVE_DOWN, blockDir)) {
mark(x, y+k, blockDir);
break;
}
}
}
改动后:
void move(void) {
//初始位置
int x = START_X;
int y = START_Y;
int k = 0;//y偏移量
block_dir_t blockDir = BLOCK_UP;//当前朝向
int curSpeed = speed;//当前速度
//检测游戏是否结束
failCheck();
//持续向下
while(1) {
clearBlock(x, k, blockDir);//清除当前方块
k += 20;//偏移量加一格
//绘制当前方块
drawBlock(x, y+k, blockDir);
for(int i = 0; i < curSpeed / 10; i++) {
Sleep(10);
if(kbhit()) {
int key = getch();
//清除当前方块
clearBlock(x, k, blockDir);
if(key == KEY_UP) {
block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);
if(rotateable(x, y+k, nextDir)) {
blockDir = nextDir;
}
}
else if(key == KEY_DOWN) {
curSpeed = 50;
break;
}
else if(key == KEY_LEFT){
if(moveable(x, y+k, MOVE_LEFT, blockDir))
x -= 20;
}
else if(key == KEY_RIGHT) {
if(moveable(x, y+k, MOVE_RIGHT, blockDir))
x += 20;
}
else if(key == KEY_SPACE) {
getch();
}
drawBlock(x, y+k, blockDir);
}
}
//方块的"固化"处理,能否向下移动
if(!moveable(x, y+k, MOVE_DOWN, blockDir)) {
mark(x, y+k, blockDir);
break;
}
}
}
我是没信号的法杖,发不出去信号,也接收不到信号。