问题描述
我正在用C语言编写一个简单的游戏,并且我不想使用任何高级库(例如OpenGL
)。最烦人的问题是更改显示场景的问题。不久前,有人告诉我您在Windows中使用SwapBuffers()
函数。我试图在我的PaintEngine中编写类似的代码,从而产生了以下功能:
ECode PaintEngine_SwapBuffers (PaintEngine PE) {
PaintEngine_Platform *platform = &(PE->platform);
XCopyArea (platform->display,platform->pixmap,platform->window,platform->gc,PE->width,PE->height,0);
return ECode_OK;
}
平台结构定义如下:
typedef struct {
Display *display;
int screen;
Window window;
GC gc;
int depth;
Colormap colormap;
Visual *visual;
Pixmap pixmap;
} PaintEngine_Platform;
每次调整窗口大小时,像素图都会更改:
platform->pixmap = XCreatePixmap (platform->display,XRootWindow(platform->display,platform->screen),platform->depth);
因此,我在像素图上进行了所有绘制,并且在事件处理周期中一次调用了PaintEngine_SwapBuffers()。
我的问题:
- 持续闪烁。一切都闪烁得很明显
- 有时候,当我调整窗口大小时,像素图似乎没有被调整大小。
我知道,这种方法可能还可以,问题出在我的PaintEngine的其余部分中,所以这里是完整的代码:
#if defined(__linux__) || defined(__FreeBSD__)
#include <X11/Xlib.h>
#endif
#include <time.h>
extern void *malloc (size_t);
extern void free (void *);
// Type definitions
typedef u_int8_t ECode;
#define ECode_OK (char) 0
#define ECode_ERROR (char) 1
#define ECode_QUIT (char) 2
#if defined(__linux__) || defined(__FreeBSD__)
typedef struct {
Display *display;
int screen;
Window window;
GC gc;
int depth;
Colormap colormap;
Visual *visual;
Pixmap pixmap;
} PaintEngine_Platform;
#endif
typedef struct _PaintEngine_Mouse {
u_int32_t x;
u_int32_t y;
u_int32_t x_prev;
u_int32_t y_prev;
u_int8_t press [5];
u_int8_t moves;
} PaintEngine_Mouse;
#define Mouse_Left 0
#define Mouse_Middle 1
#define Mouse_Right 2
#define Mouse_ScrollUp 4
#define Mouse_ScrollDown 5
typedef struct _PaintEngine {
u_int32_t width;
u_int32_t height;
u_int32_t pixel_size;
u_int8_t full_screen;
u_int32_t (*OnCreate ) (struct _PaintEngine *);
u_int32_t (*OnDestroy) (struct _PaintEngine *);
u_int32_t (*OnUpdate ) (struct _PaintEngine *,float);
u_int32_t active;
clock_t t1,t2;
PaintEngine_Mouse mouse;
PaintEngine_Platform platform;
u_int32_t (*OnButtonPress) (struct _PaintEngine *);
u_int32_t (*OnMotion) (struct _PaintEngine *);
u_int32_t (*OnButtonRelease) (struct _PaintEngine *);
} *PaintEngine;
PaintEngine PaintEngine_Create (u_int32_t,u_int32_t,u_int8_t);
ECode PaintEngine_Start (PaintEngine);
u_int32_t PaintEngine_OnCreate (PaintEngine);
u_int32_t PaintEngine_OnDestroy (PaintEngine);
u_int32_t PaintEngine_OnUpdate (PaintEngine,float);
ECode PaintEngine_CreateWindow (PaintEngine);
u_int32_t PaintEngine_ProcessCycle (PaintEngine);
ECode PaintEngine_ProcessLoop (PaintEngine);
ECode PaintEngine_ProcessLoopInit (PaintEngine);
ECode PaintEngine_CleanUp (PaintEngine);
void PaintEngine_ProcessEvents (PaintEngine);
u_int32_t PaintEngine_OnButtonPress (PaintEngine);
u_int32_t PaintEngine_OnButtonRelease (PaintEngine);
u_int32_t PaintEngine_OnMotion (PaintEngine);
ECode PaintEngine_SwapBuffers (PaintEngine);
ECode PaintEngine_ClearWindow (PaintEngine);
PaintEngine PaintEngine_Create (u_int32_t width,u_int32_t height,u_int32_t pixel_size,u_int8_t full_screen) {
PaintEngine PE = malloc(sizeof(struct _PaintEngine));
PE->width = width;
PE->height = height;
PE->pixel_size = pixel_size;
PE->full_screen = full_screen;
PE->OnCreate = PaintEngine_OnCreate;
PE->OnDestroy = PaintEngine_OnDestroy;
PE->OnUpdate = PaintEngine_OnUpdate;
PE->OnMotion = PaintEngine_OnMotion;
PE->OnButtonPress = PaintEngine_OnButtonPress;
PE->OnButtonRelease = PaintEngine_OnButtonRelease;
return PE;
}
#if defined(__linux__) || defined(__FreeBSD__)
ECode PaintEngine_Start (PaintEngine PE) {
ECode ecode;
if ((ecode = PaintEngine_CreateWindow (PE)) != ECode_OK)
return ecode;
if ((ecode = PaintEngine_ProcessLoop (PE)) != ECode_OK)
return ecode;
return PaintEngine_CleanUp (PE);
}
#endif
u_int32_t PaintEngine_OnCreate (PaintEngine PE) { return 1; }
u_int32_t PaintEngine_OnDestroy (PaintEngine PE) { return 1; }
u_int32_t PaintEngine_OnUpdate (PaintEngine PE,float unused) { return 1; }
u_int32_t PaintEngine_OnMotion (PaintEngine PE) { return 1; }
u_int32_t PaintEngine_OnButtonPress (PaintEngine PE) { return 1; }
u_int32_t PaintEngine_OnButtonRelease (PaintEngine PE) { return 1; }
#if defined(__linux__) || defined(__FreeBSD__)
ECode PaintEngine_CreateWindow (PaintEngine PE) {
PaintEngine_Platform *platform = &(PE->platform);
XSetWindowAttributes wa;
u_int32_t display_width,display_height;
XInitThreads();
platform->display = XOpenDisplay (0);
platform->screen = DefaultScreen (platform->display);
platform->depth = DefaultDepth (platform->display,platform->screen);
platform->visual = DefaultVisual (platform->display,platform->screen);
wa.background_pixel = XBlackPixel (platform->display,platform->screen);
wa.override_redirect = False;
wa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
ButtonReleaseMask | PointerMotionMask | FocusChangeMask | StructureNotifyMask;
display_width = DisplayWidth (platform->display,platform->screen);
display_height = DisplayHeight (platform->display,platform->screen);
if (PE->full_screen) {
PE->width = DisplayWidth (platform->display,platform->screen);
PE->height = DisplayHeight (platform->display,platform->screen);
#if defined(__linux__)
wa.override_redirect = True;
#endif
}
platform->window = XCreateWindow (platform->display,XRootWindow (platform->display,(display_width - PE->width) / 2,(display_height - PE->height) / 2,platform->depth,InputOutput,platform->visual,CWBackPixel | CWEventMask | CWOverrideRedirect,&wa);
XMapWindow (platform->display,platform->window);
// platform->colormap = XCreateColormap (platform->display,AllocAll);
platform->gc = XCreateGC (platform->display,0);
platform->pixmap = XCreatePixmap (platform->display,platform->depth);
XSetForeground (platform->display,XWhitePixel(platform->display,platform->screen));
XSetBackground (platform->display,platform->screen));
XFlush(platform->display);
return ECode_OK;
}
#endif
ECode PaintEngine_ProcessLoop (PaintEngine PE) {
PE->active = PE->OnCreate(PE);
PaintEngine_ProcessLoopInit (PE);
while (PE->active) {
while (PE->active)
PaintEngine_ProcessCycle (PE);
if (!PE->OnDestroy (PE))
PE->active = 1;
}
PaintEngine_CleanUp (PE);
return ECode_OK;
}
ECode PaintEngine_ProcessLoopInit (PaintEngine PE) {
int i;
PE->t1 = clock();
for (i=0; i < 5; i++)
(PE->mouse).press[i] = 0;
(PE->mouse).x_prev = 0;
(PE->mouse).y_prev = 0;
return ECode_OK;
}
u_int32_t PaintEngine_ProcessCycle (PaintEngine PE) {
float elapsed_time;
PE->t2 = clock();
elapsed_time = (float) (PE->t2 - PE->t1) / CLOCKS_PER_SEC;
PE->t1 = PE->t2;
PaintEngine_ProcessEvents (PE);
PE->active = PE->OnUpdate(PE,elapsed_time);
// PaintEngine_ClearWindow(PE);
PaintEngine_SwapBuffers(PE);
printf("Here\n");
return 1;
}
#if defined(__linux__) || defined(__FreeBSD__)
void PaintEngine_ProcessEvents (PaintEngine PE) {
XEvent event;
PaintEngine_Platform *platform = &(PE->platform);
PaintEngine_Mouse *mouse = &(PE->mouse);
while (XPending (platform->display)) {
XNextEvent (platform->display,&event);
mouse->moves = 0;
switch (event.type) {
case Expose:
break;
case ConfigureNotify:
PE->width = event.xconfigure.x;
PE->height = event.xconfigure.y;
XFreePixmap (platform->display,platform->pixmap);
platform->pixmap = XCreatePixmap (platform->display,platform->depth);
break;
case KeyPress:
PaintEngine_SwapBuffers(PE);
break;
case ButtonPress:
mouse->x_prev = mouse->x;
mouse->y_prev = mouse->y;
mouse->x = event.xbutton.x;
mouse->y = event.xbutton.y;
(mouse->press)[event.xbutton.button-1] = 1;
PE->OnButtonPress(PE);
break;
case MotionNotify:
mouse->moves = 1;
mouse->x_prev = mouse->x;
mouse->y_prev = mouse->y;
mouse->x = event.xmotion.x;
mouse->y = event.xmotion.y;
PE->OnMotion(PE);
break;
case LeaveNotify:
case ButtonRelease:
PE->OnButtonRelease(PE);
(mouse->press)[event.xbutton.button-1] = 0;
break;
default:
break;
}
}
return;
}
ECode PaintEngine_SwapBuffers (PaintEngine PE) {
PaintEngine_Platform *platform = &(PE->platform);
XCopyArea (platform->display,0);
return ECode_OK;
}
ECode PaintEngine_DrawLine (PaintEngine PE,u_int32_t x1,u_int32_t y1,u_int32_t x2,u_int32_t y2) {
PaintEngine_Platform *platform = &(PE->platform);
XDrawLine (platform->display,x1,y1,x2,y2);
printf("(%d,%d) - (%d,%d)\n",y2);
return ECode_OK;
}
ECode PaintEngine_ClearWindow (PaintEngine PE) {
PaintEngine_Platform *platform = &(PE->platform);
XClearWindow (platform->display,platform->window);
return ECode_OK;
}
ECode PaintEngine_CleanUp (PaintEngine PE) {
PaintEngine_Platform *platform = &(PE->platform);
XFreeGC (platform->display,platform->gc);
XDestroyWindow (platform->display,platform->window);
XFreePixmap (platform->display,platform->pixmap);
free (PE);
return ECode_OK;
}
#endif
对于其他有关引擎的建议,我也将不胜感激
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)