add main.cpp and Makefile

This commit is contained in:
PoliEcho 2025-02-14 19:52:44 +01:00
parent 7db9f1fa89
commit 8d33ba71ff
2 changed files with 192 additions and 0 deletions

38
Makefile Normal file
View File

@ -0,0 +1,38 @@
# Compiler and flags
CPPC = g++
CPPC_FLAGS = -std=c++23 -s -O3 -Wall -Wextra -lSDL3 -lSDL3_image
# Debug flags:
#CPPC_FLAGS = $(CPPC_FLAGS) -ggdb
SRC_PATH := src
OBJ_PATH := build/obj
BIN_PATH := build/bin
SRC_FILES := $(shell find $(SRC_PATH) -name '*.cpp')
# Generate corresponding object file paths by replacing src/ with build/obj/
OBJ_FILES := $(patsubst $(SRC_PATH)/%.cpp,$(OBJ_PATH)/%.o,$(SRC_FILES))
all: make-build-dir $(BIN_PATH)/naval_swarm
make-build-dir:
mkdir -p $(OBJ_PATH)
mkdir -p $(BIN_PATH)
$(BIN_PATH)/naval_swarm: $(OBJ_FILES)
$(CPPC) $(CPPC_FLAGS) $^ -o $@
$(OBJ_PATH)/%.o: $(SRC_PATH)/%.cpp
$(CPPC) $(CPPC_FLAGS) -c $< -o $@
clean:
rm -fr build
.PHONY: all clean make-build-dir

154
src/main.cpp Normal file
View File

@ -0,0 +1,154 @@
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
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;
struct Animation {
SDL_Rect frames[4];
int currentFrame = 0;
Uint32 frameDuration = 100;
Uint32 lastFrameTime = 0;
};
struct Entity {
SDL_FRect position;
SDL_Texture* texture;
Animation animation;
float speed = 250.0f;
};
struct Camera {
SDL_FRect view = {0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT};
bool followPlayer = true;
float speed = 500.0f;
float smoothness = 0.1f;
};
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");
// Load textures
SDL_Texture* spriteSheet = IMG_LoadTexture(renderer, "assets/spritesheet.png");
SDL_Texture* bgTexture = IMG_LoadTexture(renderer, "assets/background.png");
// Initialize player
Entity player;
player.texture = spriteSheet;
player.position = {WORLD_WIDTH/2.0f, WORLD_HEIGHT/2.0f, 64.0f, 64.0f};
for(int i = 0; i < 4; i++) {
player.animation.frames[i] = {i * 64, 0, 64, 64};
}
// Initialize camera
Camera camera;
bool running = true;
Uint64 lastFrameTime = SDL_GetTicksNS();
float deltaTime = 0.0f;
while (running) {
const Uint64 frameStart = SDL_GetTicksNS();
// Event handling
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) running = false;
}
// 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
float moveX = keystate[SDL_SCANCODE_RIGHT] - keystate[SDL_SCANCODE_LEFT];
float moveY = keystate[SDL_SCANCODE_DOWN] - keystate[SDL_SCANCODE_UP];
player.position.x += moveX * player.speed * deltaTime;
player.position.y += moveY * player.speed * deltaTime;
// Camera movement
if (camera.followPlayer) {
// Smooth follow
float targetX = player.position.x + player.position.w/2 - camera.view.w/2;
float targetY = player.position.y + player.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 {
// Manual camera control with IJKL
float camMoveX = keystate[SDL_SCANCODE_L] - keystate[SDL_SCANCODE_J];
float camMoveY = keystate[SDL_SCANCODE_K] - keystate[SDL_SCANCODE_I];
camera.view.x += camMoveX * camera.speed * deltaTime;
camera.view.y += camMoveY * camera.speed * deltaTime;
}
// World bounds
player.position.x = SDL_clamp(player.position.x, 0.0f, WORLD_WIDTH - player.position.w);
player.position.y = SDL_clamp(player.position.y, 0.0f, WORLD_HEIGHT - player.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 update
if (moveX != 0 || moveY != 0) {
Uint32 now = SDL_GetTicks();
if (now - player.animation.lastFrameTime > player.animation.frameDuration) {
player.animation.currentFrame = (player.animation.currentFrame + 1) % 4;
player.animation.lastFrameTime = now;
}
} else {
player.animation.currentFrame = 0;
}
// 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
SDL_FRect srcFRect;
SDL_RectToFRect(&player.animation.frames[player.animation.currentFrame], &srcFRect);
SDL_FRect destRect = {
player.position.x - camera.view.x,
player.position.y - camera.view.y,
player.position.w,
player.position.h
};
SDL_RenderTextureRotated(renderer, player.texture, &srcFRect, &destRect, 0.0, nullptr, SDL_FLIP_NONE);
SDL_RenderPresent(renderer);
// Frame timing
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;
}