opencv+c++写的小游戏,泡泡堂超级基础版

2018.7.3--2018.7.14,这是这几天的成果,从安装编译器,到配置环境,到学习新的编译器使用,到学习C++,学习opencv,再到写出整个游戏,经历了很多,也学会了很多,不怕软件崩,不怕电脑崩,更要不怕心态崩,要真正的静下心来面对自己的代码,面对自己的人物,希望以后真正成为一名程序媛的时候,这些经历会成为我美好的回忆

1:主函数控制整个程序的运行

#include "stdafx.h"
#include"Game.h"
#include"BackMusic.h"

int main()

{
    CBackMusic music;
    music.PlayMusic();
    CGame game;
    game.Run();
    return 0;
}

2:接下来分别写人物地图爆炸背景音乐以及控制游戏各种界面跳转的游戏类

人物类:

#include "stdafx.h"
#include "Player.h"


CPlayer::CPlayer()
{
    m_ori = 0;
    char name[100];
    for (int i = 0; i < 4; i++)
    {
        sprintf_s(name, "image\\player%d.jpg", i);
        m_img[i] = cvLoadImage(name);
    }
    m_pos.x = 40;
    m_pos.y = 40;
    m_speed = 40;
}


CPlayer::~CPlayer()
{
    for (int i = 0; i < 4; i++)
    {
        cvReleaseImage(&m_img[i]);
    }
}

void CPlayer::Move(char key, CGameMap * map)
{
    int x = m_pos.x;
    int y = m_pos.y;
    switch (key)
    {
    case 'W':
    case 'w':
        if (y > 0)
        {
            m_ori = 0;
            y -= m_speed;
        }
        break;
    case 'S':
    case 's':
        if (y < 600)
        {
            m_ori = 3;
            y += m_speed;
        }
        break;
    case 'A':
    case 'a':
        if (x > 0)
        {
            m_ori = 2;
            x -= m_speed;
        }
        break;
    case 'D':
    case 'd':
        if (x <660)
        {
            m_ori = 1;
            x += m_speed;
        }
        break;
    }
    if (map->Judge(x, y))
    {
        m_pos.x = x;
        m_pos.y = y;
    }
}

void CPlayer::Move(char key, CLevelTwoMap * map)
{
    int x = m_pos.x;
    int y = m_pos.y;
    switch (key)
    {
    case 'W':
    case 'w':
        if (y > 0)
        {
            m_ori = 0;
            y -= m_speed;
        }
        break;
    case 'S':
    case 's':
        if (y < 600)
        {
            m_ori = 3;
            y += m_speed;
        }
        break;
    case 'A':
    case 'a':
        if (x > 0)
        {
            m_ori = 2;
            x -= m_speed;
        }
        break;
    case 'D':
    case 'd':
        if (x <660)
        {
            m_ori = 1;
            x += m_speed;
        }
        break;
    }
    if (map->Judge(x, y))
    {
        m_pos.x = x;
        m_pos.y = y;
    }
}

void CPlayer::DrawtoBack(IplImage * back)
{
    CTools::DrawtoBack(back, m_img[m_ori], m_pos.x, m_pos.y, 225, 225, 225);
}

地图类:

#include "stdafx.h"
#include "GameMap.h"


CGameMap::CGameMap()
{
    m_StaticBack = cvLoadImage("image\\back1.jpg", 1);
    m_ShowImg = cvCloneImage(m_StaticBack);
    char name[100];
    for (int i = 0; i < 10; i++)
    {
        sprintf_s(name, "image\\stone%d.jpg", i);
        m_Stone[i] = cvLoadImage(name);
    }
}


CGameMap::~CGameMap()
{
    cvReleaseImage(&m_StaticBack);
    for (int i = 0; i < 10; i++)
    {
        cvReleaseImage(&m_Stone[i]);
    }
}

void CGameMap::ReadMap()
{
    ifstream inf;
    inf.open("image\\map_lever2.txt");
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 16; j++)
        {
            inf >> m_Map[i][j];
        }
    }
}

void CGameMap::CreateMap()
{
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j <16; j++)
        {
            int x = i * 40;
            int y = j * 40;
            int k = m_Map[i][j];
            if (k != -1)
                CTools::DrawtoBack(m_StaticBack, m_Stone[k], x, y, 235, 235, 235);//不同图片贴上去
        }
    }
}

IplImage *CGameMap::GetShowMap()
{
    CreateMap();
    return m_StaticBack;
}

int CGameMap::Judge(int x, int y)
{
    int px = x / 40;
    int py = y / 40;
    if (m_Map[px][py] == -1)
        return 1;
    else
        return 0;
}
爆炸类:

#include "stdafx.h"
#include "Bomb.h"


CBomb::CBomb()
{
    m = 0;
    m_flag = false;
    m_timecount = 40;
    char name[100];
    for (int i = 0; i < 2; i++)
    {
        sprintf_s(name, "image\\crump%d.bmp", i);

        m_bombing[i] = cvLoadImage(name, 1);
    }
    for (int i = 0; i < 5; i++)
    {
        sprintf_s(name, "image\\shockwave-00%d.bmp", i);
        m_bombed[i] = cvLoadImage(name, 1);
    }
}


CBomb::~CBomb()
{
    for (int i = 0; i < 2; i++)
    {
        cvReleaseImage(&m_bombing[i]);
    }
    for (int i = 0; i < 5; i++)
    {
        cvReleaseImage(&m_bombed[i]);
    }
}


int CBomb::JudgeMap(CGameMap *giftmap)
{
    m = 0;
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 16; j++)
        {
            if (giftmap->m_Map[i][j] >= 6)
            {
                m = 1;
            }
        }
    }
    return m;
}

int CBomb::JudgeMap2(CLevelTwoMap *giftmap)
{
    m = 0;
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 16; j++)
        {
            if (giftmap->m_Map[i][j] >= 6)
            {
                m = 1;
            }
        }
    }
    return m;
}

void CBomb::BombState(IplImage * imgback)
{
    m_timecount--;
    if (m_timecount >= 35)
    {
        m_bombstate = 0;
    }
    else
        if (m_timecount >= 30)
        {
            m_bombstate = 1;
        }
        else
            if (m_timecount <28)
            {
                m_bombstate = 2;
            }
}

void CBomb::BombChange(IplImage * imgback, CGameMap * map, CGameMap *bombmap)
{
    switch (m_bombstate)
    {
    case 0:
        CTools::DrawBomb(imgback, m_bombing[0], m_pos.x, m_pos.y, 0, 0, 255);
        break;
    case 1:
        CTools::DrawBomb(imgback, m_bombing[1], m_pos.x, m_pos.y, 0, 0, 255);
        break;
    case 2:
        CTools::DrawBomb(imgback, m_bombed[004], m_pos.x, m_pos.y, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[001], m_pos.x, m_pos.y - 40, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[002], m_pos.x + 40, m_pos.y, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[003], m_pos.x, m_pos.y + 40, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[000], m_pos.x - 40, m_pos.y, 0, 0, 255);
        ClearBomb(bombmap, m_pos.x, m_pos.y);
        ClearBomb(bombmap, m_pos.x - 40, m_pos.y);
        ClearBomb(bombmap, m_pos.x + 40, m_pos.y);
        ClearBomb(bombmap, m_pos.x, m_pos.y - 40);
        ClearBomb(bombmap, m_pos.x, m_pos.y + 40);
        m_flag = false;
        m_timecount = 40;
        break;

    }
}

void CBomb::BombChange2(IplImage * imgback, CLevelTwoMap * map, CLevelTwoMap *bombmap)
{
    switch (m_bombstate)
    {
    case 0:
        CTools::DrawBomb(imgback, m_bombing[0], m_pos.x, m_pos.y, 0, 0, 255);
        break;
    case 1:
        CTools::DrawBomb(imgback, m_bombing[1], m_pos.x, m_pos.y, 0, 0, 255);
        break;
    case 2:
        CTools::DrawBomb(imgback, m_bombed[004], m_pos.x, m_pos.y, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[001], m_pos.x, m_pos.y - 40, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[002], m_pos.x + 40, m_pos.y, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[003], m_pos.x, m_pos.y + 40, 0, 0, 255);
        CTools::DrawBomb(imgback, m_bombed[000], m_pos.x - 40, m_pos.y, 0, 0, 255);
        ClearBomb(bombmap, m_pos.x, m_pos.y);
        ClearBomb(bombmap, m_pos.x - 40, m_pos.y);
        ClearBomb(bombmap, m_pos.x + 40, m_pos.y);
        ClearBomb(bombmap, m_pos.x, m_pos.y - 40);
        ClearBomb(bombmap, m_pos.x, m_pos.y + 40);
        m_flag = false;
        m_timecount = 40;
        break;

    }
}

int CBomb::Bombed(int x, int y)
{

    if ((x == m_pos.x&&y == m_pos.y) || (y == m_pos.y - 40 && x == m_pos.x) || (y == m_pos.y + 40 && x == m_pos.x) || (y == m_pos.y&&x == m_pos.x - 40) || (y == m_pos.y&&x == m_pos.x + 40))
        return 1;
    else
        return 0;
}

void CBomb::ClearBomb(CGameMap *bombmap, int x, int y)//清除炸弹,
{
    if (bombmap->m_Map[x / 40][y / 40] != 5)//墙无法被炸掉
    {
        if (bombmap->m_Map[x / 40][y / 40] != -1)
        {
            bombmap->m_Map[x / 40][y / 40] = -1;
        }
    }
}

void CBomb::ClearBomb(CLevelTwoMap *bombmap, int x, int y)
{
    if (bombmap->m_Map[x / 40][y / 40] != 5)
    {
        if (bombmap->m_Map[x / 40][y / 40] != -1)
        {
            bombmap->m_Map[x / 40][y / 40] = -1;
        }
    }
}

以及贴图时所用的工具类,调用工具类里里面的函数来对图片进行处理,这里用到了像素宏的处理方法

#include "stdafx.h"
#include "Tools.h"


CTools::CTools()
{
}


CTools::~CTools()
{
}

void CTools::DrawtoBack(IplImage * back, IplImage * img, int x, int y, int blue, int green, int red)
{
    for (int i = 0; i < img->height; i++)
    {
        for (int j = 0; j < img->width; j++)
        {
            int b = CV_IMAGE_ELEM(img, uchar, i, j * 3 + 0);
            int g = CV_IMAGE_ELEM(img, uchar, i, j * 3 + 1);
            int r = CV_IMAGE_ELEM(img, uchar, i, j * 3 + 2);
            if (!((b > blue) && (g > green) && (r > red)))
            {
                CV_IMAGE_ELEM(back, uchar, i + y, (j + x) * 3 + 0) = b;
                CV_IMAGE_ELEM(back, uchar, i + y, (j + x) * 3 + 1) = g;
                CV_IMAGE_ELEM(back, uchar, i + y, (j + x) * 3 + 2) = r;
            }
        }
    }
}

void CTools::DrawBomb(IplImage * imgback, IplImage * img, int x, int y, int blue, int green, int red)
{
    if (img != NULL) {
        for (int i = 0; i < img->height; i++)
        {
            for (int j = 0; j < img->width; j++)
            {
                int b = CV_IMAGE_ELEM(img, uchar, i, j * 3 + 0);
                int g = CV_IMAGE_ELEM(img, uchar, i, j * 3 + 1);
                int r = CV_IMAGE_ELEM(img, uchar, i, j * 3 + 2);
                if (CV_IMAGE_ELEM(img, uchar, i, j * 3 + 2) < 255)
                {
                    CV_IMAGE_ELEM(imgback, uchar, y + i, (j + x) * 3) = b;
                    CV_IMAGE_ELEM(imgback, uchar, y + i, (j + x) * 3 + 1) = g;
                    CV_IMAGE_ELEM(imgback, uchar, y + i, (j + x) * 3 + 2) = r;
                }
            }
        }
    }
}
背景音乐类:可以专门播放背景音乐,其实可以设置不同的关卡或者爆炸呀什么不同的音乐,但是这里初学的时候不知道怎么弄,因此整个游戏就一个音乐

#include "stdafx.h"
#include "BackMusic.h"


CBackMusic::CBackMusic()
{
}


CBackMusic::~CBackMusic()
{
}

void CBackMusic::PlayMusic()
{
    PlaySound(TEXT("image\\back.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
}
如果需要设置另外的关卡,只需要将你需要变换的地图呀人物呀以及输赢方式变换一下重新写一个类或者直接继承就行了,这里初学的时候,加上时间紧迫,设置关卡就设置了两关,并且只是修改了相关的地图,其他的都没有变,以后有时间有想法再来改进

#include "stdafx.h"
#include "LevelTwoMap.h"


CLevelTwoMap::CLevelTwoMap()
{
    m_StaticBack = cvLoadImage("image\\back1.jpg", 1);
    m_ShowImg = cvCloneImage(m_StaticBack);
    char name[100];
    for (int i = 0; i < 10; i++)
    {
        sprintf_s(name, "image\\obstacle%d.jpg", i);
        m_obstacle[i] = cvLoadImage(name);
    }
}


CLevelTwoMap::~CLevelTwoMap()
{
    cvReleaseImage(&m_StaticBack);
    for (int i = 0; i < 10; i++)
    {
        cvReleaseImage(&m_obstacle[i]);
    }
}

void CLevelTwoMap::ReadMap()
{
    ifstream inf;
    inf.open("image\\map_lever1.txt");
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 16; j++)
        {
            inf >> m_Map[i][j];
        }
    }
}

void CLevelTwoMap::CreateMap()
{
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j <16; j++)
        {
            int x = i * 40;
            int y = j * 40;
            int k = m_Map[i][j];
            if (k != -1)
                CTools::DrawtoBack(m_StaticBack, m_obstacle[k], x, y, 235, 235, 235);//不同图片贴上去
        }
    }
}

IplImage * CLevelTwoMap::GetShowMap()
{
    CreateMap();
    return m_StaticBack;
}

int CLevelTwoMap::Judge(int x, int y)
{
    int px = x / 40;
    int py = y / 40;
    if (m_Map[px][py] == -1)
        return 1;
    else
        return 0;
}
最后就是最重要的Game类,控制整个游戏的运行,其中穿插了时间的计算,但是没有想到办法把时间显示在游戏界面上,以后想到了再说,其实核心控制游戏进行,想法还是挺简单的,遗憾的是鼠标事件没有加上去,其实学历,但是加上去的时候始终有错,所以就放弃了,等以后能熟练运用鼠标事件函数再来解决这个问题,毕竟游戏都离不开鼠标,GAme类看起来还是很简单的,小卫星那个一下就可以想通,整个游戏也是比较简单的,比较适合真的那种新手看

#include "stdafx.h"
#include "Game.h"


CGame::CGame()
{
    m_state = 0;
    m_mapob.ReadMap ();
    m_mapob.GetShowMap();
    cvNamedWindow("QQ candy", 1);
}


CGame::~CGame()
{
    cvDestroyWindow("QQ candy");
    cvReleaseImage(&m_showimg);
}

void CGame::Run()
{
    Welcome();
    while (1)
    {
        switch (m_state)
        {
        case 1:
            Help();
            break;
        case 2:
            Choice();
            break;
        case 3:
            Win();
            break;
        case 4:
            Lose();
            break;
        case 5:
            Level1();
            break;
        case 6:
            Level2();
            break;
        default:
            break;
        }
    }
}

void CGame::Welcome()
{
    m_mapob.GetShowMap();
    m_showimg = cvLoadImage("image\\welcome.jpg");
    cvNamedWindow("QQ candy");
    cvShowImage("QQ candy", m_showimg);
    char key = cvWaitKey(0);
    if (key == ' ')
    {
        m_state = 2;
    }
    if (key == 'H' || key == 'h')
    {
        m_state = 1;
    }
    if (key == 'Q' || key == 'q')
    {
        m_state = 8;
    }
    cvReleaseImage(&m_showimg);
    cvDestroyWindow("QQ candy");
}

void CGame::Choice()
{
    m_choice = cvLoadImage("image\\choice.jpg", 1);
    cvShowImage("QQ candy", m_choice);
    char key = cvWaitKey(0);
    if (key == 'F' || key == 'f')
    {
        m_state = 5;
    }
    if (key == 'S' || key == 's')
    {
        m_state = 6;
    }
}

void CGame::Help()
{
    m_helpimg = cvLoadImage("image\\help.jpg", 1);
    cvShowImage("QQ candy", m_helpimg);
    char key = cvWaitKey(0);
    if (key == ' ')
    {
        m_state = 2;
    }
}
void CGame::Level1()
{
    time_t start, end;
    double cost;
    time(&start);
    m_mapob.ReadMap();
    m_mapob.GetShowMap();
    m_player.m_pos.x = 40;
    m_player.m_pos.y = 40;
    while (1)
    {
        time(&end);
        cost = difftime(end, start);
        printf("%f\n", cost);
        if (cost > 60)
        {
            m_state = 4;
            break;
        }
        UpdateMap();
        m_bomb.m = m_bomb.JudgeMap(&m_mapob);
        if (m_bomb.m == 0)
        {
            m_state = 3;
            break;
        }
        cvCopy(m_mapob.m_StaticBack, m_mapob.m_ShowImg);
        char key = cvWaitKey(50);
        if (key == ' ' && !m_bomb.m_flag)
        {
            m_bomb.m_pos.y = m_player.m_pos.y;
            m_bomb.m_pos.x = m_player.m_pos.x;
            m_bomb.m_flag = true;
        }
        if (m_bomb.m_flag)
        {
            m_bomb.BombState(m_mapob.m_ShowImg);
            m_bomb.BombChange(m_mapob.m_ShowImg, &m_mapob, &m_mapob);
            if (!m_bomb.m_flag)
            {
                if (m_bomb.Bombed(m_player.m_pos.x, m_player.m_pos.y))
                {
                    m_state = 4;
                    break;
                }
            }
        }
        m_player.Move(key, &m_mapob);
        m_player.DrawtoBack(m_mapob.m_ShowImg);
        cvShowImage("QQ candy", m_mapob.m_ShowImg);
    }
}

void CGame::Level2()
{
    time_t start, end;
    double cost;
    time(&start);
    m_mapob2.ReadMap();
    m_mapob2.GetShowMap();
    m_player.m_pos.x = 40;
    m_player.m_pos.y = 40;
    while (1)
    {
        time(&end);
        cost = difftime(end, start);
        if (cost > 60)
        {
            m_state = 4;
            break;
        }
        UpdateMap2();
        m_bomb.m = m_bomb.JudgeMap2(&m_mapob2);
        if (m_bomb.m == 0)
        {
            m_state = 3;
            break;
        }
        cvCopy(m_mapob2.m_StaticBack, m_mapob2.m_ShowImg);
        char key = cvWaitKey(50);
        if (key == ' ' && !m_bomb.m_flag)
        {
            m_bomb.m_pos.y = m_player.m_pos.y;
            m_bomb.m_pos.x = m_player.m_pos.x;
            m_bomb.m_flag = true;
        }
        if (m_bomb.m_flag)
        {
            m_bomb.BombState(m_mapob2.m_ShowImg);
            m_bomb.BombChange2(m_mapob2.m_ShowImg, &m_mapob2, &m_mapob2);
            if (!m_bomb.m_flag)
            {
                if (m_bomb.Bombed(m_player.m_pos.x, m_player.m_pos.y))
                {
                    m_state = 4;
                    break;
                }
            }
        }
        m_player.Move(key, &m_mapob2);
        m_player.DrawtoBack(m_mapob2.m_ShowImg);
        cvShowImage("QQ candy", m_mapob2.m_ShowImg);
    }
}

void CGame::Win()
{
    m_win = cvLoadImage("image\\win.jpg", 1);
    cvShowImage("QQ candy", m_win);
    cvWaitKey(0);
    Welcome();
}

void CGame::Lose()
{
    m_lost = cvLoadImage("image\\lost.jpg", 1);
    cvShowImage("QQ candy", m_lost);
    cvWaitKey(0);
    Welcome();
}

void CGame::UpdateMap()
{
    m_mapob.m_StaticBack = cvLoadImage("image\\back1.jpg", 1);
    m_mapob.m_StaticBack = m_mapob.GetShowMap();
}

void CGame::UpdateMap2()
{
    m_mapob2.m_StaticBack = cvLoadImage("image\\back1.jpg", 1);
    m_mapob2.m_StaticBack = m_mapob2.GetShowMap();
}

真正的适合新手的,这是我写的第一个比较成型的游戏,虽然很简单,过程也很艰难,感谢朋友的陪伴以及帮助和鼓励,10天的成果,对于一个没有学过C++和opencv的人而言,已经足够了,希望以后能好好改进,做出更好的游戏来。

猜你喜欢

转载自blog.csdn.net/qq_41698013/article/details/81152686
今日推荐