超抽象飞机大战——天翌版
一,场景设置
A. 在main函数中创建场景
//创建场景
QGraphicsScene * scene =new QGraphicsScene;
创建一个QGraphicsScene类的对象
B.场景滚动效果的实现
// 创建两个背景图片
QPixmap originalPixmap(":/images/rubbish/stone.png");
QPixmap scaledPixmap = originalPixmap.scaled(GameSetting::SceneWidth, GameSetting::SceneHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
QGraphicsPixmapItem *background1 = scene->addPixmap(scaledPixmap);
QGraphicsPixmapItem *background2 = scene->addPixmap(scaledPixmap);
background2->setY(-background2->pixmap().height());
- 创建两个背景图片,并将它们添加到场景中。
- 再将originalPixmap缩放到GameSetting::SceneWidthGameSetting::SceneHeight的大小。Qt::IgnoreAspectRatio参数表示在缩放时忽略原始图片的宽高比,Qt::SmoothTransformation参数表示使用平滑的缩放算法。
- background2->setY(-background2->pixmap().height());:将background2的y坐标设置为-background2->pixmap().height()。这意味着background2的顶部会被放置在场景的顶部之上,这样在开始时background2就不会被看到。这通常用于创建滚动背景的效果,当background1滚动到场景的底部时,background2就会滚动到场景的顶部,从而创建出无限滚动的背景的效果。
// 创建定时器,每隔一段时间就移动背景图片
QTimer *timer = new QTimer;
QObject::connect(timer, &QTimer::timeout, [=]() {
background1->setY(background1->y() + 1);
background2->setY(background2->y() + 1);
if (background1->y() >= 0) {
background2->setY(background1->y() - background2->pixmap().height());
}
if (background2->y() >= 0) {
background1->setY(background2->y() - background1->pixmap().height());
}
});
timer->start(1000 / 60); // 60 帧每秒
- 创建一个QTimer的对象
- 连接timer的timeout信号到一个匿名函数。这个匿名函数会在每次timer的timeout信号被触发时执行。
- 将background1和background2的y坐标向下移动1个单位。这会使得背景图片向下滚动。
- 检查background1和background2的y坐标是否已经到达或超过0。如果是,那么就将另一个背景图片的y坐标设置为当前背景图片的y坐标减去另一个背景图片的高度。这会使得另一个背景图片被放置在当前背景图片的上方,从而在当前背景图片滚动到底部时,另一个背景图片就会滚动到顶部,创建出无限滚动的背景的效果。
- 启动timer,并设置其超时时间为1000 / 60毫秒,也就是大约16.67毫秒。这意味着timer的timeout信号会每秒触发大约60次,也就是每秒更新60帧,从而创建出流畅的滚动效果。
C场景的大小设置
scene->setSceneRect(0,0,GameSetting::SceneWidth,GameSetting::SceneHeight);//设置场景高度和宽度
scene->setBackgroundBrush(QImage(":/images/rubbish/stone.png"));//背景源
定义场景的宽度和高度,这个游戏只有x轴和y轴,所以前两个参数就设置成0了
二,Player类的思路与实现
A.类的创建与继承
class Player :public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
public:
Player(QGraphicsItem *parent = nullptr);
// QGraphicsItem interface
protected:
virtual void keyPressEvent(QKeyEvent *event) override;//press
void keyReleaseEvent(QKeyEvent *event) override;//release
这里的Player之间继承QObject和QGraphicsPixmapItem。
B.按键的基本设置和按键连贯性的实现
如果只是单纯写按键后面加个功能的话,这样在游戏按键的时候就会有移动的适合卡帧,或者移动时按发子弹键会卡住的情况,为了解决这个问题,翌就使用了Qt的事件循环和信号槽机制。

1.按键连贯实现
创建QTimer对象
连接信号槽
keyRespondTimer = new QTimer(this); //构造函数中创建定时器对象,并连接信号槽
connect(keyRespondTimer, &QTimer::timeout, this, &Player::slotTimeOut);
设置按下按键的函数
void Player::keyPressEvent(QKeyEvent *event)
{
if(!event->isAutoRepeat()) //判断如果不是长按时自动触发的按下,就将key值加入容器
keys.append(event->key());
if(!keyRespondTimer->isActive()) //如果定时器不在运行,就启动一下
keyRespondTimer->start(4);
}
设置释放按键的函数
void Player::keyReleaseEvent(QKeyEvent *event){
if(!event->isAutoRepeat()) //判断如果不是长按时自动触发的释放,就将key值从容器中删除
keys.removeAll(event->key());
if(keys.isEmpty()) //容器空了,关闭定时器
keyRespondTimer



被折叠的 条评论
为什么被折叠?



