You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现可渲染平台并存储坐标的类?避免重复创建对象

解决方案

核心问题分析

你当前的代码存在两个关键问题:

  1. 单个platform对象重复调用render时,只会覆盖自身坐标,无法保存多个平台的位置数据;
  2. 每帧render都重复加载纹理,既浪费性能又会导致内存泄漏;
  3. 碰撞类无法获取所有平台的坐标信息,因为没有持久化存储多个平台的数据。

重构方案

通过让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;
}

关键改进点

  1. 平台状态持久化:每个Platform对象独立存储自己的坐标和纹理,不会被覆盖;
  2. 性能优化:纹理仅加载一次,避免每帧重复IO操作;
  3. 便捷管理:用std::vector统一管理所有平台,添加/删除平台只需操作集合,无需手动定义大量变量;
  4. 碰撞支持:碰撞类可直接遍历platforms集合,获取每个平台的坐标进行检测。

内容的提问来源于stack exchange,提问作者user16595186

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:55:09