如何在不使用动画的情况下停止qgraphicsobject对象

How to stop an object of QGraphicsObjcet without using animation?

本文关键字:情况下 qgraphicsobject 对象 动画      更新时间:2023-10-16

在这个程序中,我有一个继承QGraphicsObject的类。这个对象(马里奥)向前走,回去跳。为了这个任务,我改变了马里奥的坐标。但我有个问题。我想让它在与砖块碰撞时停止。虽然我不使用QPropertyAnimation如何停止这个项目。

extern mario* _mario=new mario;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
  size_of_plane_y=600;
  size_of_plane_x=2000;
  view=new QGraphicsView;
  scene=new QGraphicsScene;
  rec=new QGraphicsRectItem;
  setCentralWidget(view);
  view->setScene(scene);
  scene->setSceneRect(0,0,size_of_plane_x,size_of_plane_y);
  scene->addRect(scene->sceneRect());
  x_scene=0;
  y_scene=0;
  int tmpb=8*30+120+10*30+120;
  int tmpb2=10*30+120+8*30+120;
  int firstb=100;
  int firstb2=100+8*30+120;
  for(int i=0;i<3;i++)
  {
    _brick=new brick(0,firstb,size_of_plane_y-180);
    scene->addItem(_brick);
    _brick2=new brick2(0,firstb2,size_of_plane_y-180);
    scene->addItem(_brick2);
    firstb+=tmpb;
    firstb2+=tmpb2;
  }
  timer1=new QTimer(this);
  timer1->setInterval(500);
  connect(timer1,SIGNAL(timeout()),this,SLOT(up()));
};
void MainWindow::keyPressEvent(QKeyEvent *k)
{
  switch (k->key())
  {
    case Qt::Key_J:
    {
      forward();
      break;
    }
    case Qt::Key_Z:
    {
      timer1->start();
      break;
    }
    case Qt::Key_F:
    {
       back();
       break;
    }
    default:
      break;
  }
}
void MainWindow::forward()
{
   if(ismovepossible(_mario->pos().x()+50,_mario->pos().y())==true)
   {
    _mario->setX(_mario->pos().x()+50);
    scene->setSceneRect(x_scene+40,y_scene,size_of_plane_x,size_of_plane_y);
    x_scene+=40;
   }     
}
void MainWindow::up()
{
  static bool flag=0;
  if(!flag)
  {
    if(ismovepossible(_mario->pos().x(),_mario->pos().y()-90)==true)
    {  
      _mario->setY(_mario->pos().y()-90);
       flag=1;
    }      
  }
  else
  {
    if(ismovepossible(_mario->pos().x(),_mario->pos().y()-90)==true)
   {
    _mario->setY(_mario->pos().y()+90);
    timer1->stop();
    flag=0;
   } 
  }
}
void MainWindow::back()
{
   if(ismovepossible(_mario->pos().x()-50,_mario->pos().y())==true)
   {
    _mario->setX(_mario->pos().x()-50);
    scene->setSceneRect(x_scene-50,y_scene,size_of_plane_x,size_of_plane_y);
    x_scene-=50;
   }
}
////////////////edit
void MainWindow::projectile()//when user press Z and J simultaneity
{
   static bool flag=0;
   if(!flag)
   {
   if(ismovepossible(_mario->pos().x()+50,_mario->pos().y()-90)==true)
   {
    _mario->setY(_mario->pos().y()-90);
    _mario->setX(_mario->pos().x()+50);
    scene->setSceneRect(x_scene+50,y_scene,size_of_plane_x,size_of_plane_y);
     x_scene-=50;
    text->setPos(x_scene+200,10);
     flag=1;
   }
   }
   else
   {
   if(ismovepossible(_mario->pos().x(),_mario->pos().y()+90)==true)
   {
   _mario->setY(_mario->pos().y()+90);
   timer2->stop();
   flag=0;
   }
   }
 }
 /////////////////////add function
 bool MainWindow::ismovepossible(int x, int y)
{
  int dis_b=10*30+120+120;
  int dis_b2=4*30+120+8*30+120;//8*30+120+120;
  int firstb=100;
  int endb=/*firstb*/100+8*30;
  int firstb2=/*endb*/100+8*30+120;
  int endb2=/*firstb2*/100+8*30+120+4*30;
  int firstb3=/*endb2*/100+8*30+120+4*30+2*30;
  int endb3=/*firstb3*/100+8*30+120+4*30+2*30+4*30;
  int dis_b3=120+8*30+120+4*30+2*30;
  if(y>size_of_plane_y-60 && y<=size_of_plane_y)
  {
    return false;
  }
  while(endb<size_of_plane_x)
  {
    if((y>size_of_plane_y-180 && y<size_of_plane_y-180+30)&&(x>firstb && x<endb))
    {
    return false;
    }
    else
    {
    firstb+=dis_b;
    endb+=firstb;
    }
  }
  while(endb2<size_of_plane_x)
  {
    if((y>size_of_plane_y-180 && y<size_of_plane_y-180+30)&&(x>firstb2 && x<endb2))
    {
        return false;
    }
    else
    {
    firstb2+=dis_b2;
    endb2+=firstb2;
    }
  }
  while(endb3<size_of_plane_x)
  {
    if((y>size_of_plane_y-180 && y<size_of_plane_y-180+30)&&(x>firstb3 && x<endb3))
    {
        return false;
    }
    else
    {
    firstb3+=dis_b3;
    endb3+=firstb3;
    }
  }
  return true;
}
class brick : public QGraphicsObject
{
  Q_OBJECT
  public:
  explicit brick(QGraphicsItem *parent = 0,int x=100,int y=600-180);
  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
  QRectF boundingRect()const;
  public slots:
  void collision();
  private:
  int size_of_plane_y;
  int start_x;
  int start_y;
  int size_brick;
};
brick::brick(QGraphicsItem *parent, int x, int y) : QGraphicsObject(parent)
{
  size_of_plane_y=600;
  start_x=x;
  start_y=y;
  size_brick=30;
  connect(_mario,SIGNAL(xChanged()),this,SLOT(collision()));
  connect(_mario,SIGNAL(yChanged()),this,SLOT(collision()));
}
void brick::collision()
{
  if(this->collidesWithItem(_mario))
  {
    qDebug()<<"collision";
    //what write here for stopping super mario? 
  }    
}

我认为你应该修改你的算法。这里的主要问题是你在移动马里奥之前没有检查是否有砖块。

你移动马里奥,你发出信号xChanged()或yChanged(),检查你是否在砖上?那你还得回到原来的位置吗?

既然你知道你把砖块放在哪里,你可以这样做:

void MainWindow::forward()
{
    if(moveIsPossible(xDest, yDest))
    {
        _mario->setX(...);
        [...]
}

在moveIsPossible(xDest, yDest)中,你放置未来位置的元组(X,Y),如果你没有砖,没有墙,没有任何你想要的,它返回true,否则返回false。

看到你的代码,我只是想提醒你注意很多事情:

  • 尝试使用const变量来放置任何配置变量,如板大小,砖大小等。
  • 尝试为特定的功能创建特定的类。Forward (), back(),等等。不能在主窗口类中实现。