期中大作业 俄罗斯方块

一、 作业内容

设计一个简化版的俄罗斯方块游戏 。游戏窗口大小是20×10的方形棋盘格阵列(下图左),游戏中出现的方块共有7种(下图右),每种方块的旋转中心由黑点标出 。留空代码“tetris.cpp”文件中针对L形状记录方块布局的数组vec2 allRotationsLshape[4][4]的设定请参看(下图右)中的第五行图示(老师上课的时候也会简单说明一下)。

具体实现内容和步骤包括:

  1. 方块/棋盘格的渲染和方块向下移动
    创建OpenGL绘制窗口,然后绘制网格线来完成对棋盘格的渲染。随机选择方块并赋上颜色,从窗口最上方中间开始往下自动移动,每次移动一个格子。初始的方块类型和方向也必须随机选择,另外可以通过键盘控制方块向下移动的速度,在方块移动到窗口底部的时候,新的方块出现并重复上述移动过程。
  2. 方块叠加
    不断下落的方块需要能够相互叠加在一起,即不同的方块之间不能相互碰撞和叠加。另外,所有方块移动不能超出窗口的边界。
  3. 键盘控制方块的移动
    通过方向键(上/下/左/右)来控制方块的移动。按“上”键使方块以旋转中心顺(逆)时针旋转,每次旋转90°,按“左”和“右”键分别将方块向左/右方向移动一格,按“下”键加速方块移动。
  4. 游戏逻辑
    当游戏窗口中的任意一行被方块占满,该行即被消除,所有上面的方块向下移动一格子。当整个窗口被占满而不能再出现新的方块时,游戏结束。通过按下“q”键结束游戏,和按下“r”键重新开始游戏。

代码解析

为了实现方块形状和颜色的随机生成,方块的自动下落,以及额外添加的积分和暂停功能所增加的变量:

根据教程图写出来的方块的形状以及旋转后的位置()

根据教程图写出来的方块的形状以及旋转后的位置()


新增加的颜色:


我们需要新增一个全局变量二维数组记录每个格子的颜色:

当改变颜色的时候,同时修改这个格子的颜色


生成方块时需要做的事:

初始化游戏界面时,在另一个窗口增添游戏指引:

初始化时,增添了一步:将所有方块的颜色初始化为黑色

方块的碰撞检测:

判断某行是否被填满,如果被填满需要进行一系列的操作:

当物体运行到窗口底部或者是碰到物体则需要执行以下函数:

重新启动游戏

注意键盘响应时,如果处于暂停状态则不触发功能

在键盘响应部分添加P键的操作:暂停功能


在idle函数内增加物块下落的操作

实验效果

(具体实际效果可以看视频
随机生成方块的形状及颜色,每隔一段时间,都会自然往下掉落,当有一行被填满时,则会自动消除,上面一行的方块将会往下掉一行


暂停或者恢复时也会有提示,暂停时按下暂停键则会恢复

重启游戏后,界面也会全部清空,下落速度恢复到初始状态

完整代码

/** - 本代码仅仅是参考代码,具体要求请参考作业说明,按照顺序逐步完成。* - 关于配置OpenGL开发环境、编译运行,请参考第一周实验课程相关文档。** - 已实现功能如下:* - 1) 绘制棋盘格和‘L’型方块* - 2) 键盘左/右/下键控制方块的移动,上键旋转方块** - 未实现功能如下:* - 1) 随机生成方块并赋上不同的颜色* - 2) 方块的自动向下移动* - 3) 方块之间的碰撞检测* - 4) 棋盘格中每一行填充满之后自动消除* - 5) 其他** 致谢:参考代码来自于西蒙弗雷泽大学CMPT361-Assignment*/#include "include/Angel.h"#pragma comment(lib, "glew32.lib")#include <cstdlib>
#include <iostream>using namespace std;int starttime;         // 控制方块向下移动时间
int rotation = 0;      // 控制当前窗口中的方块旋转
vec2 tile[4];           // 表示当前窗口中的方块
bool gameover = false; // 游戏结束控制变量
int xsize = 400;       // 窗口大小(尽量不要变动窗口大小!)
int ysize = 720;
int ColorNum;//颜色数量
int ShapeNum;//形状的数量
int DownTime = 1000;//下落的时间间隔
int nowTime;
int DownNum = 1;//下落了多少个方块
int Point = 0;//积分数量 每消除一行积分加10
bool pause = false;//用来表示游戏是否暂停的变量
int Rank = 1;//游戏难度// 一个二维数组表示所有可能出现的方块和方向。
//这个数组的设置比较难理解,是根据word文档里面的(下图右)里面的图示而来,老师上课会解释一下,请注意听
vec2 allRotationsLshape[7][4][4] =
{//以下按照实验指导的图形顺序//1:O型方块
{   {vec2(0, 0), vec2(-1,0), vec2(0, -1), vec2(-1,-1)}, {vec2(0, 0), vec2(-1,0), vec2(0, -1), vec2(-1,-1)},   {vec2(0, 0), vec2(-1,0), vec2(0, -1), vec2(-1,-1)},    {vec2(0, 0), vec2(-1,0), vec2(0, -1), vec2(-1,-1)}  },//2:I型方块
{   {vec2(-2, 0), vec2(-1,0), vec2(1, 0), vec2(0,0)},   {vec2(0, 1), vec2(0, 0), vec2(0,-1), vec2(0, -2)},   {vec2(-2, 0), vec2(-1,0), vec2(1, 0), vec2(0,0)},     {vec2(0, 1), vec2(0, 0), vec2(0,-1), vec2(0, -2)}  },//3:S型方块
{   {vec2(0, 0), vec2(0,-1), vec2(-1, -1), vec2(1,0)},  {vec2(0, 1), vec2(0, 0), vec2(1,0), vec2(1, -1)},    {vec2(0, 0), vec2(0,-1), vec2(-1, -1), vec2(1,0)},    {vec2(0, 1), vec2(0, 0), vec2(1,0), vec2(1, -1)}  },//4:Z型方块
{   {vec2(-1, 0), vec2(0,0), vec2(0, -1), vec2(1,-1)},  {vec2(0, 0), vec2(0, -1), vec2(1,0), vec2(1, 1)},    {vec2(-1, 0), vec2(0,0), vec2(0, -1), vec2(1,-1)},  {vec2(0, 0), vec2(0, -1), vec2(1,0), vec2(1, 1)}  },//5:L型方块
{   {vec2(0, 0), vec2(-1,0), vec2(1, 0), vec2(-1,-1)},  {vec2(0, 1), vec2(0, 0), vec2(0,-1), vec2(1, -1)},     {vec2(1, 1), vec2(-1,0), vec2(0, 0), vec2(1,  0)},   {vec2(-1,1), vec2(0, 1), vec2(0, 0), vec2(0, -1)}  },//6:J型方块
{   {vec2(-1, 0), vec2(0,0), vec2(1, 0), vec2(1,-1)},   {vec2(0, 1), vec2(0, 0), vec2(0,-1), vec2(1, 1)},  {vec2(-1, 0), vec2(0,0), vec2(1, 0), vec2(-1,  1)},     {vec2(-1,-1), vec2(0, -1), vec2(0, 0), vec2(0, 1)} },//7:T型方块
{   {vec2(-1, 0), vec2(0,0), vec2(1, 0), vec2(0,-1)},   {vec2(0, -1), vec2(0, 0), vec2(0,1), vec2(1, 0)},    {vec2(-1, 0), vec2(0,0), vec2(1, 0), vec2(0,  1)},      {vec2(-1,0), vec2(0, -1), vec2(0, 0), vec2(0, 1)}  },};// 绘制窗口的颜色变量vec4 white  = vec4(1.0, 1.0, 1.0, 1.0);
vec4 black  = vec4(0.0, 0.0, 0.0, 1.0);
vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
vec4 green = vec4(0.0, 1.0, 0.0, 1.0);
vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);
vec4 orange = vec4(1.0, 0.5, 0.0, 1.0);
vec4 pink = vec4(1.0, 0.75, 0.8, 1.0);
vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);
vec4 purple = vec4(0.8, 0.0, 0.8, 1.0);
vec4 bluegreen = vec4(0.0, 1.0, 1.0, 1.0);
vec4 CubeColor[] = { red,green,blue,orange,pink,yellow,purple,bluegreen };
// 当前方块的位置(以棋盘格的左下角为原点的坐标系)
vec2 tilepos = vec2(5, 19);// 布尔数组表示棋盘格的某位置是否被方块填充,即board[x][y] = true表示(x,y)处格子被填充。
// (以棋盘格的左下角为原点的坐标系)
bool board[10][20]; //用来记录每个格子的颜色
vec4 BoardColor[10][20];// 当棋盘格某些位置被方块填充之后,记录这些位置上被填充的颜色
vec4 boardcolours[1200];  //棋盘格 10*20*2 = 400 个三角形,每个三角形3个点,3*400=1200个点的颜色值需要记录GLuint locxsize;
GLuint locysize;GLuint vaoIDs[3];
GLuint vboIDs[6];//
// 修改棋盘格在pos位置的颜色为colour,并且更新对应的VBO
void changecellcolour(vec2 pos, vec4 colour)
{BoardColor[int(pos.x)][int(pos.y)] = colour;// 每个格子是个正方形,包含两个三角形,总共6个顶点,并在特定的位置赋上适当的颜色for (int i = 0; i < 6; i++)boardcolours[(int)(6*(10*pos.y + pos.x) + i)] = colour;vec4 newcolours[6] = {colour, colour, colour, colour, colour, colour};glBindBuffer(GL_ARRAY_BUFFER, vboIDs[3]);// 计算偏移量,在适当的位置赋上颜色int offset = 6 * sizeof(vec4) * (int)(10*pos.y + pos.x);glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(newcolours), newcolours);glBindBuffer(GL_ARRAY_BUFFER, 0);
}//
// 当前方块移动或者旋转时,更新VBO
void updatetile()
{glBindBuffer(GL_ARRAY_BUFFER, vboIDs[4]);// 每个方块包含四个格子for (int i = 0; i < 4; i++){// 计算格子的坐标值GLfloat x = tilepos.x + tile[i].x;GLfloat y = tilepos.y + tile[i].y;vec4 p1 = vec4(33.0 + (x * 33.0), 33.0 + (y * 33.0), .4, 1); vec4 p2 = vec4(33.0 + (x * 33.0), 66.0 + (y * 33.0), .4, 1);vec4 p3 = vec4(66.0 + (x * 33.0), 33.0 + (y * 33.0), .4, 1);vec4 p4 = vec4(66.0 + (x * 33.0), 66.0 + (y * 33.0), .4, 1);// 每个格子包含两个三角形,所以有6个顶点坐标vec4 newpoints[6] = {p1, p2, p3, p2, p3, p4};glBufferSubData(GL_ARRAY_BUFFER, i*6*sizeof(vec4), 6*sizeof(vec4), newpoints);}glBindVertexArray(0);
}//
// 设置当前方块为下一个即将出现的方块。在游戏开始的时候调用来创建一个初始的方块,
// 在游戏结束的时候判断,没有足够的空间来生成新的方块。
void newtile()
{//判断最上面两行的中间是否被填满,如果被填满说明无法再生成方块,游戏结束int flag = 0;for (int i = 18; i < 20; i++) {for (int j = 4; j < 7; j++) {if (board[j][i] == true)flag = 1;}}if (flag == 1) {cout << "游戏结束,请按下R键重新开始游戏,或者按下Q或Esc键退出游戏。"<<endl;gameover = true;return;}// 将新方块放于棋盘格的最上行中间位置并设置默认的旋转方向tilepos = vec2(5 , 19);rotation = 0;ShapeNum = (starttime+rand()) % 7;for (int i = 0; i < 4; i++){tile[i] = allRotationsLshape[ShapeNum][0][i];}updatetile();// 给新方块赋上颜色vec4 newcolours[24];ColorNum = (starttime+rand()) % 8;for (int i = 0; i < 24; i++)newcolours[i] = CubeColor[ColorNum];glBindBuffer(GL_ARRAY_BUFFER, vboIDs[5]);glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(newcolours), newcolours);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);
}//
// 游戏和OpenGL初始化
void init()
{std::cout << "欢迎来到俄罗斯方块游戏,接下来我来给您介绍游戏规则:" << endl;std::cout << "由小方块组成的不同形状的板块陆续从屏幕上方落下来,它们会自动下落,玩家通过调整板块的位置和方向,使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失,给新落下来的板块腾出空间,与此同时,玩家得到分数奖励。没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,玩家便告输,游戏结束。" << endl;std::cout << "按键操作:↑键旋转,↓键往下落,←键往左移,→键往右移,P键暂停或恢复游戏,R键重启游戏,Q或ESC键退出游戏。" << endl;std::cout << "接下来请操控小方块来获取更多的分数吧!" << endl;std::cout << "当前难度:" << Rank << endl;std::cout << "积分:" << Point << endl;// 初始化棋盘格,包含64个顶点坐标(总共32条线),并且每个顶点一个颜色值vec4 gridpoints[64];vec4 gridcolours[64];// 纵向线(10个格子所以11条线)for (int i = 0; i < 11; i++){gridpoints[2*i] = vec4((33.0 + (33.0 * i)), 33.0, 0, 1);gridpoints[2*i + 1] = vec4((33.0 + (33.0 * i)), 693.0, 0, 1);}// 水平线for (int i = 0; i < 21; i++){gridpoints[22 + 2*i] = vec4(33.0, (33.0 + (33.0 * i)), 0, 1);gridpoints[22 + 2*i + 1] = vec4(363.0, (33.0 + (33.0 * i)), 0, 1);}// 将所有线赋成白色for (int i = 0; i < 64; i++)gridcolours[i] = white;// 初始化棋盘格,并将没有被填充的格子设置成黑色vec4 boardpoints[1200];for (int i = 0; i < 1200; i++)boardcolours[i] = black;// 对每个格子,初始化6个顶点,表示两个三角形,绘制一个正方形格子for (int i = 0; i < 20; i++)for (int j = 0; j < 10; j++){vec4 p1 = vec4(33.0 + (j * 33.0), 33.0 + (i * 33.0), .5, 1);vec4 p2 = vec4(33.0 + (j * 33.0), 66.0 + (i * 33.0), .5, 1);vec4 p3 = vec4(66.0 + (j * 33.0), 33.0 + (i * 33.0), .5, 1);vec4 p4 = vec4(66.0 + (j * 33.0), 66.0 + (i * 33.0), .5, 1);boardpoints[6*(10*i + j)    ] = p1;boardpoints[6*(10*i + j) + 1] = p2;boardpoints[6*(10*i + j) + 2] = p3;boardpoints[6*(10*i + j) + 3] = p2;boardpoints[6*(10*i + j) + 4] = p3;boardpoints[6*(10*i + j) + 5] = p4;}// 将棋盘格所有位置的填充与否都设置为false(没有被填充)for (int i = 0; i < 10; i++)for (int j = 0; j < 20; j++) {board[i][j] = false;BoardColor[i][j] = black;//将所有方块的颜色初始化为黑色}// 载入着色器GLuint program = InitShader("vshader.glsl", "fshader.glsl");glUseProgram(program);locxsize = glGetUniformLocation(program, "xsize");locysize = glGetUniformLocation(program, "ysize");GLuint vPosition = glGetAttribLocation(program, "vPosition");GLuint vColor = glGetAttribLocation(program, "vColor");glGenVertexArrays(3, &vaoIDs[0]);// 棋盘格顶点glBindVertexArray(vaoIDs[0]);glGenBuffers(2, vboIDs);// 棋盘格顶点位置glBindBuffer(GL_ARRAY_BUFFER, vboIDs[0]);glBufferData(GL_ARRAY_BUFFER, 64*sizeof(vec4), gridpoints, GL_STATIC_DRAW);glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(vPosition);// 棋盘格顶点颜色glBindBuffer(GL_ARRAY_BUFFER, vboIDs[1]);glBufferData(GL_ARRAY_BUFFER, 64*sizeof(vec4), gridcolours, GL_STATIC_DRAW);glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(vColor);// 棋盘格每个格子  glBindVertexArray(vaoIDs[1]);glGenBuffers(2, &vboIDs[2]);// 棋盘格每个格子顶点位置glBindBuffer(GL_ARRAY_BUFFER, vboIDs[2]);glBufferData(GL_ARRAY_BUFFER, 1200*sizeof(vec4), boardpoints, GL_STATIC_DRAW);glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(vPosition);// 棋盘格每个格子顶点颜色glBindBuffer(GL_ARRAY_BUFFER, vboIDs[3]);glBufferData(GL_ARRAY_BUFFER, 1200*sizeof(vec4), boardcolours, GL_DYNAMIC_DRAW);glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(vColor);// 当前方块glBindVertexArray(vaoIDs[2]);glGenBuffers(2, &vboIDs[4]);// 当前方块顶点位置glBindBuffer(GL_ARRAY_BUFFER, vboIDs[4]);glBufferData(GL_ARRAY_BUFFER, 24*sizeof(vec4), NULL, GL_DYNAMIC_DRAW);glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(vPosition);// 当前方块顶点颜色glBindBuffer(GL_ARRAY_BUFFER, vboIDs[5]);glBufferData(GL_ARRAY_BUFFER, 24*sizeof(vec4), NULL, GL_DYNAMIC_DRAW);glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(vColor);glBindVertexArray(0);glClearColor(0, 0, 0, 0);// 游戏初始化newtile();starttime = glutGet(GLUT_ELAPSED_TIME);
}//
// 检查在cellpos位置的格子是否被填充或者是否在棋盘格的边界范围内。
bool checkvalid(vec2 cellpos)
{if((cellpos.x >=0) && (cellpos.x < 10) && (cellpos.y >= 0)       //判断是否在窗口范围内&& (cellpos.y < 20)&& (board[(int)cellpos.x][(int)cellpos.y]==false))//判断该位置是否已被填充return true;elsereturn false;
}//
// 判断在棋盘上有足够空间的情况下旋转当前方块
void rotate()
{      // 计算得到下一个旋转方向int nextrotation = (rotation + 1) % 4;// 检查当前旋转之后的位置的有效性if (checkvalid((allRotationsLshape[ShapeNum][nextrotation][0]) + tilepos)&& checkvalid((allRotationsLshape[ShapeNum][nextrotation][1]) + tilepos)&& checkvalid((allRotationsLshape[ShapeNum][nextrotation][2]) + tilepos)&& checkvalid((allRotationsLshape[ShapeNum][nextrotation][3]) + tilepos)){// 更新旋转,将当前方块设置为旋转之后的方块rotation = nextrotation;for (int i = 0; i < 4; i++)tile[i] = allRotationsLshape[ShapeNum][rotation][i];updatetile();}
}//
// 检查棋盘格在row行有没有被填充满//传入某一行,判断这一行是否被填满,如果被填满需要:消除这行,上一行往下掉,增加积分
void checkfullrow(int row)
{int flag = 1;int i = row;for (int j = 0; j < 10; j++) {if (board[j][i] == false) {flag = 0;//这一行有格子没被填满则说明不能消行}}if (flag == 1) {Point += 10;std::cout << "积分:" << Point << endl;//积分数量每增加50,则难度自动增加,使得方块下落时间变长if (Point >= Rank * 20) {Rank++;DownTime /= 2;//调整下落时间间隔DownNum*= 2;//这里让DoneNum*=2是和判断是否下落的方式有关,//为了让下落时间间隔和下落数量的乘积与之前相同cout << "当前难度:" << Rank<<endl;}for (int j = 0; j < 10; j++) {changecellcolour(vec2(j, i), black);//颜色全部变黑board[j][i] = false;//这一行全部变成未填满状态}for (int k = row + 1; k < 20; k++) {for (int j = 0; j < 10; j++) {if (board[j][k] == true) {//如果上一行有方块,则需要往下掉一行board[j][k] = false;//将上一行置为未填满状态changecellcolour(vec2(j, k - 1), BoardColor[j][k]);//下一行对应位置的颜色变成上一行对应位置的颜色changecellcolour(vec2(j, k), black);//上一行清空为黑色board[j][k-1] = true;//下一行对应位置设置为填满状态}}}}}//
// 放置当前方块,并且更新棋盘格对应位置顶点的颜色VBOvoid settile()
{// 每个格子for (int i = 0; i < 4; i++){// 获取格子在棋盘格上的坐标int x = (tile[i] + tilepos).x;int y = (tile[i] + tilepos).y;// 将格子对应在棋盘格上的位置设置为填充board[x][y] = true;// 并将相应位置的颜色修改changecellcolour(vec2(x,y), CubeColor[ColorNum]);}for (int i = 0; i < 4; i++) {int y = (tile[i] + tilepos).y;checkfullrow(y);//这个物体的四个方块所处的y轴都需要判断是否被填满}}//
// 给定位置(x,y),移动方块。有效的移动值为(-1,0),(1,0),(0,-1),分别对应于向
// 左,向右和向下移动。如果移动成功,返回值为true,反之为false。
bool movetile(vec2 direction)
{// 计算移动之后的方块的位置坐标vec2 newtilepos[4];for (int i = 0; i < 4; i++)newtilepos[i] = tile[i] + tilepos + direction;// 检查移动之后的有效性if (checkvalid(newtilepos[0]) && checkvalid(newtilepos[1])&& checkvalid(newtilepos[2])&& checkvalid(newtilepos[3])){// 有效:移动该方块tilepos.x = tilepos.x + direction.x;tilepos.y = tilepos.y + direction.y;updatetile();return true;}return false;
}//
// 重新启动游戏
void restart()
{//先将所有格子清空for (int i = 0; i < 10; i++) {for (int j = 0; j < 20; j++) {board[i][j] = false;BoardColor[i][j] = black;changecellcolour(vec2(i, j), black);} }starttime= glutGet(GLUT_ELAPSED_TIME);std::cout << "您已重启游戏,游戏还原成初始模样,积分已清零。"<<endl;Point = 0;std::cout << "积分:" << Point << endl;Rank = 1;DownTime = 1000;//难度和下落时间重新设立DownNum = 0;pause = false;//设置游戏为运行状态gameover = false;//结束游戏的标志置为falsenewtile();
}//
// 游戏渲染部分
void display()
{glClear(GL_COLOR_BUFFER_BIT);glUniform1i(locxsize, xsize);glUniform1i(locysize, ysize);glBindVertexArray(vaoIDs[1]);glDrawArrays(GL_TRIANGLES, 0, 1200); // 绘制棋盘格 (10*20*2 = 400 个三角形)glBindVertexArray(vaoIDs[2]);glDrawArrays(GL_TRIANGLES, 0, 24);  // 绘制当前方块 (8 个三角形)glBindVertexArray(vaoIDs[0]);glDrawArrays(GL_LINES, 0, 64);       // 绘制棋盘格的线glutSwapBuffers();
}//
// 在窗口被拉伸的时候,控制棋盘格的大小,使之保持固定的比例。
void reshape(GLsizei w, GLsizei h)
{xsize = w;ysize = h;glViewport(0, 0, w, h);
}//
// 键盘响应事件中的特殊按键响应
void special(int key, int x, int y)
{if(!gameover&&pause==false){switch(key){case GLUT_KEY_UP:    // 向上按键旋转方块rotate();break;case GLUT_KEY_DOWN: // 向下按键移动方块if (!movetile(vec2(0, -1))){settile();newtile();}break;case GLUT_KEY_LEFT:  // 向左按键移动方块movetile(vec2(-1, 0));break;case GLUT_KEY_RIGHT: // 向右按键移动方块movetile(vec2(1, 0));break;}}
}//
// 键盘响应时间中的普通按键响应
void keyboard(unsigned char key, int x, int y)
{switch(key) {case 'p'://  'p' 键暂停游戏if (pause == false) {pause = true;std::cout << "您已暂停游戏" << endl;}else if (pause == true) {pause = false;std::cout << "您已恢复游戏" << endl;}break;case 033: // ESC键 和 'q' 键退出游戏std::cout << "您已退出游戏,欢迎下次再来玩。" << endl;exit(EXIT_SUCCESS);break;case 'q':std::cout << "您已退出游戏,欢迎下次再来玩。" << endl;exit (EXIT_SUCCESS);break;case 'r': // 'r' 键重启游戏restart();break;}glutPostRedisplay();
}//void idle(void)
{//idle函数会不断地执行,时间也会不断地增加,//因此在这里加入物块下落的操作nowTime = glutGet(GLUT_ELAPSED_TIME);//由于时间不断的增加,我们用时间是否大于下落数量乘以//下落间隔来判断是否要进行下落操作if (nowTime-starttime> DownNum * DownTime) {DownNum++;if (gameover == false&&pause==false) {if (!movetile(vec2(0, -1))){settile();newtile();}}}glutPostRedisplay();
}//int main(int argc, char **argv)
{glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);glutInitWindowSize(xsize, ysize);glutInitWindowPosition(680, 178);glutCreateWindow("Mid-Term-Skeleton-Code");glewInit();init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutSpecialFunc(special);glutKeyboardFunc(keyboard);glutIdleFunc(idle);glutMainLoop();return 0;
}

计算机图形学 期中大作业 俄罗斯方块相关推荐

  1. 深圳大学计算机图形学期末大作业——OpenGL glfw库实现简单的Minecraft游戏

    源代码: OpenGL大作业OpenCraft-其他文档类资源-CSDN下载 目录 1. OBJ文件读取 2. 物体渲染与纹理着色. 3. 相机变换的实现 4. 光照与阴影的实现 5. 阴影设计 6. ...

  2. 计算机图形学期末作业,计算机图形学期末大作业3D建模.doc

    文档介绍: 深圳大学实验报告课程名称:计算图形学 实验名称:3D建模和真实感图形绘制学院:计算机与软件学院专业:计算机科学与技术报告人:学号:班级:1同组人:无指导教师:周虹实验时间:2014年11. ...

  3. 计算机图形学在线作业,电子科大16秋《计算机图形学》在线作业3答案

    一.单选题(共 10 道试题,共 50 分.) 1.  在下列有关曲线和曲面概念的叙述语句中,错误的论述为____. . 实体模型和曲面造型是系统中常用的主要造型方法,曲面造型是用参数曲面描述来表示一 ...

  4. [XJTUSE]计算机图形学第二章作业,使用OpenGL编程实现DDA、中点画线和Bresenham算法和中点画圆法

    首先是Windows10 + Visual Studio 2019 搭建OpenGL环境可以查看如下链接: 萌新向!!!Windows10 + Visual Studio 2019 搭建OpenGL环 ...

  5. 计算机图形学在线作业,电子科大16秋《计算机图形学》在线作业1答案

    16秋<计算机图形学>在线作业1 一.单选题(共 10 道试题,共 50 分.) 1.  下列叙述中错误的是____. . 计算机图形处理中,除了应用到各种算法外,还经常会处理大量的图形方 ...

  6. java大作业私人管家系统_操作系统概念(Operating System Concepts)第十版期中大作业...

    更正: 第一题中,哲学家就餐问题中的哲学家的状态state[i]应属于临界区变量,是可能会产生读写冲突的,所以对其进行读写的时候均需要加一把互斥锁. 非常感谢不听不听不听的指正. ---------- ...

  7. 计算机图形学在线作业,电子科技16秋《计算机图形学》在线作业3 辅导资料

    16秋<计算机图形学>在线作业3 一.单选题(共 10 道试题,共 50 分.) 1. 在下列有关曲线和曲面概念的叙述语句中,错误的论述为____. . 实体模型和曲面造型是系统中常用的主 ...

  8. 上海电力学院计算机软件技术大作业,计算机网络应用设计 大作业报告.doc

    计算机网络应用设计 大作业报告 上 海 电 力 学 院 课程设计(大型作业)报告 设计名称 计算机网络应用课程设计 课程代码 1305312 院 (系) 电子与信息工程学院 专 业 通信工程 班 级 ...

  9. Web 编程期中大作业

    Web 编程期中大作业: node.js进行网页爬虫 前言 在做期中作业之前,我们已经学习了HTML,CSS,Node.js,javascript的相关知识,但这个项目还是令我感到一头雾水,不知从何下 ...

  10. 计算机英语大作业,计算机专业英语大作业.doc

    计算机专业英语大作业 Patterns Instruction in Software Engineering Abstract: The paper deals with a training sy ...

最新文章

  1. html滑动逐渐覆盖效果,创意jQuery和CSS3滑动覆盖响应式幻灯片特效
  2. Java 对象初始化的过程介绍
  3. VS2019错误提示:_CRT_SECURE_NO_WARNINGS的解决方法
  4. Java微信订单查询
  5. java 无法执行export 命令_模块中的export、import以及复合模式的使用方法
  6. zoj 1154 Niven numbers
  7. 北理工的石锅饭依然美味
  8. 关于idea maven ojdbc6.jar 报错问题
  9. Android测试总结
  10. 墨刀和axure使用经验分享
  11. 微信小程序毕业设计选题
  12. [转帖]rsync简介
  13. oracle form视频,深入浅出Oracle 之Form开发
  14. UI设计色彩模式选择
  15. 打开Xmind提示The contiolrator Userslwangappication DatalXMindlconfiquration-cathy win32-R3.79.2019120523
  16. 利用canvas画图片
  17. 【牛客网】华为机试题(00、C++版本)
  18. 在线教育工程结构(二)----在线教育工程结构
  19. 专硕学制悄然改变!大批高校专硕需要读三年!
  20. TCPDF生成PDF文件方法教程说明

热门文章

  1. 一网打尽:指针和数组
  2. win10安装SVN失败问题汇总
  3. 使用 React-Sketchapp
  4. 【计算机二级Python】模拟试卷第4套选择题
  5. 中关村GHOST WIN7 SP1旗舰版
  6. php搜索银行所在支行,多家银行宣布启动社区支行战略但风光不再
  7. OpenAi ChatGPT注册及使用教程
  8. 自学python的痛楚,来报团报吧
  9. 李彦宏创业12年解读:企业家精神改变工程师命运
  10. 【深度学习】Mask DINO四部曲—DETR潘多拉魔盒的正确打开方式