如何在SDL2中渲染同一种结构的多个实例

huangapple go评论60阅读模式
英文:

How to render multiple instances of the same struct in SDL2

问题

// 主游戏循环
void Game::gameLoop(){
    实体 player;
    实体 bulletHead;
    实体 *bulletTail = new 实体();

    bulletTail = &bulletHead;

    player.x = 500;
    player.y = 640;
    player.dx = 0;
    player.dy = 0;
    player.texture = loadTexture((char*)"res/images/player.png");
    SDL_QueryTexture(player.texture, NULL, NULL, &player.w, &player.h);

    SDL_Texture *bulletTexture = loadTexture((char*)"res/images/bullet.png");

    while(gameState != GameState::EXIT){
        准备场景(); // 设置渲染
        处理事件(); // 收集和处理用户输入

        player.x += player.dx;
        player.y += player.dy;

        // 玩家按键输入
        if(player.reload > 0) player.reload--;

        if (up)
        {
            player.y -= 4;
        }

        if (down)
        {
            player.y += 4;
        }

        if (left)
        {
            player.x -= 4;
        }

        if (right)
        {
            player.x += 4;
        }

        // 允许每8帧射击子弹
        if(fire && player.reload == 0){
            player.reload = 8;

            // 创建子弹
            实体 *bullet = new 实体();
            memset(bullet, 0, sizeof(实体));

            bulletTail->next = bullet;
            bulletTail = bullet;

            bullet->x = player.x + 8;
            bullet->y = player.y;
            bullet->dx = 0;
            bullet->dy = -PLAYER_BULLET_SPEED;
            bullet->health = 1;
            bullet->texture = bulletTexture;
            SDL_QueryTexture(bullet->texture, NULL, NULL, &bullet->w, &bullet->h); 
        }

        // 处理每颗子弹的物理和渲染
        实体 *b = new 实体();
        实体 *prev = new 实体();
        prev = &bulletHead;
        // 错误从这里开始 👇	🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫
        for (b = bulletHead.next ; b != NULL ; b = b->next){
            b->x += b->dx;
            b->y += b->dy;

            blit(b->texture, b->x, b->y);

            if(b->y < 0){
                if (b == bulletTail)
                {
                    bulletTail = prev;
                }
                prev->next = b->next;
                free(b);
                b = prev;
            }

            prev = b;
        }
        // 错误在这里结束 🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫

        blit(player.texture, player.x, player.y); // 显示图像

        显示场景(); // 显示场景
        SDL_Delay(16); // 限制帧速率为大约62帧每秒
    }

    SDL_DestroyWindow(window);
    SDL_Quit();
}
英文:

I am building a C++ game using SDL2. Everything was going well and I was able to make the player shoot a single bullet. I later modified my code to render multiple bullets as shown below.

Main game loop

void Game::gameLoop(){
Entity player;
Entity bulletHead;
Entity *bulletTail = new Entity();
bulletTail = &bulletHead;
player.x = 500;
player.y = 640;
player.dx = 0;
player.dy = 0;
player.texture = loadTexture((char*)"res/images/player.png");
SDL_QueryTexture(player.texture, NULL, NULL, &player.w, &player.h);
SDL_Texture *bulletTexture = loadTexture((char*)"res/images/bullet.png");
while(gameState != GameState::EXIT){
prepareScene(); // sets up rendering
handleEvents(); // collects and precesses user input
player.x += player.dx;
player.y += player.dy;
// Player key input
if(player.reload > 0) player.reload--;
if (up)
{
player.y -= 4;
}
if (down)
{
player.y += 4;
}
if (left)
{
player.x -= 4;
}
if (right)
{
player.x += 4;
}
// allow fire bullet every 8 frames
if(fire && player.reload == 0){
player.reload = 8;
// Create bullet
Entity *bullet = new Entity();
memset(bullet, 0, sizeof(Entity));
bulletTail->next = bullet;
bulletTail = bullet;
bullet->x = player.x + 8;
bullet->y = player.y;
bullet->dx = 0;
bullet->dy = -PLAYER_BULLET_SPEED;
bullet->health = 1;
bullet->texture = bulletTexture;
SDL_QueryTexture(bullet->texture, NULL, NULL, &bullet->w, &bullet->h); 
}
// handle physics and render for each bullet
Entity *b = new Entity();
Entity *prev = new Entity();
prev = &bulletHead;
// Error starts here 👇	🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫
for (b = bulletHead.next ; b != NULL ; b = b->next){
b->x += b->dx;
b->y += b->dy;
blit(b->texture, b->x, b->y);
if(b->y < 0){
if (b == bulletTail)
{
bulletTail = prev;
}
prev->next = b->next;
free(b);
b = prev;
}
prev = b;
}
// Error stops here 🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫🚫
blit(player.texture, player.x, player.y); // display image
presentScene(); // displays scene
SDL_Delay(16); // limits fps to around 62fps
}
SDL_DestroyWindow(window);
SDL_Quit();
}

As can be seen above, I can successfully create bullets but whenever I include the for loop to go through my linked list of bullets and move/draw them, the program closes unexpectedly. No error is shown, it just closes as soon as I ran it. Removing the for loop works but I need a way to loop through the linked list of bullets and draw/animate them.

答案1

得分: 0

标准库提供了许多容器供您使用,例如 std::vector。以下示例假设您有一个 std::vector<Entity> bullets

如果您想遍历一个向量并在遍历过程中删除项目的选项,有两种选择,您可以使用 erase 方法,它会从向量中删除一个项目并返回一个新迭代器

使用方法:

for (auto it = bullets.begin(); it != bullets.end(); /* 无操作,见下文 */) {
  // 使用 *it 进行操作
  if (/* 需要删除子弹 */) {
    it = bullets.erase(it);
  } else {
    // 前进到下一个项目
    it++;
  }
}
英文:

The standard library has lots of containers for you to use, for example std::vector. The examples below assume you have a std::vector<Entity> bullets.
If you want to walk a vector and have the option to remove items as you go, there are two options, you can use the erase method, which removes an item from the vector and returns a new iterator.

To use:

for (auto it = bullets.begin(); it != bullets.end(); /* no-op, see below */) {
// do stuff with *it
if (/* bullet needs to be removed */) {
it = bullets.erase(it);
} else {
// advance to the next item
it++;
}

huangapple
  • 本文由 发表于 2023年4月6日 20:49:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75949725.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定