【SDL游戏编程入门第八卷】视口Viewport
一、前言
SDL2.0 还允许使用视口控制在屏幕上的渲染位置,我们可以使用视口来创建子屏幕。
有时,您只想为小地图之类的内容渲染屏幕的一部分。使用视口,您可以控制在屏幕上的渲染位置。
二、使用视口
// --- rendering -----------------------------------------------------------------------
// 设置渲染器绘制颜色(黑色)
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255);
// 清屏
SDL_RenderClear(gRenderer);
SDL_Rect topLeftViewport{ 0, 0, 256, 256 };
SDL_RenderSetViewport(gRenderer, &topLeftViewport);
// 最后一个参数为 nullptr,会填充所在的视口区域
SDL_RenderCopy(gRenderer, gTexture, nullptr, nullptr);
SDL_Rect topRightViewport{ SCREEN_WIDTH - 256, 0, 256, 256 };
SDL_RenderSetViewport(gRenderer, &topRightViewport);
// 最后一个参数为 nullptr,会填充所在的视口区域
SDL_RenderCopy(gRenderer, gTexture, nullptr, nullptr);
// 更新屏幕
SDL_RenderPresent(gRenderer);
这里使用 SDL_RenderSetViewport
设置渲染器视口大小
这里使用的之前的加载纹理函数,加载了一张纹理图片
本卷使用的纹理
三、示例代码
/* 此源代码版权归 AnnihilateSword (2022-*)所有,未经书面许可不得转载。*/
// 使用 SDL 和 iostream
#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
// 链接库
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_image.lib")
// 屏幕尺寸常量
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
bool Init(); // 启动 SDL 并创建窗口
bool LoadMedia(); // 加载媒体
SDL_Texture* LoadTexture(const char* path); // 加载纹理
void Close(); // 清理资源,关闭窗口以及SDL
SDL_Window* gWindow = nullptr; // 主窗口
SDL_Renderer* gRenderer = nullptr; // 主窗口渲染器
SDL_Texture* gTexture = nullptr; // 需要加载的纹理(表面)
int main(int argc, char* argv[]) // 必须要填写此参数,不然会出现链接错误
{
// 初始化 SDL
if (Init())
{
// 加载媒体资源
if (!LoadMedia())
std::cout << "[Error]: Failed to load media!" << std::endl;
// 窗口循环
SDL_Event e;
bool quit = false;
while (quit == false)
{
// 处理事件
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
quit = true;
}
// --- rendering -----------------------------------------------------------------------
// 设置渲染器绘制颜色(黑色)
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 255);
// 清屏
SDL_RenderClear(gRenderer);
SDL_Rect topLeftViewport{ 0, 0, 256, 256 };
SDL_RenderSetViewport(gRenderer, &topLeftViewport);
// 最后一个参数为 nullptr,会填充所在的视口区域
SDL_RenderCopy(gRenderer, gTexture, nullptr, nullptr);
SDL_Rect topRightViewport{ SCREEN_WIDTH - 256, 0, 256, 256 };
SDL_RenderSetViewport(gRenderer, &topRightViewport);
// 最后一个参数为 nullptr,会填充所在的视口区域
SDL_RenderCopy(gRenderer, gTexture, nullptr, nullptr);
// 更新屏幕
SDL_RenderPresent(gRenderer);
}
}
// 清理资源
Close();
return 0;
}
/**
* @brief 启动 SDL 并创建窗口
*/
bool Init()
{
// 初始化 SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << "[Error]: SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
else
{
// 设置纹理线性过滤
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
std::cout << "[Warning]: Linear texture filtering not enabled!" << std::endl;
// 创建窗口
gWindow = SDL_CreateWindow("HelloSDL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (!gWindow)
{
std::cout << "[Error]: Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
else
{
// 创建窗口渲染器
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED); // -1 初始化支持所请求标志的第一个
if (!gRenderer)
{
std::cout << "[Error]: Renderer could not bo created! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
else
{
// 初始化渲染器绘制颜色(蓝色),这次在主循环中设置
//SDL_SetRenderDrawColor(gRenderer, 51, 76, 204, 255);
// 初始化 PNG 加载
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
std::cout << "[Error]: SDL_image could not initialize! SDL_image Error: " << IMG_GetError() << std::endl;
return false;
}
}
}
}
return true;
}
/**
* @brief 加载媒体
*/
bool LoadMedia()
{
gTexture = LoadTexture(R"(res\textures\akl.jpg)");
if (!gTexture)
{
std::cout << "[Error]: Failed to load texture!" << std::endl;
return false;
}
return true;
}
/**
* @brief 加载纹理
* @param path:资源路径
*/
SDL_Texture* LoadTexture(const char* path)
{
// 使用这个一步到位
return IMG_LoadTexture(gRenderer, path);
}
/**
* @brief 清理资源,关闭窗口以及SDL
*/
void Close()
{
// 清理纹理资源
if (gTexture)
{
SDL_DestroyTexture(gTexture);
gTexture = nullptr;
}
// 销毁窗口渲染器
if (gRenderer)
{
SDL_DestroyRenderer(gRenderer);
gRenderer = nullptr;
}
// 销毁窗口
if (gWindow)
{
SDL_DestroyWindow(gWindow);
gWindow = nullptr;
}
// 退出 IMG 和 SDL
IMG_Quit();
SDL_Quit();
}
1. 运行结果
本节内容就到这里了,下卷会继续分享 SDL 的基本使用
The End.