我正在用 SDL2 和 C 创建一个游戏。虽然我在其他编程语言方面有很多经验,但我已经多年没有用 C 编码了,我想再试一次。无论如何,我发现了一个名为 SDL2 的 C 库并决定创建一个游戏。仍然没有选择游戏的想法,但我正在尝试创建一个“虚拟视窗”,它基本上只是一个矩形,您可以拖动并在其中显示内容。我已经完成了几乎所有的事情,除了拖动部分。我想拖动视窗的工具列,并根据我的鼠标位置移动整个视窗。基本上,我想把鼠标放在工具列中,当点击和拖动时,我希望整个视窗随着鼠标移动,但我几乎所有的尝试都是整个视窗在我的鼠标末端传送,所以我可以不要把它移到左边,只有向右和向下。我找到了一种可能的方法,它包含在源代码中,但视窗总是切换位置。我真的不知道如何解释这一点,但它会在例如一帧切换,X 为 68,下一帧为 271,下一帧为 67(68-1),下一帧为 270( 271-1) 等。我在我的帖子中包含了源代码。
“视窗”类:
class Window {
public:
int x, y, w, h;
SDL_Color winc, wintc;
bool draggable;
int titleh;
Window(int wx, int wy, int ww, int wh, SDL_Color window_color = {255, 255, 255, 255}, SDL_Color window_title_color = {200, 200, 200, 255}) {
x = wx;
y = wy;
w = ww;
h = wh;
winc = window_color;
wintc = window_title_color;
draggable = true;
titleh = 50;
}
void Render(SDL_Renderer* renderer) {
SDL_Rect _t;
_t.x = x;
_t.y = y;
_t.w = w;
_t.h = h;
SDL_SetRenderDrawColor(renderer, winc.r, winc.g, winc.b, winc.a);
SDL_RenderFillRect(renderer, &_t);
SDL_Rect title;
title.x = x;
title.y = y;
title.w = w;
title.h = titleh;
SDL_SetRenderDrawColor(renderer, wintc.r, wintc.g, wintc.b, wintc.a);
SDL_RenderFillRect(renderer, &title);
int tx, ty;
if (draggable == true and isdown == true and mx > x and mx < (x w) and my > y and my < (y titleh)) {
tx = x;
ty = y;
x = mx - tx;
y = my - ty;
}
}
};
整个档案:
// Library includes
#include <SDL2/SDL.h>
#include <stdio.h>
bool isdown = false;
int mx, my;
// Screen rendering helper
void on_render(SDL_Window* window, SDL_Renderer* renderer);
// Concatenation (probably not spelt correctly but idrc) for easier use
const char * concat(const char * one, const char * two) {
char * buffer = new char[strlen(one) strlen(two) 1];
strcpy(buffer, one);
strcat(buffer, two);
return buffer;
}
// Main method, required for performing application run
int main(int argc, const char * argv[]) {
SDL_Renderer *renderer = NULL; // Initialize the renderer
SDL_Event event = { 0 }; // Create a null event
SDL_Window *win = NULL; // Initialize a window
int exit = 0; // If exit is 1, win closes
// Window pre-modifiers
const char * appName = "test";
// SDL VIDEO mode initialization and error check
if(SDL_Init(SDL_INIT_VIDEO) == -1) {
printf("SDL_Init() failed with \"%s.\"", SDL_GetError());
return 1;
}
// Create the window and load it into a previously defined variable
win = SDL_CreateWindow(concat(appName, " - Initialization in progress"), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
// Window creation was unsuccessfull
if(!win) {
printf("SDL_CreateWindow() failed with \"%s.\"", SDL_GetError());
return -1;
}
// Creating renderer
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
// If renderer failed to load...
if(!renderer) {
printf("SDL_CreateRenderer() failed with \"%s.\"", SDL_GetError());
return -1;
}
// Everything has gone OK, thus the window can be renamed
SDL_SetWindowTitle(win, appName);
// Game loop, as said previously, false = 0, true = 1.
// while !exit |
// while not exit <- |
// while exit is 0 (false) <-
while (!exit) {
// Event loop
if (SDL_WaitEvent(&event)) {
// Event types
switch(event.type) {
case SDL_QUIT:
exit = 1; // Exit = 1, thus app is being exitted
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE) exit = 1; // If ESC is pressed
break;
case SDL_MOUSEBUTTONUP:
isdown = false;
break;
case SDL_MOUSEBUTTONDOWN:
isdown = true;
break;
case SDL_MOUSEMOTION:
mx = event.motion.x;
my = event.motion.y;
break;
case SDL_WINDOWEVENT:
switch(event.window.event) {
case SDL_WINDOWEVENT_CLOSE: // macOS and/or other OSes rely on right click Quit to fully exit out of an application. This makes it easier by just hitting the close button.
exit = 1;
break;
}
break;
default: break;
}
}
// Render the screen
on_render(win, renderer);
// Swap buffers to display
SDL_RenderPresent(renderer);
}
// Cleanup
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
class Window {
public:
int x, y, w, h;
SDL_Color winc, wintc;
bool draggable;
int titleh;
Window(int wx, int wy, int ww, int wh, SDL_Color window_color = {255, 255, 255, 255}, SDL_Color window_title_color = {200, 200, 200, 255}) {
x = wx;
y = wy;
w = ww;
h = wh;
winc = window_color;
wintc = window_title_color;
draggable = true;
titleh = 50;
}
void Render(SDL_Renderer* renderer) {
SDL_Rect _t;
_t.x = x;
_t.y = y;
_t.w = w;
_t.h = h;
SDL_SetRenderDrawColor(renderer, winc.r, winc.g, winc.b, winc.a);
SDL_RenderFillRect(renderer, &_t);
SDL_Rect title;
title.x = x;
title.y = y;
title.w = w;
title.h = titleh;
SDL_SetRenderDrawColor(renderer, wintc.r, wintc.g, wintc.b, wintc.a);
SDL_RenderFillRect(renderer, &title);
int tx, ty;
if (draggable == true and isdown == true and mx > x and mx < (x w) and my > y and my < (y titleh)) {
tx = x;
ty = y;
x = mx - tx;
y = my - ty;
}
}
};
Window test1 = Window(300, 200, 300, 200);
void on_render(SDL_Window* window, SDL_Renderer* renderer) {
SDL_Rect wind = { 0 };
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_GetWindowSize(window, &wind.w, &wind.h);
test1.Render(renderer);
}
uj5u.com热心网友回复:
问题是 event.motion.x (mx) 和 event.motion.y (my) 是相对于应用程序视窗的鼠标坐标。由于您没有在计算新的 Window 物件位置时添加任何偏移量,因此渲染将从这些坐标处开始。
例如,您可以执行以下操作,将鼠标指标置于 Window 物件中:
//Mouse-cursor will stay in the middle of the Window-object
x = mx - w / 2;
y = my - h / 2;
或者,您可以像这样将鼠标游标的位置保留在 Window 物件中:
class Window
{
private:
//Are the offsets already calculated?
bool offset_calculated = false;
//...
}
在您的视窗物件渲染功能中:
if (draggable == true and isdown == true and mx > x and mx < (x w) and my > y and my < (y titleh))
{
if(!offset_calculated)
{
//Calculate x- and y-offset once per click
offsetx = mx - x;
offsety = my - y;
offset_calculated = true;
}
//Keep mouse-cursor position inside of the Window-object
x = mx - offsetx;
y = my - offsety;
}
else
{
offset_calculated = false;
}
档案:https : //wiki.libsdl.org/SDL_MouseMotionEvent
0 评论