inital commit

This commit is contained in:
2026-07-09 00:27:26 +01:00
commit 06bcac9bf7
22 changed files with 793 additions and 0 deletions
+132
View File
@@ -0,0 +1,132 @@
#include <asset_packer/asset.hpp>
#include <asset/asset.hpp>
#include <asset/raylib_asset.hpp>
#include <raylib.h>
#include <string>
#include <iostream>
#include <filesystem>
#include <variant>
namespace fs = std::filesystem;
AssetLoader::AssetLoader(std::string asset_data) : asset_reader(asset_data){
if (!asset_reader.load_index()){
std::cerr << "Failed to load assets!!!" << std::endl;
}
}
AssetReader AssetLoader::get_reader(){
return asset_reader;
}
RaylibAssetLoader::RaylibAssetLoader(std::string asset_data) : AssetLoader(asset_data) {
}
RaylibAssetLoader::~RaylibAssetLoader(){
unload_all_assets();
}
void RaylibAssetLoader::load_asset(std::string path){
fs::path file_path(path);
Asset new_asset;
new_asset.name = file_path.filename().string() ;
std::cout << file_path.extension() << std::endl;
if (file_path.extension() == ".png"){
auto texture_data = get_reader().extract_asset(path);
Image img = LoadImageFromMemory(".png", texture_data.data(), texture_data.size());
auto texture = LoadTextureFromImage(img);
UnloadImage(img);
new_asset.data = ImageData { new Texture(texture)};
}else if(file_path.extension() == ".ogg"){
}else if(file_path.extension() == ".wav"){
}else if(file_path.extension() == ".json"){
}
assets[path] = new_asset;
}
void RaylibAssetLoader::unload_asset(std::string path){
Asset asset = assets[path];
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, ImageData>) {
UnloadTexture(*((Texture*) arg.texture));
delete (Texture*) arg.texture;
}
else if constexpr (std::is_same_v<T, SoundData>) {
UnloadSound(*((Sound*) arg.sound));
delete (Sound*) arg.sound;
}
else if constexpr (std::is_same_v<T, MusicData>) {
UnloadMusicStream(*((Music*) arg.music));
delete (Music*) arg.music;
}
// JsonData requires no manual step because std::string cleans itself up!
}, asset.data);
}
void RaylibAssetLoader::unload_all_assets(){
for (auto [path,_] : assets){
unload_asset(path);
}
}
Asset RaylibAssetLoader::get_asset(std::string path){
if (assets.contains(path)){
return assets[path];
}else{
return {};
}
}
Texture* RaylibAssetLoader::get_texture(std::string path){
Asset asset = get_asset(path);
if (auto* ptr = std::get_if<ImageData>(&asset.data)) {
return (Texture*)ptr->texture;
}
return nullptr;
}
Sound* RaylibAssetLoader::get_sound(std::string path){
Asset asset = get_asset(path);
if (auto* ptr = std::get_if<SoundData>(&asset.data)) {
return (Sound*)ptr->sound;
}
return nullptr;
}
Music* RaylibAssetLoader::get_music(std::string path){
Asset asset = get_asset(path);
if (auto* ptr = std::get_if<MusicData>(&asset.data)) {
return (Music*)ptr->music;
}
return nullptr;
}
std::string RaylibAssetLoader::get_json(std::string path){
Asset asset = get_asset(path);
if (auto* ptr = std::get_if<JsonData>(&asset.data)) {
return ptr->json;
}
return "{}";
}
+8
View File
@@ -0,0 +1,8 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400
[Window][VBoxContainer]
Pos=540,275
Size=200,250
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include <asset_packer/asset.hpp>
#include <string>
#include <variant>
#include <unordered_map>
struct ImageData {
void* texture;
};
struct SoundData {
void* sound;
};
struct MusicData {
void* music;
};
struct JsonData {
std::string json;
};
struct Asset {
std::string name;
std::variant<ImageData, SoundData, MusicData, JsonData> data;
};
class AssetLoader{
private:
AssetReader asset_reader;
protected:
std::unordered_map<std::string,Asset> assets;
virtual void load_all_assets(std::string data_path) = 0;
virtual void unload_all_assets() = 0;
AssetReader get_reader();
public:
AssetLoader(std::string asset_data);
~AssetLoader() = default;
virtual void load_asset(std::string path) = 0;
virtual void unload_asset(std::string path) = 0;
virtual Asset get_asset(std::string path) = 0;;
};
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include "asset_packer/asset.hpp"
#include <asset/asset.hpp>
#include <raylib.h>
class RaylibAssetLoader : AssetLoader{
protected:
void load_all_assets(std::string asset_list) override {};
void unload_all_assets() override;
public:
RaylibAssetLoader(std::string asset_data = "data.dat");
~RaylibAssetLoader();
void load_asset(std::string path) override;
void unload_asset(std::string path) override;
Asset get_asset(std::string path) override;
Texture* get_texture(std::string path);
Sound* get_sound(std::string path);
Music* get_music(std::string path);
std::string get_json(std::string path);
};
extern RaylibAssetLoader asset_loader;
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include<raylib.h>
struct Position{
float x;
float y;
};
struct Velocity{
float dx;
float dy;
};
struct Player{};
struct Sprite{
Texture *texture;
};
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include<entt/entt.hpp>
void update_movement_system(entt::registry& registry, float dt);
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include <entt/entt.hpp>
#include<raylib.h>
void create_player(entt::registry& registry,Texture* texture);
void update_player_system(entt::registry& registry,float dt);
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <entt/entt.hpp>
void update_render_system(entt::registry &registry);
+86
View File
@@ -0,0 +1,86 @@
#pragma once
#include <functional>
#include <entt/entt.hpp>
enum class SceneType{
MENU,
GAMEPLAY
};
// Simple global data structure to hold the switch request
struct EngineState {
bool pendingSwitch = false;
SceneType nextScene;
bool shouldQuit = false;
void request_switch(SceneType type) {
nextScene = type;
pendingSwitch = true;
}
void quit(){
shouldQuit = true;
}
};
// Expose the global state to any file that includes scene.hpp
extern EngineState g_Engine;
class Scene{
public:
Scene() = default;
virtual ~Scene() = default;
virtual void update(float dt) = 0;
virtual void render() = 0;
virtual void ui() = 0;
};
class GamePlayScene : public Scene{
private:
entt::registry registry;
public:
GamePlayScene();
~GamePlayScene();
void update(float dt) override;
void render() override;
void ui() override;
};
class MenuScene : public Scene{
public:
MenuScene();
~MenuScene() = default;
void update(float dt) override;
void render() override;
void ui() override;
};
class SceneManager{
private:
Scene* current_scene = nullptr;
SceneType next_scene_type;
bool should_switch = false;
public:
SceneManager();
~SceneManager();
void update(float dt);
void render();
void ui();
void process_scene_switch();
};
+84
View File
@@ -0,0 +1,84 @@
#include <asset/raylib_asset.hpp>
#include <scene.hpp>
#include <components.hpp>
#include <box2d/box2d.h>
#include <box2d/types.h>
#include <raylib.h>
#include <rlImGui.h>
#include <imgui.h>
#include <entt/entt.hpp>
#include <asset_packer/asset.hpp>
#include <iostream>
// Globals
EngineState g_Engine;
RaylibAssetLoader asset_loader;
int main(){
//
int screen_width = 1280;
int screen_height = 800;
// initialized scene manager
SceneManager scene_manager;
entt::registry registry;
rlImGuiSetup(true);
ImGuiStyle& style = ImGui::GetStyle();
// Rounded corners
style.WindowRounding = 6.0f;
style.ChildRounding = 4.0f;
style.FrameRounding = 4.0f;
style.PopupRounding = 4.0f;
style.ScrollbarRounding = 9.0f;
style.GrabRounding = 4.0f;
style.TabRounding = 4.0f;
// Sizes and Spacing
style.WindowPadding = ImVec2(15.0f, 15.0f);
style.FramePadding = ImVec2(6.0f, 6.0f);
style.ItemSpacing = ImVec2(10.0f, 8.0f);
style.ScrollbarSize = 15.0f;
SetTargetFPS(60);
SetTraceLogLevel(TraceLogLevel::LOG_NONE);
InitWindow(screen_width, screen_height, "Bullet bird");
SetWindowState(FLAG_WINDOW_RESIZABLE);
while (!WindowShouldClose() && !g_Engine.shouldQuit){
float dt = GetFrameTime();
if (dt > 0.1f) dt = 0.1f; // cap dt just for now
scene_manager.update(dt);
BeginDrawing();
ClearBackground(RAYWHITE);
scene_manager.render();
rlImGuiBegin();
scene_manager.ui();
rlImGuiEnd();
EndDrawing();
scene_manager.process_scene_switch(); // !!! After scene_manager is done with the current loop
}
CloseWindow();
rlImGuiShutdown();
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
// src\movement.cpp
#include <entt/entt.hpp>
#include <components.hpp>
void update_movement_system(entt::registry& registry, float dt) {
// We get Position and Velocity, but EXCLUDE entities that have the Player tag
auto view = registry.view<Position, Velocity>();
view.each([dt](Position &position, Velocity &velocity) {
// This will only run for pipes, enemies, or particles!
position.x += velocity.dx * dt;
position.y += velocity.dy * dt;
});
}
+34
View File
@@ -0,0 +1,34 @@
// src\player.cpp
#include<raylib.h>
#include<entt/entt.hpp>
#include<components.hpp>
entt::entity player;
void create_player(entt::registry& registry,Texture* texture){
const auto entity = registry.create();
registry.emplace<Position>(entity,100.0f,0.0f);
registry.emplace<Velocity>(entity,0.0f,0.0f);
registry.emplace<Player>(entity);
registry.emplace<Sprite>(entity,texture);
}
void update_player_system(entt::registry& registry,float dt){
auto view = registry.view<const Player, Velocity>();
// Constants for fine-tuning game feel
const float GRAVITY = 900.0f; // Constant downward pull (pixels/sec^2)
const float JUMP_FORCE = -350.0f; // Negative force to burst UPWARD
view.each([dt,GRAVITY,JUMP_FORCE](const auto &player, auto &velocity){
if (IsKeyPressed(KEY_SPACE)){
velocity.dy = JUMP_FORCE;
}
velocity.dy += GRAVITY * dt;
});
}
+18
View File
@@ -0,0 +1,18 @@
#include <render.hpp>
#include <components.hpp>
#include<raylib.h>
#include <entt/entt.hpp>
void update_render_system(entt::registry &registry){
auto view = registry.view<const Sprite, const Position>();
view.each([] (const auto &sprite, const auto &position){
if (sprite.texture){
DrawTexture(*(sprite.texture),position.x,position.y,WHITE);
}else{
DrawRectangle(position.x,position.y,50, 70,BLACK);
}
});
}
+33
View File
@@ -0,0 +1,33 @@
#include <player.hpp>
#include <movement.hpp>
#include <scene.hpp>
#include <render.hpp>
#include <asset/raylib_asset.hpp>
GamePlayScene::GamePlayScene() {
registry = entt::registry();
asset_loader.load_asset("assets/bird.png");
create_player(registry,asset_loader.get_texture("assets/bird.png"));
}
void GamePlayScene::update(float dt) {
update_movement_system(registry, dt);
update_player_system(registry, dt);
}
void GamePlayScene::render() {
update_render_system(registry);
}
void GamePlayScene::ui() {
}
GamePlayScene::~GamePlayScene(){
asset_loader.unload_asset("assets/bird.png");
}
+56
View File
@@ -0,0 +1,56 @@
#include <player.hpp>
#include <movement.hpp>
#include <scene.hpp>
#include <imgui.h>
// #include <format>
MenuScene::MenuScene() {
}
void MenuScene::update(float dt) {
}
void MenuScene::render() {}
void MenuScene::ui() {
// Get the current screen/viewport size
ImVec2 screen_size = ImGui::GetIO().DisplaySize;
// size of button container
ImVec2 vbox_size = ImVec2(200.0f, 250.0f);
// set next container to be center of the screen
ImVec2 screen_center = ImVec2(screen_size.x * 0.5f, screen_size.y * 0.5f);
ImGui::SetNextWindowPos(screen_center, ImGuiCond_Always,ImVec2(0.5f, 0.5f));
ImGui::SetNextWindowSize(vbox_size);
// remove sub window decoration
ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground;
ImGui::Begin("VBoxContainer", nullptr, flags);
// set button width to be size fill container
ImVec2 button_size = ImVec2(ImGui::GetContentRegionAvail().x, 50.0f);
// ImGui::SetCursorPos(centeredPos);
if (ImGui::Button("Play",button_size)){
g_Engine.request_switch(SceneType::GAMEPLAY);
}
ImGui::Dummy(ImVec2(0, 10)); // Gap
if (ImGui::Button("Quit",button_size)){
g_Engine.quit();
}
ImGui::End();
// ImGui::Begin("Debug");
// ImGui::Button("Hello",button_size);
// ImGui::TextUnformatted(std::format("window size: {} {} ", screen_size.x,screen_size.y).c_str());
// ImGui::End();
}
+39
View File
@@ -0,0 +1,39 @@
#include <scene.hpp>
SceneManager::SceneManager(){
current_scene = new MenuScene();
}
SceneManager::~SceneManager(){
delete current_scene;
}
void SceneManager::process_scene_switch(){
if (!g_Engine.pendingSwitch) return;
delete current_scene;
switch(g_Engine.nextScene){
case SceneType::MENU:
current_scene = new MenuScene();
break;
case SceneType::GAMEPLAY:
current_scene = new GamePlayScene();
break;
}
g_Engine.pendingSwitch = false;
}
void SceneManager::update(float dt){
if (current_scene){
current_scene->update(dt);
}
}
void SceneManager::render(){
current_scene->render();
}
void SceneManager::ui(){
current_scene->ui();
}