faundation for json loading

This commit is contained in:
PoliEcho 2025-02-16 21:58:49 +01:00
parent b6551d9d6d
commit 87c6b5abdf
4 changed files with 296 additions and 211 deletions

11
assets/entities.json Normal file
View File

@ -0,0 +1,11 @@
{
"ships": [
{
"destroyer": {
"texture": "assets/entities/ships/destroyer.svg",
"width": 58,
"height": 512
}
}
]
}

23
src/helper_funcs.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "types.hpp"
#include <fstream>
#include <nlohmann/json.hpp>
#include <string>
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);
}
}

View File

@ -1,173 +1,205 @@
#include "types.hpp"
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <cmath>
#include "types.hpp"
#define destroyer_width 58
#define destroyer_height 512
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Naval Swarm", SCREEN_WIDTH, SCREEN_HEIGHT, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, "gpu,vulcan");
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window =
SDL_CreateWindow("Naval Swarm", SCREEN_WIDTH, SCREEN_HEIGHT, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(window, "gpu,vulcan");
// Load textures
SDL_Texture* spriteSheet = IMG_LoadTexture(renderer, "assets/destroyer.svg");
SDL_Texture* bgTexture = IMG_LoadTexture(renderer, "assets/background.png");
// 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.position = {WORLD_WIDTH/2.0f, WORLD_HEIGHT/2.0f, 58.0f, 512.0f};
destroyer.srcRect = {0, 0, 58, 512}; // Static source rectangle
destroyer.angle = 0;
// 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;
// Initialize camera
Camera camera;
bool running = true;
Uint64 lastFrameTime = SDL_GetTicksNS();
float deltaTime = 0.0f;
// Initialize camera
Camera camera;
bool running = true;
Uint64 lastFrameTime = SDL_GetTicksNS();
float deltaTime = 0.0f;
while (running) {
const Uint64 frameStart = SDL_GetTicksNS();
while (running) {
const Uint64 frameStart = SDL_GetTicksNS();
// Event handling
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) running = false;
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
// Check specific button (e.g., left mouse button)
if (event.button.button == SDL_BUTTON_LEFT) {
printf("Left mouse clicked at (%.1f, %.1f)\nCamera position: (%.1f, %.1f)\nTarget position: (%.1f, %.1f)\n",
event.button.x, event.button.y, camera.view.x, camera.view.y, camera.view.x+event.button.x, camera.view.y+event.button.y);
destroyer.Tposition.x = camera.view.x+event.button.x;
destroyer.Tposition.y = camera.view.y+event.button.y;
destroyer.gotoT = true;
}
}
// Event handling
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT)
running = false;
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
// Check specific button (e.g., left mouse button)
if (event.button.button == SDL_BUTTON_LEFT) {
printf("Left mouse clicked at (%.1f, %.1f)\nCamera position: (%.1f, "
"%.1f)\nTarget position: (%.1f, %.1f)\n",
event.button.x, event.button.y, camera.view.x, camera.view.y,
camera.view.x + event.button.x,
camera.view.y + event.button.y);
destroyer.Tposition.x = camera.view.x + event.button.x;
destroyer.Tposition.y = camera.view.y + event.button.y;
destroyer.gotoT = true;
}
// Input handling
const bool* keystate = SDL_GetKeyboardState(NULL);
// Toggle camera mode with C key
static Uint32 lastToggle = 0;
if (keystate[SDL_SCANCODE_C] && (SDL_GetTicks() - lastToggle > 200)) {
camera.followPlayer = !camera.followPlayer;
lastToggle = SDL_GetTicks();
}
// Player movement
int moveX = keystate[SDL_SCANCODE_RIGHT] - keystate[SDL_SCANCODE_LEFT];
int moveY = keystate[SDL_SCANCODE_DOWN] - keystate[SDL_SCANCODE_UP];
// There is propably more eficient way to do this
switch (moveX) {
case 1:
switch (moveY) {
case 1:
destroyer.angle = 135;
break;
case -1:
destroyer.angle = 45;
break;
default:
destroyer.angle = 90;
}
break;
case -1:
switch (moveY) {
case 1:
destroyer.angle = 225;
break;
case -1:
destroyer.angle = 315;
break;
default:
destroyer.angle = 270;
}
break;
default:
switch (moveY) {
case 1:
destroyer.angle = 180;
break;
case -1:
destroyer.angle = 0;
break;
}
}
destroyer.position.x += (float)moveX * destroyer.speed * deltaTime;
destroyer.position.y += (float)moveY * destroyer.speed * deltaTime;
if(destroyer.gotoT) {
destroyer.angle = std::atan2(destroyer.Tposition.y - destroyer.position.y, destroyer.Tposition.x - destroyer.position.x) * 180 / M_PI;
}
// Camera movement
if (camera.followPlayer) {
float targetX = destroyer.position.x + destroyer.position.w/2 - camera.view.w/2;
float targetY = destroyer.position.y + destroyer.position.h/2 - camera.view.h/2;
camera.view.x += (targetX - camera.view.x) * camera.smoothness;
camera.view.y += (targetY - camera.view.y) * camera.smoothness;
} else {
float camMoveX = keystate[SDL_SCANCODE_D] - keystate[SDL_SCANCODE_A];
float camMoveY = keystate[SDL_SCANCODE_S] - keystate[SDL_SCANCODE_W];
camera.view.x += camMoveX * camera.speed * deltaTime;
camera.view.y += camMoveY * camera.speed * deltaTime;
}
// World bounds
destroyer.position.x = SDL_clamp(destroyer.position.x, 0.0f, WORLD_WIDTH - destroyer.position.w);
destroyer.position.y = SDL_clamp(destroyer.position.y, 0.0f, WORLD_HEIGHT - destroyer.position.h);
camera.view.x = SDL_clamp(camera.view.x, 0.0f, WORLD_WIDTH - camera.view.w);
camera.view.y = SDL_clamp(camera.view.y, 0.0f, WORLD_HEIGHT - camera.view.h);
//ANIMATION HERE
// Rendering
SDL_SetRenderDrawColor(renderer, 30, 30, 45, 255);
SDL_RenderClear(renderer);
// Draw background
if (bgTexture) {
SDL_FRect bgDest = { -camera.view.x, -camera.view.y, WORLD_WIDTH, WORLD_HEIGHT };
SDL_RenderTexture(renderer, bgTexture, NULL, &bgDest);
}
// Draw player (simplified without animation)
SDL_FRect srcFRect;
SDL_RectToFRect(&destroyer.srcRect, &srcFRect);
SDL_FRect destRect = {
destroyer.position.x - camera.view.x,
destroyer.position.y - camera.view.y,
destroyer.position.w,
destroyer.position.h
};
SDL_RenderTextureRotated(renderer, destroyer.texture, &srcFRect, &destRect, destroyer.angle, nullptr, SDL_FLIP_NONE);
SDL_RenderPresent(renderer);
// Frame timing (unchanged)
const Uint64 frameTime = SDL_GetTicksNS() - frameStart;
if (frameTime < TARGET_FRAME_TIME_NS) {
const Uint64 sleepTime = TARGET_FRAME_TIME_NS - frameTime;
SDL_DelayNS(sleepTime - 2'000'000);
while (SDL_GetTicksNS() - frameStart < TARGET_FRAME_TIME_NS) {}
}
deltaTime = (SDL_GetTicksNS() - lastFrameTime) / 1e9f;
lastFrameTime = SDL_GetTicksNS();
}
}
// Cleanup
SDL_DestroyTexture(spriteSheet);
SDL_DestroyTexture(bgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
// Input handling
const bool *keystate = SDL_GetKeyboardState(NULL);
// Toggle camera mode with C key
static Uint32 lastToggle = 0;
if (keystate[SDL_SCANCODE_C] && (SDL_GetTicks() - lastToggle > 200)) {
camera.followPlayer = !camera.followPlayer;
lastToggle = SDL_GetTicks();
}
// Player movement
int moveX = keystate[SDL_SCANCODE_RIGHT] - keystate[SDL_SCANCODE_LEFT];
int moveY = keystate[SDL_SCANCODE_DOWN] - keystate[SDL_SCANCODE_UP];
// There is propably more eficient way to do this
switch (moveX) {
case 1:
switch (moveY) {
case 1:
destroyer.angle = 135;
break;
case -1:
destroyer.angle = 45;
break;
default:
destroyer.angle = 90;
}
break;
case -1:
switch (moveY) {
case 1:
destroyer.angle = 225;
break;
case -1:
destroyer.angle = 315;
break;
default:
destroyer.angle = 270;
}
break;
default:
switch (moveY) {
case 1:
destroyer.angle = 180;
break;
case -1:
destroyer.angle = 0;
break;
}
}
float step = destroyer.speed * deltaTime;
destroyer.position().x += (float)moveX * step;
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;
destroyer.angle = std::atan2(dy, dx) * 180 / M_PI;
float distance = std::sqrt(dx * dx + dy * dy);
if (distance > 0) {
dx /= distance;
dy /= distance;
if (distance <= step) {
destroyer.position().x = destroyer.Tposition.x;
destroyer.position().y = destroyer.Tposition.y;
} else {
destroyer.position().x += dx * step;
destroyer.position().y += dy * step;
}
} else {
destroyer.gotoT = false;
}
}
// Camera movement
if (camera.followPlayer) {
float targetX = destroyer.position().x + destroyer.position().w / 2 -
camera.view.w / 2;
float targetY = destroyer.position().y + destroyer.position().h / 2 -
camera.view.h / 2;
camera.view.x += (targetX - camera.view.x) * camera.smoothness;
camera.view.y += (targetY - camera.view.y) * camera.smoothness;
} else {
float camMoveX = keystate[SDL_SCANCODE_D] - keystate[SDL_SCANCODE_A];
float camMoveY = keystate[SDL_SCANCODE_S] - keystate[SDL_SCANCODE_W];
camera.view.x += camMoveX * camera.speed * deltaTime;
camera.view.y += camMoveY * camera.speed * deltaTime;
}
// World bounds
destroyer.position().x = SDL_clamp(destroyer.position().x, 0.0f,
WORLD_WIDTH - destroyer.position().w);
destroyer.position().y = SDL_clamp(destroyer.position().y, 0.0f,
WORLD_HEIGHT - destroyer.position().h);
camera.view.x = SDL_clamp(camera.view.x, 0.0f, WORLD_WIDTH - camera.view.w);
camera.view.y =
SDL_clamp(camera.view.y, 0.0f, WORLD_HEIGHT - camera.view.h);
// ANIMATION HERE
// Rendering
SDL_SetRenderDrawColor(renderer, 30, 30, 45, 255);
SDL_RenderClear(renderer);
// Draw background
if (bgTexture) {
SDL_FRect bgDest = {-camera.view.x, -camera.view.y, WORLD_WIDTH,
WORLD_HEIGHT};
SDL_RenderTexture(renderer, bgTexture, NULL, &bgDest);
}
// Draw player (simplified without animation)
SDL_FRect srcFRect;
SDL_RectToFRect(&destroyer.srcRect, &srcFRect);
SDL_FRect destRect = {destroyer.position().x - camera.view.x,
destroyer.position().y - camera.view.y,
destroyer.position().w, destroyer.position().h};
SDL_RenderTextureRotated(renderer, destroyer.texture, &srcFRect, &destRect,
destroyer.angle, nullptr, SDL_FLIP_NONE);
SDL_RenderPresent(renderer);
// Frame timing (unchanged)
const Uint64 frameTime = SDL_GetTicksNS() - frameStart;
if (frameTime < TARGET_FRAME_TIME_NS) {
const Uint64 sleepTime = TARGET_FRAME_TIME_NS - frameTime;
SDL_DelayNS(sleepTime - 2'000'000);
while (SDL_GetTicksNS() - frameStart < TARGET_FRAME_TIME_NS) {
}
}
deltaTime = (SDL_GetTicksNS() - lastFrameTime) / 1e9f;
lastFrameTime = SDL_GetTicksNS();
}
// Cleanup
SDL_DestroyTexture(spriteSheet);
SDL_DestroyTexture(bgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

View File

@ -1,63 +1,82 @@
#include "const.hpp"
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include "const.hpp"
#include <iostream>
struct Angle360 {
private:
int value{0};
void normalize() {
value %= 360;
if (value < 0) value += 360; // Handle negative values
}
public:
// Constructor
Angle360(int val = 0) : value(val) { normalize(); }
// Assignment operator
Angle360& operator=(int val) {
value = val;
normalize();
return *this;
}
// Compound assignment
Angle360& operator+=(int rhs) {
value += rhs;
normalize();
return *this;
}
Angle360& operator-=(int rhs) {
value -= rhs;
normalize();
return *this;
}
// Type conversion
operator int() const { return value; }
// Stream output
friend std::ostream& operator<<(std::ostream& os, const Angle360& a) {
return os << a.value;
}
private:
int value{0};
void normalize() {
value %= 360;
if (value < 0)
value += 360; // Handle negative values
}
public:
// Constructor
Angle360(int val = 0) : value(val) { normalize(); }
// Assignment operator
Angle360 &operator=(int val) {
value = val;
normalize();
return *this;
}
// Compound assignment
Angle360 &operator+=(int rhs) {
value += rhs;
normalize();
return *this;
}
Angle360 &operator-=(int rhs) {
value -= rhs;
normalize();
return *this;
}
// Type conversion
operator int() const { return value; }
// Stream output
friend std::ostream &operator<<(std::ostream &os, const Angle360 &a) {
return os << a.value;
}
};
struct Entity {
SDL_FRect position;
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}; // 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;
};
struct Camera {
SDL_FRect view = {0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT};
bool followPlayer = false;
float speed = 500.0f;
float smoothness = 0.1f;
SDL_FRect view = {0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT};
bool followPlayer = false;
float speed = 500.0f;
float smoothness = 0.1f;
};