【c++|SDL】二、读取图片、显示图片、动画制作

every blog every motto: You can do more than you think.
https://blog.csdn.net/weixin_39190382?type=blog

0. 前言

读取图片,显示图片,动画


SDL中有两种在屏幕上显示的方法

  • SDL_Surface: 使用软件渲染处理
  • SDL_Texture: 使用硬件加速渲染处理

1. 在界面上显示图片

修改Game.h

#ifndef __Game__
#define __Game__

#include <SDL2/SDL.h>
class Game
{

public:
    Game() {};
    ~Game() {};
    // simply set the running variable to true
    bool init(const char* title, int xpos, int ypos,int width, int height, bool fullscreen);
    void render();
    void update();
    void handleEvents();
    void clean();
    // a function to access the private running variable
    bool running() { return m_bRunning; }
private:
    bool m_bRunning;
    // SDL_Window* m_pWindow;
    // SDL_Renderer* m_pRenderer;

    SDL_Window* m_pWindow;
    SDL_Renderer* m_pRenderer;
    SDL_Texture* m_pTexture; // the new SDL_Texture variable
    SDL_Rect m_sourceRectangle; // the first rectangle
    SDL_Rect m_destinationRectangle; // another rectangle
};

#endif /* defined(__Game__) */

修改Game.cpp

修改其中的init和render函数

#include "Game.h"
#include <iostream>

using namespace std;

bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{   
    int flags = 0;
    if (fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }
    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if(m_pWindow != 0) // window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
            if(m_pRenderer != 0) // renderer init success
            {
                std::cout << "renderer creation success\n";
                SDL_SetRenderDrawColor(m_pRenderer,255,255,255,255);
            }
            else
            {
                std::cout << "renderer init fail\n";
                return false; // renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false; // window init fail
        }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    std::cout << "init success\n";

    SDL_Surface* pTempSurface = SDL_LoadBMP("assets/rider.bmp");
    m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);

    SDL_QueryTexture(m_pTexture, NULL, NULL,&m_sourceRectangle.w,&m_sourceRectangle.h); // 获取长宽

    m_destinationRectangle.x = m_sourceRectangle.x = 0;
    m_destinationRectangle.y = m_sourceRectangle.y = 0;
    m_destinationRectangle.w = m_sourceRectangle.w;
    m_destinationRectangle.h = m_sourceRectangle.h;

    m_bRunning = true; // everything inited successfully, start the main loop
    return true;
}

void Game::render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
    SDL_RenderCopy(m_pRenderer, m_pTexture,&m_sourceRectangle,&m_destinationRectangle);
    SDL_RenderPresent(m_pRenderer); // draw to the screen
}


void Game::handleEvents()
{
    SDL_Event event;
    if(SDL_PollEvent(&event))
    {
        switch (event.type)
    {
        case SDL_QUIT:
            m_bRunning = false;
        break;

        default:
        break;
    }
    }
}

void Game::clean()
{
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::update()
{

}

在这里插入图片描述

2. 显示位置和范围

修改m_sourceRectangle和m_destinationRectangle
具体在Game.cpp SDL_QueryTexture代码下面

Game.cpp init函数代码如下,其他代码相同

bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{   
    int flags = 0;
    if (fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }
    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if(m_pWindow != 0) // window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
            if(m_pRenderer != 0) // renderer init success
            {
                std::cout << "renderer creation success\n";
                SDL_SetRenderDrawColor(m_pRenderer,255,255,255,255);
            }
            else
            {
                std::cout << "renderer init fail\n";
                return false; // renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false; // window init fail
        }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    std::cout << "init success\n";

    SDL_Surface* pTempSurface = SDL_LoadBMP("assets/rider.bmp");
    m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);

    SDL_QueryTexture(m_pTexture, NULL, NULL,&m_sourceRectangle.w,&m_sourceRectangle.h); // 获取长宽

    m_sourceRectangle.w = 50;
    m_sourceRectangle.h = 50;
    m_destinationRectangle.x = 100;
    m_destinationRectangle.y = 100;

    m_sourceRectangle.x = 50;
    m_sourceRectangle.y = 50;
    
    // m_destinationRectangle.x = m_sourceRectangle.x = 0;
    // m_destinationRectangle.y = m_sourceRectangle.y = 0;
    m_destinationRectangle.w = m_sourceRectangle.w;
    m_destinationRectangle.h = m_sourceRectangle.h;

    m_bRunning = true; // everything inited successfully, start the main loop
    return true;
}

在这里插入图片描述

3. 动图

有多帧图片,每100ms显示其中一张,可以让图片动起来
在这里插入图片描述

#include "Game.h"
#include <iostream>

using namespace std;

bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{   
    int flags = 0;
    if (fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }
    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if(m_pWindow != 0) // window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
            if(m_pRenderer != 0) // renderer init success
            {
                std::cout << "renderer creation success\n";
                SDL_SetRenderDrawColor(m_pRenderer,255,255,255,255);
            }
            else
            {
                std::cout << "renderer init fail\n";
                return false; // renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false; // window init fail
        }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    std::cout << "init success\n";

    // SDL_Surface* pTempSurface = SDL_LoadBMP("assets/rider.bmp");
    SDL_Surface* pTempSurface = SDL_LoadBMP("assets/animate.bmp");
    m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);

    SDL_QueryTexture(m_pTexture, NULL, NULL,&m_sourceRectangle.w,&m_sourceRectangle.h); // 获取长宽

    m_sourceRectangle.x = 0;
    m_sourceRectangle.y = 0;
    m_sourceRectangle.w = 128;
    m_sourceRectangle.h = 82;

    m_destinationRectangle.x = 0;
    m_destinationRectangle.y = 0;

    
    // m_destinationRectangle.x = m_sourceRectangle.x = 0;
    // m_destinationRectangle.y = m_sourceRectangle.y = 0;
    m_destinationRectangle.w = m_sourceRectangle.w;
    m_destinationRectangle.h = m_sourceRectangle.h;

    m_bRunning = true; // everything inited successfully, start the main loop
    return true;
}

void Game::render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
    // SDL_RenderCopy(m_pRenderer, m_pTexture,0,0);
    SDL_RenderCopy(m_pRenderer, m_pTexture,&m_sourceRectangle,&m_destinationRectangle);
    SDL_RenderPresent(m_pRenderer); // draw to the screen
}


void Game::handleEvents()
{
    SDL_Event event;
    if(SDL_PollEvent(&event))
    {
        switch (event.type)
    {
        case SDL_QUIT:
            m_bRunning = false;
        break;

        default:
        break;
    }
    }
}

void Game::clean()
{
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::update()
{
    m_sourceRectangle.x = 128 * int(((SDL_GetTicks() / 100) % 6));

}

在这里插入图片描述

可以翻转图片

void Game::render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
    // SDL_RenderCopy(m_pRenderer, m_pTexture,0,0);
    // SDL_RenderCopy(m_pRenderer, m_pTexture,&m_sourceRectangle,&m_destinationRectangle);
    SDL_RenderCopyEx(m_pRenderer, m_pTexture,&m_sourceRectangle, &m_destinationRectangle,0, 0, SDL_FLIP_HORIZONTAL); // pass in the horizontal flip
    SDL_RenderPresent(m_pRenderer); // draw to the screen
}

3. SDL_image

前面用的是SDL_LoadBMP只能加载bmp图片,SDL_image可以加载很多格式的图片,包括png,jpg,bmp,tiff,pcx,tif,lbm,xpm,gif,tk和xv等。

Game.h中引入SDL_image

#include <SDL2/SDL_image.h>

修改加载图片代码Game.cpp

SDL_Surface* pTempSurface = IMG_Load("assets/animate.png");

编译修改为:

g++ m14main.cpp Game.cpp  -o m14 -lSDL2 -lSDL2_image

Game.cpp代码如下:

#include "Game.h"
#include <iostream>

using namespace std;

bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{   
    int flags = 0;
    if (fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }
    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if(m_pWindow != 0) // window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
            if(m_pRenderer != 0) // renderer init success
            {
                std::cout << "renderer creation success\n";
                SDL_SetRenderDrawColor(m_pRenderer,255,0,0,255);
            }
            else
            {
                std::cout << "renderer init fail\n";
                return false; // renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false; // window init fail
        }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    std::cout << "init success\n";

    // SDL_Surface* pTempSurface = SDL_LoadBMP("assets/rider.bmp");
    // SDL_Surface* pTempSurface = SDL_LoadBMP("assets/animate.bmp");
    // SDL_Surface* pTempSurface = IMG_Load("assets/animate.png");
    SDL_Surface* pTempSurface = IMG_Load("assets/animate-alpha.png");
    m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);

    SDL_QueryTexture(m_pTexture, NULL, NULL,&m_sourceRectangle.w,&m_sourceRectangle.h); // 获取长宽

    m_sourceRectangle.x = 0;
    m_sourceRectangle.y = 0;
    m_sourceRectangle.w = 128;
    m_sourceRectangle.h = 82;

    m_destinationRectangle.x = 0;
    m_destinationRectangle.y = 0;

    
    // m_destinationRectangle.x = m_sourceRectangle.x = 0;
    // m_destinationRectangle.y = m_sourceRectangle.y = 0;
    m_destinationRectangle.w = m_sourceRectangle.w;
    m_destinationRectangle.h = m_sourceRectangle.h;

    m_bRunning = true; // everything inited successfully, start the main loop
    return true;
}

void Game::render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
    // SDL_RenderCopy(m_pRenderer, m_pTexture,0,0);
    // SDL_RenderCopy(m_pRenderer, m_pTexture,&m_sourceRectangle,&m_destinationRectangle);
    SDL_RenderCopyEx(m_pRenderer, m_pTexture,&m_sourceRectangle, &m_destinationRectangle,0, 0, SDL_FLIP_HORIZONTAL); // pass in the horizontal flip
    SDL_RenderPresent(m_pRenderer); // draw to the screen
}


void Game::handleEvents()
{
    SDL_Event event;
    if(SDL_PollEvent(&event))
    {
        switch (event.type)
    {
        case SDL_QUIT:
            m_bRunning = false;
        break;

        default:
        break;
    }
    }
}

void Game::clean()
{
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::update()
{
    m_sourceRectangle.x = 128 * int(((SDL_GetTicks() / 100) % 6));

}

在这里插入图片描述

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡侃有料

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值