Add X11 frontend

This commit is contained in:
Miloslav Ciz 2025-05-29 22:27:28 +02:00
parent eb640d27a1
commit f7a24f2aa1
4 changed files with 204 additions and 15 deletions

View file

@ -11,13 +11,8 @@ fuck issue trackers :D
- Nibble, should hopefully be powerful enough.
- ESPboy?
- linux framebuffer?
- make car turned on its back behave nicer? but how?
- press forward map??? :-D only when physics is frozen
- make some kinda repo for world record runs? how will they submit it?
- Try doing the bouncy car body? Just keep a point and its velocity, change
its velocity by a proportion of car's velocity change (this minus prev.
frame), then offset car body by this. However we'll also have to transform
inbetween world space and model space.
- final tests:
- very long replay
- different resolutions
@ -43,6 +38,11 @@ fuck issue trackers :D
=========== HANDLED ==============
- should drifting make a sound? NO NEED
- make car turned on its back behave nicer? but how? PROLLY NOT
- Try doing the bouncy car body? Just keep a point and its velocity, change
its velocity by a proportion of car's velocity change (this minus prev.
frame), then offset car body by this. However we'll also have to transform
inbetween world space and model space. LEAVE FOR A MOD
- add display of inputs on the screen (option in setting? arg?)
- viewing replay during countdown bugs!
- sometimes after restart the timer shows not 0:0:0, but something like 0:0:033

2
data
View file

@ -135,4 +135,4 @@ details
#RLC2 00'24'948;00LC2;3c5ba5dd 0000756:0001:0143:0021:01a9:0051:00b5:0031:01d9:0041:0069:0031:00c9:0041:0079:0021:01d3:0061:0063:0031:0073:0072:0043:0041:0033:0061:0243:0041:0189:0021:0129:0021:0133:0021:0085:0031:0053:0041:0033:0041:0043:00d1:02f9:0031:00c9:0031:00a3:0051:00f9:0061:00d9:0031:01d3:0101:0043:0041:0059:00a1:0093:0031:00b9:0031:00a3:00e7:0046:0092:0043:00d1:00f9:0031:0033:0031:0033:0051:0093:0051:00a9:0031:00a9:0041
#RLC5 00'25'971;00LC5;90f26004 0000787:0001:0023:0071:0063:0031:0155:0031:0139:0031:01d9:0021:0179:0031:0064:006c:0038:0029:0171:0063:0091:0033:0061:00e9:0041:0029:0031:0093:0081:0079:0091:00a9:0051:0019:0061:0039:0031:0099:0031:0029:0041:0089:0041:0029:0031:0049:0031:0019:0071:0029:0031:0193:0031:00a3:0021:00d3:0051:0063:0021:0139:0068:001c:0070:0028:0059:00b1:0033:00d1:0043:0041:0043:0051:0319:00d1:0043:0051:0189:0061:0029:0031:0099:0031:00b5:0051:00c9:0051:0039:0051:0049:0061:0039:0041:0169:0051:0105:0031:01f3:0031:0053:0012:0076:0062:0043:0101:00b9:0021
#RLCtiny2 00'05'181;00LCtiny2;833ee4b2 0000157:0011:0320:0034:00a0:00d4:00f0
#RLCtiny3 00'12'342;00LCtiny3;df0bd8ce
#RLCtiny1 00'12'276;00LCtiny1;ae1ab677 0000372:0001:02e9:0021:01e9:0051:00c9:0151:0073:0091:0059:0051:0073:0041:00a9:0031:0033:0031:0063:0031:0063:0021:0023:0087:0073:0131:0023:00a1:0069:0091:0103:0031:0205:0021:00b3:0091:0113:0021:00b9:0031:0053:0051:0039

183
frontend_x11.c Normal file
View file

@ -0,0 +1,183 @@
/** @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
#define DATA_FILE_NAME "data"
#include "game.h"
char framebuffer[LCR_SETTING_RESOLUTION_X * LCR_SETTING_RESOLUTION_Y * 4];
FILE *dataFile = 0;
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;
}
char LCR_getNextDataFileChar(void)
{
if (!dataFile)
return 0;
int c = fgetc(dataFile);
if (c == EOF)
{
rewind(dataFile);
return 0;
}
return c;
}
void LCR_appendDataStr(const char *str)
{
if (!dataFile)
return;
if (str == 0 || *str == 0)
rewind(dataFile);
else
{
fclose(dataFile);
dataFile = fopen(DATA_FILE_NAME,"a");
if (dataFile)
{
fprintf(dataFile,"%s",str);
fclose(dataFile);
dataFile = fopen(DATA_FILE_NAME,"r");
}
}
}
uint8_t LCR_keyPressed(uint8_t key)
{
return buttonStates[key % 8];
}
void LCR_sleep(uint16_t timeMs)
{
usleep(timeMs * 1000);
}
void LCR_log(const char *str)
{
printf("LOG: %s\n",str);
}
int main(int argc, char **argv)
{
int running = 1;
struct timeval now;
LCR_gameInit(argc,(const char **) argv);
Display *display = XOpenDisplay(0);
int screen = DefaultScreen(display);
dataFile = fopen(DATA_FILE_NAME,"r");
if (!dataFile)
LCR_log("couldn't open data file");
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);
if (dataFile)
fclose(dataFile);
LCR_gameEnd();
return 0;
}

24
make.sh
View file

@ -30,30 +30,36 @@ if [ $# -gt 0 ]; then
fi
if [ $PLATFORM = "sdl" ]; then
# PC SDL build, requires:
# - SDL2 (dev) package
# PC SDL build, requires: SDL2 (dev) package
# preferred, should support all features
SDL_FLAGS=`sdl2-config --cflags --libs`
COMMAND="${COMPILER} ${C_FLAGS} frontend_sdl.c -I/usr/local/include ${SDL_FLAGS}"
elif [ $PLATFORM = "csfml" ]; then
# PC CMFML build, requires:
# - csfml (dev) package
# PC CMFML build, requires: csfml (dev) package
# similar to SDL, should support all features
COMMAND="${COMPILER} ${C_FLAGS} frontend_csfml.c -lcsfml-graphics -lcsfml-window -lcsfml-system -lcsfml-audio"
elif [ $PLATFORM = "saf" ]; then
# SAF build, requires:
# - saf.h
# - backend libraries (SDL2 by default)
# SAF build, requires: saf.h, backend libraries (SDL2 by default)
# limited by SAF (low resoulution, few colors, no files, simple sound, ...)
SDL_FLAGS=`sdl2-config --cflags --libs`
COMMAND="${COMPILER} ${C_FLAGS} frontend_saf.c -lcsfml-graphics -I/use/local/include ${SDL_FLAGS}"
elif [ $PLATFORM = "test" ]; then
# autotest build
# unplayable, only serves for development
COMMAND="${COMPILER} ${C_FLAGS} frontend_test.c"
elif [ $PLATFORM = "x11" ]; then
# X11 build, requires: xlib
# has no sound
COMMAND="${COMPILER} ${C_FLAGS} -lX11 frontend_x11.c"
elif [ $PLATFORM = "emscripten" ]; then
# emscripten (browser Javascript) build, requires:
# - emscripten
# emscripten (browser Javascript) build, requires: emscripten
# limited, low quality, no files
COMMAND="../emsdk/upstream/emscripten/emcc ./frontend_sdl.c -s USE_SDL=2 -O3 -lopenal --shell-file HTMLshell.html -o licar.html -s EXPORTED_FUNCTIONS='[\"_main\"]' -s EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'"
else
echo "unknown frontend"