您的位置:首页 > 编程语言 > Qt开发

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

2016-05-06 00:37 435 查看
继续学习图形视图框架~

唔,因为要做游戏,游戏对象很多都需要持续的播放,所以把之前做的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
{

4000
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的图自己猜

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


原谅我表达能力差~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: