From 6193bceb749cb6dc31e1ba6a295348049c5d66a7 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Tue, 21 Nov 2023 07:07:50 +0000 Subject: [PATCH] music stop; sprite alpha blending; sprite sorting; change to anim --- Makefile | 79 ++++++++++++++++--------------------- docs/building.md | 7 +++- scripts/components.js | 15 ++++--- scripts/entity.js | 11 +++--- source/engine/gameobject.c | 13 ++++++ source/engine/gameobject.h | 4 ++ source/engine/jsffi.c | 9 +++++ source/engine/sound/music.h | 1 + source/engine/sprite.c | 43 +++++++++++++------- source/engine/sprite.h | 1 + source/engine/yugine.c | 20 ++++++++++ source/shaders/sprite.sglsl | 7 +++- 12 files changed, 136 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index 89d2134..36e0e6a 100755 --- a/Makefile +++ b/Makefile @@ -31,36 +31,35 @@ ifeq ($(CC), x86_64-w64-mingw32-gcc) endif ifdef NEDITOR - CFLAGS += -DNO_EDITOR + CPPFLAGS += -DNO_EDITOR endif ifdef NFLAC - CFLAGS += -DNFLAC + CPPFLAGS += -DNFLAC endif ifdef NMP3 - CFLAGS += -DNMP3 + CPPFLAGS += -DNMP3 endif ifdef NSVG - CFLAGS += -DNSVG + CPPFLAGS += -DNSVG endif ifdef NQOA - CFLAGS += -DNQOA + CPPFLAGS += -DNQOA endif ifeq ($(DBG),1) - CFLAGS += -g + CPPFLAGS += -g INFO += _dbg - LDFLAGS += -g else - CFLAGS += -DNDEBUG + CPPFLAGS += -DNDEBUG LDFLAGS += -s endif ifeq ($(OPT),small) - CFLAGS += -Oz -flto -fno-ident -fno-asynchronous-unwind-tables + CPPFLAGS += -Oz -flto -fno-ident -fno-asynchronous-unwind-tables LDFLAGS += -flto ifeq ($(CC), emcc) @@ -70,15 +69,14 @@ ifeq ($(OPT),small) INFO := $(addsuffix _small,$(INFO)) else ifeq ($(OPT), 1) - CFLAGS += -O2 -flto - LDFLAGS += -flto + CPPFLAGS += -O2 -flto INFO := $(addsuffix _opt,$(INFO)) else - CFLAGS += -O0 + CPPFLAGS += -O0 endif endif -CFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DTINYSPLINE_FLOAT_PRECISION -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(VER)\" -DINFO=\"$(INFO)\" +CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DTINYSPLINE_FLOAT_PRECISION -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(VER)\" -DINFO=\"$(INFO)\" PKGCMD = tar --directory $(BIN) --exclude="./*.a" --exclude="./obj" -czf $(DISTDIR)/$(DIST) . ZIP = .tar.gz @@ -89,32 +87,32 @@ ifeq ($(ARCH),) endif STEAMPATH = steam/sdk/redistributable_bin +DISCORDPATH = discord/lib + +ifdef DISCORD + LDPATHS += $(DISCORDPATH)/$(ARCH) + LDLIBS += discord_game_sdk + CPPFLAGS += -DDISCORD +endif + +ifdef STEAM + LDLIBS += steam_api + LDPATHS += $(STEAMPATH)/$(ARCH) +endif ifeq ($(OS), Windows_NT) - LDFLAGS += -mwin32 -static -g - CFLAGS += -mwin32 -g + LDFLAGS += -mwin32 -static + CPPFLAGS += -mwin32 LDLIBS += mingw32 kernel32 d3d11 user32 shell32 dxgi gdi32 ws2_32 ole32 winmm setupapi m EXT = .exe ARCH := x86_64 PKGCMD = cd $(BIN); zip -q -r $(MAKEDIR)/$(DISTDIR)/$(DIST) . -x \*.a ./obj/\* ZIP = .zip UNZIP = unzip -o -q $(DISTDIR)/$(DIST) -d $(DESTDIR) - - ifdef STEAM - LDPATHS += $(STEAMPATH)/win64 - LDLIBS += steam_api64 - endif - -else ifeq ($(OS), ios) - TTARGET = arm64-apple-ios13.1 - SYSRT := /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk - CFLAGS += --target=$(TTARGET) -isysroot $(SYSRT) -DTARGET_OS_IPHONE -x objective-c - LDFLAGS += --target=$(TTARGET) -isysroot $(SYSRT) -framework Foundation -framework UIKit -framework Metal -framework MetalKit -framework AudioToolbox -framework AVFoundation - else ifeq ($(CC), emcc) OS := Web LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -pthread -sTOTAL_MEMORY=450MB - CFLAGS += -pthread + CPPFLAGS += -pthread LDLIBS += pthread quickjs GL openal c m dl CC = emcc EXT = .html @@ -125,21 +123,14 @@ else OS := Linux LDFLAGS += -pthread -rdynamic LDLIBS += GL pthread c m dl X11 Xi Xcursor EGL asound - - ifdef STEAM - LDLIBS += steam_api - LDPATHS += $(STEAMPATH)/linux64 - endif endif ifeq ($(UNAME), Darwin) OS := macos - CFLAGS += -arch $(ARCH) -x objective-c - LDFLAGS += -arch $(ARCH) -framework Cocoa -framework QuartzCore -framework AudioToolbox -framework Metal -framework MetalKit - ifdef STEAM - LDPATHS += $(STEAMPATH)/osx - LDLIBS += steam_api - endif + CPPFLAGS += -arch $(ARCH) + CFLAGS += -x objective-c + CXXFLAGS += -std=c++11 + LDFLAGS += -framework Cocoa -framework QuartzCore -framework AudioToolbox -framework Metal -framework MetalKit endif endif @@ -168,7 +159,7 @@ includeflag := $(addprefix -I, $(includeflag)) # Adding different SDKs ifdef STEAM includeflag += -Isteam/sdk/public - CFLAGS += -DSTEAM + CPPFLAGS += -DSTEAM # BIN += /steam endif @@ -204,7 +195,7 @@ install: $(BIN)/$(NAME) $(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a @echo Linking $(NAME) - $(LD) $^ $(LDFLAGS) -L$(BIN) $(LDPATHS) $(LDLIBS) -o $@ + $(LD) $^ $(CPPFLAGS) $(LDFLAGS) -L$(BIN) $(LDPATHS) $(LDLIBS) -o $@ @echo Finished build $(DISTDIR)/$(DIST): $(BIN)/$(NAME) @@ -257,17 +248,17 @@ $(BIN)/libquickjs.a: $(QUICKJS_O) $(OBJDIR)/%.o: %.c @mkdir -p $(@D) @echo Making C object $@ - @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ $(OBJDIR)/%.o: %.cpp @mkdir -p $(@D) @echo Making C++ object $@ with $(CXX) - @$(CXX) $(CFLAGS) -c $< -o $@ + @$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ $(OBJDIR)/%.o: %.m @mkdir -p $(@D) @echo Making Objective-C object $@ - @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ shaders: $(SHADERS) @echo Making shaders diff --git a/docs/building.md b/docs/building.md index e10da63..82cfc22 100644 --- a/docs/building.md +++ b/docs/building.md @@ -33,6 +33,11 @@ Basic boolean flags, set to 0 or 1, to enable or disable features in the build ## Building for Steam -Get the steam SDK -Unpack it into a folder named 'steam' at the top level directory + -Move the steam libs into the lib folders arm64, x86, and x86_64 -Make with STEAM=1 -Steam uses a C++ based SDK, so a C-only compiler like TCC will not work. \ No newline at end of file +Steam uses a C++ based SDK, so a C-only compiler like TCC will not work. + +## Building with Discord + -Get the steam SDK + -Make with DISCORD=1 \ No newline at end of file diff --git a/scripts/components.js b/scripts/components.js index 3f609f4..259449d 100644 --- a/scripts/components.js +++ b/scripts/components.js @@ -98,6 +98,7 @@ component.sprite.impl = { set pos(x) { cmd(37,this.id,x); }, set layer(x) { cmd(60, this.id, x); }, get layer() { return undefined; }, + emissive(x) { cmd(170, this.id, x); }, boundingbox() { return cwh2bb([0,0],[0,0]); @@ -251,7 +252,7 @@ SpriteAnim.find.doc = 'Given a path, find the relevant animation for the file.'; /* Container to play sprites and anim2ds */ component.char2d = Object.create(component.sprite); -Object.assign(component.char2d, { +component.char2dimpl = { boundingbox() { var dim = this.acur.dim.slice(); dim = dim.scale(this.gameobject.scale); @@ -273,8 +274,7 @@ Object.assign(component.char2d, { play_anim(anim) { this.acur = anim; this.frame = 0; - this.timer.time = this.acur.frames[this.frame].time; - this.timer.start(); + this.gameobject.delay(this.advance.bind(this), this.acur.frames[this.frame].time); this.setsprite(); }, @@ -303,9 +303,7 @@ Object.assign(component.char2d, { advance() { this.frame = (this.frame + 1) % this.acur.frames.length; this.setsprite(); - - if (this.frame === 0 && !this.acur.loop) - this.timer.pause(); + this.gameobject.delay(this.advance.bind(this), this.acur.frames[this.frame].time); }, devance() { @@ -329,7 +327,6 @@ Object.assign(component.char2d, { }, kill() { - this.timer.kill(); cmd(9, this.id); }, @@ -351,7 +348,9 @@ Object.assign(component.char2d, { } Object.hide(this, 'acur'); }, -}); +}; + +Object.assign(component.char2d, component.char2dimpl); component.char2d.doc = { doc: "An animation player for sprites.", diff --git a/scripts/entity.js b/scripts/entity.js index 95414bb..8ffc3d0 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -108,6 +108,10 @@ var gameobject = { if (!this.level) return this.worldpos(); return this.level.world2this(this.worldpos()); }, + + get draw_layer() { return cmd(171, this.body); }, + set draw_layer(x) { cmd(172, this.body, x); }, + get elasticity() { return cmd(107,this.body); }, set elasticity(x) { cmd(106,this.body,x); }, @@ -130,10 +134,6 @@ var gameobject = { set phys(x) { set_body(1, this.body, x); }, get phys() { return q_body(0,this.body); }, -// set mask(x) { cmd(41, this.body, x); }, -// get mask() { return cmd(43, this.body); }, -// set category(x) { cmd(40, this.body, x); }, -// get category() { return cmd(42, this.body); }, get velocity() { return q_body(3, this.body); }, set velocity(x) { set_body(9, this.body, x); }, // get damping() { return cmd(157,this.body); }, @@ -225,10 +225,10 @@ var gameobject = { delete this.objects[obj.toString()]; delete this[obj.toString()]; }, + }, - draw_layer: 1, components: {}, objects: {}, level: undefined, @@ -345,6 +345,7 @@ var gameobject = { max_angularvelocity: Infinity, mass:1, layer:0, + draw_layer:0, worldpos() { return [0,0]; }, save:true, diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index c896ec5..7bcb0a4 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -137,6 +137,18 @@ HMM_Vec2 mat_t_dir(HMM_Mat3 m, HMM_Vec2 dir) return HMM_MulM3V3(m, (HMM_Vec3){dir.x, dir.y, 1}).XY; } +HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos) +{ + return HMM_MulM4V4(m, (HMM_Vec4){pos.X, pos.Y, pos.Z, 1}).XYZ; +} + +HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir) +{ + m.Columns[4] = (HMM_Vec4){0,0,0,1}; + return mat3_t_pos(m, dir); +} + + HMM_Vec2 goscale(struct gameobject *go, HMM_Vec2 pos) { return HMM_MulV2(go->scale.XY, pos); @@ -301,6 +313,7 @@ int MakeGameobject() { .mass = 1.f, .next = -1, .sensor = 0, + .drawlayer = 0, .shape_cbs = NULL, .gravity = 1, .cgravity = (HMM_Vec2){0,0}, diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h index bb8c904..6c6f691 100644 --- a/source/engine/gameobject.h +++ b/source/engine/gameobject.h @@ -46,6 +46,7 @@ typedef struct gameobject { HMM_Mat3 transform; struct gameobject *master; transform2d t; /* The local transformation of this object */ + float drawlayer; } gameobject; extern struct gameobject *gameobjects; @@ -77,6 +78,9 @@ HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos); /* Transform a direction via the matrix - does not take into account translation of matrix */ HMM_Vec2 mat_t_dir(HMM_Mat3 m, HMM_Vec2 dir); +HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos); +HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir); + struct gameobject *get_gameobject_from_id(int id); struct gameobject *id2go(int id); int id_from_gameobject(struct gameobject *go); diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index e44aa43..8528329 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -1181,6 +1181,15 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) case 169: ret = num2js(js2go(argv[1])->timescale); break; + case 170: + id2sprite(js2int(argv[1]))->emissive = js2color(argv[2]); + break; + case 171: + ret = num2js(js2go(argv[1])->drawlayer); + break; + case 172: + js2go(argv[1])->drawlayer = js2number(argv[2]); + break; } if (str) diff --git a/source/engine/sound/music.h b/source/engine/sound/music.h index cf64b34..d5d47c4 100644 --- a/source/engine/sound/music.h +++ b/source/engine/sound/music.h @@ -13,5 +13,6 @@ struct dsp_midi_song { void play_song(const char *midi, const char *sf); void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n); +void music_stop(); #endif diff --git a/source/engine/sprite.c b/source/engine/sprite.c index c2ff9a9..144d463 100644 --- a/source/engine/sprite.c +++ b/source/engine/sprite.c @@ -30,6 +30,7 @@ struct sprite_vert { HMM_Vec2 pos; HMM_Vec2 uv; struct rgba color; + struct rgba emissive; }; static int num_spriteverts = 5000; @@ -54,6 +55,7 @@ struct slice9_vert { int make_sprite(int go) { struct sprite sprite = { .color = color_white, + .emissive = {0,0,0,0}, .size = {1.f, 1.f}, .tex = texture_loadfromfile(NULL), .go = go, @@ -115,21 +117,30 @@ void sprite_io(struct sprite *sprite, FILE *f, int read) { } } +int sprite_sort(int *a, int *b) +{ + struct gameobject *goa = id2go(sprites[*a].go); + struct gameobject *gob = id2go(sprites[*b].go); + if (goa->drawlayer == gob->drawlayer) return 0; + if (goa->drawlayer > gob->drawlayer) return 1; + return -1; +} + void sprite_draw_all() { sg_apply_pipeline(pip_sprite); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection)); - static struct sprite **layers[5]; - - for (int i = 0; i < 5; i++) - arrfree(layers[i]); + static int *layers; + if (layers) arrfree(layers); for (int i = 0; i < arrlen(sprites); i++) - if (sprites[i].go >= 0 && sprites[i].enabled) arrpush(layers[sprites[i].layer], &sprites[i]); - + if (sprites[i].go >= 0 && sprites[i].enabled) arrpush(layers, i); - for (int i = 4; i >= 0; i--) - for (int j = 0; j < arrlen(layers[i]); j++) - sprite_draw(layers[i][j]); + if (arrlen(layers) == 0) return; + if (arrlen(layers) > 1) + qsort(layers, arrlen(layers), sizeof(*layers), sprite_sort); + + for (int i = 0; i < arrlen(layers); i++) + sprite_draw(&sprites[layers[i]]); } void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) { @@ -151,9 +162,11 @@ void sprite_initialize() { .attrs = { [0].format = SG_VERTEXFORMAT_FLOAT2, [1].format = SG_VERTEXFORMAT_FLOAT2, - [2].format = SG_VERTEXFORMAT_UBYTE4N}}, + [2].format = SG_VERTEXFORMAT_UBYTE4N, + [3].format = SG_VERTEXFORMAT_UBYTE4N}}, .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP, .label = "sprite pipeline", + .colors[0].blend = blend_trans, .depth = { .write_enabled = true, .compare = SG_COMPAREFUNC_LESS_EQUAL, @@ -192,7 +205,7 @@ void sprite_initialize() { } /* offset given in texture offset, so -0.5,-0.5 results in it being centered */ -void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, float wrapscale) { +void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba emissive) { struct sprite_vert verts[4]; HMM_Vec2 sposes[4] = { @@ -208,9 +221,9 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo }; for (int i = 0; i < 4; i++) { - HMM_Vec3 v = HMM_MulM3V3(m, (HMM_Vec3){sposes[i].X, sposes[i].Y, 1.0}); - verts[i].pos = (HMM_Vec2){v.X, v.Y}; + verts[i].pos = mat_t_pos(m, sposes[i]); verts[i].color = color; + verts[i].emissive = emissive; } if (!wrap) { @@ -257,7 +270,7 @@ void sprite_draw(struct sprite *sprite) { HMM_Mat3 sm = HMM_MulM3(ss, ts); m = HMM_MulM3(m, sm); - tex_draw(sprite->tex, m, sprite->frame, sprite->color, 0, (HMM_Vec2){0,0}, 0); + tex_draw(sprite->tex, m, sprite->frame, sprite->color, 0, (HMM_Vec2){0,0}, 0, sprite->emissive); } } @@ -275,7 +288,7 @@ void gui_draw_img(const char *img, HMM_Vec2 pos, HMM_Vec2 scale, float angle, in t.pos = pos; t.angle = angle; t.scale = scale; - tex_draw(tex, transform2d2mat(t), tex_get_rect(tex), color, wrap, wrapoffset, wrapscale); + tex_draw(tex, transform2d2mat(t), tex_get_rect(tex), color, wrap, wrapoffset, wrapscale, (struct rgba){0,0,0,0}); } void slice9_draw(const char *img, HMM_Vec2 pos, HMM_Vec2 dimensions, struct rgba color) diff --git a/source/engine/sprite.h b/source/engine/sprite.h index 2600667..24455b0 100644 --- a/source/engine/sprite.h +++ b/source/engine/sprite.h @@ -15,6 +15,7 @@ struct sprite { HMM_Vec2 size; float rotation; struct rgba color; + struct rgba emissive; int go; /* id of gameobject */ struct Texture *tex; struct glrect frame; diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 1336be7..cb8b92d 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -36,6 +36,10 @@ #include "steamffi.h" #endif +#ifdef DISCORD +#include "discord.h" +#endif + #include "string.h" #include "render.h" @@ -349,6 +353,22 @@ int main(int argc, char **argv) { #ifdef STEAM steaminit(); +#endif + +#ifdef DISCORD +struct IDiscordCore *core; +DiscordCreate(DISCORD_VERSION, &(struct DiscordCreateParams){ + .client_id = 1176355046590533714, + .flags = DiscordCreateFlags_Default +}, &core); +struct IDiscordUserManager *dum; +struct IDiscordActivityManager *dam; +dam = core->get_activity_manager(core); + +struct DiscordActivity da; +sprintf(da.state, "Playing Solo Pinball"); +sprintf(da.details, "COMPetitive"); +dam->update_activity(dam, &da, NULL, NULL); #endif stm_setup(); /* time */ diff --git a/source/shaders/sprite.sglsl b/source/shaders/sprite.sglsl index 60272d3..7b83b47 100644 --- a/source/shaders/sprite.sglsl +++ b/source/shaders/sprite.sglsl @@ -2,15 +2,18 @@ in vec2 vertex; in vec2 uv; in vec4 vc; +in vec4 emissive; out vec2 texcoords; out vec4 fcolor; +out vec4 femissive; uniform vs_p { mat4 proj; }; void main() { fcolor = vc; + femissive = emissive; texcoords = uv; gl_Position = proj * vec4(vertex, 0.0, 1.0); } @@ -19,6 +22,7 @@ void main() @fs fs in vec2 texcoords; in vec4 fcolor; +in vec4 femissive; out vec4 color; uniform texture2D image; @@ -31,7 +35,8 @@ void main() if (color.a <= 0.1f) discard; - color *=fcolor; + color *= fcolor; + color.xyz = mix(color.xyz, femissive.xyz, femissive.a); } @end