Sun, 20 Jul 2025 23:31:40 +0200
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; } }