zoukankan      html  css  js  c++  java
  • 桌面冰球游戏总结说明

    桌面冰球游戏说明

     

    桌面冰球游戏中使用的类与对象说明

    Ball 类:

    class Ball:public QGraphicsItem

    成员属性:

    Speed:速度

    Angle:运动方向

    Ratio:图形比例

    Radius:球的半径

    操作属性:

    Advance:根据单位采样时间前进;

        xvel =speed*1.0/FRECUENCY *qCos(angle);

          yvel = speed*1.0/FRECUENCY *qSin(angle);

        collisionCalcualte(collisionType direction)//计算碰撞后的速度和方向

        setPos():设置位置

        void setSpeed(qreal);

        void setAngle(qreal);

     

    GraphWidget

    成员属性:

        GameWidget * game;创建父对象的指针,便于传递信息

        QPointF ballPosition;球的位置

        QPointF HandlePosition; 操作手柄的位置

        timerId; 定时器id,定时器用于产生基本的更新时间周期

        Ball *ballmove; 冰球

        Frame *frame; 边框

        Frame * frameUp;

        Frame * frameLeft;

        Frame * frameDown;

        Frame * frameRight;

    userHandle * userhandle;  手柄

        QGraphicsScene *scene;场景对象,将item加入其中

        gameScoreText:得分文本

     

        操作属性:

    timerEvent:定时器回应函数:

    获取当前ballHandle位置信息,传递给上层gamewidget

    进行碰撞检测:获取碰撞信息传递给Ball用于更新速度

         获取碰撞信息,决定游戏状态

    运动物体的运动更新ballmove->advance();

     

    GameWidget

        成员属性:

        QLabel *labelBall

        QLabel *labelHandle

        QLineEdit *editBall:显示当前球的坐标(单位:像素)

        QLineEdit *editHandle:显示当前Handle的坐标(单位:像素)

     

    GraphWidget *showwidget:游戏动画界面对象

        操作属性:

        setPosition():获取下一级成员showwidgetposition属性,显示到界面上

     

     

     

    动作:

     

    等待开始:

    暂停:

     

    进球之后触发的事件:

    球的位置复原;

    更新分数;

     

     

    重置:

    球的位置复原;

    分数重置;

     

     

    编程技巧与错误总结:

    基本的编程语法要熟悉,比如if语句,case语句,语句的排列顺序暗含了一定的优先级,if...if if...else if 是不同的,在代码段中加上returncontinuebreak等语句可能产生不同的效果。

    固定的可更改的参数,例如周期频率、弧度PI等可以用宏定义实现,方便更改。

    一系列的状态可以用enum枚举类型实现,字面意义很明确

     

    充分利用Qt的信号与槽机制,完成数据的共享与信息的传递,自身的信号和槽能够和另外的一个类的信号与槽连接。单向的信息传递只需要用简单的信号与槽的连接实现。

    不同的功能用不同的类实现,特定的功能放置在相应的类中实现。

    在有一定的基础的前提下,可以预先设计相应的类,写出想要的属性和操作,不同的类之间减少耦合,独享和共享的数据分离开,信号的传递方向要明确。

    使用图形视图机制

     graphwidget.cpp

    #include <QDebug>
    #include <QGraphicsScene>
    #include <QWheelEvent>
    #include <QRectF>
    #include <math.h>
    #include <QtCore/qmath.h>
    
    #include "ball.h"
    #include "frame.h"
    #include "userhandle.h"
    
    #include "graphwidget.h"
    #include "gamewidget.h"
    
    GraphWidget::GraphWidget(GameWidget *gamewidget) : timerId(0)
    {
        game = gamewidget;
        x1 = 0;
        x2 = 0;
    
        QGraphicsScene *scene = new QGraphicsScene(this);
        scene->setItemIndexMethod(QGraphicsScene::NoIndex);
        scene->setSceneRect(-300-10, -500-10, 600+20, 1000+20);
        setScene(scene);//
        setCacheMode(CacheBackground);
        setViewportUpdateMode(BoundingRectViewportUpdate);
        setRenderHint(QPainter::Antialiasing);
        setTransformationAnchor(AnchorUnderMouse);
        setResizeAnchor(AnchorViewCenter);
        scene->setBackgroundBrush(QColor(255-20*2, 255-20*2, 255-20*2, 127));//
    
        // 得分文本
        gameScoreText = new QGraphicsTextItem();
        gameScoreText->setFont(QFont("Times", 20, QFont::Bold));
        gameScoreText->setPos(200, 0);
        setScore(0,0);
        //gameScoreText->setHtml(tr("<font color=red>%1:%2</font>").arg(0).arg(0));//设置初始分数
        scene->addItem(gameScoreText);//
    
        //添加球洞
    
        uphole = new QGraphicsRectItem(0,0,100,40);
        uphole->setBrush(Qt::blue);
        uphole->setData(0,"hole1");
        scene->addItem(uphole);//上边
        uphole->setPos(-50,-500-20);
        uphole->setFlag(QGraphicsItem::ItemIsMovable,false);//禁止鼠标拖动 // // // //
    
        downhole = new QGraphicsRectItem(0,0,100,40);
        downhole->setBrush(Qt::yellow);
        downhole->setData(0,"hole2");
        scene->addItem(downhole);//下边
        downhole->setPos(-50,500-20);
        downhole->setFlag(QGraphicsItem::ItemIsMovable,false);//禁止鼠标拖动 // // // //
    
        //添加球
        ballmove  =new Ball(this);
        scene->addItem(ballmove);
        //ballmove->setPos(0,0);
          ballmove->setData(0,"ball");//设置键值up
        ballmove->setFlag(QGraphicsItem::ItemIsMovable,false);//禁止鼠标拖动 // // // //
    
        //添加标示线
        //    Frame * LineFrame = new Frame(this,QRectF(-300,-5,600,10));
        //    scene->addItem(LineFrame);
        //    LineFrame->setPos(0,0);
        scene->addLine(QLineF(-300,0,300,0),QPen(QColor(Qt::red)));
        //scene->addEllipse();
    
        //添加边框
        frameUp = new Frame(this,QRectF(-0,-0,300-50,20));
        scene->addItem(frameUp);
        frameUp->setPos(-300,-500);
        frameUp->setData(0,"up");//设置键值up
        frameUp->setFlag(QGraphicsItem::ItemIsMovable,false);//边框禁止鼠标拖动 // // // //
    
        Frame *up2 = new Frame(this,QRectF(-0,-0,300-50,20));
        scene->addItem(up2);
        up2->setPos(0+50,-500);
        up2->setData(0,"up");//设置键值up
        up2->setFlag(QGraphicsItem::ItemIsMovable,false);// // // // //
    
        frameDown = new Frame(this,QRectF(0,0,300-50,20));
        scene->addItem(frameDown);
        frameDown->setPos(-300,+500-20);
        frameDown->setData(0,"down");//设置键值down
        frameDown->setFlag(QGraphicsItem::ItemIsMovable,false);// // // // //
    
        Frame *down2 = new Frame(this,QRectF(0,0,300-50,20));
        scene->addItem(down2);
        down2->setPos(0+50,500-20);
        down2->setData(0,"down");//设置键值down
        down2->setFlag(QGraphicsItem::ItemIsMovable,false);// // // // //
    
    
        frameLeft = new Frame(this,QRectF(-300,-500,20,1000));
        scene->addItem(frameLeft);
        frameLeft->setPos(0,0);
        frameLeft->setData(0,"left");//设置键值left
        frameLeft->setFlag(QGraphicsItem::ItemIsMovable,false);// // // // //
    
        frameRight = new Frame(this,QRectF(300-20,-500,20,1000));
        scene->addItem(frameRight);
        frameRight->setPos(0,0);
        frameRight->setData(0,"right");//设置键值right
        frameRight->setFlag(QGraphicsItem::ItemIsMovable,false);// // // // //
    
        //添加游戏手柄
    
        userhandle  =new userHandle(this);
        scene->addItem(userhandle);
        userhandle->setPos(10,200);
        userhandle->setData(0,"userhandle");//设置键值userhandle
    
        scale(qreal(0.8), qreal(0.8));
        setMinimumSize(500, 800+50);
        //   setMinimumSize(600+50, 1000+60);
        setWindowTitle(tr("Elastic Nodes"));
    
        //设置更新时间,(如果时间太长,也就是更新太慢,当speed太小时会导致更新比鼠标运动还要慢,出错)、
        timerId = startTimer(1000 / FRECUENCY);//设置更新的时间间隔 FRECUENCY = 100
    
    }
    void GraphWidget::timerEvent(QTimerEvent *event)
    {
     Q_UNUSED(event);
    
        //碰撞检测、速度更新
        //ballmove->collidingItems();
    
        //获取球和Handle的位置,【】相邻两次Handle的位置可以计算出Handle的速度
        ballPosition = ballmove->pos();
        HandlePosition  = userhandle->pos();
        game->showPosition();
        //判断球是否进洞
        if(ballmove->pos().y() < -500+20)
        {x2 = x2+1;
    
            setScore(x1,x2);
            //延时一段时间
    
            ballmove->Reset();
            return;
        }
        if(ballmove->pos().y() > +500-20)
        {
             x1 = x1+1;
            setScore(x1,x2);
            //延时一段时间
    
            ballmove->Reset();
            return;
        }
        /*
         QList<QGraphicsItem *>  collisionsforhole1 = uphole->collidingItems();//获取所有碰撞的对象
         foreach (QGraphicsItem *item, collisionsforhole1)
         {
             if(item->data(0).toString().contains("ball")) // 如果碰到了上边的hole
             {
                x1 = x1+1;
                setScore(x1,x2);
                //延时一段时间
    
                ballmove->Reset();
                break;
             }
             if
         }
    
         QList<QGraphicsItem *>  collisionsforhole2 = downhole->collidingItems(Qt::ContainsItemBoundingRect);//获取所有碰撞的对象
         foreach (QGraphicsItem *item, collisionsforhole2)
         {
             if(item->data(0).toString().contains("ball")) // 如果碰到了下边的hole
             {
                x2 = x2+1;
                setScore(x1,x2);
                //延时一段时间
    
                ballmove->Reset();
                break;
             }
         }*/
         //判断球与边框的碰撞
         QList<QGraphicsItem *>  collisions = ballmove->collidingItems();//获取所有碰撞的对象
         foreach (QGraphicsItem *item, collisions)
         {
             //碰撞物体检测
             if(item->data(0).toString().contains("up")) // 如果碰到了上边的Frame; if collide with Right wall
             {
                ballmove->collisionCalcualte(Up) ;
             }
             if(item->data(0).toString().contains("down")) // 如果碰到了下边的Frame; if collide with Right wall
             {
                ballmove->collisionCalcualte(Down) ;
             }
             if(item->data(0).toString().contains("left")) // 如果碰到了左边的Frame; if collide with Right wall
             {
                ballmove->collisionCalcualte(Left) ;
             }
             if(item->data(0).toString().contains("right")) // 如果碰到了右边的Frame; if collide with Right wall
             {
                ballmove->collisionCalcualte(Right) ;
             }
             if(item->data(0).toString().contains("userhandle")) // 如果碰到了userhandle; if collide with Right wall
             {
    
                 //将嵌入到Handle的 ball退出来,【】但是可能把球推出去了;
    
        //        {
        //            qreal angle=0;
        //            QPointF point = HandlePosition;
    
        ////            qDebug()<<point;
        //            point-=ballPosition;
        //            qreal collisionAngle =  PI+qAtan2(point.y(),point.x() );
        //            //angle = 2.0*(collisionAngle+PI/2.0)-ballmove->angle; //angle 是由ball指向Handle
    
        //          //  angle = angle+ PI; //angle 是由Handle指向ball
        //            angle = collisionAngle;
        //            point = HandlePosition;
        //            point+=QPointF((ballmove->Radius+userhandle->Radius)*cos(angle)/2.0,(ballmove->Radius+userhandle->Radius)*sin(angle)/2.0);
        //            ballmove->setPos(point);
        //        }
                 //或者使用另外一种方式 ,ball 退回一步
                 {
                     qreal xvel = 0;
                     qreal yvel = 0;
                     qreal angle = ballmove->angle;
    
                     xvel =ballmove->speed*0.01*qCos(angle);
                     yvel = ballmove->speed*0.01*qSin(angle);
    
                     QPointF newPos = ballmove->pos() -QPointF(2*xvel, 2*yvel);//往回退回一步,*2表示多退一点
    
                     ballmove->setPos(newPos);
                 }
                  ballmove->collisionCalcualte(Handle) ;//一定要先退出来再反弹
             }
         }
    
        //运动物体的运动更新
    
        ballmove->advance();
    
    //    ballmove->moveBy(0.1,0.1);
    }
    
    //设置分数
    void GraphWidget::setScore(int x1 ,int x2)
    {
     gameScoreText->setHtml(tr("<font color=red>%1:%2</font>").arg(x1).arg(x2));//设置分数
    }
    
    
    void GraphWidget ::start()
    {
        //showwidget->ballmove->Reset();
        ballmove->Reset();
        ballmove->setSpeed(400);
    }
    
    void GraphWidget ::pause()
    {
        if(ballmove->speed > 0)
        {
             ballmove->setSpeed(0);
        }
        else if(ballmove->speed < 1.0)
        {
             ballmove->setSpeed(400);
        }
    
    }
    void GraphWidget ::reset()
    {
        ballmove->Reset();
        ballmove->setSpeed(0);
        x1 = 0;
        x2 = 0;
        gameScoreText->setHtml(tr("<font color=red>%1:%2</font>").arg(0).arg(0));//设置分数
    }

     

  • 相关阅读:
    杭电 搜索 1253 胜利大逃亡
    杭电 搜索 1258 Sum It Up
    杭电搜索 2612 Find a way
    杭电 搜索 水题1072 Nightmare
    杭电1175简单搜索 连连看
    杭电 1372 Knight Moves
    杭电 oj Rescue 1242
    杭电 1241 Oil Deposits
    杭电 2100 Children’s Queue
    杭电 1103 Flo's Restaurant
  • 原文地址:https://www.cnblogs.com/tangyuanjie/p/6246928.html
Copyright © 2011-2022 走看看