【c++|SDL】三、画图类抽象

news2024/12/24 17:58:16

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

0. 前言

1. 画图类抽象

之前将画图(显示图像)放在Game.cpp中,现在将其单独放在一个类中,

编译运行为:

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

TextureManager.h
包含加载图片,显示图片,显示动画三个方法

#ifndef __TextureManager__
#define __TextureManager__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <string>
#include <iostream>
#include <map>

using namespace std;

class TextureManager
{

public:
    TextureManager() {};
    ~TextureManager() {};

    bool load(std::string fileName,std::string id, SDL_Renderer* pRenderer);
    // draw
    void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
    // drawframe
    void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer,SDL_RendererFlip flip = SDL_FLIP_NONE);
    
    std::map<std::string, SDL_Texture*> m_textureMap;
    
// private:
//     bool m_bRunning;

};

#endif /* defined(__Game__) */

TextureManager.cpp

#include "TextureManager.h"

bool TextureManager::load(std::string fileName, std::string id, SDL_Renderer* pRenderer)
{
    SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
    if(pTempSurface == 0)
    {
        return false;
    }
    SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);
    // everything went ok, add the texture to our list
    if(pTexture != 0)
    {
        m_textureMap[id] = pTexture;
        return true;
    }
    // reaching here means something went wrong
    return false;
}

void TextureManager::draw(std::string id,int x, int y, int width, int height,SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
    SDL_Rect srcRect;
    SDL_Rect destRect;
    srcRect.x = 0;
    srcRect.y = 0;
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect, 0, 0, flip);
}

void TextureManager::drawFrame(std::string id, int x, int y, int width, int height,int currentRow, int currentFrame,SDL_Renderer *pRenderer, SDL_RendererFlip flip)
{
    SDL_Rect srcRect;
    SDL_Rect destRect;
    srcRect.x = width * currentFrame;
    srcRect.y = height * (currentRow - 1);
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopyEx(pRenderer,m_textureMap[id], &srcRect, &destRect, 0, 0, flip);
}

之前Game.cpp中的加载显示等相关操作需要删除,并进行修改

Game.h

#ifndef __Game__
#define __Game__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// #include "TextureManager.h"
#include "TextureManager.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

    int m_currentFrame;
    TextureManager m_textureManager;
};

#endif /* defined(__Game__) */

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_textureManager.load("assets/animate-alpha.png", "animate", m_pRenderer);
    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

    SDL_RenderClear(m_pRenderer);
    m_textureManager.draw("animate", 0,0, 128, 82,m_pRenderer);
    m_textureManager.drawFrame("animate", 100,100, 128, 82, 1, m_currentFrame, m_pRenderer);
    SDL_RenderPresent(m_pRenderer);
}


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));
    m_currentFrame = int(((SDL_GetTicks() /100) % 6));

}

如下所示,其中右下角为动图

在这里插入图片描述

2. 单例模式

我们想在整个游戏中重用这个TextureManager,所以我们不想让它成为game类的成员,因为那样我们就必须把它传递给draw函数。对我们来说,一个很好的选择是将TextureManager实现为单例。单例是一个只能有一个实例的类

TextureManager.h

#ifndef __TextureManager__
#define __TextureManager__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <string>
#include <iostream>
#include <map>

using namespace std;

class TextureManager
{

public:

    bool load(std::string fileName,std::string id, SDL_Renderer* pRenderer);
    // draw
    void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
    // drawframe
    void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer,SDL_RendererFlip flip = SDL_FLIP_NONE);
    
    std::map<std::string, SDL_Texture*> m_textureMap;
    
    static TextureManager* Instance()
    {
        if(s_pInstance == 0)
        {
            s_pInstance = new TextureManager();
            return s_pInstance;
        }
        return s_pInstance;
    }
private:
    TextureManager() {};
    ~TextureManager() {};
    static TextureManager* s_pInstance;
//     bool m_bRunning;

};

typedef TextureManager TheTextureManager;

#endif /* defined(__Game__) */

TextureManager.cpp 中添加如下代码

TextureManager* TextureManager::s_pInstance = 0;

Game.h注释掉如下代码

TextureManager m_textureManager;

Game.cpp中读取图片替换为:

// to load
if(!TheTextureManager::Instance()->load("assets/animate-alpha.png", "animate",m_pRenderer))
{
    return false;
}

显示图片替换为:

// to draw
TheTextureManager::Instance()->draw("animate",0,0, 128, 82, m_pRenderer);
TheTextureManager::Instance()->drawFrame("animate", 100,100, 128, 82, 1, m_currentFrame, m_pRenderer);

最终效果相同

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1274225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Course1-Week3-分类问题

Course1-Week3-分类问题 文章目录 Course1-Week3-分类问题1. 逻辑回归1.1 线性回归不适用于分类问题1.2 逻辑回归模型1.3 决策边界 2. 逻辑回归的代价函数3. 实现梯度下降4. 过拟合与正则化4.1 线性回归和逻辑回归中的过拟合4.2 解决过拟合的三种方法4.3 正则化4.4 用于线性回归…

C语言之结构体详解

C语言之结构体详解 文章目录 C语言之结构体详解1. 结构体类型的声明2. 结构体变量的创建和初始化3. 结构体的特殊声明4. 结构体的自引用结构体的自引用匿名结构体的自引用 5. 结构体内存对齐5.1 练习一5.2 练习三 6. 为什么存在内存对⻬? 1. 结构体类型的声明 struct tag {me…

【Web】UUCTF 2022 新生赛 个人复现

目录 ①websign ②ez_rce ③ez_upload ④ez_unser ⑤ezsql ⑥ezpop ⑦funmd5 ⑧phonecode ⑨ezrce ①websign 右键打不开&#xff0c;直接抓包发包看源码 ②ez_rce “反引号” 在PHP中会被当作SHELL命令执行 ?codeprintf(l\s /); ?codeprintf(ta\c /ffffffffffl…

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

我的往期文章&#xff1a; leetCode 647.回文子串 动态规划 优化空间 / 中心扩展法 双指针-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133883091?spm1001.2014.3001.5501leetCode 131.分割回文串 回溯算法 图解 笔记-CSDN博客https://blog.csdn.n…

有什么值得推荐的node. js练手项目吗?

前言 可以参考一下下面的nodejs相关的项目&#xff0c;希望对你的学习有所帮助&#xff0c;废话少说&#xff0c;让我们直接进入正题 1、 NodeBB Star: 13.3k 一个基于Node.js的现代化社区论坛软件&#xff0c;具有快速、可扩展、易于使用和灵活的特点。它支持多种数据库&…

在Windows中加密文件或文件夹不需要太大的努力就可以实现,主要有两种加密方法

如果你正在寻找一种在Windows计算机上保持文件和文件夹隐私的简单方法,你有几个选择。 得益于Microsoft Office Suite,你可以使用内置的加密功能对Office文件(如Word文档或PowerPoint演示文稿)进行密码保护。 一些Windows操作系统还配备了加密文件系统(EFS),可以对任何…

Set集合的特点

Set系列集合特点&#xff1a; 无序&#xff1a;添加数据的顺序和获取出的数据顺序不一致&#xff1b;不重复&#xff1b;无索引&#xff1b; HashSet&#xff1a;无序&#xff0c;不重复&#xff0c;无索引 LinkedHashSet&#xff1a;有序&#xff0c;不重复&#xff0c;无索引…

python进阶技巧

1.闭包 通过函数嵌套&#xff0c;可以让内部函数依赖外部变量&#xff0c;可以避免全局变量的污染问题 闭包注意事项&#xff1a; 总结&#xff1a; 2.装饰器 2.1装饰器的一般写法 2.2 装饰器的语法糖写法 def outer(func):def inner():print(睡了)func()print(起床)retur…

Zookeeper从零入门笔记

Zookeeper从零入门笔记 一、入门1. 概述2. 特点3. 数据结构4. 应用场景 二、本地1.安装2. 参数解读 三、集群操作3.1.1 集群安装3.2 选举机制1. 第一次启动2. 非第一次启动 3.3 ZK集群启动停止脚本3.4 客户端命令行操作3.2.1 命令行语法3.2.2 节点类型&#xff08;持久/短暂/有…

飞致云开源社区月度动态报告(2023年11月)

自2023年6月起&#xff0c;中国领先的开源软件公司FIT2CLOUD飞致云以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大屏…

传统算法:使用 Pygame 实现选择排序

使用 Pygame 模块实现了选择排序的动画演示。首先,它生成一个包含随机整数的数组,并通过 Pygame 在屏幕上绘制这个数组的条形图。接着,通过选择排序算法对数组进行排序,动画效果可视化每一步的排序过程。在排序的过程中,程序找到未排序部分的最小元素,并将其与未排序部分…

如何获取阿里巴巴中国站按图搜索1688商品(拍立淘) API接口(item_search_img-按图搜索1688商品(拍立淘))

一、背景介绍 阿里巴巴中国站作为中国领先的B2B电子商务平台&#xff0c;提供了大量的商品信息和交易服务。其中&#xff0c;按图搜索1688商品&#xff08;拍立淘&#xff09;是阿里巴巴中国站特有的功能之一&#xff0c;它可以通过上传图片来搜索与图片相似的商品&#xff0c…

Js页面录屏切片存储数据上传后端

前端 screenShot(){// 获取屏幕共享流navigator.mediaDevices.getDisplayMedia({video: true,audio: true,//preferCurrentTab 共享本次操作的页面preferCurrentTab: true}).then(async stream > {const mediaRecorder new MediaRecorder(stream, { mimeType: video/webm; …

基于AT89C51单片机的秒表设计

1&#xff0e;设计任务 利用单片机AT89C51设计秒表&#xff0c;设计计时长度为9:59:59&#xff0c;超过该长度&#xff0c;报警。创新&#xff1a;设置重启&#xff1b;暂停&#xff1b;清零等按钮。最后10s时播放音乐提示。 本设计是采用AT89C51单片机为中心&#xff0c;利用其…

代码随想录算法训练营第一天 | 704. 二分查找 27. 移除元素

class Solution { public:int search(vector<int>& nums, int target) {int l0;int rnums.size()-1;while(l<r){int mid(lr)>>1;if(targetnums[mid]) return mid;if(target>nums[mid]){lmid1;}else{rmid-1;}}return -1;} }; 之前就已经熟悉二分法了&am…

【Linux】第二十三站:缓冲区

文章目录 一、一些奇怪的现象二、用户级缓冲区三、用户级缓冲区刷新问题四、一些其他问题1.缓冲区刷新的时机2.为什么要有这个缓冲区3.这个缓冲区在哪里&#xff1f;4.这个FILE对象属于用户呢&#xff1f;还是操作系统呢&#xff1f;这个缓冲区&#xff0c;是不是用户级的缓冲区…

Linux实现类似cp的命令

1.利用主函数的三个函数进行传参 1).主函数的三个参数的含义: argc:主函数的参数个数 argv:主函数的参数内容 envp:环境变量; 2).演示代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc,char *argv[],char *envp[]…

Vue3.x 中 hooks 函数封装和使用

一、hooks 是什么 vue3 中的 hooks 就是函数的一种写法&#xff0c;就是将文件的一些单独功能的 js 代码进行抽离出来进行封装使用。 它的主要作用是 Vue3 借鉴了 React 的一种机制&#xff0c;用于在函数组件中共享状态逻辑和副作用&#xff0c;从而实现代码的可复用性。 注…

[笔记]dubbo发送接收

个人笔记 consumer 主要使用ThreadlessExecutor实现全consumer的全双工通讯。consumer创建本次请求的requestId用于将response和request匹配。 然后分以下几步完成一次请求发送并接收结果&#xff1a; 槽&#xff1a;发送消息前将用于接收结果的executor放到一个map中存储 发…

AI落地现状:没有mission、业务零碎、连2B还是2C都在摇摆

最近我私下问某TOP AI 2.0公司的核心产品负责人&#xff0c;你们现在主要是2C还是2B&#xff1f; 他说的第一句话是&#xff0c;“整体没有misson”。 结合近期的各种信息&#xff0c;给大家说下行业最前沿的内幕。 1、据说&#xff0c;某1、2位大佬的AI认知&#xff0c;其实并…