作业描述 | 详情 |
---|---|
这个作业属于哪个课程 | 2020面向对象程序设计 |
这个作业要求在哪里 | 我罗斯方块汇报1 |
这个作业的目标 | -汇报自己这个阶段的开发进度。(完成了哪几个模块) -讲述自己遇到的问题和尝试解决的方法和最后的结果(解决与否) -制作一篇开发日记,例子如此,描述自己开发某一个模块的过程 |
作业正文 | 我罗斯方块阶段报告(1) |
其他参考文献 | |
小组成员 | 031903146 罗佳昱 031903144 李雨情 111900811 林杞垒 |
开发进度
本组设计涉及到四个类:方块类(Mino)、玩家类(Player)、渲染类(Tetris)、游戏类(Game)
方块类(Mino): 目前已经完成方块的显示、擦除、方块的旋转以及随机生成,方块的下落和垃圾行的生成还未完成
玩家类(Player): 两个玩家键盘响应已完成
渲染类(Tetris): 完成首界面、欢迎界面以及游戏界面,光标移动控制,增加了对方块的颜色设置
游戏类(Game): 考虑到双人对战(只要有玩家方块触顶,对方就获胜),打算不设置游戏计分。(如果双方玩家都比较厉害,后期可以考虑阶段下落速度提升)
开发难题
一、线程问题,游戏中若采用单线程,在双方玩家的信息传递,时间控制上容易出现问题。而采用双线程,难点在于两个线程彼此需同步调配。两个玩家均同从键盘按键中获取键值进行相应操作,要避免二者相互冲突,还需引进临界区变量。
二、目前还处于分工阶段,未进行整合,在一些参数设置上可能会有些不同,一些函数调用,友元函数使用也会出现问题。
三、游戏中,基于单人俄罗斯方块,存在游戏区方块位置异常的情况(在几次调试中,偶尔会出现方块左右偏移的情况,出现bug的原因还没找到)
开发日记
罗佳昱
2020.05.08
在小组内进行讨论各个模块的实现方法
2020.05.11
进行了组内分工
我负责的是方块的下落,旋转,随机生成,边界判断,玩家键盘读入
2020.05.12
看起来玩家的键盘读入好像会比较简单的样子呢!那就先完成它吧
w,s,d,a键的读入没啥问题,↑,↓,←,→键才是让我比较懵的,后来查询了资料,知道了↑,↓,←,→有两个键值。
实际上完成起来还算是挺容易的哈哈哈,不过还是需要配合其他模块的很多函数才能实现真正的可行
void Mino1::readKey()
2020.05.14
开始折腾方块类
刚开始动手就遇到了一个头疼的问题,要怎么生成随机方块
查了好一些资料之后总算是发现了srand(), rand(), time()
函数,再结合之前已经想好的各种方块的形状记录,开始动工!
参考如下
void Mino1::Random()
{
srand((int)time(0));
id1 = rand() % 15;
next_id1 = rand() % 15;
Draw(point[0], point[1], id1);
Draw(6, 15, next_id1);
}
2020.05.17
完成了随机生成方块部分的代码,开始做方块旋转。
在之前的讨论中分析了旋转部分依然是与各种方块的形状记录有关,给每个形状一个编号,旋转时将编号改变即可切换图形。
所以这一块做的比较快
参考如下
void Mino1::TurnFirst(int num)//旋转函数
{
switch(num)
{
case a1: id1 = a2; break; //条形互换
case a2: id1 = a1; break;
case b: id1 = b; break; //方块无法旋转
case c1: id1 = c2; break; //各种L形互换
case c2: id1 = c3; break;
case c3: id1 = c4; break;
case c4: id1 = c1; break;
case d1: id1 = d2; break; //各种T形互换
case d2: id1 = d3; break;
case d3: id1 = d4; break;
case d4: id1 = d1; break;
case e1: id1 = e2; break; //两种Z形互换
case e2: id1 = e1; break;
case f1: id1 = f2; break;
case f2: id1 = f1; break;
}
}
2020.05.18
完成了方块旋转部分的代码,开始研究方块下落与边界判断
void Mino1::Down()//下落函数
bool Mino1::JudgeFirst(int x, int y, int num)
2020.05.22
方块下落未完成
已完成边界判断
现在都是分模块做,不敢想到时候整合起来会出什么问题,估计会疯狂报错以及方块乱走吧哈哈哈哈。
李雨情
2020.05.13
我负责方块类的显示擦除,以及消行增行。
基于已经初始化的方块以及基点,方块显示和擦除都较容易
void Tetris::Draw(int x, int y, int num)//方块显示
{
int nx, ny;
for (int i = 0; i < 4; i++)
{
nx = x + sharp[num][2 * i];
ny = y + sharp[num][2 * i + 1];
SetPos((ny + 1) * 2, nx + 1);
SetColor(i + 1);
cout << "■";
}
}
void Tetris::ReDraw(int x, int y, int num);//方块擦除,实现方法与显示类似
void ClearLine(int x, int y, int num);//消除行
//其中通过一个循环判定某一行是否满, 用flag来标记
对于方块偏移的bug,查看了其它一些代码写法,问题可能是出现在字段宽度上
参考如下:
void Mino::PlaceOn();//此函数用于初始化最开始4*4数组的方块信息
void Mino::Show(bool info = false) //将方块在屏幕上输出,info表示是否是信息栏
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
MagicShow(Point(p.x + i, p.y + j), state[i][j], info);
}
}
void MagicShow(const Point& p, bool flag = false, bool info = false) //因为输出/擦除类似,可以通过同一个函数实现
//因为信息栏里也有方块信息,也需要变换
template<typename T>
void PrintAt(const Point& p, T data, int wid = 0) //在点p处输出data
{
SetCursor(p);
if (wid)
cout.width(wid);//控制符int width()将用来调整字段的宽度
cout << data;
}
然后,垃圾行的生成还没完成
需考虑生成行的空格数、空格位置位置以及什么时候显示,实现过程需要借助srand(), rand()
函数
后期可以在消行上增加一些flash_times闪烁效果
林杞垒
2020.05.12
在构思界面设计的时候,觉得原有的颜色过于单一,并且在实际打块过程中不容易识别辨认方块,于是设置了5种颜色
void Tetris::SetColor(int color_num) //设置颜色
{
int n;
switch (color_num)
{
case 0: n = 0x08; break;
case 1: n = 0x0C; break;
case 2: n = 0x0D; break;
case 3: n = 0x0E; break;
case 4: n = 0x0A; break;
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n);
}
接下来是欢迎界面设置
void Tetris::Welocme() //欢迎界面
{
SetColor(1);
char x;
while (1)
{
system("cls");
cout << "■■■■■■■■■■■■■■■■■■■■■" << endl;
cout << " 我 罗 斯 方 块 " << endl;
cout << "■■■■■■■■■■■■■■■■■■■■■" << endl;
cout << " 疫 情 宅 家 无 事 做 " << endl;
cout << " 来 玩 我 罗 斯 方 块 " << endl;
cout << " 双 人 运 动 " << endl;
cout << " 激 情 对 战 " << endl;
cout << "■■■■■■■■■■■■■■■■■■■■■" << endl;
cout << " Press any key to continue " << endl;
SetPos(20, 10);
}
}
尽可能的设计的足够土
在设计双人对战框架时,自己曾试过12×20,或者15×25的playfield,但在测试下,既不美观对称,也不够合理。后来去搜索了Tetris Online和Tetris 99等在线对战俄罗斯方块的详细规则,参考了其中对于playfield的搭建,选用了Tetris Online的10×20(宽*高)的规格。
效果图预览
void Tetris::DrawMap() //画游戏时界面
void Tetris::SetColor(int color_num) //设置颜色
void Tetris::Welocme() //欢迎界面
void SetPos(int i, int j) //控制光标位置, 列, 行
渲染类中的四个函数已完成
GitHub地址:我罗斯方块阶段报告(1)