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

Bloom Options using Database #154

Merged
merged 10 commits into from
Jan 26, 2024
2 changes: 1 addition & 1 deletion assets/data/backgrounds.ron
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
star_position_x_range: ( start: -90.0, end: -30.0),
star_position_z_range: (start: -250.0, end: -150.0),
planet_translation: (8.0, -8.0, 30.0),
star_color_range: (start: 0.0, end: 15.0),
star_color_range: (start: 0.0, end: 1.0),
background_quad_width: 375.0,
background_quad_height: 375.0,
background_alpha: 0.06,
Expand Down
1 change: 1 addition & 0 deletions crates/thetawave_interface/src/game/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

/// Resources/singletons with the within-game/run counts/metrics.
pub mod historical_metrics;
pub mod options;
12 changes: 12 additions & 0 deletions crates/thetawave_interface/src/game/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use bevy_ecs::system::Resource;
use serde::Deserialize;

pub const DEFAULT_OPTIONS_PROFILE_ID: usize = 1;

/// The 'model' of the Options Sqlite table.
/// Defaults the least graphically intense options.
#[derive(Debug, Default, Clone, Deserialize, Resource)]
pub struct GameOptions {
pub bloom_enabled: bool,
pub bloom_intensity: f32,
}
23 changes: 21 additions & 2 deletions crates/thetawave_storage/src/core.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy::prelude::info;
use bevy::log::info;
use directories::ProjectDirs;
use rusqlite;
use rusqlite::Connection;
use rusqlite::{self, OptionalExtension};
use std::env::var_os;
use std::ffi::OsStr;
use std::path::PathBuf;
Expand All @@ -10,6 +10,7 @@ pub(super) const THETAWAVE_DB_PATH_ENVVAR: &'static str = "THETAWAVE_DB_PATH";
const THETAWAVE_DB_FILE: &'static str = "thetawave.sqlite";
pub(super) const USERSTAT: &'static str = "UserStat";
pub(super) const ENEMY_KILL_HISTORY_TABLE_NAME: &'static str = "EnemiesKilled";
pub(super) const OPTIONS_TABLE_NAME: &'static str = "Options";

#[derive(Error, Debug, derive_more::From)]
pub(super) enum OurDBError {
Expand Down Expand Up @@ -56,9 +57,27 @@ pub(super) fn setup_db(conn: Connection) -> rusqlite::Result<()> {
PRIMARY KEY (userId, enemyMobType)
)"
);

let create_options_table_sql = format!(
"CREATE TABLE IF NOT EXISTS {OPTIONS_TABLE_NAME} (
optionsProfileId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
cdsupina marked this conversation as resolved.
Show resolved Hide resolved
bloomEnabled BOOLEAN NOT NULL DEFAULT TRUE,
bloomIntensity REAL NOT NULL DEFAULT 1.0
)"
);

conn.execute(&create_user_stats_sql, []).map(|_| ())?;
conn.execute(&create_enemies_killed_table_sql, [])
.map(|_| ())?;
conn.execute(&create_options_table_sql, []).map(|_| ())?;

// insert a default options row if it is not in the db
let default_options_row_exists: Option<u32> = conn
.query_row("SELECT 1 FROM Options LIMIT 1", [], |row| row.get(0))
.optional()?;
if default_options_row_exists.is_none() {
conn.execute("INSERT INTO Options DEFAULT VALUES", [])?;
}
Copy link
Contributor

@varoonp123 varoonp123 Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To just make sure a row is always in the table:

// Ensure that the default options profile is _always_ usable. 
let upsert_default_gameopts_sql = format!("INSERT OR REPLACE INTO {} (optionsProfileId, bloomEnabled, bloomIntensity) VALUES (?1, TRUE, 1.0) ON CONFLICT REPLACE", OPTIONS_TABLE_NAME);
conn.execute(upsert_default_gameopts_sql. [DEFAULT_OPTIONS_PROFILE_ID])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like having "INSERT OR REPLACE" and "ON CONFLICT REPLACE" doesn't work. Looks like having just "INSERT OR REPLACE" is the way to go, let me know if I'm missing something.

info!("Created sqlite db");
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions crates/thetawave_storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
/// thetawave releases. There are public functions to read data (exposing as few db implementation details as possible),
/// while all upserts/mutations/deletions are handled via a Bevy plugin.
pub mod core;
pub mod options;
pub mod plugin;
pub mod user_stats;
37 changes: 37 additions & 0 deletions crates/thetawave_storage/src/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::core::{get_db, OurDBError, OPTIONS_TABLE_NAME};
use bevy::log::error;
use rusqlite::Result;

use thetawave_interface::game::options::GameOptions;

fn _get_game_options(options_profile_id: usize) -> Result<Option<GameOptions>, OurDBError> {
let conn = get_db()?;
let stmt_raw = format!(
"
SELECT bloomEnabled, bloomIntensity FROM {OPTIONS_TABLE_NAME}
WHERE optionsProfileId=?1
"
);
let mut stmt = conn.prepare(&stmt_raw)?;
let mut rows = stmt.query([options_profile_id])?;
match rows.next()? {
Some(r) => {
let bloom_enabled = r.get(0)?;
let bloom_intensity = r.get(1)?;
Ok(Some(GameOptions {
bloom_enabled,
bloom_intensity,
}))
}

None => Ok(None),
}
}

/// Returns all of the options in the game.
pub fn get_game_options(options_profile_id: usize) -> Option<GameOptions> {
_get_game_options(options_profile_id).unwrap_or_else(|err| {
error!("Could not read game options. {}", &err);
None
})
}
15 changes: 14 additions & 1 deletion crates/thetawave_storage/src/plugin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/// Exposes a single Plugin that links the game and our persistence layer.
use bevy::prelude::*;
use thetawave_interface::game::options::{GameOptions, DEFAULT_OPTIONS_PROFILE_ID};

use crate::options::get_game_options;
use crate::user_stats::{
get_mob_killed_counts_for_user, get_user_stats, set_user_stats_for_user_id,
};
Expand Down Expand Up @@ -47,7 +49,11 @@ impl Plugin for DBPlugin {
app.add_systems(OnEnter(states::AppStates::LoadingAssets), db_setup_system);
app.add_systems(
OnExit(states::AppStates::LoadingAssets),
(load_user_stats_cache_from_db, load_mob_kills_cache_from_db),
(
load_user_stats_cache_from_db,
load_mob_kills_cache_from_db,
load_game_options_from_db,
),
);
app.add_systems(
OnExit(states::AppStates::GameOver),
Expand All @@ -58,6 +64,13 @@ impl Plugin for DBPlugin {
);
}
}

fn load_game_options_from_db(mut game_options: ResMut<GameOptions>) {
if let Some(db_game_options) = get_game_options(DEFAULT_OPTIONS_PROFILE_ID) {
*game_options = db_game_options;
}
}

fn load_user_stats_cache_from_db(
mut user_stats_cache: ResMut<UserStatsByPlayerForCompletedGamesCache>,
) {
Expand Down
8 changes: 6 additions & 2 deletions src/assets/consumable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ impl ConsumableAssets {
}

#[allow(unused)] // Placeholder for if we put this in the item config files
pub fn get_color(&self, consumable_type: &ConsumableType) -> Color {
Color::rgb(1.6, 1.6, 1.6)
pub fn get_color(&self, consumable_type: &ConsumableType, bloom_intensity: f32) -> Color {
Color::rgb(
1.0 + 0.6 * bloom_intensity,
1.0 + 0.6 * bloom_intensity,
1.0 + 0.6 * bloom_intensity,
)
}
}
64 changes: 52 additions & 12 deletions src/assets/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,59 @@ impl EffectAssets {
}
}

pub fn get_color(&self, effect_type: &EffectType) -> Color {
pub fn get_color(&self, effect_type: &EffectType, bloom_intensity: f32) -> Color {
match effect_type {
EffectType::BarrierGlow => Color::rgb(1.0, 1.0, 1.4),
EffectType::AllyBlastExplosion => Color::rgb(4.0, 4.0, 4.0),
EffectType::EnemyBlastExplosion => Color::rgb(4.0, 4.0, 4.0),
EffectType::AllyBulletExplosion => Color::rgb(5.0, 5.0, 5.0),
EffectType::EnemyBulletExplosion => Color::rgb(5.0, 5.0, 5.0),
EffectType::MobExplosion => Color::rgb(6.0, 6.0, 6.0),
EffectType::AllyBlastDespawn => Color::rgb(4.0, 4.0, 4.0),
EffectType::ConsumableDespawn => Color::rgb(3.0, 3.0, 3.0),
EffectType::EnemyBlastDespawn => Color::rgb(4.0, 4.0, 4.0),
EffectType::AllyBulletDespawn => Color::rgb(5.0, 5.0, 5.0),
EffectType::EnemyBulletDespawn => Color::rgb(5.0, 5.0, 5.0),
EffectType::BarrierGlow => Color::rgb(1.0, 1.0, 1.0 + 0.4 * bloom_intensity),
EffectType::AllyBlastExplosion => Color::rgb(
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
),
EffectType::EnemyBlastExplosion => Color::rgb(
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
),
EffectType::AllyBulletExplosion => Color::rgb(
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
),
EffectType::EnemyBulletExplosion => Color::rgb(
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
),
EffectType::MobExplosion => Color::rgb(
1.0 + 5.0 * bloom_intensity,
1.0 + 5.0 * bloom_intensity,
1.0 + 5.0 * bloom_intensity,
),
EffectType::AllyBlastDespawn => Color::rgb(
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
),
EffectType::ConsumableDespawn => Color::rgb(
1.0 + 2.0 * bloom_intensity,
1.0 + 2.0 * bloom_intensity,
1.0 + 2.0 * bloom_intensity,
),
EffectType::EnemyBlastDespawn => Color::rgb(
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
1.0 + 3.0 * bloom_intensity,
),
EffectType::AllyBulletDespawn => Color::rgb(
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
),
EffectType::EnemyBulletDespawn => Color::rgb(
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
1.0 + 4.0 * bloom_intensity,
),
EffectType::Text(_) => Color::rgb(0.0, 0.0, 0.0),
}
}
Expand Down
20 changes: 16 additions & 4 deletions src/assets/mob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,23 @@ impl MobAssets {
}
}

pub fn get_thruster_color(&self, mob_type: &MobType) -> Color {
pub fn get_thruster_color(&self, mob_type: &MobType, bloom_intensity: f32) -> Color {
match mob_type {
MobType::Enemy(_) => Color::rgb(3.8, 2.2, 1.0),
MobType::Ally(_) => Color::rgb(3.8, 2.2, 1.0),
MobType::Neutral(_) => Color::rgb(3.8, 2.2, 1.0),
MobType::Enemy(_) => Color::rgb(
1.0 + 2.8 * bloom_intensity,
1.0 + 1.2 * bloom_intensity,
1.0,
),
MobType::Ally(_) => Color::rgb(
1.0 + 2.8 * bloom_intensity,
1.0 + 1.2 * bloom_intensity,
1.0,
),
MobType::Neutral(_) => Color::rgb(
1.0 + 2.8 * bloom_intensity,
1.0 + 1.2 * bloom_intensity,
1.0,
),
}
}
}
14 changes: 11 additions & 3 deletions src/assets/projectile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,18 @@ impl ProjectileAssets {
},
}
}
pub fn get_color(&self, projectile_type: &ProjectileType) -> Color {
pub fn get_color(&self, projectile_type: &ProjectileType, bloom_intensity: f32) -> Color {
match projectile_type {
ProjectileType::Blast(_) => Color::rgb(3.0, 3.0, 3.0),
ProjectileType::Bullet(_) => Color::rgb(2.0, 2.0, 2.0),
ProjectileType::Blast(_) => Color::rgb(
1.0 + 2.0 * bloom_intensity,
1.0 + 2.0 * bloom_intensity,
1.0 + 2.0 * bloom_intensity,
),
ProjectileType::Bullet(_) => Color::rgb(
1.0 + 1.0 * bloom_intensity,
1.0 + 1.0 * bloom_intensity,
1.0 + 1.0 * bloom_intensity,
),
}
}
}
11 changes: 8 additions & 3 deletions src/background/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use ron::de::from_bytes;
use serde::Deserialize;
use std::ops::Range;
use thetawave_interface::{
game::options::GameOptions,
run::{RunDefeatType, RunEndEvent, RunOutcomeType},
states::{self, GameCleanup},
};
Expand Down Expand Up @@ -159,6 +160,7 @@ pub fn create_background_system(
mut materials: ResMut<Assets<StandardMaterial>>,
mut star_explode_res: ResMut<StarExplodeResource>,
backgrounds_res: Res<BackgroundsResource>,
game_options: Res<GameOptions>,
) {
// reset the star explode reource
*star_explode_res = StarExplodeResource::default();
Expand Down Expand Up @@ -280,9 +282,12 @@ pub fn create_background_system(

// Spawn a star with a random color
let star_color = Color::rgb_linear(
rng.gen_range(backgrounds_res.star_color_range.clone()),
rng.gen_range(backgrounds_res.star_color_range.clone()),
rng.gen_range(backgrounds_res.star_color_range.clone()),
rng.gen_range(backgrounds_res.star_color_range.clone())
+ 10.0 * game_options.bloom_intensity,
rng.gen_range(backgrounds_res.star_color_range.clone())
+ 10.0 * game_options.bloom_intensity,
rng.gen_range(backgrounds_res.star_color_range.clone())
+ 10.0 * game_options.bloom_intensity,
);

// Emissive colored star material for bloom
Expand Down
41 changes: 40 additions & 1 deletion src/options/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! `thetawave` player module
use bevy::prelude::*;
use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*};
use leafwing_input_manager::prelude::InputManagerPlugin;
use thetawave_interface::{
game::options::GameOptions,
input::{InputsResource, MenuAction},
states,
};
Expand Down Expand Up @@ -51,6 +52,41 @@ impl GameInitCLIOptions {
Default::default()
}
}

pub fn apply_game_options(
mut game_options: ResMut<GameOptions>,
mut camera_2d_query: Query<
(&mut Camera, &mut Tonemapping),
(With<Camera2d>, Without<Camera3d>),
>,
mut camera_3d_query: Query<
(&mut Camera, &mut Tonemapping),
(With<Camera3d>, Without<Camera2d>),
>,
) {
let (mut camera_2d, mut tonemapping_2d) = match camera_2d_query.get_single_mut() {
Ok(camera) => camera,
Err(_) => panic!("Didn't find exactly one 2D camera to apply bloom settings to."),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What.

Why.

How.

Maybe

if let ((mut camera_2d, mut tonemapping_2d), (mut camera_3d, tonemapping_3d)) = (camera_2d_query.get_single_mut(), camera_3d_query.get_single_mut()) {

}
else {
    error!("Failed to get singleton 2d and 3d cameras to apply game opts");
}

};

let (mut camera_3d, mut tonemapping_3d) = match camera_3d_query.get_single_mut() {
Ok(camera) => camera,
Err(_) => panic!("Didn't find exactly one 3D camera to apply bloom settings to."),
};

camera_2d.hdr = game_options.bloom_enabled;
camera_3d.hdr = game_options.bloom_enabled;

if game_options.bloom_enabled {
*tonemapping_2d = Tonemapping::TonyMcMapface;
*tonemapping_3d = Tonemapping::TonyMcMapface;
} else {
*tonemapping_2d = Tonemapping::None;
*tonemapping_3d = Tonemapping::None;
game_options.bloom_intensity = 0.0;
}
}

/// Whether we are playing on an arcade machine. This affects some different UI elements.
/// Generally this will be set at app startup (either inferred or explicitly provided as a game
/// startup parameter, and should probably not be mutated during the game.
Expand All @@ -68,6 +104,7 @@ impl Plugin for OptionsPlugin {

app.insert_resource(InputsResource::from(get_input_bindings()));
app.insert_resource(PlayingOnArcadeResource(self.arcade));
app.insert_resource(GameOptions::default());

app.add_systems(Startup, spawn_menu_explorer_system);

Expand All @@ -80,6 +117,8 @@ impl Plugin for OptionsPlugin {
Update,
toggle_zoom_system.run_if(in_state(states::AppStates::Game)),
);

app.add_systems(OnEnter(states::AppStates::MainMenu), apply_game_options);
}
}

Expand Down
Loading
Loading