improve structure of the game code and add a function to set the player position

Thu, 31 Jul 2025 22:14:27 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 31 Jul 2025 22:14:27 +0200
changeset 234
a1d70b8018c1
parent 233
bda74199223f
child 235
e9540bfa5803

improve structure of the game code and add a function to set the player position

test/snake/snake.c file | annotate | diff | comparison | revisions
--- a/test/snake/snake.c	Thu Jul 31 20:40:48 2025 +0200
+++ b/test/snake/snake.c	Thu Jul 31 22:14:27 2025 +0200
@@ -61,12 +61,14 @@
      * The speed in tiles per second.
      */
     float speed;
-} Spaceship;
+    asc_vec2i new_position;
+    bool reset_position;
+} Player;
 
 static const unsigned game_field_size = 16;
 static const unsigned game_field_tile_size = 32;
 
-static void init_globals(void) {
+static void globals_init(void) {
     asc_transform_identity(rotations[MOVE_UP]);
     asc_transform_roll(rotations[MOVE_LEFT], asc_rad(-90));
     asc_transform_roll(rotations[MOVE_RIGHT], asc_rad(90));
@@ -77,18 +79,18 @@
     directions[MOVE_RIGHT] = ASC_VEC2I(1, 0);
 }
 
-static void destroy_textures(void) {
+static void textures_destroy(void) {
     asc_texture_destroy(tex2d, TEX2D_COUNT);
 }
 
-static void init_textures(void) {
+static void textures_init(void) {
     asc_texture_init_2d(tex2d, TEX2D_COUNT);
     asc_texture_from_file(TEXTURE_SHIP, "ship.png");
     asc_texture_from_file(TEXTURE_BACKDROP, "backdrop.png");
-    asc_gl_context_add_cleanup_func(asc_active_glctx, destroy_textures);
+    asc_gl_context_add_cleanup_func(asc_active_glctx, textures_destroy);
 }
 
-static void scale_backdrop(AscBehavior *behavior) {
+static void backdrop_scale(AscBehavior *behavior) {
     // scale the backdrop to the size of the window
     if (asc_active_window->resized) {
         asc_ptr_cast(AscSprite, sprite, behavior->node);
@@ -97,16 +99,16 @@
     }
 }
 
-static void create_backdrop(void) {
+static void backdrop_create(void) {
     AscSceneNode *node = asc_sprite(
         .texture = TEXTURE_BACKDROP,
         .texture_scale_mode = ASC_TEXTURE_SCALE_REPEAT,
     );
-    asc_behavior_add(node, .func = scale_backdrop);
+    asc_behavior_add(node, .func = backdrop_scale);
     asc_scene_add_node(BACKDROP_SCENE, node);
 }
 
-static void update_fps_counter(AscBehavior *behavior) {
+static void fps_counter_update(AscBehavior *behavior) {
     asc_ptr_cast(AscText, node, behavior->node);
     static float last_fps = 0.f;
     if (fabsf(asc_context.frame_rate - last_fps) > 1) {
@@ -115,7 +117,7 @@
     }
 }
 
-static void tie_fps_counter_to_corner(AscBehavior *behavior) {
+static void fps_counter_tie_to_corner(AscBehavior *behavior) {
     // TODO: this should be replaced with some sort of UI layout manager
     AscSceneNode *node = behavior->node;
     if (asc_test_flag(node->flags, ASC_SCENE_NODE_GRAPHICS_UPDATED) || asc_active_window->resized) {
@@ -128,18 +130,18 @@
     }
 }
 
-static void create_fps_counter(void) {
+static void fps_counter_create(void) {
     AscSceneNode *node = asc_text(
         .name = "FPS Counter",
         .color = ASC_RGB(255, 255, 255),
         .font = asc_font(ASC_FONT_REGULAR, 12),
     );
-    asc_behavior_add(node, .func = update_fps_counter, .interval = asc_seconds(1));
-    asc_behavior_add(node, tie_fps_counter_to_corner);
+    asc_behavior_add(node, .func = fps_counter_update, .interval = asc_seconds(1));
+    asc_behavior_add(node, fps_counter_tie_to_corner);
     asc_ui_add_node(node);
 }
 
-static void create_score_counter(void) {
+static void score_counter_create(void) {
     AscSceneNode *node = asc_text(
         .name = "Score Counter",
         .x = 10, .y = 10,
@@ -150,16 +152,28 @@
     asc_ui_add_node(node);
 }
 
-static void move_spaceship(AscBehavior *behavior) {
+static void player_move(AscBehavior *behavior) {
     AscSceneNode *node = behavior->node;
-    Spaceship *spaceship = node->user_data;
+    Player *player = node->user_data;
+
+    // check if the position is set programmatically
+    if (player->reset_position) {
+        asc_scene_node_set_position2f(node,
+            ASC_VEC2F(
+                game_field_tile_size * player->new_position.x,
+                game_field_tile_size * player->new_position.y));
+        player->reset_position = false;
+        return;
+    }
+
+    // normal movement
     const int ts = (int) game_field_tile_size;
     const float fts = (float) ts;
-    const float speed = fts * spaceship->speed * asc_context.frame_factor;
-    const asc_vec2i dir = directions[spaceship->direction];
+    const float speed = fts * player->speed * asc_context.frame_factor;
+    const asc_vec2i dir = directions[player->direction];
     const asc_vec2f movement = asc_vec2f_scale(asc_vec2_itof(dir), speed);
     // check if we are supposed to change the direction
-    if (spaceship->direction == spaceship->target_direction) {
+    if (player->direction == player->target_direction) {
         // move without changing the direction
         asc_scene_node_move2f(node, movement);
     } else {
@@ -182,8 +196,8 @@
             // snap position to the center of the tile
             node->position.x = roundf(node->position.x / fts) * fts;
             node->position.y = roundf(node->position.y / fts) * fts;
-            spaceship->direction = spaceship->target_direction;
-            asc_scene_node_set_rotation(node, rotations[spaceship->direction]);
+            player->direction = player->target_direction;
+            asc_scene_node_set_rotation(node, rotations[player->direction]);
         } else {
             // changing the direction not permitted, yet, continue movement
             asc_scene_node_move2f(node, movement);
@@ -191,26 +205,30 @@
     }
 }
 
-static Spaceship *create_spaceship(void) {
+static void player_position(Player *pl, int x, int y) {
+    pl->new_position.x = x;
+    pl->new_position.y = y;
+    pl->reset_position = true;
+}
+
+static Player *player_create(void) {
     AscSceneNode *sprite = asc_sprite(
         .name = "Player",
         .texture = TEXTURE_SHIP,
-        // TODO: introduce a function to set the position of a space ship
-        .x = game_field_tile_size * 8,
-        .y = game_field_tile_size * 12,
         .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);
-    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;
+    Player *player = asc_scene_node_allocate_data(sprite, sizeof(Player));
+    player_position(player, 12, 8);
+    player->speed = 2.f; // start with 2 tiles/sec
+    asc_behavior_add(sprite, player_move);
+    return player;
 }
 
-static void create_gamefield() {
+static void gamefield_create() {
     // 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 = 1; x <= game_field_size; x++) {
@@ -229,7 +247,7 @@
     asc_scene_add_node(MAIN_SCENE, gamefield);
 }
 
-static asc_rect update_viewport_for_window_resize(asc_vec2u window_size) {
+static asc_rect main_scene_viewport_update(asc_vec2u window_size) {
 
     // margins
     const unsigned margin = 10;
@@ -275,7 +293,7 @@
     }
 
     // initialize globals
-    init_globals();
+    globals_init();
 
     // create the window
     AscWindowSettings settings;
@@ -286,7 +304,7 @@
     asc_window_set_size(0, ASC_VEC2U(700+ui_scale*200, 700));
 
     // load textures
-    init_textures();
+    textures_init();
 
     // initialize the scenes
     asc_scene_init(BACKDROP_SCENE, "backdrop",
@@ -301,21 +319,21 @@
         ),
         .viewport_clear = true,
         .clear_color = ASC_RGB(0, 128, 90),
-        .viewport_update_func = update_viewport_for_window_resize
+        .viewport_update_func = main_scene_viewport_update
     );
 
     // backdrop for letterbox/pillarbox
-    create_backdrop();
+    backdrop_create();
 
     // the game field
-    create_gamefield();
+    gamefield_create();
 
     // create UI elements
-    create_fps_counter();
-    create_score_counter();
+    fps_counter_create();
+    score_counter_create();
 
     // create spaceship
-    Spaceship *spaceship = create_spaceship();
+    Player *spaceship = player_create();
 
     // Main Loop
     do {

mercurial