opengl 雷霆战机 2d

// hsb_雷霆战机_20181005.cpp : 定义应用程序的入口点。
//

/*
    作者:
    时间:2018.10.03 - 2018.10.05
    功能:雷霆战机
*/

#include "stdafx.h"
#include "hsb_雷霆战机_20181005.h"
#include "myPlane.h"
#include <GL/glut.h>
#include <math.h>
#include <windows.h>
#include <stdlib.h>
#include "EnemyPlane.h"
#include <vector>
#include <sstream>
#include <thread>
#include <iostream>
#include <math.h>
#include "enemyBullet.h"
#include "myBullet.h"
#include <stdio.h>
#include <mmSystem.h>
#include <graphics.h>
#include <conio.h>
#include "firePoint.h"
#pragma commet(lib, "WinMM.lib")


using namespace std;

#define PI 3.14159  //设置圆周率
#define  THREAD_NUM 5
#define  ENEMY_BULLET_NUM 128; //敌人子弹总数
int n = 6, R = 10;  //多边形变数,外接圆半径
                    //创建飞机
MyPlane* myPlane = new MyPlane();
float fx = myPlane->x;
float fy = myPlane->y;

int epNum = 10; //敌方飞机数
int vepNum = 4; //敌方飞机vector数组总数
int ebNum = 128; //地方子弹数
int mbNum = 64;    //我方子弹数
int fpNum = 50; //炸弹火焰数
int second = 0; //游戏进行时间秒数

//创建敌机
vector<EnemyPlane> veps;
EnemyPlane* eps = new EnemyPlane[epNum];

//创建敌人子弹
enemyBullet* ebs = new enemyBullet[ebNum];

myBullet* mbs = new myBullet[mbNum];

FirePoint* fps = new FirePoint[fpNum];

#define MAX_CHAR 128 //字符串的最大长度

CRITICAL_SECTION Critical;      //定义临界区句柄

float theta = 0.0;  //旋转初始角度值
void Keyboard(unsigned char key, int x, int y);
void Display(void);
void Reshape(int w, int h);
void myidle();
void drawString(const char* str); //屏幕显示字体
void selectFont(int size, int charset, const char* face);
void mykeyboard(unsigned char key, int x, int y);
bool checkSide(float x, float y);
void Move(int i);
bool checkEpSide(int n, float addx, float addy);
bool checkMyEpSide();
void ebsSide(int i);
void enemyShut(EnemyPlane ep);
void ebsMove();
bool ebsMyplaneSide(int i);
//void epThread(EnemyPlane& ep);
void epThread(int i);
static DWORD WINAPI EnemyPlaneMove(LPVOID lpParameter);
void myShut();
void mbsMove();
void mbsMyplaneSide(int i);
void mbsSide(int i);
void loadImage(wchar_t str[], int x, int y);
void boomView(int x, int y);
void drawPoint(int x, int y);
void mytime(int t);

int APIENTRY _tWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR    lpCmdLine,
    int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    char *argv[] = { "hello ", " " };
    int argc = 2; // must/should match the number of strings in argv

    for (int i = 0; i < vepNum; i++)
    {
        veps.push_back(eps[i]);
    }

    PlaySound(L"background.wav",NULL,SND_FILENAME|SND_ASYNC);


    //for (unsigned int i = 0; i < veps.size(); i++)
    //{
    //    thread t(epThread, i);
    //    t.join();
    //}

    

    /*HANDLE hThread[THREAD_NUM];*/

    //for (int i = 0; i < veps.size(); i++)
    //{
    //    hThread[i] = CreateThread(NULL, 0, EnemyPlaneMove, (LPVOID)i, 0, NULL);
    //    CloseHandle(hThread[i]);//关闭内核对象,不会停止线程
    //}

    glutInit(&argc, argv);  //初始化GLUT库;
    glutInitWindowSize(800, 600);  //设置显示窗口大小
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  //设置显示模式;(注意双缓冲)
    glutCreateWindow("雷霆战机"); // 创建显示窗口
    glutDisplayFunc(Display);  //注册显示回调函数
    glutKeyboardFunc(mykeyboard);//键盘注册回调函数
    glutReshapeFunc(Reshape);  //注册窗口改变回调函数
    glutIdleFunc(myidle);    //注册闲置回调函数
    glutTimerFunc(1000, mytime, 10); //注册闲时函数
    glutDisplayFunc(&Display);//在程序运行时是自动调用的,即程序会自动调用display函数重绘窗口

    glutMainLoop();  //进入事件处理循环

    return 0;
}

void Display(void)
{

    glClear(GL_COLOR_BUFFER_BIT);

    /*thread* task = new thread[THREAD_NUM];*/

    if (myPlane->live == true)
    {
        //画自己飞机
        planeHead(*myPlane);
        planeBody(*myPlane);
        planeTail(*myPlane);
        planeWing(*myPlane);
        myPlane->planeMove(fx, fy);
    }
    

    //敌人飞机移动
    for (unsigned int i = 0; i < veps.size(); i++)
    {
        Move(i);
    }

    //画敌人飞机
    for (unsigned int i = 0; i < veps.size(); i++)
    {
        if (veps[i].live == true)
        {
            EPlaneHead(veps[i]);
            EPlaneBody(veps[i]);
            EPlaneTail(veps[i]);
            EPlaneWing(veps[i]);
        }
    }

    //敌人子弹移动函数
    ebsMove();

    //画敌人子弹
    for (int i = 0; i < ebNum; i++)
    {
        if (ebs[i].live == true)
        {
            drawBullet(ebs[i]);
        }
    }

    mbsMove();

    //画己方子弹
    for (int i = 0; i < mbNum; i++)
    {
        if (mbs[i].live == true)
        {
            drawMyBullet(mbs[i]);
        }
    }

    checkMyEpSide();//敌我飞机碰撞检测

    glColor3f(1.0f, 1.0f, 0.0f);    //设置绘图颜色
    glRectf(8.0f, -12.0f, 22.0f, 12.0f);  //绘制矩形

                                          //selectFont(48, ANSI_CHARSET, "Comic Sans MS");  //字体可以在系统文件里寻找

    glColor3f(0, 255, 0);    //设置绘图绿颜色
    glRectf(10.0f, 7.0f, 20.0f, 9.0f);  //绘制矩形

    glColor3f(255, 251, 240);    //设置绘图白颜色
    glRectf(15.0f, 7.4f, 18.0f, 8.7f);  //绘制矩形

    //得分:
    glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    stringstream stream5;
    stream5 << score;
    char str5[64] = "";
    stream5 >> str5;
    glRasterPos2f(16.0, 7.9);  //起始位置
    drawString(str5);     //输出的字符串(汉字不支持)

    glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    glRasterPos2i(12, 8);  //起始位置
    drawString("scores:");     //输出的字符串(汉字不支持)

    glColor3f(255, 251, 240);    //设置绘图白颜色
    glRectf(10.0f, -3.0f, 20.0f, 6.0f);  //绘制矩形

                                         //veps[0].x += rand() % 6 * 0.1 - 0.3;
                                         //测试
    glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    stringstream stream;
    int i = myPlane->x;
    stream << i;
    char str1[64] = "";
    stream >> str1;
    glRasterPos2f(13.0, 5.0);  //起始位置
    drawString("my plane x:");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, 4.0);  //起始位置
    drawString(str1);     //输出的字符串(汉字不支持)
    stringstream stream3;
    int i3 = myPlane->y;
    stream3 << i3;
    char str3[64] = "";
    stream3 >> str3;
    glRasterPos2f(13.0, 3.0);  //起始位置
    drawString("my plane y:");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, 2.0);  //起始位置
    drawString(str3);     //输出的字符串(汉字不支持)
    stringstream stream4;
    int i4 = myPlane->brood;
    stream4 << i4;
    char str4[64] = "";    
    stream4 >> str4;
    glRasterPos2f(13.0, 1.0);  //起始位置
    drawString("my brood:");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, 0.0);  //起始位置
    drawString(str4);     //输出的字符串(汉字不支持)
    
    stringstream stream6;
    stream6 << second;
    char str7[64] = "";
    stream6 >> str7;
    glRasterPos2f(13.0, -1.0);  //起始位置
    drawString("game time:");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, -2.0);  //起始位置
    drawString(str7);     //输出的字符串(汉字不支持)

                         //stringstream stream2;
                         //int i2 = rand() % 100;
                         //stream2 << i2;
                         //char str2[64] = "";
                         //stream2 >> str2;
                         //glRasterPos2f(13.0, 1.0);  //起始位置
                         //drawString(str2);     //输出的字符串(汉字不支持)

    glColor3f(0, 255, 0);    //设置绘图绿颜色
    glRectf(10.0f, -10.0f, 20.0f, -4.0f);  //绘制矩形

    glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    glRasterPos2f(13.0, -5.0);  //起始位置
    drawString("up is 'w'");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, -6.0);  //起始位置
    drawString("down is 's'");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, -7.0);  //起始位置
    drawString("left is 'a'");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, -8.0);  //起始位置
    drawString("right is 'd'");     //输出的字符串(汉字不支持)
    glRasterPos2f(13.0, -9.0);  //起始位置
    drawString("shoot is 'j'");     //输出的字符串(汉字不支持)

    //glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    //glRectf(13.8f, -6.0f, 16.2f, -4.5f);  //绘制矩形
    //glColor3f(0.0f, 0.0f, 0.0f);  //设置红色绘制颜色
    //glRasterPos2f(14.5f, -5.5);    //定位当前光标,起始字符位置
    //drawString("UP");     //输出的字符串(汉字不支持)

    //glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    //glRectf(10.8f, -8.0f, 13.2f, -6.5f);  //绘制矩形
    //glColor3f(0.0f, 0.0f, 0.0f);  //设置红色绘制颜色
    //glRasterPos2f(11.1f, -7.5);    //定位当前光标,起始字符位置
    //drawString("LEFT");     //输出的字符串(汉字不支持)

    //glColor3f(0, 0, 128);  //设置蓝色绘制颜色
    //glRectf(16.8f, -8.0f, 19.2f, -6.5f);  //绘制矩形
    //glColor3f(0.0f, 0.0f, 0.0f);  //设置红色绘制颜色
    //glRasterPos2f(16.9f, -7.5);    //定位当前光标,起始字符位置
    //drawString("RIGHT");     //输出的字符串(汉字不支持)

    //glColor3f(0.0, 1.0, 1.0);  //设置蓝色绘制颜色
    //glRectf(13.2f, -11.0f, 16.8f, -9.5f);  //绘制矩形
    //glColor3f(0.0f, 0.0f, 0.0f);  //设置红色绘制颜色
    //glRasterPos2f(14.2f, -10.4f);    //定位当前光标,起始字符位置
    //drawString("END");     //输出的字符串(汉字不支持)

    //glColor3f(1, 0, 0);  //设置红色绘制颜色
    //glPointSize(5.0);//点的像素大小,默认值为1.0
    //glBegin(GL_POINTS);
    //glVertex2f(0,0);
    //glVertex2f(0.1, 0.1);
    //glEnd();

    //画爆炸图
    if (fps[0].live == true)
    {
        for (int i = 0; i < fpNum; i++)
        {
            drawPoint(fps[i].x, fps[i].y);
        }
        Sleep(40);
        for (int i = 0; i < fpNum; i++)
        {
            fps[i].diet();
        }
    }

    if (myPlane->live == false)
    {
        //己方飞机死亡后
        glColor3f(1.0f, 0.0f, 0.0f);    //设置绘图颜色
        glRectf(-6.0f, -4.0f, 6.0f, 4.0f);  //绘制矩形
        glColor3f(255, 251, 240);    //设置绘图白颜色
        glRasterPos2f(-2.5, 0.0);  //起始位置
        drawString("Game is over!");     //输出的字符串(汉字不支持)
                                        
    }

    glutSwapBuffers();   //双缓冲的刷新模式;

}

void myidle()
{

    theta += 1.0;
    if (theta >= 2 * PI) theta -= 2 * PI;

    glutPostRedisplay();  //重画,相当于重新调用Display(),改编后的变量得以传给绘制函数
}

void Reshape(GLsizei w, GLsizei h)
{
    glMatrixMode(GL_PROJECTION);  //投影矩阵模式
    glLoadIdentity();  //矩阵堆栈清空
    gluOrtho2D(-1.6*R*w / h, 1.6*R*w / h, -1.2*R, 1.2*R);  //设置裁剪窗口大小
    glViewport(0, 0, w, h); //设置视区大小
    glMatrixMode(GL_MODELVIEW);  //模型矩阵模式
}

void drawString(const char* str) //屏幕显示字体
{
    static int isFirstCall = 1;
    static GLuint lists;

    if (isFirstCall) {
        isFirstCall = 0;
        // 申请MAX_CHAR个连续的显示列表编号
        lists = glGenLists(MAX_CHAR);
        // 把每个字符的绘制命令都装到对应的显示列表中
        wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists);
    }
    // 调用每个字符对应的显示列表,绘制每个字符
    for (; *str != '\0'; ++str) {
        glCallList(lists + *str);
    }
}

void selectFont(int size, int charset, const char* face) {
    HFONT hFont = CreateFontA(size, 0, 0, 0, FW_MEDIUM, 0, 0, 0,
        charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, face);
    HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);
    DeleteObject(hOldFont);
}

void mykeyboard(unsigned char key, int x, int y)
{

    switch (key)
    {
    case 'W':
    case 'w':// 矩形对角坐标变量修改使得矩形上移
        fy += 0.3;
        break;
    case 'S':
    case 's'://矩形对角坐标变量修改使得矩形下移
        fy -= 0.3;
        break;
    case 'A':
    case 'a'://矩形对角坐标变量修改使得矩形左移
        fx -= 0.3;
        break;
    case 'D':
    case 'd'://矩形对角坐标变量修改使得矩形右移
        fx += 0.3;
        break;
    case 'J':
    case 'j'://我方子弹射击
        myShut();
        break;
    }
    //参数修改后调用重画函数,屏幕图形将发生改变
    glutPostRedisplay();
}
//
//static DWORD WINAPI EnemyPlaneMove(LPVOID lpParameter)
//{
//    //Sleep(1);
//    int n = (int)lpParameter;
//    
//        do{
//            veps[n].x += rand() % 6 * 0.1 - 0.3;
//            cout << "veps[n].x:" << veps[n].x << endl;
//        } while (veps[n].x < -22.0 || veps[n].x > 8);    //边界检测函数
//
//        do{
//            veps[n].y -= rand() % 3 * 0.1;
//            cout << "veps[n].y:" << veps[n].y << endl;
//        } while (veps[n].y < -11.0 || veps[n].y > 11.0); //边界检测函数
//    
//    return 0;
//}


//我方射击函数
void myShut()
{
    for (int i = 0; i < ebNum; i++)
    {
        if (mbs[i].live == false)
        {
            mbs[i].init(*myPlane);
            break;
        }
    }
}

//我方子弹移动函数
void mbsMove()
{
    for (int i = 0; i < mbNum; i++)
    {
        if (mbs[i].live == true)
        {
            mbs[i].y += 0.5;
            mbsSide(i);
            mbsMyplaneSide(i);
        }
    }
}

//子弹是否击中敌方飞机
void mbsMyplaneSide(int i)
{
    for (unsigned int j = 0; j < veps.size(); j++)
    {
        if (veps[j].live == true)
        {
            if ((mbs[i].x > veps[j].x) && (mbs[i].x < veps[j].x + veps[j].size * 1.4) && (mbs[i].y > veps[j].y) && (mbs[i].y < veps[j].y + 0.6 * veps[j].size))
            {
                mbs[i].diet();
                PlaySound(L"midb.wav", NULL, SND_FILENAME | SND_ASYNC);
                //飞机爆炸
                veps[j].boomDiet();
                //爆炸图片
                boomView(veps[j].x, veps[j].y);

                //...
            }
        }
    }
}

//我方子弹边界检测函数
void mbsSide(int i)
{
    if (mbs[i].y > 10.0)
    {
        mbs[i].diet();
    }
}


//敌人射击函数
void enemyShut(EnemyPlane ep)
{
    for (int i = 0; i < ebNum; i++)
    {
        if (ebs[i].live == false)
        {
            ebs[i].init(ep);
            break;
        }
    }
}

//敌人子弹移动函数
void ebsMove()
{
    for (int i = 0; i < ebNum; i++)
    {
        if (ebs[i].live == true)
        {
            ebs[i].y -= 0.5;
            ebsSide(i);
            ebsMyplaneSide(i);
        }
    }
}

//子弹是否击中我方飞机
bool ebsMyplaneSide(int i)
{
    if ((ebs[i].x > myPlane->x) && (ebs[i].x < myPlane->x + myPlane->size * 1.4) && (ebs[i].y > myPlane->y) && (ebs[i].y < myPlane->y + 0.6 * myPlane->size))
    {
        if (myPlane->live == true)
        {
            ebs[i].diet();
            myPlane->hut();
            PlaySound(L"smallb.wav", NULL, SND_FILENAME | SND_ASYNC);
            boomView(myPlane->x, myPlane->y);
            return true; //击中飞机
        }
    }
    
    return false;
}

//敌人子弹边界检测函数
void ebsSide(int i)
{
    if (ebs[i].y < -13.0)
    {
        ebs[i].diet();
    }
}

//敌人飞机移动函数
void Move(int i)
{
    float addx, addy;
    Sleep(10);
    addx = rand() % 6 * 0.1 - 0.3;
    addy = rand() % 3 * 0.1;

    if (checkSide(veps[i].x + addx, veps[i].y - addy) && checkEpSide(i,addx,addy))
    {
        veps[i].x += addx;
        veps[i].y -= addy;
    }

    if (veps[i].live == true)
    {
        if (rand() % 20 <= 1) //控制飞机设计子弹数
        {
            enemyShut(veps[i]);
        }
    }

    if (veps[i].y < -13.0)
    {
        veps[i].diet();
        veps[i].init();
    }
}
//
//void Move(int n)
//{
//    Sleep(10);
//    do {
//        veps[n].x += rand() % 6 * 0.1 - 0.3;
//    } while (veps[n].x < -22.0 || veps[n].x > 8);    //边界检测函数
//
//    do {
//        veps[n].y -= rand() % 3 * 0.1;        
//    } while (veps[n].y < -11.0 || veps[n].y > 11.0); //边界检测函数
//
//    if (veps[n].y < -9.0)
//    {
//        veps[n].diet();
//        Sleep(2000);
//        veps[n].init();
//    }
//}

//void epThread(EnemyPlane& ep)
//{
//    Sleep(1000);
//    while (ep.x < -22.0 || ep.x > 8)    //边界检测函数
//    {
//        ep.x += rand() % 6 * 0.1 - 0.3;
//    }
//    while (ep.y < -11.0 || ep.y > 11.0) //边界检测函数
//    {
//        ep.y -= rand() % 3 * 0.1;
//    }
//}

//void epThread(int i)
//{
//    
//    if (veps[i].live == true)
//    {
//        while (veps[i].x < -22.0 || veps[i].x  > 8.0)    //边界检测函数
//        {
//            Sleep(2000);
//            veps[i].x += rand() % 6 * 0.1 - 0.3;
//        }
//
//        while (veps[i].y < -11.0 || veps[i].y  > 11.0) //边界检测函数
//        {
//            Sleep(2000);
//            veps[i].y -= rand() % 3 * 0.1;
            //if (veps[i].y < -11.0)
            //{
            //    veps[i].diet();
            //    Sleep(2000);
            //    veps[i].init();
            //    break;
            //}
//        }
//    }
//    
//}

void epThread(int i)
{
    float addx,addy;
    while (veps[i].live == true)
    {
        Sleep(1000);
        //EnterCriticalSection(&Critical);

        addx = rand() % 6 * 0.1 - 0.3;
        addy = rand() % 3 * 0.1;
        
        if (checkSide(veps[i].x + addx, veps[i].y - addy) && checkEpSide(i,addx,addy))
        {
            veps[i].x += addx;
            veps[i].y -= addy;    
        }
        //LeaveCriticalSection(&Critical);
    }

}

//注:sleep不能使线程延时

//边界检测函数
bool checkSide(float x, float y)
{
    if (x < -22.0 || x  > 8.0 )
    {
        return false;
    }
    else
    {
        return true;
    }
}

//敌人们的飞机碰撞检测函数
bool checkEpSide(int n,float addx, float addy)
{
    for(unsigned int i = 0; i < veps.size(); i++)
    {
        if (i != n)
        {
            if (sqrt((veps[n].x+addx-veps[i].x)*(veps[n].x+addx - veps[i].x)+ (veps[n].y-addy - veps[i].y)*(veps[n].y-addy - veps[i].y)) < sqrt((0.8*veps[i].size*0.8*veps[i].size)))
            {
                return false; //飞机碰撞
            }
        }
    }
    return true;
}

//敌我飞机碰撞检测函数
bool checkMyEpSide()
{
    for (unsigned int i = 0; i < veps.size(); i++)
    {
        if (veps[i].live == true)
        {
            if (sqrt((myPlane->x - veps[i].x)*(myPlane->x - veps[i].x) + (myPlane->y - veps[i].y)*(myPlane->y - veps[i].y)) < sqrt((1.4*veps[i].size*1.4*veps[i].size) + (0.8*veps[i].size*0.8*veps[i].size)))
            {
                myPlane->heavyHut();
                veps[i].diet();
                PlaySound(L"midb.wav", NULL, SND_FILENAME | SND_ASYNC);
                boomView(myPlane->x, myPlane->y);
                return false;
            }
        }
    }

    return true;
}


//void loadImage(wchar_t str[],int x, int y)
//{
//    initgraph(5,5);    
//    IMAGE img;    
//    loadimage(&img, str, 5, 5);//先把图片放在工程项目下,使用L+"绝对路径"    
//    putimage(x, y,&img);//显示图片    
//    _getch();    
//    closegraph();
//}

//爆炸场景函数
void boomView(int x, int y)
{
    for (int i = 0; i < fpNum; i++)
    {
        fps[i].init(rand() % 12 * 0.1 + x, rand() % 12 * 0.1 + y);
    }
}

//绘制点函数
void drawPoint(int x, int y)
{
    //绘制点
    glColor3f(1, 0, 0);  //设置红色绘制颜色
    glPointSize(2.0);//点的像素大小,默认值为1.0
    glBegin(GL_POINTS);
    glVertex2f(x, y);
    glVertex2f(x+0.1, y+0.1);
    glEnd();
}

//时间函数
void mytime(int t)
{
    second++;
    glutTimerFunc(1000, mytime, 10);
}

这个程序是大三上学期学计算机图形学开学第三周学习时间函数的使用,因为闲来无事,也想证明一下自己的能力,于是便花了两天时间写了这个程序,写完这个程序也给本人带来极大的信心

猜你喜欢

转载自blog.csdn.net/guanshanyue96/article/details/89014599