Question

I have a problem with the execution of multiple functions at once. Specific , I have two classes (MyRect and space). The Idea is similar to space invaders but I stuck on the beginning. In class MyRect I have defined two rectangles :: body (ship body) and bullet (ship bullet).In the main class space is created ship as MyRect new object with body && bullet rectangles.Also there is definition for keyPress events. Problem is that when I fire bullet , everythig stops excetp moving of bullet and until loop MyRect::fireBullet(int x, int y) is done , i cant move ship during this event.Obviously, I do some fundamental mistakes so if someone is willing to clarify this.

here is sample code ::

MyRect.h

#include <QWidget>
#include <QRect>
#include <QMainWindow>
#include <QPainter>
#include <QLabel>
#include <ctime>
#include <QtGui/QMainWindow>

class space;  

class MyRect : public QObject {

Q_OBJECT

public:
MyRect(int in_x, int in_y, int in_w, int in_h, QWidget* parent) 
    {
        itsx = in_x;
        itsy = in_y;
        itsw = in_w;
        itsh = in_h;

        body = new QRect(itsx, itsy, itsw, itsh);
        bullet = new QRect(itsx+41, itsy-15, itsw/8, itsh/2);
        itsParent = parent;
    }
~MyRect() {}

void move(int x ,int y);

public slots:
    void fireBullet(int x, int y);

private:
int itsx;
int itsy;
int itsw;
int itsh;
QWidget* itsParent;
QRect* body;
QRect* bullet;
friend class space;
};

MyRect.cpp

#include "MyRect.h"

void wait( float seconds )
{
  clock_t endwait;
  endwait = clock () + seconds * CLOCKS_PER_SEC ;
  while (clock() < endwait) {}
}

void MyRect::move(int x, int y)
{
body->moveTo(x,y);
bullet->moveTo(x+35, y-15);


}

void MyRect::fireBullet(int x, int y)
{
y = y-15;
for(int i=0 ; i<200 ; i++)
{
    bullet->moveTo(x+41, y--);
    itsParent->repaint();
    wait(0.001);

}
}

space.h

    #include <QKeyEvent>
    #include <QMouseEvent>
    #include "MyRect.h" 

class space : public QMainWindow
{
Q_OBJECT

public:
    space(QWidget *parent = 0);
    ~space(){}


protected:
    void paintEvent(QPaintEvent *event);
    void keyPressEvent(QKeyEvent* event);

private:
private:
int x;
int y;
int w;
int h;
MyRect* ship;

signals:
void fireBullet(int x, int y); 

};

space.cpp

#include "space.h"
#include <QApplication>



space::space(QWidget *parent)
    : QMainWindow(parent)
{
x = 170;
y = 250;
w = 90;
h = 25;

ship = new MyRect(x,y,w,h, this);
connect(this, SIGNAL(fireBullet(int,int)), ship, SLOT(fireBullet(int,int)) );


}


void space::paintEvent(QPaintEvent *event)
{

  QPen pen(Qt::black, 2, Qt::SolidLine);
  QColor hourColor(0, 255, 0);


  QPainter painter(this);

  painter.setBrush(hourColor);  
  painter.setPen(pen);
  painter.drawRect( *(ship->body) );
 painter.drawRect( *(ship->bullet) );



}



void space::keyPressEvent(QKeyEvent* event)
{

switch(event->key())  {

    case Qt::Key_D :
    {
        x = x+10;
        ship->move(x,y);
        this->update();
        break;
    }
    case Qt::Key_A :
    {
        x = x-10;
        ship->move(x,y);
        this->update();
        break;
    }
    case Qt::Key_M :
    {
        emit fireBullet(x,y);


        break;
    }

} 

}

main.cpp

#include "space.h"
#include <QDesktopWidget>
#include <QApplication>



int main(int argc, char *argv[])
{
  QApplication app(argc, argv);

  space window;

  window.setWindowTitle("Lines");
  window.resize(500,500);
  window.show();

  return app.exec();
}

Thanks for the answers.

Was it helpful?

Solution

You have an architectural problem. What you are doing is moving the bullet in a loop in its fireBullet method. While that loop is running, the rest of the program isn't, since a single thread can only be doing one thing at a time.

The solution is to refactor your code so that everything on the screen gets updated by one frame-worth of animation every time you call some kind of update method. Basically, you just need to retain enough state, where you are, how fast you are moving, how far you can go before disappearing, so that you can move by the desired amount each frame.

Another thing that you would change is to have the keyPressEvent update the state of the spaceship to know which way it should be moving, so that it can move on its regular paintEvent. For that you can use a QTimer

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top