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的人而言,已经足够了,希望以后能好好改进,做出更好的游戏来。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值