QT 图形视图框架之角色移动

继续学习图形视图框架~

唔,因为要做游戏,游戏对象很多都需要持续的播放,所以把之前做的Blast类抽出动画来。。。

Object.h

#ifndef OBJECT_H
#define OBJECT_H

#include <QGraphicsItem>
#include <QBasicTimer>

class Object:public QObject,public QGraphicsItem
{
    Q_OBJECT
public:
    Object();
    Object(const QString &FileName,const QPoint &Count,const bool &Direction=true);

    void setAnimationPixmap(const QList<QList<QPixmap>> Pixmap){m_Pixmap = Pixmap;}
    bool setAnimationPixmap(const QString &FileName, const QPoint &Count, const bool &Direction=true);
    bool addAnimationMovieFile(const QString &FileName);

    void start(const int &msec=150);
    void stop();

    void setState(const int &State){m_State = State;}
    bool isStop()const{return m_Timer->isActive();}
    bool isDestructible()const{return m_Destruction;}

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);

private:
    int m_State;
    int m_Index;
    bool m_Destruction;
    QBasicTimer *m_Timer;
    QList<QList<QPixmap>> m_Pixmap;

protected:
    void timerEvent(QTimerEvent *event);
};

#endif // OBJECT_H


Object.cpp

#include "object.h"
#include <QTimerEvent>
#include <QPainter>
#include <QMessageBox>
#include <QMovie>

Object::Object()
    :m_Index(0)
    ,m_State(0)
    ,m_Destruction(false)
{
    m_Timer = new QBasicTimer;
}

Object::Object(const QString &FileName, const QPoint &Count, const bool &Direction)
    :m_Index(0)
    ,m_State(0)
    ,m_Destruction(false)
{
        m_Timer = new QBasicTimer;
    if(setAnimationPixmap(FileName,Count,Direction))
    {
        QMessageBox::warning(NULL,u8"警告!",u8"加载图片失败",QMessageBox::Yes,QMessageBox::Yes);
        return;
    }
}

bool Object::setAnimationPixmap(const QString &FileName, const QPoint &Count, const bool &Direction)
{
    QPixmap *Pixmap = new QPixmap;

    if(!Pixmap->load(FileName))
        return true;

    const int &WidthCount = Count.x();
    const int &HeightCount = Count.y();
    int Width = Pixmap->width() / WidthCount;
    int Height = Pixmap->height() / HeightCount;
    if(Direction)
    {
        for(int y=0; y<HeightCount; y++)//从左向右拆分
        {
            m_Pixmap << QList<QPixmap>();
            for(int x=0; x<WidthCount; x++)
                m_Pixmap[y] << Pixmap->copy(x*Width,y*Height,Width, Height);
        }
    }
    else
    {
        for(int x=0; x<WidthCount; x++)//从上到下拆分
        {
            m_Pixmap << QList<QPixmap>();
            for(int y=0; y<HeightCount; y++)
                m_Pixmap[x] << Pixmap->copy(x*Width,y*Height,Width, Height);
        }
    }
    return false;
}

bool Object::addAnimationMovieFile(const QString &FileName)//抽出gif的帧
{
    QMovie *Movie = new QMovie(FileName);
    if(!Movie->frameCount())
        return true;

    m_Pixmap << QList<QPixmap>();
    const int Count = m_Pixmap.count()-1;
    do
    {
        m_Pixmap[Count] << Movie->currentPixmap();
    }while(Movie->jumpToNextFrame());

    return false;
}

void Object::start(const int &msec)
{
    m_Timer->start(msec,this);
}

void Object::stop()
{
    m_Index = 0;
    m_Timer->stop();
}

QRectF Object::boundingRect() const
{
    if(!m_Pixmap.count() )
        return QRectF();

    qreal penWidth = 1;
         return QRectF(-m_Pixmap[0][0].width()/2- penWidth / 2, -m_Pixmap[0][0].height()/2- penWidth / 2,
                       m_Pixmap[0][0].width() + penWidth, m_Pixmap[0][0].height() + penWidth);
}

void Object::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(widget);
    Q_UNUSED(option);

    if(!m_Pixmap.count() || m_State > m_Pixmap.count()-1)
        return;
    if(!m_Pixmap[m_State].count() || m_Index > m_Pixmap[m_State].count()-1)
        return;

    painter->drawPixmap(boundingRect().x()
                        ,boundingRect().y()
                        ,boundingRect().width()
                        ,boundingRect().height()
                        ,m_Pixmap[m_State][m_Index]);
    this->update();
}

void Object::timerEvent(QTimerEvent *event)
{
    if(!m_Pixmap.count() || m_State > m_Pixmap.count()-1)
        return;
    if(!m_Pixmap[m_State].count() || m_Index > m_Pixmap[m_State].count()-1)
        return;

    if(event->timerId() == m_Timer->timerId())
    {
        m_Index = ++m_Index % m_Pixmap[m_State].count();
    }
}



现在就来做一下移动类,首先继承上面的类

GameCharacter.h

#ifndef GAMECHARACTER_H
#define GAMECHARACTER_H

#include "object.h"
#include <QTimer>
class GameCharacter:public Object
{
public:
    GameCharacter();

    void moveLeft(const int &Index);
    void moveRight(const int &Index);
    void moveUp(const int &Index);
    void moveDown(const int &Index);
    void addBubble(){m_Bubble++;}
    void delBubble(){if(m_Bubble)m_Bubble--;}
    int getBubbleNumber()const{return m_Bubble;}

    void setMsec(const int &Mesc){m_Msec = Mesc;}
    void stopMove(){stop();m_MoveTimer->stop();}

private slots:
    void timeOut();

private:
    int m_Msec;
    int m_Speed;
    int m_xSpeed;
    int m_ySpeed;
    int m_Bubble;
    QTimer *m_MoveTimer;

    void startMove(const int &Index);
};

#endif // GAMECHARACTER_H


GameCharacter.cpp

#include "gamecharacter.h"
#include <QGraphicsScene>

GameCharacter::GameCharacter()
    :m_Speed(5)
    ,m_Msec(10)
    ,m_Bubble(1)
{
    m_MoveTimer = new QTimer(this);
    connect( m_MoveTimer, &QTimer::timeout,this,&GameCharacter::timeOut);
}

void GameCharacter::moveLeft(const int &Index)
{
    m_xSpeed = -m_Speed;
    m_ySpeed = 0;
    startMove(Index);
}

void GameCharacter::moveRight(const int &Index)
{
    m_xSpeed = m_Speed;
    m_ySpeed = 0;
    startMove(Index);
}

void GameCharacter::moveUp(const int &Index)
{
    m_xSpeed = 0;
    m_ySpeed = -m_Speed;
    startMove(Index);
}

void GameCharacter::moveDown(const int &Index)
{
    m_xSpeed = 0;
    m_ySpeed = m_Speed;
    startMove(Index);
}

void GameCharacter::startMove(const int &Index)
{
    if(!m_MoveTimer->isActive())
        m_MoveTimer->start(m_Msec);
    if(!isStop())
        start();
    setState(Index);
}

void GameCharacter::timeOut()
{
     moveBy(m_xSpeed,m_ySpeed);
}

唔相信这个类非常易于理解,其实就是利用时间上下左右移动而已,来试试

role = new GameCharacter;
    role->setAnimationPixmap(u8"E:/code/QThang/QQT素材/走图/Done_body13001_walk.png",QPoint(4,4));
    role->setMsec(10);
    scene->addItem(role);

void QThang::keyPressEvent(QKeyEvent *event)
{
    keyEvent(event);
    QGraphicsView::keyPressEvent(event);
}

void QThang::keyReleaseEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    case Qt::Key_Space:
        putDown();
    }
     keyEvent(event);
    if(!event->isAutoRepeat())
    {
        role->stopMove();
    }
    QGraphicsView::keyReleaseEvent(event);
}

void QThang::keyEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    case Qt::Key_Left:
        role->moveLeft(1);
        break;
    case Qt::Key_Right:
        role->moveRight(2);
        break;
    case Qt::Key_Up:
        role->moveUp(3);
        break;
    case Qt::Key_Down:
        role->moveDown(0);
    }
}

至于role->moveLeft(1);这个0-3是什么

请结合http://blog.csdn.net/qq_17813937/article/details/51291216的图自己猜


相信到这里运行后肯定会发现有时候移动有时候很流畅,有时候会卡着在哪里,至于怎么解决。。。。抱歉我还没找到,如果你找到了方法,并且愿意公开,期待你的评论


大笑原谅我表达能力差~

你可能感兴趣的:(游戏,移动,qt,图形视图框架)