分配 2 个向量 SDL_Rect c++ 导致垃圾值

问题描述 投票:0回答:0

在 Tilemap 类中,我使用矢量 来保存每个 Tilemap 对象的平台位置和大小。在文件 Tilemap_data 中,我声明了我所有的 Tilemap 对象,包括它们附带的 vector。 我有一个 present_tilemap_pos_x 变量来检查 Tilemap 对象是否在屏幕之外。 在main.cpp中,如果程序运行正常,当正在显示的Tilemap对象(符号为“present_tilemap”)跑出屏幕,下一个Tilemap对象(符号为“next_tilemap”)正在显示时,程序会发生变化,使得present_tilemap 取 next_tilemap 的值,next_tilemap 的数据将从包含 SDL_Rect 对象的向量数组中随机获取。 (在我上面提到的 Tilemap 对象的数据集中)。

然而,虽然为 next_tilemap 分配新值工作正常,但为 present_tilemap 对象分配值是错误的,因为向量 的 x、y 和 h 值分配正确,而 w 值是垃圾值。

我将在这里发布我的代码,为了简化它,我将删除所有与我在问题中提出的问题无关的不相关部分。为了方便起见,我还会提供一个日志文件,记录每次迭代后的程序。

文件 Tilemap.hpp:

#pragma once
#ifndef Tilemap_hpp
#define Tilemap_hpp

#include <iostream>
#include <vector>
#include <SDL2/SDL.h>

using namespace std;

class Tilemap
{
private:
    int tilemap_index;
    int tilemap[18][32];
    int number_of_platform = 0;
    vector <SDL_Rect> platform_rects;

public:
    Tilemap();
    Tilemap(int index, int tilemap[18][32], int number, SDL_Rect platform[]);
    ~Tilemap();

    int get_tilemap_index();
    int get_tilemap(int x, int y);

    void set_tilemap_index(int index);
    void set_tilemap(int x, int y, int value);

    int get_number_of_platform();
    void set_number_of_platform(int number_of_platform);

    void set_platform_rects(std::vector <SDL_Rect> platform_rects);
    
    std::vector <SDL_Rect> get_platform_rects()
    {
        return platform_rects;
    }
    vector <SDL_Rect> update_platform_rects(Tilemap& tilemap, int tilemap_pos_x);

    void create_platform_rects(int x, int y, int width, int height);

    void update_platform_rects(int tilemap_pos_x);
};
#endif /* Tilemap_hpp */

文件 Tilemap.cpp:


#include "Tilemap.hpp"

Tilemap::Tilemap()
{
}
 
Tilemap::Tilemap(int index, int tilemap[18][32], int number, SDL_Rect platform[])
{
    tilemap_index = index;
    for (int i = 0; i < 18; i++)
    {
        for (int j = 0; j < 32; j++)
        {
            this->tilemap[i][j] = tilemap[i][j];
        }
    }
    number_of_platform = number;
    for (int i = 0; i < number; i++)
    {
        platform_rects.push_back(platform[i]);
    }
}
 
Tilemap::~Tilemap()
{
}
int Tilemap::get_tilemap_index()
{
    return tilemap_index;
}
int Tilemap::get_tilemap(int x, int y)
{
    return tilemap[x][y];
}
void Tilemap::set_tilemap_index(int index)
{
    tilemap_index = index;
}
void Tilemap::set_tilemap(int x, int y, int value)
{
    tilemap[x][y] = value;
}

void Tilemap::create_platform_rects(int x, int y, int width, int height)
{
    SDL_Rect platform_rect;
    platform_rect.x = x;
    platform_rect.y = y;
    platform_rect.w = width;
    platform_rect.h = height;
    platform_rects.push_back(platform_rect);
}

void Tilemap::update_platform_rects(int tilemap_pos_x)
{
    // di chuyển các platform sang trái với tốc độ speed
    for (int i = 0; i < platform_rects.size(); i++)
    {
        platform_rects[i].x += tilemap_pos_x;
    }

    // xóa các platform ở phía bên trái màn hình
    while (!platform_rects.empty() && platform_rects[0].x + platform_rects[0].w < 0)
    {
        platform_rects.erase(platform_rects.begin());
    }
}

int Tilemap::get_number_of_platform()
{
    return number_of_platform;
}

void Tilemap::set_number_of_platform(int number_of_platform)
{
    this->number_of_platform = number_of_platform;
}

void Tilemap::set_platform_rects(std::vector<SDL_Rect> platform_rects)
{
    this->platform_rects = platform_rects;
}


vector <SDL_Rect> Tilemap::update_platform_rects(Tilemap& tilemap, int tilemap_pos_x)
{
    for (int i = 0; i < platform_rects.size(); i++)
    {
        platform_rects[i].x += tilemap_pos_x;
    }
    return platform_rects;
}

文件 Tilemap_data.hpp:

...
SDL_Rect def_platform_0 = {240, 400, 1000, 80};
SDL_Rect array_of_platforms_0[1] = {def_platform_0};
Tilemap Default_tilemap(0, tile_map_default, 1, array_of_platforms_0);

SDL_Rect tilemap1_platform_1 = {0, 280, 280, 40};
SDL_Rect tilemap1_platform_2 = {280, 240, 320, 40};
SDL_Rect tilemap1_platform_3 = {600, 360, 120, 40};
SDL_Rect tilemap1_platform_4 = {720, 560, 120, 40};
SDL_Rect tilemap1_platform_5 = {840, 480, 200, 40};
SDL_Rect tilemap1_platform_6 = {1040, 400, 240, 40};
SDL_Rect array_of_platforms_1[6] = {tilemap1_platform_1, tilemap1_platform_2, tilemap1_platform_3, tilemap1_platform_4, tilemap1_platform_5, tilemap1_platform_6};
Tilemap Tilemap_1(1, tile_map_1, 6, array_of_platforms_1)

(16 more...
To simplify, all 16 next Tilemap objects are copies of the Tilemap_1 object.)

文件main.cpp:

// Using SDL and standard IO
#include "Library.hpp"
#include <fstream>

// Screen dimension constants
const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;

Game *game = nullptr;
Player *player = nullptr;

int main(int argc, char *args[])
{
    ofstream outfile;
    outfile.open("log.txt");

    int const FPS = 60;
    int const frameDelay = 1000 / FPS;
    player = new Player(320, 0, 1, -10, 0.5, 70, 90, false, false);

    Texture_box player_texture(0, 0, player->get_width(), player->get_height(), player->get_x(), player->get_y(), player->get_width(), player->get_height());

    Texture_box background(0, 0, 1280, 720, 0, 0, 1280, 720);
    Texture_box next_background(0, 0, 1280, 720, 1280, 0, 1280, 720);

    Texture_box sky(0, 0, 1280, 720, 0, 0, 1280, 720);

    Texture_box plains(0, 0, 1280, 720, 0, 0, 1280, 720);
    Texture_box next_plains(0, 0, 1280, 720, 1280, 0, 1280, 720);

    Texture_box mountain(0, 0, 1280, 720, 0, 0, 1280, 720);
    Texture_box next_mountain(0, 0, 1280, 720, 1280, 0, 1280, 720);

    Texture_box cloud(0, 0, 1280, 720, 0, 0, 1280, 720);
    Texture_box next_cloud(0, 0, 1280, 720, 1280, 0, 1280, 720);

    Texture_box cloud_front(0, 0, 1280, 720, 0, 0, 1280, 720);
    Texture_box next_cloud_front(0, 0, 1280, 720, 1280, 0, 1280, 720);

    Texture_box cloud_behind(0, 0, 1280, 720, 0, 0, 1280, 720);
    Texture_box next_cloud_behind(0, 0, 1280, 720, 1280, 0, 1280, 720);

    Uint32 frameStart;
    int frameTime;

    game = new Game();

    game->init("Sky Runner", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, false);

    SDL_Texture *texture[50];
    enum texture_type
    {
        BACKGROUND_SKY,
        BACKGROUND_MOUNTAIN,
        BACKGROUND_PLAINS,

        BACKGROUND_CLOUD,
        BACKGROUND_CLOUD_BEHIND,
        BACKGROUND_CLOUD_FRONT,

        CHARACTER,
        MENU,
        NEW_GAME,
        INSTRUCTION,
        SETTING,
        QUIT,
        INSTRUCTION_MENU,
    };

    game->loadTexture(texture[BACKGROUND_SKY], game->getRenderer(), "Image/Background/Sky.png");
    game->loadTexture(texture[BACKGROUND_MOUNTAIN], game->getRenderer(), "Image/Background/mountain.png");
    game->loadTexture(texture[BACKGROUND_PLAINS], game->getRenderer(), "Image/Background/plains_ground.png");

    game->loadTexture(texture[BACKGROUND_CLOUD], game->getRenderer(), "Image/Background/cloud_1.png");
    game->loadTexture(texture[BACKGROUND_CLOUD_BEHIND], game->getRenderer(), "Image/Background/cloud_behind.png");
    game->loadTexture(texture[BACKGROUND_CLOUD_FRONT], game->getRenderer(), "Image/Background/cloud_front.png");

    game->loadTexture(texture[CHARACTER], game->getRenderer(), "Image/Character/Character.png");

    game->loadTexture(texture[MENU], game->getRenderer(), "Image/Menu/Menu/menu.png");

    game->loadTexture(texture[NEW_GAME], game->getRenderer(), "Image/Menu/Menu/selected_start_button.png");
    game->loadTexture(texture[INSTRUCTION], game->getRenderer(), "Image/Menu/Menu/selected_instruction_button.png");
    game->loadTexture(texture[SETTING], game->getRenderer(), "Image/Menu/Menu/selected_setting_button.png");
    game->loadTexture(texture[QUIT], game->getRenderer(), "Image/Menu/Menu/selected_quit_button.png");

    Texture_box tilemap_texture(0, 0, 40, 40, 0, 0, 40, 40);
    SDL_Texture *pT;
    game->loadTexture(pT, game->getRenderer(), "Image/Background/test.png");

    int present_tilemap_pos_x = 0;
    int next_tilemap_pos_x = 1280;

    const int speed = 5;
    bool is_first_tilemap = true;
    int present_tilemap_index = 0;
    int next_tilemap_index = game->random_tilemap(18, game->getScore());

    vector<SDL_Rect> present_platform_rects = platform_rects[0];
    vector<SDL_Rect> next_platform_rects = platform_rects[next_tilemap_index];

    Tilemap present_tilemap = array_of_tilemap[present_tilemap_index];
    Tilemap next_tilemap = array_of_tilemap[next_tilemap_index];

    present_platform_rects = array_of_tilemap[present_tilemap_index].update_platform_rects(present_tilemap, present_tilemap_pos_x);

    next_platform_rects = next_tilemap.update_platform_rects(next_tilemap, next_tilemap_pos_x);

    int count = 0;

    game->render(game->getRenderer(), texture[BACKGROUND_SKY], sky.get_sourceRect(), sky.get_destinationRect());
    game->render(game->getRenderer(), texture[BACKGROUND_CLOUD], cloud.get_sourceRect(), cloud.get_destinationRect());
    game->render(game->getRenderer(), texture[BACKGROUND_CLOUD_BEHIND], cloud_behind.get_sourceRect(), cloud_behind.get_destinationRect());
    game->render(game->getRenderer(), texture[BACKGROUND_CLOUD_FRONT], cloud_front.get_sourceRect(), cloud_front.get_destinationRect());
    game->render(game->getRenderer(), texture[BACKGROUND_MOUNTAIN], mountain.get_sourceRect(), mountain.get_destinationRect());
    game->render(game->getRenderer(), texture[BACKGROUND_PLAINS], plains.get_sourceRect(), plains.get_destinationRect());
    game->render(game->getRenderer(), texture[MENU], main_menu_screen_box.get_sourceRect(), main_menu_screen_box.get_destinationRect());

    SDL_RenderPresent(game->getRenderer());

    while (game->menu())
    {
        SDL_Event event;
        SDL_PollEvent(&event);
        switch (event.type)
        {
        case SDL_QUIT:
            game->setRunning(false);
            break;
        case SDL_MOUSEMOTION:
            int mouseX, mouseY;
            SDL_GetMouseState(&mouseX, &mouseY);
            if (isMouseInside(mouseX, mouseY, new_game_button))
            {
                game->render(game->getRenderer(), texture[NEW_GAME], main_menu_screen_box.get_sourceRect(), main_menu_screen_box.get_destinationRect());
                SDL_RenderPresent(game->getRenderer());
            }
            else if (isMouseInside(mouseX, mouseY, quit_button))
            {
                game->render(game->getRenderer(), texture[QUIT], main_menu_screen_box.get_sourceRect(), main_menu_screen_box.get_destinationRect());
                SDL_RenderPresent(game->getRenderer());
            }
            else if (isMouseInside(mouseX, mouseY, setting_button))
            {
                game->render(game->getRenderer(), texture[SETTING], main_menu_screen_box.get_sourceRect(), main_menu_screen_box.get_destinationRect());
                SDL_RenderPresent(game->getRenderer());
            }
            else if (isMouseInside(mouseX, mouseY, instruction_button))
            {
                game->render(game->getRenderer(), texture[INSTRUCTION], main_menu_screen_box.get_sourceRect(), main_menu_screen_box.get_destinationRect());
                SDL_RenderPresent(game->getRenderer());
            }
            else
            {
                game->render(game->getRenderer(), texture[MENU], main_menu_screen_box.get_sourceRect(), main_menu_screen_box.get_destinationRect());
                SDL_RenderPresent(game->getRenderer());
            }
            break;
        case SDL_MOUSEBUTTONDOWN:
            // Kiểm tra xem người dùng đã click chuột vào nút nào

            SDL_GetMouseState(&mouseX, &mouseY);
            if (isMouseInside(mouseX, mouseY, new_game_button))
            {
                game->setPlaying(true);
                game->setMenu(false);
            }
            if (isMouseInside(mouseX, mouseY, quit_button))
            {
                game->setMenu(false);
                game->setRunning(false);
            }
            break;
        }
    }

    while (game->playing())
    {
        frameStart = SDL_GetTicks64();

        SDL_Event event;
        SDL_PollEvent(&event);
        switch (event.type)
        {
        case SDL_QUIT:
            game->setPlaying(false);
            game->setRunning(false);
            break;
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym)
            {
            case SDLK_ESCAPE:
                game->setPlaying(false);
                game->setRunning(false);
                break;
            case SDLK_UP:
                player->set_jumping(true);
                break;

            case SDLK_RIGHT:

                break;
            }
        default:
            count++;
            game->setScore(count / 10);
            outfile << "Number of key event: " << count << endl;
            outfile << "Your score: " << game->getScore() << endl;

            present_platform_rects = present_tilemap.update_platform_rects(present_tilemap, -speed);
            next_platform_rects = next_tilemap.update_platform_rects(next_tilemap, -speed);

            player->player_jumping(*player);
            player->set_falling(player->is_falling(*player, present_platform_rects, next_platform_rects));

            player->player_falling(*player);

            player_texture.set_destinationRect(player->get_x(), player->get_y(), player->get_width(), player->get_height());

            present_tilemap_pos_x -= speed;
            next_tilemap_pos_x -= speed;
            break;
        }
        /*
        game->Moving_background(texture[BACKGROUND_CLOUD], cloud, next_cloud, game->getRenderer(), speed - 4);
        game->Moving_background(texture[BACKGROUND_CLOUD_BEHIND], cloud_behind, next_cloud_behind, game->getRenderer(), speed - 3);
        game->Moving_background(texture[BACKGROUND_CLOUD_FRONT], cloud_front, next_cloud_front, game->getRenderer(), speed - 2);
        game->Moving_background(texture[BACKGROUND_MOUNTAIN], mountain, next_mountain, game->getRenderer(), speed - 1);
        game->Moving_background(texture[BACKGROUND_PLAINS], plains, next_plains, game->getRenderer(), speed);
        */
        // Background render

        game->render(game->getRenderer(), texture[BACKGROUND_SKY], sky.get_sourceRect(), sky.get_destinationRect());

        game->render(game->getRenderer(), texture[BACKGROUND_CLOUD], cloud.get_sourceRect(), cloud.get_destinationRect());
        game->render(game->getRenderer(), texture[BACKGROUND_CLOUD], next_cloud.get_sourceRect(), next_cloud.get_destinationRect());

        game->render(game->getRenderer(), texture[BACKGROUND_CLOUD_BEHIND], cloud_behind.get_sourceRect(), cloud_behind.get_destinationRect());
        game->render(game->getRenderer(), texture[BACKGROUND_CLOUD_BEHIND], next_cloud_behind.get_sourceRect(), next_cloud_behind.get_destinationRect());

        game->render(game->getRenderer(), texture[BACKGROUND_CLOUD_FRONT], cloud_front.get_sourceRect(), cloud_front.get_destinationRect());
        game->render(game->getRenderer(), texture[BACKGROUND_CLOUD_FRONT], next_cloud_front.get_sourceRect(), next_cloud_front.get_destinationRect());

        game->render(game->getRenderer(), texture[BACKGROUND_MOUNTAIN], mountain.get_sourceRect(), mountain.get_destinationRect());
        game->render(game->getRenderer(), texture[BACKGROUND_MOUNTAIN], next_mountain.get_sourceRect(), next_mountain.get_destinationRect());

        game->render(game->getRenderer(), texture[BACKGROUND_PLAINS], plains.get_sourceRect(), plains.get_destinationRect());
        game->render(game->getRenderer(), texture[BACKGROUND_PLAINS], next_plains.get_sourceRect(), next_plains.get_destinationRect());

        game->render(game->getRenderer(), texture[CHARACTER], player_texture.get_sourceRect(), player_texture.get_destinationRect());

        // Tilemap render

        if (is_first_tilemap || present_tilemap_pos_x <= -1280)
        {
            if (is_first_tilemap)
            {
                game->infinite_tilemap(array_of_tilemap, 18, tilemap_texture, pT, 0, next_tilemap_index, present_tilemap_pos_x, next_tilemap_pos_x, speed);
                // present_platform_rects = platform_rects[present_tilemap_index];
                if (present_tilemap_pos_x == -1280)
                {
                    is_first_tilemap = false;
                }
            }
            else
            {
                present_tilemap_index = next_tilemap_index;
                next_tilemap_index = game->random_tilemap(18, game->getScore());

                present_tilemap = array_of_tilemap[present_tilemap_index];
                next_tilemap = array_of_tilemap[next_tilemap_index];

                present_platform_rects.clear();
                next_platform_rects.clear();
                
                present_platform_rects.assign(platform_rects[present_tilemap_index].begin(), platform_rects[present_tilemap_index].end());
                

                next_platform_rects = platform_rects[next_tilemap_index];

                present_tilemap_pos_x = 0;
                next_tilemap_pos_x = 1280;

                present_platform_rects = present_tilemap.update_platform_rects(present_tilemap, present_tilemap_pos_x);
                next_platform_rects = next_tilemap.update_platform_rects(next_tilemap, next_tilemap_pos_x);
            }
        }

        game->drawing_tilemap(array_of_tilemap[present_tilemap_index], tilemap_texture, pT, present_tilemap_pos_x);
        game->drawing_tilemap(array_of_tilemap[next_tilemap_index], tilemap_texture, pT, next_tilemap_pos_x);
        SDL_RenderPresent(game->getRenderer());

        frameTime = SDL_GetTicks64() - frameStart;

        if (frameDelay > frameTime)
        {
            SDL_Delay(frameDelay - frameTime);
        }

        game->death_message(*player);
    }

    game->clean();

    return 0;
}

文件log.txt文件:

Game start!
---------------------------------------------
Number of key event: 0
Present_tilemap_index: [0]
    platform[0]_rect: 240 400 1000 80
Next_tilemap_index: [2]
    next_platform[0]_rect: 1280 280 280 40
    next_platform[1]_rect: 1560 240 320 40
    next_platform[2]_rect: 1880 360 120 40
    next_platform[3]_rect: 2000 560 120 40
    next_platform[4]_rect: 2120 480 200 40
    next_platform[5]_rect: 2320 400 240 40
---------------------------------------------
Number of key event: 1
Present_tilemap_index: [0]
    platform[0]_rect: 235 400 1000 80
Next_tilemap_index: [2]
    next_platform[0]_rect: 1275 280 280 40
    next_platform[1]_rect: 1555 240 320 40
    next_platform[2]_rect: 1875 360 120 40
    next_platform[3]_rect: 1995 560 120 40
    next_platform[4]_rect: 2115 480 200 40
    next_platform[5]_rect: 2315 400 240 40
---------------------------------------------
Number of key event: 2
Present_tilemap_index: [0]
    platform[0]_rect: 230 400 1000 80
Next_tilemap_index: [2]
    next_platform[0]_rect: 1270 280 280 40
    next_platform[1]_rect: 1550 240 320 40
    next_platform[2]_rect: 1870 360 120 40
    next_platform[3]_rect: 1990 560 120 40
    next_platform[4]_rect: 2110 480 200 40
    next_platform[5]_rect: 2310 400 240 40
---------------------------------------------
...
---------------------------------------------
Number of key event: 256
Present_tilemap_index: [0]
    platform[0]_rect: -1040 400 1000 80
Next_tilemap_index: [2]
    next_platform[0]_rect: 0 280 280 40
    next_platform[1]_rect: 280 240 320 40
    next_platform[2]_rect: 600 360 120 40
    next_platform[3]_rect: 720 560 120 40
    next_platform[4]_rect: 840 480 200 40
    next_platform[5]_rect: 1040 400 240 40
---------------------------------------------
Number of key event: 257
Present_tilemap_index: [0]
    platform[0]_rect: -1045 400 1000 80
Next_tilemap_index: [2]
    next_platform[0]_rect: -5 280 280 40
    next_platform[1]_rect: 275 240 320 40
    next_platform[2]_rect: 595 360 120 40
    next_platform[3]_rect: 715 560 120 40
    next_platform[4]_rect: 835 480 200 40
    next_platform[5]_rect: 1035 400 240 40
--------------------------------------------- 
//My note: after "keyevent 257, the condition for assigning the Tilemap objects (that I mentioned above) is satisfied.
---------------------------------------------
My note 2: If it works directly, the log must be:
Present_tilemap_index_after_update: [2]
    platform[0]_rect: 0 280 280 40
    platform[1]_rect: 280 240 320 40
    platform[2]_rect: 600 360 120 40
    platform[3]_rect: 720 560 120 40
    platform[4]_rect: 840 480 200 40
    platform[5]_rect: 1040 400 240 40
---------------------------------------------
The real result: 
Present_tilemap_index_after_update: [2]
    platform[0]_rect: 0 280 1000 40
    platform[1]_rect: 280 240 -131965695 40
    platform[2]_rect: 600 360 -1769019472 40
    platform[3]_rect: 720 560 -131310329 40
    platform[4]_rect: 840 480 5111881 40
    platform[5]_rect: 1040 400 -131179259 40
---------------------------------------------
Number of key event: 258
Your score: 25
Player: 320 150 70 90
Player max height: 0
Falling: 0
Jumping: 0
Present_tilemap_index: [2]
    platform[0]_rect: -5 280 1000 40
    platform[1]_rect: 275 240 -131965695 40
    platform[2]_rect: 595 360 -1769019472 40
    platform[3]_rect: 715 560 -131310329 40
    platform[4]_rect: 835 480 5111881 40
    platform[5]_rect: 1035 400 -131179259 40
Next_tilemap_index: [13]
    next_platform[0]_rect: 1275 280 280 40
    next_platform[1]_rect: 1555 240 320 40
    next_platform[2]_rect: 1875 360 120 40
    next_platform[3]_rect: 1995 560 120 40
    next_platform[4]_rect: 2115 480 200 40
    next_platform[5]_rect: 2315 400 240 40
---------------------------------------------
...

我尝试了各种不同的方法,但结果还是一样。我哪里做错了?请帮我。如果您需要任何其他信息,我会提供。

c++ sdl-2
© www.soinside.com 2019 - 2024. All rights reserved.