2010年1月22日 星期五

QT4.6自製遊戲開發框架(續)

自制的QGgame_move_line類,已經能偵測許多種碰撞測試,例如碰撞後停止,爆炸,力回饋.......,移動物能自動隨機發射(上下左右)子彈,或被動發射子彈,目前還有很多要加的項目,譬如自動朝一移動物發射子彈,移動物能變換方向,最終會以GNU GPL授權方式,公開源碼,目前還在測試階段,等告一段落就會釋出.

碰撞測試我採用的是矩形碰撞
當2個矩形產生碰撞,一矩形的4頂點的其中一點必定在另一矩形內,當然還要反過來,這樣就簡單的做出碰撞判斷,那如何子彈碰到移動物,移動物會爆炸,QGgame_move_line隨機產生了許多子彈,QGgame_move_line必須讓所有子彈都時時刻刻發出矩形信號(SIGNAL),QGgame_move_line寫一個接收矩形的信號槽(SLOT),讓這2矩形做碰撞測試,若是成立QGgame_move_line就會被kill掉,原理大概就這樣,很多的運算都是直接封裝在QGgame_move_line類,這樣才能顯示這QGgame_move_line的強大.
當然我不是用QTimer或QThread來讓子彈都時時刻刻發出矩形信號,假若是這樣做CPU會LOAD太重.

目睹一下只要使用QGgame_move_line類,幾十行程是就能做出下面遊戲畫面了

soot_game.cpp
------------------------------------------------------------------------------


#include "shoot.h"
#include "ui_shoot.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////shoot game開發框架,利用此框架可輕鬆開發射擊遊戲,發揮你的想像力做出更棒的遊戲////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
shoot::shoot(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::shoot)
{

ui->setupUi(this);
newgv=new QGraphicsView(this);
ui->gridLayout_3->addWidget(newgv);
newgv->setStyleSheet("background-color: rgb(85, 170, 0);");

//birdimg=QPixmap(":/new/prefix1/icon/body.png").scaled(30,30);

//pstart.setX(240);pstart.setY(430);
//pend.setX(240);pend.setY(430);
start_movie();
score=0;
is_game_over=true;

}

shoot::~shoot()
{
delete ui;


}

void shoot::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}

void shoot::on_pushButton_pressed()
{

if(is_game_over){//清除畫面,開始GAME
newgv->deleteLater();
newgv=new QGraphicsView(this);
ui->gridLayout_3->addWidget(newgv);
newgv->setStyleSheet("background-color: rgb(85, 170, 0);");
birdimg=QPixmap(":/new/prefix1/icon/body.png").scaled(30,30);
pstart.setX(240);pstart.setY(430);
pend.setX(240);pend.setY(430);
bulletimg=QPixmap(":/new/prefix1/icon/bullet1.png").scaled(20,40);
//body會發射子彈向上,但不是自動(NOAUTO)
body=new QGame_move_line(bulletimg,"UP","NOAUTO",pstart,pend,1,2000,"KEEPWHENDSTOP",birdimg,newgv);
connect(body,SIGNAL(kill_move()),this,SLOT(game_over()));//body被delete發出信號連到GAME OVER
timer = new QTimer;
timer->start(6000);
this->plan_gen();

connect(timer, SIGNAL(timeout()), this, SLOT(plan_gen()));//一定要用this
is_game_over=false;
}



}
void shoot::game_over()
{

is_game_over=true;
QPixmap gimg=QPixmap(":/new/prefix1/icon/gameover.png").scaled(200,30);
pstart.setX(180);pstart.setY(220);
pend.setX(180);pend.setY(220);
ga=new QGame_move_line(pstart,pend,1,2000,"KEEPWHENDSTOP",gimg,newgv);//產生GAME OVER圖片

disconnect(timer, SIGNAL(timeout()), this, SLOT(plan_gen()));//一定要用this

}
void shoot::keyPressEvent(QKeyEvent* event)
{
if(!is_game_over){


if(body->get_move_obj_x()<540)
{
if(event->key()==Qt::Key_L){body->move_obj_distance("RIGHT",300);} //L鍵往右,故意設大一點300有持續移動,像在駕駛賽車
}
if(body->get_move_obj_x()>0 )
{
if(event->key()==Qt::Key_J){body->move_obj_distance("LEFT",-300);}//J鍵往左,故意設大一點300有持續移動,像在駕駛賽車
}
//按下S鍵,發射子彈
if(this->body->get_bullet_number()<5)//最多5顆
{
if(event->key()==Qt::Key_S){this->body->add_one_bullet();}//或者emit
}
}
}
void shoot::keyReleaseEvent( QKeyEvent* event )//可用此鬆開key就暫停賽車移動
{
if(!is_game_over){
if(event->key()==Qt::Key_L)body->set_move_stop(); //放開L鍵,停止body移動
if(event->key()==Qt::Key_J)body->set_move_stop(); //放開J鍵,停止body移動
}

}
void shoot::plan_gen()
{
int d=qrand()%100;
int loop_no=qrand()%10+1;
int speed=qrand()%2000+1000;
//move1 移動2次,來回移動,會自動掉子彈的直昇機
birdimg=QPixmap(":/new/prefix1/icon/plan.png").scaled(50,50); //直昇機圖
bulletimg=QPixmap(":/new/prefix1/icon/bullet.png").scaled(20,40);//子彈圖
if(qrand()%100 >50)
{
pstart.setX(0);pstart.setY(60+d);//移動開始點
pend.setX(560);pend.setY(60+d); //移動結束點
}else
{
pstart.setX(560);pstart.setY(60+d);//移動開始點
pend.setX(0);pend.setY(60+d); //移動結束點
}
//產生會自動掉向下子彈的直昇機(DOWN,AUTO),移動2次,一直重複移動
move1=new QGame_move_line(bulletimg,"DOWN","AUTO",pstart,pend,loop_no,speed,"RETURN",birdimg,newgv);
//plan_gen_connect();
connect(move1,SIGNAL(move_obj_qrect(QRect)),body,SLOT(collision_boom(QRect)));//這是直昇機撞到機台,這裡沒作用
//connect(body,SIGNAL(move_obj_qrect(QRect)),move1,SLOT(bullet_collision(QRect)));//機台連到子彈
//connect(move1,SIGNAL(emit_bullet_collision()),body,SLOT(clear_move_obj()));//子彈連到機台
connect(move1,SIGNAL(bullet_obj_qrect(QRect)),body,SLOT(collision_boom(QRect)));//子彈連到機台,子彈碰撞機台,機台消失
connect(body,SIGNAL(bullet_obj_qrect(QRect)),move1,SLOT(collision_boom(QRect)));//子彈連到直昇機,子彈碰撞直昇機,直昇機消失
connect(move1,SIGNAL(kill_move()),this,SLOT(gain_score()));//得分

}
void shoot::start_movie()//開頭動畫
{

QPixmap gimg=QPixmap(":/new/prefix1/icon/play1.png").scaled(200,30);
pstart.setX(180);pstart.setY(220);
pend.setX(180);pend.setY(220);
ga=new QGame_move_line(pstart,pend,1,2000,"KEEPWHENDSTOP",gimg,newgv);//產生GAME OVER圖片






int d=qrand()%100;
int loop_no=qrand()%10+1;
int speed=qrand()%2000+1000;
//move1 移動2次,來回移動,會自動掉子彈的直昇機
birdimg=QPixmap(":/new/prefix1/icon/plan.png").scaled(50,50); //直昇機圖
bulletimg=QPixmap(":/new/prefix1/icon/bullet.png").scaled(20,40);//子彈圖
if(qrand()%100 >50)
{
pstart.setX(0);pstart.setY(60+d);//移動開始點
pend.setX(560);pend.setY(60+d); //移動結束點
}else
{
pstart.setX(560);pstart.setY(60+d);//移動開始點
pend.setX(0);pend.setY(60+d); //移動結束點
}
//產生會自動掉向下子彈的直昇機(DOWN,AUTO),移動2次,一直重複移動
move1=new QGame_move_line(bulletimg,"DOWN","AUTO",pstart,pend,loop_no,speed,"RETURN",birdimg,newgv);


}

void shoot::gain_score()
{
score++;
ui->label_2->setText(QString::number(score));

}










沒有留言: