Add physics and level module

This commit is contained in:
2025-05-31 13:26:21 +02:00
parent b828bf6bd2
commit af6fd5fc45
8 changed files with 253 additions and 195 deletions

View File

@@ -13,6 +13,7 @@ find_package(spdlog CONFIG REQUIRED)
add_executable(HansTheGatherer
src/main.cpp
src/assets.cpp
src/physics.cpp
)
target_link_libraries(HansTheGatherer SDL3::SDL3 flecs::flecs spdlog::spdlog)

View File

@@ -1,6 +1,6 @@
#include "assets.hpp"
#include "audio.hpp"
#include "sdl_types.hpp"
#include "definitions.hpp"
#include <cstdint>
#include <spdlog/spdlog.h>

17
src/definitions.hpp Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include <SDL3/SDL.h>
static constexpr int WINDOW_WIDTH = 400;
static constexpr int WINDOW_HEIGHT = 240;
struct SdlHandles
{
SDL_Window* window;
SDL_Renderer* renderer;
};
struct Game
{
uint32_t ticks;
};

111
src/level.hpp Normal file
View File

@@ -0,0 +1,111 @@
#pragma once
#include "definitions.hpp"
#include "input.hpp"
#include "physics.hpp"
#include "sprite.hpp"
#include <flecs.h>
struct Fruit
{
};
struct Basket
{
};
struct LevelModule
{
LevelModule(flecs::world& world)
{
auto const* texture_assets = world.get<TextureAssets>();
world.entity("Background")
.set<Position>(Position{.x = 0, .y = 0})
.set<Sprite>(Sprite{.texture = &texture_assets->background, .texture_atlas_index = 0})
.set<Size>(Size{.w = WINDOW_WIDTH, .h = WINDOW_HEIGHT});
auto basket =
world.entity("Basket")
.add<WorldPosition>()
.set<Position>(Position{.x = WINDOW_WIDTH / 2 - 32, .y = WINDOW_HEIGHT - 32})
.set<Sprite>(Sprite{.texture = &texture_assets->basket, .texture_atlas_index = 0})
.set<Size>(Size{.w = 64, .h = 32})
.add<Basket>();
world.entity()
.child_of(basket)
.add<WorldPosition>()
.set<Position>(Position{.x = 0, .y = 0})
.set<Size>(Size{.w = 64, .h = 32})
.add<CollisionBox>();
world.system<Game const, TextureAssets const>("SpawnFruits")
.term_at(0)
.singleton()
.term_at(1)
.singleton()
.each(
[](flecs::iter& it,
size_t index,
Game const& game,
TextureAssets const& texture_assets)
{
if ((game.ticks % 100) == 0)
{
auto fruit =
it.world()
.entity()
.add<Fruit>()
.add<WorldPosition>()
.set<Position>(Position{
.x = static_cast<int>(game.ticks % WINDOW_WIDTH), .y = -16})
.set<Velocity>(Velocity{.x = 0, .y = 1})
.set<Sprite>(Sprite{.texture = &texture_assets.fruits,
.texture_atlas_index =
static_cast<uint16_t>(game.ticks % 228)})
.set<Size>(Size{.w = 32, .h = 32});
it.world()
.entity("CollisionBox")
.child_of(fruit)
.add<WorldPosition>()
.set<Position>(Position{.x = 0, .y = 0})
.set<Size>(Size{.w = 32, .h = 32})
.add<CollisionBox>();
}
});
// world.system<WorldPosition const, Fruit>("DespawnFruits")
// .each(
// [](flecs::entity e, WorldPosition const& pos, Fruit)
// {
// if (pos.y >= WINDOW_HEIGHT)
// e.destruct();
// });
world.system<ButtonInput const, Position, Size const, Sprite const, Basket>("MoveBasket")
.term_at(0)
.singleton()
.each(
[](ButtonInput const& input,
Position& pos,
Size const& size,
Sprite const& sprite,
Basket)
{
if (input.pressed.contains(SDLK_LEFT))
{
pos.x -= 5;
}
if (input.pressed.contains(SDLK_RIGHT))
{
pos.x += 5;
}
pos.x = pos.x < 0 ? 0 : pos.x;
pos.x = pos.x > WINDOW_WIDTH - size.w ? WINDOW_WIDTH - size.w : pos.x;
});
}
};

View File

@@ -1,6 +1,8 @@
#include "assets.hpp"
#include "definitions.hpp"
#include "input.hpp"
#include "sdl_types.hpp"
#include "level.hpp"
#include "physics.hpp"
#include "sprite.hpp"
#include <SDL3/SDL.h>
@@ -12,38 +14,6 @@
#include <flecs.h>
#include <spdlog/spdlog.h>
static constexpr int WINDOW_WIDTH = 400;
static constexpr int WINDOW_HEIGHT = 240;
struct WorldPosition
{
int x;
int y;
};
struct Position
{
int x;
int y;
};
struct Velocity
{
int x;
int y;
};
struct Size
{
int w;
int h;
};
struct Game
{
uint32_t ticks;
};
int main()
{
spdlog::info("Initialize SDL...");
@@ -69,137 +39,19 @@ int main()
}
flecs::world world;
world.set<Game>(Game{.ticks = 0});
world.set<ButtonInput>(ButtonInput{});
world.set<SdlHandles>(SdlHandles{.window = window, .renderer = renderer});
init_assets(world);
auto* texture_assets = world.get<TextureAssets>();
world.entity("Background")
.set<Position>(Position{.x = 0, .y = 0})
.set<Sprite>(Sprite{.texture = &texture_assets->background, .texture_atlas_index = 0})
.set<Size>(Size{.w = WINDOW_WIDTH, .h = WINDOW_HEIGHT});
struct Fruit
{
};
struct Basket
{
};
struct CollisionBox
{
};
world.import <PhysicsModule>();
world.import <LevelModule>();
world.system<Game>("IncrementTicks")
.term_at(0)
.singleton()
.each([](Game& game_ticks) { game_ticks.ticks += 1; });
auto basket =
world.entity("Basket")
.add<WorldPosition>()
.set<Position>(Position{.x = WINDOW_WIDTH / 2 - 32, .y = WINDOW_HEIGHT - 32})
.set<Sprite>(Sprite{.texture = &texture_assets->basket, .texture_atlas_index = 0})
.set<Size>(Size{.w = 64, .h = 32})
.add<Basket>();
world.entity("CollisionBox")
.child_of(basket)
.add<WorldPosition>()
.set<Position>(Position{.x = 0, .y = 0})
.set<Size>(Size{.w = 64, .h = 32})
.add<CollisionBox>();
world.system<SdlHandles const, WorldPosition const, Size const, CollisionBox>("DrawBoxes")
.term_at(0)
.singleton()
.each(
[](SdlHandles const& sdl_handles,
WorldPosition const& pos,
Size const& size,
CollisionBox)
{
SDL_FRect rect{static_cast<float>(pos.x),
static_cast<float>(pos.y),
static_cast<float>(size.w),
static_cast<float>(size.h)};
SDL_SetRenderDrawColor(sdl_handles.renderer, 0, 0, 255, 255);
SDL_RenderRect(sdl_handles.renderer, &rect);
});
world.system<Game const, TextureAssets const>("SpawnFruits")
.term_at(0)
.singleton()
.term_at(1)
.singleton()
.each(
[](flecs::iter& it, size_t index, Game const& game, TextureAssets const& texture_assets)
{
if ((game.ticks % 100) == 0)
{
auto fruit =
it.world()
.entity()
.add<WorldPosition>()
.set<Position>(Position{
.x = static_cast<int>(game.ticks % WINDOW_WIDTH), .y = -16})
.set<Velocity>(Velocity{.x = 0, .y = 1})
.set<Sprite>(Sprite{.texture = &texture_assets.fruits,
.texture_atlas_index =
static_cast<uint16_t>(game.ticks % 228)})
.set<Size>(Size{.w = 32, .h = 32});
it.world()
.entity("CollisionBox")
.child_of(fruit)
.add<WorldPosition>()
.set<Position>(Position{.x = 0, .y = 0})
.set<Size>(Size{.w = 32, .h = 32})
.add<CollisionBox>();
}
});
world.system<WorldPosition, Position const>("PropagatePosition")
.kind(flecs::PostUpdate)
.each(
[](flecs::entity e, WorldPosition& world_pos, Position const& local_pos)
{
if (e.parent() == flecs::entity::null())
{
world_pos.x = local_pos.x;
world_pos.y = local_pos.y;
}
else
{
auto parent_world_pos = e.parent().get<WorldPosition>();
world_pos.x = parent_world_pos->x + local_pos.x;
world_pos.y = parent_world_pos->y + local_pos.y;
}
});
world.system<WorldPosition const, Size const, CollisionBox>("CollisionCheck")
.each(
[](flecs::iter& it,
size_t index,
WorldPosition const& world_pos,
Size const& size,
CollisionBox)
{
auto basket_box = it.world().lookup("Basket::CollisionBox");
if (it.entity(index) == basket_box)
return;
auto basket_box_pos = basket_box.get<WorldPosition>();
auto basket_box_size = basket_box.get<Size>();
if (basket_box_pos->x + basket_box_size->w >= world_pos.x &&
basket_box_pos->x <= world_pos.x + size.w &&
basket_box_pos->y + basket_box_size->h >= world_pos.y &&
basket_box_pos->y <= world_pos.y + size.h)
{
spdlog::info("collision");
}
});
world.system<SdlHandles const, Position const, Size const, Sprite const>("RenderSprites")
.kind(flecs::PreUpdate)
.term_at(0)
@@ -227,37 +79,6 @@ int main()
sdl_handles.renderer, sprite.texture->sdl_texture, &srcrect, &dstrect);
});
world.system<ButtonInput const, Position, Size const, Sprite const, Basket>("MoveBasket")
.term_at(0)
.singleton()
.each(
[](ButtonInput const& input,
Position& pos,
Size const& size,
Sprite const& sprite,
Basket)
{
if (input.pressed.contains(SDLK_LEFT))
{
pos.x -= 5;
}
if (input.pressed.contains(SDLK_RIGHT))
{
pos.x += 5;
}
pos.x = pos.x < 0 ? 0 : pos.x;
pos.x = pos.x > WINDOW_WIDTH - size.w ? WINDOW_WIDTH - size.w : pos.x;
});
world.system<Position, Velocity const>("MoveSprites")
.each(
[](Position& pos, Velocity const& vel)
{
pos.x += vel.x;
pos.y += vel.y;
});
auto* audio_assets = world.get<AudioAssets>();
auto* stream = SDL_OpenAudioDeviceStream(
SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio_assets->background_music.spec, NULL, NULL);

81
src/physics.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include "physics.hpp"
#include "definitions.hpp"
#include "level.hpp"
#include <spdlog/spdlog.h>
PhysicsModule::PhysicsModule(flecs::world& world)
{
world.system<Position, Velocity const>("TranslatePhysicsObject")
.each(
[](Position& pos, Velocity const& vel)
{
pos.x += vel.x;
pos.y += vel.y;
});
// world.system<WorldPosition, Position const>("PropagatePosition")
// .kind(flecs::PostUpdate)
// .each(
// [](flecs::entity e, WorldPosition& world_pos, Position const& local_pos)
// {
// if (e.parent() == flecs::entity::null())
// {
// world_pos.x = local_pos.x;
// world_pos.y = local_pos.y;
// }
// else
// {
// auto parent_world_pos = e.parent().get<WorldPosition>();
// world_pos.x = parent_world_pos->x + local_pos.x;
// world_pos.y = parent_world_pos->y + local_pos.y;
// }
// });
world.system<SdlHandles const, WorldPosition const, Size const, CollisionBox>("DrawBoxes")
.term_at(0)
.singleton()
.each(
[](SdlHandles const& sdl_handles,
WorldPosition const& pos,
Size const& size,
CollisionBox)
{
SDL_FRect rect{static_cast<float>(pos.x),
static_cast<float>(pos.y),
static_cast<float>(size.w),
static_cast<float>(size.h)};
SDL_SetRenderDrawColor(sdl_handles.renderer, 0, 0, 255, 255);
SDL_RenderRect(sdl_handles.renderer, &rect);
});
auto basket_query = world.query<Basket>();
world.system<WorldPosition const, Size const, CollisionBox>("CollisionCheck")
.kind(flecs::OnValidate)
.each(
[basket_query](
flecs::entity e, WorldPosition const& world_pos, Size const& size, CollisionBox)
{
if (e.parent().has<Basket>())
return;
basket_query.first().children(
[world_pos, size](flecs::entity basket_child)
{
if (!basket_child.has<CollisionBox>())
return;
auto basket_child_pos = basket_child.get<WorldPosition>();
auto basket_child_size = basket_child.get<Size>();
if (basket_child_pos->x + basket_child_size->w >= world_pos.x &&
basket_child_pos->x <= world_pos.x + size.w &&
basket_child_pos->y + basket_child_size->h >= world_pos.y &&
basket_child_pos->y <= world_pos.y + size.h)
{
spdlog::info("collision");
}
});
});
}

36
src/physics.hpp Normal file
View File

@@ -0,0 +1,36 @@
#pragma once
#include <flecs.h>
struct WorldPosition
{
int x;
int y;
};
struct Position
{
int x;
int y;
};
struct Velocity
{
int x;
int y;
};
struct Size
{
int w;
int h;
};
struct CollisionBox
{
};
struct PhysicsModule
{
PhysicsModule(flecs::world& world);
};

View File

@@ -1,9 +0,0 @@
#pragma once
#include <SDL3/SDL.h>
struct SdlHandles
{
SDL_Window* window;
SDL_Renderer* renderer;
};