SDL2 学习之路-04(扣色和剪辑渲染)

该代码示例展示了如何利用SDL库加载图片并设置颜色键为透明,然后创建纹理并在窗口中渲染。CTexture类封装了加载、释放纹理及渲染过程。通过SDL_SetColorKey函数实现特定像素值的透明化,通过SDL_RenderCopy进行剪辑渲染。在main函数中,初始化SDL环境,加载精灵表并分割为四个部分,然后循环渲染这些精灵。
摘要由CSDN通过智能技术生成

使用SDL_SetColorKey可以使某个像素值在blit中被视为透明,进而不渲染,使用SDL_MapRGB确定该像素。

SDL_SetColorKey的第一个参数为加载图片的表面,第二个参数是一个布尔值,最后一个参数是我们想要进行颜色键控的像素。

SDL_MapRGB的第一个参数是像素的格式(即表面的格式),最后三个变量是要映射的颜色的红色、绿色和蓝色分量。

SDL_Surface* loadedSurface=IMG_Load("colorkey.png");
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format,0,0xFF,0xFF));

渲染

SDL_Window* window=SDL_CreateWindow("title",500,500,640,480,SDL_WINDOW_SHOWN);
SDL_Renderer* renderer=SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);

SDL_Texture* newTexture=SDL_CreateTextureFromSurface(renderer,loadedSurface);
int W=loadedSurface->w;
int H=loadedSurface->h;
SDL_FreeSurface(loadedSurface);

SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(renderer);
SDL_Rect renderQuad = { 200, 200, W, H };
SDL_RenderCopy(renderer, newTexture, NULL, &renderQuad);

SDL_RenderPresent(renderer);

当要使用剪辑渲染时,将剪辑矩形传递到SDL_RenderCopy函数的第三个参数作为源矩形,同时设置目标矩形(SDL_RenderCopy函数的第四个参数)的大小与源矩形的大小相同。源矩形定义要渲染纹理的哪个部分。当源矩形为 NULL 时不剪辑。

SDL_Rect spriteClip { 0,0,100,100 };
renderQuad.w = spriteClip ->w;
renderQuad.h = spriteClip ->h;
SDL_RenderCopy(renderer, newTexture, spriteClip , &renderQuad);

 

 完整代码

 CTexture.h

#pragma once
#include<SDL.h>
#include<string>
class CTexture {
public:
	CTexture(SDL_Renderer*& renderer);
	~CTexture();
	bool loadFromFile(std::string path);
	void free();
	void render(int x, int y, SDL_Rect* clip);
	int getWidth();
	int getHeight();
private:
	SDL_Texture* m_texture;
	SDL_Renderer* m_renderer;


	int m_width;
	int m_height;
};

CTexture.cpp

#include "CTexture.h"
#include <SDL_image.h>

CTexture::CTexture(SDL_Renderer*& renderer):m_renderer{renderer}
{
	//Initialize
	m_texture = NULL;
	m_width = 0;
	m_height = 0;

	
}

CTexture::~CTexture()
{
	//Deallocate
	free();
}

bool CTexture::loadFromFile(std::string path)
{
	//Get rid of preexisting texture
	free();

	//The final texture
	SDL_Texture* newTexture = NULL;

	//Load image at specified path
	SDL_Surface* loadedSurface = IMG_Load(path.c_str());
	if (loadedSurface == NULL)
	{
		printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
	}
	else
	{
		//Color key image
		SDL_SetColorKey(loadedSurface, true, SDL_MapRGB(loadedSurface->format, 0x00, 0xFF, 0xFF));

		//Create texture from surface pixels
		newTexture = SDL_CreateTextureFromSurface(m_renderer, loadedSurface);
		if (newTexture == NULL)
		{
			printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
		}
		else
		{
			//Get image dimensions
			m_width = loadedSurface->w;
			m_height = loadedSurface->h;
		}

		//Get rid of old loaded surface
		SDL_FreeSurface(loadedSurface);
	}

	//Return success
	m_texture = newTexture;
	return m_texture != NULL;
}

void CTexture::free()
{
	//Free texture if it exists
	if (m_texture != NULL)
	{
		SDL_DestroyTexture(m_texture);
		m_texture = NULL;
		m_width = 0;
		m_height = 0;

	
	}
}

void CTexture::render(int x, int y, SDL_Rect* clip)
{
	//Set rendering space and render to screen
	SDL_Rect renderQuad = { x, y, getWidth(), getHeight() };
	//Set clip rendering dimensions
	if (clip != NULL)
	{
		renderQuad.w = clip->w;
		renderQuad.h = clip->h;
	}
	//Render to screen
	SDL_RenderCopy(m_renderer, m_texture, clip, &renderQuad);
}

int CTexture::getWidth()
{
	return m_width;
}

int CTexture::getHeight()
{
	return m_height;
}

main.cpp

#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
#include "CTexture.h"

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Scene sprites
SDL_Rect gSpriteClips[4];
CTexture* pSpriteSheetTexture =NULL;

bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		//Set texture filtering to linear
		if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
		{
			printf("Warning: Linear texture filtering not enabled!");
		}

		//Create window
		gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
		if (gWindow == NULL)
		{
			printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			//Create renderer for window
			gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
			if (gRenderer == NULL)
			{
				printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
				success = false;
			}
			else
			{
				//Initialize renderer color
				SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);

				pSpriteSheetTexture = new CTexture(gRenderer);
				//Initialize PNG loading
				int imgFlags = IMG_INIT_PNG;
				if (!(IMG_Init(imgFlags) & imgFlags))
				{
					printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
					success = false;
				}
			}
		}
	}

	return success;
}

bool loadMedia()
{
	//Loading success flag
	bool success = true;

	//Load background texture
	if (!pSpriteSheetTexture->loadFromFile("src/dots.png"))
	{
		printf("Failed to load background texture image!\n");
		success = false;
	}
	else {
		//Set top left sprite
		gSpriteClips[0] = { 0,0,100,100 };
		

		//Set top right sprite
		gSpriteClips[1] = { 100,0,100,100 };
		
		//Set bottom left sprite
		gSpriteClips[2] = { 0,100,100,100 };
		

		//Set bottom right sprite
		gSpriteClips[3] = { 100,100,100,100 };
		
	}
	return success;
}

void close()
{
	//Free loaded images
	pSpriteSheetTexture->free();

	//Destroy window	
	SDL_DestroyRenderer(gRenderer);
	SDL_DestroyWindow(gWindow);
	gWindow = NULL;
	gRenderer = NULL;

	
	pSpriteSheetTexture = NULL;
	//Quit SDL subsystems
	IMG_Quit();
	SDL_Quit();
}

int main(int argc, char* args[])
{
	//Start up SDL and create window
	if (!init())
	{
		printf("Failed to initialize!\n");
	}
	else
	{
		//Load media
		if (!loadMedia())
		{
			printf("Failed to load media!\n");
		}
		else
		{
			//Main loop flag
			bool quit = false;

			//Event handler
			SDL_Event e;

			//While application is running
			while (!quit)
			{
				//Handle events on queue
				while (SDL_PollEvent(&e) != 0)
				{
					//User requests quit
					if (e.type == SDL_QUIT)
					{
						quit = true;
					}
				}

				//Clear screen
				SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
				SDL_RenderClear(gRenderer);

				//Render top left sprite
				pSpriteSheetTexture->render(0, 0, &gSpriteClips[0]);

				//Render top right sprite
				pSpriteSheetTexture->render(SCREEN_WIDTH - gSpriteClips[1].w, 0, &gSpriteClips[1]);

				//Render bottom left sprite
				pSpriteSheetTexture->render(0, SCREEN_HEIGHT - gSpriteClips[2].h, &gSpriteClips[2]);

				//Render bottom right sprite
				pSpriteSheetTexture->render(SCREEN_WIDTH - gSpriteClips[3].w, SCREEN_HEIGHT - gSpriteClips[3].h, &gSpriteClips[3]);

			
				//Update screen
				SDL_RenderPresent(gRenderer);
			}
		}
	}

	//Free resources and close SDL
	close();

	return 0;
}

效果截图

  

 

 

参考文章:Lazy Foo' Productions - Clip Rendering and Sprite Sheets

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平面海螺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值