高级程序设计——打飞机小游戏

实验报告(151220129 吴政亿)

一、实验要求

课程设计一

设计一个基于控制台的飞机游戏。
要求:
1. 包含玩家飞机、敌机、子弹等元素。
2. 设计过程中考虑向MFC显式的扩展性。
3. 鼓励设计其他包含交互操作的小游戏。

上传时请只上传项目文件、代码文件以及其他编译必须的文件,不要包含项目编译过程中生成的中间文件。提交文件大小限制为40MB。

课程设计二

  1. 要求在课程设计一的基础上,以windows编程、事件驱动的程序设计为基础,实现一个带有GUI界面的程序设计。
  2. 请注意保持与课程设计一的一致性。在程序设计过程中注意思考与课程设计一的联系,并尝试复用之前的代码。
  3. 如有其他设计题目、或者希望使用其他的编程环境(比如QT或者IOS等),请单独与我联系。
  4. 请使用word/txt完成实验报告一份,主要描述课程设计一和二的设计实现过程,建议包括以下内容:
    1. 课程设计的内容和目标。
    2. 类层次关系和实现。
    3. 课程设计一和二的关联和衔接。
    4. 遇到的问题和思考。

上传时请只上传实验报告、项目文件、代码文件以及其他编译必须的文件,不要包含项目编译过程中生成的中间文件。请注意提交最大大小为40MB。

学期结束前(6月24日)将安排课堂报告展示环节,建议提前做好准备。

二、设计目标

课程设计一

定义了三个类(Face、Game、Pos),结构关系如下所示

//定义界面类,负责开始界面等
class Face
{
    friend class POS;
public:
    Face();
    ~Face();
    static void drawPlaying();//绘制游戏界面
    static int drawWelcome();//绘制欢迎界面
    static void drawMyPlane(int x, int y);//绘制我方飞机
    static void drawEmeyPlane(int x, int y);//绘制敌方飞机
};
//定义游戏类
class Game
{
public:
    COORD position[10];
    COORD bullet[10];
    Frame enemy[8];
    int score;
    int rank;
    int rankf;
    string title;
    int flag_rank;

    Game();

    //初始化所有
    void initPlane();
    void initBullet();
    void initEnemy();

    //初始化其中一个
    //void initThisBullet( COORD );
    //void initThisEnemy( Frame );

    void planeMove(char);
    void bulletMove();
    void enemyMove();

    //判断碰撞函数
    bool judgeCoordInFrame(Frame frame, COORD spot);

    //填充所有
    void drawPlane();
    void drawPlaneToNull();
    void drawBullet();
    void drawBulletToNull();
    void drawEnemy();
    void drawEnemyToNull();

    //填充其中一个
    void drawThisBulletToNull(COORD);
    void drawThisEnemyToNull(Frame);

    void Pause();//游戏暂停
    void Playing();//游戏开始
    void judgePlane();//判断飞机是否坠毁
    void judgeEnemy();//判断敌机是否坠毁
    void Shoot();//射击
    void GameOver();//游戏结束
    void printScore();//打印得分
};
typedef struct
{
    COORD position[11];
    int flag;
}Frame;
//在POS中主要封装了对光标和坐标的一些操作
class POS
{
public:
    //移动光标
    static void SetPos(COORD a);
    //移动光标
    static void SetPos(int i, int j);
    //隐藏光标
    static void HideCursor();
    //把第y行,[x1, x2) 之间的坐标填充为 ch
    static void drawRow(int y, int x1, int x2, char ch);
    //在a, b 纵坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
    static void drawRow(COORD a, COORD b, char ch);
    //把第x列,[y1, y2] 之间的坐标填充为 ch
    static void drawCol(int x, int y1, int y2, char ch);
    //在a, b 横坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
    static void drawCol(COORD a, COORD b, char ch);
    //左上角坐标、右下角坐标、用row填充行、用col填充列
    static void drawFrame(COORD a, COORD b, char row, char col);
    //左上角坐标(x1,y1)、右下角坐标(x2,y2)、用row填充行、用col填充列
    static void drawFrame(int x1, int y1, int x2, int y2, char row, char col);
    static void drawFrame(Frame frame, char row, char col);
    //生成随机数a到b
    static int random(int a, int b);
    //在a,b定义的矩形中随机生成一点
    static COORD random(COORD a, COORD b);
};

我将本游戏划分为三个对象,一个对象是界面对象Face,负责欢迎界面等绘制,由于控制台的特性,我需要单独封装一个Pos类来实现各种操作如光标移动等,最后游戏被我单独封装成一个类。

其中,Game类使用Face类成员函数,Face类使用Pos类成员函数。

课程设计二

在课程设计二我使用了QT Creator 结合C++进行了打飞机小游戏的GUI设计,由于界面的实现,在课程设计一中的Face类和Pos类在QT Creator中没有意义,因此我的打飞机小游戏GUI版主要为两个类,分别对应了两个不同的ui界面。

欢迎界面

欢迎界面

在中间的两个按钮分别对应两个事件,这决定了敌方飞机飞行的速度为5还是10.

游戏界面

游戏界面

可见,右侧显示了一系列信息,击落敌机的数量,得分以及获得的称号。随着分数的上升称号变为中级飞行员到高级飞行员。
在操作飞机上,我使用了QT的私有槽函数

void keyPressEvent(QKeyEvent *k);

这个函数负责接收我的键盘信息,提供飞机上下左右飞行、射击等等,具体可以看上图右下角的操作方式。

另外,我使用了QT的QObject类封装的Timer类来实现程序的一系列时钟问题,槽函数如下:

void timerEvent(QTimerEvent *event);

这个槽函数不断的接受时间事件。在本游戏中,我有一个timeid = startTimer(50); 来负责最基础的时钟功能,每触发一次,控制所有敌方飞机向前飞翔,控制子弹前进,并且判断是否有碰撞,代码如下。

//  子弹移动
for(int i=0;i<NUM_buttle;i++){
   if(!buttle[i]->isHidden()){
       if(buttle[i]->y() < -100)
           buttle[i]->hide();
       else
           buttle[i]->move(buttle[i]->x(),buttle[i]->y()-Value_buttle);
   }
}
judgebullet();
judgeplane();
//敌机移动
for(int j=0;j<NUM_enemy;j++){
   if(!enemy[j]->isHidden()){
       if(enemy[j]->y()>660){
           enemy[j]->move(random(0,630),random(-200,-100));
       }
       else
           enemy[j]->move(enemy[j]->x(),enemy[j]->y()+Value_enemy);
   }
}
//刷新称号
if(score > 200 && score < 1000)
   ui->honor->setText(QString("中级飞行员"));
else if(score > 1000)
   ui->honor->setText(QString("高级飞行员"));

另外一个时钟是负责爆炸效果的显示,一开始我使用了QT中的QMovie类,播放我在网上下载的boom.gif

boom.gif

但是这里会出现一个非常严重的问题,就是它的背景黑色部分无法去除,而且无法随着飞机的大小变换自己的大小,因此我采取了另一种较为折衷(low)的办法,就是先使用PS将gif图每一帧单独保存为png格式并且除去他们的背景,然后在触发爆炸后,先得到爆炸发生的位置与大小,然后用QLabel控件在相应的位置播放爆炸效果图,设置一个时钟boomid=startTimer(100); 每触发一次将它的播放的当前帧转化为下一帧,最后结束。

三、课程设计一和二的关联衔接

在两次设计中,由于第一次课程设计的思路比较清晰,封装的比较好,在第二次课程设计中代码复用的比较简单。

Created with Raphaël 2.1.0 课程设计一 课程设计一 课程设计二 课程设计二 包含Pos、Face、Game类 包含Dialog类与Mainwindow类 Pos类与Face类由ui界面代替 之前的光标操作变为对ui控件的操作 Game类提升为Dialog类 飞机的射击、移动等转化为事件控制

在课程设计二中、在游戏类中整体的封装依旧与课程设计一保持一致性:

    void initPlane();
    void initLabel();
    void initEnemy();
    void initButtle();
    void restart();
    int timeid;
    int boomid;

    void judgeplane();
    void judgebullet();
    void shoot();
    void pause();
    void gameover();

四、思考总结

在本次实验中,深切体会到了老师上课所讲的有关代码复用以及封装等知识。只要前期思路清晰,封装得当,在后期写界面的时候代码复用十分方便。并且整体的构架不变。另外在本次实验中,也学习到了不少QT的知识,如控件背景透明、图片拉伸,时间事件使用等等,受益匪浅。

五、代码清单

课程设计一

Face.h

#pragma once
#include"pos.h"
class Face
{
    friend class POS;
public:
    Face();
    ~Face();
    static void drawPlaying();
    static int drawWelcome();
    static void drawMyPlane(int x, int y);
    static void drawEmeyPlane(int x, int y);
};

Face.cpp

#include "Face.h"
Face::Face()
{
}

Face::~Face()
{
}

void Face::drawPlaying()
{
    POS::drawFrame(0, 0, 48, 24, '=', '|');//   draw map frame;
    POS::drawFrame(49, 0, 79, 4, '-', '|');//       draw output frame
    POS::drawFrame(49, 4, 79, 9, '-', '|');//       draw score frame
    POS::drawFrame(49, 9, 79, 20, '-', '|');//  draw operate frame
    POS::drawFrame(49, 20, 79, 24, '-', '|');// draw other message frame
    POS::SetPos(52, 6);
    cout << "得分:";
    POS::SetPos(52, 7);
    cout << "称号:";
    POS::SetPos(52, 10);
    cout << "操作方式:";
    POS::SetPos(52, 12);
    cout << "  a,s,d,w 控制战机移动。";
    POS::SetPos(52, 14);
    cout << "  p 暂停游戏。";
    POS::SetPos(52, 16);
    cout << "  e 退出游戏。";
    POS::HideCursor();
}

int Face::drawWelcome()
{
    int level = -1;
    POS::drawFrame(0, 0, 79, 24, '=', '|');//   draw map frame;
    POS::SetPos(15, 10);
    cout << "请输入您选择的难度级别,级别为1-100" ;
    POS::SetPos(30, 11);
    cin >> level;
    level = 101 - level;
    while (level < 0 || level >2147483000) {
        POS::SetPos(35, 11);
        cout << "请输入您选择的难度级别,级别为1-100" ;
        POS::SetPos(30, 10);
        cin >> level;
    }
    return level;
}

void Face::drawMyPlane(int x, int y)
{
    POS::SetPos(x, y - 1);
    cout << "||";
    POS::SetPos(x - 2 , y);
    cout << "OO||OO";
    POS::SetPos(x - 1, y + 1);
    cout << "O||O" ;
    POS::HideCursor();
}

void Face::drawEmeyPlane(int x, int y)
{
    POS::SetPos(x - 1 , y - 1);
    cout << "O||O";
    POS::SetPos(x-2, y);
    cout << "OO||OO";
    POS::SetPos(x, y + 1);
    cout << "||";
    POS::HideCursor();
}

pos.h

#pragma once

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <string>
using namespace std;

typedef struct
{
    COORD position[11];
    int flag;
}Frame;

class POS
{
public:
    //移动光标
    static void SetPos(COORD a);
    //移动光标
    static void SetPos(int i, int j);
    //隐藏光标
    static void HideCursor();
    //把第y行,[x1, x2) 之间的坐标填充为 ch
    static void drawRow(int y, int x1, int x2, char ch);
    //在a, b 纵坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
    static void drawRow(COORD a, COORD b, char ch);
    //把第x列,[y1, y2] 之间的坐标填充为 ch
    static void drawCol(int x, int y1, int y2, char ch);
    //在a, b 横坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
    static void drawCol(COORD a, COORD b, char ch);
    //左上角坐标、右下角坐标、用row填充行、用col填充列
    static void drawFrame(COORD a, COORD b, char row, char col);
    //左上角坐标(x1,y1)、右下角坐标(x2,y2)、用row填充行、用col填充列
    static void drawFrame(int x1, int y1, int x2, int y2, char row, char col);

    static void drawFrame(Frame frame, char row, char col);

    static int random(int a, int b);

    static COORD random(COORD a, COORD b);

};

pos.cpp

#include "pos.h"
#include <assert.h>

void POS::SetPos(COORD a)// set cursor 
{
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(out, a);
}

void POS::SetPos(int i, int j)// set cursor
{
    COORD pos = { i, j };
    SetPos(pos);
}

void POS::HideCursor() //隐藏光标
{
    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

//把第y行,[x1, x2) 之间的坐标填充为 ch
void POS::drawRow(int y, int x1, int x2, char ch)
{
    SetPos(x1, y);
    for (int i = 0; i <= (x2 - x1); i++)
        cout << ch;
}

//在a, b 纵坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
void POS::drawRow(COORD a, COORD b, char ch)
{
    assert(a.Y == b.Y);
    drawRow(a.Y, a.X, b.X, ch);
}

//把第x列,[y1, y2] 之间的坐标填充为 ch
void POS::drawCol(int x, int y1, int y2, char ch)
{
    assert(y1 <= y2);
    for (int y = y1; y <= y2; y++) {
        SetPos(x, y);
        cout << ch;
    }
}

//在a, b 横坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
void POS::drawCol(COORD a, COORD b, char ch)
{
    assert(a.X == b.X);
    drawCol(a.X, a.Y, b.Y, ch);
}

//左上角坐标、右下角坐标、用row填充行、用col填充列
void POS::drawFrame(COORD a, COORD  b, char row, char col)
{
    drawRow(a.Y, a.X + 1, b.X - 1, row);
    drawRow(b.Y, a.X + 1, b.X - 1, row);
    drawCol(a.X, a.Y + 1, b.Y - 1, col);
    drawCol(b.X, a.Y + 1, b.Y - 1, col);
}

void POS::drawFrame(int x1, int y1, int x2, int y2, char row, char col)
{
    COORD a = { x1, y1 };
    COORD b = { x2, y2 };
    drawFrame(a, b, row, col);
}

void POS::drawFrame(Frame frame, char row, char col)
{
    COORD a = frame.position[0];
    COORD b = frame.position[1];
    drawFrame(a, b, row, col);
}

//在[a, b)之间产生一个随机整数
int POS::random(int a, int b)
{
    int c = (rand() % (a - b)) + a;
    return c;
}

//在两个坐标包括的矩形框内随机产生一个坐标
COORD POS::random(COORD a, COORD b)
{
    int x = random(a.X, b.X);
    int y = random(a.Y, b.Y);
    COORD c = { x, y };
    return c;
}

Game.h

#pragma once
#include "Face.h"

class Game
{
public:
    COORD position[10];
    COORD bullet[10];
    Frame enemy[8];
    int score;
    int rank;
    int rankf;
    string title;
    int flag_rank;

    Game();

    //初始化所有
    void initPlane();
    void initBullet();
    void initEnemy();

    //初始化其中一个
    //void initThisBullet( COORD );
    //void initThisEnemy( Frame );

    void planeMove(char);
    void bulletMove();
    void enemyMove();

    bool judgeCoordInFrame(Frame frame, COORD spot);

    //填充所有
    void drawPlane();
    void drawPlaneToNull();
    void drawBullet();
    void drawBulletToNull();
    void drawEnemy();
    void drawEnemyToNull();

    //填充其中一个
    void drawThisBulletToNull(COORD);
    void drawThisEnemyToNull(Frame);

    void Pause();
    void Playing();
    void judgePlane();
    void judgeEnemy();

    void Shoot();

    void GameOver();
    void printScore();
};

Game.cpp

#include "Game.h"

Game::Game()
{
    initPlane();
    initBullet();
    initEnemy();
    score = 0;
    rank = 25;
    rankf = 0;
    flag_rank = 0;
}

void Game::initPlane()
{
    COORD centren = { 39, 22 };
    position[0].X = position[5].X = position[7].X = position[9].X = centren.X;
    position[1].X = centren.X - 2;
    position[2].X = position[6].X = centren.X - 1;
    position[3].X = position[8].X = centren.X + 1;
    position[4].X = centren.X + 2;
    for (int i = 0; i <= 4; i++)
        position[i].Y = centren.Y;
    for (int i = 6; i <= 8; i++)
        position[i].Y = centren.Y + 1;
    position[5].Y = centren.Y - 1;
    position[9].Y = centren.Y - 2;
}

bool Game::judgeCoordInFrame(Frame frame, COORD spot)
{
    if (spot.X >= frame.position[0].X)
        if (spot.X <= frame.position[1].X)
            if (spot.Y >= frame.position[0].Y)
                if (spot.Y <= frame.position[0].Y)
                    return true;
    return false;
}
void Game::drawPlane()
{
    for (int i = 0; i<9; i++)
    {
        POS::SetPos(position[i]);
        switch (i) {
        case 0:cout << "O"; break;
        case 1:
        case 4:cout << "I"; break;
        case 2:
        case 3:cout << "-"; break;
        case 5:cout << "A"; break;
        case 6:
        case 8:cout << "V"; break;
        case 7:cout << "^"; break;
        }
    }
}

void Game::drawPlaneToNull()
{
    for (int i = 0; i<9; i++)
    {
        POS::SetPos(position[i]);
        cout << " ";
    }
}

void Game::initBullet()
{
    for (int i = 0; i<10; i++)
        bullet[i].Y = 30;
}

void Game::drawBullet()
{
    for (int i = 0; i<10; i++)
    {
        if (bullet[i].Y != 30)
        {
            POS::SetPos(bullet[i]);
            cout << "*";
        }
    }
}

void Game::drawBulletToNull()
{
    for (int i = 0; i<10; i++)
        if (bullet[i].Y != 30)
        {
            COORD pos = { bullet[i].X, bullet[i].Y + 1 };
            POS::SetPos(pos);
            cout << " ";
        }
}


void Game::initEnemy()
{
    COORD a = { 1, 1 };
    COORD b = { 45, 15 };
    for (int i = 0; i<8; i++)
    {
        enemy[i].position[0] = POS::random(a, b);

        enemy[i].position[1].X = enemy[i].position[0].X + 4;
        enemy[i].position[1].Y = enemy[i].position[0].Y + 2;

        enemy[i].position[2].Y = enemy[i].position[3].Y = enemy[i].position[4].Y = enemy[i].position[0].Y;
        for (int j = 5; j < 10; j++)
            enemy[i].position[j].Y = enemy[i].position[0].Y + 1;
        enemy[i].position[10].Y = enemy[i].position[0].Y + 2;

        enemy[i].position[5].X = enemy[i].position[0].X;
        enemy[i].position[2].X = enemy[i].position[6].X = enemy[i].position[0].X + 1;
        enemy[i].position[3].X = enemy[i].position[7].X = enemy[i].position[10].X = enemy[i].position[0].X + 2;
        enemy[i].position[4].X = enemy[i].position[8].X = enemy[i].position[0].X + 3;
        enemy[i].position[9].X = enemy[i].position[0].X + 4;
    }
}
/*
    III
   I=X=I
     I
*/
void Game::drawEnemy()
{
    for (int i = 0; i < 8; i++) {
        for (int j = 2; j < 11; j++) {
            POS::SetPos(enemy[i].position[j]);
            switch (j) {
            case 2:
            case 3:
            case 4:
            case 5:
            case 9:
            case 10:cout << "I"; break;
            case 6:
            case 8:cout << "="; break;
            case 7:cout << "X"; break;
            }
        }

        /*cout << " III " << endl;
        POS::SetPos(enemy[i].position[2]);
        cout << "I=X=I" << endl;
        POS::SetPos(enemy[i].position[3]);
        cout << "  I  ";*/
    }
        //POS::drawFrame(enemy[i].position[0], enemy[i].position[1], '-', '|');
}

void Game::drawEnemyToNull()
{
    for (int i = 0; i<8; i++)
    {
        for (int j = 2; j < 11; j++) {
            POS::SetPos(enemy[i].position[j]);
            cout << " ";
        }
        //POS::drawFrame(enemy[i].position[0], enemy[i].position[1], ' ', ' ');
    }
}

void Game::Pause()
{
    POS::SetPos(61, 2);
    cout << "               ";
    POS::SetPos(61, 2);
    cout << "暂停中...";
    char c = _getch();
    while (c != 'p')
        c = _getch();
    POS::SetPos(61, 2);
    cout << "         ";
}

void Game::planeMove(char x)
{
    if (x == 'a')
        if (position[1].X != 1)
            for (int i = 0; i <= 9; i++)
                position[i].X -= 2;

    if (x == 's')
        if (position[7].Y != 23)
            for (int i = 0; i <= 9; i++)
                position[i].Y += 1;

    if (x == 'd')
        if (position[4].X != 47)
            for (int i = 0; i <= 9; i++)
                position[i].X += 2;

    if (x == 'w')
        if (position[5].Y != 3)
            for (int i = 0; i <= 9; i++)
                position[i].Y -= 1;
}

void Game::bulletMove()
{
    for (int i = 0; i<10; i++)
    {
        if (bullet[i].Y != 30)
        {
            bullet[i].Y -= 1;
            if (bullet[i].Y == 1)
            {
                COORD pos = { bullet[i].X, bullet[i].Y + 1 };
                drawThisBulletToNull(pos);
                bullet[i].Y = 30;
            }

        }
    }
}

void Game::enemyMove()
{
    for (int i = 0; i<8; i++)
    {
        for (int j = 0; j<11; j++)
            enemy[i].position[j].Y++;

        if (24 == enemy[i].position[1].Y)
        {
            COORD a = { 1, 1 };
            COORD b = { 45, 3 };
            enemy[i].position[0] = POS::random(a, b);
            enemy[i].position[1].X = enemy[i].position[0].X + 4;
            enemy[i].position[1].Y = enemy[i].position[0].Y + 2;
            enemy[i].position[2].Y = enemy[i].position[3].Y = enemy[i].position[4].Y = enemy[i].position[0].Y;
            for (int j = 5; j < 10; j++)
                enemy[i].position[j].Y = enemy[i].position[0].Y + 1;
            enemy[i].position[10].Y = enemy[i].position[0].Y + 2;

            enemy[i].position[5].X = enemy[i].position[0].X;
            enemy[i].position[2].X = enemy[i].position[6].X = enemy[i].position[0].X + 1;
            enemy[i].position[3].X = enemy[i].position[7].X = enemy[i].position[10].X = enemy[i].position[0].X + 2;
            enemy[i].position[4].X = enemy[i].position[8].X = enemy[i].position[0].X + 3;
            enemy[i].position[9].X = enemy[i].position[0].X + 4;
        }
    }
}

void Game::judgePlane()
{
    for (int i = 0; i < 8; i++)
        for (int j = 0; j<9; j++)
            if (judgeCoordInFrame(enemy[i], position[j]))
            {
                POS::SetPos(62, 1);
                cout << "坠毁";
                POS::drawFrame(enemy[i], '+', '+');
                Sleep(1000);
                GameOver();
                break;
            }
}

void Game::drawThisBulletToNull(COORD c)
{
    POS::SetPos(c);
    cout << " ";
}

void Game::drawThisEnemyToNull(Frame f)
{
    for (int j = 2; j < 11; j++) {
        POS::SetPos(f.position[j]);
        cout << " ";
    }
    //POS::drawFrame(f, ' ', ' ');
}

void Game::judgeEnemy()
{
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 10; j++)
            if (judgeCoordInFrame(enemy[i], bullet[j]))
            {
                score += 5;
                drawThisEnemyToNull(enemy[i]);
                COORD a = { 1, 1 };
                COORD b = { 45, 3 };
                enemy[i].position[0] = POS::random(a, b);
                enemy[i].position[1].X = enemy[i].position[0].X + 4;
                enemy[i].position[1].Y = enemy[i].position[0].Y + 2;
                enemy[i].position[2].Y = enemy[i].position[3].Y = enemy[i].position[4].Y = enemy[i].position[0].Y;
                for (int j = 5; j < 10; j++)
                    enemy[i].position[j].Y = enemy[i].position[0].Y + 1;
                enemy[i].position[10].Y = enemy[i].position[0].Y + 2;

                enemy[i].position[5].X = enemy[i].position[0].X;
                enemy[i].position[2].X = enemy[i].position[6].X = enemy[i].position[0].X + 1;
                enemy[i].position[3].X = enemy[i].position[7].X = enemy[i].position[10].X = enemy[i].position[0].X + 2;
                enemy[i].position[4].X = enemy[i].position[8].X = enemy[i].position[0].X + 3;
                enemy[i].position[9].X = enemy[i].position[0].X + 4;
                drawThisBulletToNull(bullet[j]);
                bullet[j].Y = 30;
            }
}

void Game::Shoot()
{
    for (int i = 0; i<10; i++)
        if (bullet[i].Y == 30)
        {
            bullet[i].X = position[5].X;
            bullet[i].Y = position[5].Y - 1;
            break;
        }
}

void Game::printScore()
{
    if (score == 120 && flag_rank == 0)
    {
        rank -= 3;
        flag_rank = 1;
    }

    else if (score == 360 && flag_rank == 1)
    {
        rank -= 5;
        flag_rank = 2;
    }
    else if (score == 480 && flag_rank == 2)
    {
        rank -= 5;
        flag_rank = 3;
    }
    int x = rank / 5;
    POS::SetPos(60, 6);
    cout << score;

    if (rank != rankf)
    {
        POS::SetPos(60, 7);
        if (x == 5)
            title = "初级飞行员";
        else if (x == 4)
            title = "中级飞行员";
        else if (x == 3)
            title = "高级飞行员";
        else if (x == 2)
            title = "王牌飞行员";
        cout << title;
    }
    rankf = rank;
}

void Game::Playing()
{
    //HANDLE MFUN;
    //MFUN= CreateThread(NULL, 0, MusicFun, NULL, 0, NULL); 

    drawEnemy();
    drawPlane();

    int flag_bullet = 0;
    int flag_enemy = 0;

    while (1)
    {
        Sleep(8);
        if (_kbhit())
        {
            char x = _getch();
            if ('a' == x || 's' == x || 'd' == x || 'w' == x)
            {
                drawPlaneToNull();
                planeMove(x);
                drawPlane();
                judgePlane();
            }
            else if ('p' == x)
                Pause();
            else if ('k' == x)
                Shoot();
            else if ('e' == x)
            {
                //CloseHandle(MFUN);
                GameOver();
                break;
            }

        }
        /* 处理子弹 */
        if (0 == flag_bullet)
        {
            bulletMove();
            drawBulletToNull();
            drawBullet();
            judgeEnemy();
        }
        flag_bullet++;
        if (5 == flag_bullet)
            flag_bullet = 0;

        /* 处理敌人 */
        if (0 == flag_enemy)
        {
            drawEnemyToNull();
            enemyMove();
            drawEnemy();
            judgePlane();
        }
        flag_enemy++;
        if (flag_enemy >= rank)
            flag_enemy = 0;

        /* 输出得分 */
        printScore();
    }
}

void Game::GameOver()
{
    system("cls");
    COORD p1 = { 28,9 };
    COORD p2 = { 53,15 };
    POS::drawFrame(p1, p2, '=', '|');
    POS::SetPos(36, 12);
    string str = "Game Over!";
    for (int i = 0; i<str.size(); i++)
    {
        Sleep(80);
        cout << str[i];
    }
    Sleep(1000);
    system("cls");
    POS::drawFrame(p1, p2, '=', '|');
    POS::SetPos(31, 11);
    cout << "击落敌机:" << score / 5 << " 架";
    POS::SetPos(31, 12);
    cout << "得  分:" << score;
    POS::SetPos(31, 13);
    cout << "获得称号:" << title;
    POS::SetPos(30, 16);
    Sleep(1000);
    cout << "继续? 是(y)| 否(n)";
as:
    char x = _getch();
    if (x == 'n')
        exit(0);
    else if (x == 'y')
    {
        system("cls");
        Game game;
        int a = Face::drawWelcome();
        game.rank = a;
        system("cls");
        Face::drawPlaying();
        game.Playing();
    }
    else goto as;
}

main.cpp

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <string>
#include "Game.h"
using namespace std;

int main() {
    //游戏准备
    srand((int)time(0));    //随机种子
    POS::HideCursor();  //隐藏光标

    Game game;
    int a = Face::drawWelcome();
    game.rank = a;
    system("cls");
    Face::drawPlaying();
    game.Playing();
    return 0;
}

课程设计二

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QKeyEvent>
#include <QEvent>
#include <QLabel>
#include <QPainter>
#include <QKeyEvent>
#include <QDebug>
#include <QSize>
#include <QTimer>
#include <QLabel>
#include <QMovie>
#include <QDebug>

#define NUM_enemy 6
#define NUM_buttle 100
#define Value_buttle 30

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    int score;
    int numhit;
    int Value_enemy;
    //QMovie boom;
    //QLabel bomb;
    QLabel boompic;
    QString boomsheet;

    QLabel* buttle[100];
    QLabel* enemy[6];
    //String title;
    void initPlane();
    void initLabel();
    void initEnemy();
    void initButtle();
    void restart();
    int timeid;
    int boomid;
    //int gameoverid;

    void judgeplane();
    void judgebullet();
    void shoot();
    void pause();
    void gameover();
    ~Dialog();

private slots:
    void keyPressEvent(QKeyEvent *k);
    void timerEvent(QTimerEvent *event);
private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include <time.h>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    srand((int)time(0));    //随机种子
    ui->setupUi(this);
    restart();
}
//在[a, b)之间产生一个随机整数
int random(int a, int b)
{
    int c = (rand() % (a - b)) + a;
    return c;
}
Dialog::~Dialog()
{
    delete ui;
}

void Dialog::restart(){
    initLabel();//初始化右侧栏目
    initPlane();//初始化我方飞机位置
    initEnemy();//初始化敌方飞机位置
    initButtle();//初始化子弹
    ui->gameover->hide();
    timeid = startTimer(50);
    score = 0;
    numhit = 0;
    ui->numhit->setText(QString::number(numhit));
    ui->score->setText(QString::number(score));
    boompic.setParent(ui->frame_2);
    boompic.clear();
    boompic.hide();
}

void Dialog::initLabel(){
    ui->label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    ui->numhit->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    ui->score->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    ui->label_4->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    ui->honor->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    ui->label_6->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    ui->label_7->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
}

void Dialog::initPlane(){
    ui->myplane->move(300,530);
}
void Dialog::initEnemy(){
    enemy[0]=ui->enemy_1;
    enemy[1]=ui->enemy_2;
    enemy[2]=ui->enemy_3;
    enemy[3]=ui->enemy_4;
    enemy[4]=ui->enemy_5;
    enemy[5]=ui->enemy_6;
    for(int i=0;i<6;i++)
        enemy[i]->move(random(0,630),random(-200,-100));
}

void Dialog::initButtle(){//子弹位置是战机位置x+60,y-90.y==-70的时候就可以消失了
    for(int i=0;i<NUM_buttle;i++){
        buttle[i]=new QLabel("");
        buttle[i]->setParent(ui->frame_2);
        buttle[i]->hide();
        buttle[i]->resize(QSize(20,100));
        QString a = "QLabel{border-image: url(:/bullets.png);background-color: transparent;}";
        buttle[i]->setStyleSheet(a);

    }
}


void Dialog::judgeplane(){
    int rc1_x = ui->myplane->x()+20;
    int rc1_y = ui->myplane->y()+10;
    int rc1_width = ui->myplane->size().width()-40;
    int rc1_height = ui->myplane->size().height()-20;
    for(int i=0;i<NUM_enemy;i++){
        int rc2_x = enemy[i]->x();
        int rc2_y = enemy[i]->y();
        int rc2_width = enemy[i]->size().width();
        int rc2_height = enemy[i]->size().height();

        if (rc1_x + rc1_width  > rc2_x &&
            rc2_x + rc2_width  > rc1_x &&
            rc1_y + rc1_height > rc2_y &&
            rc2_y + rc2_height > rc1_y
           ){
            /*int boom_x = ui->myplane->x();
            int boom_y = ui->myplane->y();
            QSize boom_p = ui->myplane->size();
            boomsheet = "QLabel{border-image: url(:/bomb1.png);background-color: transparent;}";
            boompic.setStyleSheet(boomsheet);
            boompic.move(boom_x,boom_y);
            boompic.resize(boom_p);
            boompic.show();
            boomid=startTimer(100);
            gameoverid=startTimer(800);*/
            gameover();
        }
    }
}

void Dialog::judgebullet(){
    for(int i=0;i<NUM_buttle;i++){
        if(!buttle[i]->isHidden()){
            int rc1_x = buttle[i]->x();
            int rc1_y = buttle[i]->y();
            int rc1_width = buttle[i]->size().width();
            int rc1_height = buttle[i]->size().height();

            for(int j=0;j<NUM_enemy;j++){
                int rc2_x = enemy[j]->x();
                int rc2_y = enemy[j]->y();
                int rc2_width = enemy[j]->size().width();
                int rc2_height = enemy[j]->size().height();

                if (rc1_x + rc1_width  > rc2_x &&
                    rc2_x + rc2_width  > rc1_x &&
                    rc1_y + rc1_height > rc2_y &&
                    rc2_y + rc2_height > rc1_y
                   ){//命中敌机
                    buttle[i]->hide();
                    int boom_x = enemy[j]->x();
                    int boom_y = enemy[j]->y();
                    QSize boom_p = enemy[j]->size();
                    boomsheet = "QLabel{border-image: url(:/bomb1.png);background-color: transparent;}";
                    boompic.setStyleSheet(boomsheet);
                    boompic.move(boom_x,boom_y);
                    boompic.resize(boom_p);
                    boompic.show();
                    boomid=startTimer(100);

                    enemy[j]->move(random(0,630),random(-200,-100));
                    score += 10;
                    numhit++;
                    ui->score->setText(QString::number(score));
                    ui->numhit->setText(QString::number(numhit));


                }
            }
        }
    }
}

void Dialog::shoot(){
    int i;
    for(i=0;i<NUM_buttle;i++){
        if(buttle[i]->isHidden())
            break;
    }
    if(i<NUM_buttle){
        buttle[i]->move(ui->myplane->x()+60,ui->myplane->y());
        buttle[i]->show();
    }
}

void Dialog::pause(){
    killTimer(timeid);
}

void Dialog::gameover(){
    pause();
    ui->gameover->show();
}

void Dialog::timerEvent(QTimerEvent *event){
    if(event->timerId() == timeid){
        //  子弹移动
        for(int i=0;i<NUM_buttle;i++){
            if(!buttle[i]->isHidden()){
                if(buttle[i]->y() < -100)
                    buttle[i]->hide();
                else
                    buttle[i]->move(buttle[i]->x(),buttle[i]->y()-Value_buttle);
            }
        }
        judgebullet();
        judgeplane();
        for(int j=0;j<NUM_enemy;j++){
            if(!enemy[j]->isHidden()){
                if(enemy[j]->y()>660){
                    enemy[j]->move(random(0,630),random(-200,-100));
                }
                else
                    enemy[j]->move(enemy[j]->x(),enemy[j]->y()+Value_enemy);
            }
        }
        if(score > 200 && score < 1000)
            ui->honor->setText(QString("中级飞行员"));
        else if(score > 1000)
            ui->honor->setText(QString("高级飞行员"));
    }
    else if(event->timerId() == boomid){
        //bomb.hide();
        switch(boomsheet[31].toLatin1()){
            case '1':boomsheet[31]='2';boompic.setStyleSheet(boomsheet);boompic.update();break;
            case '2':boomsheet[31]='3';boompic.setStyleSheet(boomsheet);boompic.update();break;
            case '3':boomsheet[31]='4';boompic.setStyleSheet(boomsheet);boompic.update();break;
            case '4':boomsheet[31]='5';boompic.setStyleSheet(boomsheet);boompic.update();break;
            case '5':boomsheet[31]='6';boompic.setStyleSheet(boomsheet);boompic.update();break;
            case '6':boomsheet[31]='7';boompic.setStyleSheet(boomsheet);boompic.update();break;
            case '7':boomsheet[31]='1';boompic.setStyleSheet(boomsheet);killTimer(boomid);boompic.hide();break;
            default:qDebug()<<boomsheet[31].toLatin1();
        }
    }

}

void Dialog::keyPressEvent(QKeyEvent *k)
{
    switch(k->key()){
    case Qt::Key_W:
        if(ui->myplane->y()<=0)break;
        ui->myplane->move(ui->myplane->x(),ui->myplane->y()-10);judgeplane();break;
    case Qt::Key_S:
        if(ui->myplane->y()>=640)break;
        ui->myplane->move(ui->myplane->x(),ui->myplane->y()+10);judgeplane();break;
    case Qt::Key_A:
        if(ui->myplane->x()<=0)break;
        ui->myplane->move(ui->myplane->x()-10,ui->myplane->y());judgeplane();break;
    case Qt::Key_D:
        if(ui->myplane->x()>=740)break;
        ui->myplane->move(ui->myplane->x()+10,ui->myplane->y());judgeplane();break;
    /*case (Qt::Key_W | Qt::Key_A):ui->myplane->move(ui->myplane->x()-10,ui->myplane->y()-10);judgeplane();break;
    case (Qt::Key_W | Qt::Key_D):ui->myplane->move(ui->myplane->x()+10,ui->myplane->y()-10);judgeplane();break;
    case (Qt::Key_S | Qt::Key_A):ui->myplane->move(ui->myplane->x()-10,ui->myplane->y()+10);judgeplane();break;
    case (Qt::Key_S | Qt::Key_D):ui->myplane->move(ui->myplane->x()+10,ui->myplane->y()+10);judgeplane();break;*/
    case Qt::Key_K:shoot();break;
    case Qt::Key_P:pause();break;
    case Qt::Key_O:timeid = startTimer(50);break;
    case Qt::Key_E:gameover();this->close();break;
    case Qt::Key_R:restart();break;
    }

}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "dialog.h"
#include <QLabel>
#include <QMovie>



namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    Dialog gameui;

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    gameui.hide();

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
   this->hide();
   gameui.Value_enemy = 5;
   gameui.restart();
   gameui.show();
}

void MainWindow::on_pushButton_2_clicked()
{
    this->hide();
    gameui.Value_enemy = 10;
    gameui.restart();
    gameui.show();
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值