SDL基础使用05(事件系统event)

文章详细介绍了如何使用SDL库中的事件系统来控制图片的平铺和前景图的移动,包括响应键盘和鼠标事件调整图片位置和大小。
摘要由CSDN通过智能技术生成

 SDL事件实现背景平铺、前景图移动

#include <iostream>
#include <string>
// SDL_Event事件使用 sdl_event.h
extern "C"
{
#include <SDL.h>
#include <SDL_image.h>
}
#pragma comment(lib, "SDL2.lib")


// 窗口宽度
#define SCREEN_WIDTH  1600
#define SCREEN_HEIGHT  900

// 全局窗口和渲染器
SDL_Window   *window   = nullptr;
SDL_Renderer *renderer = nullptr;

// 加载图片(返回纹理指针)
SDL_Texture* LoadImage(std::string file)
{
	SDL_Texture* tex = nullptr;
	tex = IMG_LoadTexture(renderer, file.c_str());			// 加载图片到纹理
	if (tex == nullptr)
		throw std::runtime_error("Load image failed" + file + IMG_GetError());
	return tex;
}

// 拷贝纹理到渲染器
void copyTextureToRender(int x, int y, SDL_Texture *tex, SDL_Renderer *rend)
{
	SDL_Rect pos;			// srcRect
	pos.x = x;
	pos.y = y;
	SDL_QueryTexture(tex, NULL, NULL, &pos.w, &pos.h);			// 查询纹理的宽高
	SDL_RenderCopy(rend, tex, NULL, &pos);						// 拷贝纹理到渲染器
}

#undef main
int main(int argc, char** argv)
{
	// 1. 初始化SDL
	if (::SDL_Init(SDL_INIT_EVERYTHING) == -1)
	{
		std::cout << SDL_GetError() << std::endl;
		return 1;
	}

	// 2. 创建窗口
	window = ::SDL_CreateWindow("Event Demo",
		SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
		SCREEN_WIDTH, SCREEN_HEIGHT, 
		SDL_WINDOW_SHOWN);
	if (window == nullptr)
	{
		std::cout << SDL_GetError() << std::endl;
		return 2;
	}

	// 3. 基于窗口创建渲染器
	renderer = ::SDL_CreateRenderer(window, -1,
		SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	if (renderer == nullptr)
	{
		std::cout << SDL_GetError() << std::endl;
		return 3;
	}

	// 4. 创建背景和前景纹理			::IMG_LoadTexture
	SDL_Texture *background = nullptr, *image = nullptr;
	try {
		background = LoadImage("./bk.jpg");
		image = LoadImage("./longong.jpg");
	}
	catch (const std::runtime_error &e) {
		std::cout << e.what() << std::endl;
		return 4;
	}

	bool quit = false;			// 是否退出循环
	SDL_Event e;				// SDL事件
	int iW, iH, x, y;			// x y为前景图pos, iW iH 为前景图宽高
	int dx = 0, dy = 0;			// 前景图偏移pos
	// 主循环(CPU高占用)
	while (!quit)
	{
		// 轮询事件栈e
		while (SDL_PollEvent(&e))		// 循环从事件队列中获取事件
		{
			if (e.type == SDL_QUIT)		// 退出事件
				quit = true;

			if (e.type == SDL_KEYDOWN)	// 键盘事件
			{
				if (e.key.keysym.sym == SDLK_LEFT)	
				{
					dx -= 10;
					printf("SDLK_LEFT...");
				}
				else if (e.key.keysym.sym == SDLK_RIGHT)
				{
					printf("SDLK_RIGHT...");
					dx += 10;

				}
				else if (e.key.keysym.sym == SDLK_UP)
				{
					printf("SDLK_UP...");
					dy -= 10;
				}
				else if (e.key.keysym.sym == SDLK_DOWN)
				{
					printf("SDLK_DOWN...");
					dy += 10;
				}

			}

			if (e.type == SDL_MOUSEBUTTONDOWN) 			// 用户点击鼠标
				quit = true;

			// 清空渲染器
			SDL_RenderClear(renderer);

			// 在渲染器内平铺背景
			int bW, bH;
			SDL_QueryTexture(background, NULL, NULL, &bW, &bH);		// 查询背景纹理宽高
			for (int y = 0; y <= SCREEN_HEIGHT; y += bH)			// (0, 0) (bW, bH)  防止背景图太小,循环平铺 		
			for (int x = 0; x <= SCREEN_WIDTH; x += bW)				
				copyTextureToRender(x, y, background, renderer);	


			// 在渲染器中央放置前景			
			SDL_QueryTexture(image, NULL, NULL, &iW, &iH);			// 查询前景纹理宽高
			x = SCREEN_WIDTH / 2 - iW / 2 + dx;
			y = SCREEN_HEIGHT / 2 - iH / 2 + dy;
			copyTextureToRender(x, y, image, renderer);

			SDL_RenderPresent(renderer);							// 刷新渲染器显示
		}
	}

	// 释放资源
	if (background)
	{
		SDL_DestroyTexture(background);
	}
	if (image)
	{
		SDL_DestroyTexture(image);
	}
	if (renderer)
	{
		SDL_DestroyRenderer(renderer);
	}
	if (window)
	{
		SDL_DestroyWindow(window);
	}
	SDL_Quit();

	return 0;
}

 使用SDL事件实现图片的移动、缩放

#include <iostream>

extern "C"
{
	#include <SDL.h>
}

#undef main
int main()
{
	// 1. 初始化SDL
	SDL_Init(SDL_INIT_EVERYTHING);

	// 2. 创建窗口
	SDL_Window* win = SDL_CreateWindow("yx3sxmeng", 
		SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
		800, 600, 
		SDL_WINDOW_SHOWN);

	// 3. 创建渲染器
	SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);

	// 4. 将图片加载到surface
	SDL_Surface* surface = SDL_LoadBMP("./Panda.bmp");
	
	// 5. 根据surface创建纹理
	SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);


	// 6. SDL事件循环机制 
	bool quit = false;
	SDL_Event ev;						// SDL 事件
	SDL_Rect rect = { 0, 0, 800, 600 };	// 图片位置大小(x,y, w,h);
	int sx = 0, sy = 0;					// 保存经过事件处理后的图片的位置
	while (!quit)
	{
		while (SDL_PollEvent(&ev))		// 从循环队列中获取事件
		{
			switch (ev.type)
			{
			case SDL_QUIT:
				quit = true;
				break;
			case SDL_MOUSEBUTTONDOWN:			// 鼠标按下(记录鼠标按下位置到图片x y的距离)
				sx = ev.button.x + rect.x;
				sy = ev.button.y + rect.y;
				break;
			case SDL_MOUSEMOTION:							// 鼠标左键按下移动
				if (ev.motion.state & SDL_BUTTON_LMASK)
				{
					rect.x = ev.motion.x - sx;				// 计算图片应该绘制的xy位置(通过鼠标按下记录的sx xy)
					rect.y = ev.motion.y - sy;
				}
				break;
			case SDL_KEYDOWN:
				if (ev.key.keysym.sym == SDLK_LEFT)		// 向左移动
				{
					rect.x -= 10;					
					printf("SDLK_LEFT...");
				}
				else if (ev.key.keysym.sym == SDLK_RIGHT)		// 向右移动
				{		
					rect.x += 10;
					printf("SDLK_RIGHT...");
				}
				else if (ev.key.keysym.sym == SDLK_UP)			// 放大
				{
					rect.w += 10;
					rect.h += 10;
					printf("SDLK_UP...");
				}
				else if (ev.key.keysym.sym == SDLK_DOWN)		// 缩小
				{
					rect.w -= 10;
					rect.h -= 10;
					printf("SDLK_DOWN...");
				}
				printf("scancode=%d\n", ev.key.keysym.scancode);
				break;
			case SDL_MOUSEWHEEL:
				if (ev.wheel.y > 0)		// 放大
				{
					rect.h *= 1.1;
					rect.w *= 1.1;
				}
				if (ev.wheel.y < 0)		// 缩小
				{
					rect.w /= 1.1;
					rect.h /= 1.1;
				}
				break;
			}
		}
		// 7. 渲染三部曲
		SDL_RenderClear(renderer);
		SDL_RenderCopy(renderer, texture, NULL, &rect);
		SDL_RenderPresent(renderer);
		SDL_Delay(16);
	}

	// 8. 释放资源 退出
	SDL_DestroyTexture(texture);
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(win);

	SDL_Quit();
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

石小浪♪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值