diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 0000000..a8730ba --- /dev/null +++ b/.luarc.json @@ -0,0 +1,19 @@ +{ + "runtime": { + "version": "LuaJIT" + }, + "diagnostics": { + "globals": [ + "pxl8", + "pxl8_gfx", + "pxl8_input", + "pxl8_rng", + "pxl8_sfx", + "pxl8_sys" + ], + "disable": [ + "lowercase-global", + "unbalanced-assignments" + ] + } +} diff --git a/demo/main.fnl b/demo/main.fnl index 7c8d6cd..216ae6e 100644 --- a/demo/main.fnl +++ b/demo/main.fnl @@ -95,7 +95,7 @@ :logo (do (pxl8.clear 0) (when logo-sprite - (pxl8.sprite logo-sprite logo-x logo-y 128 64))) + (pxl8.sprite logo-sprite logo-x logo-y 128 64 (< logo-dx 0) (< logo-dy 0)))) :plasma (pxl8.vfx_plasma time 0.10 0.04 1) diff --git a/src/lua/pxl8.lua b/src/lua/pxl8.lua index 1aafe31..2ca1696 100644 --- a/src/lua/pxl8.lua +++ b/src/lua/pxl8.lua @@ -1,5 +1,3 @@ -local ffi = require("ffi") - local core = require("pxl8.core") local gfx2d = require("pxl8.gfx2d") local input = require("pxl8.input") @@ -13,11 +11,10 @@ local world = require("pxl8.world") local transition = require("pxl8.transition") local anim = require("pxl8.anim") local sfx = require("pxl8.sfx") - -core.init(_pxl8_gfx, _pxl8_input, _pxl8_rng, _pxl8_sfx_mixer, _pxl8_sys) - local pxl8 = {} +core.init(pxl8_gfx, pxl8_input, pxl8_rng, pxl8_sfx, pxl8_sys) + pxl8.get_fps = core.get_fps pxl8.get_height = core.get_height pxl8.get_title = core.get_title diff --git a/src/lua/pxl8/core.lua b/src/lua/pxl8/core.lua index 680a03c..58860f0 100644 --- a/src/lua/pxl8/core.lua +++ b/src/lua/pxl8/core.lua @@ -3,11 +3,11 @@ local C = ffi.C local core = {} -function core.init(gfx, input, rng, sfx_mixer, sys) +function core.init(gfx, input, rng, sfx, sys) core.gfx = gfx core.input = input core.rng = rng - core.sfx_mixer = sfx_mixer + core.sfx = sfx core.sys = sys end diff --git a/src/lua/pxl8/sfx.lua b/src/lua/pxl8/sfx.lua index a1225e9..563bc49 100644 --- a/src/lua/pxl8/sfx.lua +++ b/src/lua/pxl8/sfx.lua @@ -105,15 +105,15 @@ function sfx.delay_set_time(node, time_l, time_r) end function sfx.get_master_volume() - return C.pxl8_sfx_mixer_get_master_volume(core.sfx_mixer) + return C.pxl8_sfx_mixer_get_master_volume(core.sfx) end function sfx.mixer_attach(ctx) - C.pxl8_sfx_mixer_attach(core.sfx_mixer, ctx) + C.pxl8_sfx_mixer_attach(core.sfx, ctx) end function sfx.mixer_detach(ctx) - C.pxl8_sfx_mixer_detach(core.sfx_mixer, ctx) + C.pxl8_sfx_mixer_detach(core.sfx, ctx) end function sfx.node_destroy(node) @@ -154,7 +154,7 @@ function sfx.reverb_set_room(node, room) end function sfx.set_master_volume(volume) - C.pxl8_sfx_mixer_set_master_volume(core.sfx_mixer, volume) + C.pxl8_sfx_mixer_set_master_volume(core.sfx, volume) end function sfx.stop_all(ctx) diff --git a/src/pxl8_gfx.c b/src/pxl8_gfx.c index 5eac152..7e66657 100644 --- a/src/pxl8_gfx.c +++ b/src/pxl8_gfx.c @@ -590,32 +590,33 @@ void pxl8_text(pxl8_gfx* gfx, const char* text, i32 x, i32 y, u32 color) { } -void pxl8_sprite(pxl8_gfx* gfx, u32 sprite_id, i32 x, i32 y, i32 w, i32 h) { +void pxl8_sprite(pxl8_gfx* gfx, u32 sprite_id, i32 x, i32 y, i32 w, i32 h, bool flip_x, bool flip_y) { if (!gfx || !gfx->atlas || !gfx->framebuffer) return; const pxl8_atlas_entry* entry = pxl8_atlas_get_entry(gfx->atlas, sprite_id); if (!entry || !entry->active) return; - + i32 clip_left = (x < 0) ? -x : 0; i32 clip_top = (y < 0) ? -y : 0; i32 clip_right = (x + w > gfx->framebuffer_width) ? x + w - gfx->framebuffer_width : 0; i32 clip_bottom = (y + h > gfx->framebuffer_height) ? y + h - gfx->framebuffer_height : 0; - + i32 draw_width = w - clip_left - clip_right; i32 draw_height = h - clip_top - clip_bottom; - + if (draw_width <= 0 || draw_height <= 0) return; - + i32 dest_x = x + clip_left; i32 dest_y = y + clip_top; bool is_1to1_scale = (w == entry->w && h == entry->h); bool is_unclipped = (clip_left == 0 && clip_top == 0 && clip_right == 0 && clip_bottom == 0); + bool is_flipped = flip_x || flip_y; u32 atlas_width = pxl8_atlas_get_width(gfx->atlas); const u8* atlas_pixels = pxl8_atlas_get_pixels(gfx->atlas); - if (is_1to1_scale && is_unclipped) { + if (is_1to1_scale && is_unclipped && !is_flipped) { if (gfx->pixel_mode == PXL8_PIXEL_HICOLOR) { const u16* sprite_data = (const u16*)atlas_pixels + entry->y * atlas_width + entry->x; pxl8_blit_hicolor( @@ -638,8 +639,12 @@ void pxl8_sprite(pxl8_gfx* gfx, u32 sprite_id, i32 x, i32 y, i32 w, i32 h) { } else { for (i32 py = 0; py < draw_height; py++) { for (i32 px = 0; px < draw_width; px++) { - i32 src_x = entry->x + ((px + clip_left) * entry->w) / w; - i32 src_y = entry->y + ((py + clip_top) * entry->h) / h; + i32 local_x = (px + clip_left) * entry->w / w; + i32 local_y = (py + clip_top) * entry->h / h; + + i32 src_x = flip_x ? entry->x + entry->w - 1 - local_x : entry->x + local_x; + i32 src_y = flip_y ? entry->y + entry->h - 1 - local_y : entry->y + local_y; + i32 src_idx = src_y * atlas_width + src_x; i32 dest_idx = (dest_y + py) * gfx->framebuffer_width + (dest_x + px); diff --git a/src/pxl8_gfx.h b/src/pxl8_gfx.h index 5efd3ac..38f0797 100644 --- a/src/pxl8_gfx.h +++ b/src/pxl8_gfx.h @@ -65,7 +65,7 @@ void pxl8_line(pxl8_gfx* gfx, i32 x0, i32 y0, i32 x1, i32 y1, u32 color); void pxl8_pixel(pxl8_gfx* gfx, i32 x, i32 y, u32 color); void pxl8_rect(pxl8_gfx* gfx, i32 x, i32 y, i32 w, i32 h, u32 color); void pxl8_rect_fill(pxl8_gfx* gfx, i32 x, i32 y, i32 w, i32 h, u32 color); -void pxl8_sprite(pxl8_gfx* gfx, u32 sprite_id, i32 x, i32 y, i32 w, i32 h); +void pxl8_sprite(pxl8_gfx* gfx, u32 sprite_id, i32 x, i32 y, i32 w, i32 h, bool flip_x, bool flip_y); void pxl8_text(pxl8_gfx* gfx, const char* text, i32 x, i32 y, u32 color); void pxl8_3d_clear_zbuffer(pxl8_gfx* gfx); diff --git a/src/pxl8_script.c b/src/pxl8_script.c index bf1f70c..c89d06f 100644 --- a/src/pxl8_script.c +++ b/src/pxl8_script.c @@ -677,7 +677,7 @@ void pxl8_script_set_gfx(pxl8_script* script, pxl8_gfx* gfx) { script->gfx = gfx; if (script->L && gfx) { lua_pushlightuserdata(script->L, gfx); - lua_setglobal(script->L, "_pxl8_gfx"); + lua_setglobal(script->L, "pxl8_gfx"); } } @@ -686,7 +686,7 @@ void pxl8_script_set_input(pxl8_script* script, pxl8_input_state* input) { script->input = input; if (script->L && input) { lua_pushlightuserdata(script->L, input); - lua_setglobal(script->L, "_pxl8_input"); + lua_setglobal(script->L, "pxl8_input"); } } @@ -694,7 +694,7 @@ void pxl8_script_set_rng(pxl8_script* script, void* rng) { if (!script) return; if (script->L && rng) { lua_pushlightuserdata(script->L, rng); - lua_setglobal(script->L, "_pxl8_rng"); + lua_setglobal(script->L, "pxl8_rng"); } } @@ -703,7 +703,7 @@ void pxl8_script_set_sfx(pxl8_script* script, pxl8_sfx_mixer* mixer) { script->mixer = mixer; if (script->L && mixer) { lua_pushlightuserdata(script->L, mixer); - lua_setglobal(script->L, "_pxl8_sfx_mixer"); + lua_setglobal(script->L, "pxl8_sfx"); } } @@ -711,7 +711,7 @@ void pxl8_script_set_sys(pxl8_script* script, void* sys) { if (!script) return; if (script->L && sys) { lua_pushlightuserdata(script->L, sys); - lua_setglobal(script->L, "_pxl8_sys"); + lua_setglobal(script->L, "pxl8_sys"); } } @@ -1049,7 +1049,7 @@ static bool pxl8_script_is_builtin_global(const char* name) { "print", "pxl8", "rawequal", "rawget", "rawset", "require", "select", "setfenv", "setmetatable", "string", "table", "tonumber", "tostring", "type", "unpack", "update", "frame", - "xpcall", "_pxl8_gfx", "_pxl8_input", "_pxl8_rng", "_pxl8_sfx_mixer", "_pxl8_sys", + "xpcall", "pxl8_gfx", "pxl8_input", "pxl8_rng", "pxl8_sfx", "pxl8_sys", NULL }; for (int i = 0; builtins[i]; i++) {