QT如何使用setPixmap skin.copy()来做动画?

时间:2015-07-24 16:17:31

标签: c++ qt animation

我想在我的应用程序中做一些动画。我有一个小行星,当他向右移动时,动画向右移动,当他向右移动动画时向右移动, 角度在0到360°之间。 我已经添加了瓷砖,为您解释如何完美切割它。 我在课堂上有一个整数,其数字为0和34(图像上的小行星)我减少-1或在每个动画中为此变量添加+1。

为小行星设置动画的方法:

void Asteroid::animation(){
    int x = 1; 
    int y = 1;
    int width = 5;
    int height = 5;
    // what should I add here?    

    if(this->angle >= 0 && this->angle < 180){
        // cut image go to the right
        setPixmap(this->skin.copy(x,y,width,height));

        this->frame++;
        if(frame > 34) this->frame = 1;
    } else {
        // cut image go to the left
        setPixmap(this->skin.copy(x,y,width,height));

        this->frame--;
        if(frame < 1) this->frame = 34;
    }
}

skin像素图的内容:

Asteroids skin

接口

#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPoint>
#include <QVector>
#include <QPixmap>
#include <QString>
#include <QTimer>
#include <QObject>
#include <time.h>
#include <QtCore/qmath.h>

#include "SettingsAsteroid.h"

class Asteroid : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT

    // Animation
    QPixmap skin;
    int frame; // 32 images

    // Data
    int speed;
    int size;
    int pv;
    float angle;

public:  
    Asteroid(int size);
    Asteroid(QPointF position, int size);
    ~Asteroid();

    int getPosX();
    int getPosY();

    void setPosX(int newPos);
    void setPosY(int newPos);

    int getSpeed();
    int getSize();
    int getPV();
    int getAngle();

    // météorite détruite
    void destroyed();

    // toucher par un tir
    void touched(int damage);

    bool isDestroyed();

private slots:
    // mouvement de la météorite
    void move();

    // animation de la météorite
    void animation();

signals:
    //void notKilled();

    // transmet la taille du météorite détruit
    void killed(int);
};

实施

#include "Asteroid.h"

Asteroid::Asteroid(int size)
{
    this->skin = QPixmap(SettingsAsteroid::getRandomSkin());
    this->speed = SettingsAsteroid::getRandomSpeed(4,8);
    this->pv = SettingsAsteroid::getPV(size);
    this->angle = SettingsAsteroid::getRandomAngle();
    this->frame = 1;

    // Position de départ random
    QPointF position = QPointF(SettingsAsteroid::getRandomStartPosition());
    this->setPos(position.x(), position.y());

    this->size = size;

    // mouvement de l'astéroide
    QTimer* timer2 = new QTimer();
    connect(timer2,SIGNAL(timeout()),this,SLOT(move()));
    timer2->start(this->speed);

    // animation de l'astéroide
    QTimer* timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(animation()));
    timer->start(100);
}

Asteroid::Asteroid(QPointF position, int size)
{
    this->skin = QPixmap(SettingsAsteroid::getRandomSkin());
    this->speed = SettingsAsteroid::getRandomSpeed(4,8);
    this->pv = SettingsAsteroid::getPV(size);
    this->angle = SettingsAsteroid::getRandomAngle();
    this->frame = 1;


    this->setPos(position.x(), position.y());

    this->size = size;

    QTimer* timer2 = new QTimer();
    connect(timer2,SIGNAL(timeout()),this,SLOT(move()));
    timer2->start(this->speed);

    //Decoupe sprite et anmiation
    QTimer* timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(animation()));
    timer->start(150);
}

Asteroid::~Asteroid()
{
}

int Asteroid::getPosX(){
    return this->pos().x();
}

int Asteroid::getPosY(){
    return this->pos().y();
}

void Asteroid::setPosX(int newPos){
    this->setPos(newPos, this->pos().y());
}

void Asteroid::setPosY(int newPos){
    this->setPos(this->pos().x(), newPos);
}

int Asteroid::getSpeed(){
    return this->speed;
}

int Asteroid::getSize(){
    return this->size;
}

int Asteroid::getPV(){
    return this->pv;
}

int Asteroid::getAngle(){
    return this->angle;
}

bool Asteroid::isDestroyed(){

    if(pv > 0) return false;
    else return true;
}

void Asteroid::destroyed(){
    // AVERTIR CLASSE PRINCIPALE QUE DETRUIT
}

void Asteroid::touched(int damage){
    this->pv -= damage;
    if(pv<=0) destroyed();
}

void Asteroid::move(){
    double dx = getSpeed() * qCos(qDegreesToRadians(angle)) ;
    double dy = getSpeed() * qSin(qDegreesToRadians(angle)) ;

    setPos(QPointF(getPosX() + dx, getPosY() + dy)) ;

    // place la météorite de l'autre coté de la scène
    if (getPosX()<=0) setPosX(799);
    else if (getPosY()<=0) setPosY(659);
    else if (getPosX()>= 800) setPosX(1);
    else if (getPosY()>= 600) setPosY(1);
}

void Asteroid::animation(){
    // what add here?
    int x = 1;
    int y = 1;
    int width = 5;
    int height = 5;

    if(this->angle >= 0 && this->angle < 180){
        // cut image go to the right
        setPixmap(this->skin.copy(x,y,width,height));

        this->frame++;
        if(frame > 34) this->frame = 1;
    } else {
        // cut image go to the left
        setPixmap(this->skin.copy(x,y,width,height));
        this->frame--;
        if(frame < 1) this->frame = 34;
    }
}

角度是场景中小行星的方向。将有一艘宇宙飞船应该摧毁这颗小行星。我想制作在场景中移动的小行星的动画片

1 个答案:

答案 0 :(得分:1)

假设皮肤中的小行星图像是方形的,您可以按照以下步骤进行操作。

你的皮肤只有32件,而不是34件,BTW。

void Asteroid::animation() {
  int step = skin.height();
  int N = skin.width() / step; // Number of images in the skin.
  Q_ASSERT(skin.width() % step == 0); // ensure proper format of the skin

  if (angle >= 0 && angle < 180) {    
    frame ++;
    if (frame > N) frame -= N;
  } else {
    frame --;
    if (frame < 1) frame += N; 
  }

  int x = (frame - 1) * step;
  setPixmap(skin.copy(x, 0, step, step));
}