First commit

This commit is contained in:
Fierelier 2023-05-14 12:21:03 +02:00
commit e45dd56e85
12 changed files with 650 additions and 0 deletions

6
assets/scripts/main.lua Normal file
View File

@ -0,0 +1,6 @@
texture = engine_loadTexture("assets/textures/fier0.rgba",8,32)
a = 0
function engine_onFrame()
engine_renderTexture2D(texture,math.random(-8,102),math.random(-8,72))
end

BIN
assets/textures/fier0.rgba Normal file

Binary file not shown.

BIN
assets/textures/fier1.rgba Normal file

Binary file not shown.

BIN
assets/textures/fier2.rgba Normal file

Binary file not shown.

BIN
engine Executable file

Binary file not shown.

49
main.c Normal file
View File

@ -0,0 +1,49 @@
#include <stdio.h>
#include <stdlib.h>
#include "modules/engine/main.c"
#include "modules/engine/frontend/sdl/main.c"
#include "modules/engine/frontend/generic/textures.c"
#include "modules/engine/addon/lua.c"
void handleEvent(struct ENGINE_EVENT event) {
if (event.type == ENGINE_EVENT_TYPE_EXIT) {
exit(0);
}
}
int frame = 0;
int frameSec = 0;
Uint32 lastSec = 0;
void tick() {
frame += 1;
frameSec += 1;
unsigned long tick = engine_time_get();
if (tick - lastSec >= 1000) {
printf("FPS: %d\n",frameSec);
lastSec = tick;
frameSec = 0;
}
luaL_loadstring(engine_lua_state,"engine_onFrame()");
lua_call(engine_lua_state,0,0);
engine_render();
//engine_sleep(33);
}
int main(int argc, char **argv) {
for (int i = 0; i < argc; ++i) {
printf("argv[%d]: %s\n", i, argv[i]);
}
engine_init(96,64,"Game");
engine_luaInit();
while (1) {
struct ENGINE_EVENT event = engine_getEvent();
if (event.type != ENGINE_EVENT_TYPE_NONE) {
handleEvent(event);
} else {
tick();
}
}
}

View File

@ -0,0 +1,51 @@
#include <lua5.3/lua.h>
#include <lua5.3/lualib.h>
#include <lua5.3/lauxlib.h>
lua_State * engine_lua_state;
int engine_luafSleep(lua_State *L) {
int time = luaL_checkinteger(L,1);
engine_sleep(time);
return 0;
}
int engine_luafTimeGet(lua_State *L) {
lua_pushinteger(L,engine_time_get());
return 1;
}
int engine_luafLoadTexture(lua_State *L) {
char * fpath = (char *)luaL_checkstring(L,1);
int width = luaL_checkinteger(L,2);
int height = luaL_checkinteger(L,3);
struct ENGINE_TEXTURE * texture = engine_createTexture(width,height);
engine_fileToTexture(texture,fpath);
lua_pushlightuserdata(L,texture);
return 1;
}
int engine_luafRenderTexture2D(lua_State *L) {
struct ENGINE_TEXTURE * texture = (struct ENGINE_TEXTURE *)lua_touserdata(L,1);
int x = luaL_checkinteger(L,2);
int y = luaL_checkinteger(L,3);
engine_renderTexture2D(texture,x,y);
return 0;
}
void engine_luaInit() {
engine_lua_state = luaL_newstate();
luaL_openlibs(engine_lua_state);
// Functions
lua_pushcfunction(engine_lua_state,engine_luafSleep);
lua_setglobal (engine_lua_state,"engine_sleep");
lua_pushcfunction(engine_lua_state,engine_luafLoadTexture);
lua_setglobal (engine_lua_state,"engine_loadTexture");
lua_pushcfunction(engine_lua_state,engine_luafRenderTexture2D);
lua_setglobal (engine_lua_state,"engine_renderTexture2D");
// Start user script
luaL_loadfile(engine_lua_state,"assets/scripts/main.lua");
lua_call(engine_lua_state,0,0);
}

View File

@ -0,0 +1,78 @@
// Mostly for fun (but can very slightly increase performance for large textures). If set to 1, does not clear texture's affiliated and leaves garbage.
#define ENGINE_GENERIC_TEXTURE_NOCLEAR 1
struct ENGINE_TEXTURE { int width; int height; void * fe_texture; };
struct ENGINE_GENERIC_TEXTURE { char * pixels; };
struct ENGINE_TEXTURE * engine_createTexture(int width,int height) {
// frontend texture
char * pixels = engine_malloc(NULL,sizeof(char) * width * height * 4);
#if (ENGINE_GENERIC_TEXTURE_NOCLEAR == 0)
memset(pixels,0,sizeof(char) * width * height * 4);
#endif
struct ENGINE_GENERIC_TEXTURE * fe_texture = engine_malloc(NULL,sizeof(struct ENGINE_GENERIC_TEXTURE));
fe_texture->pixels = pixels;
// engine texture
struct ENGINE_TEXTURE * texture = engine_malloc(NULL,sizeof(struct ENGINE_TEXTURE));
texture->width = width;
texture->height = height;
texture->fe_texture = (void *)fe_texture;
return texture;
}
struct ENGINE_GENERIC_TEXTURE_COLOR { char r; char g; char b; char a; };
struct ENGINE_GENERIC_TEXTURE_COLOR engine_generic_texture_color;
void engine_textureSetColor(char r,char g,char b,char a) {
engine_generic_texture_color.r = r;
engine_generic_texture_color.g = g;
engine_generic_texture_color.b = b;
engine_generic_texture_color.a = a;
}
void engine_textureDrawPixel(struct ENGINE_TEXTURE * texture,int x,int y) {
char * pixels = ((struct ENGINE_GENERIC_TEXTURE *)(texture->fe_texture))->pixels;
long pixelIndex = (x + y * texture->width) * 4;
pixels[pixelIndex + 0] = engine_generic_texture_color.r;
pixels[pixelIndex + 1] = engine_generic_texture_color.g;
pixels[pixelIndex + 2] = engine_generic_texture_color.b;
pixels[pixelIndex + 3] = engine_generic_texture_color.a;
}
void engine_textureDestroy(struct ENGINE_TEXTURE * texture) {
struct ENGINE_GENERIC_TEXTURE * fe_texture = (struct ENGINE_GENERIC_TEXTURE *)(texture->fe_texture);
engine_free(fe_texture->pixels);
engine_free(fe_texture);
engine_free(texture);
}
void engine_renderTexture2D(struct ENGINE_TEXTURE * texture,int sx,int sy) {
char * pixels = ((struct ENGINE_GENERIC_TEXTURE *)(texture->fe_texture))->pixels;
int ex = sx + texture->width;
if (ex > engine_width) { ex = engine_width; }
int ey = sy + texture->height;
if (ey > engine_width) { ey = engine_height; }
int x = sx;
if (x < 0) { x = 0; }
int y = sy;
if (y < 0) { y = 0; }
long pixelIndex = 0;
while (y < ey) {
while (x < ex) {
pixelIndex = ((x - sx) + (y - sy) * texture->width)*4;
engine_setColor(pixels[pixelIndex],pixels[pixelIndex + 1],pixels[pixelIndex + 2],pixels[pixelIndex + 3]);
engine_drawPixel(x,y);
++x;
}
x = sx;
++y;
}
}
void engine_fileToTexture(struct ENGINE_TEXTURE * texture,char * fpath) {
FILE * f = fopen(fpath,"r");
fgets(((struct ENGINE_GENERIC_TEXTURE *)(texture->fe_texture))->pixels,texture->width * texture->height,f);
fclose(f);
}

View File

@ -0,0 +1,296 @@
// With much thanks to https://benedicthenshaw.com/soft_render_sdl2.html
// --- SETTINGS ---
// BUFFER
// How to buffer pixels.
// 0: Use SDL_Surface (fastest in software)
// 1: Use SDL_Renderer (slow?)
// TODO: Add support for GPU texture
#define ENGINE_SDL_BUFFERTYPE 0
// TRANSPARENCY
// How to draw transparent pixels (SDL_Surface buffer only).
// 0: Do not handle transparency (Fastest but non-square textures will have a halo around them)
// 1: 1-bit transparency (Alpha values under 128 are not drawn)
// 2: 8-bit transparency (Nice but slow)
// TODO: Add support for SDL_Renderer
#define ENGINE_SDL_TRANSPARENCY 1
// --- HACKS ---
// BUFFER
// Use static color conversion. This will speed up rendering, however, the wrong colors may be displayed depending on platform. This only has an effect if ENGINE_SDL_BUFFERTYPE is set to 0.
// 0 = Disable
// 1 = RGBA (raw)
// 2 = BGRA (common)
// TODO: Add custom mode with quicker conversion of known types, and slow conversion for unknown types.
#define ENGINE_SDL_COLOR 2
// INTEGER UPSCALING
// 2 makes the surface scaled 2x, 3 = 3x, etc.
// TODO: Fix ENGINE_SDL_TRANSPARENCY 2
#define ENGINE_SDL_SCALE 5
// SKIP: COLOR
// Skip setting colors every X requests. Set to 2 to skip every second request, 3 for every third, etc.
#define ENGINE_SDL_SKIP_COLOR_INTERVAL 0 // 2
// How many requests to skip, when a skip is encountered.
#define ENGINE_SDL_SKIP_COLOR_AMOUNT 2
// Whether to alternate fields. TODO
#define ENGINE_SDL_SKIP_COLOR_ALTERNATE 0
// SKIP: PIXEL
// Skip setting pixel every X requests.
#define ENGINE_SDL_SKIP_PIXEL_INTERVAL 0 // 2
#define ENGINE_SDL_SKIP_PIXEL_AMOUNT 2
#define ENGINE_SDL_SKIP_PIXEL_ALTERNATE 0
// SKIP: FRAME
#define ENGINE_SDL_SKIP_FRAME_INTERVAL 1
#define ENGINE_SDL_SKIP_FRAME_AMOUNT 1
// Entirely skip changing any colors and pixels on skipped frames, without this, this is pretty useless
#define ENGINE_SDL_SKIP_FRAME_DROP 0
// DO NOT TOUCH THESE
#if (ENGINE_SDL_SKIP_COLOR_INTERVAL > 0 && ENGINE_SDL_SKIP_COLOR_AMOUNT > 0)
#define ENGINE_SDL_SKIP_COLOR 1
#endif
#if (ENGINE_SDL_SKIP_PIXEL_INTERVAL > 0 && ENGINE_SDL_SKIP_PIXEL_AMOUNT > 0)
#define ENGINE_SDL_SKIP_PIXEL 1
#endif
#if (ENGINE_SDL_SKIP_FRAME_INTERVAL > 0 && ENGINE_SDL_SKIP_FRAME_AMOUNT > 0)
#define ENGINE_SDL_SKIP_FRAME 1
#endif
#include <SDL2/SDL.h>
SDL_Window * engine_sdl_window;
#if (ENGINE_SDL_BUFFERTYPE == 0)
SDL_Surface * engine_sdl_surface;
Uint32 * engine_sdl_pixels;
#endif
#if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_Renderer * engine_sdl_renderer;
#endif
int engine_width = 0;
int engine_height = 0;
struct ENGINE_EVENT engine_getEvent() {
struct ENGINE_EVENT event;
SDL_Event sdlevent;
if (!SDL_PollEvent(&sdlevent)) {
struct ENGINE_EVENT_NONE data;
event.type = ENGINE_EVENT_TYPE_NONE;
event.data = &data;
return event;
}
if (sdlevent.type == SDL_QUIT) {
struct ENGINE_EVENT_EXIT data;
event.type = ENGINE_EVENT_TYPE_EXIT;
event.data = &data;
return event;
}
if (sdlevent.type == SDL_KEYDOWN || sdlevent.type == SDL_KEYUP) {
if (sdlevent.key.repeat != 0) { goto unknown; }
struct ENGINE_EVENT_INPUTKB data;
data.pressed = (sdlevent.type == SDL_KEYDOWN);
data.key = sdlevent.key.keysym.scancode;
event.type = ENGINE_EVENT_TYPE_INPUTKB;
event.data = &data;
return event;
}
unknown:
struct ENGINE_EVENT_UNKNOWN data;
event.type = ENGINE_EVENT_TYPE_UNKNOWN;
event.data = &data;
return event;
}
void engine_sleep(long long ms) {
SDL_Delay(ms);
}
long long engine_time_get() {
return SDL_GetTicks();
}
#ifdef ENGINE_SDL_SKIP_FRAME
char engine_sdl_skipf_interval = 0;
char engine_sdl_skipf_amount = 0;
#endif
#ifdef ENGINE_SDL_SKIP_COLOR
char engine_sdl_skipc_interval = 0;
char engine_sdl_skipc_amount = 0;
#endif
Uint32 engine_sdl_color;
void engine_setColor(char r,char g,char b,char a) {
#ifdef ENGINE_SDL_SKIP_COLOR
if (engine_sdl_skipc_interval == 0) {
if (engine_sdl_skipc_amount == 0) {
engine_sdl_skipc_interval = ENGINE_SDL_SKIP_COLOR_INTERVAL - 1;
engine_sdl_skipc_amount = ENGINE_SDL_SKIP_COLOR_AMOUNT;
} else {
--engine_sdl_skipc_amount;
return;
}
} else {
--engine_sdl_skipc_interval;
}
#endif
#if (ENGINE_SDL_SKIP_FRAME == 1 && ENGINE_SDL_SKIP_FRAME_DROP == 1)
if (engine_sdl_skipf_interval == 0 && engine_sdl_skipf_amount > 0) {
return;
}
#endif
#if (ENGINE_SDL_BUFFERTYPE == 0)
#if (ENGINE_SDL_COLOR != 0 || ENGINE_SDL_TRANSPARENCY > 0)
Uint8 * rawcolor = (Uint8 *)&engine_sdl_color; // is doing this ok?
#endif
#if (ENGINE_SDL_COLOR == 1)
rawcolor[0] = (Uint8)r;
rawcolor[1] = (Uint8)g;
rawcolor[2] = (Uint8)b;
rawcolor[3] = (Uint8)a;
#elif (ENGINE_SDL_COLOR == 2)
rawcolor[0] = (Uint8)b;
rawcolor[1] = (Uint8)g;
rawcolor[2] = (Uint8)r;
rawcolor[3] = (Uint8)a;
#else
engine_sdl_color = SDL_MapRGBA(engine_sdl_surface->format,(Uint8)r,(Uint8)g,(Uint8)b,(Uint8)a);
#if (ENGINE_SDL_TRANSPARENCY > 0)
rawcolor[3] = (Uint8)a;
#endif
#endif
#endif
#if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_SetRenderDrawColor(engine_sdl_renderer,r,g,b,a);
#endif
}
#ifdef ENGINE_SDL_SKIP_PIXEL
char engine_sdl_skipp_interval = 0;
char engine_sdl_skipp_amount = 0;
#endif
void engine_drawPixel(int x,int y) {
#ifdef ENGINE_SDL_SKIP_PIXEL
if (engine_sdl_skipp_interval == 0) {
if (engine_sdl_skipp_amount == 0) {
engine_sdl_skipp_interval = ENGINE_SDL_SKIP_PIXEL_INTERVAL - 1;
engine_sdl_skipp_amount = ENGINE_SDL_SKIP_PIXEL_AMOUNT;
} else {
--engine_sdl_skipp_amount;
return;
}
} else {
--engine_sdl_skipp_interval;
}
#endif
#if (ENGINE_SDL_SKIP_FRAME == 1 && ENGINE_SDL_SKIP_FRAME_DROP == 1)
if (engine_sdl_skipf_interval == 0 && engine_sdl_skipf_amount > 0) {
return;
}
#endif
#if (ENGINE_SDL_BUFFERTYPE == 0)
#if (ENGINE_SDL_TRANSPARENCY == 1)
if (((Uint8 *)&engine_sdl_color)[3] < 128) { // is doing this ok?
return;
}
#endif
#if (ENGINE_SDL_TRANSPARENCY == 2)
Uint8 * rawcolor = (Uint8 *)&engine_sdl_color;
if (rawcolor[3] < 255) {
Uint8 * sourcecolor = (Uint8 *)&engine_sdl_pixels[x + y * engine_width];
float alpha = (float)rawcolor[3] / 255;
sourcecolor[0] = sourcecolor[0] + ((rawcolor[0] - sourcecolor[0])*alpha);
sourcecolor[1] = sourcecolor[1] + ((rawcolor[1] - sourcecolor[1])*alpha);
sourcecolor[2] = sourcecolor[2] + ((rawcolor[2] - sourcecolor[2])*alpha);
return;
}
#endif
#if (ENGINE_SDL_SCALE == 1)
engine_sdl_pixels[x + y * engine_width] = engine_sdl_color;
#else
char xi = 0;
while (xi < ENGINE_SDL_SCALE) {
char yi = 0;
while (yi < ENGINE_SDL_SCALE) {
engine_sdl_pixels[((x * ENGINE_SDL_SCALE) + xi) + ((y * ENGINE_SDL_SCALE) + yi) * (engine_width * ENGINE_SDL_SCALE)] = engine_sdl_color;
++yi;
}
++xi;
}
#endif
#endif
#if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_RenderDrawPoint(engine_sdl_renderer,x,y);
#endif
}
void engine_render() {
#ifdef ENGINE_SDL_SKIP_FRAME
if (engine_sdl_skipf_interval == 0) {
if (engine_sdl_skipf_amount == 0) {
engine_sdl_skipf_interval = ENGINE_SDL_SKIP_FRAME_INTERVAL - 1;
engine_sdl_skipf_amount = ENGINE_SDL_SKIP_FRAME_AMOUNT;
} else {
--engine_sdl_skipf_amount;
return;
}
} else {
--engine_sdl_skipf_interval;
}
#endif
#if (ENGINE_SDL_BUFFERTYPE == 0)
SDL_UpdateWindowSurface(engine_sdl_window);
#endif
#if (ENGINE_SDL_BUFFERTYPE == 1)
SDL_RenderPresent(engine_sdl_renderer);
#endif
}
void engine_init(int width,int height,char *title) {
SDL_Init(SDL_INIT_VIDEO);
engine_sdl_window = SDL_CreateWindow(title,SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,width * ENGINE_SDL_SCALE,height * ENGINE_SDL_SCALE,0);
#if (ENGINE_SDL_BUFFERTYPE == 0)
engine_sdl_surface = SDL_GetWindowSurface(engine_sdl_window);
engine_sdl_pixels = engine_sdl_surface->pixels;
#endif
#if (ENGINE_SDL_BUFFERTYPE == 1)
engine_sdl_renderer = SDL_CreateRenderer(engine_sdl_window,-1,0);
#endif
engine_width = width;
engine_height = height;
#if (ENGINE_SDL_BUFFERTYPE == 1)
engine_setColor(0,0,0,255);
#ifdef ENGINE_SDL_SKIP_COLOR
engine_sdl_skipc_interval = 0;
engine_sdl_skipc_amount = 0;
#endif
SDL_RenderClear(engine_sdl_renderer);
#endif
}

22
modules/engine/main.c Normal file
View File

@ -0,0 +1,22 @@
struct ENGINE_EVENT { char type; void * data; };
static char ENGINE_EVENT_TYPE_UNKNOWN = 0;
struct ENGINE_EVENT_UNKNOWN { };
static char ENGINE_EVENT_TYPE_NONE = 1;
struct ENGINE_EVENT_NONE { };
static char ENGINE_EVENT_TYPE_EXIT = 2;
struct ENGINE_EVENT_EXIT { };
static char ENGINE_EVENT_TYPE_INPUTKB = 2;
struct ENGINE_EVENT_INPUTKB { char key; char pressed; };
void * engine_malloc(void * pnt,size_t size) {
void * mem = realloc(pnt,size);
if (mem == NULL) {
printf("ERROR: Could not allocate memory.\n");
exit(1);
}
return mem;
}
void engine_free(void *pnt) {
free(pnt);
}

4
run Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -e
gcc main.c -g -lSDL2 -llua5.3 -o engine -O3 -Werror -Wall
exec ./engine

144
test.c Normal file
View File

@ -0,0 +1,144 @@
#include <stdio.h>
#include <stdlib.h>
#include "modules/engine/main.c"
#include "modules/engine/frontend/sdl/main.c"
#include "modules/engine/frontend/generic/textures.c"
//#include "modules/engine/frontend/sdl/textures.c" // TODO
void handleEvent(struct ENGINE_EVENT event) {
if (event.type == ENGINE_EVENT_TYPE_EXIT) {
exit(0);
}
}
int frame = 0;
int frameSec = 0;
Uint32 lastSec = 0;
char tr, tg, tb;
struct ENGINE_TEXTURE * texture;
void tick() {
int y = 0;
while (y < engine_height) {
int x = 0;
while (x < engine_width) {
/*tr = (char)(x + y) + ((char)frame * 1);
tg = (char)(x + y) + ((char)frame * 3);
tb = (char)(x + y) + ((char)frame * 5);*/
/*tr = (char)(x + y) * (char)frame * 1;
tg = (char)(x + y) * (char)frame * 3;
tb = (char)(x + y) * (char)frame * 5;*/
tr = (char)((x * y) + 64) + frame;
tg = (char)((x * y) + 128) + frame;
tb = (char)((x * y) + 192) + frame;
/*int part = engine_width / 3;
if (x < part * 1) {
tr = 255;
tg = 0;
tb = 0;
} else if (x < part * 2) {
tr = 0;
tg = 255;
tb = 0;
} else {
tr = 0;
tg = 0;
tb = 255;
}*/
/*tr = 0;
tg = 255 - ((char)((x * y) + 128) + frame);
tb = 0;*/
/*tr = (char)(((float)x / (float)engine_width) * 255);
tg = 255 - tr;
tb = (char)(((float)y / (float)engine_height) * 255);*/
engine_setColor(tr,tg,tb,255);
engine_drawPixel(x,y);
++x;
}
++y;
}
//y = 0;
//while (y < engine_height) {
// int x = 0;
// while (x < engine_width) {
// tr = (char)(x + y) + ((char)frame * 1);
// tg = (char)(x + y) + ((char)frame * 3);
// tb = (char)(x + y) + ((char)frame * 5);
/*tr = (char)(x + y) * (char)frame * 1;
tg = (char)(x + y) * (char)frame * 3;
tb = (char)(x + y) * (char)frame * 5;*/
/*tr = (char)((x * y) + 64) + frame;
tg = (char)((x * y) + 128) + frame;
tb = (char)((x * y) + 192) + frame;*/
/*int part = engine_width / 3;
if (x < part * 1) {
tr = 255;
tg = 0;
tb = 0;
} else if (x < part * 2) {
tr = 0;
tg = 255;
tb = 0;
} else {
tr = 0;
tg = 0;
tb = 255;
}*/
/*tr = 0;
tg = 255 - ((char)((x * y) + 128) + frame);
tb = 0;*/
/*tr = (char)(((float)x / (float)engine_width) * 255);
tg = 255 - tr;
tb = (char)(((float)y / (float)engine_height) * 255);*/
// engine_setColor(tr,tg,tb,128);
// engine_drawPixel(x,y);
// ++x;
// }
// ++y;
//}
engine_renderTexture2D(texture,5,5);
frame += 1;
frameSec += 1;
Uint32 tick = SDL_GetTicks();
if (tick - lastSec >= 1000) {
printf("FPS: %d\n",frameSec);
lastSec = tick;
frameSec = 0;
}
engine_render();
//engine_sleep(33);
}
int main(int argc, char **argv) {
texture = engine_createTexture(8,8);
engine_fileToTexture(texture,"assets/textures/fier.rgba");
for (int i = 0; i < argc; ++i) {
printf("argv[%d]: %s\n", i, argv[i]);
}
engine_init(256,256,"Game");
while (1) {
struct ENGINE_EVENT event = engine_getEvent();
if (event.type != ENGINE_EVENT_TYPE_NONE) {
handleEvent(event);
} else {
tick();
}
}
}