snap the movement to the grid

Sun, 20 Jul 2025 23:31:40 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 20 Jul 2025 23:31:40 +0200
changeset 216
943980fa37b5
parent 215
a7c8e1727971
child 217
4b3c974eab44

snap the movement to the grid

src/ascension/datatypes.h file | annotate | diff | comparison | revisions
test/snake/snake.c file | annotate | diff | comparison | revisions
--- a/src/ascension/datatypes.h	Sat Jul 19 21:29:10 2025 +0200
+++ b/src/ascension/datatypes.h	Sun Jul 20 23:31:40 2025 +0200
@@ -330,6 +330,13 @@
     return v.x*v.x + v.y*v.y + v.z*v.z;
 }
 
+static inline asc_vec2f asc_vec2f_sub(asc_vec2f a, asc_vec2f b) {
+    return ASC_VEC2F(a.x-b.x, a.y-b.y);
+}
+
+// TODO: add sub-functions for other types
+// TODO: add add-functions
+
 // --------------------------------------------------------------------------
 //   Matrix Functions
 // --------------------------------------------------------------------------
--- a/test/snake/snake.c	Sat Jul 19 21:29:10 2025 +0200
+++ b/test/snake/snake.c	Sun Jul 20 23:31:40 2025 +0200
@@ -56,6 +56,7 @@
 
 typedef struct {
     enum MoveDirection direction;
+    enum MoveDirection target_direction;
     /**
      * The speed in tiles per second.
      */
@@ -152,10 +153,32 @@
 static void move_spaceship(AscBehavior *behavior) {
     AscSceneNode *node = behavior->node;
     Spaceship *spaceship = node->user_data;
-    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]);
+    const float ts = (float) game_field_tile_size;
+    const float speed = ts * spaceship->speed * asc_context.frame_factor;
+    const asc_vec2f dvec = directions[spaceship->direction];
+    const asc_vec2f movement = asc_vec2f_scale(dvec, speed);
+    if (spaceship->direction == spaceship->target_direction) {
+        // no change of direction - keep moving
+        asc_scene_node_move2f(node, movement);
+    } else {
+        // identify the tile we are currently in
+        int x = (int) (node->position.x / ts);
+        int y = (int) (node->position.y / ts);
+        const asc_vec2f tcenter = ASC_VEC2F(x*ts, y*ts);
+        // calculate the (squared) distance to the tile's center
+        float cdist = asc_vec2f_sqrlen(asc_vec2f_sub(tcenter, ASC_VEC2F(node->position.x, node->position.y)));
+        // if it is less than squared length of the movement vector, snap to the center and rotate
+        // TODO: think about if we should allow changing direction only when we haven't passed the center yet
+        if (cdist < asc_vec2f_sqrlen(dvec)) {
+            asc_scene_node_set_position2f(node, tcenter);
+            spaceship->direction = spaceship->target_direction;
+            asc_scene_node_set_rotation(node, rotations[spaceship->direction]);
+            // TODO: this is losing some speed - improve the calculation and add partial movement after rotation
+        } else {
+            // too far away from center, continue normal movement
+            asc_scene_node_move2f(node, movement);
+        }
+    }
 }
 
 static Spaceship *create_spaceship(void) {
@@ -285,22 +308,22 @@
         // player rotation
         if (asc_key_pressed(ASC_KEY(LEFT))) {
             if (spaceship->direction != MOVE_RIGHT) {
-                spaceship->direction = MOVE_LEFT;
+                spaceship->target_direction = MOVE_LEFT;
             }
         }
         if (asc_key_pressed(ASC_KEY(RIGHT))) {
             if (spaceship->direction != MOVE_LEFT) {
-                spaceship->direction = MOVE_RIGHT;
+                spaceship->target_direction = MOVE_RIGHT;
             }
         }
         if (asc_key_pressed(ASC_KEY(UP))) {
             if (spaceship->direction != MOVE_DOWN) {
-                spaceship->direction = MOVE_UP;
+                spaceship->target_direction = MOVE_UP;
             }
         }
         if (asc_key_pressed(ASC_KEY(DOWN))) {
             if (spaceship->direction != MOVE_UP) {
-                spaceship->direction = MOVE_DOWN;
+                spaceship->target_direction = MOVE_DOWN;
             }
         }
 

mercurial