started audio library; theming
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Mar 2022 20:40:32 +0000 (14:40 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 1 Mar 2022 20:40:32 +0000 (14:40 -0600)
17 files changed:
run_tree/assets/images/background.png [new file with mode: 0644]
run_tree/assets/images/spritesheet.png
run_tree/assets/sounds/knock-1.wav [new file with mode: 0644]
run_tree/assets/sounds/prompt-1.wav [new file with mode: 0644]
run_tree/assets/sounds/walk-1.wav [new file with mode: 0644]
run_tree/scenes/quick_save_new.scene
src/build.onyx
src/entity/components/dispenser.onyx
src/entity/components/patron.onyx
src/entity/components/player.onyx
src/entity/editor.onyx
src/entity/manager.onyx
src/entity/schematics/background.onyx [new file with mode: 0644]
src/entity/schematics/player.onyx
src/game.onyx
src/sfx/audio_manager.onyx [new file with mode: 0644]
src/sfx/wav_file.onyx [new file with mode: 0644]

diff --git a/run_tree/assets/images/background.png b/run_tree/assets/images/background.png
new file mode 100644 (file)
index 0000000..d8e1a10
Binary files /dev/null and b/run_tree/assets/images/background.png differ
index fc47fea25b02c9ca15249c7047f8d56f67f8a95a..b5bd7b68479b88f1cd09f188652034cfcfa9f32e 100644 (file)
Binary files a/run_tree/assets/images/spritesheet.png and b/run_tree/assets/images/spritesheet.png differ
diff --git a/run_tree/assets/sounds/knock-1.wav b/run_tree/assets/sounds/knock-1.wav
new file mode 100644 (file)
index 0000000..f654b5a
Binary files /dev/null and b/run_tree/assets/sounds/knock-1.wav differ
diff --git a/run_tree/assets/sounds/prompt-1.wav b/run_tree/assets/sounds/prompt-1.wav
new file mode 100644 (file)
index 0000000..4214420
Binary files /dev/null and b/run_tree/assets/sounds/prompt-1.wav differ
diff --git a/run_tree/assets/sounds/walk-1.wav b/run_tree/assets/sounds/walk-1.wav
new file mode 100644 (file)
index 0000000..eb822ab
Binary files /dev/null and b/run_tree/assets/sounds/walk-1.wav differ
index 516a9a19df055ff771379329fe38df489bdfa9fe..8c8df206afb9d697a8d08a5ebc03d1eea274d6a6 100644 (file)
@@ -1,3 +1,15 @@
+[Background]
+id = 100
+flags = 0
+pos.x = 0
+pos.y = 0
+:RenderComponent
+layer = -1
+color.r = 1
+color.g = 1
+color.b = 1
+color.a = 1
+
 [Wall]
 id = 10
 flags = 2
@@ -29,10 +41,10 @@ color.a = 1.0000
 [Player]
 id = 12
 flags = 2
-pos.x = 318.3422
-pos.y = 217.0257
+pos.x = 312.5422
+pos.y = 271.0389
 size.x = 16.0000
-size.y = 16.0000
+size.y = 32.0000
 :MovementComponent
 controls.up = 87
 controls.down = 83
@@ -41,10 +53,12 @@ controls.right = 68
 controls.interact = 70
 controls.pick_up = 71
 facing = 3
+velocity.x = -0.4420
+velocity.y = 0.4767
 :PlayerComponent
 holding = 0
 :RenderComponent
-layer = 0
+layer = 10
 color.r = 0.0000
 color.g = 1.0000
 color.b = 0.0000
@@ -119,26 +133,6 @@ color.a = 1.0000
 item = "beer"
 max_timeout = 2.0000
 
-[Patron]
-id = 22
-flags = 3
-pos.x = 392.0000
-pos.y = 408.0000
-size.x = 16.0000
-size.y = 16.0000
-:RenderComponent
-layer = 5
-color.r = 1.0000
-color.g = 0.0000
-color.b = 0.0000
-color.a = 1.0000
-:PatronComponent
-state = 0
-order_item = "beer"
-order_show_animation = 0.0000
-holding = 0
-consume_timeout = 0.0000
-
 [Wall]
 id = 25
 flags = 2
@@ -154,12 +148,12 @@ color.b = 1.0000
 color.a = 1.0000
 
 [Wall]
-id = 26
+id = 27
 flags = 2
-pos.x = 424.0000
-pos.y = 592.0000
-size.x = 816.0000
-size.y = 32.0000
+pos.x = 8.0000
+pos.y = 312.0000
+size.x = 16.0000
+size.y = 592.0000
 :RenderComponent
 layer = 0
 color.r = 1.0000
@@ -168,9 +162,9 @@ color.b = 1.0000
 color.a = 1.0000
 
 [Wall]
-id = 27
+id = 28
 flags = 2
-pos.x = 8.0000
+pos.x = 792.0000
 pos.y = 312.0000
 size.x = 16.0000
 size.y = 592.0000
@@ -181,22 +175,86 @@ color.g = 1.0000
 color.b = 1.0000
 color.a = 1.0000
 
-[Wall]
-id = 28
+[Furniture]
+id = 30
+flags = 2
+pos.x = 136.0000
+pos.y = 336.0000
+size.x = 16.0000
+size.y = 32.0000
+:RenderComponent
+layer = 0
+color.r = 1.0000
+color.g = 1.0000
+color.b = 1.0000
+color.a = 1.0000
+:FurnitureComponent
+furniture_type = 0
+taken = true
+sprite.sheet = "./assets/images/spritesheet.png"
+sprite.pos.x = 32.0000
+sprite.pos.y = 32.0000
+sprite.size.x = 16.0000
+sprite.size.y = 32.0000
+sprite.color.r = 1.0000
+sprite.color.g = 1.0000
+sprite.color.b = 1.0000
+sprite.color.a = 1.0000
+
+[Furniture]
+id = 31
 flags = 2
-pos.x = 800.0000
-pos.y = 296.0000
+pos.x = 184.0000
+pos.y = 336.0000
+size.x = 16.0000
+size.y = 32.0000
+:RenderComponent
+layer = 0
+color.r = 1.0000
+color.g = 1.0000
+color.b = 1.0000
+color.a = 1.0000
+:FurnitureComponent
+furniture_type = 0
+taken = false
+sprite.sheet = "./assets/images/spritesheet.png"
+sprite.pos.x = 48.0000
+sprite.pos.y = 32.0000
+sprite.size.x = -16.0000
+sprite.size.y = 32.0000
+sprite.color.r = 1.0000
+sprite.color.g = 1.0000
+sprite.color.b = 1.0000
+sprite.color.a = 1.0000
+
+[Furniture]
+id = 32
+flags = 2
+pos.x = 160.0000
+pos.y = 336.0000
 size.x = 32.0000
-size.y = 560.0000
+size.y = 32.0000
 :RenderComponent
 layer = 0
 color.r = 1.0000
 color.g = 1.0000
 color.b = 1.0000
 color.a = 1.0000
+:FurnitureComponent
+furniture_type = 1
+taken = false
+sprite.sheet = "./assets/images/spritesheet.png"
+sprite.pos.x = 48.0000
+sprite.pos.y = 32.0000
+sprite.size.x = 32.0000
+sprite.size.y = 32.0000
+sprite.color.r = 1.0000
+sprite.color.g = 1.0000
+sprite.color.b = 1.0000
+sprite.color.a = 1.0000
 
 [Furniture]
-id = 30
+id = 40
 flags = 2
 pos.x = 136.0000
 pos.y = 256.0000
@@ -210,7 +268,7 @@ color.b = 1.0000
 color.a = 1.0000
 :FurnitureComponent
 furniture_type = 0
-taken = false
+taken = true
 sprite.sheet = "./assets/images/spritesheet.png"
 sprite.pos.x = 32.0000
 sprite.pos.y = 32.0000
@@ -222,7 +280,7 @@ sprite.color.b = 1.0000
 sprite.color.a = 1.0000
 
 [Furniture]
-id = 31
+id = 41
 flags = 2
 pos.x = 184.0000
 pos.y = 256.0000
@@ -248,7 +306,7 @@ sprite.color.b = 1.0000
 sprite.color.a = 1.0000
 
 [Furniture]
-id = 32
+id = 42
 flags = 2
 pos.x = 160.0000
 pos.y = 256.0000
@@ -273,6 +331,48 @@ sprite.color.g = 1.0000
 sprite.color.b = 1.0000
 sprite.color.a = 1.0000
 
+[Wall]
+id = 35
+flags = 2
+pos.x = 192.0000
+pos.y = 592.0000
+size.x = 352.0000
+size.y = 32.0000
+:RenderComponent
+layer = 0
+color.r = 1.0000
+color.g = 1.0000
+color.b = 1.0000
+color.a = 1.0000
+
+[Wall]
+id = 36
+flags = 2
+pos.x = 608.0000
+pos.y = 592.0000
+size.x = 352.0000
+size.y = 32.0000
+:RenderComponent
+layer = 0
+color.r = 1.0000
+color.g = 1.0000
+color.b = 1.0000
+color.a = 1.0000
+
+[Wall]
+id = 37
+flags = 2
+pos.x = 140.0000
+pos.y = -142.0000
+size.x = 16.0000
+size.y = 16.0000
+:RenderComponent
+layer = 0
+color.r = 1.0000
+color.g = 1.0000
+color.b = 1.0000
+color.a = 1.0000
+
 [Tap]
 id = 14
 flags = 3
@@ -290,3 +390,24 @@ color.a = 1.0000
 item = "beer"
 max_timeout = 2.0000
 
+[Patron]
+id = 22
+flags = 3
+pos.x = 319.2968
+pos.y = 422.7386
+size.x = 16.0000
+size.y = 32.0000
+:RenderComponent
+layer = 5
+color.r = 1.0000
+color.g = 0.0000
+color.b = 0.0000
+color.a = 1.0000
+:PatronComponent
+state = 0
+seat = 30
+order_item = "beer"
+order_show_animation = 0.0000
+holding = 0
+consume_timeout = 0.0000
+
index 6264c36c91b8e23409c40ccff213c3f8215da771..1485f53a8126696e9a4d9cb7869b4a7e3fdb4e6a 100644 (file)
@@ -19,6 +19,7 @@ MINOR_VERSION :: 1
 #load_all "./entity/components"
 #load_all "./entity/schematics"
 #load_all "./gfx"
+#load_all "./sfx"
 #load_all "./utils"
 
 #load "stb_image"
@@ -26,3 +27,4 @@ MINOR_VERSION :: 1
 
 #load "modules/opengles/module"
 #load "modules/glfw3/module"
+#load "modules/openal/module"
index 2d3698b326efcec05808b3b47b276048affdd8de..512e7d8622b3bd9bd4368e729f593677454d56ff 100644 (file)
@@ -49,6 +49,8 @@ DispenserComponent :: struct {
             // This should dynamic...
             item.pos = this.pos;
             item.size = .{16, 16};
+            // if only item.flags.Carryable = false was possible...
+            item.flags = ~~ (cast(u32) item.flags & ~(cast(u32) Entity_Flags.Carryable));
             (item->get(ItemComponent)).item = dispenser_comp.item;
 
             scene->add(item);
index 41e2f6ecfb2e50aaa6c92d1a1e2c6f884b40ed25..90d54ef65519ab54a7e9659690a5360b4bf1d6e5 100644 (file)
@@ -90,6 +90,8 @@ PatronComponent :: struct {
                 if interactor->has(PlayerComponent) {
                     patron.state = .Waiting_For_Order;
                     patron.order_show_animation = 1.0f;
+
+                    Audio_Manager.play_sound("./assets/sounds/prompt-1.wav");
                 }
             }
 
@@ -129,7 +131,7 @@ PatronComponent :: struct {
             r.y += 2;
             r.w -= 4;
             r.h -= 4;
-            immediate_set_color(.{1, 1, 1});
+            immediate_set_color(.{0.9, 0.9, 0.9});
             immediate_rectangle(r.x, r.y, r.w, r.h);
 
             r.x += 2;
index e552b9f01add865a0f03b62bbbcf16235fe43828..0501ba1f302eba6dc35183fb24b8f110d6a90c47 100644 (file)
@@ -90,6 +90,8 @@ PlayerComponent :: struct {
 
     render :: (use this: ^Entity) {
         rect := Entity.get_rect(this);
+        rect.y -= rect.h;
+        rect.h *= 2;
         immediate_subimage(^Spritesheet, rect.x, rect.y, rect.w, rect.h, 0*16, 4*16, 16, 16);
     }
 
index 753bb8c6d783e94132058bab3396947f33e70f7a..17cb769cdf1234c19baf7ce57006174aa0fdba36 100644 (file)
@@ -79,7 +79,7 @@ editor_update :: (dt: f32) {
             for scene.entities {
                 if Entity.get_rect(it) |> Rect.contains(mouse_pos) {
                     selected_entity_id = it.id;
-                    break;
+                    // break;
                 }
             }
 
index c205a23b06d4fdc3d4031a104ee1fc8495001ba2..7f454039afbc2e8c7f853e72d57840a77060c900 100644 (file)
@@ -143,6 +143,8 @@ Entity_Manager :: struct {
     query          :: entity_manager_query;
     query_by_flags :: entity_manager_query_by_flags;
 
+    count_by_component :: entity_manager_count_by_component;
+
     query_by_component :: entity_manager_query_by_component;
     create_component :: entity_manager_create_component;
     create_and_add :: entity_manager_create_and_add;
@@ -339,6 +341,17 @@ entity_manager_delete :: (use this: ^Entity_Manager, ent: ^Entity, delete_from_a
     raw_free(entity_allocator, ent);
 }
 
+entity_manager_count_by_component :: (use this: ^Entity_Manager, comp_type: type_expr) -> u32 {
+    count := 0;
+    for entities {
+        if it->has(comp_type) {
+            count += 1;
+        }
+    }
+
+    return count;
+}
+
 entity_manager_query :: (use this: ^Entity_Manager, area: Rect) -> [] ^Entity {
     ents: [..] ^Entity;
     for entities {
diff --git a/src/entity/schematics/background.onyx b/src/entity/schematics/background.onyx
new file mode 100644 (file)
index 0000000..0d294c4
--- /dev/null
@@ -0,0 +1,33 @@
+
+use package core
+
+Background :: struct {
+    #struct_tag Entity_Schematic.{
+        (scene) => {
+            this := scene->make();
+            this.pos = .{0, 0};
+            this.size = .{0, 0};
+
+            scene->create_and_add(this, RenderComponent) {
+                comp.func = Background.render;
+            }
+
+            queue_assets(^Background.assets);
+            load_assets();
+
+            return this;
+        }
+    }
+
+    render :: (this: ^Entity) {
+        size :: 10000.0f
+        immediate_set_color(.{1, 1, 1});
+        immediate_subimage(^assets.texture, this.pos.x, this.pos.y, size, size, 0, 0, size, size);
+    }
+
+    #persist assets: struct {
+        #tag "./assets/images/background.png"
+        #tag Texture_Wrap.Repeat
+        texture: Texture;
+    }
+}
\ No newline at end of file
index 40490f2d71bdb4ef23dcecd7442031680f7b6d39..3d516223491e4dbc6443a8d86286965e32d03efa 100644 (file)
@@ -41,6 +41,10 @@ Player :: struct {
         this.size = .{32, 32};
         this.flags |= .Solid;
 
+        scene->create_and_add(this, SizeComponent) {
+            comp.func = (use this: ^Entity) => Rect.{pos.x - size.x / 2, pos.y, size.x, size.y / 2};
+        }
+
         scene->create_and_add(this, MovementComponent) {
             comp.controls = controls;
         }
index 242854db10a71d066362e836ba20117cb26b6b37..fb5f83276943d3db250187098b3acd67486b9231 100644 (file)
@@ -16,6 +16,8 @@ scene_canvas: Canvas;
 Spritesheet: Texture;
 
 game_init :: () {
+    Audio_Manager.init();
+
     scene_canvas = canvas_make(800, 600);
 
     // This process of queueing the asset bucket should
@@ -34,6 +36,8 @@ game_init :: () {
 #local quick_save_file := "scenes/quick_save_new.scene";
 
 game_update :: (dt: f32) {
+    Audio_Manager.tick();
+
     if is_key_just_up(GLFW_KEY_F8) {
         debug_log(.Info, "Saving to '{}'.", quick_save_file);
         scene->save_to_file(quick_save_file);
diff --git a/src/sfx/audio_manager.onyx b/src/sfx/audio_manager.onyx
new file mode 100644 (file)
index 0000000..e7aa85a
--- /dev/null
@@ -0,0 +1,98 @@
+
+use package core
+use package openal
+
+Sound :: struct {
+    buffer: u32;
+}
+
+Audio_Manager :: struct {
+    init :: () {
+        map.init(^loaded_sounds);
+
+        alGetError();
+        device = alcOpenDevice(null);
+        audio_context = alcCreateContext(device, null);
+        alcMakeContextCurrent(audio_context);
+
+        if alGetError() != AL_NO_ERROR {
+            debug_log(.Critical, "Error creating audio context!!");
+        }
+    }
+
+    deinit :: () {
+        alcMakeContextCurrent(~~ cast(u64) 0);
+        alcDestroyContext(audio_context);
+        alcCloseDevice(device);
+    }
+
+    get_sound :: (path: str) -> Sound {
+        if loaded_sounds->has(path) {
+            return loaded_sounds[path];
+        }
+
+        wav_file := load_wav_file(path);
+
+        alGetError();
+
+        buffer: u32;
+        alGenBuffers(1, ^buffer);
+        if alGetError() != AL_NO_ERROR {
+            debug_log(.Error, "Error creating audio buffer!");
+            return .{0};
+        }
+
+        al_format: u32;
+        switch wav_file.format {
+            case .Mono8    do al_format = AL_FORMAT_MONO8;
+            case .Mono16   do al_format = AL_FORMAT_MONO16;
+            case .Stereo8  do al_format = AL_FORMAT_STEREO8;
+            case .Stereo16 do al_format = AL_FORMAT_STEREO16;
+        }
+
+        alBufferData(buffer, al_format, wav_file.data.data, wav_file.data.count, wav_file.sample_rate);
+        memory.free_slice(^wav_file.loaded_file_data);
+
+        map.put(^loaded_sounds, path, .{ buffer });
+        return .{ buffer };
+    }
+
+    play_sound :: (path: str, volume := 1.0f) {
+        sound := get_sound(path);
+
+        source: u32;
+        alGenSources(1, ^source);
+        alSourcef(source, AL_PITCH, 1);
+        alSourcef(source, AL_GAIN, volume);
+        alSource3f(source, AL_POSITION, 0, 0, 0);
+        alSource3f(source, AL_VELOCITY, 0, 0, 0);
+        alSourcei(source, AL_LOOPING, AL_FALSE);
+
+        alSourcei(source, AL_BUFFER, sound.buffer);
+        alSourcePlay(source);
+        playing_sounds << source;
+    }
+
+    tick :: () {
+        while i := 0; i < playing_sounds.count {
+            defer i += 1;
+
+            state: i32;
+            alGetSourcei(playing_sounds[i], AL_SOURCE_STATE, ^state);
+            if state != AL_PLAYING {
+                array.fast_delete(^playing_sounds, i);
+                i -= 1;
+            }
+        }
+    }
+}
+
+
+
+#local {
+    device: ALCdevice;
+    audio_context: ALCcontext;
+
+    loaded_sounds: Map(str, Sound);
+    playing_sounds: [..] u32; // List of sources
+}
\ No newline at end of file
diff --git a/src/sfx/wav_file.onyx b/src/sfx/wav_file.onyx
new file mode 100644 (file)
index 0000000..cfc5fc1
--- /dev/null
@@ -0,0 +1,130 @@
+
+use package core
+
+WAV_File :: struct {
+    Format :: enum {
+        Invalid;
+        Mono8;
+        Stereo8;
+        Mono16;
+        Stereo16;    
+    }
+
+    format: Format;
+    sample_rate: u32;
+    data: [] u8;
+
+    loaded_file_data: [] u8;
+}
+
+//
+// This greedily loads the whole file
+load_wav_file :: (path: str) -> WAV_File {
+    wav_file: WAV_File;
+    wav_file.format = .Invalid;
+
+    data := os.get_contents(path);
+    if data.data == null do return wav_file;
+    wav_file.loaded_file_data = data;
+
+    pos := 0;
+    if read_data(4) != "RIFF" do return wav_file;
+    read_data(4); // Not sure what this is suppose to be...
+    if read_data(4) != "WAVE" do return wav_file;
+
+    while true {
+        header_name := read_data(4);
+        header_size := *cast(^u32) read_data(4).data;
+
+        if header_name == "fmt " {
+            fmt := read_data(2);
+            channels := *cast(^u16) read_data(2).data;
+            sample_rate := *cast(^u32) read_data(4).data;
+            sr_bps_c_8 := *cast(^u32) read_data(4).data;
+            read_data(2);
+            bits_per_sample := *cast(^u16) read_data(2).data;
+
+            wav_file.sample_rate = sample_rate;
+
+            if channels == 1 && bits_per_sample == 8  do wav_file.format = .Mono8;
+            if channels == 1 && bits_per_sample == 16 do wav_file.format = .Mono16;
+            if channels == 2 && bits_per_sample == 8  do wav_file.format = .Stereo8;
+            if channels == 2 && bits_per_sample == 16 do wav_file.format = .Stereo16;
+        }
+
+        if header_name == "data" {
+            wav_file.data = data;
+            break;
+        }
+    }
+
+    return wav_file;
+
+    read_data :: macro (n: u32) -> str {
+        defer pos += n;
+        return data[pos .. pos+n];
+    }
+}
+
+
+#if false {
+main :: (args) => {
+    dev := alcOpenDevice(null);
+    defer alcCloseDevice(dev);
+
+    con := alcCreateContext(dev, null);
+    alcMakeContextCurrent(con);
+    defer {
+        alcMakeContextCurrent(~~ cast(u64) 0);
+        alcDestroyContext(con);
+    }
+
+    alGetError();
+    buf: u32;
+    alGenBuffers(1, ^buf);
+    defer alDeleteBuffers(1, ^buf);
+    if error := alGetError(); error != AL_NO_ERROR {
+        printf("AL ERROR: {}\n", error);
+        return;    
+    }
+
+    sample_rate := 44100;
+
+/*
+    wav_data := memory.make_slice(i16, sample_rate * 5);
+    for i: wav_data.count {
+        sample := math.sin((math.PI * 2.0f * ~~i * 263.2f) / ~~sample_rate) * 32768;
+        sample *= 1 - cast(f32) i / ~~wav_data.count;
+        wav_data[i] = cast(i16) cast(i32) (sample);
+    }
+    */
+
+    wav_file_contents := os.get_contents("/home/brendan/test.wav");
+    wav_data := extract_wav_file_data(wav_file_contents);
+
+    alBufferData(buf, AL_FORMAT_STEREO16, wav_data.data, wav_data.count, sample_rate);
+
+    alListener3f(AL_POSITION, 0, 0, 0);
+    alListener3f(AL_VELOCITY, 0, 0, 0);
+    alListenerfv(AL_ORIENTATION, ~~ f32.[0, 0, 1, 0, 1, 0]);
+
+    source: u32;
+    alGenSources(1, ^source);
+    defer alDeleteSources(1, ^source);
+    alSourcef(source, AL_PITCH, 1);
+    alSourcef(source, AL_GAIN, 0.7);
+    alSource3f(source, AL_POSITION, 0, 0, 0);
+    alSource3f(source, AL_VELOCITY, 0, 0, 0);
+    alSourcei(source, AL_LOOPING, AL_FALSE);
+
+    alSourcei(source, AL_BUFFER, buf);
+    alSourcePlay(source);
+
+    state: i32;
+    while true {
+        os.sleep(1000);
+        alGetSourcei(source, AL_SOURCE_STATE, ^state);
+        if state != AL_PLAYING do break;
+    }
+}
+}
\ No newline at end of file