我使用 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;
}
在代码的当前状态下,玩家沿着地图移动,径向光跟随他。现在我想做的是,如果玩家超出窗口中间(当相机到达地图的末端时)并朝地图的末端移动(例如朝最右侧),光线也会移动与玩家一起,而不是像现在那样停止并且玩家从光束中消失。我看看是否可以附上这两种情况的图片。
我尝试的是我在请求中输入的代码。我不知道如何继续才能达到预期的效果。你能帮助我吗 ?我必须写什么才能使播放器上的相机到达地图边缘,始终将播放器放置在相机的中心?
已解决:
#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;
}
代码正确:
#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;
}
我重新创建了光照纹理,使其尺寸大于渲染窗口,这样即使玩家位于地图边缘,它也可以覆盖整个区域。透明圆圈始终位于纹理的中心。