diff --git a/engine/editor_scene.c b/engine/editor_scene.c index 5b9b673..2620373 100644 --- a/engine/editor_scene.c +++ b/engine/editor_scene.c @@ -11,10 +11,11 @@ static Tile_t all_tiles[MAX_N_TILES] = {0}; enum EntitySpawnSelection { TOGGLE_TILE = 0, + TOGGLE_ONEWAY, SPAWN_CRATE, SPAWN_METAL_CRATE, }; -#define MAX_SPAWN_TYPE 3 +#define MAX_SPAWN_TYPE 4 static unsigned int current_spawn_selection = 0; static inline unsigned int get_tile_idx(int x, int y, unsigned int tilemap_width) @@ -38,10 +39,14 @@ static void level_scene_render_func(Scene_t* scene) int y = (i / tilemap.width) * TILE_SIZE; sprintf(buffer, "%u", sc_map_size_64(&tilemap.tiles[i].entities_set)); - if (tilemap.tiles[i].solid) + if (tilemap.tiles[i].tile_type == SOLID_TILE) { DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, BLACK); } + else if (tilemap.tiles[i].tile_type == ONEWAY_TILE) + { + DrawRectangle(x, y, TILE_SIZE, TILE_SIZE, BROWN); + } else if (tilemap.tiles[i].water_level > 0) { // Draw water tile @@ -106,7 +111,7 @@ static void level_scene_render_func(Scene_t* scene) int y = (i / tilemap.width) * TILE_SIZE; sprintf(buffer, "%u", sc_map_size_64(&tilemap.tiles[i].entities_set)); - if (tilemap.tiles[i].solid) + if (tilemap.tiles[i].solid > 0) { DrawText(buffer, x, y, 10, WHITE); } @@ -233,8 +238,30 @@ static void toggle_block_system(Scene_t* scene) switch (sel) { case TOGGLE_TILE: - tilemap.tiles[tile_idx].solid = !tilemap.tiles[tile_idx].solid; - tilemap.tiles[tile_idx].water_level = 0; + if (tilemap.tiles[tile_idx].tile_type == SOLID_TILE) + { + tilemap.tiles[tile_idx].tile_type = EMPTY_TILE; + tilemap.tiles[tile_idx].solid = NOT_SOLID; + } + else + { + tilemap.tiles[tile_idx].tile_type = SOLID_TILE; + tilemap.tiles[tile_idx].solid = SOLID; + } + tilemap.tiles[tile_idx].water_level = 0; + break; + case TOGGLE_ONEWAY: + if (tilemap.tiles[tile_idx].tile_type == ONEWAY_TILE) + { + tilemap.tiles[tile_idx].tile_type = EMPTY_TILE; + tilemap.tiles[tile_idx].solid = NOT_SOLID; + } + else + { + tilemap.tiles[tile_idx].tile_type = ONEWAY_TILE; + tilemap.tiles[tile_idx].solid = ONE_WAY; + } + tilemap.tiles[tile_idx].water_level = 0; break; case SPAWN_CRATE: spawn_crate(scene, tile_idx, false); @@ -361,13 +388,15 @@ void init_level_scene(LevelScene_t* scene) scene->data.tilemap.tiles = all_tiles; for (size_t i = 0; i < MAX_N_TILES;i++) { - all_tiles[i].solid = 0; + all_tiles[i].solid = NOT_SOLID; + all_tiles[i].tile_type = EMPTY_TILE; sc_map_init_64(&all_tiles[i].entities_set, 16, 0); } for (size_t i = 0; i < scene->data.tilemap.width; ++i) { unsigned int tile_idx = (scene->data.tilemap.height - 1) * scene->data.tilemap.width + i; - all_tiles[tile_idx].solid = true; // for testing + all_tiles[tile_idx].solid = SOLID; // for testing + all_tiles[tile_idx].tile_type = SOLID_TILE; // for testing } spawn_player(&scene->scene); diff --git a/engine/game_systems.c b/engine/game_systems.c index adec22f..a71cae2 100644 --- a/engine/game_systems.c +++ b/engine/game_systems.c @@ -47,7 +47,8 @@ static bool check_collision(const CollideEntity_t* ent, TileGrid_t* grid, Entity for(unsigned int tile_x = ent->area.tile_x1; tile_x <= ent->area.tile_x2; tile_x++) { unsigned int tile_idx = tile_y*grid->width + tile_x; - if (grid->tiles[tile_idx].solid) return true; + if (grid->tiles[tile_idx].solid == SOLID) return true; + //TODO: For one-way platform, check for collision, only return true for up direction unsigned int ent_idx; sc_map_foreach_value(&grid->tiles[tile_idx].entities_set, ent_idx) { @@ -77,6 +78,8 @@ static bool check_collision(const CollideEntity_t* ent, TileGrid_t* grid, Entity return false; } + +// TODO: This should be a point collision check, not an AABB check static bool check_collision_at( unsigned int ent_idx, Vector2 pos, Vector2 bbox_sz, TileGrid_t* grid, Vector2 point, EntityManager_t* p_manager @@ -108,8 +111,7 @@ static inline bool check_on_ground( static bool check_collision_and_move( EntityManager_t* p_manager, TileGrid_t* tilemap, unsigned int ent_idx, CTransform_t* p_ct, Vector2 sz, - Vector2 other_pos, Vector2 other_sz, bool other_solid, - uint32_t* collision_value + Vector2 other_pos, Vector2 other_sz, SolidType_t other_solid ) { Vector2 overlap = {0,0}; @@ -126,32 +128,30 @@ static bool check_collision_and_move( if (fabs(prev_overlap.y) > fabs(prev_overlap.x)) { offset.x = overlap.x; - *collision_value = (((overlap.x > 0?1:0)<< 14) | ( (uint16_t)(fabs(overlap.x)) )); } else if (fabs(prev_overlap.x) > fabs(prev_overlap.y)) { offset.y = overlap.y; - *collision_value = (((overlap.y > 0?3:2)<< 14) | ( (uint16_t)(fabs(overlap.y)) )); } else if (fabs(overlap.x) < fabs(overlap.y)) { offset.x = overlap.x; - *collision_value = (((overlap.x > 0?1:0)<< 14) | ( (uint16_t)(fabs(overlap.x)) )); } else { offset.y = overlap.y; - *collision_value = (((overlap.y > 0?3:2)<< 14) | ( (uint16_t)(fabs(overlap.y)) )); } // Resolve collision via moving player by the overlap amount only if other is solid // also check for empty to prevent creating new collision. Not fool-proof, but good enough //if (other_solid && !check_collision_at(ent_idx, p_ct->position, sz, tilemap, offset, p_manager)) - if (other_solid) + if ( other_solid == SOLID + || (other_solid == ONE_WAY && offset.y < 0) + ) { p_ct->position = Vector2Add(p_ct->position, offset); + return true; } - return true; } return false; } @@ -322,7 +322,7 @@ void player_movement_input_system(Scene_t* scene) for(unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++) { - hit |= tilemap.tiles[tile_y * tilemap.width + tile_x].solid; + hit |= tilemap.tiles[tile_y * tilemap.width + tile_x].tile_type == SOLID_TILE; } if (hit) { @@ -442,13 +442,12 @@ void tile_collision_system(Scene_t* scene) unsigned int tile_x2 = (p_ctransform->position.x + p_bbox->size.x) / TILE_SIZE; unsigned int tile_y2 = (p_ctransform->position.y + p_bbox->size.y) / TILE_SIZE; - uint32_t collision_value; for (unsigned int tile_y = tile_y1; tile_y <= tile_y2; tile_y++) { for (unsigned int tile_x = tile_x1; tile_x <= tile_x2; tile_x++) { unsigned int tile_idx = tile_y * tilemap.width + tile_x; - if(tilemap.tiles[tile_idx].solid) + if(tilemap.tiles[tile_idx].tile_type != EMPTY_TILE) { Vector2 other; other.x = (tile_idx % tilemap.width) * TILE_SIZE; @@ -457,7 +456,7 @@ void tile_collision_system(Scene_t* scene) check_collision_and_move( &scene->ent_manager, &tilemap, ent_idx, p_ctransform, p_bbox->size, other, - TILE_SZ, true, &collision_value + TILE_SZ, tilemap.tiles[tile_idx].solid ); } @@ -478,17 +477,11 @@ void tile_collision_system(Scene_t* scene) if (p_other_bbox == NULL) continue; CTransform_t *p_other_ct = get_component(&scene->ent_manager, p_other_ent, CTRANSFORM_COMP_T); - if ( - check_collision_and_move( - &scene->ent_manager, &tilemap, ent_idx, - p_ctransform, p_bbox->size, p_other_ct->position, - p_other_bbox->size, p_other_bbox->solid, &collision_value - ) - ) - { - uint32_t collision_key = ((ent_idx << 16) | other_ent_idx); - sc_map_put_32(&data->collision_events, collision_key, collision_value); - } + check_collision_and_move( + &scene->ent_manager, &tilemap, ent_idx, + p_ctransform, p_bbox->size, p_other_ct->position, + p_other_bbox->size, p_other_bbox->solid? SOLID : NOT_SOLID + ); } } } diff --git a/engine/scene_impl.h b/engine/scene_impl.h index 85ce540..60a58a5 100644 --- a/engine/scene_impl.h +++ b/engine/scene_impl.h @@ -7,8 +7,24 @@ #include "engine.h" #include "gui.h" +typedef enum TileType { + EMPTY_TILE = 0, + SOLID_TILE, + ONEWAY_TILE, + LADDER +} TileType_t; + +typedef enum SolidType +{ + NOT_SOLID = 0, + SOLID, + ONE_WAY, +}SolidType_t; + + typedef struct Tile { - bool solid; + TileType_t tile_type; + SolidType_t solid; unsigned int water_level; struct sc_map_64 entities_set; }Tile_t;