有几个问题...
- 混合使用Windows API调用(用于鼠标位置)可能是问题的一部分。忘记winAPI调用,只使用SDL鼠标位置。
- 我在Linux上测试了你的程序,所以我不得不删除winAPI的内容。结果似乎还可以。
- 在渲染后,你没有重置
endTicks
。所以,在第一次之后,它将在每个外部循环中被调用。因此,它会对渲染器造成压力。
- 最好在渲染块之外执行事件循环。
- 据我所知,没有必要重新获取鼠标位置。上一个运动事件的最后位置就足够了。
我制作了几个版本来逐步展示修复:
- 只需删除winAPI调用。
- 将事件循环移到渲染
if
块之外,并正确设置endTicks
。
- 只使用上一个运动事件的鼠标位置。
- 最终的、完全清理过的版本(不包括
#if 0
)。
在下面的代码中,我使用
cpp
条件语句来表示旧代码与新代码(例如):
// old code
// new code
// new code
(1)这是重构后的代码。这只是删除了winAPI调用:
#if 0
#include <windows.h>
#endif
#include "SDL2/SDL.h"
#define ARRAY_CONSINT (const int[])
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
void
drawRectangle(SDL_Renderer *renderer, SDL_Rect rect, const int clr[], int fill)
{
SDL_SetRenderDrawColor(renderer, clr[0], clr[1], clr[2], clr[3]);
if (fill == 0)
SDL_RenderDrawRect(renderer, &rect);
else
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
int
main(int argc, char *args[])
{
struct Mouse_s {
int X;
int Y;
};
int lQuit;
#if 0
POINT Windows_Mouse;
#endif
SDL_Window *gWindow;
SDL_Surface *screenSurface;
SDL_Renderer *renderer;
Uint32 startTicks;
Uint32 endTicks;
Uint32 DeltaTime;
int showFPS;
struct Mouse_s SDL_Mouse;
struct Mouse_s Motion_Mouse;
lQuit = 0;
SDL_Mouse.X = 0;
SDL_Mouse.Y = 0;
Motion_Mouse.X = 0;
Motion_Mouse.Y = 0;
startTicks = 0;
endTicks = 0;
DeltaTime = 0;
SDL_Init(SDL_INIT_EVERYTHING);
gWindow = SDL_CreateWindow("Window", -1, -1, SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
#if 0
renderer = SDL_CreateRenderer(gWindow, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
#else
renderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
#endif
screenSurface = SDL_GetWindowSurface(gWindow);
SDL_UpdateWindowSurface(gWindow);
while (lQuit == 0) {
startTicks = SDL_GetTicks();
DeltaTime = startTicks - endTicks;
if (DeltaTime > 1000 / 60.0) {
SDL_RenderClear(renderer);
SDL_Event EventHandler;
while (SDL_PollEvent(&EventHandler) != 0) {
if (EventHandler.type == SDL_QUIT)
lQuit = 1;
else if (EventHandler.type == SDL_MOUSEMOTION) {
Motion_Mouse.X = EventHandler.motion.x;
Motion_Mouse.Y = EventHandler.motion.y;
}
}
SDL_GetMouseState(&SDL_Mouse.X, &SDL_Mouse.Y);
const SDL_Rect rect = { SDL_Mouse.X, SDL_Mouse.Y - 50, 100, 50 };
drawRectangle(renderer, rect, ARRAY_CONSINT {
255, 0, 0, 255}, 0);
#if 0
GetCursorPos(&Windows_Mouse);
const SDL_Rect rect2 = { Windows_Mouse.x, Windows_Mouse.y - 50,
70, 40 };
#else
const SDL_Rect rect2 = { SDL_Mouse.X, SDL_Mouse.Y - 50, 70, 40 };
#endif
drawRectangle(renderer, rect2, ARRAY_CONSINT {
0, 255, 0, 255}, 0);
const SDL_Rect rect3 = { Motion_Mouse.X, Motion_Mouse.Y - 50,
40, 30 };
drawRectangle(renderer, rect3, ARRAY_CONSINT {
0, 0, 255, 255}, 0);
SDL_RenderPresent(renderer);
}
}
return 0;
}
(2)这是一个包含我提到的大部分其他修复(例如正确设置
endTicks
)的版本。它仍然使用
SDL_GetMouseState
。看起来更加流畅一些。
#if 0
#include <windows.h>
#endif
#include "SDL2/SDL.h"
#define ARRAY_CONSINT (const int[])
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
void
drawRectangle(SDL_Renderer * renderer, SDL_Rect rect, const int clr[], int fill)
{
SDL_SetRenderDrawColor(renderer, clr[0], clr[1], clr[2], clr[3]);
if (fill == 0)
SDL_RenderDrawRect(renderer, &rect);
else
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
int
main(int argc, char *args[])
{
struct Mouse_s {
int X;
int Y;
};
int lQuit;
#if 0
POINT Windows_Mouse;
#endif
SDL_Window *gWindow;
SDL_Surface *screenSurface;
SDL_Renderer *renderer;
Uint32 startTicks;
Uint32 endTicks;
Uint32 DeltaTime;
int showFPS;
struct Mouse_s SDL_Mouse;
struct Mouse_s Motion_Mouse;
lQuit = 0;
SDL_Mouse.X = 0;
SDL_Mouse.Y = 0;
Motion_Mouse.X = 0;
Motion_Mouse.Y = 0;
startTicks = 0;
endTicks = 0;
DeltaTime = 0;
SDL_Init(SDL_INIT_EVERYTHING);
gWindow = SDL_CreateWindow("Window", -1, -1, SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
#if 0
renderer = SDL_CreateRenderer(gWindow, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
#else
renderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
#endif
screenSurface = SDL_GetWindowSurface(gWindow);
SDL_UpdateWindowSurface(gWindow);
while (lQuit == 0) {
#if 1
SDL_Event EventHandler;
while (SDL_PollEvent(&EventHandler) != 0) {
if (EventHandler.type == SDL_QUIT)
lQuit = 1;
else if (EventHandler.type == SDL_MOUSEMOTION) {
Motion_Mouse.X = EventHandler.motion.x;
Motion_Mouse.Y = EventHandler.motion.y;
}
}
#endif
startTicks = SDL_GetTicks();
DeltaTime = startTicks - endTicks;
if (DeltaTime > 1000 / 60.0) {
#if 1
endTicks = startTicks;
#endif
SDL_RenderClear(renderer);
#if 0
SDL_Event EventHandler;
while (SDL_PollEvent(&EventHandler) != 0) {
if (EventHandler.type == SDL_QUIT)
lQuit = 1;
else if (EventHandler.type == SDL_MOUSEMOTION) {
Motion_Mouse.X = EventHandler.motion.x;
Motion_Mouse.Y = EventHandler.motion.y;
}
}
#endif
SDL_GetMouseState(&SDL_Mouse.X, &SDL_Mouse.Y);
const SDL_Rect rect = { SDL_Mouse.X, SDL_Mouse.Y - 50, 100, 50 };
drawRectangle(renderer, rect, ARRAY_CONSINT {
255, 0, 0, 255}, 0);
#if 0
GetCursorPos(&Windows_Mouse);
const SDL_Rect rect2 = { Windows_Mouse.x, Windows_Mouse.y - 50,
70, 40 };
#else
const SDL_Rect rect2 = { SDL_Mouse.X, SDL_Mouse.Y - 50, 70, 40 };
#endif
drawRectangle(renderer, rect2, ARRAY_CONSINT {
0, 255, 0, 255}, 0);
const SDL_Rect rect3 = { Motion_Mouse.X, Motion_Mouse.Y - 50,
40, 30 };
drawRectangle(renderer, rect3, ARRAY_CONSINT {
0, 0, 255, 255}, 0);
SDL_RenderPresent(renderer);
}
}
return 0;
}
(3)这里有一个版本,它只使用了上一个鼠标移动事件的鼠标位置:
#if 0
#include <windows.h>
#endif
#include "SDL2/SDL.h"
#define ARRAY_CONSINT (const int[])
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
void
drawRectangle(SDL_Renderer * renderer, SDL_Rect rect, const int clr[], int fill)
{
SDL_SetRenderDrawColor(renderer, clr[0], clr[1], clr[2], clr[3]);
if (fill == 0)
SDL_RenderDrawRect(renderer, &rect);
else
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
int
main(int argc, char *args[])
{
struct Mouse_s {
int X;
int Y;
};
int lQuit;
#if 0
POINT Windows_Mouse;
#endif
SDL_Window *gWindow;
SDL_Surface *screenSurface;
SDL_Renderer *renderer;
Uint32 startTicks;
Uint32 endTicks;
Uint32 DeltaTime;
int showFPS;
#if 0
struct Mouse_s SDL_Mouse;
#endif
struct Mouse_s Motion_Mouse;
lQuit = 0;
#if 0
SDL_Mouse.X = 0;
SDL_Mouse.Y = 0;
#endif
Motion_Mouse.X = 0;
Motion_Mouse.Y = 0;
startTicks = 0;
endTicks = 0;
DeltaTime = 0;
SDL_Init(SDL_INIT_EVERYTHING);
gWindow = SDL_CreateWindow("Window", -1, -1, SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
#if 0
renderer = SDL_CreateRenderer(gWindow, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
#else
renderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
#endif
screenSurface = SDL_GetWindowSurface(gWindow);
SDL_UpdateWindowSurface(gWindow);
while (lQuit == 0) {
#if 1
SDL_Event EventHandler;
while (SDL_PollEvent(&EventHandler) != 0) {
if (EventHandler.type == SDL_QUIT)
lQuit = 1;
else if (EventHandler.type == SDL_MOUSEMOTION) {
Motion_Mouse.X = EventHandler.motion.x;
Motion_Mouse.Y = EventHandler.motion.y;
}
}
#endif
startTicks = SDL_GetTicks();
DeltaTime = startTicks - endTicks;
if (DeltaTime > 1000 / 60.0) {
#if 1
endTicks = startTicks;
#endif
SDL_RenderClear(renderer);
#if 0
SDL_Event EventHandler;
while (SDL_PollEvent(&EventHandler) != 0) {
if (EventHandler.type == SDL_QUIT)
lQuit = 1;
else if (EventHandler.type == SDL_MOUSEMOTION) {
Motion_Mouse.X = EventHandler.motion.x;
Motion_Mouse.Y = EventHandler.motion.y;
}
}
#endif
#if 0
SDL_GetMouseState(&SDL_Mouse.X, &SDL_Mouse.Y);
#endif
const SDL_Rect rect = { Motion_Mouse.X, Motion_Mouse.Y - 50,
100, 50 };
drawRectangle(renderer, rect, ARRAY_CONSINT {
255, 0, 0, 255}, 0);
#if 0
GetCursorPos(&Windows_Mouse);
const SDL_Rect rect2 = { Windows_Mouse.x, Windows_Mouse.y - 50,
70, 40 };
#else
const SDL_Rect rect2 = { Motion_Mouse.X, Motion_Mouse.Y - 50,
70, 40 };
#endif
drawRectangle(renderer, rect2, ARRAY_CONSINT {
0, 255, 0, 255}, 0);
const SDL_Rect rect3 = { Motion_Mouse.X, Motion_Mouse.Y - 50,
40, 30 };
drawRectangle(renderer, rect3, ARRAY_CONSINT {
0, 0, 255, 255}, 0);
SDL_RenderPresent(renderer);
}
}
return 0;
}
(4)一个完全清理过的版本:
#include "SDL2/SDL.h"
#define ARRAY_CONSINT (const int[])
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
void
drawRectangle(SDL_Renderer *renderer, SDL_Rect rect, const int clr[], int fill)
{
SDL_SetRenderDrawColor(renderer, clr[0], clr[1], clr[2], clr[3]);
if (fill == 0)
SDL_RenderDrawRect(renderer, &rect);
else
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
}
int
main(int argc, char *args[])
{
struct Mouse_s {
int X;
int Y;
};
int lQuit;
SDL_Window *gWindow;
SDL_Surface *screenSurface;
SDL_Renderer *renderer;
Uint32 startTicks;
Uint32 endTicks;
Uint32 DeltaTime;
int showFPS;
struct Mouse_s Motion_Mouse;
lQuit = 0;
Motion_Mouse.X = 0;
Motion_Mouse.Y = 0;
startTicks = 0;
endTicks = 0;
DeltaTime = 0;
SDL_Init(SDL_INIT_EVERYTHING);
gWindow = SDL_CreateWindow("Window", -1, -1, SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
screenSurface = SDL_GetWindowSurface(gWindow);
SDL_UpdateWindowSurface(gWindow);
while (lQuit == 0) {
SDL_Event EventHandler;
while (SDL_PollEvent(&EventHandler) != 0) {
if (EventHandler.type == SDL_QUIT)
lQuit = 1;
else if (EventHandler.type == SDL_MOUSEMOTION) {
Motion_Mouse.X = EventHandler.motion.x;
Motion_Mouse.Y = EventHandler.motion.y;
}
}
startTicks = SDL_GetTicks();
DeltaTime = startTicks - endTicks;
if (DeltaTime > 1000 / 60.0) {
endTicks = startTicks;
SDL_RenderClear(renderer);
const SDL_Rect rect = { Motion_Mouse.X, Motion_Mouse.Y - 50,
100, 50 };
drawRectangle(renderer, rect, ARRAY_CONSINT {
255, 0, 0, 255}, 0);
const SDL_Rect rect2 = { Motion_Mouse.X, Motion_Mouse.Y - 50,
70, 40 };
drawRectangle(renderer, rect2, ARRAY_CONSINT {
0, 255, 0, 255}, 0);
const SDL_Rect rect3 = { Motion_Mouse.X, Motion_Mouse.Y - 50,
40, 30 };
drawRectangle(renderer, rect3, ARRAY_CONSINT {
0, 0, 255, 255}, 0);
SDL_RenderPresent(renderer);
}
}
return 0;
}
SDL_ShowCursor(SDL_DISABLE)
+ 自绘光标图像/框? - genpfault