#include "object.hpp" #include #include #include "map/tile.hpp" #include "map/map.hpp" std::vector Object::objects; Object::~Object() { for (int y = 0; y < dimension.y; y++) { for (int x = 0; x < dimension.x; x++) { size_t m_id = static_cast((y+world_tile_position.y)*Map::size.x+(x+world_tile_position.x)); if (m_id >= static_cast(Map::size.x*Map::size.y)) continue; std::vector& t_objects = Map::tile_map[m_id].objects; for (auto it = t_objects.begin(); it != t_objects.end(); ) { if (it->object_id == id) it = t_objects.erase(it); else ++it; } } } }; const char* Object::to_String(ObjectType type) { switch (type) { case ObjectType::NONE: return "NONE"; case ObjectType::ROCK: return "ROCK"; case ObjectType::TREE: return "TREE"; case ObjectType::STICK: return "STICK"; case ObjectType::BUSH: return "BUSH"; case ObjectType::FLOWER: return "FLOWER"; case ObjectType::FOOD: return "FOOD"; case ObjectType::FURNITURE: return "FURNITURE"; case ObjectType::ROOF: return "ROOF"; case ObjectType::FLOOR: return "FLOOR"; case ObjectType::FURNISHING: return "FURNISHING"; case ObjectType::WORKBENCH: return "WORKBENCH"; default: return "UNKNOWN"; } } std::vector Object::get_ObjectsByWorldPosition(SDL_Point position) { std::vector objects; for (Object* object : Object::objects) { if (object->world_tile_position.x == position.x && object->world_tile_position.y == position.y) { objects.push_back(object); } } return objects; } Object* Object::get_ObjectByWorldPositionAndTilesetObjectID(SDL_Point position, size_t ts_object_id) { std::vector os = Object::get_ObjectsByWorldPosition(position); for (Object* o : os) { if (o->tileset_object_id == ts_object_id) return o; } return nullptr; } Object* Object::get_ObjectById(size_t id) { //std::cout << "GETTT " << id << std::endl; for (Object* object : Object::objects) if (object->id == id) return object; return nullptr; } SDL_Point Object::get_SetPosition() { return Tile::tilesets[tileset_type][tileset_id].objects[tileset_object_id].tileset_info.set_position; } int Object::is_InFrontOf(SDL_FPoint world_position, SDL_FRect rect) { const int scale = Tile::tile_size / Tile::tile_collider_size; const int obj_w = dimension.x * scale; const int obj_h = dimension.y * scale; const int obj_x = world_position.x / scale; const int obj_y = world_position.y / scale; const int rect_x = rect.x / Tile::tile_collider_size; const int rect_y = rect.y / Tile::tile_collider_size; const int rect_w = (rect.w + Tile::tile_collider_size - 1) / Tile::tile_collider_size; const int rect_h = (rect.h + Tile::tile_collider_size - 1) / Tile::tile_collider_size; /* std::cout << "WP: " << world_position.x << " " << world_position.y << std::endl; std::cout << "OB " << obj_x << " " << obj_y << " " << obj_w << " " << obj_h << std::endl; std::cout << "RE " << rect_x << " " << rect_y << " " << rect_w << std::endl; */ const int row_width = obj_w; // object is left or right of rect if (rect_x + rect_w <= obj_x || rect_x >= obj_x + obj_w) return false; int start_x = std::max(rect_x, obj_x) - obj_x; int end_x = std::min(rect_x + rect_w, obj_x + obj_w) - obj_x; // is above object if (rect_y+rect_h < obj_y) return 2; // is below object if (obj_y + obj_h <= rect_y) return false; // int rect_row = rect_y - obj_y; if (rect_row >= obj_h) return 2; bool collission_below = false; bool anywhere_above = false; bool anywhere_below = false; std::vector collission_map = get_CollisionMap(); bool has_collision = false; for (int y = 0; y < obj_h; ++y) { int base = y * row_width; for (int x = 0; x < obj_w; ++x) { if (collission_map[static_cast(base + x)]) { has_collision = true; if (y < rect_row) { //std::cout << "ABOVE \n"; anywhere_above = true; if (x > start_x && x < end_x) { //std::cout << "SUPABOVE \n"; //collission_above = true; return false; } } else { //std::cout << "BELOW\n"; anywhere_below = true; if (x > start_x && x < end_x) { //std::cout << "SUPBELOW\n"; collission_below = true; } } } } } if ( !has_collision ) { //std::cout << "NO COLL\n"; SDL_FRect temp_rect = { world_position.x, world_position.y, static_cast(dimension.x*Tile::tile_size), static_cast(dimension.y*Tile::tile_size) }; //std::cout << "COLL " << SDL_HasRectIntersectionFloat(&temp_rect, &rect) << " " << world_position.x << " " << world_position.y << " " << rect.x << " " << rect.y < Object::get_CollisionMap() { std::vector map = Tile::get_ObjectCollisionsFromTileset( tileset_id, tileset_object_id, tileset_type); if (!map.empty()) return map; const size_t n = Tile::tile_collider_size * Tile::tile_collider_size; return std::vector(n, false); } bool Object::has_Collision() { for (bool collission : get_CollisionMap()) { if (collission) return true; } return false; } std::vector Object::get_CollissionsOfTile(SDL_Point tile) { std::vector collision_map = get_CollisionMap(); const size_t scale = Tile::tile_size / Tile::tile_collider_size; int y_start = tile.y * static_cast(Tile::tile_size/Tile::tile_collider_size); int y_end = y_start + static_cast(Tile::tile_size/Tile::tile_collider_size); int x_start = tile.x * static_cast(Tile::tile_size/Tile::tile_collider_size); int x_end = x_start + static_cast(Tile::tile_size/Tile::tile_collider_size); int obj_w = static_cast(dimension.x) * scale; std::vector collisions; for (int y = y_start; y < y_end; y++) { for (int x = x_start; x < x_end; x++) { size_t index = static_cast(y * obj_w + x); collisions.push_back(collision_map[index]); } } return collisions; } void Object::print_CollisionMap() { size_t collider_w = static_cast(dimension.x) * Tile::tile_size / Tile::tile_collider_size; size_t collider_h = static_cast(dimension.y) * Tile::tile_size / Tile::tile_collider_size; std::cout << "Collision Map for object " << tileset_object_id << " (collider size: " << collider_w << "x" << collider_h << "):\n"; std::vector collision_map = get_CollisionMap(); for (size_t y = 0; y < collider_h; ++y) { for (size_t x = 0; x < collider_w; ++x) { size_t index = y * collider_w + x; if (index >= collision_map.size()) { std::cout << "? "; } else { std::cout << (collision_map[index] ? "1 " : "0 "); } } std::cout << "\n"; } } void Object::Draw(SDL_Renderer* renderer, SDL_FPoint position, bool is_transparent, int transparency) { SDL_Point obj_set_pos = get_SetPosition(); SDL_FRect obj_src { static_cast(obj_set_pos.x) * static_cast(Tile::tile_size), static_cast(obj_set_pos.y) * static_cast(Tile::tile_size), static_cast(dimension.x * static_cast(Tile::tile_size)), static_cast(dimension.y * static_cast(Tile::tile_size)) }; int size = Tile::get_Size(); SDL_FRect dst; if (object_type == ObjectType::VEGETABLE) { dst = { Scale(position.x + Map::offset.x), Scale(position.y + Map::offset.y-7), Scale(dimension.x * size), Scale(dimension.y * size) }; } else { dst = { Scale(position.x + Map::offset.x), Scale(position.y + Map::offset.y), Scale(dimension.x * size), Scale(dimension.y * size) }; } SDL_Texture* tex = Tile::tilesets[tileset_type][tileset_id].texture; if (is_transparent) SDL_SetTextureAlphaMod(tex, transparency); SDL_RenderTexture(renderer, tex, &obj_src, &dst); if (is_transparent) SDL_SetTextureAlphaMod(tex, 255); #ifdef DEBUG_BUILD std::vector collision_map = get_CollisionMap(); size_t scale = Tile::tile_size / Tile::tile_collider_size; size_t collider_w = static_cast(dimension.x) * scale; size_t collider_h = static_cast(dimension.y) * scale; for (size_t y = 0; y < collider_h; ++y) { for (size_t x = 0; x < collider_w; ++x) { size_t index = y * collider_w + x; if (index >= collision_map.size()) continue; if (collision_map[index]) { SDL_FRect col_rect = { Scale(static_cast(position.x + (x * Tile::tile_collider_size)) + Map::offset.x), Scale(static_cast(position.y + (y * Tile::tile_collider_size)) + Map::offset.y), Scale(static_cast(Tile::tile_collider_size)), Scale(static_cast(Tile::tile_collider_size)) }; SDL_SetRenderDrawColor(renderer, 255, 0, 0, 120); SDL_RenderFillRect(renderer, &col_rect); } } } #endif } void Object::Remove(Object* obj) { if (!obj) return; int start_x = obj->world_tile_position.x; int start_y = obj->world_tile_position.y; int end_x = start_x + obj->dimension.x; int end_y = start_y + obj->dimension.y; for (int y = start_y; y < end_y; ++y) { for (int x = start_x; x < end_x; ++x) { size_t index = static_cast(y * Map::size.x + x); if (index >= Map::tile_map.size()) continue; auto& tile_objects = Map::tile_map[index].objects; tile_objects.erase( std::remove_if(tile_objects.begin(), tile_objects.end(), [obj](const TileObject& to) { return to.object_id == obj->id; }), tile_objects.end()); Map::set_TileCollissionForObjects({x, y}); } } Object::objects.erase( std::remove(Object::objects.begin(), Object::objects.end(), obj), Object::objects.end() ); delete obj; }