SDL2 中光追玩家

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

我使用 SDL2 和 C++ 创建了一个在 2D 游戏中跟随玩家的摄像头系统。我插入了一个具有光效果的纹理,该纹理从透明到不透明的黑色呈放射状渐变。下面是完整的代码,以使说明更清楚:

#include <SDL.h>
#include <SDL_image.h>

#include <iostream>

SDL_Texture* LoadTexture(std::string filePath, SDL_Renderer* renderTarget)
{
    SDL_Texture* texture = nullptr;
    SDL_Surface* surface = IMG_Load(filePath.c_str());
    if (surface == nullptr)
        std::cout << "Error load texture and create surface" << std::endl;
    else
    {
        texture = SDL_CreateTextureFromSurface(renderTarget, surface);
        if (texture == nullptr)
            std::cout << "Error create texture" << std::endl;
    }

    SDL_FreeSurface(surface);

    return texture;
}

//The rectangle that will move around on the screen
class Player
{
public:
    //The dimensions of the rectangle: 20x20 pixel
    static const int PLAYER_WIDTH = 20;
    static const int PLAYER_HEIGHT = 20;

    //Maximum axis velocity of the player
    static const int PLAYER_VEL = 10;

public:
    //Initializes the variables
    Player();

    //Takes key presses and adjusts the player's velocity
    void handleEvent(SDL_Event& e);

    //Moves the player
    void move();

    //Renders texture at given point
    void render(SDL_Renderer* m_render, int camX, int camY, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);

    //Position accessors
    int getPosX();
    int getPosY();
    void setPosX(int x);
    void setPosY(int y);

    void setTexture(SDL_Texture* texture);

    //Gets image dimensions
    int getWidth();
    int getHeight();

private:
    //Shows the player on the screen relative to the camera
    void renderRect(SDL_Renderer* render, int camX, int camY);

private:
    //The X and Y offsets of the player
    int mPosX, mPosY;

    //The velocity of the player
    int mVelX, mVelY;

    //The dimensions of the map
    const int MAP_WIDTH = 4096;
    const int MAP_HEIGHT = 1408;

    // rectangle player
    SDL_Rect rectPlayer = { 0, 0, PLAYER_WIDTH , PLAYER_HEIGHT };

    //The actual hardware texture
    SDL_Texture* mTexture;

    //Image dimensions
    int mWidth;
    int mHeight;
};

Player::Player()
{
    //Initialize the offsets
    mPosX = 0;
    mPosY = 0;

    //Initialize the velocity
    mVelX = 0;
    mVelY = 0;

    //Initialize
    mTexture = NULL;
    mWidth = 0;
    mHeight = 0;
}

void Player::handleEvent(SDL_Event& e)
{
    //If a key was pressed
    if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
    {
        //Adjust the velocity
        switch (e.key.keysym.sym)
        {
        case SDLK_UP: mVelY -= PLAYER_VEL; break;
        case SDLK_DOWN: mVelY += PLAYER_VEL; break;
        case SDLK_LEFT: mVelX -= PLAYER_VEL; break;
        case SDLK_RIGHT: mVelX += PLAYER_VEL; break;
        }
    }
    //If a key was released
    else if (e.type == SDL_KEYUP && e.key.repeat == 0)
    {
        //Adjust the velocity
        switch (e.key.keysym.sym)
        {
        case SDLK_UP: mVelY += PLAYER_VEL; break;
        case SDLK_DOWN: mVelY -= PLAYER_VEL; break;
        case SDLK_LEFT: mVelX += PLAYER_VEL; break;
        case SDLK_RIGHT: mVelX -= PLAYER_VEL; break;
        }
    }
}

void Player::move()
{
    //Move the player left or right
    mPosX += mVelX;

    //If the player went too far to the left or right
    if ((mPosX < 0) || (mPosX + PLAYER_WIDTH > MAP_WIDTH))
    {
        //Move back
        mPosX -= mVelX;
    }

    //Move the player up or down
    mPosY += mVelY;

    //If the player went too far up or down
    if ((mPosY < 0) || (mPosY + PLAYER_HEIGHT > MAP_HEIGHT))
    {
        //Move back
        mPosY -= mVelY;
    }
}

void Player::renderRect(SDL_Renderer* render, int camX, int camY)
{
    SDL_SetRenderDrawColor(render, 20, 220, 220, 255);
    SDL_RenderDrawRect(render, &rectPlayer);
    
    //fill up rectangle with color
    //SDL_RenderFillRect(render, &rectPlayer);
    
    //Show the player relative to the camera
    rectPlayer.x = mPosX - camX;
    rectPlayer.y = mPosY - camY;
}

void Player::render(SDL_Renderer* m_render, int camX, int camY, double angle, SDL_Point* center, SDL_RendererFlip flip)
{
    renderRect(m_render, camX, camY);

    // find texture dimension
    int widthTexture = 0;
    int heightTexture = 0;
    SDL_QueryTexture(mTexture, NULL, NULL, &widthTexture, &heightTexture);

    SDL_Rect clipRect = { 0, 0, widthTexture, heightTexture };

    //Render to screen
    SDL_RenderCopyEx(m_render, mTexture, &clipRect, &rectPlayer, angle, center, flip);
}

int Player::getPosX()
{
    return mPosX;
}

int Player::getPosY()
{
    return mPosY;
}

void Player::setPosX(int x)
{
    mPosX = x;
}

void Player::setPosY(int y)
{
    mPosY = y;
}

void Player::setTexture(SDL_Texture* texture)
{
    mTexture = texture;
}

int Player::getWidth()
{
    return mWidth;
}

int Player::getHeight()
{
    return mHeight;
}

int main(int argc, char** argv)
{
    // Initializing and loading variables
    SDL_Window* window = nullptr;
    SDL_Renderer* render = nullptr;
    int currentTime = 0;
    int prevTime = 0;
    float delta = 0.0f;
    int widthWindowCamera = 640;
    int heightWindowCamera = 480;
    SDL_Rect cameraRect = { 0, 0, widthWindowCamera, heightWindowCamera };
    SDL_Rect mapRect = { 0, 0, 0, 0 };
    int widthMap = 0;
    int heightMap = 0;
    
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::cout << "Video Initialization Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    //int data = 10;

    window = SDL_CreateWindow("SDL2 Light player", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, widthWindowCamera, heightWindowCamera, SDL_WINDOW_SHOWN);
    if (window == nullptr)
    {
        std::cout << "Window creation error: " << SDL_GetError() << std::endl;
        return 1;
    }

    render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    // load map
    SDL_Texture* texture = LoadTexture("world.png", render);
    if (texture == nullptr)
    {
        std::cout << "Error texture 'world' not create" << std::endl;
        return 1;
    }

    // find map dimension
    SDL_QueryTexture(texture, NULL, NULL, &widthMap, &heightMap);
    mapRect.w = widthMap;
    mapRect.h = heightMap;

    bool isRunning = true;
    SDL_Event ev;
    int xCenterWindow = widthWindowCamera / 2;
    int yCenterWindow = heightWindowCamera / 2;

    // create player: rectangle
    Player player;
    player.setPosX(mapRect.w/2);
    player.setPosY(mapRect.h / 2);
    float moveSpeed = 80.0f;
    player.setTexture(LoadTexture("player.png", render));

    // create light mask: rectangle
    SDL_Texture* lightMask = LoadTexture("maschera_luce.png", render);
    int widthLight = 0;
    int heightLight = 0;
    SDL_QueryTexture(lightMask, NULL, NULL, &widthLight, &heightLight);
    SDL_Rect rectLight = { 0, 0, widthLight, heightLight };

    while (isRunning)
    {
        prevTime = currentTime;
        currentTime = SDL_GetTicks();  // ms
        delta = (currentTime - prevTime) / 1000.0f;  // s
        while (SDL_PollEvent(&ev) != 0)
        {
            // Getting the events
            if (ev.type == SDL_QUIT)
                isRunning = false;

            //Handle input for the player
            player.handleEvent(ev);
        }

        // update player: move the player
        player.move();

        //Center the camera over the player
        cameraRect.x = (player.getPosX() + Player::PLAYER_WIDTH / 2) - widthWindowCamera / 2;
        cameraRect.y = (player.getPosY() + Player::PLAYER_HEIGHT / 2) - heightWindowCamera / 2;

        //Keep the camera in bounds
        if (cameraRect.x < 0)
        {
            cameraRect.x = 0;
        }
        if (cameraRect.y < 0)
        {
            cameraRect.y = 0;
        }
        if (cameraRect.x >= widthMap - cameraRect.w)
        {
            cameraRect.x = widthMap - cameraRect.w;
        }
        if (cameraRect.y >= heightMap - cameraRect.h)
        {
            cameraRect.y = heightMap - cameraRect.h;
        }
        
        //Clear screen
        SDL_SetRenderDrawColor(render, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(render);

        // render portion map (camera dimension)
        SDL_RenderCopy(render, texture, &cameraRect, nullptr);

        // render player: rectangle & texture
        player.render(render, cameraRect.x, cameraRect.y);

        // render light mask over player
        SDL_RenderCopy(render, lightMask, &rectLight, &rectLight);

        // visualizza tutto nell'area di rendering
        SDL_RenderPresent(render);
    }

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(render);
    SDL_DestroyTexture(texture);

    texture = nullptr;
    window = nullptr;
    render = nullptr;

    IMG_Quit();
    SDL_Quit();

    return 0;
}

在代码的当前状态下,玩家沿着地图移动,径向光跟随他。现在我想做的是,如果玩家超出窗口中间(当相机到达地图的末端时)并朝地图的末端移动(例如朝最右侧),光线也会移动与玩家一起,而不是像现在那样停止并且玩家从光束中消失。我看看是否可以附上这两种情况的图片。

before

after

我尝试的是我在请求中输入的代码。我不知道如何继续才能达到预期的效果。你能帮助我吗 ?我必须写什么才能使播放器上的相机到达地图边缘,始终将播放器放置在相机的中心?

已解决:

    #include <SDL.h>
    #include <SDL_image.h>

    #include <iostream>

    SDL_Texture* LoadTexture(std::string filePath, SDL_Renderer* renderTarget)
   {
       SDL_Texture* texture = nullptr;
       SDL_Surface* surface = IMG_Load(filePath.c_str());
       if (surface == nullptr)
           std::cout << "Error load texture and create surface" << std::endl;
       else
       {
        texture = SDL_CreateTextureFromSurface(renderTarget, surface);
        if (texture == nullptr)
            std::cout << "Error create texture" << std::endl;
       }

       SDL_FreeSurface(surface);

       return texture;
   }

//The rectangle that will move around on the screen
class Player
{
public:
    //The dimensions of the rectangle: 20x20 pixel
    static const int PLAYER_WIDTH = 20;
    static const int PLAYER_HEIGHT = 20;

    //Maximum axis velocity of the player
    static const int PLAYER_VEL = 10;

public:
    //Initializes the variables
    Player(SDL_Rect* rect, const int wMap, const int hMap);

    //Takes key presses and adjusts the player's velocity
    void handleEvent(SDL_Event& e);

    //Moves the player
    void move();

    //Renders texture at given point
    void render(SDL_Renderer* m_render, int camX, int camY, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);

    SDL_Rect* getRectPlayer();

    //Position accessors
    int getPosX();
    int getPosY();
    void setPosX(int x);
    void setPosY(int y);

    void setTexture(SDL_Texture* texture);

    //Gets image dimensions
    int getWidth();
    int getHeight();

private:
    //Shows the player on the screen relative to the camera
    void renderRect(SDL_Renderer* render, int camX, int camY);

private:
    //The X and Y offsets of the player
    int mPosX, mPosY;

    //The velocity of the player
    int mVelX, mVelY;

    //The dimensions of the map
    int map_width;
    int map_height;

    //The rectangle light mask
    SDL_Rect* rectLightPlayer = new SDL_Rect{ 0, 0, 0, 0 };

    // rectangle player
    SDL_Rect rectPlayer = { 0, 0, PLAYER_WIDTH , PLAYER_HEIGHT };

    //The actual hardware texture
    SDL_Texture* mTexture;

    //Image dimensions
    int mWidth;
    int mHeight;
};

Player::Player(SDL_Rect* rect, const int wMap, const int hMap)
{
    //Map dimension
    map_width = wMap;
    map_height = hMap;

    //Rectangle light
    rectLightPlayer = rect;

    //Initialize the offsets
    mPosX = 0;
    mPosY = 0;

    //Initialize the velocity
    mVelX = 0;
    mVelY = 0;

    //Initialize
    mTexture = NULL;
    mWidth = 0;
    mHeight = 0;
}

void Player::handleEvent(SDL_Event& e)
{
    //If a key was pressed
    if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
    {
        //Adjust the velocity
        switch (e.key.keysym.sym)
        {
        case SDLK_UP: mVelY -= PLAYER_VEL; break;
        case SDLK_DOWN: mVelY += PLAYER_VEL; break;
        case SDLK_LEFT: mVelX -= PLAYER_VEL; break;
        case SDLK_RIGHT: mVelX += PLAYER_VEL; break;
        }
    }
    //If a key was released
    else if (e.type == SDL_KEYUP && e.key.repeat == 0)
    {
        //Adjust the velocity
        switch (e.key.keysym.sym)
        {
        case SDLK_UP: mVelY += PLAYER_VEL; break;
        case SDLK_DOWN: mVelY -= PLAYER_VEL; break;
        case SDLK_LEFT: mVelX += PLAYER_VEL; break;
        case SDLK_RIGHT: mVelX -= PLAYER_VEL; break;
        }
    }
}

void Player::move()
{
    //Move the player left or right
    mPosX += mVelX;

    //If the player went too far to the left or right
    if ((mPosX < 0) || (mPosX + PLAYER_WIDTH > map_width))
    {
        //Move back
        mPosX -= mVelX;
    }

    //Move the player up or down
    mPosY += mVelY;

    //If the player went too far up or down
    if ((mPosY < 0) || (mPosY + PLAYER_HEIGHT > map_height))
    {
        //Move back
        mPosY -= mVelY;
    }
}

void Player::renderRect(SDL_Renderer* render, int camX, int camY)
{
    SDL_SetRenderDrawColor(render, 20, 220, 220, 255);
    SDL_RenderDrawRect(render, &rectPlayer);
    
    //fill up rectangle with color
    //SDL_RenderFillRect(render, &rectPlayer);
    
    //Show the collision box of the player relative to the camera
    rectPlayer.x = mPosX - camX;
    rectPlayer.y = mPosY - camY;
}

void Player::render(SDL_Renderer* m_render, int camX, int camY, double angle, SDL_Point* center, SDL_RendererFlip flip)
{
    renderRect(m_render, camX, camY);

    // find texture dimension
    int widthTexture = 0;
    int heightTexture = 0;
    SDL_QueryTexture(mTexture, NULL, NULL, &widthTexture, &heightTexture);

    SDL_Rect clipRect = { 0, 0, widthTexture, heightTexture };

    //Render to screen
    SDL_RenderCopyEx(m_render, mTexture, &clipRect, &rectPlayer, angle, center, flip);
}

SDL_Rect* Player::getRectPlayer()
{
    return &rectPlayer;
}

int Player::getPosX()
{
    return mPosX;
}

int Player::getPosY()
{
    return mPosY;
}

void Player::setPosX(int x)
{
    mPosX = x;
}

void Player::setPosY(int y)
{
    mPosY = y;
}

void Player::setTexture(SDL_Texture* texture)
{
    mTexture = texture;
}

int Player::getWidth()
{
    return mWidth;
}

int Player::getHeight()
{
    return mHeight;
}

int main(int argc, char** argv)
{
    // Initializing and loading variables
    SDL_Window* window = nullptr;
    SDL_Renderer* render = nullptr;
    int currentTime = 0;
    int prevTime = 0;
    float delta = 0.0f;
    int widthWindowCamera = 640;
    int heightWindowCamera = 480;
    SDL_Rect cameraRect = { 0, 0, widthWindowCamera, heightWindowCamera };
    SDL_Rect mapRect = { 0, 0, 0, 0 };
    int widthMap = 0;
    int heightMap = 0;
    
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::cout << "Video Initialization Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    window = SDL_CreateWindow("SDL2 Light player", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, widthWindowCamera, heightWindowCamera, SDL_WINDOW_SHOWN);
    if (window == nullptr)
    {
        std::cout << "Window creation error: " << SDL_GetError() << std::endl;
        return 1;
    }

    render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    // load map
    SDL_Texture* texture = LoadTexture("world.png", render);
    if (texture == nullptr)
    {
        std::cout << "Error texture 'world' not create" << std::endl;
        return 1;
    }

    // find map dimension
    SDL_QueryTexture(texture, NULL, NULL, &widthMap, &heightMap);
    mapRect.w = widthMap;
    mapRect.h = heightMap;

    bool isRunning = true;
    SDL_Event ev;
    int xCenterWindow = widthWindowCamera / 2;
    int yCenterWindow = heightWindowCamera / 2;

    // create light mask: rectangle
    SDL_Texture* lightMask = LoadTexture("maschera_luce.png", render);
    //SDL_SetTextureBlendMode(lightMask, SDL_BLENDMODE_ADD);
    SDL_SetRenderDrawColor(render, 0x36, 0x45, 0x9b, 0xff);  // 0, 0, 255, 255);  // 0x36, 0x45, 0x9b, 0xff);
    int widthLight = 0;
    int heightLight = 0;
    SDL_QueryTexture(lightMask, NULL, NULL, &widthLight, &heightLight);
    SDL_Rect* srcRectLight = new SDL_Rect{ 0, 0, widthLight, heightLight };
    SDL_Rect* dstRectLight = new SDL_Rect{ 0, 0, widthLight, heightLight };

    // create player: rectangle and light
    Player player(dstRectLight, 4096, 1408);
    player.setPosX(mapRect.w / 2);
    player.setPosY(mapRect.h / 2);
    float moveSpeed = 80.0f;
    player.setTexture(LoadTexture("player.png", render));

    while (isRunning)
    {
        prevTime = currentTime;
        currentTime = SDL_GetTicks();  // ms
        delta = (currentTime - prevTime) / 1000.0f;  // s
        while (SDL_PollEvent(&ev) != 0)
        {
            // Getting the events
            if (ev.type == SDL_QUIT) isRunning = false;
            if(ev.key.keysym.sym == SDLK_ESCAPE) isRunning = false;

            //Handle input for the player
            player.handleEvent(ev);
        }

        // update player: move the player
        player.move();

        // update light mask
        dstRectLight->x = player.getRectPlayer()->x - (dstRectLight->w / 2);
        dstRectLight->y = player.getRectPlayer()->y - (dstRectLight->h / 2) + 20;

        //Center the camera over the player
        cameraRect.x = (player.getPosX() + Player::PLAYER_WIDTH / 2) - widthWindowCamera / 2;
        cameraRect.y = (player.getPosY() + Player::PLAYER_HEIGHT / 2) - heightWindowCamera / 2;

        //Keep the camera in bounds
        if (cameraRect.x < 0)
        {
            cameraRect.x = 0;
        }
        if (cameraRect.y < 0)
        {
            cameraRect.y = 0;
        }
        if (cameraRect.x >= widthMap - cameraRect.w)
        {
            cameraRect.x = widthMap - cameraRect.w;
        }
        if (cameraRect.y >= heightMap - cameraRect.h)
        {
            cameraRect.y = heightMap - cameraRect.h;
        }
        
        //Clear screen
        SDL_SetRenderDrawColor(render, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(render);

        // render portion map (camera dimension)
        SDL_RenderCopy(render, texture, &cameraRect, nullptr);

        // render player: rectangle & texture
        player.render(render, cameraRect.x, cameraRect.y);

        // render light mask over player
        SDL_RenderCopy(render, lightMask, srcRectLight, dstRectLight);

        // view area rendering
        SDL_RenderPresent(render);
    }

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(render);
    SDL_DestroyTexture(texture);

    texture = nullptr;
    window = nullptr;
    render = nullptr;

    IMG_Quit();
    SDL_Quit();

    return 0;
}

正确

c++ windows c++17 sdl-2
1个回答
0
投票

代码正确:

    #include <SDL.h>
    #include <SDL_image.h>

    #include <iostream>

    SDL_Texture* LoadTexture(std::string filePath, SDL_Renderer* renderTarget)
   {
       SDL_Texture* texture = nullptr;
       SDL_Surface* surface = IMG_Load(filePath.c_str());
       if (surface == nullptr)
           std::cout << "Error load texture and create surface" << std::endl;
       else
       {
        texture = SDL_CreateTextureFromSurface(renderTarget, surface);
        if (texture == nullptr)
            std::cout << "Error create texture" << std::endl;
       }

       SDL_FreeSurface(surface);

       return texture;
   }

//The rectangle that will move around on the screen
class Player
{
public:
    //The dimensions of the rectangle: 20x20 pixel
    static const int PLAYER_WIDTH = 20;
    static const int PLAYER_HEIGHT = 20;

    //Maximum axis velocity of the player
    static const int PLAYER_VEL = 10;

public:
    //Initializes the variables
    Player(SDL_Rect* rect, const int wMap, const int hMap);

    //Takes key presses and adjusts the player's velocity
    void handleEvent(SDL_Event& e);

    //Moves the player
    void move();

    //Renders texture at given point
    void render(SDL_Renderer* m_render, int camX, int camY, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);

    SDL_Rect* getRectPlayer();

    //Position accessors
    int getPosX();
    int getPosY();
    void setPosX(int x);
    void setPosY(int y);

    void setTexture(SDL_Texture* texture);

    //Gets image dimensions
    int getWidth();
    int getHeight();

private:
    //Shows the player on the screen relative to the camera
    void renderRect(SDL_Renderer* render, int camX, int camY);

private:
    //The X and Y offsets of the player
    int mPosX, mPosY;

    //The velocity of the player
    int mVelX, mVelY;

    //The dimensions of the map
    int map_width;
    int map_height;

    //The rectangle light mask
    SDL_Rect* rectLightPlayer = new SDL_Rect{ 0, 0, 0, 0 };

    // rectangle player
    SDL_Rect rectPlayer = { 0, 0, PLAYER_WIDTH , PLAYER_HEIGHT };

    //The actual hardware texture
    SDL_Texture* mTexture;

    //Image dimensions
    int mWidth;
    int mHeight;
};

Player::Player(SDL_Rect* rect, const int wMap, const int hMap)
{
    //Map dimension
    map_width = wMap;
    map_height = hMap;

    //Rectangle light
    rectLightPlayer = rect;

    //Initialize the offsets
    mPosX = 0;
    mPosY = 0;

    //Initialize the velocity
    mVelX = 0;
    mVelY = 0;

    //Initialize
    mTexture = NULL;
    mWidth = 0;
    mHeight = 0;
}

void Player::handleEvent(SDL_Event& e)
{
    //If a key was pressed
    if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
    {
        //Adjust the velocity
        switch (e.key.keysym.sym)
        {
        case SDLK_UP: mVelY -= PLAYER_VEL; break;
        case SDLK_DOWN: mVelY += PLAYER_VEL; break;
        case SDLK_LEFT: mVelX -= PLAYER_VEL; break;
        case SDLK_RIGHT: mVelX += PLAYER_VEL; break;
        }
    }
    //If a key was released
    else if (e.type == SDL_KEYUP && e.key.repeat == 0)
    {
        //Adjust the velocity
        switch (e.key.keysym.sym)
        {
        case SDLK_UP: mVelY += PLAYER_VEL; break;
        case SDLK_DOWN: mVelY -= PLAYER_VEL; break;
        case SDLK_LEFT: mVelX += PLAYER_VEL; break;
        case SDLK_RIGHT: mVelX -= PLAYER_VEL; break;
        }
    }
}

void Player::move()
{
    //Move the player left or right
    mPosX += mVelX;

    //If the player went too far to the left or right
    if ((mPosX < 0) || (mPosX + PLAYER_WIDTH > map_width))
    {
        //Move back
        mPosX -= mVelX;
    }

    //Move the player up or down
    mPosY += mVelY;

    //If the player went too far up or down
    if ((mPosY < 0) || (mPosY + PLAYER_HEIGHT > map_height))
    {
        //Move back
        mPosY -= mVelY;
    }
}

void Player::renderRect(SDL_Renderer* render, int camX, int camY)
{
    SDL_SetRenderDrawColor(render, 20, 220, 220, 255);
    SDL_RenderDrawRect(render, &rectPlayer);
    
    //fill up rectangle with color
    //SDL_RenderFillRect(render, &rectPlayer);
    
    //Show the collision box of the player relative to the camera
    rectPlayer.x = mPosX - camX;
    rectPlayer.y = mPosY - camY;
}

void Player::render(SDL_Renderer* m_render, int camX, int camY, double angle, SDL_Point* center, SDL_RendererFlip flip)
{
    renderRect(m_render, camX, camY);

    // find texture dimension
    int widthTexture = 0;
    int heightTexture = 0;
    SDL_QueryTexture(mTexture, NULL, NULL, &widthTexture, &heightTexture);

    SDL_Rect clipRect = { 0, 0, widthTexture, heightTexture };

    //Render to screen
    SDL_RenderCopyEx(m_render, mTexture, &clipRect, &rectPlayer, angle, center, flip);
}

SDL_Rect* Player::getRectPlayer()
{
    return &rectPlayer;
}

int Player::getPosX()
{
    return mPosX;
}

int Player::getPosY()
{
    return mPosY;
}

void Player::setPosX(int x)
{
    mPosX = x;
}

void Player::setPosY(int y)
{
    mPosY = y;
}

void Player::setTexture(SDL_Texture* texture)
{
    mTexture = texture;
}

int Player::getWidth()
{
    return mWidth;
}

int Player::getHeight()
{
    return mHeight;
}

int main(int argc, char** argv)
{
    // Initializing and loading variables
    SDL_Window* window = nullptr;
    SDL_Renderer* render = nullptr;
    int currentTime = 0;
    int prevTime = 0;
    float delta = 0.0f;
    int widthWindowCamera = 640;
    int heightWindowCamera = 480;
    SDL_Rect cameraRect = { 0, 0, widthWindowCamera, heightWindowCamera };
    SDL_Rect mapRect = { 0, 0, 0, 0 };
    int widthMap = 0;
    int heightMap = 0;
    
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::cout << "Video Initialization Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    window = SDL_CreateWindow("SDL2 Light player", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, widthWindowCamera, heightWindowCamera, SDL_WINDOW_SHOWN);
    if (window == nullptr)
    {
        std::cout << "Window creation error: " << SDL_GetError() << std::endl;
        return 1;
    }

    render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    // load map
    SDL_Texture* texture = LoadTexture("world.png", render);
    if (texture == nullptr)
    {
        std::cout << "Error texture 'world' not create" << std::endl;
        return 1;
    }

    // find map dimension
    SDL_QueryTexture(texture, NULL, NULL, &widthMap, &heightMap);
    mapRect.w = widthMap;
    mapRect.h = heightMap;

    bool isRunning = true;
    SDL_Event ev;
    int xCenterWindow = widthWindowCamera / 2;
    int yCenterWindow = heightWindowCamera / 2;

    // create light mask: rectangle
    SDL_Texture* lightMask = LoadTexture("maschera_luce.png", render);
    //SDL_SetTextureBlendMode(lightMask, SDL_BLENDMODE_ADD);
    SDL_SetRenderDrawColor(render, 0x36, 0x45, 0x9b, 0xff);  // 0, 0, 255, 255);  // 0x36, 0x45, 0x9b, 0xff);
    int widthLight = 0;
    int heightLight = 0;
    SDL_QueryTexture(lightMask, NULL, NULL, &widthLight, &heightLight);
    SDL_Rect* srcRectLight = new SDL_Rect{ 0, 0, widthLight, heightLight };
    SDL_Rect* dstRectLight = new SDL_Rect{ 0, 0, widthLight, heightLight };

    // create player: rectangle and light
    Player player(dstRectLight, 4096, 1408);
    player.setPosX(mapRect.w / 2);
    player.setPosY(mapRect.h / 2);
    float moveSpeed = 80.0f;
    player.setTexture(LoadTexture("player.png", render));

    while (isRunning)
    {
        prevTime = currentTime;
        currentTime = SDL_GetTicks();  // ms
        delta = (currentTime - prevTime) / 1000.0f;  // s
        while (SDL_PollEvent(&ev) != 0)
        {
            // Getting the events
            if (ev.type == SDL_QUIT) isRunning = false;
            if(ev.key.keysym.sym == SDLK_ESCAPE) isRunning = false;

            //Handle input for the player
            player.handleEvent(ev);
        }

        // update player: move the player
        player.move();

        // update light mask
        dstRectLight->x = player.getRectPlayer()->x - (dstRectLight->w / 2);
        dstRectLight->y = player.getRectPlayer()->y - (dstRectLight->h / 2) + 20;

        //Center the camera over the player
        cameraRect.x = (player.getPosX() + Player::PLAYER_WIDTH / 2) - widthWindowCamera / 2;
        cameraRect.y = (player.getPosY() + Player::PLAYER_HEIGHT / 2) - heightWindowCamera / 2;

        //Keep the camera in bounds
        if (cameraRect.x < 0)
        {
            cameraRect.x = 0;
        }
        if (cameraRect.y < 0)
        {
            cameraRect.y = 0;
        }
        if (cameraRect.x >= widthMap - cameraRect.w)
        {
            cameraRect.x = widthMap - cameraRect.w;
        }
        if (cameraRect.y >= heightMap - cameraRect.h)
        {
            cameraRect.y = heightMap - cameraRect.h;
        }
        
        //Clear screen
        SDL_SetRenderDrawColor(render, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(render);

        // render portion map (camera dimension)
        SDL_RenderCopy(render, texture, &cameraRect, nullptr);

        // render player: rectangle & texture
        player.render(render, cameraRect.x, cameraRect.y);

        // render light mask over player
        SDL_RenderCopy(render, lightMask, srcRectLight, dstRectLight);

        // view area rendering
        SDL_RenderPresent(render);
    }

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(render);
    SDL_DestroyTexture(texture);

    texture = nullptr;
    window = nullptr;
    render = nullptr;

    IMG_Quit();
    SDL_Quit();

    return 0;
}

我重新创建了光照纹理,使其尺寸大于渲染窗口,这样即使玩家位于地图边缘,它也可以覆盖整个区域。透明圆圈始终位于纹理的中心。

© www.soinside.com 2019 - 2024. All rights reserved.