#include "sokol/sokol_app.h" #include "sokol/sokol_gfx.h" #include "sokol/sokol_log.h" #include "sokol/sokol_glue.h" #include "flecs.h" #include "app.h" #include "scene_manager.h" #include "scenes/menu_scene.h" #include "scenes/game_scene.h" #include "shaders/triangle-sapp.glsl.h" #include "ecs_core.h" static struct { sg_pipeline pipeline; sg_bindings bind; sg_pass_action pass_action; } state; static ecs_world_t* ecs_world; static app_context_t app_ctx; static void draw_square(float x, float y, float size, float r, float g, float b, float a) { const float s = size; float z = 0.5f; // Two triangles (6 vertices), each vertex: pos xyz + color rgba float v[6 * 7] = { // tri 1 x - s, y - s, z, r, g, b, a, x + s, y - s, z, r, g, b, a, x + s, y + s, z, r, g, b, a, // tri 2 x - s, y - s, z, r, g, b, a, x + s, y + s, z, r, g, b, a, x - s, y + s, z, r, g, b, a, }; sg_range rng = { .ptr = v, .size = sizeof(v) }; sg_update_buffer(state.bind.vertex_buffers[0], &rng); sg_apply_pipeline(state.pipeline); sg_apply_bindings(&state.bind); sg_draw(0, 6, 1); } static void init(void) { ecs_world = ecs_init(); sg_setup(&(sg_desc){ .environment = sglue_environment(), .logger.func = slog_func, }); // Create a dynamic vertex buffer large enough for one quad (6 vertices) state.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ .usage = { .vertex_buffer = true, .stream_update = true }, .size = (size_t)(sizeof(float) * 6 * 7), }); state.pipeline = sg_make_pipeline(&(sg_pipeline_desc){ .shader = sg_make_shader(triangle_shader_desc(sg_query_backend())), .layout = { .attrs = { [ATTR_triangle_position].format = SG_VERTEXFORMAT_FLOAT3, [ATTR_triangle_color0].format = SG_VERTEXFORMAT_FLOAT4 } }, }); state.pass_action = (sg_pass_action) { .colors[0] = { .load_action=SG_LOADACTION_CLEAR, .clear_value={0.0f, 0.0f, 0.0f, 1.0f } } }; app_ctx.world = ecs_world; app_ctx.pass_action = &state.pass_action; ecs_core_set_draw_api(draw_square); scene_manager_init(&app_ctx); scene_manager_set(&MenuScene); } void frame(void) { float dt = (float)sapp_frame_duration(); sg_begin_pass(&(sg_pass){ .action = state.pass_action, .swapchain = sglue_swapchain() }); scene_manager_update(dt); scene_manager_render(); sg_end_pass(); sg_commit(); } void cleanup(void) { scene_manager_shutdown(); sg_shutdown(); ecs_fini(ecs_world); } void event(const sapp_event* ev) { scene_manager_event(ev); } sapp_desc sokol_main(int argc, char* argv[]) { (void)argc; (void)argv; return (sapp_desc){ .init_cb = init, .frame_cb = frame, .cleanup_cb = cleanup, .event_cb = event, .width = 640, .height = 480, .window_title = "Triangle", .high_dpi = true, .html5 = { .canvas_resize = false, // track CSS size; sokol scales to devicePixelRatio }, .icon.sokol_default = true, .logger.func = slog_func, }; }