Clean up a bit

This commit is contained in:
Miloslav Ciz 2025-06-19 02:28:51 +02:00
parent 610c1df0b0
commit a104a12cc4
14 changed files with 207 additions and 62 deletions

View file

@ -12,9 +12,10 @@
supplied via the external data file.
NOTES:
- All images are 64x64, stored in an indexed mode (8bits pery pixel), the
image starts with a 256 color palette in RGB565 format (i.e. the palette
takes 512 bytes, then 64x64 bytes follow).
- All images are 64x64, stored in an indexed mode (8bits per pixel), the image
starts with a 256 color palette in RGB565 format (i.e. the palette takes 512
bytes, then 64x64 bytes follow).
- Each sky (background) image is composed of 4 regular images so they have
higher resolution. The partial images are stored in the above format, one
sky part consists of interlaced lines, so it effectively stores a 128x32
@ -30,17 +31,17 @@
#define LCR_MODULE_NAME "asset"
#define LCR_VERSION "0.1d"
static const char *LCR_texts[] =
{
#define LCR_TEXTS_VERSION 0
"0.5d", // version string
LCR_VERSION, // version string
#define LCR_TEXTS_TABS 1
"main menu",
"play map",
"view repl",
"race repl",
#define LCR_TEXTS_MAIN_MENU 5
"camera",
"music",
@ -55,8 +56,6 @@ static const char *LCR_texts[] =
"failed"
};
#define LCR_VERSION "0.1d"
/// String that can be used by frontends to offer help about CLI arguments.
#define LCR_ARG_HELP_STR \
" -cN set camera mode to N\n" \

View file

@ -1,5 +1,6 @@
/** @file frontend_csfml.c
CSFML frontend for Licar.
CSFML frontend for Licar, alternative to SDL.
*/
#include <SFML/Audio.h>

View file

@ -80,9 +80,7 @@ void LCR_appendDataStr(const char *str)
void setup()
{
// *((volatile uint32_t *) 0x60000900) &= ~(1); // disable watchdog
wdt_disable();
wdt_disable(); // disable watchdog
dac.begin(MCP4725address);
delay(100);

View file

@ -1,12 +1,13 @@
/** @file frontend_helper.h
Helper file for generic PC frontends that can use the stdio library, to avoid
duplication of code.
duplication of code. Just include it.
*/
#include <stdint.h>
#include <stdio.h>
// Before including this file, it's possible to define a quality preset:
#if PRESET_QUALITY == 1 // ultra low
#define LCR_SETTING_RESOLUTION_X 256
#define LCR_SETTING_RESOLUTION_Y 200
@ -86,7 +87,7 @@ void LCR_appendDataStr(const char *str)
else
{
#if LCR_SETTING_LOG_LEVEL > 1
printf("SDL: appending data \"%s\"\n",str);
printf("appending data: \"%s\"\n",str);
#endif
fclose(dataFile);

118
frontend_pokitto.cpp Normal file
View file

@ -0,0 +1,118 @@
/** @file frontend_pokitto.cpp
Experimental Pokitto frontend, very limited.
*/
#include "../PokittoLib/Pokitto/Pokitto.h"
#define LCR_SETTING_RESOLUTION_X 110
#define LCR_SETTING_RESOLUTION_Y 88
#define LCR_SETTING_RESOLUTION_SUBDIVIDE 2
#define LCR_SETTING_MUSIC 0
#define LCR_SETTING_GHOST_MAX_SAMPLES 0
#define LCR_SETTING_332_COLOR 1
#define LCR_SETTING_MAP_MAX_BLOCKS 280
#define LCR_SETTING_MAX_MAP_VERTICES 200
#define LCR_SETTING_MAX_MAP_TRIANGLES 300
#define LCR_SETTING_REPLAY_MAX_SIZE 0
#define LCR_SETTING_CAR_SHADOW 0
#define LCR_SETTING_PARTICLES 0
#define LCR_SETTING_LOD_DISTANCE 100
#define LCR_SETTING_CAR_ANIMATION_SUBDIVIDE 0
#define LCR_SETTING_FPS 20
#define LCR_SETTING_ENABLE_DATA_FILE 0
#define LCR_SETTING_ONLY_SMALL_MAPS 1
#define S3L_SORT 0
#define S3L_Z_BUFFER 0
#define S3L_MAX_TRIANGES_DRAWN 16
#define LCR_SETTING_POTATO_GRAPHICS 1
static const uint16_t palette[256] = // 332 palette as 565
{
0x0000, 0x000a, 0x0015, 0x001f, 0x0120, 0x012a, 0x0135, 0x013f, 0x0240, 0x024a,
0x0255, 0x025f, 0x0360, 0x036a, 0x0375, 0x037f, 0x0480, 0x048a, 0x0495, 0x049f,
0x05a0, 0x05aa, 0x05b5, 0x05bf, 0x06c0, 0x06ca, 0x06d5, 0x06df, 0x07e0, 0x07ea,
0x07f5, 0x07ff, 0x2000, 0x200a, 0x2015, 0x201f, 0x2120, 0x212a, 0x2135, 0x213f,
0x2240, 0x224a, 0x2255, 0x225f, 0x2360, 0x236a, 0x2375, 0x237f, 0x2480, 0x248a,
0x2495, 0x249f, 0x25a0, 0x25aa, 0x25b5, 0x25bf, 0x26c0, 0x26ca, 0x26d5, 0x26df,
0x27e0, 0x27ea, 0x27f5, 0x27ff, 0x4800, 0x480a, 0x4815, 0x481f, 0x4920, 0x492a,
0x4935, 0x493f, 0x4a40, 0x4a4a, 0x4a55, 0x4a5f, 0x4b60, 0x4b6a, 0x4b75, 0x4b7f,
0x4c80, 0x4c8a, 0x4c95, 0x4c9f, 0x4da0, 0x4daa, 0x4db5, 0x4dbf, 0x4ec0, 0x4eca,
0x4ed5, 0x4edf, 0x4fe0, 0x4fea, 0x4ff5, 0x4fff, 0x6800, 0x680a, 0x6815, 0x681f,
0x6920, 0x692a, 0x6935, 0x693f, 0x6a40, 0x6a4a, 0x6a55, 0x6a5f, 0x6b60, 0x6b6a,
0x6b75, 0x6b7f, 0x6c80, 0x6c8a, 0x6c95, 0x6c9f, 0x6da0, 0x6daa, 0x6db5, 0x6dbf,
0x6ec0, 0x6eca, 0x6ed5, 0x6edf, 0x6fe0, 0x6fea, 0x6ff5, 0x6fff, 0x9000, 0x900a,
0x9015, 0x901f, 0x9120, 0x912a, 0x9135, 0x913f, 0x9240, 0x924a, 0x9255, 0x925f,
0x9360, 0x936a, 0x9375, 0x937f, 0x9480, 0x948a, 0x9495, 0x949f, 0x95a0, 0x95aa,
0x95b5, 0x95bf, 0x96c0, 0x96ca, 0x96d5, 0x96df, 0x97e0, 0x97ea, 0x97f5, 0x97ff,
0xb000, 0xb00a, 0xb015, 0xb01f, 0xb120, 0xb12a, 0xb135, 0xb13f, 0xb240, 0xb24a,
0xb255, 0xb25f, 0xb360, 0xb36a, 0xb375, 0xb37f, 0xb480, 0xb48a, 0xb495, 0xb49f,
0xb5a0, 0xb5aa, 0xb5b5, 0xb5bf, 0xb6c0, 0xb6ca, 0xb6d5, 0xb6df, 0xb7e0, 0xb7ea,
0xb7f5, 0xb7ff, 0xd800, 0xd80a, 0xd815, 0xd81f, 0xd920, 0xd92a, 0xd935, 0xd93f,
0xda40, 0xda4a, 0xda55, 0xda5f, 0xdb60, 0xdb6a, 0xdb75, 0xdb7f, 0xdc80, 0xdc8a,
0xdc95, 0xdc9f, 0xdda0, 0xddaa, 0xddb5, 0xddbf, 0xdec0, 0xdeca, 0xded5, 0xdedf,
0xdfe0, 0xdfea, 0xdff5, 0xdfff, 0xf800, 0xf80a, 0xf815, 0xf81f, 0xf920, 0xf92a,
0xf935, 0xf93f, 0xfa40, 0xfa4a, 0xfa55, 0xfa5f, 0xfb60, 0xfb6a, 0xfb75, 0xfb7f,
0xfc80, 0xfc8a, 0xfc95, 0xfc9f, 0xfda0, 0xfdaa, 0xfdb5, 0xfdbf, 0xfec0, 0xfeca,
0xfed5, 0xfedf, 0xffe0, 0xffea, 0xfff5, 0xffff
};
#include "game.h"
Pokitto::Core pokitto;
uint8_t *pokittoScreen;
void LCR_drawPixel(unsigned long index, uint16_t color)
{
pokittoScreen[index] = color;
}
void LCR_sleep(uint16_t timeMs)
{
}
uint8_t LCR_keyPressed(uint8_t key)
{
switch (key)
{
case LCR_KEY_UP: return pokitto.upBtn(); break;
case LCR_KEY_DOWN: return pokitto.downBtn(); break;
case LCR_KEY_RIGHT: return pokitto.rightBtn(); break;
case LCR_KEY_LEFT: return pokitto.leftBtn(); break;
case LCR_KEY_A: return pokitto.aBtn(); break;
case LCR_KEY_B: return pokitto.bBtn() || pokitto.cBtn(); break;
default: return 0; break;
}
}
char LCR_getNextDataFileChar(void)
{
return 0;
}
void LCR_appendDataStr(const char *str)
{
return;
}
int main(void)
{
pokitto.begin();
pokitto.setFrameRate(255);
pokitto.display.setFont(fontTiny);
pokitto.display.persistence = 1;
pokitto.display.setInvisibleColor(-1);
pokitto.display.load565Palette(palette);
pokittoScreen = pokitto.display.screenbuffer;
LCR_gameInit(0,0);
while (pokitto.isRunning())
if (pokitto.update())
if (!LCR_gameStep(pokitto.getTime()))
break;
LCR_gameEnd();
pokitto.quit();
return 0;
}

View file

@ -72,14 +72,9 @@ void LCR_appendDataStr(const char *str)
return;
}
//Oscillator *osc;
void setup()
{
mp.begin();
// osc = new Oscillator(SINE);
// addOscillator(osc);
// SFG_init();
LCR_gameInit(0,0);
}
@ -91,8 +86,6 @@ void loop()
((mp.buttons.getJoystickY() < 200)) << 2 |
((mp.buttons.getJoystickY() > 900)) << 3;
// SFG_mainLoopBody();
LCR_gameStep(millis());
mp.update();

View file

@ -1,5 +1,6 @@
/** @file frontend_saf.c
SAF frontend for Licar.
SAF frontend for Licar, just for fun (probably not seriously playable).
*/
#define SAF_PLATFORM_SDL2

View file

@ -1,5 +1,8 @@
/** @file frontend_sdl.c
SDL2 frontend for Licar.
SDL2 frontend for Licar. This is the number one frontend, most advanced and
with most features -- if a platform supports SDL2, this should probably be
used.
*/
#include <stdio.h>
@ -8,7 +11,9 @@
#define LCR_SETTING_LOG_LEVEL 2
#define LCR_LOADING_COMMAND SDL_PumpEvents();
#define LCR_FPS_GET_MS SDL_GetTicks() // uncomment for FPS measuring
#if 0
#define LCR_FPS_GET_MS SDL_GetTicks() // enabling will log FPS in console
#endif
#ifdef __EMSCRIPTEN__
#define LCR_SETTING_RESOLUTION_X 512

View file

@ -1,5 +1,6 @@
/** @file frontend_sdl.c
X11 frontend for Licar.
X11 frontend for Licar, has no sound.
*/
#include <X11/Xlib.h>

View file

@ -5,10 +5,10 @@
Licar: general
This file holds general definitions used by all modules.
This file holds general definitions used by all Licar modules.
All Licar code uses LCR_ (or _LCR_) prefix as a kind of namespace preventing
collision with 3rd party identifiers.
collisions with 3rd party identifiers.
*/
#include <stdint.h>
@ -74,7 +74,7 @@ int _LCR_hexDigitVal(char c)
}
/**
Computes simple hash of a string represented by a function returning next
Computes a simple hash of a string represented by a function returning next
string character, ending at 0 or endChar. This is intended for simple (but
not 100% reliable) string comparison.
*/

4
map.h
View file

@ -31,8 +31,8 @@
following are characters signifying numbers 0 to 63:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$@
- M is optional block material ('0' to '3', 0 is default).
- T is an optinal transform string (for more detail see the binary format)
consisting from 0 to 3 characters, which may be:
- T is an optional transform string (for more detail see the binary
format) consisting of 0 to 3 characters, which may be:
- '|': flip horizontally
- '-': flip vertically
- 'L': rotate 90 degrees

View file

@ -1,5 +1,3 @@
WORK IN PROGRESS
'-._-'"'-_.-'"'-._.-'"'-._.-'"'- LICAR MANUAL -'"'-._.-'"'-._.-'"'-._.-'"'-._.-'
libre racing video game by drummyfish (drummyfish@disroot.org)
@ -83,9 +81,9 @@ right). There are two additional keys, A and B (depending on your platform these
may be e.g. K and L keys, RETURN and ESCAPE etc.), for restarting runs and
handling menu.
~~~~~ GAMPLAY TIPS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~ GAMEPLAY TIPS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here are some tips:
Here are some tips for playing:
- It's possible to stop the car from rotating mid-air by pressing brake.
- Similarly, holding down brake in air will slow down the car's horizontal
@ -150,30 +148,34 @@ different settings.
~~~~~ REPLAYS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If your platform supports it, Licar can save and play back recorded runs as
"replays" (sometimes also called "demos"), which are just exact records of game
inputs (so that replays, unlike videos, take very little space). Replays can
also be used to spawn a ghost car to race against.
"replays" (sometimes also called "demos") which are nothing else than exact
records of game input keys (so that replays, unlike videos, take very little
space). Replays can also be used to spawn a ghost car to race against. There
are special tabs in the menu to view a replay or race against a replay ghost.
Replays are saved in the data file.
Replays are saved in the data file (see the section about data file for
details).
Whenever a map's target time is beaten, replay is automatically saved. It's also
possible to save a replay manually by opening the menu and selecting
"save replay".
"save replay" after finishing a map. To share or add replays you can simply copy
replay strings to/from the data file with any text editor. Similarly to delete a
replay you just delete it in the data file.
~~~~~ GHOSTS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The game supports ghost cars to race against (note that this may be unsupported
on some weaker platforms). A ghost car is created from a replay and will race
in real time against the player, without being able to collide with him. This is
on some weaker platforms). A ghost car is created from a replay and will race in
real time against the player, without being able to collide with him. This is
very useful when attacking someone else's (or one's own) achieved time, to see
where exactly time losses against the opponent occur.
~~~~~ MAKING CUSTOM MAPS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Maps are stored in the data file. For its simplicity the original game doesn't
come with a user-friendly map editor, the maps are hand-written directly in the
text format that's stored in the data file, however there is a helper file for
Blender that facilitates this process.
come with a user-friendly map editor (perhaps some will be made over time), the
maps are hand-written directly in the text format that's stored in the data
file, however there is a helper file for Blender that facilitates this process.
In the game a map is represented as a 64x64x64 grid, with each cell one unit in
width, one unit in depth and HALF a unit in height. In the cell blocks can be
@ -195,12 +197,12 @@ details you won't find here. In summary:
First, if the map is preceded by another data string in the data file, remember
to start it with the `#` character (to separate it from the previous string).
Then there must be the letter `M` (for map), and the immediately the map's name
Then there must be the letter `M` (for map), and then immediately the map's name
terminated with `;`. For example a map named "mymap" will in the data file
start with "#Mmymap;". Then the map string itself follows.
This string starts with a decimal number saying the target time in physics
ticks, then a space (` `) follows, then a single digit saying the map
ticks, then a space (` `) follows, then a single digit specifying the map
environment (`0`, `1` or `2`), and then the string of map blocks follows.
Each map block starts with `:`, then immediately follows the type of the block
@ -213,9 +215,9 @@ this:
I.e. number 11 will be encoded as `b` etc. After the coordinates an optional
decimal digit MAY follow, which defines the block material (`0`, `1`, `2` or
`3`, `0` being default). Finally there MAY follow the transformation string,
which may consists of characters `|` (flip horizontally), `-` (flip vertically),
which may consist of characters `|` (flip horizontally), `-` (flip vertically),
`L` (rotate by 90 degrees), `I` (rotate by 180 degrees and `J` (rotate by 270
degrees). For example ":^5dA1-L" represents a ramp (`^`) placed on coordinates
degrees). For example ":^5dA1-L" represents a ramp (`^`) placed at coordinates
5, 13, 36, having material 1 (grass), flipped vertically (`-`) and rotated by
180 degrees (`I`).
@ -282,15 +284,40 @@ A few tips for making maps:
~~~~~ COMPILING AND MODIFYING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mods are highly recommended to be distributed as diff files that will apply
changes to the source code. This is inspired by suckless programs.
Mods are highly recommended to be distributed as context-aware diff files that
will apply changes to the base source code. This is inspired by suckless
programs. Distributing software in source form (preferably licensed as free
software), as opposed to compiled binaries, is highly advised, in Licar and
elsewhere :)
TODO
Compiling the code depends on platform, but in general is done by simply
compiling the platform's front end. For example the SDL2 frontend is compiled
just by handing frontend_sdl.c to any C99 compiler (of course with appropriate
flags, e.g. linking the SDL library). There is a Unix script that helps with
compiling: make.sh. On many systems you can compile the game just by running
the script. Otherwise read the script to learn about the details (flags etc.).
Understanding the code: the code is highly commented and meant to serve as its
own documentation, so first read the code. There is also a Doxygen file that can
help you easily generate reference pages. Otherwise the code is pretty
straightforward and shouldn't be too hard to understand (there is no OOP, no
3rd party libraries, ...). It is in some ways unique, but always in a way that
makes it easier to work with: for example the whole game is implemented solely
in header files so that you compile only a single file: your frontend. I.e. no
headaches with linking etc. The code follows the suckless philosophy and also
what's called LRS (less retarded software): check these out to learn more.
Porting and making your own frontends is quite easy, you just write a program
in C (or a compatible language such as C++) in which you include the game's
backend code (literally just #include "game.h") and implement a few basic
functions such as a function for drawing pixels or reading keyboard. Exact
details about this are documented in game.h.
~~~~~ CREDITS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Everything was created by drummyfish. Special thanks goes to my friends Blitz
and Ramon for help with testing <3
Everything was created by drummyfish, down to making own photo textures and
recording own samples for music in the soundtrack. Special thanks goes to my
friends Blitz and Ramon for help with testing and providing some ideas <3
~~~~~ FAQ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -314,7 +341,7 @@ that's meant to help the people.
Q: Can I still voluntarily donate money?
A: Currently it is possible, donation info is somewhere on my website, but I am
not dependant on donations and am sometimes doubting if it's a good thing to
not dependent on donations and am sometimes doubting if it's a good thing to
accept them, but if you still insist, I'll be very grateful, thank you very
much.

View file

@ -41,8 +41,8 @@
i.e. the series of 16 bit words in hexadecimal, each preceded by ':'. The
events (but nothing else) may otherwise be preceded or followed by other
characters (possible comments). All hexadecimal letters must be lowercase.
The word 00000000 may optinally be used to terminate the replay, the rest of
the string will be ignored.
The word 00000000 may optionally be used to terminate the replay, the rest
of the string will be ignored.
- Physics engine version: LCR_RACING_VERSION1 and LCR_RACING_VERSION2 define
a two-character version string of this module that determines compatibility
of replays. Whenever a change is made to this module that changes the
@ -81,11 +81,12 @@ typedef int32_t LCR_GameUnit; ///< Abstract game unit.
#define LCR_PHYSICS_UNIT 4096 ///< Len. of square for phys. engine.
/* The combination of values TPE_RESHAPE_TENSION_LIMIT and
TPE_RESHAPE_ITERATIONS has crucial effect on the bugginess and feel of car
physics, especially when driving onto ramps in high speed etc., the values
were chosen empirically by testing, these are the ones that showed to
subjectively feel the best. */
/*
The combination of values TPE_RESHAPE_TENSION_LIMIT and TPE_RESHAPE_ITERATIONS
has crucial effect on the bugginess and feel of car physics, especially when
driving onto ramps in high speed etc., the values were chosen empirically by
testing, these are the ones that showed to subjectively feel the best.
*/
#define TPE_RESHAPE_TENSION_LIMIT 7
#define TPE_RESHAPE_ITERATIONS 18

View file

@ -150,7 +150,7 @@ struct
polygons will be drawn without texture,
with color stored in this variable. */
#if LCR_SETTING_PARTICLES
uint_fast16_t particleColor; /**< 0x0000 means no particles active. */
uint_fast16_t particleColor; ///< 0x0000 means no particles active.
#endif
} LCR_renderer;