如何实现可渲染平台并存储坐标的类?避免重复创建对象
解决方案
核心问题分析
你当前的代码存在两个关键问题:
- 单个
platform对象重复调用render时,只会覆盖自身坐标,无法保存多个平台的位置数据; - 每帧
render都重复加载纹理,既浪费性能又会导致内存泄漏; - 碰撞类无法获取所有平台的坐标信息,因为没有持久化存储多个平台的数据。
重构方案
通过让Platform对象自身存储状态+用集合管理多个平台的方式解决问题,以下是修改后的完整代码:
1. 修改platform.h
让Platform类通过构造函数初始化坐标和纹理,自身维护状态:
class Platform { public: int x, y; SDL_Texture* tex; // 构造函数:初始化坐标与纹理 Platform(int x, int y, SDL_Renderer* renderer); // 析构函数:释放纹理,避免内存泄漏 ~Platform(); // 渲染方法:使用自身存储的坐标,无需外部传入 void render(SDL_Renderer* renderer); private: };
2. 修改platform.cpp
将纹理加载移到构造函数,渲染时直接使用自身存储的坐标:
#include "platform.h" #include "TextureManager.h" #include "MakeSquare.h" Platform::Platform(int x, int y, SDL_Renderer* renderer) { this->x = x; this->y = y; // 仅加载一次纹理,避免重复IO操作 tex = TextureManager::LoadTexture("assets/platform.png"); } Platform::~Platform() { SDL_DestroyTexture(tex); } void Platform::render(SDL_Renderer* renderer) { SDL_Rect destR; destR.x = x; destR.y = y; destR.w = destR.h = 32; // 存储当前平台的碰撞边界(需修改MakeSquare支持多平台存储,比如用vector保存所有边界) int xBounds[2] = { x - 16, x + 16 }; int yBounds[2] = { y - 16, y + 16 }; MakeSquare::storePlatformBounds(xBounds, yBounds); SDL_RenderCopy(renderer, tex, NULL, &destR); }
3. 修改Game.h
添加std::vector来统一管理所有平台对象:
#include <vector> #include "platform.h" class Game { public: Game(); ~Game(); static const int width; static const int height; void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen); void handleEvents(); void update(); void render(); void clean(); bool running() { return isRunning; } static SDL_Renderer* renderer; private: bool isRunning; SDL_Window* window; // 用vector存储所有平台,避免手动定义多个变量 std::vector<Platform> platforms; };
4. 修改Game.cpp
在初始化阶段创建所有平台,渲染时遍历集合绘制:
#include "Game.h" #include "Background.h" #include "Player.h" #include <iostream> Background* background; SDL_Renderer* Game::renderer = nullptr; SDL_Rect srcR, destR; Player player; Game::Game() {} Game::~Game() {} const int Game::width = 800; const int Game::height = 640; int cnt = 0; SDL_Texture* tex; void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) { int flags = 0; if (fullscreen) { flags = SDL_WINDOW_FULLSCREEN; } if (SDL_Init(SDL_INIT_EVERYTHING) == 0) { std::cout << "Subsystems Initialised!..." << std::endl; window = SDL_CreateWindow(title, xpos, ypos, width, height, flags); if (window) { std::cout << "Window created!" << std::endl; } renderer = SDL_CreateRenderer(window, -1, 0); if (renderer) { SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); std::cout << "Renderer created!" << std::endl; } isRunning = true; } background = new Background(); // 初始化所有平台,一次性创建,无需重复定义对象 platforms.emplace_back(100, 100, renderer); platforms.emplace_back(300, 100, renderer); platforms.emplace_back(200, 100, renderer); } void Game::handleEvents() { SDL_Event event; SDL_PollEvent(&event); player.handleInput(event); switch (event.type) { case SDL_QUIT: isRunning = false; break; default: break; } } void Game::update() { // 碰撞检测:遍历所有平台,获取每个平台的坐标 for (auto& plat : platforms) { // 示例:传递平台坐标给碰撞类 // CollisionChecker::checkPlayerPlatform(player, plat.x, plat.y); } } void Game::render() { SDL_RenderClear(renderer); background->DrawBackground(); player.render(renderer); // 遍历所有平台,逐个绘制 for (auto& plat : platforms) { plat.render(renderer); } SDL_RenderPresent(renderer); } void Game::clean() { SDL_DestroyWindow(window); SDL_DestroyRenderer(renderer); SDL_Quit(); std::cout << "Game Cleaned" << std::endl; } void boxMaker(SDL_Rect rec, int x, int y, int w, int h) { rec.x = x; rec.y = y; rec.w = w; rec.h = h; }
关键改进点
- 平台状态持久化:每个Platform对象独立存储自己的坐标和纹理,不会被覆盖;
- 性能优化:纹理仅加载一次,避免每帧重复IO操作;
- 便捷管理:用
std::vector统一管理所有平台,添加/删除平台只需操作集合,无需手动定义大量变量; - 碰撞支持:碰撞类可直接遍历
platforms集合,获取每个平台的坐标进行检测。
内容的提问来源于stack exchange,提问作者user16595186
相关产品推荐
相关产品推荐

