]> git.lizzy.rs Git - nothing.git/blobdiff - src/game/level/platforms.c
(#450) Use fmimf fmaxf
[nothing.git] / src / game / level / platforms.c
index 8fe81f34de5d9e060ce51fbd638938c61c5a059b..6a670db9d60138254806bbd3baebf6b84bf30b4f 100644 (file)
-#include <SDL2/SDL.h>
-#include <assert.h>
+#include <SDL.h>
+#include "system/stacktrace.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include "platforms.h"
-#include "system/error.h"
 #include "system/lt.h"
-#include "system/lt/lt_adapters.h"
+#include "system/line_stream.h"
+#include "system/nth_alloc.h"
+#include "system/log.h"
+#include "game/level/level_editor/rect_layer.h"
+#include "math/extrema.h"
 
-struct platforms_t {
-    lt_t *lt;
+struct Platforms {
+    Lt *lt;
 
-    rect_t *rects;
-    color_t *colors;
+    Rect *rects;
+    Color *colors;
     size_t rects_size;
 };
 
-platforms_t *create_platforms_from_stream(FILE *stream)
+Platforms *create_platforms_from_rect_layer(const RectLayer *layer)
 {
-    assert(stream);
+    trace_assert(layer);
 
-    lt_t *const lt = create_lt();
-    if (lt == NULL) {
-        return NULL;
-    }
+    Lt *lt = create_lt();
 
-    platforms_t *platforms = PUSH_LT(lt, malloc(sizeof(platforms_t)), free);
+    Platforms *platforms = PUSH_LT(
+        lt,
+        nth_calloc(1, sizeof(Platforms)),
+        free);
     if (platforms == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
+    platforms->lt = lt;
 
-    platforms->rects_size = 0;
-    if (fscanf(stream, "%lu", &platforms->rects_size) == EOF) {
-        throw_error(ERROR_TYPE_LIBC);
-        RETURN_LT(lt, NULL);
-    }
+    platforms->rects_size = rect_layer_count(layer);
 
-    platforms->rects = PUSH_LT(lt, malloc(sizeof(rect_t) * platforms->rects_size), free);
+    platforms->rects = PUSH_LT(lt, nth_calloc(1, sizeof(Rect) * platforms->rects_size), free);
     if (platforms->rects == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
+    memcpy(platforms->rects, rect_layer_rects(layer), sizeof(Rect) * platforms->rects_size);
 
-    platforms->colors = PUSH_LT(lt, malloc(sizeof(color_t) * platforms->rects_size), free);
+
+    platforms->colors = PUSH_LT(lt, nth_calloc(1, sizeof(Color) * platforms->rects_size), free);
     if (platforms->colors == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
         RETURN_LT(lt, NULL);
     }
-
-    char color[7];
-    for (size_t i = 0; i < platforms->rects_size; ++i) {
-        if (fscanf(stream, "%f%f%f%f%6s\n",
-                   &platforms->rects[i].x, &platforms->rects[i].y,
-                   &platforms->rects[i].w, &platforms->rects[i].h,
-                   color) < 0) {
-            throw_error(ERROR_TYPE_LIBC);
-            RETURN_LT(lt, NULL);
-        }
-        platforms->colors[i] = color_from_hexstr(color);
-    }
-
-    platforms->lt = lt;
+    memcpy(platforms->colors, rect_layer_colors(layer), sizeof(Color) * platforms->rects_size);
 
     return platforms;
 }
 
-platforms_t *create_platforms_from_file(const char *filename)
+void destroy_platforms(Platforms *platforms)
 {
-    assert(filename);
-
-    FILE *platforms_file = fopen(filename, "r");
-    if (platforms_file == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
-        return NULL;
-    }
-
-    platforms_t *platforms = create_platforms_from_stream(platforms_file);
-    if (platforms != NULL) {
-        fclose(platforms_file);
-        return NULL;
-    }
-
-    fclose(platforms_file);
-    return platforms;
-}
-
-void destroy_platforms(platforms_t *platforms)
-{
-    assert(platforms);
+    trace_assert(platforms);
     RETURN_LT0(platforms->lt);
 }
 
-int platforms_save_to_file(const platforms_t *platforms,
-                           const char *filename)
+int platforms_render(const Platforms *platforms,
+                     const Camera *camera)
 {
-    assert(platforms);
-    assert(filename);
-
-    lt_t *const lt = create_lt();
-    if (lt == NULL) {
-        return -1;
-    }
-
-    FILE *platforms_file = PUSH_LT(lt, fopen(filename, "w"), fclose_lt);
-
-    if (platforms_file == NULL) {
-        throw_error(ERROR_TYPE_LIBC);
-        RETURN_LT(lt, -1);
-    }
-
     for (size_t i = 0; i < platforms->rects_size; ++i) {
-        if (fprintf(platforms_file, "%f %f %f %f\n",
-                    platforms->rects[i].x, platforms->rects[i].y,
-                    platforms->rects[i].w, platforms->rects[i].h) < 0) {
-            throw_error(ERROR_TYPE_LIBC);
-            RETURN_LT(lt, -1);
+        Rect platform_rect = platforms->rects[i];
+        if (camera_fill_rect(
+                camera,
+                platform_rect,
+                platforms->colors[i]) < 0) {
+            return -1;
         }
-    }
 
-    RETURN_LT(lt, 0);
-}
-
-solid_ref_t platforms_as_solid(platforms_t *platforms)
-{
-    solid_ref_t ref = {
-        .tag = SOLID_PLATFORMS,
-        .ptr = (void*)platforms
-    };
-
-    return ref;
-}
+        char debug_text[256];
+        snprintf(debug_text, 256,
+            "id:%zd\n"
+            "x:%.2f\n"
+            "y:%.2f\n"
+            "w:%.2f\n"
+            "h:%.2f\n",
+            i, platform_rect.x, platform_rect.y, platform_rect.w, platform_rect.h);
+
+        Vec2f text_pos = (Vec2f){.x = platform_rect.x, .y = platform_rect.y};
+        Rect text_rect = sprite_font_boundary_box(text_pos, vec(2.0f, 2.0f), debug_text);
+
+        Rect world_viewport = camera_view_port(camera);
+        Rect viewport = camera_view_port_screen(camera);
+
+        if (rects_overlap(
+                camera_rect(
+                    camera,
+                    platform_rect),
+                viewport) &&
+            camera_is_point_visible(
+                camera,
+                text_pos) == false) {
+            if (platform_rect.w > text_rect.w){
+                text_pos.x = fmaxf(fminf(world_viewport.x, platform_rect.x + platform_rect.w - text_rect.w),
+                                   platform_rect.x);
+            }
+            if (platform_rect.h > text_rect.h){
+                text_pos.y = fmaxf(fminf(world_viewport.y, platform_rect.y + platform_rect.h - text_rect.h),
+                                   platform_rect.y);
+            }
+        }
 
-int platforms_render(const platforms_t *platforms,
-                     const camera_t *camera)
-{
-    for (size_t i = 0; i < platforms->rects_size; ++i) {
-        if (camera_fill_rect(
+        if (camera_render_debug_text(
                 camera,
-                platforms->rects[i],
-                platforms->colors[i]) < 0) {
-            throw_error(ERROR_TYPE_SDL2);
+                debug_text,
+                text_pos) < 0) {
             return -1;
         }
     }
@@ -149,13 +116,29 @@ int platforms_render(const platforms_t *platforms,
     return 0;
 }
 
-void platforms_touches_rect_sides(const platforms_t *platforms,
-                                  rect_t object,
+void platforms_touches_rect_sides(const Platforms *platforms,
+                                  Rect object,
                                   int sides[RECT_SIDE_N])
 {
-    assert(platforms);
+    trace_assert(platforms);
 
     for (size_t i = 0; i < platforms->rects_size; ++i) {
         rect_object_impact(object, platforms->rects[i], sides);
     }
 }
+
+Vec2f platforms_snap_rect(const Platforms *platforms,
+                         Rect *object)
+{
+    trace_assert(platforms);
+
+    Vec2f result = vec(1.0f, 1.0f);
+    for (size_t i = 0; i < platforms->rects_size; ++i) {
+        if (rects_overlap(platforms->rects[i], *object)) {
+            // TODO(#1161): can we reuse the Level Editor snapping mechanism in physics snapping
+            result = vec_entry_mult(result, rect_snap(platforms->rects[i], object));
+        }
+    }
+
+    return result;
+}