--- a/test/snake/snake.c Sat Aug 02 21:43:39 2025 +0200 +++ b/test/snake/snake.c Sun Aug 03 22:15:25 2025 +0200 @@ -68,8 +68,18 @@ bool reset_position; } Player; -static const unsigned game_field_size = 32; -static const unsigned game_field_tile_size = 32; +#define GAME_FIELD_SIZE 32 +#define GAME_FIELD_TILE_SIZE 32 + +/** The bit in the tile data indicating if the tile exists. */ +#define GAME_FIELD_TILE_EXISTS_FLAG 0x80 +/** The bits in the tile data that identify the owner. */ +#define GAME_FIELD_TILE_OWNER_MASK 0xF + +typedef struct { + AscSceneNode *nodes[GAME_FIELD_SIZE][GAME_FIELD_SIZE]; + int8_t tile_data[GAME_FIELD_SIZE][GAME_FIELD_SIZE]; +} GameField; static void globals_init(void) { asc_transform_identity(rotations[MOVE_UP]); @@ -207,14 +217,14 @@ 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)); + 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 int ts = (int) GAME_FIELD_TILE_SIZE; const float fts = (float) ts; const float speed = fts * player->speed * asc_context.frame_factor; const asc_vec2i dir = directions[player->direction]; @@ -261,10 +271,10 @@ static Player *player_create(void) { AscSceneNode *sprite = asc_sprite( .name = "Player", - .width = game_field_tile_size, - .height = game_field_tile_size, - .origin_x = game_field_tile_size / 2, - .origin_y = 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); Player *player = asc_scene_node_allocate_data(sprite, sizeof(Player)); @@ -278,21 +288,26 @@ 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++) { - for (unsigned y = 1; y <= game_field_size; y++) { + AscSceneNode *node = asc_scene_node_empty(); + GameField *data = asc_scene_node_allocate_data(node, sizeof(GameField)); + for (unsigned x = 0; x < GAME_FIELD_SIZE; x++) { + for (unsigned y = 0; y < GAME_FIELD_SIZE; y++) { AscSceneNode *tile = asc_rectangle( - .x = x*game_field_tile_size, .y = y*game_field_tile_size, .filled = true, .thickness = 2, - .origin_x = game_field_tile_size / 2, .origin_y = game_field_tile_size / 2, - .width = game_field_tile_size, .height = game_field_tile_size, + .x = (x+1)*GAME_FIELD_TILE_SIZE, .y = (y+1)*GAME_FIELD_TILE_SIZE, .filled = true, .thickness = 2, + .origin_x = GAME_FIELD_TILE_SIZE / 2, .origin_y = GAME_FIELD_TILE_SIZE / 2, + .width = GAME_FIELD_TILE_SIZE, .height = GAME_FIELD_TILE_SIZE, .color = ASC_RGB(16, 50, 160), .border_color = ASC_RGB(20, 84, 128), ); - asc_scene_node_link(gamefield, tile); + + data->tile_data[x][y] = GAME_FIELD_TILE_EXISTS_FLAG; + data->nodes[x][y] = tile; + + asc_scene_node_link(node, tile); } } - asc_scene_node_set_zindex(gamefield, -2); - asc_scene_add_node(MAIN_SCENE, gamefield); + asc_scene_node_set_zindex(node, -2); + asc_scene_add_node(MAIN_SCENE, node); } static asc_rect main_scene_viewport_update(asc_vec2u window_size) { @@ -363,8 +378,8 @@ asc_scene_init(MAIN_SCENE, "main", .type = ASC_CAMERA_ORTHO, .ortho.rect = ASC_RECT(0, 0, - (game_field_size+1)*game_field_tile_size, - (game_field_size+1)*game_field_tile_size + (GAME_FIELD_SIZE+1)*GAME_FIELD_TILE_SIZE, + (GAME_FIELD_SIZE+1)*GAME_FIELD_TILE_SIZE ), .viewport_clear = true, .clear_color = ASC_RGB(0, 32, 16),