diff --git a/assets/entities.json b/assets/entities.json index 7e31745..a58faff 100644 --- a/assets/entities.json +++ b/assets/entities.json @@ -1,11 +1,11 @@ { - "ships": [ - { - "destroyer": { - "texture": "assets/entities/ships/destroyer.svg", - "width": 58, - "height": 512 - } - } - ] -} \ No newline at end of file + "ship": { + "destroyer": { + "texture": "assets/entities/ships/destroyer.svg", + "width": 58, + "height": 512, + "speed": 250 + } + } + } + \ No newline at end of file diff --git a/assets/destroyer.svg b/assets/entities/ships/destroyer.svg similarity index 100% rename from assets/destroyer.svg rename to assets/entities/ships/destroyer.svg diff --git a/src/color.h b/src/color.h new file mode 100644 index 0000000..51d6d22 --- /dev/null +++ b/src/color.h @@ -0,0 +1,22 @@ + +#ifndef RESET + +#define RESET "\033[0m" +#define BLACK "\033[30m" /* Black */ +#define RED "\033[31m" /* Red */ +#define GREEN "\033[32m" /* Green */ +#define YELLOW "\033[33m" /* Yellow */ +#define BLUE "\033[34m" /* Blue */ +#define MAGENTA "\033[35m" /* Magenta */ +#define CYAN "\033[36m" /* Cyan */ +#define WHITE "\033[37m" /* White */ +#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */ +#define BOLDRED "\033[1m\033[31m" /* Bold Red */ +#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ +#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ +#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */ +#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ +#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */ +#define BOLDWHITE "\033[1m\033[37m" /* Bold White */ + +#endif \ No newline at end of file diff --git a/src/const.hpp b/src/const.hpp index adf7a3b..2657f6a 100644 --- a/src/const.hpp +++ b/src/const.hpp @@ -1,7 +1,13 @@ #include + +#ifndef CONST_NS +#define CONST_NS + constexpr int SCREEN_WIDTH = 800; constexpr int SCREEN_HEIGHT = 600; constexpr int WORLD_WIDTH = 1600; constexpr int WORLD_HEIGHT = 1200; constexpr int TARGET_FPS = 60; -constexpr Uint64 TARGET_FRAME_TIME_NS = 1'000'000'000 / TARGET_FPS; \ No newline at end of file +constexpr Uint64 TARGET_FRAME_TIME_NS = 1'000'000'000 / TARGET_FPS; + +#endif \ No newline at end of file diff --git a/src/exitcleanup.cpp b/src/exitcleanup.cpp new file mode 100644 index 0000000..24faded --- /dev/null +++ b/src/exitcleanup.cpp @@ -0,0 +1,63 @@ +#include +#include +#include "color.h" +#include +#include "exitcleanup.hpp" +#include "types.hpp" +#include "main.hpp" + +void SignalHandler(int code) { + switch (code) { + case SIGTERM: + std::cerr << "\nreceived SIGTERM exiting...\n"; + break; + case SIGINT: + std::cerr << "\nreceived SIGINT exiting...\n"; + break; + case SIGQUIT: + std::cerr << "\nreceived SIGQUIT exiting...\n"; + break; + case SIGHUP: + std::cerr << "\nreceived SIGHUP exiting...\n"; + break; + + case SIGSEGV: + std::cerr << "\nreceived SIGSEGV(segmentaiton fault) exiting...\nIf this " + "repeats please report it as a bug\n"; + break; + } + try { + GeneralCleanUp(code); + } catch(...) { + std::cerr << RED"[ERROR]" << RESET" general cleanup error\n"; + exit(errno); + } + } + + void GeneralCleanUp(int code) { + + for(Entity *entity : loaded_entities) { + try { + SDL_DestroyTexture(entity->texture); + } catch(...) { + std::cerr << RED"[ERROR]" << RESET" failed to destroy texture of entity\nentity address:" << YELLOW << entity << RESET"\n"; + } + } + + try { + SDL_DestroyWindow(main_sdl_session.window); + } catch(...) { + std::cerr << RED"[ERROR]" << RESET" failed to destroy window\n"; + } + try{ + SDL_DestroyRenderer(main_sdl_session.renderer); + } catch(...) { + std::cerr << RED"[ERROR]" << RESET" failed to destroy renderer\n"; + } + try { + SDL_Quit(); + } catch (...) { + std::cerr << RED"[ERROR]" << RESET" failed to quit sdl\n"; + } + exit(code); + } \ No newline at end of file diff --git a/src/exitcleanup.hpp b/src/exitcleanup.hpp new file mode 100644 index 0000000..9a7e0c0 --- /dev/null +++ b/src/exitcleanup.hpp @@ -0,0 +1,4 @@ +#ifndef EC_NS +#define EC_NS +void GeneralCleanUp(int code = 0); +#endif \ No newline at end of file diff --git a/src/helper_funcs.cpp b/src/helper_funcs.cpp deleted file mode 100644 index 1a2bd04..0000000 --- a/src/helper_funcs.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "types.hpp" -#include -#include -#include - -using json = nlohmann::json; - -void load_entity(Entity &entity, std::string type, std::string name) { - try { - std::ifstream entitiesF("assets/entities.json"); - json entities = json::parse(entitiesF); - - } catch (const json::parse_error &e) { - std::cerr << "Parse error: " << e.what() << "\n"; - exit(1); - } catch (const std::exception &e) { - std::cerr << "Error: " << e.what() << "\n"; - exit(2); - } - - - -} \ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp new file mode 100644 index 0000000..c61c39f --- /dev/null +++ b/src/init.cpp @@ -0,0 +1,50 @@ +#include "init.hpp" +#include +#include +#include +#include +#include +#include +#include "main.hpp" +#include +#include +#include "color.h" + +using json = nlohmann::json; + +void init_entity(Entity &entity, SDL_Renderer *renderer,std::string type, std::string name) { + json entities; + try { + std::ifstream entitiesF("./assets/entities.json"); + entities = json::parse(entitiesF); + + } catch (const json::parse_error &e) { + std::cerr << "Parse error: " << e.what() << "\n"; + exit(1); + } catch (const std::exception &e) { + std::cerr << "Error: " << e.what() << "\n"; + exit(2); + } + + loaded_entities.push_back(&entity); + std::clog << entities[type]; + + entity.texture = IMG_LoadTexture(renderer, entities[type][name]["texture"].get().c_str()); + + if(entity.texture == NULL) { + std::cerr << "\n" << RED"[ERROR]" << RESET" failed to load texture\n"; + exit(ENOENT); + } + + entity.width = entities[type][name]["width"].get(); + entity.height = entities[type][name]["height"].get(); + + entity.srcRect = {0, 0, static_cast(entity.width), + static_cast(entity.height)}; + + entity.set_central_offset(static_cast(entity.width) / 2, static_cast(entity.height) / 2); + + entity.speed = entities[type][name]["speed"].get(); + +} + diff --git a/src/init.hpp b/src/init.hpp new file mode 100644 index 0000000..926c242 --- /dev/null +++ b/src/init.hpp @@ -0,0 +1,8 @@ +#include "types.hpp" + +#ifndef IN_NS +#define IN_NS + +void init_entity(Entity &entity, SDL_Renderer *renderer,std::string type, std::string name); + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 878a6a5..83589d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,31 +1,33 @@ +#include "init.hpp" +#include "exitcleanup.hpp" #include "types.hpp" #include #include #include +#include +#include -#define destroyer_width 58 -#define destroyer_height 512 +std::vector loaded_entities; +sdl_session main_sdl_session; int main() { SDL_Init(SDL_INIT_VIDEO); - SDL_Window *window = + + main_sdl_session.window = SDL_CreateWindow("Naval Swarm", SCREEN_WIDTH, SCREEN_HEIGHT, 0); - SDL_Renderer *renderer = SDL_CreateRenderer(window, "gpu,vulcan"); + SDL_Renderer *renderer = SDL_CreateRenderer( main_sdl_session.window, "gpu,vulcan"); // Load textures - SDL_Texture *spriteSheet = IMG_LoadTexture(renderer, "assets/destroyer.svg"); SDL_Texture *bgTexture = IMG_LoadTexture(renderer, "assets/background.png"); // Initialize player Entity destroyer; - destroyer.texture = spriteSheet; - destroyer.set_offset(destroyer_width / 2, destroyer_height / 2); - destroyer.position() = {WORLD_WIDTH / 2.0f, WORLD_HEIGHT / 2.0f, 58.0f, - 512.0f}; - destroyer.srcRect = {0, 0, destroyer_width, - destroyer_height}; // Static source rectangle - destroyer.angle = 0; + init_entity(destroyer, renderer, "ship", "destroyer"); + + + destroyer.position() = {WORLD_WIDTH / 2.0f, WORLD_HEIGHT / 2.0f, static_cast(destroyer.width),static_cast(destroyer.height)}; + // Initialize camera Camera camera; bool running = true; @@ -111,10 +113,11 @@ int main() { destroyer.position().y += (float)moveY * step; if (destroyer.gotoT) { - float dx = destroyer.Tposition.x - destroyer.position().x; - float dy = destroyer.Tposition.y - destroyer.position().y; + float dx = destroyer.Tposition.x - destroyer.Central_position().x; + float dy = destroyer.Tposition.y - destroyer.Central_position().y; - destroyer.angle = std::atan2(dy, dx) * 180 / M_PI; + destroyer.angle = std::atan2(dy, dx) * 180 / M_PI + 90; + std::clog << "angle: " << destroyer.angle << "\ncalc: " << std::atan2(dy, dx) * 180 / M_PI << "\n"; float distance = std::sqrt(dx * dx + dy * dy); if (distance > 0) { @@ -122,11 +125,11 @@ int main() { dy /= distance; if (distance <= step) { - destroyer.position().x = destroyer.Tposition.x; - destroyer.position().y = destroyer.Tposition.y; + destroyer.Central_position().x = destroyer.Tposition.x; + destroyer.Central_position().y = destroyer.Tposition.y; } else { - destroyer.position().x += dx * step; - destroyer.position().y += dy * step; + destroyer.Central_position().x += dx * step; + destroyer.Central_position().y += dy * step; } } else { @@ -196,10 +199,8 @@ int main() { } // Cleanup - SDL_DestroyTexture(spriteSheet); SDL_DestroyTexture(bgTexture); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + GeneralCleanUp(); SDL_Quit(); return 0; } diff --git a/src/main.hpp b/src/main.hpp new file mode 100644 index 0000000..7325973 --- /dev/null +++ b/src/main.hpp @@ -0,0 +1,10 @@ +#include +#include "types.hpp" + +#ifndef MAIN_NS +#define MAIN_NS + +extern std::vector loaded_entities; +extern sdl_session main_sdl_session; + +#endif \ No newline at end of file diff --git a/src/types.hpp b/src/types.hpp index 4384f48..d7c6b6f 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -3,6 +3,9 @@ #include #include +#ifndef TYPES_NS +#define TYPES_NS + struct Angle360 { private: int value{0}; @@ -47,36 +50,59 @@ public: }; struct Entity { -private: - SDL_FRect m_position; - SDL_FPoint m_offset{0, 0}; // Default offset - -public: - // Direct access reference with auto-sync - SDL_FRect &position() { return m_position; } - const SDL_FRect &position() const { return m_position; } - - // Computed central position (always fresh) - SDL_FRect Central_position() const { - return {m_position.x + m_offset.x, m_position.y + m_offset.y, m_position.w, - m_position.h}; - } - - // Set offset values - void set_offset(float x, float y) { m_offset = {x, y}; } - - // --- Existing members --- - SDL_FRect Tposition; - bool gotoT; - SDL_Texture *texture; - SDL_Rect srcRect; - float speed = 250.0f; - Angle360 angle; -}; + private: + SDL_FRect m_position; + SDL_FPoint m_offset{0, 0}; + SDL_FRect m_central_cache; // New cached position + + public: + // Direct access reference with auto-sync + SDL_FRect& position() { + // Update cache when position changes + m_central_cache = { + m_position.x + m_offset.x, + m_position.y + m_offset.y, + m_position.w, + m_position.h + }; + return m_position; + } + + // Return reference to cached central position + SDL_FRect& Central_position() { + // Auto-update cache before return + m_central_cache.x = m_position.x + m_offset.x; + m_central_cache.y = m_position.y + m_offset.y; + return m_central_cache; + } + + // Set offset values with cache invalidation + void set_central_offset(float x, float y) { + m_offset = {x, y}; + Central_position(); // Update cache + } + + // --- Existing members --- + SDL_FRect Tposition; + bool gotoT; + SDL_Texture* texture; + SDL_Rect srcRect; + float speed; + Angle360 angle = 0; + unsigned int width; + unsigned int height; + }; + struct Camera { SDL_FRect view = {0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT}; bool followPlayer = false; float speed = 500.0f; float smoothness = 0.1f; -}; \ No newline at end of file +}; + +struct sdl_session { + SDL_Window *window; + SDL_Renderer *renderer; +}; +#endif \ No newline at end of file