最近貌似禽流感又出现了。也许经历了非典啊、禽流感啊,这样的流行病多了,人们对此似乎见怪不怪了,反正我是淡定了,在食堂鸡鸭鹅的什么也都不忌讳。好了,废话不多说了,先上个图(写的不好,请大神轻喷):
细菌病毒战的主界面
分四个模式;
单人攻击模式:通过a,s,d,w控制红细胞的运动方向,然后通过鼠标左右键控制发射抗体,来消灭流感病毒;
双人攻击模式:通过a,s,d,w和i,j,k,l来控制两个红细胞的运动方向,然后分别通过x,c和n,m控制两个红细胞发射抗体;
单人和双人防守模式:控制红细胞躲避病毒,(被病毒撞上会消耗生命值);
这个游戏是带音效的哦,双人模式中存活时间最长的为胜者。
单人攻击模式:(美工还行吧)
双人攻击模式:
游戏中的声音通过QSound类实现:
void BackGroundMusicThread::playBackGroundSound(const QString filename) { if( this->backgroudSound!=NULL ) { this->backgroudSound->destroyed(); delete this->backgroudSound; this->backgroudSound = new QSound(filename); this->backgroudSound->play(); } }
背景音乐播放,继承QThread类:
class BackGroundMusicThread : public QThread { Q_OBJECT public: explicit BackGroundMusicThread(QObject *parent = 0); ~BackGroundMusicThread(); void playBackGroundSound(); void playBackGroundSound(const QString fileName); void setSoudnLoop(int lo); void run(); signals: public slots: private: QSound *backgroudSound; QObject *parentWidget; };
这样实现抽象函数run(),就可以在游戏结束的时候播放想要播放的声音了。
void BackGroundMusicThread::run() { qDebug() << "IN THREAD RUN..............................."; this->setSoudnLoop(2); // play this music 2 times this->playBackGroundSound(); while(true) { if( ((Widget*)(this->parentWidget))->isGameOver() ) { Resource *resource = new Resource(); QSound *gameoverSound = new QSound(resource->picLocation+"gameover.wav"); delete resource; gameoverSound->play(); if( gameoverSound->isFinished()) { delete gameoverSound; } } if( ((Widget*)(this->parentWidget))->isExit()) { break; } } qDebug() << "THREAD RUN STOP..............................."; }
按键的实现通过继承Widget里的MouseEven实现:
void mouseMoveEvent(QMouseEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *);
具体代码:
void Widget::mouseMoveEvent(QMouseEvent *event){ if( Startgame ) { world->setMousePos(event->x(),event->y()); } } void Widget::mousePressEvent(QMouseEvent *event){ qDebug() << "mouse event type :" << event->type(); if( this->world->getMode() == SINGLE_ATTACK_PLAYER) { if ( Startgame ) { world->fireFlag = true; this->world->setKeyP(event->button()); } } } void Widget::mouseReleaseEvent(QMouseEvent *event){ qDebug() << "mouse event type :" << event->type(); if( this->world->getMode() == SINGLE_ATTACK_PLAYER) { if( Startgame ) { world->fireFlag = false; this->world->setKeyR(event->button()); } } }
在SetKeyR和SetKeyP中获取按键和放开键的具体键值:
void World::setKeyP(int k){ switch(this->getMode()) { case SINGLE_ATTACK_PLAYER: //play one if(k==Qt::Key_W) //up key['w'] = true; if(k==Qt::Key_S) //down key['s'] = true; if(k==Qt::Key_A) //left key['a'] = true; if(k==Qt::Key_D) //right key['d'] = true; if(k==Qt::LeftButton) //right click, bullet state 1 { //play shot sound this->playShotSound(); this->me->fireflag=true; this->me->bulletstate=1; } else if(k==Qt::RightButton) // left click, bullet state 2 { //play bomb sound this->playBombSound(); this->me->fireflag=true; this->me->bulletstate=2; } // bullets status if(k== Qt::Key_1) this->bulletState = 1; if(k==Qt::Key_3) this->bulletState = 3; if(k==Qt::Key_4) this->bulletState = 4; break; case SINGLE_DEFENCE_PLAYER: //play one if(k==Qt::Key_W) //up key['w'] = true; if(k==Qt::Key_S) //down key['s'] = true; if(k==Qt::Key_A) //left key['a'] = true; if(k==Qt::Key_D) //right key['d'] = true; this->fireFlag = false; break; case DOUBLE_ATTACK_PLAYER: //play one if(k==Qt::Key_W) //up key['w'] = true; if(k==Qt::Key_S) //down key['s'] = true; if(k==Qt::Key_A) //left key['a'] = true; if(k==Qt::Key_D) //right key['d'] = true; //player tow if(k==Qt::Key_I) //up key['i'] = true; if(k==Qt::Key_K) //down key['k'] = true; if(k==Qt::Key_J) //left key['j'] = true; if(k==Qt::Key_L) //right key['l'] = true; // fire keys if(k==Qt::Key_N) //N key fire, bullet state 1 { //play shot sound this->playShotSound(); this->you->fireflag=true; this->you->bulletstate=1; } if(k==Qt::Key_M) //M key fire, bullet state 2 { //play bomb sound this->playBombSound(); this->you->fireflag=true; this->you->bulletstate=2; } if(k==Qt::Key_C) //C key fire, bullet state 1 { //play shot sound this->playShotSound(); this->me->fireflag=true; this->me->bulletstate=1; } else if(k==Qt::Key_X) // X key fire, bullet state 2 { //play bomb sound this->playBombSound(); this->me->fireflag=true; this->me->bulletstate=2; } // bullets status if(k== Qt::Key_1) this->bulletState = 1; if(k==Qt::Key_3) this->bulletState = 3; if(k==Qt::Key_4) this->bulletState = 4; break; case DOUBLE_DEFENCE_PLAYER: //play one if(k==Qt::Key_W) //up key['w'] = true; if(k==Qt::Key_S) //down key['s'] = true; if(k==Qt::Key_A) //left key['a'] = true; if(k==Qt::Key_D) //right key['d'] = true; //player tow if(k==Qt::Key_I) //up key['i'] = true; if(k==Qt::Key_K) //down key['k'] = true; if(k==Qt::Key_J) //left key['j'] = true; if(k==Qt::Key_L) //right key['l'] = true; this->fireFlag = false; break; default: break; } // move Sound effect is bad , so wape it out, if you like it, add it /*if( k==Qt::Key_W || k==Qt::Key_S || k== Qt::Key_A || k==Qt::Key_D || k==Qt::Key_I || k==Qt::Key_J || k== Qt::Key_K || k==Qt::Key_L ) { this->playMoveSound(); } */ } void World::setKeyR(int k){ switch(this->getMode()) { case SINGLE_ATTACK_PLAYER: // player one if(k==Qt::Key_W) //up key['w'] = false; if(k==Qt::Key_S) //down key['s'] = false; if(k==Qt::Key_A) //left key['a'] = false; if(k==Qt::Key_D) //right key['d'] = false; if(k==Qt::LeftButton) //release left, bullet state 1 { this->me->fireflag=false; this->me->bulletstate=1; } else if(k==Qt::RightButton) //release right, bullet state 2 { this->me->fireflag=false; this->me->bulletstate=2; } break; case SINGLE_DEFENCE_PLAYER: // player one if(k==Qt::Key_W) //up key['w'] = false; if(k==Qt::Key_S) //down key['s'] = false; if(k==Qt::Key_A) //left key['a'] = false; if(k==Qt::Key_D) //right key['d'] = false; break; case DOUBLE_ATTACK_PLAYER: // player one if(k==Qt::Key_W) //up key['w'] = false; if(k==Qt::Key_S) //down key['s'] = false; if(k==Qt::Key_A) //left key['a'] = false; if(k==Qt::Key_D) //right key['d'] = false; //player tow if(k==Qt::Key_I) //up key['i'] = false; if(k==Qt::Key_K) // down key['k'] = false; if(k==Qt::Key_J) //left key['j'] = false; if(k==Qt::Key_L) //right key['l'] = false; if(k==Qt::Key_N)// bullet state 1 { this->you->fireflag=false; // this->you->bulletstate=1; } //key['[']=true; if(k==Qt::Key_M) //bullet state 2 { this->you->fireflag=false; // this->you->bulletstate=2; } if(k==Qt::Key_C) //bullet state 1 { this->me->fireflag=false; this->me->bulletstate=1; } else if(k==Qt::Key_X) //bullet state 2 { this->me->fireflag=false; this->me->bulletstate=2; } break; case DOUBLE_DEFENCE_PLAYER: // player one if(k==Qt::Key_W) //up key['w'] = false; if(k==Qt::Key_S) //down key['s'] = false; if(k==Qt::Key_A) //left key['a'] = false; if(k==Qt::Key_D) //right key['d'] = false; //player tow if(k==Qt::Key_I) //up key['i'] = false; if(k==Qt::Key_K) // down key['k'] = false; if(k==Qt::Key_J) //left key['j'] = false; if(k==Qt::Key_L) //right key['l'] = false; break; default: break; } }
代码有点长,就不再往下贴了。(大家可以到这里下载全部工程文件: 点击打开链接)
这个游戏的主要思路:
动画效果的实现:继承控件widget的paint方法,在每次重绘的时候计算‘流感病毒’和‘红细胞’的位置
病毒追逐红细胞效果的实现:每个流感病毒自己有一个运动方向属性,每次重绘时,计算每个流感病毒的运动方向和自己坐标与红细胞坐标连线之间的夹角,然后将该夹角缩小一定的百分比,然后再计算流感病毒的新坐标,在重绘多次后就可以呈现流感病毒追逐红细胞的效果了。
工程文件里QT小游戏是在windows下编译成功的(当然在linux下也是可以的),用的工具是:qt-windows-opensource-5.0.0-msvc2010_32-x86-offline(默认安装了VS2010),下面给出一个下载地址点击打开链接,如果不能下载网上也有很多,安装后需要编译一遍: