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;
}