提问人:huabanlu 提问时间:10/13/2023 最后编辑:genpfaulthuabanlu 更新时间:10/13/2023 访问量:58
SDL_RenderCopyEx() 未按预期旋转
SDL_RenderCopyEx() did not rotate as expected
问:
我希望箭头围绕屏幕中心旋转。但实际效果是箭头在屏幕右侧的某个点旋转,对吧?让我觉得很奇怪!我对这个功能有错吗?
自 https://lazyfoo.net/tutorials/SDL/15_rotation_and_flipping/index.php 年正式示例以来的代码更改
/*This source code copyrighted by Lazy Foo' Productions 2004-2023
and may not be redistributed without written permission.*/
// Using SDL, SDL_image, standard IO, math, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
#include <cmath>
// Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
// Texture wrapper class
class LTexture
{
public:
// Initializes variables
LTexture();
// Deallocates memory
~LTexture();
// Loads image at specified path
bool loadFromFile(std::string path);
// Deallocates texture
void free();
// Set color modulation
void setColor(Uint8 red, Uint8 green, Uint8 blue);
// Set blending
void setBlendMode(SDL_BlendMode blending);
// Set alpha modulation
void setAlpha(Uint8 alpha);
// Renders texture at given point
void render(int x, int y, SDL_Rect *clip = NULL, double angle = 0.0, SDL_Point *center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE);
// Gets image dimensions
int getWidth();
int getHeight();
private:
// The actual hardware texture
SDL_Texture *mTexture;
// Image dimensions
int mWidth;
int mHeight;
};
// 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 texture
LTexture gArrowTexture;
LTexture::LTexture()
{
// Initialize
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
LTexture::~LTexture()
{
// Deallocate
free();
}
bool LTexture::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, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF));
// Create texture from surface pixels
newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
if (newTexture == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
}
else
{
// Get image dimensions
mWidth = loadedSurface->w;
mHeight = loadedSurface->h;
}
// Get rid of old loaded surface
SDL_FreeSurface(loadedSurface);
}
// Return success
mTexture = newTexture;
return mTexture != NULL;
}
void LTexture::free()
{
// Free texture if it exists
if (mTexture != NULL)
{
SDL_DestroyTexture(mTexture);
mTexture = NULL;
mWidth = 0;
mHeight = 0;
}
}
void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
// Modulate texture rgb
SDL_SetTextureColorMod(mTexture, red, green, blue);
}
void LTexture::setBlendMode(SDL_BlendMode blending)
{
// Set blending function
SDL_SetTextureBlendMode(mTexture, blending);
}
void LTexture::setAlpha(Uint8 alpha)
{
// Modulate texture alpha
SDL_SetTextureAlphaMod(mTexture, alpha);
}
void LTexture::render(int x, int y, SDL_Rect *clip, double angle, SDL_Point *center, SDL_RendererFlip flip)
{
// Set rendering space and render to screen
SDL_Rect renderQuad = {x, y, mWidth, mHeight};
// Set clip rendering dimensions
if (clip != NULL)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
// Render to screen
SDL_RenderCopyEx(gRenderer, mTexture, clip, &renderQuad, angle, center, flip);
}
int LTexture::getWidth()
{
return mWidth;
}
int LTexture::getHeight()
{
return mHeight;
}
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 vsynced renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
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);
// 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 arrow
if (!gArrowTexture.loadFromFile("./test/asset/arrow.png"))
{
printf("Failed to load arrow texture!\n");
success = false;
}
return success;
}
void close()
{
// Free loaded images
gArrowTexture.free();
// Destroy window
SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow);
gWindow = NULL;
gRenderer = 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;
// Angle of rotation
double degrees = 0;
// Flip type
SDL_RendererFlip flipType = SDL_FLIP_NONE;
// 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;
}
else if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_a:
degrees -= 15;
break;
case SDLK_d:
degrees += 15;
break;
case SDLK_q:
flipType = SDL_FLIP_HORIZONTAL;
break;
case SDLK_w:
flipType = SDL_FLIP_NONE;
break;
case SDLK_e:
flipType = SDL_FLIP_VERTICAL;
break;
}
}
}
// Clear screen
SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(gRenderer);
SDL_Point center = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
SDL_Point arrowPoint = {center.x, center.y - (gArrowTexture.getHeight() / 2)};
// Render arrow
gArrowTexture.render(arrowPoint.x, arrowPoint.y, NULL, degrees, ¢er, flipType);
SDL_Rect filledRect = {center.x - 3, center.y - 3, 5, 5};
SDL_SetRenderDrawColor(gRenderer, 255, 0, 0, 255);
SDL_RenderFillRect(gRenderer, &filledRect);
// Update screen
SDL_RenderPresent(gRenderer);
}
}
}
// Free resources and close SDL
close();
return 0;
}
我希望箭头在我按 a,d 时在屏幕中央旋转
答:
0赞
Nelfeal
10/13/2023
#1
旋转中心相对于渲染纹理的位置( 和 )。您会看到(大约)窗口右下角周围发生的旋转,因为您正在渲染中心纹理,并将窗口尺寸的一半添加到旋转中心。dstrect.x
dstrect.y
你想要这样的东西:
SDL_Point center = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 };
SDL_Point arrowPoint = { center.x, center.y - (gArrowTexture.getHeight() / 2) };
SDL_Point rotationCenter = { center.x - arrowPoint.x, center.y - arrowPoint.y };
gArrowTexture.render(arrowPoint.x, arrowPoint.y, NULL, degrees, &rotationCenter, flipType);
上一个:获取 char 中的位数
评论
LTexture