• 7016阅读
  • 11回复

用QT3寫彈跳球的程式 [复制链接]

上一主题 下一主题
离线pkmon
 
只看楼主 倒序阅读 楼主  发表于: 2008-09-22
— 本帖被 XChinux 执行加亮操作(2008-09-22) —
請問該如何用QT3寫一個在視窗內不斷碰撞左、上、右三邊的程式

但是對於碰觸到邊線後該如何撰寫依職不是很順,不知道哪位大大可以給小地指點迷津嗎?

以下是小弟我目前寫出的程式碼

#include "bump.h"
#include <qpainter.h>
#include <qpixmap.h>
#include <qtimer.h>

BumpField::BumpField( QWidget *parent, const char *name )
        : QWidget( parent, name )
 
  { 
    x = 0;
    timerCount = 0;
    autoShootTimer = new QTimer( this, "movement handler" );
    connect( autoShootTimer, SIGNAL(timeout()), this, SLOT(moveshoot()) );
    barrelPressed = FALSE;
    setPalette(QPalette( QColor( 250, 250, 250)) );
  }


void BumpField::setMove( int value )
 
  {
    if ( value < 0 )
      value = 0;
    if ( value > 720 )
      value = 720;
    if ( x == value )
      return;
    x = value;
    repaint();
   
  }


void BumpField::shoot()
{
    if ( autoShootTimer->isActive() )
        return;
    timerCount = 0;
    autoShootTimer->start( 50 );
}


void BumpField::moveShot()
{
    QRegion r( shotRect() );
    timerCount++;
   
    QRect shotR = shotRect();
   
    ( shotR.x() > width() || shotR.x() < width() || shotR.y() < hight()  )
                                                                                /* 是在這邊許判斷式嗎?      */
    else
      r = r.unite( QRegion( ShotR ) );
    repaint( r );
   
           
}


void BumpField::paintShoot( QPainter *p )
  {
    p->setBrush( black );
    p->setPen( NoPen );
    p->drawRect( shotRect() );

  }


void BumpField::paintCannon( QPainter *p )

  {
    QPainter b( this );
   
    b.setBrush( blue );
    b.setPen( NoPen );
   
    b.translate( x, rect().bottom() );
    b.drawRect( QRect( 0, -10, 60, 8 ) ); 
  } 
 


void BumpField::mousePressEvent( QMouseEvent *e )
  {
    if ( e->button() != LeftButton )
        return;
    if ( barrelHit(e->pos()) )
        barrelPressed = TRUE;
  }

void BumpField::mouseMoveEvent( QMouseEvent *e )
  {
  if ( !barrelPressed )
      return;
  QPoint pnt = e->pos();
  if ( pnt.x() <=0 )
      pnt.setX(1);
  if ( pnt.y() >= height() )
      pnt.setY( height() - 1 );
    setMove( pnt.x() );
  }

void BumpField::mouseReleaseEvent( QMouseEvent *e )
  {
  if (e->button() == LeftButton)
        barrelPressed = FALSE;
  }

bool BumpField::barrelHit( const QPoint &p ) const
  {
  QWMatrix mtx;
  mtx.translate( x, height() - 1 );
  mtx = mtx.invert();
  return QRect( 0, -10, 60, 8 ).contains( mtx.map(p) );
  }


QRect BumpField::shotRect() const
  {
   
    double time = timerCount / 4.0; 
    double x0  = QRect( 0, -10, 60, 8 ).right()+5;
    double y0  = QRect( 0, -10, 60, 8 ).right()+5;
    double x    = x0*time;
    double y    = y0*time;

    QRect r = QRect( 0, 0, 6, 6 );
    r.moveCenter( QPoint( qRound(x), height() - 1 -qRound(y) ) );
    return r;
  }

QSizePolicy BumpField::sizePolicy() const

  {
    return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
  }

离线yfx2003

只看该作者 1楼 发表于: 2008-09-24
记得opengl程序设计 作者: 乔林 费广正 林杜 芦丽丹 马晓峰  一书中有这个例子

应该可以解决你的问题……
www.qtcn.org/gpq4/
ajaxref.okajax.com/
离线nmiirq

只看该作者 2楼 发表于: 2008-09-24
你写的这个比较有意思,我以前在其它平台上写过
判断碰撞最主要的是比较时的一些细节,还有碰撞成功后应该做的处理~
没明白你现在的问题是什么样的?
离线pkmon
只看该作者 3楼 发表于: 2008-09-24
感謝樓上的大大提供的訊息

我現在是卡在方程式寫不出來

反彈的方程式應該是將原方程式的斜率乗上一個負號吧

可是我方程式是由時間驅動的,乘上負號後球就會直接消失耶= =

請問各位大大我該如何修改我的程式呢?

以下是我的程式碼

#include "bump.h"
#include <qpainter.h>
#include <qpixmap.h>
#include <qtimer.h>

BumpField::BumpField( QWidget *parent, const char *name )
        : QWidget( parent, name )
 
  { 
    v = 1;
    m = 0;
    timerCount = 0;
    autoShootTimer = new QTimer( this, "movement handler" );
    connect( autoShootTimer, SIGNAL(timeout()), this, SLOT(moveShot()) );
    barrelPressed = FALSE;
    setPalette(QPalette( QColor( 250, 250, 250)) );
  }


void BumpField::setMove( int value )
 
  {
    if ( value < 0 )
      value = 0;
    if ( value > 720 )
      value = 720;
    if ( m == value )
      return;
    m = value;
    repaint();
   
  }


void BumpField::moveShot()
{
    QRegion r( shotRect() );
    timerCount++;
   
    QRect shotR = shotRect();
   
    if ( shotR. intersects(QRect( 0, 10, 790, 1 )) )
        v = -1; 
    else
    r = r.unite( QRegion( shotR ) );
    repaint( r );
   
           
}


void BumpField::paintEvent( QPaintEvent *e )
{
    QRect updateR = e->rect();
    QPainter p( this );

    paintCannon( &p );
    paintWallright( &p );
    paintWallleft( &p );
    paintWallup( &p );
    paintShoot( &p );
   
}


void BumpField::paintWallright( QPainter *p )
{
    p->setBrush( black );
    p->setPen( NoPen );
    p->drawRect( QRect( -1, 0, 1, 520 ) );   
}


void BumpField::paintWallleft( QPainter *p )
{
    p->setBrush( black );
    p->setPen( NoPen );
    p->drawRect( QRect( 770, 0, 1, 520 ) );   
}


void BumpField::paintWallup( QPainter *p )
{
    p->setBrush( black );
    p->setPen( NoPen );
    p->drawRect( QRect( 0, 10, 790, 1 ) );   
}


void BumpField::paintShoot( QPainter *p )
  {
    p->setBrush( black );
    p->setPen( NoPen );
    p->drawRect( shotRect() );

  }


void BumpField::paintCannon( QPainter *p )

  {
    QPainter b( this );
   
    b.setBrush( blue );
    b.setPen( NoPen );
   
    b.translate( m, rect().bottom() );
    b.drawRect( QRect( 0, -10, 60, 8 ) ); 
  } 
 


void BumpField::mousePressEvent( QMouseEvent *e )
  {
    if ( e->button() != LeftButton )
        return;
    if ( barrelHit(e->pos()) )
        barrelPressed = TRUE;
        autoShootTimer->start( 5 );       
  }

void BumpField::mouseMoveEvent( QMouseEvent *e )
  {
  if ( !barrelPressed )
      return;
  QPoint pnt = e->pos();
  if ( pnt.x() <=0 )
      pnt.setX(1);
  if ( pnt.y() >= height() )
      pnt.setY( height() - 1 );
    setMove( pnt.x() );
  }

void BumpField::mouseReleaseEvent( QMouseEvent *e )
  {
  if (e->button() == LeftButton)
        barrelPressed = FALSE;
  }

bool BumpField::barrelHit( const QPoint &p ) const
  {
  QWMatrix mtx;
  mtx.translate( m, height() - 1 );
  mtx = mtx.invert();
  return QRect( 0, -10, 60, 8 ).contains( mtx.map(p) );
  }


QRect BumpField::shotRect() const
  {   
    double x    = timerCount;     
    double y    = v * x ;                  /*  此段該如何修改呢?  */             

    QRect r = QRect( 0, 0, 6, 6 );
    r.moveCenter( QPoint( qRound(x), height() - 1 -qRound(y) ) );
    return r;
  }

QSizePolicy BumpField::sizePolicy() const

  {
    return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
  }
离线nmiirq

只看该作者 4楼 发表于: 2008-09-25
球一下子消失,是因为它的坐标太小或是太小了
你可以在Debug模式下查看一下当时具体的情况
这里面有可能会牵扯到无符号数与有符号数的运算,
不晓得QT是如何处理的,有可能会出现一些意想不到的情况
我当时的处量是把这两种情况分开判断,如果是为正号的话就在正方向上移动,反之为减!
你若用的是QRect的移动方法的话,则可以考虑把正负号反映在移动的目的地上~

离线pkmon
只看该作者 5楼 发表于: 2008-09-27
根據樓上大哥的建議修改了一下程式


  a = 0;
    v = 1;
    m = 0;
    timerCount = 0;
    autoShootTimer = new QTimer( this, "movement handler" );
    connect( autoShootTimer, SIGNAL(timeout()), this, SLOT(moveShot()) );
    barrelPressed = FALSE;
    setPalette(QPalette( QColor( 250, 250, 250)) );
  }

.
.
.

void BumpField::moveShot()
{
    QRegion r( shotRect() );
    timerCount++;
   
    QRect shotR = shotRect();
   
    if ( shotR. intersects(QRect( 0, 10, 790, 1 )) )
        v = -1, a = 1; 
    if ( shotR. intersects(QRect( 7, 500, 790, 1 )) )
        v = 1, a = 1.5;
    else
    r = r.unite( QRegion( shotR ) );
    repaint( r );
}

.
.
.

QRect BumpField::shotRect() const
  {   
    int radion = v * 80 *  3.1415926/180;
    double x    = cos(radion) * timerCount;     
    double y    = sin(radion) * timerCount + a * 990 ;                           

    QRect r = QRect( 0, 0, 6, 6 );
    r.moveCenter( QPoint( qRound(x), height() - 1 -qRound(y) ) );
    return r;
  }

但是這樣似乎只是治標不治本 = =
還是說我要將4邊的牆都設成case , 然後再依照不同的case去跑呢?
离线pkmon
只看该作者 6楼 发表于: 2008-09-28
再次修改程式後變成不會反彈,碰到上璧後沿X軸方向移動= =
並不會彈下去,估計應該是不斷執行++和--的動作....= =||
請問我該如何修改呢?

以下附上現在的code

#include "bump.h"
#include <qpainter.h>
#include <qpixmap.h>
#include <qtimer.h>
#include <math.h>

BumpField::BumpField( QWidget *parent, const char *name )
        : QWidget( parent, name )
 
  {
    a = 0;
    m = 0;
    timerCount1 = 0;
    timerCount2 = 0;
    autoShootTimer = new QTimer( this, "movement handler" );
    connect( autoShootTimer, SIGNAL(timeout()), this, SLOT(moveShot()) );
    barrelPressed = FALSE;
    setPalette(QPalette( QColor( 250, 250, 250)) );
  }


void BumpField::setMove( int value )
 
  {
    if ( value < 0 )
      value = 0;
    if ( value > 720 )
      value = 720;
    if ( m == value )
      return;
    m = value;
    repaint();
   
  }


void BumpField::moveShot()
{
    QRegion r( shotRect() );
   
    timerCount1++;
    timerCount2++;
    QRect shotR = shotRect();
       
    if ( shotR.y() < height() - 500 )
    a = 1;
    if ( shotR.y() > height() - 4 )
    a = 2;
    if ( shotR.x() > width() - 5 )
    a = 3;
    if ( shotR.x() < width() - 771 )
    a = 4;
  switch(a)
      {
        case 1:
            --timerCount2;
              break;
        case 2:
            timerCount2++;
              break;
        case 3:
            --timerCount1;
              break;
        case 4:
            timerCount1++;
              break;
      };
    r = r.unite( QRegion( shotR ) );
    repaint( r );
   
           
}


void BumpField::paintEvent( QPaintEvent *e )
{
    QRect updateR = e->rect();
    QPainter p( this );
   
    paintCannon( &p );
    paintShoot( &p );
   
}

void BumpField::paintShoot( QPainter *p )
  {
    p->setBrush( black );
    p->setPen( NoPen );
    p->drawRect( shotRect() );

  }


void BumpField::paintCannon( QPainter *p )

  { 
    QPainter bar( this );
   
    bar.setBrush( blue );
    bar.setPen( NoPen );
   
    bar.translate( m, rect() .bottom() );
    bar.drawRect( QRect( 0, -10, 60, 8 ) );
   
  } 
 

void BumpField::mousePressEvent( QMouseEvent *e )
  {
    if ( e->button() != LeftButton )
        return;
    if ( barrelHit(e->pos()) )
        barrelPressed = TRUE;
        autoShootTimer->start( 5 );       
  }

void BumpField::mouseMoveEvent( QMouseEvent *e )
  {
  if ( !barrelPressed )
      return;
  QPoint pnt = e->pos();
  if ( pnt.x() <=0 )
      pnt.setX(1);
  if ( pnt.y() >= height() )
      pnt.setY( height() - 1 );
    setMove( pnt.x() );
  }

void BumpField::mouseReleaseEvent( QMouseEvent *e )
  {
  if (e->button() == LeftButton)
        barrelPressed = FALSE;
  }

bool BumpField::barrelHit( const QPoint &p ) const
  {
  QWMatrix mtx;
  mtx.translate( m, height() - 1 );
  mtx = mtx.invert();
  return QRect( 0, -10, 60, 8 ).contains( mtx.map(p) );
  }


QRect BumpField::shotRect() const
  { 
   
    double radians = 80*3.14159265/180;
    double x = cos(radians)*timerCount1;
    double y = sin(radians)*timerCount2;
   
   
    QRect r = QRect( 0, 0, 6, 6 );
    r.moveCenter( QPoint( qRound(x), height() - 1 -qRound(y) ) );
   
    return r;
  }

QSizePolicy BumpField::sizePolicy() const

  {
    return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
  }
离线nmiirq

只看该作者 7楼 发表于: 2008-09-28
应该是临界值没有处理好的问题,方便的话,把bump.h贴一下,我给你改一下!或是离线发给我,QQ:276289228
离线jzj139
只看该作者 8楼 发表于: 2008-09-29
我记得有QT网站上有个标准的例子的
qt
离线pkmon
只看该作者 9楼 发表于: 2008-09-30
請問樓上的大哥 再哪裡呀?可以貼個網址嗎?

附上我的bump.h檔

#ifndef BUMP_H
#define BUMP_H
#include <qwidget.h>


class BumpField : public QWidget

  {
      Q_OBJECT
  public:
      BumpField( QWidget *parent=0, const char *name=0 );

      QSizePolicy sizePolicy() const;
   
      int move() const { return m; }

  public slots:
      void setMove( int value );
   
  private slots:
      void moveShot();
   
  signals:
      void moveChanged( int );

  protected:
      void paintEvent( QPaintEvent * );
      void mousePressEvent( QMouseEvent * );
      void mouseMoveEvent( QMouseEvent * );
      void mouseReleaseEvent( QMouseEvent * );


  private:
      void paintCannon( QPainter * );
      void paintShoot( QPainter * );
                     
      int a;
      int m;
      int timerCount1;
      int timerCount2;     

      QRect cannonRect() const;
      QRect shotRect() const;
     
      QTimer * autoShootTimer;
      QPoint target;

      bool barrelHit( const QPoint & ) const;
      bool barrelPressed;

  };


#endif
离线pkmon
只看该作者 10楼 发表于: 2008-10-01
經過幾天的努力,小弟我終於把程式寫出來啦~~~

以下附上最後修改出來的部份程式碼

if ( shotR.y() < height() - 500)
    { if ( x1 < x0)
        a = 1;
      else
        a = 2; 
      }
    else if ( shotR.y() >height() - 5)
    { if( x1 > x0 )
        a = 3;
      else
        a = 4;
      }     
    else if ( shotR.x() > width() - 5 )
    { if( y1 > y0 )
        a = 2;
      else
        a = 3;
      }
    else if ( shotR.x() < width() - 770 )
    { if( y1 < y0 )
        a = 4;
      else
        a = 1;
      }
    else
      x1 = x0++;
      y1 = y0++;
    switch(a)
      {
        case 1:
            y0 = y0 - 2;
              break;
        case 2:
            x0 = x0 - 2;
            y0 = y0 - 2;
           
              break;
        case 3:
            x0 = x0 - 2;
              break;
        case 4:
              break;
      };

但是此程式還是有一個問題,就是我左面的牆完全不會彈跳= =
只會上下碰撞而已,如果對他加上x0 = x0 + 1的話又會造成加速的效果,請問我到底是哪裡出問題了呢?
离线nmiirq

只看该作者 11楼 发表于: 2008-10-02
Sorry,我的虚拟机文件坏了,现在没有qt3的环境,
但我那天有在ThizLInux下调过,基本上没什么大的问题,主要是标志性变量的调整,
但有一点,你的QRect刚初始化完出来第一次的x,y坐标就不是正数的,这个会导致你判断上的一些问题,你可以在这方面查一下!
快速回复
限100 字节
 
上一个 下一个