Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.3 #15

Merged
merged 11 commits into from
Jan 27, 2024
Merged

v0.3 #15

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(project_prefix bave)
project(${project_prefix} VERSION 0.2.0)
project(${project_prefix} VERSION 0.3.0)

set(is_root_project FALSE)

Expand All @@ -15,10 +15,6 @@ endif()

set(build_tests ${is_root_project})

if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set(build_tests FALSE)
endif()

option(BAVE_USE_PCH "Use PCH for bave builds" ON)
option(BAVE_BUILD_EXAMPLE "Build bave example" ${is_root_project})
option(BAVE_BUILD_TESTS "Build bave tests" ${build_tests})
Expand Down
2,806 changes: 2,806 additions & 0 deletions Doxyfile

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ https://github.com/karnkaul/bave/assets/16272243/86539229-0640-42c5-baac-ca74eb3
- [x] Audio playback.
- [x] Streaming audio (music).

## API Reference

Documentation is located [here](https://karnkaul.github.io/bave-docs/).

## Requirements

### Runtime
Expand Down
2 changes: 1 addition & 1 deletion example/desktop/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ auto main(int argc, char** argv) -> int {
auto const create_info = bave::DesktopApp::CreateInfo{
.args = bave::make_args(argc, argv),
.title = "BaveExample",
.extent = {720, 1280},
.mode = bave::Windowed{.extent = {720, 1280}},
.assets_patterns = "assets,example/assets",
};

Expand Down
2 changes: 1 addition & 1 deletion example/flappy/src/pipes.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include <bave/core/random.hpp>
#include <bave/graphics/sprite.hpp>
#include <bave/graphics/sprite_9slice.hpp>
#include <src/config.hpp>

class Pipes {
Expand Down
8 changes: 8 additions & 0 deletions lib/docs/main_page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
\mainpage bave API Reference

`bave` stands for "BAsic Vulkan Engine" and is a 2D game engine library that can target desktop and/or Android.

This documentation is a WIP.

- <a href="files.html">File List</a>: all interface headers, effectively the entire public API.

81 changes: 72 additions & 9 deletions lib/include/bave/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,88 @@
#include <vector>

namespace bave {
enum struct ErrCode : int { eSuccess = 0, eFailure = 1 };
/// \brief Error code.
enum struct ErrCode : int { eSuccess = EXIT_SUCCESS, eFailure = EXIT_FAILURE };

/// \brief Application API and entrypoint.
///
/// Owns window, devices, game and event loops.
/// Customized via Driver sub-class.
class App : public PolyPinned {
public:
/// \brief Individual feature flags.
struct Feature {
static constexpr std::size_t resizeable{0};
static constexpr std::size_t has_title{1};
static constexpr std::size_t has_icon{2};
static constexpr std::size_t validation_layers{3};

static constexpr std::size_t count_v{8};
};
/// \brief Bitset of feature flags.
using FeatureFlags = std::bitset<Feature::count_v>;

/// \brief Driver Factory.
using Bootloader = std::function<std::unique_ptr<class Driver>(App&)>;

explicit App(std::string tag = "App");

/// \brief Set Bootloader.
/// \param bootloader Driver factory callback.
///
/// App will create a Driver after successful initialization of the window and devices.
void set_bootloader(Bootloader bootloader);
/// \brief Set custom DataStore.
/// \param data_store store instance to use.
/// \pre data_store should not be null.
void set_data_store(std::unique_ptr<DataStore> data_store);

/// \brief Run the game loop.
/// \returns Error code.
auto run() -> ErrCode;

/// \brief Request shutdown.
void shutdown();
/// \brief Check if shutting down.
/// \returns true if shutting down.
[[nodiscard]] auto is_shutting_down() const { return m_shutting_down; }

auto set_window_size(glm::ivec2 size) -> bool { return do_set_window_size(size); }
/// \brief Set window size.
/// \returns true if success.
///
/// Android windows cannot be resized.
auto set_window_size(glm::ivec2 const size) -> bool { return do_set_window_size(size); }
/// \brief Set framebuffer size.
/// \returns true if success.
///
/// Android windows cannot be resized.
auto set_framebuffer_size(glm::ivec2 size) -> bool;
/// \brief Set window icons.
/// \returns true if success.
///
/// Android windows do not have icons.
auto set_window_icon(std::span<BitmapView const> bitmaps) -> bool { return do_set_window_icon(bitmaps); }
/// \brief Set the window title.
/// \returns true if success.
///
/// Android windows do not have a title.
auto set_title(CString title) -> bool { return do_set_title(title); }

/// \brief Load a shader for drawing.
/// \param vertex URI of vertex shader (SPIR-V).
/// \param fragment URI of fragment shader (SPIR-V).
/// \returns Shader if loaded successfully.
///
/// Loaded shaders are cached and not reloaded on every call.
/// A Shader instance is intended to be temporary, within a draw scope.
[[nodiscard]] auto load_shader(std::string_view vertex, std::string_view fragment) const -> std::optional<Shader>;

/// \brief Change the data store mount point.
/// \param directory Directory to mount.
/// \returns true on success.
///
/// Mount point is fixed on Android.
auto change_mount_point(std::string_view directory) -> bool;

[[nodiscard]] auto get_features() const -> FeatureFlags;

[[nodiscard]] auto get_data_store() const -> DataStore& { return *m_data_store; }
[[nodiscard]] auto get_render_device() const -> RenderDevice& { return do_get_render_device(); }
Expand All @@ -58,12 +122,9 @@ class App : public PolyPinned {
[[nodiscard]] auto get_timer() -> Timer& { return m_timer; }
[[nodiscard]] auto get_driver() const -> Ptr<Driver> { return do_get_driver(); }

[[nodiscard]] auto load_shader(std::string_view vertex, std::string_view fragment) const -> std::optional<Shader>;

auto change_mount_point(std::string_view directory) -> bool;
auto set_title(CString title) -> bool { return do_set_title(title); }

protected:
explicit App(std::string tag = "App");

void start_next_frame();
void push_event(Event event);
void push_drop(std::string path);
Expand All @@ -83,6 +144,7 @@ class App : public PolyPinned {

virtual void do_shutdown() = 0;

[[nodiscard]] virtual auto do_get_native_features() const -> FeatureFlags { return {}; }
[[nodiscard]] virtual auto do_get_window_size() const -> glm::ivec2 { return do_get_framebuffer_size(); }
[[nodiscard]] virtual auto do_get_framebuffer_size() const -> glm::ivec2 = 0;

Expand All @@ -92,6 +154,7 @@ class App : public PolyPinned {

virtual auto do_set_window_size(glm::ivec2 size) -> bool = 0;
virtual auto do_set_title(CString /*title*/) -> bool { return false; }
virtual auto do_set_window_icon(std::span<BitmapView const> /*bitmaps*/) -> bool { return false; }

void pre_tick();

Expand Down
9 changes: 9 additions & 0 deletions lib/include/bave/audio/audio_clip.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@
#include <capo/state.hpp>

namespace bave {
/// \brief Compression of a PCM datastream.
using Compression = capo::Compression;
/// \brief State of audio source.
using AudioState = capo::State;

/// \brief Storage for PCM audio.
class AudioClip {
public:
/// \brief Attempt to load PCM data.
/// \param bytes Compressed bytestream.
/// \param compression Type of audio compression.
/// \returns true if successful.
auto load_from_bytes(std::span<std::byte const> bytes, Compression compression = Compression::eUnknown) -> bool;

/// \brief Obtain a clip (view) into the stored PCM data.
/// \returns View into stored PCM data.
[[nodiscard]] auto get_clip() const -> capo::Clip { return m_pcm.pcm.clip(); }

explicit operator bool() const { return !!m_pcm; }
Expand Down
24 changes: 24 additions & 0 deletions lib/include/bave/audio/audio_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,46 @@
#include <vector>

namespace bave {
/// \brief Audio source for sounds (SFX).
using SoundSource = capo::SoundSource;
/// \brief Audio source for streams (music).
using StreamSource = capo::StreamSource;

/// \brief Audio device.
class AudioDevice {
public:
/// \brief Default maximum managed SFXs that will play simultaneously.
static constexpr std::size_t max_sfxs_v{16};

/// \brief Create a new SoundSource.
/// \returns SoundSource instance.
[[nodiscard]] auto make_sound_source() const -> SoundSource { return m_device.make_sound_source(); }
/// \brief Create a new StreamSource.
/// \returns StreamSource instance.
[[nodiscard]] auto make_stream_source() const -> StreamSource { return m_device.make_stream_source(); }

/// \brief Obtain the maximum number of managed SFXs.
/// \returns Number of maximum managed SFXs.
[[nodiscard]] auto get_max_sfxs() const -> std::size_t { return m_max_sfxs; }
/// \brief Set the maximum number of managed SFXs.
/// \param count Number of maximum managed SFXs.
void set_max_sfxs(std::size_t count);

/// \brief Play an audio clip once using a managed SFX.
/// \param clip Clip to play.
/// \param gain Gain to play at.
///
/// Clip data is copied to the native audio device before playback,
/// so it does not need to be stored on the user side.
void play_once(AudioClip const& clip, float gain = 1.0f) const;
/// \brief Loop an audio clip.
/// \param clip Clip to play.
/// \returns SoundSource that will be playing the clip.
///
/// The clip will keep looping until the returned SoundSource is destroyed / modified.
[[nodiscard]] auto play_looped(AudioClip const& clip) const -> SoundSource;

/// \brief Master gain for managed SFX.
float sfx_gain{1.0f};

private:
Expand Down
23 changes: 21 additions & 2 deletions lib/include/bave/audio/audio_streamer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,44 @@
#include <optional>

namespace bave {
/// \brief Audio streamer with crossfade support.
class AudioStreamer {
public:
/// \brief Handle for a paused stream.
struct Pause {};

AudioStreamer(AudioDevice const& audio_device);
/// \brief Implicit constructor.
/// \param audio_device AudioDevice.
/*implicit*/ AudioStreamer(AudioDevice const& audio_device);

/// \brief Start playing an audio clip.
/// \param clip Clip to play.
/// \param cross_fade Time to cross fade to full gain.
void play(NotNull<std::shared_ptr<AudioClip>> const& clip, Seconds cross_fade = 1s);
/// \brief Stop playback(if playing a stream).
void stop() { m_primary.stream.stop(); }
/// \brief Seek to time (if playing a stream).
/// \param time Position to seek to.
void seek(Seconds time) { m_primary.stream.seek(time); }

/// \brief Pause playback (if playing a stream).
/// \returns Token that must be passed back in resume().
[[nodiscard]] auto pause() -> std::optional<Pause>;
/// \brief Resume playback (if paused).
void resume(Pause);

/// \brief Obtain the current playback position.
/// \returns Playback position in Seconds.
[[nodiscard]] auto get_cursor() const -> Seconds { return m_primary.stream.cursor(); }
/// \brief Obtain the current playback state.
/// \returns Playback state.
[[nodiscard]] auto get_state() const -> AudioState { return m_primary.stream.state(); }

/// \brief Update (for cross fading).
/// \param dt Time elapsed since last call.
void tick(Seconds dt);

//! Master gain for streaming audio.
/// \brief Master gain for streaming audio.
float gain{1.0f};

private:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#include <platform/desktop/clap/from_string.hpp>
#include <bave/clap/from_string.hpp>
#include <concepts>
#include <memory>
#include <span>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include <bave/clap/clap.hpp>
#include <bave/core/error.hpp>
#include <platform/desktop/clap/clap.hpp>
#include <span>

namespace bave::clap {
Expand Down
9 changes: 8 additions & 1 deletion lib/include/bave/core/c_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@
#include <string_view>

namespace bave {
/// \brief Wrapper over a C string (char const*).
class CString {
public:
CString() = default;

constexpr CString(char const* text) : text(text) {}
/// \brief Implicit constructor.
/// \param text string to store.
/*implicit*/ constexpr CString(char const* text) : text(text) {}

/// \brief View as C string.
/// \returns const pointer to first char (of empty string by default, not nullptr).
[[nodiscard]] constexpr auto c_str() const -> char const* { return text; }
/// \brief View as string_view.
/// \returns std::string_view into stored string.
[[nodiscard]] constexpr auto as_view() const -> std::string_view { return c_str(); }

constexpr operator std::string_view() const { return as_view(); }
Expand Down
4 changes: 4 additions & 0 deletions lib/include/bave/core/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
#include <fmt/format.h>

namespace bave {
/// \brief Base class for all errors thrown within bave.
class Error : public std::runtime_error {
public:
/// \brief Constructor.
/// \param fmt Format string.
/// \param args Arguments.
template <typename... Args>
explicit Error(fmt::format_string<Args...> fmt, Args&&... args) : std::runtime_error{fmt::format(fmt, std::forward<Args>(args)...)} {}
};
Expand Down
Loading