一、实验目的
1.了解 qt 图形开发基本原理
2.掌握 C++的整体架构
3.深入理解 C++对象的机制和实现方法
二、实验原理
本实验以树莓派作为控制器,以 qt crearor 作为开发工具,完成一个飞机大战的小游戏。
三、使用仪器、材料
1.树莓派开发板
2. qt crearor
四、实验步骤
(1)实现玩家类的创建并能控制其移动
(2)实现敌机类的创建及其自动移动
(3)实现敌机和玩家的碰撞检测
(4)实现子弹类的创建及子弹和敌机、子弹和玩家的碰撞检测
(5)实现敌机的随机创建和销毁
(6)实现子弹的创建和销毁
(7)添加文字和背景图片,完成基本的界面美化
五、实验过程原始记录(计算机源代码)
#ifndef BULLET_H
#define BULLET_H//子弹类
#include "config.h"//导入配置文件
#include <QPixmap>
class bullet
{
public:
bullet();
QPixmap m_bullet;
QRect rect;
int x;//坐标
int y;
int speed;//速度
bool free;
void setPosistion();//设置位置
};
#endif // BULLET_H
#ifndef CONFIG_H
#define CONFIG_H//配置类
enum Direction//定义方向上下左右
{
DOWN,
UP,
LEFT,
RIGHT
};
//定义一些基本参数
#define ENEMYBULLET_INTERVAL 5
#define ENEMY_APPEAR 50
#define ENEMY_NUM 15
#define ENMEY_INTERVAL 30
#define BUL_NUM 30
#define BUL_SPEED 5
#define MAP_SPEED 2
#define GAME_RATE 10
#define ENEMY_SPEED 5
#define BULLET_NUM 5
#define BUL_INTERVAL 20
#define GAME_WIDTH 480
#define PLANE_SPEED 10
#define GAME_HEIGTH 650
#define BULLET_SPEED 5
#define ONCE_FINALHIT 5
#define FINALHIT_NUM 10
#define TOTAL_FINALHIT 50
#define FINALHIT_SPEED 10
//定义飞机大战中所用的图片
#define GAME_TITLE "飞机大战"
#define MAP_PATH ":/res/map.jpg"
#define GAME_ICO ":/res/game.ico"
#define BULLET_PATH ":/res/bullet.png"
#define ENEMY_PATH ":/res/1.png"
#define HEROPLANE_PATH ":/res/heroplane.png"
#define PLANEDEATH_PATH ":/res/plane_death.png"
#define ENEMYDEATH_PATH ":/res/enemy_death.png"
#define ENEMYBULLET_PATH ":/res/enemy_bullet.png"
#endif // CONFIG_H
#ifndef ENEMY_H
#define ENEMY_H//敌机类
#include "config.h"
#include <QPixmap>
#include "enemybullet.h"
class Enemy
{
public:
Enemy();
QPixmap pic;
QRect rect;
EnemyBullet bul[BUL_NUM];//定义敌机子弹数组,
QPixmap pic_death;
int x;//定义坐标
int y;
int speed;// 速度
bool free;
bool death;//是否死亡
int recorder;//再次还原
void shoot();//射击函数
void explode();
void updatePosistion();//更新位置
void allDeath();//敌机死亡
};
#endif // ENEMY_H
#ifndef ENEMYBULLET_H
#define ENEMYBULLET_H//敌机子弹类
#include <QPixmap>
#include "bullet.h"
class EnemyBullet : public bullet//继承子弹类
{
public:
EnemyBullet();
void setPosistion();//设置子弹位置,
void allDisappear();//子弹消失
};
#endif // ENEMYBULLET_H
#ifndef FINALHIT_H//大招类
#define FINALHIT_H
#include "finalhit.h"
#include <QPixmap>
#include "config.h"
class FinalHit
{
public:
FinalHit();
QPixmap finalHit;
QRect rect;
int x;//定义坐标
int y;
int speed;//速度
bool free;
void updatePosistion();//更新位置
};
#endif
#ifndef HEROPLANE_H
#define HEROPLANE_H//本机类
#include "config.h"
#include <QPixmap>
#include <QKeyEvent>
#include "bullet.h"
#include "finalhit.h"
class HeroPlane
{
public:
HeroPlane();
QPixmap plane;
QPixmap plane_death;
QRect rect;
QRect death_rect;
int x;//定义坐标
int y;
int life;//生命值
bool death;//生命值
int finahit_num;//大招数量
void shoot();//射击函数
void final_hit();//大招函数
bullet m_bullet[BULLET_NUM];//子弹数组
FinalHit m_finalhit[TOTAL_FINALHIT];//大招数组
};
#endif // HEROPLANE_H
#ifndef MAINSCENE_H
#define MAINSCENE_H//基础控制类:
#include <QMainWindow>
#include <QTimer>
#include "map.h"//地图类
#include "heroplane.h"//本机类
#include <QKeyEvent>
#include "bullet.h"//子弹类
#include "enemy.h"//敌机类
#include <QProgressBar>
namespace Ui {
class MainScene;
}
class MainScene : public QMainWindow
{
Q_OBJECT
public:
explicit MainScene(QWidget *parent = 0);
~MainScene();
QTimer enemy_timer;//定义敌机定时器,用于增加敌机数量、显示爆炸
QTimer timer;//本机定时器,用于移动飞机、判断战机和敌机、敌机和子弹是否发生碰撞
Map map;//地图
HeroPlane plane;//地图
bullet m_bullet[BULLET_NUM];//子弹数组
Enemy enemy[ENEMY_NUM];//敌机数组
Enemy m;
int enemy_recorder;//定义敌机的恢复数量
void Init_Scene();//初始化屏幕函数
void keyPressEvent(QKeyEvent *event);//键盘点击事件
void mouseMoveEvent(QMouseEvent *event);//鼠标点击事件
void crash();//敌机碰撞
public slots://定义slots创建用于接收的槽函数
void play_game();//开始游戏
void updatePosistion();//更新本机位置更新本机位置
void paintEvent(QPaintEvent *event);
void enemy_updatePosistion();//更新敌机位置
private:
Ui::MainScene *ui;
};
#endif // MAINSCENE_H
#ifndef MAP_H
#define MAP_H//背景图类
#include <QPixmap>
class Map
{
public:
Map();
QPixmap map1;//定义两张背景图
QPixmap map2;
int map1_y;//定义两张背景图的移动位置
int map2_y;
int speed;//背景图的移动速度
void updataPosistion();//更新背景图位置
};
#endif // MAP_H
#include "map.h"
#include "config.h"
Map::Map()
{
map1.load(MAP_PATH);//采用两张图片
map2.load(MAP_PATH);
map1_y = 0;//初始化图片位置一张在桌面水平线上,一张在桌面水平线下
map2_y = -GAME_HEIGTH;
}
void Map::updataPosistion()//更新背景图位置
{
map1_y += MAP_SPEED;//一张图片不断往下移动,另一张不断从上补充
if(map1_y >= GAME_HEIGTH)
{
map1_y = 0;
}
map2_y += MAP_SPEED;
if(map2_y >= 0)
{
map2_y = -GAME_HEIGTH;
}
}
#include "mainscene.h"
#include "ui_mainscene.h"
#include "config.h"
#include <QPainter>
#include <QDebug>
#include <ctime>
#include <QProgressBar>
#include <QPixmap>
MainScene::MainScene(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainScene)
{
ui->setupUi(this);
enemy_recorder = 10;//初始化敌机数量10个,
Init_Scene();
m.pic.load(":/res/1.png");//初始化屏幕,设置碰撞的结果图片,设置碰撞结果图的长度和宽度
m.rect.setWidth(m.pic.width());
m.rect.setHeight(m.pic.height());
m.rect.moveTo(0, 0);
}
MainScene::~MainScene()
{
delete ui;
}
void MainScene::Init_Scene()//初始化屏幕的函数
{
setFixedSize(GAME_WIDTH, GAME_HEIGTH);//设置字体大小,窗口标题,窗口图标
setWindowTitle(GAME_TITLE);
setWindowIcon(QIcon(GAME_ICO));
ui->liftProcess->setOrientation(Qt::Vertical);
ui->liftProcess->setRange(0, 20);
ui->liftProcess->setValue(20);
ui->liftProcess->setFixedSize(10, 250);
ui->liftProcess->move(460, 0);
ui->liftProcess->setTextVisible(false);
connect(&timer, &QTimer::timeout, [=]()//连接本机的定时器更新本机位置
{
updatePosistion();
update();
crash();
});
timer.start(GAME_RATE);//启动定时器
connect(&enemy_timer, &QTimer::timeout, [=]()//连接敌机的定时器更新敌机位置
{
enemy_updatePosistion();
});
enemy_timer.start(ENEMY_APPEAR);//启动敌机定时器
qsrand(time(NULL));
}
void MainScene::play_game()//启动游戏的函数
{
connect(&timer, &QTimer::timeout, [=]()//连接定时器更新位置
{
updatePosistion();
});
timer.start(GAME_RATE);//启动定时器
}
void MainScene::updatePosistion()//更新位置的函数
{
map.updataPosistion();//先更新背景图的位置
for(int i=0; i<BULLET_NUM; i++)//更新子弹的位置
{
if(!plane.m_bullet[i].free)
{
plane.m_bullet[i].setPosistion();
}
}
for(int i=0; i<TOTAL_FINALHIT; i++)//更新本机大招的位置
{
if(!plane.m_finalhit[i].free)
{
plane.m_finalhit[i].updatePosistion();
}
}
for(int i=0; i<ENEMY_NUM; i++)//更新敌机子弹的位置
{
for(int j=0; j<BULLET_NUM; j++)
{
if(!enemy[i].bul[j].free)
{
enemy[i].bul[j].setPosistion();
}
}
}
}
void MainScene::paintEvent(QPaintEvent *event){
//重绘事件
static int count = 0;
QPainter painters(this);
//绘制动态背景
painters.drawPixmap(0, 0, m.pic);
painters.drawPixmap(0, map.map1_y, map.map1);
painters.drawPixmap(0, map.map2_y, map.map2);
//绘制我方飞机活着和死亡的状态
if(plane.death){
painters.drawPixmap(plane.x, plane.y, plane.plane_death);
enemy_timer.stop();
timer.stop();
}else{
painters.drawPixmap(plane.x, plane.y, plane.plane);
}
//绘制我方子弹
for(int i=0; i<BULLET_NUM; i++){
if(!plane.m_bullet[i].free){
painters.drawPixmap(plane.m_bullet[i].x, plane.m_bullet[i].y, plane.m_bullet[i].m_bullet);
}
}
//绘制我方大招
for(int i=0; i<TOTAL_FINALHIT; i++){
if(!plane.m_finalhit[i].free){
painters.drawPixmap(plane.m_finalhit[i].x, plane.m_finalhit[i].y, plane.m_finalhit[i].finalHit);
}
}
//绘制敌方飞机活着和死亡的状态,绘制敌方子弹
for(int i=0; i<ENEMY_NUM; i++){
if(!enemy[i].free){
painters.drawPixmap(enemy[i].x, enemy[i].y, enemy[i].pic);
}
for(int j=0; j<BULLET_NUM; j++){
if(!enemy[i].bul[j].free){
painters.drawPixmap(enemy[i].bul[j].x, enemy[i].bul[j].y, enemy[i].bul[j].m_bullet);
}
}
if(enemy[i].death){
count++;
if(count >= 10){
count = 0;
enemy[i].death = false;
}
painters.drawPixmap(enemy[i].x, enemy[i].y, enemy[i].pic_death);
}
}
}
void MainScene::mouseMoveEvent(QMouseEvent *event){
// 鼠标点击事件的函数
if(event->x()>=plane.x && event->x()<=(plane.x+60) && event->y()>=plane.y && event->y()<=plane.y+85){
plane.x = event->x() - plane.rect.width() *0.5; //鼠标位置 - 飞机矩形的一半
plane.y = event->y() - plane.rect.height()*0.5;
//进行边界检测
if(plane.x <= 0 ){
plane.x = 0;
}
if(plane.x >= GAME_WIDTH - plane.rect.width()){
plane.x = GAME_WIDTH - plane.rect.width();
}
if(plane.y <= 0){
plane.y = 0;
}
if(plane.y >= GAME_HEIGTH - plane.rect.height()){
plane.y = GAME_HEIGTH - plane.rect.height();
}
qDebug() << "x = " << plane.x << "y = " << plane.y;
plane.rect.moveTo(plane.x, plane.y);
}
}
void MainScene::keyPressEvent(QKeyEvent *event){
//键盘点击事件的函数
if(event->key() == Qt::Key_W) //up,键盘上点击W、S、A、D分别对应我方飞机上、下、左、右移动功能
{
if(plane.y >= plane.rect.width()){
plane.y -= PLANE_SPEED;
}
}
else if(event->key() == Qt::Key_S) //down
{
if(plane.y <= (GAME_HEIGTH-plane.rect.height())){
plane.y += PLANE_SPEED;
}
}
else if(event->key() == Qt::Key_A) //left
{
if(plane.x >= 0){
plane.x -= PLANE_SPEED;
}
}
else if(event->key() == Qt::Key_D){
//right
if(plane.x <= GAME_WIDTH-plane.rect.width()){
plane.x += PLANE_SPEED;
}
}
else if(event->key() == Qt::Key_J){
//键盘上点击J发射子弹
plane.shoot();
}
else if(event->key() == Qt::Key_K){
//键盘上点击K发射大招
if(plane.finahit_num > 0){
plane.finahit_num--;
plane.final_hit();
for(int i=0; i<ENEMY_NUM; i++){
if(!enemy[i].free){
enemy[i].allDeath();
}
for(int j=0; j<BULLET_NUM; j++){
enemy[i].bul[j].allDisappear();
}
}
}
}
plane.rect.moveTo(plane.x, plane.y);
}
void MainScene::enemy_updatePosistion(){
//更新敌方飞机位置的函数,
for(int j=0; j<ENEMY_NUM; j++){
//如果我方飞机放了大招,敌机清零,
if(enemy[j].recorder > ENEMYBULLET_INTERVAL && (!enemy[j].free)){
enemy[j].recorder = 0;
enemy[j].shoot();
}
if(!enemy[j].free){
//如果敌机为空,那么增加敌机数量并且更新敌机位置
enemy[j].recorder++;
enemy[j].updatePosistion();
}
}
enemy_recorder++;
if(enemy_recorder >= 10){
enemy_recorder = 0;
for(int i=0; i<ENEMY_NUM; i++){
if(enemy[i].free){
enemy[i].free = false;
enemy[i].x = qrand() % (GAME_WIDTH-enemy[i].rect.width());
enemy[i].y = 0;
enemy[i].speed = (qrand()%2) ? ENEMY_SPEED : -ENEMY_SPEED;
enemy[i].rect.moveTo(enemy[i].x, enemy[i].y);
break;
}
}
}
}
void MainScene::crash()//检测碰撞的函数,
{
for(int j=0; j<BULLET_NUM; j++){
//第一部分检测我方飞机子弹和敌机相撞的爆炸
if(!plane.m_bullet[j].free){
//遍历我方飞机子弹
for(int i=0; i<ENEMY_NUM; i++){
if(!enemy[i].free){
//如果检测到与敌方飞机相撞,让这架敌机消失free,并标记其死亡
if(enemy[i].rect.intersects(plane.m_bullet[j].rect)){
enemy[i].free = true;
plane.m_bullet[j].free = true;
enemy[i].death = true;
break;
}
}
}
}
}
for(int j=0; j<ENEMY_NUM; j++) {
//第二部分检测我方飞机和敌机相撞的爆炸
if(!enemy[j].free) {
//遍历敌方飞机
if(enemy[j].rect.intersects(plane.rect)){
//如果检测到与敌方飞机相撞,让这架敌机消失free,并标记其死亡,同时我方飞机的生命值减2
enemy[j].free = true;
enemy[j].death = true;
plane.life -= 2;
ui->liftProcess->setValue(plane.life);
if(plane.life <= 5 && plane.life > 0){
ui->liftProcess->setStyleSheet("QProgressBar::chunk { background-color: rgb(255, 0, 0) }");
}
else if(plane.life <= 0){
ui->liftProcess->setValue(0);
plane.death = true;
}
}
}
}
for(int j=0; j<ENEMY_NUM; j++) {
//第三部分检测我方飞机和敌机子弹相撞的爆炸
for(int i=0; i<BULLET_NUM; i++){
//遍历敌方飞机和敌方子弹
if((!enemy[j].free) && (!enemy[j].bul[i].free)){
if(plane.rect.intersects(enemy[j].bul[i].rect)){
//如果检测到与敌方飞机的子弹相撞,只让我方飞机的生命值减1,敌方飞机保持不变
enemy[j].bul[i].free = true;
plane.life--;
ui->liftProcess->setValue(plane.life);
if(plane.life <= 5 && plane.life > 0){
ui->liftProcess->setStyleSheet("QProgressBar::chunk { background-color: rgb(255, 0, 0) }");
}
else if(plane.life <= 0){
plane.death = true;
}
}
}
}
}
}
实验结果
转载:https://blog.csdn.net/lf18879954995/article/details/115936011
查看评论