diff --git a/README.md b/README.md index 43414e1..0ba3673 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ currently just kind of sits and wanders around you can right click to catmode +config is in `~/.config/funfriend/` or `%AppData%/funfriend/` or `~/Library/Application Support/funfriend` + ## installation grab yourself `SDL2`, `SDL2_mixer` and `GLFW` development libraries, then run diff --git a/src/configman.cr b/src/configman.cr new file mode 100644 index 0000000..b3034f3 --- /dev/null +++ b/src/configman.cr @@ -0,0 +1,80 @@ +require "file_utils" +require "ini" + +module Funfriend::ConfigMan + extend self + + APPLICATION_NAME = "funfriend" + + CONFIG_NAME = "cfg.ini" + + alias ConfigValue = String | Int32 | Bool + alias ConfigSection = Hash(String, ConfigValue) + alias Config = Hash(String, ConfigSection) + + DEFAULT_CONFIG = { + "window" => { + "funfriend_size" => 64.as(ConfigValue) + } + }.as(Config) + + def get_config_path : Path + {% if flag?(:windows) %} + Path.new(ENV["APPDATA"]) / APPLICATION_NAME + {% elsif flag?(:macosx) %} + Path.home / "Library" / "Application Support" / APPLCATION_NAME + {% elsif flag?(:unix) %} + (ENV["XDG_CONFIG_HOME"]?.try { |p| Path.new(p) } || (Path.home / ".config")) / APPLICATION_NAME + {% end %} + end + + @@config_initialized = false + @@config = {} of String => ConfigSection + + def config + if !@@config_initialized + raise "config read before initialization" + end + @@config + end + + def init + config_path = get_config_path + FileUtils.mkdir_p(config_path) + + config_file = config_path / CONFIG_NAME + + if !File.exists?(config_file) + @@config = DEFAULT_CONFIG.dup + File.write(config_file, INI.build(@@config)) + else + parsed = INI.parse(File.read(config_file)) + @@config = DEFAULT_CONFIG.dup + parsed.each do |sect_i, section| + section.each do |key, value| + # if it exists in the default config + if DEFAULT_CONFIG[sect_i]?.try &.[key]? + # try casting + casted_val = case DEFAULT_CONFIG[sect_i][key] + when String + value + when Int32 + puts "huh" + value.to_i32? + when Bool + value === "1" || value.downcase === "true" + end + + # casted_val being nil means it failed; fall back to default + if casted_val != nil + # write to config + @@config[sect_i][key] = casted_val.not_nil! + end + end + end + end + end + + @@config_initialized = true + end +end diff --git a/src/funfriend.cr b/src/funfriend.cr index 0816cf7..44e1f7e 100644 --- a/src/funfriend.cr +++ b/src/funfriend.cr @@ -6,6 +6,7 @@ require "crystimage" require "./log.cr" require "./ease.cr" require "./gl.cr" +require "./configman.cr" require "./textureman.cr" require "./fontman.cr" require "./soundman.cr" @@ -47,6 +48,7 @@ module Funfriend def self.run Logging.init + ConfigMan.init SoundMan.init CrystGLFW.run do diff --git a/src/funfriend_context.cr b/src/funfriend_context.cr index 9e6b9da..8d4e9de 100644 --- a/src/funfriend_context.cr +++ b/src/funfriend_context.cr @@ -1,5 +1,4 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext - WINDOW_SIZE = {width: 82, height: 82} CHATTER_TIMER = 3.0 CHATTER_ARRAY = [ @@ -32,7 +31,7 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext def initialize super( title: "??_FUNFRIEND_??", - width: WINDOW_SIZE[:width], height: WINDOW_SIZE[:height], + width: window_size[:width], height: window_size[:height], transparent: true ) @@ -70,11 +69,17 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext # pick a random pos monitor = Monitor.primary - window.position = { + random_pos = { x: monitor.position[:x] + (monitor.video_mode.size[:width] * rand((0.0..1.0))).to_i, y: monitor.position[:y] + (monitor.video_mode.size[:height] * rand((0.0..1.0))).to_i } - @static_pos = window.position + window.position = random_pos + @static_pos = random_pos + end + + def window_size + funfriend_size = ConfigMan.config["window"]["funfriend_size"].as(Int32) + {width: (funfriend_size * 1.3).to_i, height: (funfriend_size * 1.3).to_i} end def render(dt : Float64) @@ -82,7 +87,7 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext window.make_context_current # draw funfriend - renderer.render(dt, WINDOW_SIZE[:width], WINDOW_SIZE[:height]) + renderer.render(dt, window_size[:width], window_size[:height]) end def goto(pos : NamedTuple(x: Int32, y: Int32), dur : Float64) @@ -139,8 +144,8 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext end Funfriend.add_context(ChatterContext.new(text, { - x: window.position[:x] + WINDOW_SIZE[:width] // 2, - y: window.position[:y] + WINDOW_SIZE[:height] // 2 - 70 + x: window.position[:x] + window_size[:width] // 2, + y: window.position[:y] - 20 }, parent: self)) SoundMan.play_sound("assets/sfx/talk#{(1..8).sample}.ogg") diff --git a/src/funfriend_renderer.cr b/src/funfriend_renderer.cr index e167850..79fb768 100644 --- a/src/funfriend_renderer.cr +++ b/src/funfriend_renderer.cr @@ -1,5 +1,4 @@ class Funfriend::FunfriendRenderer - FUNFRIEND_SIZE = {width: 64, height: 64} FPS = 10.0 getter shader_program : Program @@ -17,6 +16,11 @@ class Funfriend::FunfriendRenderer @textures = init_textures end + def funfriend_size + funfriend_size = ConfigMan.config["window"]["funfriend_size"].as(Int32) + {width: funfriend_size, height: funfriend_size} + end + def init_textures return { "normal" => TextureMan::TextureBasket.new( @@ -96,7 +100,7 @@ class Funfriend::FunfriendRenderer frame[:tex].bind(Texture::Target::Texture2D) do shader_program.use do |shader| shader.set_uniform("texture1", 0) - shader.set_uniform("funfriendSize", FUNFRIEND_SIZE[:width].to_f32, FUNFRIEND_SIZE[:height].to_f32) + shader.set_uniform("funfriendSize", funfriend_size[:width].to_f32, funfriend_size[:height].to_f32) shader.set_uniform("resolution", window_width.to_f32, window_height.to_f32) shader.set_uniform("time", CrystGLFW.time.to_f32)