c++ - 如何在不使用动画的情况下停止 QGraphicsObject 的对象?

标签 c++ qt qgraphicsitem

在这个程序中,我有一个继承自 QGraphicsObject 的类。这个物体(马里奥)前进,后退并跳跃。对于这个工作,我改变了马里奥的坐标。但我有一个问题。我希望它在与砖 block 碰撞时停止。虽然我不使用 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? 
  }    
}

最佳答案

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

你移动马里奥,你发出信号 xChanged() 或 yChanged(),检查你是否在砖 block 上?然后你必须回到以前的位置?

既然你知道你把积木放在哪里,你可以做更多类似的事情:

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

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

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

  • 尝试使用 const 变量来放置任何配置变量,如电路板尺寸、砖 block 尺寸等......
  • 尝试为特定功能创建特定类。 forward()、back() 等。不必在主窗口类中实现。

关于c++ - 如何在不使用动画的情况下停止 QGraphicsObject 的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24526582/

相关文章:

c++ - 释放分配给存储在 vector 中的堆的内存

c++ - 使用 dlopen 动态加载 gtkmm 对象

c++ - 确保 move 构造函数存在时永远不会调用复制构造函数

c++ - #ifdef _DEBUG vs 2008 中的 Release模式

c++ - Q_UNUSED 相对于省略参数名称有什么好处?

c++ - 带有Qt 4.8.5的Netbeans 7.3.1-无法编译

c++ - 如何在内存(RAM)中隐藏敏感字符串?

c++ - 当 QToolTip 应该跟随 QGraphicsItem 上的鼠标时出现奇怪的行为

c++ - QGraphicsItem 在场景中的位置始终为 NULL

python - 删除 QGraphicsItem 的父项