与超过1个Object SDL 2.0-C ++的冲突

时间:2015-11-25 19:16:37

标签: c++ sdl-2

我是新来的。我一直在学习课程,并尝试制作一个非常简单的平台游戏。但我现在有问题。我想设置Class" Player"碰撞2个Class" Block"但是碰撞不适用于其中一个。

这是我的代码:

#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#undef main

class Block
{
private:
    SDL_Texture *BlockTexture;
public:
    Block(SDL_Renderer *renderTarget, std::string filePath, int xPos, int yPos, int Width, int Height);
    ~Block();
    void Draw(SDL_Renderer *renderTarget);
    SDL_Rect BlockPos;
};
Block::Block(SDL_Renderer *renderTarget, std::string filePath, int xPos, int yPos, int Width, int Height)
{
    SDL_Surface *surface = IMG_Load(filePath.c_str());
    {
        BlockTexture = SDL_CreateTextureFromSurface(renderTarget, surface);
    }
    SDL_FreeSurface(surface);

    BlockPos.x = xPos;
    BlockPos.y = yPos;
    BlockPos.w = Width;
    BlockPos.h = Height;
}
Block::~Block()
{
    SDL_DestroyTexture(BlockTexture);
}
void Block::Draw(SDL_Renderer *renderTarget)
{
    SDL_RenderCopy(renderTarget, BlockTexture, NULL, &BlockPos);
}
class Player
{
private:
    SDL_Texture *Texture;
    float moveSpeed;
    float jumpSpeed;
    int falling = 0;
    SDL_Scancode keys [3];
public:
    SDL_Rect PlayerPos;
    Player(SDL_Renderer *renderTarget, std::string filePath, int PosX, int PosY,     int Width, int Height);
    ~Player();

    void Update(float delta, const Uint8 *Keystate);
    void Draw(SDL_Renderer *renderTarget);

    bool Collision(Block &p);
};
Player::Player(SDL_Renderer *renderTarget, std::string filePath, int PosX, int     PosY, int Width, int Height)
{
    SDL_Surface *surface = IMG_Load(filePath.c_str());
    {
        Texture = SDL_CreateTextureFromSurface(renderTarget, surface);
    }
    SDL_FreeSurface(surface);

    PlayerPos.x = PosX;
    PlayerPos.y = PosY;
    PlayerPos.w = Width;
    PlayerPos.h = Height;

    keys[0] = SDL_SCANCODE_UP;
    keys[1] = SDL_SCANCODE_LEFT;
    keys[2] = SDL_SCANCODE_RIGHT;

    moveSpeed = 200.f;
    jumpSpeed = 100.f;
}
Player::~Player()
{
    SDL_DestroyTexture(Texture);
}
void Player::Update(float delta, const Uint8 *KeyState)
{
    if(KeyState[keys[0]])
    {
        PlayerPos.y -= moveSpeed * delta;
    }
    if(KeyState[keys[1]])
    {
        PlayerPos.x -= (moveSpeed / 2) * delta;
    }
    if(KeyState[keys[2]])
    {
        PlayerPos.x += moveSpeed * delta;
    }
    if(falling == 0)
    {
        PlayerPos.y += jumpSpeed * delta;
    }
}
void Player::Draw(SDL_Renderer *renderTarget)
{
    SDL_RenderCopy(renderTarget, Texture, NULL, &PlayerPos);
}
bool Player::Collision(Block &p)
{
    if(PlayerPos.x + PlayerPos.w <= p.BlockPos.x || PlayerPos.x >= p.BlockPos.x + p.BlockPos.w ||
        PlayerPos.y + PlayerPos.h <= p.BlockPos.y || PlayerPos.y >= p.BlockPos.y + p.BlockPos.h)
    {
        falling = 0;
        return true;
    }
    else
        falling = 1;
        return false;
}
SDL_Texture *LoadTexture(std::string filePath, SDL_Renderer *Renderer)
{
    SDL_Texture *texture = NULL;
    SDL_Surface *surface = IMG_Load(filePath.c_str());
    {
        texture = SDL_CreateTextureFromSurface(Renderer, surface);
    }
    SDL_FreeSurface(surface);
    return texture;
}
int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_EVERYTHING);

    SDL_Window *window = SDL_CreateWindow("Platform", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
    SDL_Renderer *renderTarget = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    int imgFlags = IMG_INIT_PNG;

    int currentTime = 0;
    int previousTime = 0;
    float delta = 0;

    const Uint8 *Keystate;

    Player Player(renderTarget, "BlockP.png", 100, 100, 50, 50);

    Block Block1(renderTarget, "Block.png", 0, 500, 800, 100);
    Block Block2(renderTarget, "Block.png", 100, 300, 300, 50);

    bool isRunning = true;
    SDL_Event ev;

    while(isRunning)
    {
        Keystate = SDL_GetKeyboardState(NULL);

        Player.Collision(Block1);
        Player.Collision(Block2);

        previousTime = currentTime;
        currentTime = SDL_GetTicks();
        delta = (currentTime - previousTime) / 1000.0f;

        Player.Update(delta, Keystate);

        while(SDL_PollEvent(&ev) != 0)
        {
            if(ev.type == SDL_QUIT)
                isRunning = false;
        }
        SDL_RenderClear(renderTarget);

        Player.Draw(renderTarget);

        Block1.Draw(renderTarget);
        Block2.Draw(renderTarget);

        SDL_RenderPresent(renderTarget);
    }
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderTarget);
    window = NULL;
    renderTarget = NULL;

    SDL_Quit();

    return 0;
}

1 个答案:

答案 0 :(得分:0)

您的代码存在的问题是每次调用Player.Collision都会覆盖“fall”变量。

Player.Collision(Block1); //this call calculates a falling value
Player.Collision(Block2); //...then this call overwrites falling with a new value

如此有效的代码只测试播放器是否与Block2发生冲突,因此忽略与Block1的冲突。

目前您的碰撞功能是:

bool Player::Collision(Block &p)
{
    if(PlayerPos.x + PlayerPos.w <= p.BlockPos.x || PlayerPos.x >= p.BlockPos.x + p.BlockPos.w ||
        PlayerPos.y + PlayerPos.h <= p.BlockPos.y || PlayerPos.y >= p.BlockPos.y + p.BlockPos.h)
    {
        falling = 0;
        return true;
    }
    else
        falling = 1;
        return false;
}

首先,你的“回归假”;实际上并不是其他的一部分,因为你没有{}。在这个特殊的情况下,它没有区别,因为其他人退出然后返回发生,但你的缩进会建议你期望“返回错误;”要作为else块的一部分执行的行,所以你应该把:

else
{
    falling = 1;
    return false;
}

接下来你要说的是你是否已经检测到碰撞(例如,使用Block1)然后不要设置为1,为此添加一个if语句。

else
{
    if(falling != 0) //if we haven't already detected a collision this frame
    {
        falling = 1;
    }
    return false;
}

然而,你需要在每帧开始时设置回落到1,否则如果在一帧上检测到碰撞,那么即使它们没有与一个块碰撞,玩家也不会落在后续帧上。 / p>

作为旁注,如果下降== 0,你的Player.Update代码会修改玩家的y位置,这似乎是反直觉的,因为通常0为假,1为真,因此你似乎在说如果不下降然后更新y ,如果下降更新y应该是在哪里。我个人会使用bool而不是int来保存掉落的值,然后说如果(下降)更新y,这将使你的代码更清晰。