Licar/frontend_x11.c

153 lines
3.7 KiB
C
Raw Normal View History

2025-05-29 22:27:28 +02:00
/** @file frontend_sdl.c
X11 frontend for Licar.
*/
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>
#include <unistd.h> // for usleep
#define LCR_SETTING_LOG_LEVEL 2
#define LCR_SETTING_RESOLUTION_X 320
#define LCR_SETTING_RESOLUTION_Y 240
#define LCR_SETTING_MUSIC 0
2025-06-02 16:58:02 +02:00
#ifndef PRESET_QUALITY
#define PRESET_QUALITY 3
#endif
2025-06-01 19:59:09 +02:00
#include "frontend_helper.h"
2025-06-02 16:58:02 +02:00
#include "game.h"
2025-05-29 22:27:28 +02:00
char framebuffer[LCR_SETTING_RESOLUTION_X * LCR_SETTING_RESOLUTION_Y * 4];
uint8_t buttonStates[8];
void LCR_drawPixel(unsigned long index, uint16_t color)
{
char *p = framebuffer + 4 * index;
*p = (color << 3) & 0xff;
p++;
*p = (color >> 3) & 0xfc;
p++;
*p = (color >> 8) & 0xf8;
}
uint8_t LCR_keyPressed(uint8_t key)
{
return buttonStates[key % 8];
}
void LCR_sleep(uint16_t timeMs)
{
usleep(timeMs * 1000);
}
2025-05-31 18:23:13 +02:00
void printHelp(void)
{
printf(
"Licar, 3D racing game, v. " LCR_VERSION ", X11 frontend, args:\n"
" -h print help and quit\n"
LCR_ARG_HELP_STR);
}
2025-05-29 22:27:28 +02:00
int main(int argc, char **argv)
{
int running = 1;
struct timeval now;
2025-05-31 18:23:13 +02:00
for (int i = 0; i < argc; ++i)
if (argv[i][0] == '-')
switch (argv[i][1])
{
case 'h': printHelp(); return 0; break;
default: break;
}
2025-05-29 22:27:28 +02:00
LCR_gameInit(argc,(const char **) argv);
Display *display = XOpenDisplay(0);
int screen = DefaultScreen(display);
2025-06-01 19:59:09 +02:00
openDataFile();
2025-05-29 22:27:28 +02:00
Window window = XCreateSimpleWindow(display,RootWindow(display,screen),10,10,
LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y,1,
BlackPixel(display,screen),WhitePixel(display,screen));
XSizeHints *sizeHints = XAllocSizeHints();
sizeHints->flags = PMaxSize | PMinSize;
sizeHints->max_width = LCR_SETTING_RESOLUTION_X;
sizeHints->min_width = LCR_SETTING_RESOLUTION_X;
sizeHints->max_height = LCR_SETTING_RESOLUTION_Y;
sizeHints->min_height = LCR_SETTING_RESOLUTION_Y;
XSetWMNormalHints(display,window,sizeHints);
XFree(sizeHints);
XMapWindow(display,window);
XSelectInput(display,window,KeyPressMask | KeyReleaseMask);
GC context = DefaultGC(display,screen);
XStoreName(display,window,"Licar");
/*
Hardcoded constants here may perhaps cause trouble on some platforms, but
doing X11 "the right way" would mean 1 billion lines of code, so fuck it.
*/
XImage *image = XCreateImage(display,DefaultVisual(display,screen),
/*DefaultDepth(display,screen)*/24,ZPixmap,0,framebuffer,
LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y,8,0);
while (running) // main loop
{
XEvent event;
gettimeofday(&now,NULL);
running &= LCR_gameStep(now.tv_sec * 1000 + now.tv_usec / 1000);
XPutImage(display,window,context,image,0,0,0,0,LCR_SETTING_RESOLUTION_X,
LCR_SETTING_RESOLUTION_Y);
while (XCheckWindowEvent(display,window,KeyPressMask |
KeyReleaseMask,&event) != False)
{
uint8_t state = event.xkey.type == KeyPress;
switch (XKeycodeToKeysym(display,event.xkey.keycode,0))
{
case XK_Up: case XK_w:
buttonStates[LCR_KEY_UP % 8] = state; break;
case XK_Left: case XK_a:
buttonStates[LCR_KEY_LEFT % 8] = state; break;
case XK_Right: case XK_d:
buttonStates[LCR_KEY_RIGHT % 8] = state; break;
case XK_Down: case XK_s:
buttonStates[LCR_KEY_DOWN % 8] = state; break;
case XK_j: case XK_Return:
buttonStates[LCR_KEY_A % 8] = state; break;
case XK_k: case XK_Escape:
buttonStates[LCR_KEY_B % 8] = state; break;
default: break;
}
}
}
XDestroyImage(image);
XCloseDisplay(display);
2025-06-01 19:59:09 +02:00
closeDataFile();
2025-05-29 22:27:28 +02:00
LCR_gameEnd();
return 0;
}