Qt 在UI界面通过键盘控制飞机上下左右移动

本项目资源文件借鉴了此篇文章内容,https://blog.csdn.net/weixin_42756970/article/details/108975622python版本的雷电小游戏。


前言

通过Qt做一个UI界面控制飞机上下左右移动的小实验,通过按下WSAD四个键盘按键,实现飞机的移动,并且在飞机向上移动的状态时,添加飞机尾焰的视觉效果。
本实验的主要思路是通过在GUI界面类Widget类中,重写keyPressEvent、keyReleaseEvent进行相关的判断操作,并且重写paintEvent,设定一个定时器,到设定的时间时,不断地调用update()函数进行图形界面的重绘。


效果

实验效果如下图所示,通过键盘WSAD来控制红色小飞机的移动。
通过Qt做一个UI界面控制飞机上下左右移动的小实验,通过按下WSAD四个键盘按键,实现飞机的移动,并且在飞机向上移动的状态时,添加飞机尾焰的视觉效果。


资源下载

本次实验全部代码请至https://download.csdn.net/download/wang_chao118/86427796下载。


核心代码

分开定义飞机类heroPlane以及GUI界面类Widget。

heroplane.h

#ifndef HEROPLANE_H
#define HEROPLANE_H

#include <QPixmap>

class heroPlane
{
public:
    heroPlane();
	//飞机原始图片
    QPixmap plane_pic;
    //向左移动时的飞机图片
    QPixmap plane_pic_moveleft;
    //向右移动时的飞机图片
    QPixmap plane_pic_moveright;
    //尾焰图片
    QPixmap air;
	//飞机当前坐标
    int m_X;
    int m_Y;
};

#endif // HEROPLANE_H

heroplane.cpp

#include "heroplane.h"
#include "config.h"

heroPlane::heroPlane()
{	
	//加载飞机图片
    plane_pic.load(":/hero.png");
    plane_pic_moveleft = plane_pic.copy(198,0,318-255,87);
    plane_pic_moveright = plane_pic.copy(53,0,318-255,87);
    plane_pic = plane_pic.copy(120, 0, 318 - 242, 87);

    air.load(":/air.png");
    air = air.copy(80, 0, 55, 65);

    //初始化坐标
    m_X = GAME_WIDTH * 0.5 - plane_pic.width() *0.5;
    m_Y = GAME_HEIGHT - plane_pic.height();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <QDebug>
#include <QPainter>
#include <QTimer>
#include "heroplane.h"
#include "config.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void keyPressEvent(QKeyEvent * event);
    void keyReleaseEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent *event);
    void judgekey();

private:
    Ui::Widget *ui;
    heroPlane *hero;
    QTimer *timer;
	//按键标志位,用于判断是否有按键按下
    bool keypressflag;
    //按键种类标志,用于判断是WSAD中的哪个
    int keyflag;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setFixedSize(GAME_WIDTH, GAME_HEIGHT);
    keypressflag = false;
    //实例化一个飞机对象
    hero = new heroPlane;
	//设置重绘速率,此处为每5ms重绘一次界面
    timer = new QTimer(this);
    //每次到时间就调用update()函数,update()函数将调用paintEvent()
    connect(timer,SIGNAL(timeout()),this,SLOT(update()));
    timer->start(5);

}

Widget::~Widget()
{
    delete ui;
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    qDebug()<<event->key();
	//判断按键种类
    switch(event->key())
    {

    case Qt::Key_W:
    	//有按键按下即将按键标志位置1
        keypressflag = true;
        //设置按键种类标志位
        keyflag = 1;
        return;

    case Qt::Key_S:
        keypressflag = true;
        keyflag = 2;
        return;

    case Qt::Key_A:
        keypressflag = true;
        keyflag = 3;
        return;

    case Qt::Key_D:
        keypressflag = true;
        keyflag = 4;
        return;
    }
}

void Widget::keyReleaseEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    //有按键松开时即将按键标志位置0
    case Qt::Key_W:
        keypressflag = false;
        return;

    case Qt::Key_S:
        keypressflag = false;
        return;

    case Qt::Key_A:
        keypressflag = false;
        return;

    case Qt::Key_D:
        keypressflag = false;
        return;
    }
}

//界面绘制事件
void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    if(keypressflag)
    {	
    //判断是哪个键按下了,绘制对应的图片
        judgekey();
    }
    else
    {
        QPainter painter(this);
        painter.drawPixmap(hero->m_X,hero->m_Y,hero->plane_pic);
    }
//    qDebug()<<"keypressflag: "<<keypressflag;
}

void Widget::judgekey()
{
    QPainter painter(this);
    switch(keyflag)
    {
    case 1:
    //设置飞机的坐标值,绘制向上移动的飞机
        hero->m_Y = (hero->m_Y - 1 < 0) ? hero->m_Y : hero->m_Y - 1;
        painter.drawPixmap(hero->m_X,hero->m_Y,hero->plane_pic);
        //绘制尾焰图形
        painter.drawPixmap(hero->m_X+8,hero->m_Y + 80,hero->air);
        return;

    case 2:
        hero->m_Y = (hero->m_Y + 1 + hero->plane_pic.height() > GAME_HEIGHT) ? hero->m_Y : hero->m_Y + 1;
        painter.drawPixmap(hero->m_X,hero->m_Y,hero->plane_pic);
        return;

    case 3:
        hero->m_X = (hero->m_X - 1 < 0) ? hero->m_X : hero->m_X - 1;
        painter.drawPixmap(hero->m_X,hero->m_Y,hero->plane_pic_moveleft);
        return;

    case 4:
        hero->m_X = (hero->m_X + 1 + hero->plane_pic.width() > GAME_WIDTH) ? hero->m_X : hero->m_X + 1;
        painter.drawPixmap(hero->m_X,hero->m_Y,hero->plane_pic_moveright);
        return;
    }
}

资源下载

本次实验全部代码请至https://download.csdn.net/download/wang_chao118/86427796下载。

遗留问题

Qt按键事件中的相应问题:
(1)Qt按键在长按状态下会反复调用keyPressEvent以及keyReleaseEvent,且如果一直在长按状态下时,第一次的keyPressEvent与第二次的keyPressEvent之间有一定间隔时间,导致的现象就是,如果直接在keyPressEvent函数中直接设定飞机的位置的话,将会产生一种“停顿”的现象,为了避免这种现象,本案例在Widget类中引入了一个keypressflag来判断按键是否按下,只要有按键按下就开始重绘界面,直到有keyReleaseEvent后停止重绘界面,解决了“停顿”现象。
(2)本案例稍有缺陷,如果同时按下多个按键,即同时按下W及A按键、按下多个按键,然后再松开某个按键时,飞机的运行状态不明确,或产生不运动的现象。

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Qt控制小车的上下左右移动,你需要使用Qt的图形界面和事件处理机制。以下是一个简单的示例代码,可以用来控制小车的移动。 首先,你需要创建一个QWidget类,这是一个Qt的基本窗口组件。然后,你可以在这个类中实现一些事件处理函数,例如keyPressEvent()和paintEvent()。keyPressEvent()函数可以用来处理按键事件,而paintEvent()函数可以用来绘制小车。 下面是一个简单的示例代码,用于控制小车的移动: ```cpp #include <QKeyEvent> #include <QWidget> #include <QPainter> class Car : public QWidget { public: Car(QWidget *parent = nullptr) : QWidget(parent) { x = 0; y = 0; width = 50; height = 50; } protected: void keyPressEvent(QKeyEvent *event) override { int step = 10; switch (event->key()) { case Qt::Key_Up: y -= step; break; case Qt::Key_Down: y += step; break; case Qt::Key_Left: x -= step; break; case Qt::Key_Right: x += step; break; default: break; } update(); // 重新绘制小车 } void paintEvent(QPaintEvent *event) override { QPainter painter(this); painter.fillRect(x, y, width, height, Qt::red); } private: int x; int y; int width; int height; }; ``` 在上面的代码中,我们创建了一个名为Car的QWidget类,并在构造函数中初始化了小车的位置和大小。然后,我们重写了keyPressEvent()函数,根据按下的按键来移动小车,并调用了update()函数来重新绘制小车。最后,我们重写了paintEvent()函数,用红色填充小车的矩形区域。 你可以在主函数中创建一个Car对象,并将其显示在窗口中,例如: ```cpp #include <QApplication> int main(int argc, char *argv[]) { QApplication app(argc, argv); Car car; car.show(); return app.exec(); } ``` 这样,你就可以使用方向键来控制小车的移动了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wang_chao118

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值