add a tiled game field default tip

Thu, 17 Jul 2025 20:26:39 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 17 Jul 2025 20:26:39 +0200
changeset 213
3d252dbd7c8e
parent 212
90bbacb97cb6

add a tiled game field

src/ascension/scene_node.h file | annotate | diff | comparison | revisions
src/ascension/window.h file | annotate | diff | comparison | revisions
src/window.c file | annotate | diff | comparison | revisions
test/snake/snake.c file | annotate | diff | comparison | revisions
--- a/src/ascension/scene_node.h	Thu Jul 17 20:15:56 2025 +0200
+++ b/src/ascension/scene_node.h	Thu Jul 17 20:26:39 2025 +0200
@@ -272,6 +272,20 @@
     asc_scene_node_update_transform(node);
 }
 
+/**
+ * Sets the z-index of a 2D scene node.
+ *
+ * The index is relative to the parent nodes and by default one.
+ * This means, children of a 2D node by default stack onto the parent node.
+ *
+ * @param node the 2D node
+ * @param n the local z-index (default: 1)
+ */
+static inline void asc_scene_node_set_zindex(AscSceneNode *node, int n) {
+    node->position.z = n*ASC_SCENE_2D_DEPTH_OFFSET;
+    asc_scene_node_update_transform(node);
+}
+
 static inline void asc_scene_node_move2f(AscSceneNode *node, asc_vec2f offset) {
     node->position.x += offset.x;
     node->position.y += offset.y;
--- a/src/ascension/window.h	Thu Jul 17 20:15:56 2025 +0200
+++ b/src/ascension/window.h	Thu Jul 17 20:26:39 2025 +0200
@@ -46,7 +46,7 @@
 
 typedef struct asc_window_settings_s {
     AscGLContextSettings glsettings;
-    asc_vec2i dimensions;
+    asc_vec2u dimensions;
     const char *title;
     bool fullscreen;
 } AscWindowSettings;
--- a/src/window.c	Thu Jul 17 20:15:56 2025 +0200
+++ b/src/window.c	Thu Jul 17 20:26:39 2025 +0200
@@ -32,8 +32,8 @@
 #include <GL/glew.h>
 
 void asc_window_settings_init_defaults(AscWindowSettings *settings) {
-    settings->dimensions.width = 800;
-    settings->dimensions.height = 600;
+    settings->dimensions.width = 800u;
+    settings->dimensions.height = 600u;
     settings->fullscreen = false;
     settings->glsettings.depth_size = 24;
     settings->glsettings.vsync = 1;
--- a/test/snake/snake.c	Thu Jul 17 20:15:56 2025 +0200
+++ b/test/snake/snake.c	Thu Jul 17 20:26:39 2025 +0200
@@ -56,8 +56,15 @@
 
 typedef struct {
     enum MoveDirection direction;
+    /**
+     * The speed in tiles per second.
+     */
+    float speed;
 } Spaceship;
 
+static const unsigned game_field_size = 512;
+static const unsigned game_field_tile_size = 32;
+
 static void init_globals(void) {
     asc_transform_identity(rotations[MOVE_UP]);
     asc_transform_roll(rotations[MOVE_LEFT], asc_rad(-90));
@@ -80,6 +87,24 @@
     asc_gl_context_add_cleanup_func(asc_active_glctx, destroy_textures);
 }
 
+static void scale_backdrop(AscBehavior *behavior) {
+    // scale the backdrop to the size of the window
+    if (asc_active_window->resized) {
+        asc_ptr_cast(AscSprite, sprite, behavior->node);
+        asc_vec2u window_size = asc_active_window->dimensions;
+        asc_sprite_set_size(sprite, window_size);
+    }
+}
+
+static void create_backdrop(void) {
+    AscSceneNode *node = asc_sprite(
+        .texture = TEXTURE_BACKDROP,
+        .texture_scale_mode = ASC_TEXTURE_SCALE_REPEAT
+    );
+    asc_behavior_add(node, .func = scale_backdrop);
+    asc_scene_add_node(BACKDROP_SCENE, node);
+}
+
 static void update_fps_counter(AscBehavior *behavior) {
     asc_ptr_cast(AscText, node, behavior->node);
     static float last_fps = 0.f;
@@ -102,24 +127,6 @@
     }
 }
 
-static void scale_backdrop(AscBehavior *behavior) {
-    // scale the backdrop to the size of the window
-    if (asc_active_window->resized) {
-        asc_ptr_cast(AscSprite, sprite, behavior->node);
-        asc_vec2u window_size = asc_active_window->dimensions;
-        asc_sprite_set_size(sprite, window_size);
-    }
-}
-
-static void create_backdrop(void) {
-    AscSceneNode *node = asc_sprite(
-        .texture = TEXTURE_BACKDROP,
-        .texture_scale_mode = ASC_TEXTURE_SCALE_REPEAT
-    );
-    asc_behavior_add(node, .func = scale_backdrop);
-    asc_scene_add_node(BACKDROP_SCENE, node);
-}
-
 static void create_fps_counter(void) {
     asc_font(ASC_FONT_REGULAR, 12);
     asc_ink_rgb(255, 255, 255);
@@ -143,7 +150,7 @@
 static void move_spaceship(AscBehavior *behavior) {
     AscSceneNode *node = behavior->node;
     Spaceship *spaceship = node->user_data;
-    float speed = 32.f * asc_context.frame_factor;
+    float speed = 32.f * spaceship->speed * asc_context.frame_factor;
     asc_vec2f movement = asc_vec2f_scale(directions[spaceship->direction], speed);
     asc_scene_node_move2f(node, movement);
     asc_scene_node_set_rotation(node, rotations[spaceship->direction]);
@@ -153,19 +160,39 @@
     AscSceneNode *sprite = asc_sprite(
         .name = "Player",
         .texture = TEXTURE_SHIP,
-        .x = 250,
-        .y = 300,
-        .width = 32,
-        .height = 32,
-        .origin_x = 16,
-        .origin_y = 16,
+        // TODO: introduce a function to set the position of a space ship
+        .x = game_field_tile_size * 8 - game_field_tile_size / 2,
+        .y = game_field_tile_size * 12 - game_field_tile_size / 2,
+        .width = game_field_tile_size,
+        .height = game_field_tile_size,
+        .origin_x = game_field_tile_size / 2,
+        .origin_y = game_field_tile_size / 2,
     );
     asc_scene_add_node(MAIN_SCENE, sprite);
-    asc_scene_node_allocate_data(sprite, sizeof(Spaceship));
+    Spaceship *ship = asc_scene_node_allocate_data(sprite, sizeof(Spaceship));
+    ship->speed = 2.f; // start with 2 tiles/sec
     asc_behavior_add(sprite, move_spaceship);
     return sprite->user_data;
 }
 
+static void create_gamefield() {
+    // TODO: create a proper data structure and a more interesting map than just a basic grid
+    AscSceneNode *gamefield = asc_scene_node_empty();
+    for (unsigned x = 0; x < game_field_size; x+=game_field_tile_size) {
+        for (unsigned y = 0; y < game_field_size; y+=game_field_tile_size) {
+            asc_ink_rgb(0, 128, 255);
+            AscSceneNode *tile = asc_rectangle(
+                .x = x, .y = y, .filled = true, .thickness = 1,
+                .width = game_field_tile_size, .height = game_field_tile_size,
+                .border_color = ASC_RGB(64, 196, 255),
+            );
+            asc_scene_node_link(gamefield, tile);
+        }
+    }
+    asc_scene_node_set_zindex(gamefield, -2);
+    asc_scene_add_node(MAIN_SCENE, gamefield);
+}
+
 static asc_rect update_viewport_for_window_resize(asc_vec2u window_size) {
     // Compute scaling and offsets
     unsigned viewport_size, offset_x = 0, offset_y = 0;
@@ -203,6 +230,7 @@
     AscWindowSettings settings;
     asc_window_settings_init_defaults(&settings);
     settings.title = "Snake";
+    settings.dimensions = ASC_VEC2U(800, 800);
     asc_window_initialize(0, &settings);
     asc_ui_scale_auto();
 
@@ -210,7 +238,6 @@
     init_textures();
 
     // initialize the scenes
-    const int game_field_size = 512;
     asc_scene_init(BACKDROP_SCENE,
         .type = ASC_CAMERA_ORTHO,
         .projection_update_func = asc_camera_ortho_update_size
@@ -218,7 +245,12 @@
     asc_ink_rgb(0, 128, 90);
     asc_scene_init(MAIN_SCENE,
         .type = ASC_CAMERA_ORTHO,
-        .ortho.rect = ASC_RECT(0, 0, game_field_size, game_field_size),
+        .ortho.rect = ASC_RECT(
+            -game_field_tile_size/2,
+            -game_field_tile_size/2,
+            game_field_size+game_field_tile_size,
+            game_field_size+game_field_tile_size
+        ),
         .viewport_clear = true,
         .viewport_update_func = update_viewport_for_window_resize
     );
@@ -226,6 +258,9 @@
     // backdrop for letterbox/pillarbox
     create_backdrop();
 
+    // the game field
+    create_gamefield();
+
     // create UI elements
     create_fps_counter();
     create_score_counter();

mercurial