A few issues ...
- Intermixing windows API calls (for mouse position) may be part of the problem. Forget the winAPI calls and just use the SDL mouse position.
- I tested your program on linux, so I had to remove the winAPI stuff. The result seemed to be "okay"
- You do not reset
endTicks
after doing a render. So, after the first time, it will be called on every outer loop. So, it is hammering the renderer.
- Better to do the event loop outside of the rendering block.
- AFAICT, there is no need to (re)get the mouse position. The last position from the the last motion event is sufficient.
I've produced a few versions to progressively show the fixes:
- Just remove winAPI calls.
- Move event loop outside of the render
if
block and set endTicks
correctly.
- Just use the mouse position from the last motion event.
- Final, fully cleaned up version (without
#if 0
).
In the code below, I use cpp
conditionals to denote old vs. new code (e.g):
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
(1) Here is the refactored code. This just has removal of the winAPI calls:
#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) {
// endTicks = SDL_GetTicks();
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) Here is a version with most of the other fixes I mentioned (e.g. setting endTicks
correctly). It still does SDL_GetMouseState
. It seems to be a bit smoother:
#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) {
// NOTE/FIX: do this on every loop
#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) {
// NOTE/FIX: set endTicks to prevent _excessive_ rendering
#if 1
endTicks = startTicks;
#endif
SDL_RenderClear(renderer);
// NOTE/BUG: do this _outside_ the rendering time and do _not_ do it after
// the render clear
#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) Here is a version that just uses the mouse position from the last motion event:
#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) {
// NOTE/FIX: do this on every loop
#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) {
// NOTE/FIX: set endTicks to prevent _excessive_ rendering
#if 1
endTicks = startTicks;
#endif
SDL_RenderClear(renderer);
// NOTE/BUG: do this _outside_ the rendering time and do _not_ do it after
// the render clear
#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
// NOTE/BUG: no need to reget mouse position -- the motion event has it
#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) A fully cleaned up version:
#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;
}