「C/C++」有手就能学会系列
小白手写游戏经典-俄罗斯方块 #C语言初学#
儿时经典的掌机游戏,你还记得吗?
花式消行技巧,荣耀伙伴的最高纪录,仿佛又回到了纯真的战斗时代。
致敬俄罗斯方块之父“阿列克谢·帕基特诺夫”,一起实现这个传奇经典游戏吧!
当时他耗费了6天时间,今天的你需要几天呢?
在我们的B站中有详细的讲解视频,以及相关的素材,只需90分钟就能实现这个经典!
>>>>私信我获得详细教程地址
先看一下游戏效果:
搭建环境
首先,我们来搭建开发环境:
VC++2010或以上版本,推荐使用VS2015以上版本。下载SFML库,可以到SFML官网下载,或者联系作者。SFML是一个非常方便的工具库,我下载的是SFML2.5.1 32位版本(32位可以在32位和64位平台运行)下载后解压到电脑的任意位置,比如:C:SFMLSFML-2.5.1_32bit
3.使用VC++或者VS创建一个空项目,然后配置头文件以及库文件。
配置使用的库文件:
sfml-window-d.lib
sfml-system-d.lib
sfml-graphics-d.lib
sfml-audio-d.lib
准备游戏素材
准备好游戏的素材(图片,背景音乐,音效音乐, 字体文件)。
背景图片如下,也可以更换成自己喜欢的其他图片。
游戏区域四周的方框图片,这个图片可以让游戏界面更好看哦,也可以省略不要。
俄罗斯方块的纹理图片如下。在代码中,我们会按照小方块的大小进行切割,得到多个不同颜色的小方块。
游戏逻辑结构
搭建游戏框架
先写好游戏框架:
#include <SFML/Graphics.hpp>#include <SFML/Audio.hpp>#include <time.h>using namespace sf;void keyEvent(RenderWindow * window) {Event e;// pollEvent 从事件队列中取出一个事件while (window->pollEvent(e)){if (e.type == Event::Closed)window->close();if (e.type == Event::KeyPressed) {switch (e.key.code) {case Keyboard::Up:break;case Keyboard::Left:break;case Keyboard::Right:break;default:break;}}}}int main(){srand(time(0));// 创建窗口RenderWindow window(VideoMode(320, 416), //窗口大小"Rock"); //标题// 创建表示图片的精灵Texture t2, t3;t2.loadFromFile("images/bg2.jpg");t3.loadFromFile("images/frame.png");Sprite spriteBg(t2);Sprite spriteFrame(t3);while (window.isOpen()){keyEvent(&window);window.clear(Color::White);window.draw(spriteBg);window.draw(spriteFrame);window.display();}return 0;}
运行后,效果如下:
俄罗斯方块的设计
俄罗斯方块的实现,有很多实现方式,最简单的方式是使用多个二位数组,每个二位数组来表示一种方块。不过有更高效的实现方式,使用一个二维数组来表示多种俄罗斯方块。
const int ROW_COUNT = 20;const int COL_COUNT = 10;int blocks[7][4] = {1,3,5,7, // I2,4,5,7, // Z 1型3,5,4,6, // Z 2型3,5,4,7, // T2,3,5,7, // L3,5,7,6, // J2,3,4,5, // 田};
把方块信息转换成位置坐标
所以对于“I”字型的方块,{1,3,5,7} 就使用4个坐标来表示,(1,0),(1,1),(1,2),(1,3)
struct Point {int x, y;} curBlock[4], BakBlock[4];......for (int i = 0; i < 4; i++){curBlock[i].x = blocks[n][i] % 2;curBlock[i].y = blocks[n][i] / 2;}
俄罗斯方块的旋转
旋转效果,最简单的方式是,为每一种方向使用一个二位数组。我们使用最灵活的方式,对俄罗斯方块进行旋转处理。
直接使用通用的数学公式,就可以直接得到旋转后的坐标位置。
直接使用数学公式,平面中,一个点(x,y)绕任意点(dx,dy)顺时针旋转a度后的坐标
xx= (x - dx)*cos(-a) - (y - dy)*sin(-a) + dx ;
yy= (x - dx)*sin(-a) + (y - dy)*cos(-a) +dy ;
平面中,一个点(x,y)绕任意点(dx,dy)逆时针旋转a度后的坐标
xx= (x - dx)*cos(a) - (y - dy)*sin(a) + dx ;
yy= (x - dx)*sin(a) + (y - dy)*cos(a) +dy ;
我们需要的是逆时针旋转90度代入公式,得:
Point p = curBlock[1]; //center of rotationfor (int i = 0; i < 4; i++){struct Point tmp = curBlock[i];curBlock[i].x = p.x - tmp.y + p.y;curBlock[i].y = p.y + tmp.x - p.x;}
使用时钟控制自由下落
每次循环开始的时候,就累加时间,如果时间超过延时间隔,就调用自定义的降落函数drop()
......while (window.isOpen()){float time = clock.getElapsedTime().asSeconds();clock.restart(); //计时器重启及时timer += time;keyEvent(&window);if (timer > delay) {drop(); //下降一个位置timer = 0;}.....}
游戏方块的渲染
消行的实现
从底部向上逐行扫描。
撸码捷径
边看视频边写代码,遇到问题,私信小编。
>>>>私信我获得详细教程地址
举报/反馈