贪吃蛇系列!
Qt 学习之路 2(31):贪吃蛇游戏(1)
Qt 学习之路 2(32):贪吃蛇游戏(2)
Qt 学习之路 2(33):贪吃蛇游戏(3)
Qt 学习之路 2(34):贪吃蛇游戏(4)
ubuntu 16.04 + Qt 5.5.1 环境下,解决吃食物崩溃的方法:
scene.addItem(snake);
Food *a1 = new Food(0, -50);
scene.addItem(a1);
有待完善的地方:
1.wall;
2.暂停和继续;
3.难度,如调整蛇的移动速度,可以考虑关卡?
4.蛇往前进方向的反方向走会崩溃的bug。
Q&A:
1.MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
scene(new QGraphicsScene(this)),
view(new QGraphicsView(scene,this)),
game(new GameController(*scene,this))
MainWindow::MainWindow(QWidget *parent)这个在创建的时候就有但是后面那部分是干什么的?
这些是构造函数初始化列表,会在构造函数执行之前执行。
2.请问为什么要使用adjustViewSize()? 由于使用了resize(600, 600); 我把scene->setSceneRect(-100, -100, 200, 200);
改成scene->setSceneRect(-300, -300, 600, 600);
,TILE_SIZE = 10 改为TILE_SIZE = 30不就可以了吗?
放在 adjustViewSize() 槽中去执行,主要是为了避免在绘制没有完成之前就调整了大小,导致显示异常。因为我们的程序比较简单,绘制能够很快完成,但是对于一些很复杂的程序,绘制可能需要消耗很长时间,所以会放在槽中,在 singleSlot() 信号发出之后再调用。
3.请问
MainWindow.h里
class QGraphicsScene;
class QGraphicsView;
class GameController;
是什么作用 为什么要这样写?如果是Qt自带,加入头文件不就可以了?如果是自己声明那不是需要有类定义吗?或者是仅仅声明作用?
这是 C++ 的前置声明。加入头文件的问题是,如果头文件发生改变,所有 include 的文件都要重新编译。在大型项目中,这会消耗大量时间。使用前置声明则不存在这个问题。具体细节可以参考 C++ 相关内容。
4.mainwindow类里的成员变量GameController *game放在mainwindow类有什么作用呢,在mainwindow.cpp里也没有用到。
这个类作为整个游戏的控制器,在 MainWindow 里面只起到一个全局控制的作用(因为 MainWindow 相当于是全局单例)。目前在这里没有其它用处,不过在以后的扩展中,比如你需要增加暂停、重启等功能,就可以在 MainWindow 直接连接 GameController 的槽函数了。
5.给GameController安装过滤器时为什么调用scene的函数?过滤器到底是装在scene上的还是装在GameController上的?
首先,注意到我们的程序,过滤器是要作为 sence 的控制,监视的是 sence 接收到的键盘事件,因此过滤器是要安装在 sence 上面(这是过滤器安装的对象);第二,过滤器本身是由 controller 实现的,因此函数的参数是 this。总之,这是为一个对象(sence)安装另外一个对象(controller)实现的过滤器。
6.请问为什么要先painter->save()?
注意这里的 painter 指针是参数传进来的,也就是 painter 是系统回调时创建的,可能会被其它组件共用。这里是为了防止影响到其它组件的使用(考虑到 QPainter 是一个状态机),因此需要添加这两个语句。当然,因为我们的程序比较简单,没有类似情况,所以不会有影响,但是不能保证复杂情况下也没有影响。为谨慎起见,这里添加了保存状态的代码。