Renderer是如何传递给其他类的

How did a Renderer pass to the rest of the classes?

本文关键字:其他 何传递 Renderer      更新时间:2024-05-10

我有一个Game类,它通过构造函数初始化窗口和SDL渲染器。我从目前为止读到的内容(不多(中了解到,每个窗口应该只有一个渲染器。

然后我有一个Player类,我想通过构造函数加载一个带有图像的纹理,为此我需要渲染器,因此,我将渲染器作为构造函数参数,通过这种方式,我被迫从Game的构造函数将渲染器传递给Player构造函数(因为它在Game类中实例化了Player类(。

事实上,渲染器是在创建之前传递的,我不知道是否有其他方法可以从游戏中调用播放器的构造函数,因为它迫使我这么说。我把代码留给你看:

游戏类别:

#pragma once
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "player.hpp"
//#include "helpers.hpp"
using namespace std;
#define WINDOW_WIDHT 640
#define WINDOW_HEIGTH 480
class Game
{
public:
Game();
~Game();
void loop();
void update() {}
void input();
void render();
void draw() {}
private:
SDL_Window *window;
SDL_Renderer *renderer = nullptr;
SDL_Event event;
SDL_Texture *gTexture;
bool running;
Player player;
};
Game::Game() : player(renderer)
{
SDL_Init(0);
SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Intento...");
//inicializa la carga de pngs
int imgFlags = IMG_INIT_PNG;
if (!IMG_Init(imgFlags) & imgFlags)
{
cout << "No se puede inicializar SDL_Img" << endl;
}

running = true;
loop();
}
Game::~Game()
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}
void Game::loop()
{
while (running)
{
input();
render();
update();
}
}
void Game::render()
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_Rect rect;
rect.x = rect.y = 0;
rect.w = WINDOW_WIDHT;
rect.h = WINDOW_HEIGTH;
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
}
void Game::input()
{
while (SDL_PollEvent(&event) > 0)
{
switch (event.type)
{
case SDL_QUIT:
running = false;
break;
}
}
}

冲突玩家:

#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
//#include "helpers.hpp"
using namespace std;
class Player
{
public:
Player(SDL_Renderer *renderer);
~Player() = default;
const SDL_Rect getDest() { return dest; }
const SDL_Rect getSrc() { return src; }
void setDest(int x, int y, int w, int h);
void setSrc(int x, int y, int w, int h);
SDL_Texture *loadTexture(std::string path, SDL_Renderer *renderer);
private:
SDL_Rect dest;
SDL_Rect src;
};
Player::Player(SDL_Renderer *renderer){
loadTexture("mario.png", renderer);
/* setSrc(48, 48, 48, 48);
setDest(100, 100, 48, 48);
SDL_Rect playerRectSrc = getSrc();
SDL_Rect playerRectDest = getDest(); */
}
void Player::setDest(int x, int y, int w, int h){
dest.x = x;
dest.y = y;
dest.w = w;
dest.h = h;
}
void Player::setSrc(int x, int y, int w, int h){
src.x = x;
src.y = y;
src.w = w;
src.h = h;
}
SDL_Texture* Player::loadTexture(std::string path, SDL_Renderer *renderer)
{
SDL_Texture *newTexture = NULL;
SDL_Surface *loadedSurface = IMG_Load(path.c_str());
if (loadedSurface == NULL)
{
cout << "No se pudo cargar la imagen" << endl;
}
else
{
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (newTexture == NULL)
{
cout << "No se pudo generar la textura para player" << endl;
}
SDL_FreeSurface(loadedSurface);
}
return newTexture;
}

问题是如何在创建渲染器后调用Player构造函数?我唯一能想到的不是通过构造函数创建纹理,而是通过函数创建纹理,但这不是正确的做法,对吧?这就是的构造函数

我唯一能想到的不是通过构造函数创建纹理,而是通过函数创建纹理,但这不是正确的做法,对吧?这就是的构造函数

右。然而,SDL是一个C库,因此它不使用负责构建/销毁的C++RAII。首先,我们调用成员初始值设定项列表(: foo{}, bar{foo}(中的构造函数,它为我们提供了完全构造的成员对象。然后,我们在构造函数主体({ use(foo); }(中执行我们想要的任何操作。但是,在您的情况下,在成员初始化(: player{renderer}(之前需要构造函数主体({ SDL_CreateWindowAndRenderer(...); }(。

问题是如何在创建渲染器后调用Player构造函数?

在构造Player:之前构造所有SDL_内容

class RenderWindow {
SDL_Window* window;
SDL_Renderer* renderer;
public:
RenderWindow() {
SDL_Init(0);
SDL_CreateWindowAndRenderer(WINDOW_WIDHT, WINDOW_HEIGTH, 0, &window, &renderer);
SDL_SetWindowTitle(window, "Intento...");
}
// an easy double-free protection, you can use anything else
RenderWindow(RenderWindow&&) = delete;
~RenderWindow() {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
// lvalue-only to forbid dangling like RenderWindow{}.raw_renderer()
auto raw_renderer() & { return renderer; }
};

现在,您的PlayerGame可以在一个自然的RAII构造中实现,然后使用方法:

class Player {
public:
Player(SDL_Renderer*); // TODO implement
};
class Game {
// note the declaration order: construction goes from top to bottom
RenderWindow render_window;
Player player;
public:
// SDL_* happens in render_window{},
// so player{render_window.raw_renderer()} gets an initialized SDL_Renderer
Game(): /*render_window{},*/ player{render_window.raw_renderer()} {}
};